Search in sources :

Example 1 with NewMetaMethod

use of org.codehaus.groovy.runtime.metaclass.NewMetaMethod in project groovy by apache.

the class MetaClassImpl method replaceWithMOPCalls.

private void replaceWithMOPCalls(final CachedMethod[] mopMethods) {
    // no MOP methods if not a child of GroovyObject
    if (!isGroovyObject)
        return;
    class MOPIter extends MethodIndexAction {

        boolean useThis;

        @Override
        public boolean skipClass(Class clazz) {
            return !useThis && clazz == theClass;
        }

        @Override
        public void methodNameAction(Class clazz, MetaMethodIndex.Entry e) {
            if (useThis) {
                if (e.methods == null)
                    return;
                if (e.methods instanceof FastArray) {
                    FastArray methods = (FastArray) e.methods;
                    processFastArray(methods);
                } else {
                    MetaMethod method = (MetaMethod) e.methods;
                    if (method instanceof NewMetaMethod)
                        return;
                    if (useThis ^ Modifier.isPrivate(method.getModifiers()))
                        return;
                    String mopName = method.getMopName();
                    int index = Arrays.binarySearch(mopMethods, mopName, CachedClass.CachedMethodComparatorWithString.INSTANCE);
                    if (index >= 0) {
                        int from = index;
                        while (from > 0 && mopMethods[from - 1].getName().equals(mopName)) from--;
                        int to = index;
                        while (to < mopMethods.length - 1 && mopMethods[to + 1].getName().equals(mopName)) to++;
                        int matchingMethod = findMatchingMethod(mopMethods, from, to, method);
                        if (matchingMethod != -1) {
                            e.methods = mopMethods[matchingMethod];
                        }
                    }
                }
            } else {
                if (e.methodsForSuper == null)
                    return;
                if (e.methodsForSuper instanceof FastArray) {
                    FastArray methods = (FastArray) e.methodsForSuper;
                    processFastArray(methods);
                } else {
                    MetaMethod method = (MetaMethod) e.methodsForSuper;
                    if (method instanceof NewMetaMethod)
                        return;
                    if (useThis ^ Modifier.isPrivate(method.getModifiers()))
                        return;
                    String mopName = method.getMopName();
                    // GROOVY-4922: Due to a numbering scheme change, we must find the super$X$method which exists
                    // with the highest number. If we don't, no method may be found, leading to a stack overflow
                    String[] decomposedMopName = decomposeMopName(mopName);
                    int distance = Integer.parseInt(decomposedMopName[1]);
                    while (distance > 0) {
                        String fixedMopName = decomposedMopName[0] + distance + decomposedMopName[2];
                        int index = Arrays.binarySearch(mopMethods, fixedMopName, CachedClass.CachedMethodComparatorWithString.INSTANCE);
                        if (index >= 0) {
                            int from = index;
                            while (from > 0 && mopMethods[from - 1].getName().equals(fixedMopName)) from--;
                            int to = index;
                            while (to < mopMethods.length - 1 && mopMethods[to + 1].getName().equals(fixedMopName)) to++;
                            int matchingMethod = findMatchingMethod(mopMethods, from, to, method);
                            if (matchingMethod != -1) {
                                e.methodsForSuper = mopMethods[matchingMethod];
                                distance = 0;
                            }
                        }
                        distance--;
                    }
                }
            }
        }

        private String[] decomposeMopName(final String mopName) {
            int idx = mopName.indexOf("$");
            if (idx > 0) {
                int eidx = mopName.indexOf("$", idx + 1);
                if (eidx > 0) {
                    return new String[] { mopName.substring(0, idx + 1), mopName.substring(idx + 1, eidx), mopName.substring(eidx) };
                }
            }
            return new String[] { "", "0", mopName };
        }

        private void processFastArray(FastArray methods) {
            final int len = methods.size();
            final Object[] data = methods.getArray();
            for (int i = 0; i != len; ++i) {
                MetaMethod method = (MetaMethod) data[i];
                if (method instanceof NewMetaMethod)
                    continue;
                boolean isPrivate = Modifier.isPrivate(method.getModifiers());
                if (useThis ^ isPrivate)
                    continue;
                String mopName = method.getMopName();
                int index = Arrays.binarySearch(mopMethods, mopName, CachedClass.CachedMethodComparatorWithString.INSTANCE);
                if (index >= 0) {
                    int from = index;
                    while (from > 0 && mopMethods[from - 1].getName().equals(mopName)) from--;
                    int to = index;
                    while (to < mopMethods.length - 1 && mopMethods[to + 1].getName().equals(mopName)) to++;
                    int matchingMethod = findMatchingMethod(mopMethods, from, to, method);
                    if (matchingMethod != -1) {
                        methods.set(i, mopMethods[matchingMethod]);
                    }
                }
            }
        }
    }
    MOPIter iter = new MOPIter();
    // replace all calls for super with the correct MOP method
    iter.useThis = false;
    iter.iterate();
    // replace all calls for this with the correct MOP method
    iter.useThis = true;
    iter.iterate();
}
Also used : NewInstanceMetaMethod(org.codehaus.groovy.runtime.metaclass.NewInstanceMetaMethod) NewMetaMethod(org.codehaus.groovy.runtime.metaclass.NewMetaMethod) MixinInstanceMetaMethod(org.codehaus.groovy.runtime.metaclass.MixinInstanceMetaMethod) NewStaticMetaMethod(org.codehaus.groovy.runtime.metaclass.NewStaticMetaMethod) GeneratedMetaMethod(org.codehaus.groovy.reflection.GeneratedMetaMethod) ClosureMetaMethod(org.codehaus.groovy.runtime.metaclass.ClosureMetaMethod) TransformMetaMethod(org.codehaus.groovy.runtime.metaclass.TransformMetaMethod) FastArray(org.codehaus.groovy.util.FastArray) NewMetaMethod(org.codehaus.groovy.runtime.metaclass.NewMetaMethod) CachedClass(org.codehaus.groovy.reflection.CachedClass)

Example 2 with NewMetaMethod

use of org.codehaus.groovy.runtime.metaclass.NewMetaMethod in project groovy-core by groovy.

the class MetaClassImpl method replaceWithMOPCalls.

private void replaceWithMOPCalls(final CachedMethod[] mopMethods) {
    // no MOP methods if not a child of GroovyObject
    if (!isGroovyObject)
        return;
    class MOPIter extends MethodIndexAction {

        boolean useThis;

        public boolean skipClass(CachedClass clazz) {
            return !useThis && clazz == theCachedClass;
        }

        public void methodNameAction(Class clazz, MetaMethodIndex.Entry e) {
            if (useThis) {
                if (e.methods == null)
                    return;
                if (e.methods instanceof FastArray) {
                    FastArray methods = (FastArray) e.methods;
                    processFastArray(methods);
                } else {
                    MetaMethod method = (MetaMethod) e.methods;
                    if (method instanceof NewMetaMethod)
                        return;
                    if (useThis ^ Modifier.isPrivate(method.getModifiers()))
                        return;
                    String mopName = method.getMopName();
                    int index = Arrays.binarySearch(mopMethods, mopName, CachedClass.CachedMethodComparatorWithString.INSTANCE);
                    if (index >= 0) {
                        int from = index;
                        while (from > 0 && mopMethods[from - 1].getName().equals(mopName)) from--;
                        int to = index;
                        while (to < mopMethods.length - 1 && mopMethods[to + 1].getName().equals(mopName)) to++;
                        int matchingMethod = findMatchingMethod(mopMethods, from, to, method);
                        if (matchingMethod != -1) {
                            e.methods = mopMethods[matchingMethod];
                        }
                    }
                }
            } else {
                if (e.methodsForSuper == null)
                    return;
                if (e.methodsForSuper instanceof FastArray) {
                    FastArray methods = (FastArray) e.methodsForSuper;
                    processFastArray(methods);
                } else {
                    MetaMethod method = (MetaMethod) e.methodsForSuper;
                    if (method instanceof NewMetaMethod)
                        return;
                    if (useThis ^ Modifier.isPrivate(method.getModifiers()))
                        return;
                    String mopName = method.getMopName();
                    // GROOVY-4922: Due to a numbering scheme change, we must find the super$X$method which exists
                    // with the highest number. If we don't, no method may be found, leading to a stack overflow
                    String[] decomposedMopName = decomposeMopName(mopName);
                    int distance = Integer.parseInt(decomposedMopName[1]);
                    while (distance > 0) {
                        String fixedMopName = decomposedMopName[0] + distance + decomposedMopName[2];
                        int index = Arrays.binarySearch(mopMethods, fixedMopName, CachedClass.CachedMethodComparatorWithString.INSTANCE);
                        if (index >= 0) {
                            int from = index;
                            while (from > 0 && mopMethods[from - 1].getName().equals(fixedMopName)) from--;
                            int to = index;
                            while (to < mopMethods.length - 1 && mopMethods[to + 1].getName().equals(fixedMopName)) to++;
                            int matchingMethod = findMatchingMethod(mopMethods, from, to, method);
                            if (matchingMethod != -1) {
                                e.methodsForSuper = mopMethods[matchingMethod];
                                distance = 0;
                            }
                        }
                        distance--;
                    }
                }
            }
        }

        private String[] decomposeMopName(final String mopName) {
            int idx = mopName.indexOf("$");
            if (idx > 0) {
                int eidx = mopName.indexOf("$", idx + 1);
                if (eidx > 0) {
                    return new String[] { mopName.substring(0, idx + 1), mopName.substring(idx + 1, eidx), mopName.substring(eidx) };
                }
            }
            return new String[] { "", "0", mopName };
        }

        private void processFastArray(FastArray methods) {
            final int len = methods.size();
            final Object[] data = methods.getArray();
            for (int i = 0; i != len; ++i) {
                MetaMethod method = (MetaMethod) data[i];
                if (method instanceof NewMetaMethod)
                    continue;
                boolean isPrivate = Modifier.isPrivate(method.getModifiers());
                if (useThis ^ isPrivate)
                    continue;
                String mopName = method.getMopName();
                int index = Arrays.binarySearch(mopMethods, mopName, CachedClass.CachedMethodComparatorWithString.INSTANCE);
                if (index >= 0) {
                    int from = index;
                    while (from > 0 && mopMethods[from - 1].getName().equals(mopName)) from--;
                    int to = index;
                    while (to < mopMethods.length - 1 && mopMethods[to + 1].getName().equals(mopName)) to++;
                    int matchingMethod = findMatchingMethod(mopMethods, from, to, method);
                    if (matchingMethod != -1) {
                        methods.set(i, mopMethods[matchingMethod]);
                    }
                }
            }
        }
    }
    MOPIter iter = new MOPIter();
    // replace all calls for super with the correct MOP method
    iter.useThis = false;
    iter.iterate();
    // replace all calls for this with the correct MOP method
    iter.useThis = true;
    iter.iterate();
}
Also used : NewInstanceMetaMethod(org.codehaus.groovy.runtime.metaclass.NewInstanceMetaMethod) NewMetaMethod(org.codehaus.groovy.runtime.metaclass.NewMetaMethod) MixinInstanceMetaMethod(org.codehaus.groovy.runtime.metaclass.MixinInstanceMetaMethod) NewStaticMetaMethod(org.codehaus.groovy.runtime.metaclass.NewStaticMetaMethod) GeneratedMetaMethod(org.codehaus.groovy.reflection.GeneratedMetaMethod) ClosureMetaMethod(org.codehaus.groovy.runtime.metaclass.ClosureMetaMethod) TransformMetaMethod(org.codehaus.groovy.runtime.metaclass.TransformMetaMethod) CachedClass(org.codehaus.groovy.reflection.CachedClass) FastArray(org.codehaus.groovy.util.FastArray) NewMetaMethod(org.codehaus.groovy.runtime.metaclass.NewMetaMethod) CachedClass(org.codehaus.groovy.reflection.CachedClass)

Aggregations

CachedClass (org.codehaus.groovy.reflection.CachedClass)2 GeneratedMetaMethod (org.codehaus.groovy.reflection.GeneratedMetaMethod)2 ClosureMetaMethod (org.codehaus.groovy.runtime.metaclass.ClosureMetaMethod)2 MixinInstanceMetaMethod (org.codehaus.groovy.runtime.metaclass.MixinInstanceMetaMethod)2 NewInstanceMetaMethod (org.codehaus.groovy.runtime.metaclass.NewInstanceMetaMethod)2 NewMetaMethod (org.codehaus.groovy.runtime.metaclass.NewMetaMethod)2 NewStaticMetaMethod (org.codehaus.groovy.runtime.metaclass.NewStaticMetaMethod)2 TransformMetaMethod (org.codehaus.groovy.runtime.metaclass.TransformMetaMethod)2 FastArray (org.codehaus.groovy.util.FastArray)2