use of com.oracle.truffle.espresso.runtime.Attribute in project graal by oracle.
the class ClassfileParser method parseCodeAttribute.
private CodeAttribute parseCodeAttribute(Symbol<Name> name) {
int maxStack = stream.readU2();
int maxLocals = stream.readU2();
final int codeLength = stream.readS4();
if (codeLength <= 0) {
throw ConstantPool.classFormatError("code_length must be > than 0");
} else if (codeLength > 0xFFFF) {
throw ConstantPool.classFormatError("code_length > than 64 KB");
}
byte[] code;
try (DebugCloseable codeRead = CODE_READ.scope(context.getTimers())) {
code = stream.readByteArray(codeLength);
}
ExceptionHandler[] entries;
try (DebugCloseable handlers = EXCEPTION_HANDLERS.scope(context.getTimers())) {
entries = parseExceptionHandlerEntries();
}
int attributeCount = stream.readU2();
final Attribute[] codeAttributes = spawnAttributesArray(attributeCount);
int totalLocalTableCount = 0;
CommonAttributeParser commonAttributeParser = new CommonAttributeParser(InfoType.Code);
StackMapTableAttribute stackMapTable = null;
for (int i = 0; i < attributeCount; i++) {
final int attributeNameIndex = stream.readU2();
final Symbol<Name> attributeName;
attributeName = pool.symbolAt(attributeNameIndex, "attribute name");
final int attributeSize = stream.readS4();
final int startPosition = stream.getPosition();
if (attributeName.equals(Name.LineNumberTable)) {
codeAttributes[i] = parseLineNumberTable(attributeName);
} else if (attributeName.equals(Name.LocalVariableTable)) {
codeAttributes[i] = parseLocalVariableAttribute(attributeName, codeLength, maxLocals);
totalLocalTableCount++;
} else if (attributeName.equals(Name.LocalVariableTypeTable)) {
codeAttributes[i] = parseLocalVariableTypeAttribute(attributeName, codeLength, maxLocals);
} else if (attributeName.equals(Name.StackMapTable)) {
if (stackMapTable != null) {
throw ConstantPool.classFormatError("Duplicate StackMapTable attribute");
}
codeAttributes[i] = stackMapTable = parseStackMapTableAttribute(attributeName, attributeSize);
} else {
Attribute attr = commonAttributeParser.parseCommonAttribute(attributeName, attributeSize);
// stream.skip(attributeSize);
codeAttributes[i] = attr == null ? new Attribute(attributeName, stream.readByteArray(attributeSize)) : attr;
}
if (attributeSize != stream.getPosition() - startPosition) {
throw ConstantPool.classFormatError("Invalid attribute length for " + attributeName + " attribute");
}
}
if (totalLocalTableCount > 0) {
validateLocalTables(codeAttributes);
}
return new CodeAttribute(name, maxStack, maxLocals, code, entries, codeAttributes, majorVersion);
}
use of com.oracle.truffle.espresso.runtime.Attribute in project graal by oracle.
the class ClassfileParser method parseClassImpl.
private ParserKlass parseClassImpl() {
readMagic();
minorVersion = stream.readU2();
majorVersion = stream.readU2();
verifyVersion(majorVersion, minorVersion);
try (DebugCloseable closeable = CONSTANT_POOL.scope(context.getTimers())) {
this.pool = ConstantPool.parse(context.getLanguage(), stream, this, classDefinitionInfo.patches, context, majorVersion, minorVersion);
}
// JVM_ACC_MODULE is defined in JDK-9 and later.
if (majorVersion >= JAVA_9_VERSION) {
classFlags = stream.readU2() & (JVM_RECOGNIZED_CLASS_MODIFIERS | ACC_MODULE);
} else {
classFlags = stream.readU2() & (JVM_RECOGNIZED_CLASS_MODIFIERS);
}
if ((classFlags & ACC_INTERFACE) != 0 && majorVersion < JAVA_6_VERSION) {
// Set abstract bit for old class files for backward compatibility
classFlags |= ACC_ABSTRACT;
}
boolean isModule = (classFlags & ACC_MODULE) != 0;
if (isModule) {
throw ConstantPool.noClassDefFoundError(classType + " is not a class because access_flag ACC_MODULE is set");
}
if (badConstantSeen != null) {
// https://bugs.openjdk.java.net/browse/JDK-8175383
throw ConstantPool.classFormatError(String.format("Unknown constant tag %s [in class file %s]", badConstantSeen, classfile));
}
verifyClassFlags(classFlags, majorVersion);
// this class
int thisKlassIndex = stream.readU2();
Symbol<Name> thisKlassName = pool.classAt(thisKlassIndex).getName(pool);
final boolean isInterface = Modifier.isInterface(classFlags);
// TODO(peterssen): Verify class names.
Symbol<Type> thisKlassType = context.getTypes().fromName(thisKlassName);
if (Types.isPrimitive(thisKlassType) || Types.isArray(thisKlassType)) {
throw ConstantPool.classFormatError(".this_class cannot be array nor primitive " + classType);
}
// Update classType which could be null previously to reflect the name in the constant pool.
classType = thisKlassType;
// Checks if name in class file matches requested name
if (requestedClassType != null && !classDefinitionInfo.isHidden() && !requestedClassType.equals(classType)) {
throw ConstantPool.noClassDefFoundError(classType + " (wrong name: " + requestedClassType + ")");
}
Symbol<Type> superKlass = parseSuperKlass();
if (!Type.java_lang_Object.equals(classType) && superKlass == null) {
throw ConstantPool.classFormatError("Class " + classType + " must have a superclass");
}
if (isInterface && !Type.java_lang_Object.equals(superKlass)) {
throw ConstantPool.classFormatError("Interface " + classType + " must extend java.lang.Object");
}
Symbol<Type>[] superInterfaces;
try (DebugCloseable closeable = PARSE_INTERFACES.scope(context.getTimers())) {
superInterfaces = parseInterfaces();
}
final ParserField[] fields;
try (DebugCloseable closeable = PARSE_FIELD.scope(context.getTimers())) {
fields = parseFields(isInterface);
}
final ParserMethod[] methods;
try (DebugCloseable closeable = PARSE_METHODS.scope(context.getTimers())) {
methods = parseMethods(isInterface);
}
final Attribute[] attributes;
try (DebugCloseable closeable = PARSE_CLASSATTR.scope(context.getTimers())) {
attributes = parseClassAttributes();
}
// Ensure there are no trailing bytes
stream.checkEndOfFile();
if (classDefinitionInfo.isHidden()) {
assert requestedClassType != null;
int futureKlassID = context.getNewKlassId();
classDefinitionInfo.initKlassID(futureKlassID);
thisKlassName = context.getNames().getOrCreate(Types.hiddenClassName(requestedClassType, futureKlassID));
thisKlassType = context.getTypes().fromName(thisKlassName);
pool = pool.patchForHiddenClass(thisKlassIndex, thisKlassName);
}
return new ParserKlass(pool, classDefinitionInfo.patchFlags(classFlags), thisKlassName, thisKlassType, superKlass, superInterfaces, methods, fields, attributes, thisKlassIndex);
}
Aggregations