You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by pa...@apache.org on 2020/02/01 05:53:33 UTC
[groovy] 02/02: GROOVY-9380: VMPlugin refactor: Coalesce Java5
through Java7 into Java8 (remove deprecated classes)
This is an automated email from the ASF dual-hosted git repository.
paulk pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git
commit 6e10c35b7fdc7c6b213372d7fa771f723ca5906a
Author: Paul King <pa...@asert.com.au>
AuthorDate: Sat Feb 1 15:52:22 2020 +1000
GROOVY-9380: VMPlugin refactor: Coalesce Java5 through Java7 into Java8 (remove deprecated classes)
---
.../org/codehaus/groovy/vmplugin/v5/Java5.java | 604 -----------
.../vmplugin/v5/PluginDefaultGroovyMethods.java | 143 ---
.../org/codehaus/groovy/vmplugin/v5/package.html | 28 -
.../org/codehaus/groovy/vmplugin/v6/Java6.java | 33 -
.../groovy/vmplugin/v7/CacheableCallSite.java | 93 --
.../groovy/vmplugin/v7/IndyArrayAccess.java | 142 ---
.../v7/IndyGuardsFiltersAndSignatures.java | 212 ----
.../codehaus/groovy/vmplugin/v7/IndyInterface.java | 340 ------
.../org/codehaus/groovy/vmplugin/v7/IndyMath.java | 278 -----
.../org/codehaus/groovy/vmplugin/v7/Java7.java | 108 --
.../groovy/vmplugin/v7/MethodHandleWrapper.java | 65 --
.../org/codehaus/groovy/vmplugin/v7/Selector.java | 1088 --------------------
.../codehaus/groovy/vmplugin/v7/TypeHelper.java | 112 --
.../groovy/vmplugin/v7/TypeTransformers.java | 245 -----
14 files changed, 3491 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/vmplugin/v5/Java5.java b/src/main/java/org/codehaus/groovy/vmplugin/v5/Java5.java
deleted file mode 100644
index 327b892..0000000
--- a/src/main/java/org/codehaus/groovy/vmplugin/v5/Java5.java
+++ /dev/null
@@ -1,604 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.codehaus.groovy.vmplugin.v5;
-
-import groovy.lang.MetaClass;
-import groovy.lang.MetaMethod;
-import org.codehaus.groovy.GroovyBugError;
-import org.codehaus.groovy.ast.AnnotatedNode;
-import org.codehaus.groovy.ast.AnnotationNode;
-import org.codehaus.groovy.ast.ClassHelper;
-import org.codehaus.groovy.ast.ClassNode;
-import org.codehaus.groovy.ast.CompileUnit;
-import org.codehaus.groovy.ast.ConstructorNode;
-import org.codehaus.groovy.ast.FieldNode;
-import org.codehaus.groovy.ast.GenericsType;
-import org.codehaus.groovy.ast.MethodNode;
-import org.codehaus.groovy.ast.PackageNode;
-import org.codehaus.groovy.ast.Parameter;
-import org.codehaus.groovy.ast.expr.ClassExpression;
-import org.codehaus.groovy.ast.expr.ConstantExpression;
-import org.codehaus.groovy.ast.expr.Expression;
-import org.codehaus.groovy.ast.expr.ListExpression;
-import org.codehaus.groovy.ast.expr.PropertyExpression;
-import org.codehaus.groovy.ast.stmt.ReturnStatement;
-import org.codehaus.groovy.vmplugin.VMPlugin;
-import org.codehaus.groovy.vmplugin.VMPluginFactory;
-
-import java.lang.annotation.Annotation;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import java.lang.reflect.AccessibleObject;
-import java.lang.reflect.Array;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Field;
-import java.lang.reflect.GenericArrayType;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.MalformedParameterizedTypeException;
-import java.lang.reflect.Method;
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.ReflectPermission;
-import java.lang.reflect.Type;
-import java.lang.reflect.TypeVariable;
-import java.lang.reflect.WildcardType;
-import java.security.Permission;
-import java.util.List;
-
-/**
- * java 5 based functions
- */
-@Deprecated
-public class Java5 implements VMPlugin {
- private static final Class[] EMPTY_CLASS_ARRAY = new Class[0];
- private static final Class[] PLUGIN_DGM = {PluginDefaultGroovyMethods.class};
- private static final Method[] EMPTY_METHOD_ARRAY = new Method[0];
- private static final Annotation[] EMPTY_ANNOTATION_ARRAY = new Annotation[0];
-
- public void setAdditionalClassInformation(ClassNode cn) {
- setGenericsTypes(cn);
- }
-
- private void setGenericsTypes(ClassNode cn) {
- TypeVariable[] tvs = cn.getTypeClass().getTypeParameters();
- GenericsType[] gts = configureTypeVariable(tvs);
- cn.setGenericsTypes(gts);
- }
-
- private GenericsType[] configureTypeVariable(TypeVariable[] tvs) {
- if (tvs.length == 0) return null;
- GenericsType[] gts = new GenericsType[tvs.length];
- for (int i = 0; i < tvs.length; i++) {
- gts[i] = configureTypeVariableDefinition(tvs[i]);
- }
- return gts;
- }
-
- private GenericsType configureTypeVariableDefinition(TypeVariable tv) {
- return configureTypeVariableDefinition(configureTypeVariableReference(tv.getName()), configureTypes(tv.getBounds()));
- }
-
- public static GenericsType configureTypeVariableDefinition(ClassNode base, ClassNode[] cBounds) {
- ClassNode redirect = base.redirect();
- base.setRedirect(null);
- GenericsType gt;
- if (cBounds == null || cBounds.length == 0) {
- gt = new GenericsType(base);
- } else {
- gt = new GenericsType(base, cBounds, null);
- gt.setName(base.getName());
- gt.setPlaceholder(true);
- }
- base.setRedirect(redirect);
- return gt;
- }
-
- private ClassNode[] configureTypes(Type[] types) {
- if (types.length == 0) return null;
- ClassNode[] nodes = new ClassNode[types.length];
- for (int i = 0; i < types.length; i++) {
- nodes[i] = configureType(types[i]);
- }
- return nodes;
- }
-
- private ClassNode configureType(Type type) {
- if (type instanceof WildcardType) {
- return configureWildcardType((WildcardType) type);
- } else if (type instanceof ParameterizedType) {
- return configureParameterizedType((ParameterizedType) type);
- } else if (type instanceof GenericArrayType) {
- return configureGenericArray((GenericArrayType) type);
- } else if (type instanceof TypeVariable) {
- return configureTypeVariableReference(((TypeVariable) type).getName());
- } else if (type instanceof Class) {
- return configureClass((Class) type);
- } else if (type==null) {
- throw new GroovyBugError("Type is null. Most probably you let a transform reuse existing ClassNodes with generics information, that is now used in a wrong context.");
- } else {
- throw new GroovyBugError("unknown type: " + type + " := " + type.getClass());
- }
- }
-
- private static ClassNode configureClass(Class c) {
- if (c.isPrimitive()) {
- return ClassHelper.make(c);
- } else {
- return ClassHelper.makeWithoutCaching(c, false);
- }
- }
-
- private ClassNode configureGenericArray(GenericArrayType genericArrayType) {
- Type component = genericArrayType.getGenericComponentType();
- ClassNode node = configureType(component);
- return node.makeArray();
- }
-
- private ClassNode configureWildcardType(final WildcardType wildcardType) {
- ClassNode base = ClassHelper.makeWithoutCaching("?");
- base.setRedirect(ClassHelper.OBJECT_TYPE);
-
- ClassNode[] lowers = configureTypes(wildcardType.getLowerBounds());
- ClassNode[] uppers = configureTypes(wildcardType.getUpperBounds());
- // beware of [Object] upper bounds; often it's <?> or <? super T>
- if (lowers != null || wildcardType.getTypeName().equals("?")) {
- uppers = null;
- }
-
- GenericsType gt = new GenericsType(base, uppers, lowers != null ? lowers[0] : null);
- gt.setWildcard(true);
-
- ClassNode wt = ClassHelper.makeWithoutCaching(Object.class, false);
- wt.setGenericsTypes(new GenericsType[]{gt});
- return wt;
- }
-
- private ClassNode configureParameterizedType(ParameterizedType parameterizedType) {
- ClassNode base = configureType(parameterizedType.getRawType());
- GenericsType[] gts = configureTypeArguments(parameterizedType.getActualTypeArguments());
- base.setGenericsTypes(gts);
- return base;
- }
-
- public static ClassNode configureTypeVariableReference(String name) {
- ClassNode cn = ClassHelper.makeWithoutCaching(name);
- cn.setGenericsPlaceHolder(true);
- ClassNode cn2 = ClassHelper.makeWithoutCaching(name);
- cn2.setGenericsPlaceHolder(true);
- GenericsType[] gts = new GenericsType[]{new GenericsType(cn2)};
- cn.setGenericsTypes(gts);
- cn.setRedirect(ClassHelper.OBJECT_TYPE);
- return cn;
- }
-
- private GenericsType[] configureTypeArguments(Type[] ta) {
- if (ta.length == 0) return null;
- GenericsType[] gts = new GenericsType[ta.length];
- for (int i = 0; i < ta.length; i++) {
- ClassNode t = configureType(ta[i]);
- if (ta[i] instanceof WildcardType) {
- GenericsType[] gen = t.getGenericsTypes();
- gts[i] = gen[0];
- } else {
- gts[i] = new GenericsType(t);
- }
- }
- return gts;
- }
-
- public Class[] getPluginDefaultGroovyMethods() {
- return PLUGIN_DGM;
- }
-
- public Class[] getPluginStaticGroovyMethods() {
- return EMPTY_CLASS_ARRAY;
- }
-
- private void setAnnotationMetaData(Annotation[] annotations, AnnotatedNode an) {
- for (Annotation annotation : annotations) {
- AnnotationNode node = new AnnotationNode(ClassHelper.make(annotation.annotationType()));
- configureAnnotation(node, annotation);
- an.addAnnotation(node);
- }
- }
-
- @Deprecated
- public void configureAnnotationFromDefinition(AnnotationNode definition, AnnotationNode root) {
- VMPlugin plugin = VMPluginFactory.getPlugin();
- plugin.configureAnnotationNodeFromDefinition(definition, root);
- }
-
- public void configureAnnotationNodeFromDefinition(AnnotationNode definition, AnnotationNode root) {
- ClassNode type = definition.getClassNode();
- if ("java.lang.annotation.Retention".equals(type.getName())) {
- Expression exp = definition.getMember("value");
- if (!(exp instanceof PropertyExpression)) return;
- PropertyExpression pe = (PropertyExpression) exp;
- String name = pe.getPropertyAsString();
- RetentionPolicy policy = RetentionPolicy.valueOf(name);
- setRetentionPolicy(policy, root);
- } else if ("java.lang.annotation.Target".equals(type.getName())) {
- Expression exp = definition.getMember("value");
- if (!(exp instanceof ListExpression)) return;
- ListExpression le = (ListExpression) exp;
- int bitmap = 0;
- for (Expression e : le.getExpressions()) {
- if (!(e instanceof PropertyExpression)) return;
- PropertyExpression element = (PropertyExpression) e;
- String name = element.getPropertyAsString();
- ElementType value = ElementType.valueOf(name);
- bitmap |= getElementCode(value);
- }
- root.setAllowedTargets(bitmap);
- }
- }
-
- public void configureAnnotation(AnnotationNode node) {
- ClassNode type = node.getClassNode();
- VMPlugin plugin = VMPluginFactory.getPlugin();
- List<AnnotationNode> annotations = type.getAnnotations();
- for (AnnotationNode an : annotations) {
- plugin.configureAnnotationNodeFromDefinition(an, node);
- }
- plugin.configureAnnotationNodeFromDefinition(node, node);
- }
-
- private void configureAnnotation(AnnotationNode node, Annotation annotation) {
- Class type = annotation.annotationType();
- if (type == Retention.class) {
- Retention r = (Retention) annotation;
- RetentionPolicy value = r.value();
- setRetentionPolicy(value, node);
- node.setMember("value", new PropertyExpression(
- new ClassExpression(ClassHelper.makeWithoutCaching(RetentionPolicy.class, false)),
- value.toString()));
- } else if (type == Target.class) {
- Target t = (Target) annotation;
- ElementType[] elements = t.value();
- ListExpression elementExprs = new ListExpression();
- for (ElementType element : elements) {
- elementExprs.addExpression(new PropertyExpression(
- new ClassExpression(ClassHelper.ELEMENT_TYPE_TYPE), element.name()));
- }
- node.setMember("value", elementExprs);
- } else {
- Method[] declaredMethods;
- try {
- declaredMethods = type.getDeclaredMethods();
- } catch (SecurityException se) {
- declaredMethods = EMPTY_METHOD_ARRAY;
- }
- for (Method declaredMethod : declaredMethods) {
- try {
- Object value = declaredMethod.invoke(annotation);
- Expression valueExpression = annotationValueToExpression(value);
- if (valueExpression == null)
- continue;
- node.setMember(declaredMethod.getName(), valueExpression);
- } catch (IllegalAccessException | InvocationTargetException e) {
- }
- }
- }
- }
-
- private Expression annotationValueToExpression (Object value) {
- if (value == null || value instanceof String || value instanceof Number || value instanceof Character || value instanceof Boolean)
- return new ConstantExpression(value);
-
- if (value instanceof Class)
- return new ClassExpression(ClassHelper.makeWithoutCaching((Class)value));
-
- if (value.getClass().isArray()) {
- ListExpression elementExprs = new ListExpression();
- int len = Array.getLength(value);
- for (int i = 0; i != len; ++i)
- elementExprs.addExpression(annotationValueToExpression(Array.get(value, i)));
- return elementExprs;
- }
-
- return null;
- }
-
- private static void setRetentionPolicy(RetentionPolicy value, AnnotationNode node) {
- switch (value) {
- case RUNTIME:
- node.setRuntimeRetention(true);
- break;
- case SOURCE:
- node.setSourceRetention(true);
- break;
- case CLASS:
- node.setClassRetention(true);
- break;
- default:
- throw new GroovyBugError("unsupported Retention " + value);
- }
- }
-
- protected int getElementCode(ElementType value) {
- switch (value) {
- case TYPE:
- return AnnotationNode.TYPE_TARGET;
- case CONSTRUCTOR:
- return AnnotationNode.CONSTRUCTOR_TARGET;
- case METHOD:
- return AnnotationNode.METHOD_TARGET;
- case FIELD:
- return AnnotationNode.FIELD_TARGET;
- case PARAMETER:
- return AnnotationNode.PARAMETER_TARGET;
- case LOCAL_VARIABLE:
- return AnnotationNode.LOCAL_VARIABLE_TARGET;
- case ANNOTATION_TYPE:
- return AnnotationNode.ANNOTATION_TARGET;
- case PACKAGE:
- return AnnotationNode.PACKAGE_TARGET;
- }
- if ("MODULE".equals(value.name())) {
- return AnnotationNode.TYPE_TARGET;
- } else {
- throw new GroovyBugError("unsupported Target " + value);
- }
- }
-
- private static void setMethodDefaultValue(MethodNode mn, Method m) {
- ConstantExpression cExp = new ConstantExpression(m.getDefaultValue());
- mn.setCode(new ReturnStatement(cExp));
- mn.setAnnotationDefault(true);
- }
-
- public void configureClassNode(CompileUnit compileUnit, ClassNode classNode) {
- try {
- Class clazz = classNode.getTypeClass();
- Field[] fields = clazz.getDeclaredFields();
- for (Field f : fields) {
- ClassNode ret = makeClassNode(compileUnit, f.getGenericType(), f.getType());
- FieldNode fn = new FieldNode(f.getName(), f.getModifiers(), ret, classNode, null);
- setAnnotationMetaData(f.getAnnotations(), fn);
- classNode.addField(fn);
- }
- Method[] methods = clazz.getDeclaredMethods();
- for (Method m : methods) {
- ClassNode ret = makeClassNode(compileUnit, m.getGenericReturnType(), m.getReturnType());
- Parameter[] params = processParameters(compileUnit, m);
- ClassNode[] exceptions = makeClassNodes(compileUnit, m.getGenericExceptionTypes(), m.getExceptionTypes());
- MethodNode mn = new MethodNode(m.getName(), m.getModifiers(), ret, params, exceptions, null);
- mn.setSynthetic(m.isSynthetic());
- setMethodDefaultValue(mn, m);
- setAnnotationMetaData(m.getAnnotations(), mn);
- mn.setGenericsTypes(configureTypeVariable(m.getTypeParameters()));
- classNode.addMethod(mn);
- }
- Constructor[] constructors = clazz.getDeclaredConstructors();
- for (Constructor ctor : constructors) {
- Type[] types = ctor.getGenericParameterTypes();
- Parameter[] params1 = Parameter.EMPTY_ARRAY;
- if (types.length > 0) {
- params1 = new Parameter[types.length];
- for (int i = 0; i < params1.length; i++) {
- params1[i] = makeParameter(compileUnit, types[i], ctor.getParameterTypes()[i], getConstructorParameterAnnotations(ctor)[i], "param" + i);
- }
- }
- Parameter[] params = params1;
- ClassNode[] exceptions = makeClassNodes(compileUnit, ctor.getGenericExceptionTypes(), ctor.getExceptionTypes());
- ConstructorNode cn = classNode.addConstructor(ctor.getModifiers(), params, exceptions, null);
- setAnnotationMetaData(ctor.getAnnotations(), cn);
- }
-
- Class sc = clazz.getSuperclass();
- if (sc != null) classNode.setUnresolvedSuperClass(makeClassNode(compileUnit, clazz.getGenericSuperclass(), sc));
- makeInterfaceTypes(compileUnit, classNode, clazz);
- setAnnotationMetaData(classNode.getTypeClass().getAnnotations(), classNode);
-
- PackageNode packageNode = classNode.getPackage();
- if (packageNode != null) {
- setAnnotationMetaData(classNode.getTypeClass().getPackage().getAnnotations(), packageNode);
- }
- } catch (NoClassDefFoundError e) {
- throw new NoClassDefFoundError("Unable to load class "+classNode.toString(false)+" due to missing dependency "+e.getMessage());
- } catch (MalformedParameterizedTypeException e) {
- throw new RuntimeException("Unable to configure class node for class "+classNode.toString(false)+" due to malformed parameterized types", e);
- }
- }
-
- protected Parameter[] processParameters(CompileUnit compileUnit, Method m) {
- Type[] types = m.getGenericParameterTypes();
- Parameter[] params = Parameter.EMPTY_ARRAY;
- if (types.length > 0) {
- params = new Parameter[types.length];
- for (int i = 0; i < params.length; i++) {
- params[i] = makeParameter(compileUnit, types[i], m.getParameterTypes()[i], m.getParameterAnnotations()[i], "param" + i);
- }
- }
- return params;
- }
-
- /**
- * Synthetic parameters such as those added for inner class constructors may
- * not be included in the parameter annotations array. This is the case when
- * at least one parameter of an inner class constructor has an annotation with
- * a RUNTIME retention (this occurs for JDK8 and below). This method will
- * normalize the annotations array so that it contains the same number of
- * elements as the array returned from {@link Constructor#getParameterTypes()}.
- *
- * If adjustment is required, the adjusted array will be prepended with a
- * zero-length element. If no adjustment is required, the original array
- * from {@link Constructor#getParameterAnnotations()} will be returned.
- *
- * @param constructor the Constructor for which to return parameter annotations
- * @return array of arrays containing the annotations on the parameters of the given Constructor
- */
- private Annotation[][] getConstructorParameterAnnotations(Constructor<?> constructor) {
- /*
- * TODO: Remove after JDK9 is the minimum JDK supported
- *
- * JDK9+ correctly accounts for the synthetic parameter and when it becomes
- * the minimum version this method should no longer be required.
- */
- int parameterCount = constructor.getParameterTypes().length;
- Annotation[][] annotations = constructor.getParameterAnnotations();
- int diff = parameterCount - annotations.length;
- if (diff > 0) {
- // May happen on JDK8 and below. We add elements to the front of the array to account for the synthetic params:
- // - for an inner class we expect one param to account for the synthetic outer reference
- // - for an enum we expect two params to account for the synthetic name and ordinal
- if ((!constructor.getDeclaringClass().isEnum() && diff > 1) || diff > 2) {
- throw new GroovyBugError(
- "Constructor parameter annotations length [" + annotations.length + "] " +
- "does not match the parameter length: " + constructor
- );
- }
- Annotation[][] adjusted = new Annotation[parameterCount][];
- for (int i = 0; i < diff; i++) {
- adjusted[i] = EMPTY_ANNOTATION_ARRAY;
- }
- System.arraycopy(annotations, 0, adjusted, diff, annotations.length);
- return adjusted;
- }
- return annotations;
- }
-
- private void makeInterfaceTypes(CompileUnit cu, ClassNode classNode, Class clazz) {
- Type[] interfaceTypes = clazz.getGenericInterfaces();
- if (interfaceTypes.length == 0) {
- classNode.setInterfaces(ClassNode.EMPTY_ARRAY);
- } else {
- ClassNode[] ret = new ClassNode[interfaceTypes.length];
- for (int i = 0; i < interfaceTypes.length; i++) {
- Type type = interfaceTypes[i];
- while (!(type instanceof Class)) {
- ParameterizedType pt = (ParameterizedType) type;
- Type t2 = pt.getRawType();
- if (t2==type) {
- throw new GroovyBugError("Cannot transform generic signature of "+clazz+
- " with generic interface "+interfaceTypes[i]+" to a class.");
- }
- type = t2;
- }
- ret[i] = makeClassNode(cu, interfaceTypes[i], (Class) type);
- }
- classNode.setInterfaces(ret);
- }
- }
-
- private ClassNode[] makeClassNodes(CompileUnit cu, Type[] types, Class[] cls) {
- ClassNode[] nodes = new ClassNode[types.length];
- for (int i = 0; i < nodes.length; i++) {
- nodes[i] = makeClassNode(cu, types[i], cls[i]);
- }
- return nodes;
- }
-
- private ClassNode makeClassNode(CompileUnit cu, Type t, Class c) {
- ClassNode back = null;
- if (cu != null) back = cu.getClass(c.getName());
- if (back == null) back = ClassHelper.make(c);
- if (!(t instanceof Class)) {
- ClassNode front = configureType(t);
- front.setRedirect(back);
- return front;
- }
- return back.getPlainNodeReference();
- }
-
- protected Parameter makeParameter(CompileUnit cu, Type type, Class cl, Annotation[] annotations, String name) {
- ClassNode cn = makeClassNode(cu, type, cl);
- Parameter parameter = new Parameter(cn, name);
- setAnnotationMetaData(annotations, parameter);
- return parameter;
- }
-
- public void invalidateCallSites() {}
-
- @Override
- public Object getInvokeSpecialHandle(Method m, Object receiver){
- throw new GroovyBugError("getInvokeSpecialHandle requires at least JDK 7 wot private access to Lookup");
- }
-
- @Override
- public int getVersion() {
- return 5;
- }
-
- @Override
- public Object invokeHandle(Object handle, Object[] args) throws Throwable {
- throw new GroovyBugError("invokeHandle requires at least JDK 7");
- }
-
- /**
- * The following scenarios can not set accessible, i.e. the return value is false
- * 1) SecurityException occurred
- * 2) the accessible object is a Constructor object for the Class class
- *
- * @param accessibleObject the accessible object to check
- * @param callerClass the callerClass to invoke {@code setAccessible}
- * @return the check result
- */
- @Override
- public boolean checkCanSetAccessible(AccessibleObject accessibleObject, Class<?> callerClass) {
- SecurityManager sm = System.getSecurityManager();
- try {
- if (sm != null) {
- sm.checkPermission(ACCESS_PERMISSION);
- }
- } catch (SecurityException e) {
- return false;
- }
-
- if (accessibleObject instanceof Constructor) {
- Constructor c = (Constructor) accessibleObject;
- if (c.getDeclaringClass() == Class.class) {
- return false; // Cannot make a java.lang.Class constructor accessible
- }
- }
-
- return true;
- }
-
- @Override
- public boolean checkAccessible(Class<?> callerClass, Class<?> declaringClass, int memberModifiers, boolean allowIllegalAccess) {
- return true;
- }
-
- @Override
- public boolean trySetAccessible(AccessibleObject ao) {
- try {
- ao.setAccessible(true);
- return true;
- } catch (SecurityException e) {
- throw e;
- } catch (Throwable t) {
- return false;
- }
- }
-
- @Override
- public MetaMethod transformMetaMethod(MetaClass metaClass, MetaMethod metaMethod, Class<?> caller) {
- return metaMethod;
- }
-
- @Override
- public MetaMethod transformMetaMethod(MetaClass metaClass, MetaMethod metaMethod) {
- return transformMetaMethod(metaClass, metaMethod, null);
- }
-
- private static final Permission ACCESS_PERMISSION = new ReflectPermission("suppressAccessChecks");
-}
-
diff --git a/src/main/java/org/codehaus/groovy/vmplugin/v5/PluginDefaultGroovyMethods.java b/src/main/java/org/codehaus/groovy/vmplugin/v5/PluginDefaultGroovyMethods.java
deleted file mode 100644
index 95f95f3..0000000
--- a/src/main/java/org/codehaus/groovy/vmplugin/v5/PluginDefaultGroovyMethods.java
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.codehaus.groovy.vmplugin.v5;
-
-import groovy.lang.EmptyRange;
-import groovy.lang.GString;
-import groovy.lang.IntRange;
-import org.codehaus.groovy.runtime.DefaultGroovyMethodsSupport;
-import org.codehaus.groovy.runtime.InvokerHelper;
-import org.codehaus.groovy.runtime.RangeInfo;
-
-import java.lang.reflect.Method;
-import java.util.Arrays;
-
-/**
- * This class defines new Java 5 specific groovy methods which extend the normal
- * JDK classes inside the Groovy environment. Static methods are used with the
- * first parameter the destination class.
- */
-@Deprecated
-public class PluginDefaultGroovyMethods extends DefaultGroovyMethodsSupport {
-
- /**
- * This method is called by the ++ operator for enums. It will invoke
- * Groovy's default next behaviour for enums do not have their own
- * next method.
- *
- * @param self an Enum
- * @return the next defined enum from the enum class
- */
- public static Object next(final Enum self) {
- for (Method method : self.getClass().getMethods()) {
- if (method.getName().equals("next") && method.getParameterCount() == 0) {
- return InvokerHelper.invokeMethod(self, "next", InvokerHelper.EMPTY_ARGS);
- }
- }
- Object[] values = (Object[]) InvokerHelper.invokeStaticMethod(self.getClass(), "values", InvokerHelper.EMPTY_ARGS);
- int index = Arrays.asList(values).indexOf(self);
- return values[index < values.length - 1 ? index + 1 : 0];
- }
-
- /**
- * This method is called by the -- operator for enums. It will invoke
- * Groovy's default previous behaviour for enums that do not have
- * their own previous method.
- *
- * @param self an Enum
- * @return the previous defined enum from the enum class
- */
- public static Object previous(final Enum self) {
- for (Method method : self.getClass().getMethods()) {
- if (method.getName().equals("previous") && method.getParameterCount() == 0) {
- return InvokerHelper.invokeMethod(self, "previous", InvokerHelper.EMPTY_ARGS);
- }
- }
- Object[] values = (Object[]) InvokerHelper.invokeStaticMethod(self.getClass(), "values", InvokerHelper.EMPTY_ARGS);
- int index = Arrays.asList(values).indexOf(self);
- return values[index > 0 ? index - 1 : values.length - 1];
- }
-
- /**
- * Standard Groovy size() method for StringBuilders.
- *
- * @param builder a StringBuilder
- * @return the length of the StringBuilder
- */
- public static int size(final StringBuilder builder) {
- return builder.length();
- }
-
- /**
- * Overloads the left shift operator to provide an easy way to append multiple
- * objects as string representations to a StringBuilder.
- *
- * @param self a StringBuilder
- * @param value a value to append
- * @return the StringBuilder on which this operation was invoked
- */
- public static StringBuilder leftShift(final StringBuilder self, final Object value) {
- if (value instanceof GString) {
- // Force the conversion of the GString to string now, or appending
- // is going to be extremely expensive, due to calls to GString#charAt,
- // which is going to re-evaluate the GString for each character!
- return self.append(value.toString());
- }
- if (value instanceof CharSequence) {
- return self.append((CharSequence)value);
- }
- return self.append(value);
- }
-
- /**
- * Support the range subscript operator for StringBuilder.
- * Index values are treated as characters within the builder.
- *
- * @param self a StringBuilder
- * @param range a Range
- * @param value the object that's toString() will be inserted
- */
- public static void putAt(final StringBuilder self, final IntRange range, final Object value) {
- RangeInfo info = subListBorders(self.length(), range);
- self.replace(info.from, info.to, value.toString());
- }
-
- /**
- * Support the range subscript operator for StringBuilder.
- *
- * @param self a StringBuilder
- * @param range a Range
- * @param value the object that's toString() will be inserted
- */
- public static void putAt(final StringBuilder self, final EmptyRange range, final Object value) {
- RangeInfo info = subListBorders(self.length(), range);
- self.replace(info.from, info.to, value.toString());
- }
-
- /**
- * Appends a String to this StringBuilder.
- *
- * @param self a StringBuilder
- * @param value a String
- * @return a String
- */
- public static String plus(final StringBuilder self, final String value) {
- return self + value;
- }
-}
diff --git a/src/main/java/org/codehaus/groovy/vmplugin/v5/package.html b/src/main/java/org/codehaus/groovy/vmplugin/v5/package.html
deleted file mode 100644
index ae4d56a..0000000
--- a/src/main/java/org/codehaus/groovy/vmplugin/v5/package.html
+++ /dev/null
@@ -1,28 +0,0 @@
-<!--
-
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-
--->
-<html>
- <body>
- <p>
- Java 5 specific classes.
- </p>
- </body>
-</html>
-
diff --git a/src/main/java/org/codehaus/groovy/vmplugin/v6/Java6.java b/src/main/java/org/codehaus/groovy/vmplugin/v6/Java6.java
deleted file mode 100644
index 5322444..0000000
--- a/src/main/java/org/codehaus/groovy/vmplugin/v6/Java6.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.codehaus.groovy.vmplugin.v6;
-
-import org.codehaus.groovy.vmplugin.v5.Java5;
-
-/**
- * Java 6 based functions. M12n moved these to modules.
- */
-@Deprecated
-public class Java6 extends Java5 {
-
- @Override
- public int getVersion() {
- return 6;
- }
-}
diff --git a/src/main/java/org/codehaus/groovy/vmplugin/v7/CacheableCallSite.java b/src/main/java/org/codehaus/groovy/vmplugin/v7/CacheableCallSite.java
deleted file mode 100644
index 9f85413..0000000
--- a/src/main/java/org/codehaus/groovy/vmplugin/v7/CacheableCallSite.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.codehaus.groovy.vmplugin.v7;
-
-import org.apache.groovy.util.SystemUtil;
-import org.codehaus.groovy.GroovyBugError;
-import org.codehaus.groovy.runtime.memoize.LRUCache;
-import org.codehaus.groovy.runtime.memoize.MemoizeCache;
-
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodType;
-import java.lang.invoke.MutableCallSite;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicLong;
-
-/**
- * Represents a cacheable call site, which can reduce the cost of resolving methods
- *
- * @since 3.0.0
- */
-@Deprecated
-public class CacheableCallSite extends MutableCallSite {
- private static final int CACHE_SIZE = SystemUtil.getIntegerSafe("groovy.indy.callsite.cache.size", 16);
- private final MemoizeCache<String, MethodHandleWrapper> cache = new LRUCache<>(CACHE_SIZE);
- private volatile MethodHandleWrapper latestHitMethodHandleWrapper = null;
- private final AtomicLong fallbackCount = new AtomicLong(0);
- private MethodHandle defaultTarget;
- private MethodHandle fallbackTarget;
-
- public CacheableCallSite(MethodType type) {
- super(type);
- }
-
- public MethodHandleWrapper getAndPut(String className, MemoizeCache.ValueProvider<? super String, ? extends MethodHandleWrapper> valueProvider) {
- final MethodHandleWrapper result = cache.getAndPut(className, valueProvider);
- final MethodHandleWrapper lhmh = latestHitMethodHandleWrapper;
-
- if (lhmh == result) {
- result.incrementLatestHitCount();
- } else {
- result.resetLatestHitCount();
- if (null != lhmh) lhmh.resetLatestHitCount();
-
- latestHitMethodHandleWrapper = result;
- }
-
- return result;
- }
-
- public MethodHandleWrapper put(String name, MethodHandleWrapper mhw) {
- return cache.put(name, mhw);
- }
-
- public long incrementFallbackCount() {
- return fallbackCount.incrementAndGet();
- }
-
- public void resetFallbackCount() {
- fallbackCount.set(0);
- }
-
- public MethodHandle getDefaultTarget() {
- return defaultTarget;
- }
-
- public void setDefaultTarget(MethodHandle defaultTarget) {
- this.defaultTarget = defaultTarget;
- }
-
- public MethodHandle getFallbackTarget() {
- return fallbackTarget;
- }
-
- public void setFallbackTarget(MethodHandle fallbackTarget) {
- this.fallbackTarget = fallbackTarget;
- }
-}
diff --git a/src/main/java/org/codehaus/groovy/vmplugin/v7/IndyArrayAccess.java b/src/main/java/org/codehaus/groovy/vmplugin/v7/IndyArrayAccess.java
deleted file mode 100644
index 3e4ca5f..0000000
--- a/src/main/java/org/codehaus/groovy/vmplugin/v7/IndyArrayAccess.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.codehaus.groovy.vmplugin.v7;
-
-import org.codehaus.groovy.GroovyBugError;
-
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodHandles;
-import java.lang.invoke.MethodType;
-import java.lang.reflect.Array;
-import java.util.HashMap;
-
-/**
- * Class for handling array access through invokedynamic using static callsite information
- *
- * @since 2.5.0
- */
-@Deprecated
-public class IndyArrayAccess {
-
- private static final MethodHandle notNegative, normalizeIndex;
-
- static {
- try {
- notNegative = MethodHandles.lookup().findStatic(IndyArrayAccess.class, "notNegative", MethodType.methodType(boolean.class, int.class));
- normalizeIndex = MethodHandles.lookup().findStatic(IndyArrayAccess.class, "normalizeIndex", MethodType.methodType(int.class, Object.class, int.class));
- } catch (ReflectiveOperationException e) {
- throw new GroovyBugError(e);
- }
- }
-
- private static final HashMap<Class<?>, MethodHandle> getterMap, setterMap;
-
- static {
- getterMap = new HashMap<>();
- Class<?>[] classes = new Class<?>[]{
- int[].class, byte[].class, short[].class, long[].class,
- double[].class, float[].class,
- boolean[].class, char[].class, Object[].class};
- for (Class<?> arrayClass : classes) {
- MethodHandle handle = buildGetter(arrayClass);
- getterMap.put(arrayClass, handle);
- }
- setterMap = new HashMap<>();
- for (Class<?> arrayClass : classes) {
- MethodHandle handle = buildSetter(arrayClass);
- setterMap.put(arrayClass, handle);
- }
- }
-
- private static MethodHandle buildGetter(Class<?> arrayClass) {
- MethodHandle get = MethodHandles.arrayElementGetter(arrayClass);
- MethodHandle fallback = MethodHandles.explicitCastArguments(get, get.type().changeParameterType(0, Object.class));
-
- fallback = MethodHandles.dropArguments(fallback, 2, int.class);
- MethodType reorderType = fallback.type().
- insertParameterTypes(0, int.class).
- dropParameterTypes(2, 3);
- fallback = MethodHandles.permuteArguments(fallback, reorderType, 1, 0, 0);
-
- fallback = MethodHandles.foldArguments(fallback, normalizeIndex);
- fallback = MethodHandles.explicitCastArguments(fallback, get.type());
-
- MethodHandle guard = MethodHandles.dropArguments(notNegative, 0, arrayClass);
- MethodHandle handle = MethodHandles.guardWithTest(guard, get, fallback);
- return handle;
- }
-
- private static MethodHandle buildSetter(Class<?> arrayClass) {
- MethodHandle set = MethodHandles.arrayElementSetter(arrayClass);
- MethodHandle fallback = MethodHandles.explicitCastArguments(set, set.type().changeParameterType(0, Object.class));
-
- fallback = MethodHandles.dropArguments(fallback, 3, int.class);
- MethodType reorderType = fallback.type().
- insertParameterTypes(0, int.class).
- dropParameterTypes(4, 5);
- fallback = MethodHandles.permuteArguments(fallback, reorderType, 1, 0, 3, 0);
-
- fallback = MethodHandles.foldArguments(fallback, normalizeIndex);
- fallback = MethodHandles.explicitCastArguments(fallback, set.type());
-
- MethodHandle guard = MethodHandles.dropArguments(notNegative, 0, arrayClass);
- MethodHandle handle = MethodHandles.guardWithTest(guard, set, fallback);
- return handle;
- }
-
- private static int getLength(Object array) {
- if (null == array || !array.getClass().isArray()) {
- return 0;
- }
-
- return Array.getLength(array);
- }
-
- private static int normalizeIndex(Object array, int i) {
- int temp = i;
- int size = getLength(array);
- i += size;
- if (i < 0) {
- throw new ArrayIndexOutOfBoundsException("Negative array index [" + temp + "] too large for array size " + size);
- }
- return i;
- }
-
- public static boolean notNegative(int index) {
- return index >= 0;
- }
-
- public static MethodHandle arrayGet(MethodType type) {
- Class<?> key = type.parameterType(0);
- MethodHandle res = getterMap.get(key);
- if (res != null) return res;
- res = buildGetter(key);
- res = MethodHandles.explicitCastArguments(res, type);
- return res;
- }
-
- public static MethodHandle arraySet(MethodType type) {
- Class<?> key = type.parameterType(0);
- MethodHandle res = setterMap.get(key);
- if (res != null) return res;
- res = buildSetter(key);
- res = MethodHandles.explicitCastArguments(res, type);
- return res;
- }
-}
diff --git a/src/main/java/org/codehaus/groovy/vmplugin/v7/IndyGuardsFiltersAndSignatures.java b/src/main/java/org/codehaus/groovy/vmplugin/v7/IndyGuardsFiltersAndSignatures.java
deleted file mode 100644
index 08ef8f9..0000000
--- a/src/main/java/org/codehaus/groovy/vmplugin/v7/IndyGuardsFiltersAndSignatures.java
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.codehaus.groovy.vmplugin.v7;
-
-import groovy.lang.Closure;
-import groovy.lang.GroovyObject;
-import groovy.lang.GroovyRuntimeException;
-import groovy.lang.MetaClass;
-import groovy.lang.MetaMethod;
-import groovy.lang.MetaObjectProtocol;
-import groovy.lang.MetaProperty;
-import groovy.lang.MissingMethodException;
-import org.codehaus.groovy.GroovyBugError;
-import org.codehaus.groovy.reflection.stdclasses.CachedSAMClass;
-import org.codehaus.groovy.runtime.GroovyCategorySupport;
-import org.codehaus.groovy.runtime.InvokerHelper;
-import org.codehaus.groovy.runtime.ScriptBytecodeAdapter;
-import org.codehaus.groovy.runtime.metaclass.MissingMethodExecutionFailed;
-import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation;
-import org.codehaus.groovy.runtime.typehandling.GroovyCastException;
-import org.codehaus.groovy.runtime.wrappers.Wrapper;
-
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodHandles;
-import java.lang.invoke.MethodType;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Map;
-
-import static org.codehaus.groovy.vmplugin.v7.IndyInterface.LOOKUP;
-
-/**
- * This class contains guards, runtime filters and
- * MethodType signatures used by indy.
- */
-@Deprecated
-public class IndyGuardsFiltersAndSignatures {
-
- private static final MethodType
- ZERO_GUARD = MethodType.methodType(boolean.class),
- OBJECT_GUARD = MethodType.methodType(boolean.class, Object.class),
- CLASS1_GUARD = MethodType.methodType(boolean.class, Class.class, Object.class),
- METACLASS1_GUARD = MethodType.methodType(boolean.class, MetaClass.class, Object.class),
-
- GRE_GUARD = MethodType.methodType(Object.class, GroovyRuntimeException.class),
-
- OBJECT_FILTER = MethodType.methodType(Object.class, Object.class),
-
- BOUND_INVOKER = MethodType.methodType(Object.class, Object[].class),
- ANO_INVOKER = MethodType.methodType(Object.class, Object.class, Object[].class),
- INVOKER = MethodType.methodType(Object.class, Object.class, String.class, Object[].class),
- GET_INVOKER = MethodType.methodType(Object.class, String.class);
-
- protected static final MethodHandle
- SAME_CLASS, UNWRAP_METHOD,
- SAME_MC, IS_NULL,
- UNWRAP_EXCEPTION, META_METHOD_INVOKER,
- GROOVY_OBJECT_INVOKER, GROOVY_OBJECT_GET_PROPERTY,
- HAS_CATEGORY_IN_CURRENT_THREAD_GUARD,
- BEAN_CONSTRUCTOR_PROPERTY_SETTER,
- META_PROPERTY_GETTER,
- SLOW_META_CLASS_FIND, META_CLASS_INVOKE_STATIC_METHOD,
- MOP_GET, MOP_INVOKE_CONSTRUCTOR, MOP_INVOKE_METHOD,
- INTERCEPTABLE_INVOKER,
- CLASS_FOR_NAME, BOOLEAN_IDENTITY,
- DTT_CAST_TO_TYPE, SAM_CONVERSION,
- HASHSET_CONSTRUCTOR, ARRAYLIST_CONSTRUCTOR, GROOVY_CAST_EXCEPTION,
- EQUALS;
-
- static {
- try {
- SAME_CLASS = LOOKUP.findStatic(IndyGuardsFiltersAndSignatures.class, "sameClass", CLASS1_GUARD);
- UNWRAP_METHOD = LOOKUP.findStatic(IndyGuardsFiltersAndSignatures.class, "unwrap", OBJECT_FILTER);
- SAME_MC = LOOKUP.findStatic(IndyGuardsFiltersAndSignatures.class, "isSameMetaClass", METACLASS1_GUARD);
- IS_NULL = LOOKUP.findStatic(IndyGuardsFiltersAndSignatures.class, "isNull", OBJECT_GUARD);
- UNWRAP_EXCEPTION = LOOKUP.findStatic(IndyGuardsFiltersAndSignatures.class, "unwrap", GRE_GUARD);
- GROOVY_OBJECT_INVOKER = LOOKUP.findStatic(IndyGuardsFiltersAndSignatures.class, "invokeGroovyObjectInvoker", INVOKER.insertParameterTypes(0, MissingMethodException.class));
-
- META_METHOD_INVOKER = LOOKUP.findVirtual(MetaMethod.class, "doMethodInvoke", ANO_INVOKER);
- HAS_CATEGORY_IN_CURRENT_THREAD_GUARD = LOOKUP.findStatic(GroovyCategorySupport.class, "hasCategoryInCurrentThread", ZERO_GUARD);
- GROOVY_OBJECT_GET_PROPERTY = LOOKUP.findVirtual(GroovyObject.class, "getProperty", GET_INVOKER);
- META_CLASS_INVOKE_STATIC_METHOD = LOOKUP.findVirtual(MetaObjectProtocol.class, "invokeStaticMethod", INVOKER);
-
- BEAN_CONSTRUCTOR_PROPERTY_SETTER = LOOKUP.findStatic(IndyGuardsFiltersAndSignatures.class, "setBeanProperties", MethodType.methodType(Object.class, MetaClass.class, Object.class, Map.class));
- META_PROPERTY_GETTER = LOOKUP.findVirtual(MetaProperty.class, "getProperty", OBJECT_FILTER);
- MOP_GET = LOOKUP.findVirtual(MetaObjectProtocol.class, "getProperty", MethodType.methodType(Object.class, Object.class, String.class));
- MOP_INVOKE_CONSTRUCTOR = LOOKUP.findVirtual(MetaObjectProtocol.class, "invokeConstructor", BOUND_INVOKER);
- MOP_INVOKE_METHOD = LOOKUP.findVirtual(MetaObjectProtocol.class, "invokeMethod", INVOKER);
- SLOW_META_CLASS_FIND = LOOKUP.findStatic(InvokerHelper.class, "getMetaClass", MethodType.methodType(MetaClass.class, Object.class));
- INTERCEPTABLE_INVOKER = LOOKUP.findVirtual(GroovyObject.class, "invokeMethod", MethodType.methodType(Object.class, String.class, Object.class));
-
- CLASS_FOR_NAME = LOOKUP.findStatic(Class.class, "forName", MethodType.methodType(Class.class, String.class, boolean.class, ClassLoader.class));
-
- BOOLEAN_IDENTITY = MethodHandles.identity(Boolean.class);
- DTT_CAST_TO_TYPE = LOOKUP.findStatic(DefaultTypeTransformation.class, "castToType", MethodType.methodType(Object.class, Object.class, Class.class));
- SAM_CONVERSION = LOOKUP.findStatic(CachedSAMClass.class, "coerceToSAM", MethodType.methodType(Object.class, Closure.class, Method.class, Class.class));
- HASHSET_CONSTRUCTOR = LOOKUP.findConstructor(HashSet.class, MethodType.methodType(void.class, Collection.class));
- ARRAYLIST_CONSTRUCTOR = LOOKUP.findConstructor(ArrayList.class, MethodType.methodType(void.class, Collection.class));
- GROOVY_CAST_EXCEPTION = LOOKUP.findConstructor(GroovyCastException.class, MethodType.methodType(void.class, Object.class, Class.class));
-
- EQUALS = LOOKUP.findVirtual(Object.class, "equals", OBJECT_GUARD);
- } catch (Exception e) {
- throw new GroovyBugError(e);
- }
- }
-
- protected static final MethodHandle NULL_REF = MethodHandles.constant(Object.class, null);
-
- /**
- * This method is called by he handle to realize the bean constructor
- * with property map.
- */
- public static Object setBeanProperties(MetaClass mc, Object bean, Map properties) {
- for (Object o : properties.entrySet()) {
- Map.Entry entry = (Map.Entry) o;
- String key = entry.getKey().toString();
-
- Object value = entry.getValue();
- mc.setProperty(bean, key, value);
- }
- return bean;
- }
-
- /**
- * {@link GroovyObject#invokeMethod(String, Object)} path as fallback.
- * This method is called by the handle as exception handler in case the
- * selected method causes a MissingMethodExecutionFailed, where
- * we will just give through the exception, and a normal
- * MissingMethodException where we call {@link GroovyObject#invokeMethod(String, Object)}
- * if receiver class, the type transported by the exception and the name
- * for the method stored in the exception and our current method name
- * are equal.
- * Should those conditions not apply we just rethrow the exception.
- */
- public static Object invokeGroovyObjectInvoker(MissingMethodException e, Object receiver, String name, Object[] args) {
- if (e instanceof MissingMethodExecutionFailed) {
- throw (MissingMethodException) e.getCause();
- } else if (receiver.getClass() == e.getType() && e.getMethod().equals(name)) {
- //TODO: we should consider calling this one directly for MetaClassImpl,
- // then we save the new method selection
-
- // in case there's nothing else, invoke the object's own invokeMethod()
- return ((GroovyObject) receiver).invokeMethod(name, args);
- } else {
- throw e;
- }
- }
-
- /**
- * Unwraps a {@link GroovyRuntimeException}.
- * This method is called by the handle to unwrap internal exceptions
- * of the runtime.
- */
- public static Object unwrap(GroovyRuntimeException gre) throws Throwable {
- throw ScriptBytecodeAdapter.unwrap(gre);
- }
-
- /**
- * called by handle
- */
- public static boolean isSameMetaClass(MetaClass mc, Object receiver) {
- //TODO: remove this method if possible by switchpoint usage
- return receiver instanceof GroovyObject && mc == ((GroovyObject) receiver).getMetaClass();
- }
-
- /**
- * Unwraps a {@link Wrapper}.
- * This method is called by the handle to unwrap a Wrapper, which
- * we use to force method selection.
- */
- public static Object unwrap(Object o) {
- Wrapper w = (Wrapper) o;
- return w.unwrap();
- }
-
- /**
- * Guard to check if the argument is null.
- * This method is called by the handle to check
- * if the provided argument is null.
- */
- public static boolean isNull(Object o) {
- return o == null;
- }
-
- /**
- * Guard to check if the provided Object has the same
- * class as the provided Class. This method will
- * return false if the Object is null.
- */
- public static boolean sameClass(Class<?> c, Object o) {
- if (o == null) return false;
- return o.getClass() == c;
- }
-}
diff --git a/src/main/java/org/codehaus/groovy/vmplugin/v7/IndyInterface.java b/src/main/java/org/codehaus/groovy/vmplugin/v7/IndyInterface.java
deleted file mode 100644
index fff40836..0000000
--- a/src/main/java/org/codehaus/groovy/vmplugin/v7/IndyInterface.java
+++ /dev/null
@@ -1,340 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.codehaus.groovy.vmplugin.v7;
-
-import groovy.lang.GroovySystem;
-import org.apache.groovy.util.SystemUtil;
-import org.codehaus.groovy.GroovyBugError;
-import org.codehaus.groovy.runtime.NullObject;
-
-import java.lang.invoke.CallSite;
-import java.lang.invoke.ConstantCallSite;
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodHandles;
-import java.lang.invoke.MethodHandles.Lookup;
-import java.lang.invoke.MethodType;
-import java.lang.invoke.MutableCallSite;
-import java.lang.invoke.SwitchPoint;
-import java.util.Map;
-import java.util.function.BiFunction;
-import java.util.function.Function;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-/**
- * Bytecode level interface for bootstrap methods used by invokedynamic.
- * This class provides a logging ability by using the boolean system property
- * groovy.indy.logging. Other than that this class contains the
- * interfacing methods with bytecode for invokedynamic as well as some helper
- * methods and classes.
- */
-@Deprecated
-public class IndyInterface {
- private static final long INDY_OPTIMIZE_THRESHOLD = SystemUtil.getLongSafe("groovy.indy.optimize.threshold", 100_000L);
-
- /**
- * flags for method and property calls
- */
- public static final int
- SAFE_NAVIGATION = 1, THIS_CALL = 2,
- GROOVY_OBJECT = 4, IMPLICIT_THIS = 8,
- SPREAD_CALL = 16, UNCACHED_CALL = 32;
-
- /**
- * Enum for easy differentiation between call types
- */
- public enum CallType {
- /**
- * Method invocation type
- */
- METHOD("invoke"),
- /**
- * Constructor invocation type
- */
- INIT("init"),
- /**
- * Get property invocation type
- */
- GET("getProperty"),
- /**
- * Set property invocation type
- */
- SET("setProperty"),
- /**
- * Cast invocation type
- */
- CAST("cast");
-
- private static final Map<String, CallType> NAME_CALLTYPE_MAP =
- Stream.of(CallType.values()).collect(Collectors.toMap(CallType::getCallSiteName, Function.identity()));
-
- /**
- * The name of the call site type
- */
- private final String name;
-
- CallType(String callSiteName) {
- this.name = callSiteName;
- }
-
- /**
- * Returns the name of the call site type
- */
- public String getCallSiteName() {
- return name;
- }
-
- public static CallType fromCallSiteName(String callSiteName) {
- return NAME_CALLTYPE_MAP.get(callSiteName);
- }
- }
-
- /**
- * Logger
- */
- protected static final Logger LOG;
- /**
- * boolean to indicate if logging for indy is enabled
- */
- protected static final boolean LOG_ENABLED;
-
- static {
- boolean enableLogger = false;
-
- LOG = Logger.getLogger(IndyInterface.class.getName());
-
- try {
- if (System.getProperty("groovy.indy.logging") != null) {
- LOG.setLevel(Level.ALL);
- enableLogger = true;
- }
- } catch (SecurityException e) {
- // Allow security managers to prevent system property access
- }
-
- LOG_ENABLED = enableLogger;
- }
-
- /**
- * LOOKUP constant used for for example unreflect calls
- */
- public static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
-
- /**
- * handle for the fromCache method
- */
- private static final MethodHandle FROM_CACHE_METHOD;
-
- /**
- * handle for the selectMethod method
- */
- private static final MethodHandle SELECT_METHOD;
-
- static {
-
- try {
- MethodType mt = MethodType.methodType(Object.class, MutableCallSite.class, Class.class, String.class, int.class, Boolean.class, Boolean.class, Boolean.class, Object.class, Object[].class);
- FROM_CACHE_METHOD = LOOKUP.findStatic(IndyInterface.class, "fromCache", mt);
- } catch (Exception e) {
- throw new GroovyBugError(e);
- }
-
- try {
- MethodType mt = MethodType.methodType(Object.class, MutableCallSite.class, Class.class, String.class, int.class, Boolean.class, Boolean.class, Boolean.class, Object.class, Object[].class);
- SELECT_METHOD = LOOKUP.findStatic(IndyInterface.class, "selectMethod", mt);
- } catch (Exception e) {
- throw new GroovyBugError(e);
- }
- }
-
- protected static SwitchPoint switchPoint = new SwitchPoint();
-
- static {
- GroovySystem.getMetaClassRegistry().addMetaClassRegistryChangeEventListener(cmcu -> invalidateSwitchPoints());
- }
-
- /**
- * Callback for constant meta class update change
- */
- protected static void invalidateSwitchPoints() {
- if (LOG_ENABLED) {
- LOG.info("invalidating switch point");
- }
-
- synchronized (IndyInterface.class) {
- SwitchPoint old = switchPoint;
- switchPoint = new SwitchPoint();
- SwitchPoint.invalidateAll(new SwitchPoint[]{old});
- }
- }
-
- /**
- * bootstrap method for method calls from Groovy compiled code with indy
- * enabled. This method gets a flags parameter which uses the following
- * encoding:<ul>
- * <li>{@value #SAFE_NAVIGATION} is the flag value for safe navigation see {@link #SAFE_NAVIGATION}</li>
- * <li>{@value #THIS_CALL} is the flag value for a call on this see {@link #THIS_CALL}</li>
- * </ul>
- *
- * @param caller - the caller
- * @param callType - the type of the call
- * @param type - the call site type
- * @param name - the real method name
- * @param flags - call flags
- * @return the produced CallSite
- * @since Groovy 2.1.0
- */
- public static CallSite bootstrap(Lookup caller, String callType, MethodType type, String name, int flags) {
- CallType ct = CallType.fromCallSiteName(callType);
- if (null == ct) throw new GroovyBugError("Unknown call type: " + callType);
-
- int callID = ct.ordinal();
- boolean safe = (flags & SAFE_NAVIGATION) != 0;
- boolean thisCall = (flags & THIS_CALL) != 0;
- boolean spreadCall = (flags & SPREAD_CALL) != 0;
-
- return realBootstrap(caller, name, callID, type, safe, thisCall, spreadCall);
- }
-
- /**
- * backing bootstrap method with all parameters
- */
- private static CallSite realBootstrap(Lookup caller, String name, int callID, MethodType type, boolean safe, boolean thisCall, boolean spreadCall) {
- // since indy does not give us the runtime types
- // we produce first a dummy call site, which then changes the target to one when INDY_OPTIMIZE_THRESHOLD is reached,
- // that does the method selection including the direct call to the
- // real method.
- CacheableCallSite mc = new CacheableCallSite(type);
- final Class<?> sender = caller.lookupClass();
- MethodHandle mh = makeAdapter(mc, sender, name, callID, type, safe, thisCall, spreadCall);
- mc.setTarget(mh);
- mc.setDefaultTarget(mh);
- mc.setFallbackTarget(makeFallBack(mc, sender, name, callID, type, safe, thisCall, spreadCall));
-
- return mc;
- }
-
- /**
- * Makes a fallback method for an invalidated method selection
- */
- protected static MethodHandle makeFallBack(MutableCallSite mc, Class<?> sender, String name, int callID, MethodType type, boolean safeNavigation, boolean thisCall, boolean spreadCall) {
- return make(mc, sender, name, callID, type, safeNavigation, thisCall, spreadCall, SELECT_METHOD);
- }
-
- /**
- * Makes an adapter method for method selection, i.e. get the cached methodhandle(fast path) or fallback
- */
- private static MethodHandle makeAdapter(MutableCallSite mc, Class<?> sender, String name, int callID, MethodType type, boolean safeNavigation, boolean thisCall, boolean spreadCall) {
- return make(mc, sender, name, callID, type, safeNavigation, thisCall, spreadCall, FROM_CACHE_METHOD);
- }
-
- private static MethodHandle make(MutableCallSite mc, Class<?> sender, String name, int callID, MethodType type, boolean safeNavigation, boolean thisCall, boolean spreadCall, MethodHandle originalMH) {
- MethodHandle mh = MethodHandles.insertArguments(originalMH, 0, mc, sender, name, callID, safeNavigation, thisCall, spreadCall, /*dummy receiver:*/ 1);
- return mh.asCollector(Object[].class, type.parameterCount()).asType(type);
- }
-
- /**
- * Get the cached methodhandle. if the related methodhandle is not found in the inline cache, cache and return it.
- */
- public static Object fromCache(MutableCallSite callSite, Class<?> sender, String methodName, int callID, Boolean safeNavigation, Boolean thisCall, Boolean spreadCall, Object dummyReceiver, Object[] arguments) throws Throwable {
- MethodHandleWrapper mhw =
- doWithCallSite(
- callSite, arguments,
- (cs, receiver) ->
- cs.getAndPut(
- receiver.getClass().getName(),
- c -> fallback(callSite, sender, methodName, callID, safeNavigation, thisCall, spreadCall, dummyReceiver, arguments)
- )
- );
-
- if (mhw.isCanSetTarget() && (callSite.getTarget() != mhw.getTargetMethodHandle()) && (mhw.getLatestHitCount() > INDY_OPTIMIZE_THRESHOLD)) {
- callSite.setTarget(mhw.getTargetMethodHandle());
- if (LOG_ENABLED) LOG.info("call site target set, preparing outside invocation");
-
- mhw.resetLatestHitCount();
- }
-
- return mhw.getCachedMethodHandle().invokeExact(arguments);
- }
-
- /**
- * Core method for indy method selection using runtime types.
- */
- public static Object selectMethod(MutableCallSite callSite, Class<?> sender, String methodName, int callID, Boolean safeNavigation, Boolean thisCall, Boolean spreadCall, Object dummyReceiver, Object[] arguments) throws Throwable {
- final MethodHandleWrapper mhw = fallback(callSite, sender, methodName, callID, safeNavigation, thisCall, spreadCall, dummyReceiver, arguments);
-
- if (callSite instanceof CacheableCallSite) {
- CacheableCallSite cacheableCallSite = (CacheableCallSite) callSite;
-
- final MethodHandle defaultTarget = cacheableCallSite.getDefaultTarget();
- final long fallbackCount = cacheableCallSite.incrementFallbackCount();
- if ((fallbackCount > INDY_OPTIMIZE_THRESHOLD) && (cacheableCallSite.getTarget() != defaultTarget)) {
- cacheableCallSite.setTarget(defaultTarget);
- if (LOG_ENABLED) LOG.info("call site target reset to default, preparing outside invocation");
-
- cacheableCallSite.resetFallbackCount();
- }
-
- if (defaultTarget == cacheableCallSite.getTarget()) {
- // correct the stale methodhandle in the inline cache of callsite
- // it is important but impacts the performance somehow when cache misses frequently
- doWithCallSite(callSite, arguments, (cs, receiver) -> cs.put(receiver.getClass().getName(), mhw));
- }
- }
-
- return mhw.getCachedMethodHandle().invokeExact(arguments);
- }
-
- private static MethodHandleWrapper fallback(MutableCallSite callSite, Class<?> sender, String methodName, int callID, Boolean safeNavigation, Boolean thisCall, Boolean spreadCall, Object dummyReceiver, Object[] arguments) {
- Selector selector = Selector.getSelector(callSite, sender, methodName, callID, safeNavigation, thisCall, spreadCall, arguments);
- selector.setCallSiteTarget();
-
- return new MethodHandleWrapper(
- selector.handle.asSpreader(Object[].class, arguments.length).asType(MethodType.methodType(Object.class, Object[].class)),
- selector.handle,
- selector.cache
- );
- }
-
- private static <T> T doWithCallSite(MutableCallSite callSite, Object[] arguments, BiFunction<? super CacheableCallSite, ? super Object, ? extends T> f) {
- if (callSite instanceof CacheableCallSite) {
- CacheableCallSite cacheableCallSite = (CacheableCallSite) callSite;
- Object receiver = arguments[0];
-
- if (null == receiver) receiver = NullObject.getNullObject();
-
- return f.apply(cacheableCallSite, receiver);
- }
-
- throw new GroovyBugError("CacheableCallSite is expected, but the actual callsite is: " + callSite);
- }
-
- /**
- * @since 2.5.0
- */
- public static CallSite staticArrayAccess(MethodHandles.Lookup lookup, String name, MethodType type) {
- if (type.parameterCount() == 2) {
- return new ConstantCallSite(IndyArrayAccess.arrayGet(type));
- } else {
- return new ConstantCallSite(IndyArrayAccess.arraySet(type));
- }
- }
-}
diff --git a/src/main/java/org/codehaus/groovy/vmplugin/v7/IndyMath.java b/src/main/java/org/codehaus/groovy/vmplugin/v7/IndyMath.java
deleted file mode 100644
index f758ae5..0000000
--- a/src/main/java/org/codehaus/groovy/vmplugin/v7/IndyMath.java
+++ /dev/null
@@ -1,278 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.codehaus.groovy.vmplugin.v7;
-
-import groovy.lang.MetaMethod;
-import org.codehaus.groovy.GroovyBugError;
-
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodType;
-import java.math.BigDecimal;
-import java.util.HashMap;
-import java.util.Map;
-
-import static org.codehaus.groovy.vmplugin.v7.IndyInterface.LOOKUP;
-import static org.codehaus.groovy.vmplugin.v7.TypeHelper.isBigDecCategory;
-import static org.codehaus.groovy.vmplugin.v7.TypeHelper.isDoubleCategory;
-import static org.codehaus.groovy.vmplugin.v7.TypeHelper.isIntCategory;
-import static org.codehaus.groovy.vmplugin.v7.TypeHelper.isLongCategory;
-import static org.codehaus.groovy.vmplugin.v7.TypeHelper.replaceWithMoreSpecificType;
-
-/**
- * This class contains math operations used by indy instead of the normal
- * meta method and call site caching system. The goal is to avoid boxing, thus
- * use primitive types for parameters and return types where possible.
- * WARNING: This class is for internal use only. Do not use it outside of the
- * org.codehaus.groovy.vmplugin.v7 package of groovy-core.
- */
-@Deprecated
-public class IndyMath {
-
- private static final MethodType
- IV = MethodType.methodType(Void.TYPE, int.class),
- II = MethodType.methodType(int.class, int.class),
- IIV = MethodType.methodType(Void.TYPE, int.class, int.class),
- III = MethodType.methodType(int.class, int.class, int.class),
- LV = MethodType.methodType(Void.TYPE, long.class),
- LL = MethodType.methodType(long.class, long.class),
- LLV = MethodType.methodType(Void.TYPE, long.class, long.class),
- LLL = MethodType.methodType(long.class, long.class, long.class),
- DV = MethodType.methodType(Void.TYPE, double.class),
- DD = MethodType.methodType(double.class, double.class),
- DDV = MethodType.methodType(Void.TYPE, double.class, double.class),
- DDD = MethodType.methodType(double.class, double.class, double.class),
- GV = MethodType.methodType(Void.TYPE, BigDecimal.class),
- GGV = MethodType.methodType(Void.TYPE, BigDecimal.class, BigDecimal.class),
- OOV = MethodType.methodType(Void.TYPE, Object.class, Object.class);
-
- private static void makeMapEntry(String method, MethodType[] keys, MethodType[] values) throws NoSuchMethodException, IllegalAccessException {
- Map<MethodType, MethodHandle> xMap = new HashMap<>();
- METHODS.put(method, xMap);
- for (int i = 0; i < keys.length; i++) {
- xMap.put(keys[i], LOOKUP.findStatic(IndyMath.class, method, values[i]));
- }
- }
-
- private static final Map<String, Map<MethodType, MethodHandle>> METHODS = new HashMap<>();
-
- static {
- try {
-
- MethodType[] keys = new MethodType[]{IIV, LLV, DDV};
- MethodType[] values = new MethodType[]{III, LLL, DDD};
- makeMapEntry("minus", keys, values);
- makeMapEntry("plus", keys, values);
- makeMapEntry("multiply", keys, values);
-
- keys = new MethodType[]{DDV};
- values = new MethodType[]{DDD};
- makeMapEntry("div", keys, values);
-
- keys = new MethodType[]{IV, LV, DV};
- values = new MethodType[]{II, LL, DD};
- makeMapEntry("next", keys, values);
- makeMapEntry("previous", keys, values);
-
- keys = new MethodType[]{IIV, LLV};
- values = new MethodType[]{III, LLL};
- makeMapEntry("mod", keys, values);
- makeMapEntry("or", keys, values);
- makeMapEntry("xor", keys, values);
- makeMapEntry("and", keys, values);
- makeMapEntry("leftShift", keys, values);
- makeMapEntry("rightShift", keys, values);
-
- } catch (Exception e) {
- throw new GroovyBugError(e);
- }
- }
-
- /**
- * Choose a method to replace the originally chosen metaMethod to have a
- * more efficient call path.
- */
- public static boolean chooseMathMethod(Selector info, MetaMethod metaMethod) {
- Map<MethodType, MethodHandle> xmap = METHODS.get(info.name);
- if (xmap == null) return false;
-
- MethodType type = replaceWithMoreSpecificType(info.args, info.targetType);
- type = widenOperators(type);
-
- MethodHandle handle = xmap.get(type);
- if (handle == null) return false;
-
- info.handle = handle;
- return true;
- }
-
- /**
- * Widens the operators. For math operations like a+b we generally
- * execute them using a conversion to certain types. If a for example
- * is an int and b a byte, we do the operation using integer math. This
- * method gives a simplified MethodType that contains the two operators
- * with this widening according to Groovy rules applied. That means both
- * parameters in the MethodType will have the same type.
- */
- private static MethodType widenOperators(MethodType mt) {
- final int parameterCount = mt.parameterCount();
- if (parameterCount == 2) {
- Class<?> leftType = mt.parameterType(0);
- Class<?> rightType = mt.parameterType(1);
-
- if (isIntCategory(leftType) && isIntCategory(rightType)) return IIV;
- if (isLongCategory(leftType) && isLongCategory(rightType)) return LLV;
- if (isBigDecCategory(leftType) && isBigDecCategory(rightType)) return GGV;
- if (isDoubleCategory(leftType) && isDoubleCategory(rightType)) return DDV;
-
- return OOV;
- } else if (parameterCount == 1) {
- Class<?> leftType = mt.parameterType(0);
- if (isIntCategory(leftType)) return IV;
- if (isLongCategory(leftType)) return LV;
- if (isBigDecCategory(leftType)) return GV;
- if (isDoubleCategory(leftType)) return DV;
- }
- return mt;
- }
-
- // math methods used by indy
-
- // int x int
- public static int plus(int a, int b) {
- return a + b;
- }
-
- public static int minus(int a, int b) {
- return a - b;
- }
-
- public static int multiply(int a, int b) {
- return a * b;
- }
-
- public static int mod(int a, int b) {
- return a % b;
- }
-
- public static int or(int a, int b) {
- return a | b;
- }
-
- public static int xor(int a, int b) {
- return a ^ b;
- }
-
- public static int and(int a, int b) {
- return a & b;
- }
-
- public static int leftShift(int a, int b) {
- return a << b;
- }
-
- public static int rightShift(int a, int b) {
- return a >> b;
- }
-
- // long x long
- public static long plus(long a, long b) {
- return a + b;
- }
-
- public static long minus(long a, long b) {
- return a - b;
- }
-
- public static long multiply(long a, long b) {
- return a * b;
- }
-
- public static long mod(long a, long b) {
- return a % b;
- }
-
- public static long or(long a, long b) {
- return a | b;
- }
-
- public static long xor(long a, long b) {
- return a ^ b;
- }
-
- public static long and(long a, long b) {
- return a & b;
- }
-
- public static long leftShift(long a, long b) {
- return a << b;
- }
-
- public static long rightShift(long a, long b) {
- return a >> b;
- }
-
- // double x double
- public static double plus(double a, double b) {
- return a + b;
- }
-
- public static double minus(double a, double b) {
- return a - b;
- }
-
- public static double multiply(double a, double b) {
- return a * b;
- }
-
- public static double div(double a, double b) {
- return a / b;
- }
-
- // next & previous
- public static int next(int i) {
- return i + 1;
- }
-
- public static long next(long l) {
- return l + 1;
- }
-
- public static double next(double d) {
- return d + 1;
- }
-
- public static int previous(int i) {
- return i - 1;
- }
-
- public static long previous(long l) {
- return l - 1;
- }
-
- public static double previous(double d) {
- return d - 1;
- }
-
- /*
- further operations to be handled here maybe:
- a / b a.div(b) (if one is double, return double, otherwise BD)
- a[b] a.getAt(b)
- a[b] = c a.putAt(b, c)
- */
-}
diff --git a/src/main/java/org/codehaus/groovy/vmplugin/v7/Java7.java b/src/main/java/org/codehaus/groovy/vmplugin/v7/Java7.java
deleted file mode 100644
index 6f0eca9..0000000
--- a/src/main/java/org/codehaus/groovy/vmplugin/v7/Java7.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.codehaus.groovy.vmplugin.v7;
-
-import org.codehaus.groovy.GroovyBugError;
-import org.codehaus.groovy.reflection.ReflectionUtils;
-import org.codehaus.groovy.vmplugin.v6.Java6;
-
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodHandles;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Method;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-
-/**
- * Java 7 based functions.
- * <p>
- * For crude customization, you can add your own methods to your own version and place it on the classpath ahead of this one.
- */
-@Deprecated
-public class Java7 extends Java6 {
- private static class LookupHolder {
- private static final Constructor<MethodHandles.Lookup> LOOKUP_Constructor;
-
- static {
- Constructor<MethodHandles.Lookup> con;
- try {
- con = MethodHandles.Lookup.class.getDeclaredConstructor(Class.class, int.class);
- } catch (NoSuchMethodException e) {
- throw new GroovyBugError(e);
- }
- try {
- if (!con.isAccessible()) {
- final Constructor tmp = con;
- AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
- ReflectionUtils.trySetAccessible(tmp);
- return null;
- });
- }
- } catch (SecurityException se) {
- con = null;
- } catch (RuntimeException re) {
- // test for JDK9 JIGSAW
- if (!"java.lang.reflect.InaccessibleObjectException".equals(re.getClass().getName())) throw re;
- con = null;
- }
- LOOKUP_Constructor = con;
- }
- }
-
- private static Constructor<MethodHandles.Lookup> getLookupConstructor() {
- return LookupHolder.LOOKUP_Constructor;
- }
-
- @Override
- public void invalidateCallSites() {
- IndyInterface.invalidateSwitchPoints();
- }
-
- @Override
- public int getVersion() {
- return 7;
- }
-
- @Override
- public Object getInvokeSpecialHandle(final Method method, final Object receiver) {
- if (getLookupConstructor() == null) {
- return super.getInvokeSpecialHandle(method, receiver);
- }
- if (!method.isAccessible()) {
- AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
- ReflectionUtils.trySetAccessible(method);
- return null;
- });
- }
- Class declaringClass = method.getDeclaringClass();
- try {
- return getLookupConstructor().newInstance(declaringClass, -1).
- unreflectSpecial(method, declaringClass).
- bindTo(receiver);
- } catch (ReflectiveOperationException e) {
- throw new GroovyBugError(e);
- }
- }
-
- @Override
- public Object invokeHandle(Object handle, Object[] args) throws Throwable {
- MethodHandle mh = (MethodHandle) handle;
- return mh.invokeWithArguments(args);
- }
-}
diff --git a/src/main/java/org/codehaus/groovy/vmplugin/v7/MethodHandleWrapper.java b/src/main/java/org/codehaus/groovy/vmplugin/v7/MethodHandleWrapper.java
deleted file mode 100644
index c2e4d43..0000000
--- a/src/main/java/org/codehaus/groovy/vmplugin/v7/MethodHandleWrapper.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.codehaus.groovy.vmplugin.v7;
-
-import java.lang.invoke.MethodHandle;
-import java.util.concurrent.atomic.AtomicLong;
-
-/**
- * Wrap method handles
- *
- * @since 3.0.0
- */
-@Deprecated
-class MethodHandleWrapper {
- private final MethodHandle cachedMethodHandle;
- private final MethodHandle targetMethodHandle;
- private final boolean canSetTarget;
- private final AtomicLong latestHitCount = new AtomicLong(0);
-
- public MethodHandleWrapper(MethodHandle cachedMethodHandle, MethodHandle targetMethodHandle, boolean canSetTarget) {
- this.cachedMethodHandle = cachedMethodHandle;
- this.targetMethodHandle = targetMethodHandle;
- this.canSetTarget = canSetTarget;
- }
-
- public MethodHandle getCachedMethodHandle() {
- return cachedMethodHandle;
- }
-
- public MethodHandle getTargetMethodHandle() {
- return targetMethodHandle;
- }
-
- public boolean isCanSetTarget() {
- return canSetTarget;
- }
-
- public long incrementLatestHitCount() {
- return latestHitCount.incrementAndGet();
- }
-
- public void resetLatestHitCount() {
- latestHitCount.set(0);
- }
-
- public long getLatestHitCount() {
- return latestHitCount.get();
- }
-}
diff --git a/src/main/java/org/codehaus/groovy/vmplugin/v7/Selector.java b/src/main/java/org/codehaus/groovy/vmplugin/v7/Selector.java
deleted file mode 100644
index 7633a24..0000000
--- a/src/main/java/org/codehaus/groovy/vmplugin/v7/Selector.java
+++ /dev/null
@@ -1,1088 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.codehaus.groovy.vmplugin.v7;
-
-import groovy.lang.AdaptingMetaClass;
-import groovy.lang.Closure;
-import groovy.lang.ExpandoMetaClass;
-import groovy.lang.GroovyInterceptable;
-import groovy.lang.GroovyObject;
-import groovy.lang.GroovyRuntimeException;
-import groovy.lang.GroovySystem;
-import groovy.lang.MetaClass;
-import groovy.lang.MetaClassImpl;
-import groovy.lang.MetaClassImpl.MetaConstructor;
-import groovy.lang.MetaMethod;
-import groovy.lang.MetaProperty;
-import groovy.lang.MissingMethodException;
-import groovy.transform.Internal;
-import org.codehaus.groovy.GroovyBugError;
-import org.codehaus.groovy.reflection.CachedField;
-import org.codehaus.groovy.reflection.CachedMethod;
-import org.codehaus.groovy.reflection.ClassInfo;
-import org.codehaus.groovy.reflection.GeneratedMetaMethod;
-import org.codehaus.groovy.reflection.stdclasses.CachedSAMClass;
-import org.codehaus.groovy.runtime.GeneratedClosure;
-import org.codehaus.groovy.runtime.GroovyCategorySupport;
-import org.codehaus.groovy.runtime.GroovyCategorySupport.CategoryMethod;
-import org.codehaus.groovy.runtime.NullObject;
-import org.codehaus.groovy.runtime.dgmimpl.NumberNumberMetaMethod;
-import org.codehaus.groovy.runtime.metaclass.ClosureMetaClass;
-import org.codehaus.groovy.runtime.metaclass.MetaClassRegistryImpl;
-import org.codehaus.groovy.runtime.metaclass.MethodMetaProperty;
-import org.codehaus.groovy.runtime.metaclass.NewInstanceMetaMethod;
-import org.codehaus.groovy.runtime.metaclass.NewStaticMetaMethod;
-import org.codehaus.groovy.runtime.metaclass.ReflectionMetaMethod;
-import org.codehaus.groovy.runtime.wrappers.Wrapper;
-import org.codehaus.groovy.vmplugin.VMPluginFactory;
-import org.codehaus.groovy.vmplugin.v7.IndyInterface.CallType;
-
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodHandles;
-import java.lang.invoke.MethodType;
-import java.lang.invoke.MutableCallSite;
-import java.lang.reflect.Array;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
-
-import static org.codehaus.groovy.vmplugin.v7.IndyGuardsFiltersAndSignatures.ARRAYLIST_CONSTRUCTOR;
-import static org.codehaus.groovy.vmplugin.v7.IndyGuardsFiltersAndSignatures.BEAN_CONSTRUCTOR_PROPERTY_SETTER;
-import static org.codehaus.groovy.vmplugin.v7.IndyGuardsFiltersAndSignatures.BOOLEAN_IDENTITY;
-import static org.codehaus.groovy.vmplugin.v7.IndyGuardsFiltersAndSignatures.CLASS_FOR_NAME;
-import static org.codehaus.groovy.vmplugin.v7.IndyGuardsFiltersAndSignatures.DTT_CAST_TO_TYPE;
-import static org.codehaus.groovy.vmplugin.v7.IndyGuardsFiltersAndSignatures.EQUALS;
-import static org.codehaus.groovy.vmplugin.v7.IndyGuardsFiltersAndSignatures.GROOVY_CAST_EXCEPTION;
-import static org.codehaus.groovy.vmplugin.v7.IndyGuardsFiltersAndSignatures.GROOVY_OBJECT_GET_PROPERTY;
-import static org.codehaus.groovy.vmplugin.v7.IndyGuardsFiltersAndSignatures.GROOVY_OBJECT_INVOKER;
-import static org.codehaus.groovy.vmplugin.v7.IndyGuardsFiltersAndSignatures.HASHSET_CONSTRUCTOR;
-import static org.codehaus.groovy.vmplugin.v7.IndyGuardsFiltersAndSignatures.HAS_CATEGORY_IN_CURRENT_THREAD_GUARD;
-import static org.codehaus.groovy.vmplugin.v7.IndyGuardsFiltersAndSignatures.INTERCEPTABLE_INVOKER;
-import static org.codehaus.groovy.vmplugin.v7.IndyGuardsFiltersAndSignatures.IS_NULL;
-import static org.codehaus.groovy.vmplugin.v7.IndyGuardsFiltersAndSignatures.META_CLASS_INVOKE_STATIC_METHOD;
-import static org.codehaus.groovy.vmplugin.v7.IndyGuardsFiltersAndSignatures.META_METHOD_INVOKER;
-import static org.codehaus.groovy.vmplugin.v7.IndyGuardsFiltersAndSignatures.META_PROPERTY_GETTER;
-import static org.codehaus.groovy.vmplugin.v7.IndyGuardsFiltersAndSignatures.MOP_GET;
-import static org.codehaus.groovy.vmplugin.v7.IndyGuardsFiltersAndSignatures.MOP_INVOKE_CONSTRUCTOR;
-import static org.codehaus.groovy.vmplugin.v7.IndyGuardsFiltersAndSignatures.MOP_INVOKE_METHOD;
-import static org.codehaus.groovy.vmplugin.v7.IndyGuardsFiltersAndSignatures.NULL_REF;
-import static org.codehaus.groovy.vmplugin.v7.IndyGuardsFiltersAndSignatures.SAME_CLASS;
-import static org.codehaus.groovy.vmplugin.v7.IndyGuardsFiltersAndSignatures.SAME_MC;
-import static org.codehaus.groovy.vmplugin.v7.IndyGuardsFiltersAndSignatures.SAM_CONVERSION;
-import static org.codehaus.groovy.vmplugin.v7.IndyGuardsFiltersAndSignatures.UNWRAP_EXCEPTION;
-import static org.codehaus.groovy.vmplugin.v7.IndyGuardsFiltersAndSignatures.UNWRAP_METHOD;
-import static org.codehaus.groovy.vmplugin.v7.IndyGuardsFiltersAndSignatures.unwrap;
-import static org.codehaus.groovy.vmplugin.v7.IndyInterface.LOG;
-import static org.codehaus.groovy.vmplugin.v7.IndyInterface.LOG_ENABLED;
-import static org.codehaus.groovy.vmplugin.v7.IndyInterface.LOOKUP;
-import static org.codehaus.groovy.vmplugin.v7.IndyInterface.switchPoint;
-
-@Deprecated
-public abstract class Selector {
- public Object[] args, originalArguments;
- public MetaMethod method;
- public MethodType targetType, currentType;
- public String name;
- public MethodHandle handle;
- public boolean useMetaClass = false, cache = true;
- public MutableCallSite callSite;
- public Class<?> sender;
- public boolean isVargs;
- public boolean safeNavigation, safeNavigationOrig, spread;
- public boolean skipSpreadCollector;
- public boolean thisCall;
- public Class<?> selectionBase;
- public boolean catchException = true;
- public CallType callType;
-
- /**
- * Cache values for read-only access
- */
- private static final CallType[] CALL_TYPE_VALUES = CallType.values();
-
- /**
- * Returns the Selector
- */
- public static Selector getSelector(MutableCallSite callSite, Class<?> sender, String methodName, int callID, boolean safeNavigation, boolean thisCall, boolean spreadCall, Object[] arguments) {
- CallType callType = CALL_TYPE_VALUES[callID];
- switch (callType) {
- case INIT:
- return new InitSelector(callSite, sender, methodName, callType, safeNavigation, thisCall, spreadCall, arguments);
- case METHOD:
- return new MethodSelector(callSite, sender, methodName, callType, safeNavigation, thisCall, spreadCall, arguments);
- case GET:
- return new PropertySelector(callSite, sender, methodName, callType, safeNavigation, thisCall, spreadCall, arguments);
- case SET:
- throw new GroovyBugError("your call tried to do a property set, which is not supported.");
- case CAST:
- return new CastSelector(callSite, arguments);
- default:
- throw new GroovyBugError("unexpected call type");
- }
- }
-
- abstract void setCallSiteTarget();
-
- /**
- * Helper method to transform the given arguments, consisting of the receiver
- * and the actual arguments in an Object[], into a new Object[] consisting
- * of the receiver and the arguments directly. Before the size of args was
- * always 2, the returned Object[] will have a size of 1+n, where n is the
- * number arguments.
- */
- private static Object[] spread(Object[] args, boolean spreadCall) {
- if (!spreadCall) return args;
- Object[] normalArguments = (Object[]) args[1];
- Object[] ret = new Object[normalArguments.length + 1];
- ret[0] = args[0];
- System.arraycopy(normalArguments, 0, ret, 1, ret.length - 1);
- return ret;
- }
-
- private static class CastSelector extends MethodSelector {
- private final Class<?> staticSourceType, staticTargetType;
-
- public CastSelector(MutableCallSite callSite, Object[] arguments) {
- super(callSite, Selector.class, "", CallType.CAST, false, false, false, arguments);
- this.staticSourceType = callSite.type().parameterType(0);
- this.staticTargetType = callSite.type().returnType();
- }
-
- @Override
- public void setCallSiteTarget() {
- // targetTypes String, Enum and Class are handled
- // by the compiler already
- // Boolean / boolean
- handleBoolean();
- handleNullWithoutBoolean();
-
- // !! from here on args[0] is always not null !!
- handleInstanceCase();
-
- // targetType is abstract Collection fitting for HashSet or ArrayList
- // and object is Collection or array
- handleCollections();
- handleSAM();
-
- // will handle :
- // * collection case where argument is an array
- // * array transformation (staticTargetType.isArray())
- // * constructor invocation
- // * final GroovyCastException
- castToTypeFallBack();
-
- if (!handle.type().equals(callSite.type())) castAndSetGuards();
- }
-
- private void castAndSetGuards() {
- handle = MethodHandles.explicitCastArguments(handle, targetType);
- setGuards(args[0]);
- doCallSiteTargetSet();
- }
-
- private void handleNullWithoutBoolean() {
- if (handle != null || args[0] != null) return;
-
- if (staticTargetType.isPrimitive()) {
- handle = MethodHandles.insertArguments(GROOVY_CAST_EXCEPTION, 1, staticTargetType);
- // need to call here here because we used the static target type
- // it won't be done otherwise because handle.type() == callSite.type()
- castAndSetGuards();
- } else {
- handle = MethodHandles.identity(staticSourceType);
- }
- }
-
- private void handleInstanceCase() {
- if (handle != null) return;
-
- if (staticTargetType.isAssignableFrom(args[0].getClass())) {
- handle = MethodHandles.identity(staticSourceType);
- }
- }
-
- private static boolean isAbstractClassOf(Class<?> toTest, Class<?> givenOnCallSite) {
- if (!toTest.isAssignableFrom(givenOnCallSite)) return false;
- if (givenOnCallSite.isInterface()) return true;
- return Modifier.isAbstract(givenOnCallSite.getModifiers());
- }
-
- private void handleCollections() {
- if (handle != null) return;
-
- if (!(args[0] instanceof Collection)) return;
- if (isAbstractClassOf(HashSet.class, staticTargetType)) {
- handle = HASHSET_CONSTRUCTOR;
- } else if (isAbstractClassOf(ArrayList.class, staticTargetType)) {
- handle = ARRAYLIST_CONSTRUCTOR;
- }
- }
-
- private void handleSAM() {
- if (handle != null) return;
-
- if (!(args[0] instanceof Closure)) return;
- Method m = CachedSAMClass.getSAMMethod(staticTargetType);
- if (m == null) return;
- //TODO: optimize: add guard based on type Closure
- handle = MethodHandles.insertArguments(SAM_CONVERSION, 1, m, staticTargetType);
- }
-
- private void castToTypeFallBack() {
- if (handle != null) return;
-
- // generic fallback to castToType
- handle = MethodHandles.insertArguments(DTT_CAST_TO_TYPE, 1, staticTargetType);
- }
-
- private void handleBoolean() {
- if (handle != null) return;
-
- // boolean->boolean, Boolean->boolean, boolean->Boolean
- // is handled by compiler
- // that leaves (T)Z and (T)Boolean, where T is the static type
- // but runtime type of T might be Boolean
-
- boolean primitive = staticTargetType == boolean.class;
- if (!primitive && staticTargetType != Boolean.class) return;
- if (args[0] == null) {
- if (primitive) {
- handle = MethodHandles.constant(boolean.class, false);
- handle = MethodHandles.dropArguments(handle, 0, staticSourceType);
- } else {
- handle = BOOLEAN_IDENTITY;
- }
- } else if (args[0] instanceof Boolean) {
- // give value through or unbox
- handle = BOOLEAN_IDENTITY;
- } else {
- //call asBoolean
- name = "asBoolean";
- super.setCallSiteTarget();
- }
- }
- }
-
- private static class PropertySelector extends MethodSelector {
- private boolean insertName = false;
-
- public PropertySelector(MutableCallSite callSite, Class<?> sender, String methodName, CallType callType, boolean safeNavigation, boolean thisCall, boolean spreadCall, Object[] arguments) {
- super(callSite, sender, methodName, callType, safeNavigation, thisCall, spreadCall, arguments);
- }
-
- /**
- * We never got the interceptor path with a property get
- */
- @Override
- public boolean setInterceptor() {
- return false;
- }
-
- /**
- * this method chooses a property from the meta class.
- */
- @Override
- public void chooseMeta(MetaClassImpl mci) {
- Object receiver = getCorrectedReceiver();
- if (receiver instanceof GroovyObject) {
- Class<?> aClass = receiver.getClass();
- try {
- Method reflectionMethod = aClass.getMethod("getProperty", String.class);
- if (!reflectionMethod.isSynthetic() && !isMarkedInternal(reflectionMethod)) {
- handle = MethodHandles.insertArguments(GROOVY_OBJECT_GET_PROPERTY, 1, name);
- return;
- }
- } catch (ReflectiveOperationException ignored) {
- }
- } else if (receiver instanceof Class) {
- handle = MOP_GET;
- handle = MethodHandles.insertArguments(handle, 2, name);
- handle = MethodHandles.insertArguments(handle, 0, this.mc);
- return;
- }
-
- if (method != null || mci == null) return;
- Class<?> chosenSender = this.sender;
- if (mci.getTheClass() != chosenSender && GroovyCategorySupport.hasCategoryInCurrentThread()) {
- chosenSender = mci.getTheClass();
- }
- MetaProperty res = mci.getEffectiveGetMetaProperty(chosenSender, receiver, name, false);
- if (res instanceof MethodMetaProperty) {
- MethodMetaProperty mmp = (MethodMetaProperty) res;
- method = mmp.getMetaMethod();
- insertName = true;
- } else if (res instanceof CachedField) {
- CachedField cf = (CachedField) res;
- Field f = cf.getCachedField();
- try {
- handle = LOOKUP.unreflectGetter(f);
- if (Modifier.isStatic(f.getModifiers())) {
- // normally we would do the following
- // handle = MethodHandles.dropArguments(handle,0,Class.class);
- // but because there is a bug in invokedynamic in all jdk7 versions
- // maybe use Unsafe.ensureClassInitialized
- handle = META_PROPERTY_GETTER.bindTo(res);
- }
- } catch (IllegalAccessException iae) {
- throw new GroovyBugError(iae);
- }
- } else {
- handle = META_PROPERTY_GETTER.bindTo(res);
- }
- }
-
- private boolean isMarkedInternal(Method reflectionMethod) {
- return reflectionMethod.getAnnotation(Internal.class) != null;
- }
-
- /**
- * Additionally to the normal {@link MethodSelector#setHandleForMetaMethod()}
- * task we have to also take care of generic getter methods, that depend
- * one the name.
- */
- @Override
- public void setHandleForMetaMethod() {
- if (handle != null) return;
- super.setHandleForMetaMethod();
- if (handle != null && insertName && handle.type().parameterCount() == 2) {
- handle = MethodHandles.insertArguments(handle, 1, name);
- }
- }
-
- /**
- * The MOP requires all get property operations to go through
- * {@link GroovyObject#getProperty(String)}. We do this in case
- * no property was found before.
- */
- @Override
- public void setMetaClassCallHandleIfNeeded(boolean standardMetaClass) {
- if (handle != null) return;
- useMetaClass = true;
- if (LOG_ENABLED) LOG.info("set meta class invocation path for property get.");
- handle = MethodHandles.insertArguments(MOP_GET, 2, this.name);
- handle = MethodHandles.insertArguments(handle, 0, mc);
- }
- }
-
- private static class InitSelector extends MethodSelector {
- private boolean beanConstructor;
-
- public InitSelector(MutableCallSite callSite, Class<?> sender, String methodName, CallType callType, boolean safeNavigation, boolean thisCall, boolean spreadCall, Object[] arguments) {
- super(callSite, sender, methodName, callType, safeNavigation, thisCall, spreadCall, arguments);
- }
-
- /**
- * Constructor calls are not intercepted, thus always returns false.
- */
- @Override
- public boolean setInterceptor() {
- return false;
- }
-
- /**
- * For a constructor call we always use the static meta class from the registry
- */
- @Override
- public MetaClass getMetaClass() {
- Object receiver = args[0];
- mc = GroovySystem.getMetaClassRegistry().getMetaClass((Class<?>) receiver);
- return mc;
- }
-
- /**
- * This method chooses a constructor from the meta class.
- */
- @Override
- public void chooseMeta(MetaClassImpl mci) {
- if (mci == null) return;
- if (LOG_ENABLED) LOG.info("getting constructor");
- Object[] newArgs = removeRealReceiver(args);
- method = mci.retrieveConstructor(newArgs);
- if (method instanceof MetaConstructor) {
- MetaConstructor mcon = (MetaConstructor) method;
- if (mcon.isBeanConstructor()) {
- if (LOG_ENABLED) LOG.info("do beans constructor");
- beanConstructor = true;
- }
- }
- }
-
- /**
- * Adds {@link MetaConstructor} handling.
- */
- @Override
- public void setHandleForMetaMethod() {
- if (method == null) return;
- if (method instanceof MetaConstructor) {
- if (LOG_ENABLED) LOG.info("meta method is MetaConstructor instance");
- MetaConstructor mc = (MetaConstructor) method;
- isVargs = mc.isVargsMethod();
- Constructor con = mc.getCachedConstrcutor().getCachedConstructor();
- try {
- handle = LOOKUP.unreflectConstructor(con);
- if (LOG_ENABLED) LOG.info("successfully unreflected constructor");
- } catch (IllegalAccessException e) {
- throw new GroovyBugError(e);
- }
- } else {
- super.setHandleForMetaMethod();
- }
- if (beanConstructor) {
- // we have handle that takes no arguments to create the bean,
- // we have to use its return value to call #setBeanProperties with it
- // and the meta class.
-
- // to do this we first bind the values to #setBeanProperties
- MethodHandle con = BEAN_CONSTRUCTOR_PROPERTY_SETTER.bindTo(mc);
- // inner class case
- MethodType foldTargetType = MethodType.methodType(Object.class);
- if (args.length == 3) {
- con = MethodHandles.dropArguments(con, 1, targetType.parameterType(1));
- foldTargetType = foldTargetType.insertParameterTypes(0, targetType.parameterType(1));
- }
- handle = MethodHandles.foldArguments(con, handle.asType(foldTargetType));
- }
- if (method instanceof MetaConstructor) {
- handle = MethodHandles.dropArguments(handle, 0, Class.class);
- }
- }
-
- /**
- * In case of a bean constructor we don't do any varags or implicit null argument
- * transformations. Otherwise we do the same as for {@link MethodSelector#correctParameterLength()}
- */
- @Override
- public void correctParameterLength() {
- if (beanConstructor) return;
- super.correctParameterLength();
- }
-
- /**
- * In case of a bean constructor we don't do any coercion, otherwise
- * we do the same as for {@link MethodSelector#correctCoerce()}
- */
- @Override
- public void correctCoerce() {
- if (beanConstructor) return;
- super.correctCoerce();
- }
-
- /**
- * Set MOP based constructor invocation path.
- */
- @Override
- public void setMetaClassCallHandleIfNeeded(boolean standardMetaClass) {
- if (handle != null) return;
- useMetaClass = true;
- if (LOG_ENABLED) LOG.info("set meta class invocation path");
- handle = MOP_INVOKE_CONSTRUCTOR.bindTo(mc);
- handle = handle.asCollector(Object[].class, targetType.parameterCount() - 1);
- handle = MethodHandles.dropArguments(handle, 0, Class.class);
- if (LOG_ENABLED) LOG.info("create collector for arguments");
- }
- }
-
- /**
- * Method invocation based {@link Selector}.
- * This Selector is called for method invocations and is base for cosntructor
- * calls as well as getProperty calls.
- */
- private static class MethodSelector extends Selector {
- private static final Object[] SINGLE_NULL_ARRAY = {null};
- protected MetaClass mc;
- private boolean isCategoryMethod;
-
- public MethodSelector(MutableCallSite callSite, Class<?> sender, String methodName, CallType callType, Boolean safeNavigation, Boolean thisCall, Boolean spreadCall, Object[] arguments) {
- this.callType = callType;
- this.targetType = callSite.type();
- this.name = methodName;
- this.originalArguments = arguments;
- this.args = spread(arguments, spreadCall);
- this.callSite = callSite;
- this.sender = sender;
- this.safeNavigationOrig = safeNavigation;
- this.safeNavigation = safeNavigation && arguments[0] == null;
- this.thisCall = thisCall;
- this.spread = spreadCall;
- this.cache = !spread;
-
- if (LOG_ENABLED) {
- StringBuilder msg =
- new StringBuilder("----------------------------------------------------" +
- "\n\t\tinvocation of method '" + methodName + "'" +
- "\n\t\tinvocation type: " + callType +
- "\n\t\tsender: " + sender +
- "\n\t\ttargetType: " + targetType +
- "\n\t\tsafe navigation: " + safeNavigation +
- "\n\t\tthisCall: " + thisCall +
- "\n\t\tspreadCall: " + spreadCall +
- "\n\t\twith " + arguments.length + " arguments");
- for (int i = 0; i < arguments.length; i++) {
- msg.append("\n\t\t\targument[").append(i).append("] = ");
- if (arguments[i] == null) {
- msg.append("null");
- } else {
- msg.append(arguments[i].getClass().getName()).append("@").append(Integer.toHexString(System.identityHashCode(arguments[i])));
- }
- }
- LOG.info(msg.toString());
- }
- }
-
- /**
- * Sets the null constant for safe navigation.
- * In case of foo?.bar() and foo being null, we don't call the method,
- * instead we simply return null. This produces a handle, which will
- * return the constant.
- */
- public boolean setNullForSafeNavigation() {
- if (!safeNavigation) return false;
- handle = MethodHandles.dropArguments(NULL_REF, 0, targetType.parameterArray());
- if (LOG_ENABLED) LOG.info("set null returning handle for safe navigation");
- return true;
- }
-
- /**
- * Gives the meta class to an Object.
- */
- public MetaClass getMetaClass() {
- Object receiver = args[0];
- if (receiver == null) {
- mc = NullObject.getNullObject().getMetaClass();
- } else if (receiver instanceof GroovyObject) {
- mc = ((GroovyObject) receiver).getMetaClass();
- } else if (receiver instanceof Class) {
- Class<?> c = (Class<?>) receiver;
- mc = GroovySystem.getMetaClassRegistry().getMetaClass(c);
- this.cache &= !ClassInfo.getClassInfo(c).hasPerInstanceMetaClasses();
- } else {
- mc = ((MetaClassRegistryImpl) GroovySystem.getMetaClassRegistry()).getMetaClass(receiver);
- this.cache &= !ClassInfo.getClassInfo(receiver.getClass()).hasPerInstanceMetaClasses();
- }
- mc.initialize();
-
- return mc;
- }
-
- /**
- * Uses the meta class to get a meta method for a method call.
- * There will be no meta method selected, if the meta class is no MetaClassImpl
- * or the meta class is an AdaptingMetaClass.
- */
- public void chooseMeta(MetaClassImpl mci) {
- if (mci == null) return;
- Object receiver = getCorrectedReceiver();
- Object[] newArgs = removeRealReceiver(args);
- if (receiver instanceof Class) {
- if (LOG_ENABLED) LOG.info("receiver is a class");
- if (!mci.hasCustomStaticInvokeMethod()) method = mci.retrieveStaticMethod(name, newArgs);
- } else {
- String changedName = name;
- if (receiver instanceof GeneratedClosure && changedName.equals("call")) {
- changedName = "doCall";
- }
- if (!mci.hasCustomInvokeMethod())
- method = mci.getMethodWithCaching(selectionBase, changedName, newArgs, false);
- }
- if (LOG_ENABLED) LOG.info("retrieved method from meta class: " + method);
- }
-
- /**
- * Creates a MethodHandle using a before selected MetaMethod.
- * If the MetaMethod has reflective information available, then
- * we will use that information to create the target MethodHandle.
- * If that is not the case we will produce a handle, which will use the
- * MetaMethod itself for invocation.
- */
- public void setHandleForMetaMethod() {
- MetaMethod metaMethod = method;
- isCategoryMethod = method instanceof CategoryMethod;
-
- if (metaMethod instanceof NumberNumberMetaMethod
- || (method instanceof GeneratedMetaMethod && (name.equals("next") || name.equals("previous")))) {
- if (LOG_ENABLED) LOG.info("meta method is number method");
- if (IndyMath.chooseMathMethod(this, metaMethod)) {
- catchException = false;
- if (LOG_ENABLED) LOG.info("indy math successful");
- return;
- }
- }
-
- boolean isCategoryTypeMethod = metaMethod instanceof NewInstanceMetaMethod;
- if (LOG_ENABLED) LOG.info("meta method is category type method: " + isCategoryTypeMethod);
- boolean isStaticCategoryTypeMethod = metaMethod instanceof NewStaticMetaMethod;
- if (LOG_ENABLED) LOG.info("meta method is static category type method: " + isCategoryTypeMethod);
-
- if (metaMethod instanceof ReflectionMetaMethod) {
- if (LOG_ENABLED) LOG.info("meta method is reflective method");
- ReflectionMetaMethod rmm = (ReflectionMetaMethod) metaMethod;
- metaMethod = rmm.getCachedMethod();
- }
-
- if (metaMethod instanceof CachedMethod) {
- if (LOG_ENABLED) LOG.info("meta method is CachedMethod instance");
- CachedMethod cm = (CachedMethod) metaMethod;
- cm = (CachedMethod) VMPluginFactory.getPlugin().transformMetaMethod(getMetaClass(), cm);
- isVargs = cm.isVargsMethod();
- try {
- Method m = cm.getCachedMethod();
- handle = correctClassForNameAndUnReflectOtherwise(m);
- if (LOG_ENABLED) LOG.info("successfully unreflected method");
- if (isStaticCategoryTypeMethod) {
- handle = MethodHandles.insertArguments(handle, 0, new Object[]{null});
- handle = MethodHandles.dropArguments(handle, 0, targetType.parameterType(0));
- } else if (!isCategoryTypeMethod && isStatic(m)) {
- // we drop the receiver, which might be a Class (invocation on Class)
- // or it might be an object (static method invocation on instance)
- // Object.class handles both cases at once
- handle = MethodHandles.dropArguments(handle, 0, Object.class);
- }
- } catch (IllegalAccessException e) {
- throw new GroovyBugError(e);
- }
- } else if (method != null) {
- if (LOG_ENABLED) LOG.info("meta method is dgm helper");
- // generic meta method invocation path
- handle = META_METHOD_INVOKER;
- handle = handle.bindTo(method);
- if (spread) {
- args = originalArguments;
- skipSpreadCollector = true;
- } else {
- // wrap arguments from call site in Object[]
- handle = handle.asCollector(Object[].class, targetType.parameterCount() - 1);
- }
- currentType = removeWrapper(targetType);
- if (LOG_ENABLED) LOG.info("bound method name to META_METHOD_INVOKER");
- }
- }
-
- private MethodHandle correctClassForNameAndUnReflectOtherwise(Method m) throws IllegalAccessException {
- if (m.getDeclaringClass() == Class.class && m.getName().equals("forName") && m.getParameterTypes().length == 1) {
- return MethodHandles.insertArguments(CLASS_FOR_NAME, 1, true, sender.getClassLoader());
- } else {
- return LOOKUP.unreflect(m);
- }
- }
-
- /**
- * Helper method to manipulate the given type to replace Wrapper with Object.
- */
- private MethodType removeWrapper(MethodType targetType) {
- Class<?>[] types = targetType.parameterArray();
- for (int i = 0; i < types.length; i++) {
- if (types[i] == Wrapper.class) {
- targetType = targetType.changeParameterType(i, Object.class);
- }
- }
- return targetType;
- }
-
- /**
- * Creates a MethodHandle, which will use the meta class path.
- * This method is called only if no handle has been created before. This
- * is usually the case if the method selection failed.
- */
- public void setMetaClassCallHandleIfNeeded(boolean standardMetaClass) {
- if (handle != null) return;
- useMetaClass = true;
- if (LOG_ENABLED) LOG.info("set meta class invocation path");
- Object receiver = getCorrectedReceiver();
- if (receiver instanceof Class) {
- handle = META_CLASS_INVOKE_STATIC_METHOD.bindTo(mc);
- if (LOG_ENABLED) LOG.info("use invokeStaticMethod with bound meta class");
- } else {
- handle = MOP_INVOKE_METHOD.bindTo(mc);
- if (LOG_ENABLED) LOG.info("use invokeMethod with bound meta class");
-
- if (receiver instanceof GroovyObject) {
- // if the meta class call fails we may still want to fall back to call
- // GroovyObject#invokeMethod if the receiver is a GroovyObject
- if (LOG_ENABLED) LOG.info("add MissingMethod handler for GrooObject#invokeMethod fallback path");
- handle = MethodHandles.catchException(handle, MissingMethodException.class, GROOVY_OBJECT_INVOKER);
- }
- }
- handle = MethodHandles.insertArguments(handle, 1, name);
- if (!spread) handle = handle.asCollector(Object[].class, targetType.parameterCount() - 1);
- if (LOG_ENABLED) LOG.info("bind method name and create collector for arguments");
- }
-
- /**
- * Corrects method argument wrapping.
- * In cases in which we want to force a certain method selection
- * we use Wrapper classes to transport the static type information.
- * This method will be used to undo the wrapping.
- */
- public void correctWrapping() {
- if (useMetaClass) return;
- Class<?>[] pt = handle.type().parameterArray();
- if (currentType != null) pt = currentType.parameterArray();
- for (int i = 1; i < args.length; i++) {
- if (args[i] instanceof Wrapper) {
- Class<?> type = pt[i];
- MethodType mt = MethodType.methodType(type, Wrapper.class);
- handle = MethodHandles.filterArguments(handle, i, UNWRAP_METHOD.asType(mt));
- if (LOG_ENABLED) LOG.info("added filter for Wrapper for argument at pos " + i);
- }
- }
- }
-
- /**
- * Handles cases in which we have to correct the length of arguments
- * using the parameters. This might be needed for vargs and for one
- * parameter calls without arguments (null is used then).
- */
- public void correctParameterLength() {
- if (handle == null) return;
-
- Class<?>[] params = handle.type().parameterArray();
- if (currentType != null) params = currentType.parameterArray();
- if (!isVargs) {
- if (spread && useMetaClass) return;
- if (params.length == 2 && args.length == 1) {
- handle = MethodHandles.insertArguments(handle, 1, SINGLE_NULL_ARRAY);
- }
- return;
- }
-
- Class<?> lastParam = params[params.length - 1];
- Object lastArg = unwrapIfWrapped(args[args.length - 1]);
- if (params.length == args.length) {
- // may need rewrap
- if (lastArg == null) return;
- if (lastParam.isInstance(lastArg)) return;
- if (lastArg.getClass().isArray()) return;
- // arg is not null and not assignment compatible
- // so we really need to rewrap
- handle = handle.asCollector(lastParam, 1);
- } else if (params.length > args.length) {
- // we depend on the method selection having done a good
- // job before already, so the only case for this here is, that
- // we have no argument for the array, meaning params.length is
- // args.length+1. In that case we have to fill in an empty array
- handle = MethodHandles.insertArguments(handle, params.length - 1, Array.newInstance(lastParam.getComponentType(), 0));
- if (LOG_ENABLED) LOG.info("added empty array for missing vargs part");
- } else { //params.length < args.length
- // we depend on the method selection having done a good
- // job before already, so the only case for this here is, that
- // all trailing arguments belong into the vargs array
- handle = handle.asCollector(
- lastParam,
- args.length - params.length + 1);
- if (LOG_ENABLED) LOG.info("changed surplus arguments to be collected for vargs call");
- }
- }
-
- /**
- * There are some conversions we have to do explicitly.
- * These are GString to String, Number to Byte and Number to BigInteger
- * conversions.
- */
- public void correctCoerce() {
- if (useMetaClass) return;
-
- Class<?>[] parameters = handle.type().parameterArray();
- if (currentType != null) parameters = currentType.parameterArray();
- if (args.length != parameters.length) {
- throw new GroovyBugError("At this point argument array length and parameter array length should be the same");
- }
- for (int i = 0; i < args.length; i++) {
- if (parameters[i] == Object.class) continue;
- Object arg = unwrapIfWrapped(args[i]);
- // we have to handle here different cases in which we do no
- // transformations. We depend on our method selection to have
- // selected only a compatible method, that means for a null
- // argument we don't have to do anything. Same of course is if
- // the argument is an instance of the parameter type. We also
- // exclude boxing, since the MethodHandles will do that part
- // already for us. Another case is the conversion of a primitive
- // to another primitive or of the wrappers, or a combination of
- // these. This is also handled already. What is left is the
- // GString conversion and the number conversions.
-
- if (arg == null) continue;
- Class<?> got = arg.getClass();
-
- // equal class, nothing to do
- if (got == parameters[i]) continue;
-
- Class<?> wrappedPara = TypeHelper.getWrapperClass(parameters[i]);
- // equal class with one maybe a primitive, the later explicitCastArguments will solve this case
- if (wrappedPara == TypeHelper.getWrapperClass(got)) continue;
-
- // equal in terms of an assignment in Java. That means according to Java widening rules, or
- // a subclass, interface, superclass relation, this case then handles also
- // primitive to primitive conversion. Those case are also solved by explicitCastArguments.
- if (parameters[i].isAssignableFrom(got)) continue;
-
- // to aid explicitCastArguments we convert to the wrapper type to let is only unbox
- handle = TypeTransformers.addTransformer(handle, i, arg, wrappedPara);
- if (LOG_ENABLED)
- LOG.info("added transformer at pos " + i + " for type " + got + " to type " + wrappedPara);
- }
- }
-
- /**
- * Gives a replacement receiver for null.
- * In case of the receiver being null we want to do the method
- * invocation on NullObject instead.
- */
- public void correctNullReceiver() {
- if (args[0] != null) return;
- handle = handle.bindTo(NullObject.getNullObject());
- handle = MethodHandles.dropArguments(handle, 0, targetType.parameterType(0));
- if (LOG_ENABLED) LOG.info("binding null object receiver and dropping old receiver");
- }
-
- public void correctSpreading() {
- if (!spread || useMetaClass || skipSpreadCollector) return;
- handle = handle.asSpreader(Object[].class, args.length - 1);
- }
-
- /**
- * Adds the standard exception handler.
- */
- public void addExceptionHandler() {
- //TODO: if we would know exactly which paths require the exceptions
- // and which paths not, we can sometimes save this guard
- if (handle == null || !catchException) return;
- Class<?> returnType = handle.type().returnType();
- if (returnType != Object.class) {
- MethodType mtype = MethodType.methodType(returnType, GroovyRuntimeException.class);
- handle = MethodHandles.catchException(handle, GroovyRuntimeException.class, UNWRAP_EXCEPTION.asType(mtype));
- } else {
- handle = MethodHandles.catchException(handle, GroovyRuntimeException.class, UNWRAP_EXCEPTION);
- }
- if (LOG_ENABLED) LOG.info("added GroovyRuntimeException unwrapper");
- }
-
- /**
- * Sets all argument and receiver guards.
- */
- public void setGuards(Object receiver) {
- if (handle == null) return;
- if (!cache) return;
-
- MethodHandle fallback;
- if (callSite instanceof CacheableCallSite) {
- fallback = ((CacheableCallSite) callSite).getFallbackTarget();
- } else {
- throw new GroovyBugError("CacheableCallSite is expected, but the actual callsite is: " + callSite);
- }
-
- // special guards for receiver
- if (receiver instanceof GroovyObject) {
- GroovyObject go = (GroovyObject) receiver;
- MetaClass mc = go.getMetaClass();
- MethodHandle test = SAME_MC.bindTo(mc);
- // drop dummy receiver
- test = test.asType(MethodType.methodType(boolean.class, targetType.parameterType(0)));
- handle = MethodHandles.guardWithTest(test, handle, fallback);
- if (LOG_ENABLED) LOG.info("added meta class equality check");
- } else if (receiver instanceof Class) {
- MethodHandle test = EQUALS.bindTo(receiver);
- test = test.asType(MethodType.methodType(boolean.class, targetType.parameterType(0)));
- handle = MethodHandles.guardWithTest(test, handle, fallback);
- if (LOG_ENABLED) LOG.info("added class equality check");
- }
-
- if (!useMetaClass && isCategoryMethod) {
- // category method needs Thread check
- // cases:
- // (1) method is a category method
- // We need to check if the category in the current thread is still active.
- // Since we invalidate on leaving the category checking for it being
- // active directly is good enough.
- // (2) method is in use scope, but not from category
- // Since entering/leaving a category will invalidate, there is no need for any special check
- // (3) method is not in use scope /and not from category
- // Since entering/leaving a category will invalidate, there is no need for any special check
- if (method instanceof NewInstanceMetaMethod) {
- handle = MethodHandles.guardWithTest(HAS_CATEGORY_IN_CURRENT_THREAD_GUARD, handle, fallback);
- if (LOG_ENABLED) LOG.info("added category-in-current-thread-guard for category method");
- }
- }
-
- // handle constant meta class and category changes
- handle = switchPoint.guardWithTest(handle, fallback);
- if (LOG_ENABLED) LOG.info("added switch point guard");
-
- // guards for receiver and parameter
- Class<?>[] pt = handle.type().parameterArray();
- for (int i = 0; i < args.length; i++) {
- Object arg = args[i];
- MethodHandle test;
- if (arg == null) {
- test = IS_NULL.asType(MethodType.methodType(boolean.class, pt[i]));
- if (LOG_ENABLED) LOG.info("added null argument check at pos " + i);
- } else {
- Class<?> argClass = arg.getClass();
- if (pt[i].isPrimitive()) continue;
- //if (Modifier.isFinal(argClass.getModifiers()) && TypeHelper.argumentClassIsParameterClass(argClass,pt[i])) continue;
- test = SAME_CLASS.
- bindTo(argClass).
- asType(MethodType.methodType(boolean.class, pt[i]));
- if (LOG_ENABLED) LOG.info("added same class check at pos " + i);
- }
- Class<?>[] drops = new Class[i];
- System.arraycopy(pt, 0, drops, 0, drops.length);
- test = MethodHandles.dropArguments(test, 0, drops);
- handle = MethodHandles.guardWithTest(test, handle, fallback);
- }
- }
-
- /**
- * do the actual call site target set, if the call is supposed to be cached
- */
- public void doCallSiteTargetSet() {
- if (LOG_ENABLED) LOG.info("call site stays uncached");
- /*
- if (!cache) {
- if (LOG_ENABLED) LOG.info("call site stays uncached");
- } else {
- callSite.setTarget(handle);
- if (LOG_ENABLED) LOG.info("call site target set, preparing outside invocation");
- }
- */
- }
-
- /**
- * Sets the selection base.
- */
- public void setSelectionBase() {
- if (thisCall) {
- selectionBase = sender;
- } else if (args[0] == null) {
- selectionBase = NullObject.class;
- } else {
- selectionBase = mc.getTheClass();
- }
- if (LOG_ENABLED) LOG.info("selection base set to " + selectionBase);
- }
-
- /**
- * Sets a handle to call {@link GroovyInterceptable#invokeMethod(String, Object)}
- */
- public boolean setInterceptor() {
- if (!(this.args[0] instanceof GroovyInterceptable)) return false;
- handle = MethodHandles.insertArguments(INTERCEPTABLE_INVOKER, 1, this.name);
- handle = handle.asCollector(Object[].class, targetType.parameterCount() - 1);
- handle = handle.asType(targetType);
- return true;
- }
-
- /**
- * setting a call site target consists of the following steps:
- * # get the meta class
- * # select a method/constructor/property from it, if it is a MetaClassImpl
- * # make a handle out of the selection
- * # if nothing could be selected select a path through the given MetaClass or the GroovyObject
- * # apply transformations for vargs, implicit null argument, coercion, wrapping, null receiver and spreading
- */
- @Override
- public void setCallSiteTarget() {
- if (!setNullForSafeNavigation() && !setInterceptor()) {
- getMetaClass();
- if (LOG_ENABLED) LOG.info("meta class is " + mc);
- setSelectionBase();
- MetaClassImpl mci = getMetaClassImpl(mc, callType != CallType.GET);
- chooseMeta(mci);
- setHandleForMetaMethod();
- setMetaClassCallHandleIfNeeded(mci != null);
- correctParameterLength();
- correctCoerce();
- correctWrapping();
- correctNullReceiver();
- correctSpreading();
-
- if (LOG_ENABLED) LOG.info("casting explicit from " + handle.type() + " to " + targetType);
- handle = MethodHandles.explicitCastArguments(handle, targetType);
-
- addExceptionHandler();
- }
- setGuards(args[0]);
- doCallSiteTargetSet();
- }
- }
-
- /**
- * Unwraps the given object from a {@link Wrapper}. If not
- * wrapped, the given object is returned.
- */
- private static Object unwrapIfWrapped(Object object) {
- if (object instanceof Wrapper) return unwrap(object);
- return object;
- }
-
- /**
- * Returns {@link NullObject#getNullObject()} if the receiver
- * (args[0]) is null. If it is not null, the recevier itself
- * is returned.
- */
- public Object getCorrectedReceiver() {
- Object receiver = args[0];
- if (receiver == null) {
- if (LOG_ENABLED) LOG.info("receiver is null");
- receiver = NullObject.getNullObject();
- }
- return receiver;
- }
-
- /**
- * Returns if a method is static
- */
- private static boolean isStatic(Method m) {
- int mods = m.getModifiers();
- return (mods & Modifier.STATIC) != 0;
- }
-
- /**
- * Returns the MetaClassImpl if the given MetaClass is one of
- * MetaClassImpl, AdaptingMetaClass or ClosureMetaClass. If
- * none of these cases matches, this method returns null.
- */
- private static MetaClassImpl getMetaClassImpl(MetaClass mc, boolean includeEMC) {
- Class<?> mcc = mc.getClass();
- boolean valid = mcc == MetaClassImpl.class ||
- mcc == AdaptingMetaClass.class ||
- mcc == ClosureMetaClass.class ||
- (includeEMC && mcc == ExpandoMetaClass.class);
- if (!valid) {
- if (LOG_ENABLED)
- LOG.info("meta class is neither MetaClassImpl, nor AdoptingMetaClass, nor ClosureMetaClass, normal method selection path disabled.");
- return null;
- }
- if (LOG_ENABLED) LOG.info("meta class is a recognized MetaClassImpl");
- return (MetaClassImpl) mc;
- }
-
- /**
- * Helper method to remove the receiver from the argument array
- * by producing a new array.
- */
- private static Object[] removeRealReceiver(Object[] args) {
- Object[] ar = new Object[args.length - 1];
- System.arraycopy(args, 1, ar, 0, args.length - 1);
- return ar;
- }
-}
diff --git a/src/main/java/org/codehaus/groovy/vmplugin/v7/TypeHelper.java b/src/main/java/org/codehaus/groovy/vmplugin/v7/TypeHelper.java
deleted file mode 100644
index 266e72b..0000000
--- a/src/main/java/org/codehaus/groovy/vmplugin/v7/TypeHelper.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.codehaus.groovy.vmplugin.v7;
-
-
-import java.lang.invoke.MethodType;
-import java.math.BigDecimal;
-import java.math.BigInteger;
-
-/**
- * This class contains helper methods for converting and comparing types.
- * WARNING: This class is for internal use only. do not use it outside of its
- * package and not outside groovy-core.
- */
-@Deprecated
-public class TypeHelper {
- /**
- * Get wrapper class for a given class.
- * If the class is for a primitive number type, then the wrapper class
- * will be returned. If it is no primitive number type, we return the
- * class itself.
- */
- protected static Class<?> getWrapperClass(Class<?> c) {
- if (c == Integer.TYPE) {
- c = Integer.class;
- } else if (c == Byte.TYPE) {
- c = Byte.class;
- } else if (c == Long.TYPE) {
- c = Long.class;
- } else if (c == Double.TYPE) {
- c = Double.class;
- } else if (c == Float.TYPE) {
- c = Float.class;
- } else if (c == Boolean.TYPE) {
- c = Boolean.class;
- } else if (c == Character.TYPE) {
- c = Character.class;
- } else if (c == Short.TYPE) {
- c = Short.class;
- }
- return c;
- }
-
- /**
- * Realizes an unsharp equal for the class.
- * In general we return true if the provided arguments are the same. But
- * we will also return true if our argument class is a wrapper for
- * the parameter class. For example the parameter is an int and the
- * argument class is a wrapper.
- */
- protected static boolean argumentClassIsParameterClass(Class<?> argumentClass, Class<?> parameterClass) {
- if (argumentClass == parameterClass) return true;
- return getWrapperClass(parameterClass) == argumentClass;
- }
-
- /**
- * Replaces the types in the callSiteType parameter if more specific types
- * given through the arguments. This is in general the case, unless
- * the argument is null.
- */
- protected static MethodType replaceWithMoreSpecificType(Object[] args, MethodType callSiteType) {
- for (int i = 0; i < args.length; i++) {
- // if argument null, take the static type
- if (args[i] == null) continue;
- if (callSiteType.parameterType(i).isPrimitive()) continue;
- Class<?> argClass = args[i].getClass();
- callSiteType = callSiteType.changeParameterType(i, argClass);
- }
- return callSiteType;
- }
-
- protected static boolean isIntCategory(Class<?> x) {
- return x == Integer.class || x == int.class ||
- x == Byte.class || x == byte.class ||
- x == Short.class || x == short.class;
- }
-
- protected static boolean isLongCategory(Class<?> x) {
- return x == Long.class || x == long.class ||
- isIntCategory(x);
- }
-
- private static boolean isBigIntCategory(Class<?> x) {
- return x == BigInteger.class || isLongCategory(x);
- }
-
- protected static boolean isBigDecCategory(Class<?> x) {
- return x == BigDecimal.class || isBigIntCategory(x);
- }
-
- protected static boolean isDoubleCategory(Class<?> x) {
- return x == Float.class || x == float.class ||
- x == Double.class || x == double.class ||
- isBigDecCategory(x);
- }
-}
diff --git a/src/main/java/org/codehaus/groovy/vmplugin/v7/TypeTransformers.java b/src/main/java/org/codehaus/groovy/vmplugin/v7/TypeTransformers.java
deleted file mode 100644
index 823902c..0000000
--- a/src/main/java/org/codehaus/groovy/vmplugin/v7/TypeTransformers.java
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.codehaus.groovy.vmplugin.v7;
-
-import groovy.lang.Closure;
-import groovy.lang.GString;
-import groovy.lang.GroovyObject;
-import groovy.util.ProxyGenerator;
-import org.codehaus.groovy.GroovyBugError;
-import org.codehaus.groovy.reflection.stdclasses.CachedSAMClass;
-import org.codehaus.groovy.runtime.ConvertedClosure;
-import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation;
-import org.codehaus.groovy.transform.trait.Traits;
-
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodHandles;
-import java.lang.invoke.MethodType;
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-
-/**
- * This class contains several transformers for used during method invocation.
- */
-@Deprecated
-public class TypeTransformers {
- private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
- private static final MethodHandle
- TO_STRING, TO_BYTE, TO_INT, TO_LONG, TO_SHORT,
- TO_FLOAT, TO_DOUBLE, TO_BIG_INT, AS_ARRAY,
- TO_REFLECTIVE_PROXY, TO_GENERATED_PROXY, TO_SAMTRAIT_PROXY,
- DOUBLE_TO_BIG_DEC, DOUBLE_TO_BIG_DEC_WITH_CONVERSION, LONG_TO_BIG_DEC, BIG_INT_TO_BIG_DEC;
-
- static {
- try {
- TO_STRING = LOOKUP.findVirtual(Object.class, "toString", MethodType.methodType(String.class));
- TO_BYTE = LOOKUP.findVirtual(Number.class, "byteValue", MethodType.methodType(Byte.TYPE));
- TO_SHORT = LOOKUP.findVirtual(Number.class, "shortValue", MethodType.methodType(Short.TYPE));
- TO_INT = LOOKUP.findVirtual(Number.class, "intValue", MethodType.methodType(Integer.TYPE));
- TO_LONG = LOOKUP.findVirtual(Number.class, "longValue", MethodType.methodType(Long.TYPE));
- TO_FLOAT = LOOKUP.findVirtual(Number.class, "floatValue", MethodType.methodType(Float.TYPE));
- TO_DOUBLE = LOOKUP.findVirtual(Number.class, "doubleValue", MethodType.methodType(Double.TYPE));
-
- // BigDecimal conversion is done by using the double value
- DOUBLE_TO_BIG_DEC = LOOKUP.findConstructor(BigDecimal.class, MethodType.methodType(Void.TYPE, Double.TYPE));
- DOUBLE_TO_BIG_DEC_WITH_CONVERSION = MethodHandles.filterReturnValue(TO_DOUBLE, DOUBLE_TO_BIG_DEC);
-
- // BigDecimal conversion is done by using the double value
- LONG_TO_BIG_DEC = LOOKUP.findConstructor(BigDecimal.class, MethodType.methodType(Void.TYPE, Long.TYPE));
-
- // BigDecimal conversion is done by using the double value
- BIG_INT_TO_BIG_DEC = LOOKUP.findConstructor(BigDecimal.class, MethodType.methodType(Void.TYPE, BigInteger.class));
-
-
- // BigInteger conversion is done by using the string representation
- MethodHandle tmp = LOOKUP.findConstructor(BigInteger.class, MethodType.methodType(Void.TYPE, String.class));
- TO_BIG_INT = MethodHandles.filterReturnValue(TO_STRING, tmp);
-
- // generic array to array conversion
- AS_ARRAY = LOOKUP.findStatic(DefaultTypeTransformation.class, "asArray", MethodType.methodType(Object.class, Object.class, Class.class));
-
- // reflective proxy generation, since we need a ConvertedClosure but have only a normal Closure, we need to create that wrapper object as well
- MethodHandle newProxyInstance = LOOKUP.findStatic(Proxy.class, "newProxyInstance",
- MethodType.methodType(Object.class, ClassLoader.class, Class[].class, InvocationHandler.class));
- MethodHandle newConvertedClosure = LOOKUP.findConstructor(ConvertedClosure.class, MethodType.methodType(Void.TYPE, Closure.class, String.class));
- // prepare target newProxyInstance for fold to drop additional arguments needed by newConvertedClosure
- MethodType newOrder = newProxyInstance.type().dropParameterTypes(2, 3);
- newOrder = newOrder.insertParameterTypes(0, InvocationHandler.class, Closure.class, String.class);
- tmp = MethodHandles.permuteArguments(newProxyInstance, newOrder, 3, 4, 0);
- // execute fold:
- TO_REFLECTIVE_PROXY = MethodHandles.foldArguments(tmp, newConvertedClosure.asType(newConvertedClosure.type().changeReturnType(InvocationHandler.class)));
-
- {
- // generated proxy using a map to store the closure
- MethodHandle map = LOOKUP.findStatic(Collections.class, "singletonMap",
- MethodType.methodType(Map.class, Object.class, Object.class));
- newProxyInstance = LOOKUP.findVirtual(ProxyGenerator.class, "instantiateAggregateFromBaseClass",
- MethodType.methodType(GroovyObject.class, Map.class, Class.class));
- newOrder = newProxyInstance.type().dropParameterTypes(1, 2);
- newOrder = newOrder.insertParameterTypes(0, Map.class, Object.class, Object.class);
- tmp = MethodHandles.permuteArguments(newProxyInstance, newOrder, 3, 0, 4);
- tmp = MethodHandles.foldArguments(tmp, map);
- TO_GENERATED_PROXY = tmp;
- }
- {
- // Trait SAM coercion generated proxy using a map to store the closure
- MethodHandle map = LOOKUP.findStatic(Collections.class, "singletonMap",
- MethodType.methodType(Map.class, Object.class, Object.class));
- newProxyInstance = LOOKUP.findVirtual(ProxyGenerator.class, "instantiateAggregate",
- MethodType.methodType(GroovyObject.class, Map.class, List.class));
- newOrder = newProxyInstance.type().dropParameterTypes(1, 2);
- newOrder = newOrder.insertParameterTypes(0, Map.class, Object.class, Object.class);
- tmp = MethodHandles.permuteArguments(newProxyInstance, newOrder, 3, 0, 4);
- tmp = MethodHandles.foldArguments(tmp, map);
- TO_SAMTRAIT_PROXY = tmp;
- }
- } catch (Exception e) {
- throw new GroovyBugError(e);
- }
- }
-
- /**
- * Adds a type transformer applied at runtime.
- * This method handles transformations to String from GString,
- * array transformations and number based transformations
- */
- protected static MethodHandle addTransformer(MethodHandle handle, int pos, Object arg, Class<?> parameter) {
- MethodHandle transformer = null;
- if (arg instanceof GString) {
- transformer = TO_STRING;
- } else if (arg instanceof Closure) {
- transformer = createSAMTransform(arg, parameter);
- } else if (Number.class.isAssignableFrom(parameter)) {
- transformer = selectNumberTransformer(parameter, arg);
- } else if (parameter.isArray()) {
- transformer = MethodHandles.insertArguments(AS_ARRAY, 1, parameter);
- }
- if (transformer == null)
- throw new GroovyBugError("Unknown transformation for argument " + arg + " at position " + pos + " with " + arg.getClass() + " for parameter of type " + parameter);
- return applyUnsharpFilter(handle, pos, transformer);
- }
-
- /**
- * creates a method handle able to transform the given Closure into a SAM type
- * if the given parameter is a SAM type
- */
- private static MethodHandle createSAMTransform(Object arg, Class<?> parameter) {
- Method method = CachedSAMClass.getSAMMethod(parameter);
- if (method == null) return null;
- // TODO: have to think about how to optimize this!
- if (parameter.isInterface()) {
- if (Traits.isTrait(parameter)) {
- // the following code will basically do this:
- // Map<String,Closure> impl = Collections.singletonMap(method.getName(),arg);
- // return ProxyGenerator.INSTANCE.instantiateAggregate(impl,Collections.singletonList(clazz));
- // TO_SAMTRAIT_PROXY is a handle (Object,Object,ProxyGenerator,Class)GroovyObject
- // where the second object is the input closure, everything else
- // needs to be provide and is in remaining order: method name,
- // ProxyGenerator.INSTANCE and singletonList(parameter)
- MethodHandle ret = TO_SAMTRAIT_PROXY;
- ret = MethodHandles.insertArguments(ret, 2, ProxyGenerator.INSTANCE, Collections.singletonList(parameter));
- ret = MethodHandles.insertArguments(ret, 0, method.getName());
- return ret;
- }
- // the following code will basically do this:
- // return Proxy.newProxyInstance(
- // arg.getClass().getClassLoader(),
- // new Class[]{parameter},
- // new ConvertedClosure((Closure) arg));
- // TO_REFLECTIVE_PROXY will do that for us, though
- // input is the closure, the method name, the class loader and the
- // class[]. All of that but the closure must be provided here
- MethodHandle ret = TO_REFLECTIVE_PROXY;
- ret = MethodHandles.insertArguments(ret, 1,
- method.getName(),
- arg.getClass().getClassLoader(),
- new Class[]{parameter});
- return ret;
- } else {
- // the following code will basically do this:
- //Map<String, Object> m = Collections.singletonMap(method.getName(), arg);
- //return ProxyGenerator.INSTANCE.
- // instantiateAggregateFromBaseClass(m, parameter);
- // TO_GENERATED_PROXY is a handle (Object,Object,ProxyGenerator,Class)GroovyObject
- // where the second object is the input closure, everything else
- // needs to be provide and is in remaining order: method name,
- // ProxyGenerator.INSTANCE and parameter
- MethodHandle ret = TO_GENERATED_PROXY;
- ret = MethodHandles.insertArguments(ret, 2, ProxyGenerator.INSTANCE, parameter);
- ret = MethodHandles.insertArguments(ret, 0, method.getName());
- return ret;
- }
- }
-
- /**
- * Apply a transformer as filter.
- * The filter may not match exactly in the types. In this case needed
- * additional type transformations are done by {@link MethodHandle#asType(MethodType)}
- */
- public static MethodHandle applyUnsharpFilter(MethodHandle handle, int pos, MethodHandle transformer) {
- MethodType type = transformer.type();
- Class<?> given = handle.type().parameterType(pos);
- if (type.returnType() != given || type.parameterType(0) != given) {
- transformer = transformer.asType(MethodType.methodType(given, type.parameterType(0)));
- }
- return MethodHandles.filterArguments(handle, pos, transformer);
- }
-
- /**
- * returns a transformer later applied as filter to transform one
- * number into another
- */
- private static MethodHandle selectNumberTransformer(Class<?> param, Object arg) {
- param = TypeHelper.getWrapperClass(param);
-
- if (param == Byte.class) {
- return TO_BYTE;
- } else if (param == Character.class || param == Integer.class) {
- return TO_INT;
- } else if (param == Long.class) {
- return TO_LONG;
- } else if (param == Float.class) {
- return TO_FLOAT;
- } else if (param == Double.class) {
- return TO_DOUBLE;
- } else if (param == BigInteger.class) {
- return TO_BIG_INT;
- } else if (param == BigDecimal.class) {
- if (arg instanceof Double) {
- return DOUBLE_TO_BIG_DEC;
- } else if (arg instanceof Long) {
- return LONG_TO_BIG_DEC;
- } else if (arg instanceof BigInteger) {
- return BIG_INT_TO_BIG_DEC;
- } else {
- return DOUBLE_TO_BIG_DEC_WITH_CONVERSION;
- }
- } else if (param == Short.class) {
- return TO_SHORT;
- } else {
- return null;
- }
- }
-}