--- /dev/null 2016-05-31 09:42:47.975716356 -0700 +++ new/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileConstantPool.java 2016-12-09 00:57:06.048445666 -0800 @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.replacements.classfile; + +import static org.graalvm.compiler.replacements.classfile.Classfile.skipFully; +import static org.graalvm.compiler.replacements.classfile.ClassfileConstant.CONSTANT_Class; + +import java.io.DataInputStream; +import java.io.IOException; + +import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.replacements.classfile.ClassfileConstant.ClassRef; +import org.graalvm.compiler.replacements.classfile.ClassfileConstant.ExecutableRef; +import org.graalvm.compiler.replacements.classfile.ClassfileConstant.FieldRef; +import org.graalvm.compiler.replacements.classfile.ClassfileConstant.Primitive; +import org.graalvm.compiler.replacements.classfile.ClassfileConstant.Utf8; + +import jdk.vm.ci.meta.ConstantPool; +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.JavaField; +import jdk.vm.ci.meta.JavaMethod; +import jdk.vm.ci.meta.JavaType; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.meta.Signature; + +class ClassfileConstantPool implements ConstantPool { + + final ClassfileConstant[] entries; + final ClassfileBytecodeProvider context; + + public static class Bytecodes { + public static final int GETSTATIC = 178; // 0xB2 + public static final int PUTSTATIC = 179; // 0xB3 + public static final int GETFIELD = 180; // 0xB4 + public static final int PUTFIELD = 181; // 0xB5 + public static final int INVOKEVIRTUAL = 182; // 0xB6 + public static final int INVOKESPECIAL = 183; // 0xB7 + public static final int INVOKESTATIC = 184; // 0xB8 + public static final int INVOKEINTERFACE = 185; // 0xB9 + public static final int INVOKEDYNAMIC = 186; // 0xBA + } + + ClassfileConstantPool(DataInputStream stream, ClassfileBytecodeProvider context) throws IOException { + this.context = context; + byte tag; + + int count = stream.readUnsignedShort(); + entries = new ClassfileConstant[count]; + + int i = 1; + while (i < count) { + entries[i] = readConstant(stream); + tag = entries[i].tag; + + if ((tag == ClassfileConstant.CONSTANT_Double) || (tag == ClassfileConstant.CONSTANT_Long)) { + i += 2; + } else { + i += 1; + } + } + } + + static final ClassfileConstant readConstant(DataInputStream stream) throws IOException { + byte tag = stream.readByte(); + + switch (tag) { + case ClassfileConstant.CONSTANT_Class: + return new ClassfileConstant.ClassRef(stream); + case ClassfileConstant.CONSTANT_Fieldref: + return new ClassfileConstant.FieldRef(stream); + case ClassfileConstant.CONSTANT_Methodref: + return new ClassfileConstant.MethodRef(stream); + case ClassfileConstant.CONSTANT_InterfaceMethodref: + return new ClassfileConstant.InterfaceMethodRef(stream); + case ClassfileConstant.CONSTANT_String: + return new ClassfileConstant.StringRef(stream); + case ClassfileConstant.CONSTANT_Integer: + return new ClassfileConstant.Primitive(tag, JavaConstant.forInt(stream.readInt())); + case ClassfileConstant.CONSTANT_Float: + return new ClassfileConstant.Primitive(tag, JavaConstant.forFloat(stream.readFloat())); + case ClassfileConstant.CONSTANT_Long: + return new ClassfileConstant.Primitive(tag, JavaConstant.forLong(stream.readLong())); + case ClassfileConstant.CONSTANT_Double: + return new ClassfileConstant.Primitive(tag, JavaConstant.forDouble(stream.readDouble())); + case ClassfileConstant.CONSTANT_NameAndType: + return new ClassfileConstant.NameAndType(stream); + case ClassfileConstant.CONSTANT_Utf8: + return new ClassfileConstant.Utf8(stream.readUTF()); + case ClassfileConstant.CONSTANT_MethodHandle: + skipFully(stream, 3); // reference_kind, reference_index + return new ClassfileConstant.Unsupported(tag, "CONSTANT_MethodHandle_info"); + case ClassfileConstant.CONSTANT_MethodType: + skipFully(stream, 2); // descriptor_index + return new ClassfileConstant.Unsupported(tag, "CONSTANT_MethodType_info"); + case ClassfileConstant.CONSTANT_InvokeDynamic: + skipFully(stream, 4); // bootstrap_method_attr_index, name_and_type_index + return new ClassfileConstant.Unsupported(tag, "CONSTANT_InvokeDynamic_info"); + default: + throw new GraalError("Invalid constant pool tag: " + tag); + } + } + + @Override + public int length() { + return entries.length; + } + + T get(Class c, int index) { + return c.cast(entries[index]); + } + + @Override + public void loadReferencedType(int index, int opcode) { + if (opcode == Bytecodes.INVOKEDYNAMIC) { + throw new GraalError("INVOKEDYNAMIC not supported by " + ClassfileBytecodeProvider.class.getSimpleName()); + } + entries[index].loadReferencedType(this, index, opcode); + } + + @Override + public JavaField lookupField(int index, ResolvedJavaMethod method, int opcode) { + return get(FieldRef.class, index).resolve(this, opcode); + } + + @Override + public JavaMethod lookupMethod(int index, int opcode) { + if (opcode == Bytecodes.INVOKEDYNAMIC) { + throw new GraalError("INVOKEDYNAMIC not supported by" + ClassfileBytecodeProvider.class.getSimpleName()); + } + return get(ExecutableRef.class, index).resolve(this, opcode); + } + + @Override + public JavaType lookupType(int index, int opcode) { + return get(ClassRef.class, index).resolve(this); + } + + @Override + public String lookupUtf8(int index) { + return ((Utf8) entries[index]).value; + } + + @Override + public Signature lookupSignature(int index) { + throw GraalError.shouldNotReachHere(); + } + + @Override + public Object lookupConstant(int index) { + ClassfileConstant c = entries[index]; + if (c instanceof Primitive) { + Primitive p = (Primitive) c; + return p.value; + } + switch (c.tag) { + case CONSTANT_Class: + final int opcode = -1; + return lookupType(index, opcode); + case ClassfileConstant.CONSTANT_String: + return ((ClassfileConstant.StringRef) c).getValue(this); + default: + throw new GraalError("Unexpected constant pool tag %s", c.tag); + } + } + + @Override + public JavaConstant lookupAppendix(int index, int opcode) { + if (opcode == Bytecodes.INVOKEVIRTUAL) { + return null; + } + throw GraalError.shouldNotReachHere(); + } +}