Search in sources :

Example 21 with Klass

use of com.oracle.truffle.espresso.impl.Klass in project graal by oracle.

the class InnerClassRedefiner method matchClassInfo.

private void matchClassInfo(HotSwapClassInfo hotSwapInfo, List<ObjectKlass> removedInnerClasses, Map<StaticObject, Map<Symbol<Symbol.Name>, Symbol<Symbol.Name>>> renamingRules) throws RedefintionNotSupportedException {
    Klass klass = hotSwapInfo.getKlass();
    // try to fetch all direct inner classes
    // based on the constant pool in the class bytes
    // by means of the defining class loader
    fetchMissingInnerClasses(hotSwapInfo);
    if (klass == null) {
        // non-mapped hotSwapInfo means it's a new inner class that didn't map
        // to any previous inner class
        // we need to generate a new unique name and apply to nested inner classes
        HotSwapClassInfo outerInfo = hotSwapInfo.getOuterClassInfo();
        String name = outerInfo.addHotClassMarker();
        hotSwapInfo.rename(context.getNames().getOrCreate(name));
        addRenamingRule(renamingRules, hotSwapInfo.getClassLoader(), hotSwapInfo.getName(), hotSwapInfo.getNewName(), context);
    } else {
        ImmutableClassInfo previousInfo = getGlobalClassInfo(klass);
        ArrayList<ImmutableClassInfo> previousInnerClasses = previousInfo.getImmutableInnerClasses();
        ArrayList<HotSwapClassInfo> newInnerClasses = hotSwapInfo.getHotSwapInnerClasses();
        // before matching
        if (hotSwapInfo.isRenamed()) {
            for (HotSwapClassInfo newInnerClass : newInnerClasses) {
                newInnerClass.outerRenamed(hotSwapInfo.getName().toString(), hotSwapInfo.getNewName().toString());
            }
        }
        if (previousInnerClasses.size() > 0 || newInnerClasses.size() > 0) {
            ArrayList<ImmutableClassInfo> removedClasses = new ArrayList<>(previousInnerClasses);
            for (HotSwapClassInfo info : newInnerClasses) {
                ImmutableClassInfo bestMatch = null;
                int maxScore = 0;
                for (ImmutableClassInfo removedClass : removedClasses) {
                    int score = info.match(removedClass);
                    if (score > 0 && score > maxScore) {
                        maxScore = score;
                        bestMatch = removedClass;
                        if (maxScore == MAX_SCORE) {
                            // found a perfect match, so stop iterating
                            break;
                        }
                    }
                }
                if (bestMatch != null) {
                    removedClasses.remove(bestMatch);
                    // rename class and associate with previous klass object
                    if (!info.getName().equals(bestMatch.getName())) {
                        info.rename(bestMatch.getName());
                        addRenamingRule(renamingRules, info.getClassLoader(), info.getName(), info.getNewName(), context);
                    }
                    info.setKlass(bestMatch.getKlass());
                }
            }
            for (ImmutableClassInfo removedClass : removedClasses) {
                if (removedClass.getKlass() != null) {
                    removedInnerClasses.add(removedClass.getKlass());
                }
            }
        }
    }
    for (HotSwapClassInfo innerClass : hotSwapInfo.getHotSwapInnerClasses()) {
        matchClassInfo(innerClass, removedInnerClasses, renamingRules);
    }
}
Also used : Klass(com.oracle.truffle.espresso.impl.Klass) ObjectKlass(com.oracle.truffle.espresso.impl.ObjectKlass) ArrayList(java.util.ArrayList)

Example 22 with Klass

use of com.oracle.truffle.espresso.impl.Klass in project graal by oracle.

the class InnerClassRedefiner method findLoadedInnerClasses.

Set<ObjectKlass> findLoadedInnerClasses(Klass klass) {
    // we use a cache to store inner/outer class mappings
    Map<Symbol<Symbol.Type>, Set<ObjectKlass>> classLoaderMap = innerKlassCache.get(klass.getDefiningClassLoader());
    if (classLoaderMap == null) {
        classLoaderMap = new HashMap<>();
        // register a listener on the registry to fill in
        // future loaded anonymous inner classes
        ClassRegistry classRegistry = context.getRegistries().getClassRegistry(klass.getDefiningClassLoader());
        classRegistry.registerOnLoadListener(new DefineKlassListener() {

            @Override
            public void onKlassDefined(ObjectKlass objectKlass) {
                InnerClassRedefiner.this.onKlassDefined(objectKlass);
            }
        });
        // do a one-time look up of all currently loaded
        // classes for this loader and fill in the map
        List<Klass> loadedKlasses = classRegistry.getLoadedKlasses();
        for (Klass loadedKlass : loadedKlasses) {
            if (loadedKlass instanceof ObjectKlass) {
                ObjectKlass objectKlass = (ObjectKlass) loadedKlass;
                Matcher matcher = ANON_INNER_CLASS_PATTERN.matcher(loadedKlass.getNameAsString());
                if (matcher.matches()) {
                    Symbol<Symbol.Name> outerClassName = getOuterClassName(loadedKlass.getName());
                    if (outerClassName != null && outerClassName.length() > 0) {
                        Symbol<Symbol.Type> outerType = context.getTypes().fromName(outerClassName);
                        Set<ObjectKlass> innerKlasses = classLoaderMap.get(outerType);
                        if (innerKlasses == null) {
                            innerKlasses = new HashSet<>(1);
                            classLoaderMap.put(outerType, innerKlasses);
                        }
                        innerKlasses.add(objectKlass);
                    }
                }
            }
        }
        // add to cache
        innerKlassCache.put(klass.getDefiningClassLoader(), classLoaderMap);
    }
    Set<ObjectKlass> innerClasses = classLoaderMap.get(klass.getType());
    return innerClasses != null ? innerClasses : new HashSet<>(0);
}
Also used : Set(java.util.Set) HashSet(java.util.HashSet) ClassRegistry(com.oracle.truffle.espresso.impl.ClassRegistry) Matcher(java.util.regex.Matcher) Symbol(com.oracle.truffle.espresso.descriptors.Symbol) ObjectKlass(com.oracle.truffle.espresso.impl.ObjectKlass) Klass(com.oracle.truffle.espresso.impl.Klass) ObjectKlass(com.oracle.truffle.espresso.impl.ObjectKlass)

Example 23 with Klass

use of com.oracle.truffle.espresso.impl.Klass in project graal by oracle.

the class ClassRedefinition method redefineClass.

public int redefineClass(ChangePacket packet, List<ObjectKlass> invalidatedClasses, List<ObjectKlass> redefinedClasses) {
    try {
        switch(packet.classChange) {
            case METHOD_BODY_CHANGE:
            case CONSTANT_POOL_CHANGE:
            case CLASS_NAME_CHANGED:
            case ADD_METHOD:
            case REMOVE_METHOD:
            case SCHEMA_CHANGE:
                doRedefineClass(packet, invalidatedClasses, redefinedClasses);
                return 0;
            case CLASS_HIERARCHY_CHANGED:
                context.markChangedHierarchy();
                doRedefineClass(packet, invalidatedClasses, redefinedClasses);
                return 0;
            case NEW_CLASS:
                ClassInfo classInfo = packet.info;
                // if there is a currently loaded class under that name
                // we have to replace that in the class loader registry etc.
                // otherwise, don't eagerly define the new class
                Symbol<Symbol.Type> type = context.getTypes().fromName(classInfo.getName());
                ClassRegistry classRegistry = context.getRegistries().getClassRegistry(classInfo.getClassLoader());
                Klass loadedKlass = classRegistry.findLoadedKlass(type);
                if (loadedKlass != null) {
                    // OK, we have to define the new klass instance and
                    // inject it under the existing JDWP ID
                    classRegistry.onInnerClassRemoved(type);
                    ObjectKlass newKlass = classRegistry.defineKlass(type, classInfo.getBytes());
                    packet.info.setKlass(newKlass);
                }
                return 0;
            default:
                return 0;
        }
    } catch (EspressoException ex) {
        // we get from parsing the class file
        return ErrorCodes.INVALID_CLASS_FORMAT;
    }
}
Also used : ClassRegistry(com.oracle.truffle.espresso.impl.ClassRegistry) Klass(com.oracle.truffle.espresso.impl.Klass) ObjectKlass(com.oracle.truffle.espresso.impl.ObjectKlass) ParserKlass(com.oracle.truffle.espresso.impl.ParserKlass) EspressoException(com.oracle.truffle.espresso.runtime.EspressoException) ObjectKlass(com.oracle.truffle.espresso.impl.ObjectKlass)

Example 24 with Klass

use of com.oracle.truffle.espresso.impl.Klass in project graal by oracle.

the class ClassRedefinition method getLoadedKlass.

private static Klass getLoadedKlass(Symbol<Symbol.Type> klassType, ObjectKlass oldKlass) throws RedefintionNotSupportedException {
    Klass klass;
    klass = oldKlass.getContext().getRegistries().findLoadedClass(klassType, oldKlass.getDefiningClassLoader());
    if (klass == null) {
        // new super interface must be loaded eagerly then
        StaticObject resourceGuestString = oldKlass.getMeta().toGuestString(Types.binaryName(klassType));
        try {
            StaticObject loadedClass = (StaticObject) oldKlass.getMeta().java_lang_ClassLoader_loadClass.invokeDirect(oldKlass.getDefiningClassLoader(), resourceGuestString);
            klass = loadedClass.getMirrorKlass();
        } catch (Throwable t) {
            throw new RedefintionNotSupportedException(ErrorCodes.ABSENT_INFORMATION);
        }
    }
    return klass;
}
Also used : Klass(com.oracle.truffle.espresso.impl.Klass) ObjectKlass(com.oracle.truffle.espresso.impl.ObjectKlass) ParserKlass(com.oracle.truffle.espresso.impl.ParserKlass) StaticObject(com.oracle.truffle.espresso.runtime.StaticObject)

Example 25 with Klass

use of com.oracle.truffle.espresso.impl.Klass in project graal by oracle.

the class MHLinkToNode method call.

@Override
public Object call(Object[] args) {
    assert (getMethod().isStatic());
    Method.MethodVersion resolutionSeed = getTarget(args);
    Object[] basicArgs = unbasic(args, resolutionSeed.getMethod().getParsedSignature(), 0, argCount - 1, hasReceiver);
    // method might have been redefined or removed by redefinition
    if (!resolutionSeed.getRedefineAssumption().isValid()) {
        if (resolutionSeed.getMethod().isRemovedByRedefition()) {
            Klass receiverKlass = hasReceiver ? ((StaticObject) basicArgs[0]).getKlass() : resolutionSeed.getMethod().getDeclaringKlass();
            resolutionSeed = resolutionSeed.getMethod().getContext().getClassRedefinition().handleRemovedMethod(resolutionSeed.getMethod(), receiverKlass).getMethodVersion();
        }
    }
    Method target = linker.linkTo(resolutionSeed.getMethod(), args);
    Object result = executeCall(basicArgs, target.getMethodVersion());
    return rebasic(result, target.getReturnKind());
}
Also used : Klass(com.oracle.truffle.espresso.impl.Klass) StaticObject(com.oracle.truffle.espresso.runtime.StaticObject) Method(com.oracle.truffle.espresso.impl.Method)

Aggregations

Klass (com.oracle.truffle.espresso.impl.Klass)71 ObjectKlass (com.oracle.truffle.espresso.impl.ObjectKlass)54 ArrayKlass (com.oracle.truffle.espresso.impl.ArrayKlass)49 StaticObject (com.oracle.truffle.espresso.runtime.StaticObject)33 JavaType (com.oracle.truffle.espresso.substitutions.JavaType)24 Meta (com.oracle.truffle.espresso.meta.Meta)21 Method (com.oracle.truffle.espresso.impl.Method)19 TruffleBoundary (com.oracle.truffle.api.CompilerDirectives.TruffleBoundary)10 Name (com.oracle.truffle.espresso.descriptors.Symbol.Name)10 NoSafepoint (com.oracle.truffle.espresso.jni.NoSafepoint)10 ExportMessage (com.oracle.truffle.api.library.ExportMessage)8 Field (com.oracle.truffle.espresso.impl.Field)7 ArrayList (java.util.ArrayList)7 RuntimeConstantPool (com.oracle.truffle.espresso.classfile.RuntimeConstantPool)6 EspressoException (com.oracle.truffle.espresso.runtime.EspressoException)6 InnerClassesAttribute (com.oracle.truffle.espresso.classfile.attributes.InnerClassesAttribute)5 Type (com.oracle.truffle.espresso.descriptors.Symbol.Type)5 NativeType (com.oracle.truffle.espresso.ffi.NativeType)5 TruffleObject (com.oracle.truffle.api.interop.TruffleObject)3 EnclosingMethodAttribute (com.oracle.truffle.espresso.classfile.attributes.EnclosingMethodAttribute)3