Search in sources :

Example 66 with Klass

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

the class EspressoContext method initializeKnownClass.

private void initializeKnownClass(Symbol<Type> type) {
    Klass klass = getMeta().loadKlassOrFail(type, StaticObject.NULL, StaticObject.NULL);
    klass.safeInitialize();
}
Also used : Klass(com.oracle.truffle.espresso.impl.Klass) ObjectKlass(com.oracle.truffle.espresso.impl.ObjectKlass)

Example 67 with Klass

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

the class BaseInterop method toDisplayString.

@ExportMessage
@TruffleBoundary
public static Object toDisplayString(StaticObject object, boolean allowSideEffects) {
    if (object.isForeignObject()) {
        InteropLibrary interopLibrary = InteropLibrary.getUncached();
        try {
            return "Foreign object: " + interopLibrary.asString(interopLibrary.toDisplayString(object.rawForeignObject(), allowSideEffects));
        } catch (UnsupportedMessageException e) {
            throw EspressoError.shouldNotReachHere("Interop library failed to convert display string to string");
        }
    }
    if (StaticObject.isNull(object)) {
        return "NULL";
    }
    Klass thisKlass = object.getKlass();
    Meta meta = thisKlass.getMeta();
    if (allowSideEffects) {
        // Call guest toString.
        int toStringIndex = meta.java_lang_Object_toString.getVTableIndex();
        Method toString = thisKlass.vtableLookup(toStringIndex);
        return meta.toHostString((StaticObject) toString.invokeDirect(object));
    }
    // Handle some special instances without side effects.
    if (thisKlass == meta.java_lang_Class) {
        return "class " + thisKlass.getTypeAsString();
    }
    if (thisKlass == meta.java_lang_String) {
        return meta.toHostString(object);
    }
    return thisKlass.getTypeAsString() + "@" + Integer.toHexString(System.identityHashCode(object));
}
Also used : Meta(com.oracle.truffle.espresso.meta.Meta) Klass(com.oracle.truffle.espresso.impl.Klass) UnsupportedMessageException(com.oracle.truffle.api.interop.UnsupportedMessageException) InteropLibrary(com.oracle.truffle.api.interop.InteropLibrary) Method(com.oracle.truffle.espresso.impl.Method) ExportMessage(com.oracle.truffle.api.library.ExportMessage) TruffleBoundary(com.oracle.truffle.api.CompilerDirectives.TruffleBoundary)

Example 68 with Klass

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

the class ClassRedefinition method detectClassChanges.

// detect all types of class changes, but return early when a change that require arbitrary
// changes
private static ClassChange detectClassChanges(ParserKlass newParserKlass, ObjectKlass oldKlass, DetectedChange collectedChanges, ParserKlass finalParserKlass) throws RedefintionNotSupportedException {
    ClassChange result = ClassChange.NO_CHANGE;
    ParserKlass oldParserKlass = oldKlass.getLinkedKlass().getParserKlass();
    boolean isPatched = finalParserKlass != null;
    // detect method changes (including constructors)
    ParserMethod[] newParserMethods = newParserKlass.getMethods();
    List<Method> oldMethods = new ArrayList<>(Arrays.asList(oldKlass.getDeclaredMethods()));
    List<ParserMethod> newMethods = new ArrayList<>(Arrays.asList(newParserMethods));
    Map<Method, ParserMethod> bodyChanges = new HashMap<>();
    List<ParserMethod> newSpecialMethods = new ArrayList<>(1);
    boolean constantPoolChanged = false;
    if (!Arrays.equals(oldParserKlass.getConstantPool().getRawBytes(), newParserKlass.getConstantPool().getRawBytes())) {
        constantPoolChanged = true;
    }
    Iterator<Method> oldIt = oldMethods.iterator();
    Iterator<ParserMethod> newIt;
    while (oldIt.hasNext()) {
        Method oldMethod = oldIt.next();
        ParserMethod oldParserMethod = oldMethod.getLinkedMethod().getParserMethod();
        // verify that there is a new corresponding method
        newIt = newMethods.iterator();
        while (newIt.hasNext()) {
            ParserMethod newMethod = newIt.next();
            if (isSameMethod(oldParserMethod, newMethod)) {
                // detect method changes
                ClassChange change = detectMethodChanges(oldParserMethod, newMethod);
                switch(change) {
                    case NO_CHANGE:
                        if (isPatched) {
                            checkForSpecialConstructor(collectedChanges, bodyChanges, newSpecialMethods, oldMethod, oldParserMethod, newMethod);
                        } else if (constantPoolChanged) {
                            if (isObsolete(oldParserMethod, newMethod, oldParserKlass.getConstantPool(), newParserKlass.getConstantPool())) {
                                result = ClassChange.CONSTANT_POOL_CHANGE;
                                collectedChanges.addMethodBodyChange(oldMethod, newMethod);
                            } else {
                                collectedChanges.addUnchangedMethod(oldMethod);
                            }
                        } else {
                            collectedChanges.addUnchangedMethod(oldMethod);
                        }
                        break;
                    case METHOD_BODY_CHANGE:
                        result = change;
                        if (isPatched) {
                            checkForSpecialConstructor(collectedChanges, bodyChanges, newSpecialMethods, oldMethod, oldParserMethod, newMethod);
                        } else {
                            collectedChanges.addMethodBodyChange(oldMethod, newMethod);
                        }
                        break;
                    default:
                        return change;
                }
                newIt.remove();
                oldIt.remove();
                break;
            }
        }
    }
    if (isPatched) {
        ParserMethod[] finalMethods = finalParserKlass.getMethods();
        // map found changed methods
        for (Map.Entry<Method, ParserMethod> entry : bodyChanges.entrySet()) {
            Method oldMethod = entry.getKey();
            ParserMethod changed = entry.getValue();
            for (int i = 0; i < newParserMethods.length; i++) {
                if (newParserMethods[i] == changed) {
                    collectedChanges.addMethodBodyChange(oldMethod, finalMethods[i]);
                    break;
                }
            }
        }
        // map found new methods
        newMethods.addAll(newSpecialMethods);
        for (ParserMethod changed : newMethods) {
            for (int i = 0; i < newParserMethods.length; i++) {
                if (newParserMethods[i] == changed) {
                    collectedChanges.addNewMethod(finalMethods[i]);
                    break;
                }
            }
        }
    } else {
        collectedChanges.addNewMethods(newMethods);
    }
    for (Method oldMethod : oldMethods) {
        collectedChanges.addRemovedMethod(oldMethod.getMethodVersion());
    }
    if (!oldMethods.isEmpty()) {
        result = ClassChange.REMOVE_METHOD;
    } else if (!newMethods.isEmpty()) {
        result = ClassChange.ADD_METHOD;
    }
    if (isPatched) {
        result = ClassChange.CLASS_NAME_CHANGED;
    }
    // detect field changes
    Field[] oldFields = oldKlass.getDeclaredFields();
    ParserField[] newFields = newParserKlass.getFields();
    ArrayList<Field> oldFieldsList = new ArrayList<>(Arrays.asList(oldFields));
    ArrayList<ParserField> newFieldsList = new ArrayList<>(Arrays.asList(newFields));
    Map<ParserField, Field> compatibleFields = new HashMap<>();
    Iterator<Field> oldFieldsIt = oldFieldsList.iterator();
    Iterator<ParserField> newFieldsIt;
    while (oldFieldsIt.hasNext()) {
        Field oldField = oldFieldsIt.next();
        newFieldsIt = newFieldsList.iterator();
        // search for a new corresponding field
        while (newFieldsIt.hasNext()) {
            ParserField newField = newFieldsIt.next();
            // first look for a perfect match
            if (isUnchangedField(oldField, newField, compatibleFields)) {
                // A nested anonymous inner class may contain a field reference to the outer
                // class instance. Since we match against the patched (inner class rename rules
                // applied) if the current class was patched (renamed) the resulting outer
                // field pointer will have a changed type. Hence we should mark it as a new
                // field.
                Matcher matcher = InnerClassRedefiner.ANON_INNER_CLASS_PATTERN.matcher(oldField.getType().toString());
                if (isPatched && matcher.matches()) {
                    break;
                }
                oldFieldsIt.remove();
                newFieldsIt.remove();
                break;
            }
        }
    }
    if (!newFieldsList.isEmpty()) {
        if (isPatched) {
            ParserField[] finalFields = finalParserKlass.getFields();
            // lookup the final new field based on the index in the parser field array
            for (ParserField parserField : newFieldsList) {
                for (int i = 0; i < newFields.length; i++) {
                    if (parserField == newFields[i]) {
                        collectedChanges.addNewField(finalFields[i]);
                        break;
                    }
                }
            }
        } else {
            collectedChanges.addNewFields(newFieldsList);
        }
        result = ClassChange.SCHEMA_CHANGE;
    }
    if (!oldFieldsList.isEmpty()) {
        collectedChanges.addRemovedFields(oldFieldsList);
        result = ClassChange.SCHEMA_CHANGE;
    }
    // detect class-level changes
    if (newParserKlass.getFlags() != oldParserKlass.getFlags()) {
        result = ClassChange.SCHEMA_CHANGE;
    }
    collectedChanges.addCompatibleFields(compatibleFields);
    // detect changes to superclass and implemented interfaces
    Klass superKlass = oldKlass.getSuperKlass();
    if (!newParserKlass.getSuperKlass().equals(oldParserKlass.getSuperKlass())) {
        result = ClassChange.CLASS_HIERARCHY_CHANGED;
        superKlass = getLoadedKlass(newParserKlass.getSuperKlass(), oldKlass);
    }
    collectedChanges.addSuperKlass((ObjectKlass) superKlass);
    ObjectKlass[] newSuperInterfaces = oldKlass.getSuperInterfaces();
    if (!Arrays.equals(newParserKlass.getSuperInterfaces(), oldParserKlass.getSuperInterfaces())) {
        result = ClassChange.CLASS_HIERARCHY_CHANGED;
        newSuperInterfaces = new ObjectKlass[newParserKlass.getSuperInterfaces().length];
        for (int i = 0; i < newParserKlass.getSuperInterfaces().length; i++) {
            newSuperInterfaces[i] = (ObjectKlass) getLoadedKlass(newParserKlass.getSuperInterfaces()[i], oldKlass);
        }
    }
    collectedChanges.addSuperInterfaces(newSuperInterfaces);
    return result;
}
Also used : HashMap(java.util.HashMap) Matcher(java.util.regex.Matcher) ArrayList(java.util.ArrayList) ObjectKlass(com.oracle.truffle.espresso.impl.ObjectKlass) RedefineAddedField(com.oracle.truffle.espresso.impl.RedefineAddedField) Field(com.oracle.truffle.espresso.impl.Field) ParserField(com.oracle.truffle.espresso.impl.ParserField) ParserKlass(com.oracle.truffle.espresso.impl.ParserKlass) ParserMethod(com.oracle.truffle.espresso.impl.ParserMethod) ParserMethod(com.oracle.truffle.espresso.impl.ParserMethod) Method(com.oracle.truffle.espresso.impl.Method) ParserField(com.oracle.truffle.espresso.impl.ParserField) Klass(com.oracle.truffle.espresso.impl.Klass) ObjectKlass(com.oracle.truffle.espresso.impl.ObjectKlass) ParserKlass(com.oracle.truffle.espresso.impl.ParserKlass) HashMap(java.util.HashMap) EconomicMap(org.graalvm.collections.EconomicMap) Map(java.util.Map)

Example 69 with Klass

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

the class EspressoInterop method fitsInShort.

@ExportMessage
static boolean fitsInShort(StaticObject receiver) {
    receiver.checkNotForeign();
    if (isNull(receiver)) {
        return false;
    }
    Klass klass = receiver.getKlass();
    if (isAtMostShort(klass)) {
        return true;
    }
    Meta meta = klass.getMeta();
    if (klass == meta.java_lang_Integer) {
        int content = meta.java_lang_Integer_value.getInt(receiver);
        return (short) content == content;
    }
    if (klass == meta.java_lang_Long) {
        long content = meta.java_lang_Long_value.getLong(receiver);
        return (short) content == content;
    }
    if (klass == meta.java_lang_Float) {
        float content = meta.java_lang_Float_value.getFloat(receiver);
        return (short) content == content && !isNegativeZero(content);
    }
    if (klass == meta.java_lang_Double) {
        double content = meta.java_lang_Double_value.getDouble(receiver);
        return (short) content == content && !isNegativeZero(content);
    }
    return false;
}
Also used : Meta(com.oracle.truffle.espresso.meta.Meta) Klass(com.oracle.truffle.espresso.impl.Klass) ObjectKlass(com.oracle.truffle.espresso.impl.ObjectKlass) ArrayKlass(com.oracle.truffle.espresso.impl.ArrayKlass) ExportMessage(com.oracle.truffle.api.library.ExportMessage)

Example 70 with Klass

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

the class EspressoInterop method readNumberValue.

private static Number readNumberValue(StaticObject receiver) throws UnsupportedMessageException {
    assert receiver.isEspressoObject();
    Klass klass = receiver.getKlass();
    Meta meta = klass.getMeta();
    if (klass == meta.java_lang_Byte) {
        return (Byte) meta.java_lang_Byte_value.get(receiver);
    }
    if (klass == meta.java_lang_Short) {
        return (Short) meta.java_lang_Short_value.get(receiver);
    }
    if (klass == meta.java_lang_Integer) {
        return (Integer) meta.java_lang_Integer_value.get(receiver);
    }
    if (klass == meta.java_lang_Long) {
        return (Long) meta.java_lang_Long_value.get(receiver);
    }
    if (klass == meta.java_lang_Float) {
        return (Float) meta.java_lang_Float_value.get(receiver);
    }
    if (klass == meta.java_lang_Double) {
        return (Double) meta.java_lang_Double_value.get(receiver);
    }
    CompilerDirectives.transferToInterpreter();
    throw UnsupportedMessageException.create();
}
Also used : Meta(com.oracle.truffle.espresso.meta.Meta) InteropUtils.isAtMostFloat(com.oracle.truffle.espresso.runtime.InteropUtils.isAtMostFloat) Klass(com.oracle.truffle.espresso.impl.Klass) ObjectKlass(com.oracle.truffle.espresso.impl.ObjectKlass) ArrayKlass(com.oracle.truffle.espresso.impl.ArrayKlass) InteropUtils.isAtMostByte(com.oracle.truffle.espresso.runtime.InteropUtils.isAtMostByte) InteropUtils.isAtMostLong(com.oracle.truffle.espresso.runtime.InteropUtils.isAtMostLong) InteropUtils.isAtMostShort(com.oracle.truffle.espresso.runtime.InteropUtils.isAtMostShort)

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