Search in sources :

Example 81 with Method

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

the class Target_java_lang_invoke_MethodHandleNatives method init.

/**
 * Plants an already resolved target into a memberName.
 *
 * @param self the memberName
 * @param ref the target. Can be either a mathod or a field.
 */
@Substitution
public static void init(@JavaType(internalName = "Ljava/lang/invoke/MemberName;") StaticObject self, @JavaType(Object.class) StaticObject ref, @Inject Meta meta) {
    Klass targetKlass = ref.getKlass();
    if (targetKlass.getType() == Type.java_lang_reflect_Method) {
        // Actual planting
        Method target = Method.getHostReflectiveMethodRoot(ref, meta);
        plantResolvedMethod(self, target, target.getRefKind(), meta);
        // Finish the job
        meta.java_lang_invoke_MemberName_clazz.setObject(self, target.getDeclaringKlass().mirror());
    } else if (targetKlass.getType() == Type.java_lang_reflect_Field) {
        // Actual planting
        Field field = Field.getReflectiveFieldRoot(ref, meta);
        plantResolvedField(self, field, getRefKind(meta.java_lang_invoke_MemberName_flags.getInt(self)), meta);
        // Finish the job
        Klass fieldKlass = meta.java_lang_reflect_Field_class.getObject(ref).getMirrorKlass();
        meta.java_lang_invoke_MemberName_clazz.setObject(self, fieldKlass.mirror());
    } else if (targetKlass.getType() == Type.java_lang_reflect_Constructor) {
        Method target = Method.getHostReflectiveConstructorRoot(ref, meta);
        plantResolvedMethod(self, target, target.getRefKind(), meta);
        meta.java_lang_invoke_MemberName_clazz.setObject(self, target.getDeclaringKlass().mirror());
    } else {
        throw EspressoError.shouldNotReachHere("invalid argument for MemberName.init: ", ref.getKlass());
    }
}
Also used : REF_getField(com.oracle.truffle.espresso.classfile.Constants.REF_getField) Field(com.oracle.truffle.espresso.impl.Field) REF_putField(com.oracle.truffle.espresso.classfile.Constants.REF_putField) Klass(com.oracle.truffle.espresso.impl.Klass) Method(com.oracle.truffle.espresso.impl.Method)

Example 82 with Method

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

the class MethodHandleIntrinsics method findIntrinsic.

private Method findIntrinsic(Method m, MethodRef methodRef) {
    Method method = getIntrinsic(methodRef);
    if (method != null) {
        return method;
    }
    CompilerAsserts.neverPartOfCompilation();
    method = m.createIntrinsic(methodRef.signature);
    Method previous = putIntrinsic(methodRef, method);
    if (previous != null) {
        return previous;
    }
    return method;
}
Also used : Method(com.oracle.truffle.espresso.impl.Method)

Example 83 with Method

use of com.oracle.truffle.espresso.impl.Method 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 84 with Method

use of com.oracle.truffle.espresso.impl.Method 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 85 with Method

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

the class EspressoInterop method asDate.

@ExportMessage
@TruffleBoundary
static LocalDate asDate(StaticObject receiver, @Shared("error") @Cached BranchProfile error) throws UnsupportedMessageException {
    receiver.checkNotForeign();
    if (isDate(receiver)) {
        Meta meta = receiver.getKlass().getMeta();
        if (instanceOf(receiver, meta.java_time_LocalDate)) {
            int year = (int) meta.java_time_LocalDate_year.get(receiver);
            short month = (short) meta.java_time_LocalDate_month.get(receiver);
            short day = (short) meta.java_time_LocalDate_day.get(receiver);
            return LocalDate.of(year, month, day);
        } else if (instanceOf(receiver, meta.java_time_LocalDateTime)) {
            StaticObject localDate = (StaticObject) meta.java_time_LocalDateTime_toLocalDate.invokeDirect(receiver);
            assert instanceOf(localDate, meta.java_time_LocalDate);
            return asDate(localDate, error);
        } else if (instanceOf(receiver, meta.java_time_Instant)) {
            StaticObject zoneIdUTC = (StaticObject) meta.java_time_ZoneId_of.invokeDirect(null, meta.toGuestString("UTC"));
            assert instanceOf(zoneIdUTC, meta.java_time_ZoneId);
            StaticObject zonedDateTime = (StaticObject) meta.java_time_Instant_atZone.invokeDirect(receiver, zoneIdUTC);
            assert instanceOf(zonedDateTime, meta.java_time_ZonedDateTime);
            StaticObject localDate = (StaticObject) meta.java_time_ZonedDateTime_toLocalDate.invokeDirect(zonedDateTime);
            assert instanceOf(localDate, meta.java_time_LocalDate);
            return asDate(localDate, error);
        } else if (instanceOf(receiver, meta.java_time_ZonedDateTime)) {
            StaticObject localDate = (StaticObject) meta.java_time_ZonedDateTime_toLocalDate.invokeDirect(receiver);
            assert instanceOf(localDate, meta.java_time_LocalDate);
            return asDate(localDate, error);
        } else if (instanceOf(receiver, meta.java_util_Date)) {
            // return ((Date) obj).toInstant().atZone(UTC).toLocalDate();
            int index = meta.java_util_Date_toInstant.getVTableIndex();
            Method virtualToInstant = receiver.getKlass().vtableLookup(index);
            StaticObject instant = (StaticObject) virtualToInstant.invokeDirect(receiver);
            return asDate(instant, error);
        }
    }
    error.enter();
    throw UnsupportedMessageException.create();
}
Also used : Meta(com.oracle.truffle.espresso.meta.Meta) StaticObject(com.oracle.truffle.espresso.runtime.StaticObject) Method(com.oracle.truffle.espresso.impl.Method) ExportMessage(com.oracle.truffle.api.library.ExportMessage) TruffleBoundary(com.oracle.truffle.api.CompilerDirectives.TruffleBoundary)

Aggregations

Method (com.oracle.truffle.espresso.impl.Method)91 StaticObject (com.oracle.truffle.espresso.runtime.StaticObject)57 Meta (com.oracle.truffle.espresso.meta.Meta)27 TruffleObject (com.oracle.truffle.api.interop.TruffleObject)22 Klass (com.oracle.truffle.espresso.impl.Klass)19 JavaType (com.oracle.truffle.espresso.substitutions.JavaType)19 ObjectKlass (com.oracle.truffle.espresso.impl.ObjectKlass)16 TruffleBoundary (com.oracle.truffle.api.CompilerDirectives.TruffleBoundary)14 ExportMessage (com.oracle.truffle.api.library.ExportMessage)12 ArrayKlass (com.oracle.truffle.espresso.impl.ArrayKlass)10 NoSafepoint (com.oracle.truffle.espresso.jni.NoSafepoint)9 FrameInstance (com.oracle.truffle.api.frame.FrameInstance)8 ArityException (com.oracle.truffle.api.interop.ArityException)8 UnsupportedTypeException (com.oracle.truffle.api.interop.UnsupportedTypeException)8 ArrayList (java.util.ArrayList)8 Name (com.oracle.truffle.espresso.descriptors.Symbol.Name)7 EspressoException (com.oracle.truffle.espresso.runtime.EspressoException)5 Field (com.oracle.truffle.espresso.impl.Field)4 MethodParametersAttribute (com.oracle.truffle.espresso.classfile.attributes.MethodParametersAttribute)3 Signature (com.oracle.truffle.espresso.descriptors.Symbol.Signature)3