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);
}
}
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);
}
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;
}
}
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;
}
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());
}
Aggregations