1 /* 2 * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 #ifndef SHARE_VM_CLASSFILE_BYTECODEASSEMBLER_HPP 26 #define SHARE_VM_CLASSFILE_BYTECODEASSEMBLER_HPP 27 28 #include "memory/allocation.hpp" 29 #include "oops/method.hpp" 30 #include "oops/symbol.hpp" 31 #include "utilities/globalDefinitions.hpp" 32 #include "utilities/growableArray.hpp" 33 #include "utilities/resourceHash.hpp" 34 35 36 /** 37 * Bytecode Assembler 38 * 39 * These classes are used to synthesize code for creating new methods from 40 * within the VM. This is only a partial implementation of an assembler; 41 * only the bytecodes that are needed by clients are implemented at this time. 42 * This is used during default method analysis to create overpass methods 43 * and add them to a call during parsing. Other uses (such as creating 44 * bridges) may come later. Any missing bytecodes can be implemented on an 45 * as-need basis. 46 */ 47 48 class BytecodeBuffer : public GrowableArray<u1> { 49 public: 50 BytecodeBuffer() : GrowableArray<u1>(20) {} 51 }; 52 53 // Entries in a yet-to-be-created constant pool. Limited types for now. 54 class BytecodeCPEntry VALUE_OBJ_CLASS_SPEC { 55 public: 56 enum tag { 57 ERROR_TAG, 58 UTF8, 59 KLASS, 60 STRING, 61 NAME_AND_TYPE, 62 METHODREF 63 }; 64 65 u1 _tag; 66 union { 67 Symbol* utf8; 68 u2 klass; 69 u2 string; 70 struct { 71 u2 name_index; 72 u2 type_index; 73 } name_and_type; 74 struct { 75 u2 class_index; 76 u2 name_and_type_index; 77 } methodref; 78 uintptr_t hash; 79 } _u; 80 81 BytecodeCPEntry() : _tag(ERROR_TAG) { _u.hash = 0; } 82 BytecodeCPEntry(u1 tag) : _tag(tag) { _u.hash = 0; } 83 84 static BytecodeCPEntry utf8(Symbol* symbol) { 85 BytecodeCPEntry bcpe(UTF8); 86 bcpe._u.utf8 = symbol; 87 return bcpe; 88 } 89 90 static BytecodeCPEntry klass(u2 index) { 91 BytecodeCPEntry bcpe(KLASS); 92 bcpe._u.klass = index; 93 return bcpe; 94 } 95 96 static BytecodeCPEntry string(u2 index) { 97 BytecodeCPEntry bcpe(STRING); 98 bcpe._u.string = index; 99 return bcpe; 100 } 101 102 static BytecodeCPEntry name_and_type(u2 name, u2 type) { 103 BytecodeCPEntry bcpe(NAME_AND_TYPE); 104 bcpe._u.name_and_type.name_index = name; 105 bcpe._u.name_and_type.type_index = type; 106 return bcpe; 107 } 108 109 static BytecodeCPEntry methodref(u2 class_index, u2 nat) { 110 BytecodeCPEntry bcpe(METHODREF); 111 bcpe._u.methodref.class_index = class_index; 112 bcpe._u.methodref.name_and_type_index = nat; 113 return bcpe; 114 } 115 116 static bool equals(BytecodeCPEntry const& e0, BytecodeCPEntry const& e1) { 117 return e0._tag == e1._tag && e0._u.hash == e1._u.hash; 118 } 119 120 static unsigned hash(BytecodeCPEntry const& e0) { 121 return (unsigned)(e0._tag ^ e0._u.hash); 122 } 123 }; 124 125 class BytecodeConstantPool : ResourceObj { 126 private: 127 typedef ResourceHashtable<BytecodeCPEntry, u2, 128 &BytecodeCPEntry::hash, &BytecodeCPEntry::equals> IndexHash; 129 130 ConstantPool* _orig; 131 GrowableArray<BytecodeCPEntry> _entries; 132 IndexHash _indices; 133 134 u2 find_or_add(BytecodeCPEntry const& bcpe); 135 136 public: 137 138 BytecodeConstantPool(ConstantPool* orig) : _orig(orig) {} 139 140 BytecodeCPEntry const& at(u2 index) const { return _entries.at(index); } 141 142 InstanceKlass* pool_holder() const { 143 return _orig->pool_holder(); 144 } 145 146 u2 utf8(Symbol* sym) { 147 return find_or_add(BytecodeCPEntry::utf8(sym)); 148 } 149 150 u2 klass(Symbol* class_name) { 151 return find_or_add(BytecodeCPEntry::klass(utf8(class_name))); 152 } 153 154 u2 string(Symbol* str) { 155 return find_or_add(BytecodeCPEntry::string(utf8(str))); 156 } 157 158 u2 name_and_type(Symbol* name, Symbol* sig) { 159 return find_or_add(BytecodeCPEntry::name_and_type(utf8(name), utf8(sig))); 160 } 161 162 u2 methodref(Symbol* class_name, Symbol* name, Symbol* sig) { 163 return find_or_add(BytecodeCPEntry::methodref( 164 klass(class_name), name_and_type(name, sig))); 165 } 166 167 ConstantPool* create_constant_pool(TRAPS) const; 168 }; 169 170 // Partial bytecode assembler - only what we need for creating 171 // overpass methods for default methods is implemented 172 class BytecodeAssembler : StackObj { 173 private: 174 BytecodeBuffer* _code; 175 BytecodeConstantPool* _cp; 176 177 void append(u1 imm_u1); 178 void append(u2 imm_u2); 179 void append(u4 imm_u4); 180 181 void xload(u4 index, u1 quick, u1 twobyte); 182 183 public: 184 BytecodeAssembler(BytecodeBuffer* buffer, BytecodeConstantPool* cp) 185 : _code(buffer), _cp(cp) {} 186 187 void aload(u4 index); 188 void areturn(); 189 void athrow(); 190 void checkcast(Symbol* sym); 191 void dload(u4 index); 192 void dreturn(); 193 void dup(); 194 void fload(u4 index); 195 void freturn(); 196 void iload(u4 index); 197 void invokespecial(Method* method); 198 void invokespecial(Symbol* cls, Symbol* name, Symbol* sig); 199 void invokevirtual(Method* method); 200 void invokevirtual(Symbol* cls, Symbol* name, Symbol* sig); 201 void ireturn(); 202 void ldc(u1 index); 203 void ldc_w(u2 index); 204 void lload(u4 index); 205 void lreturn(); 206 void _new(Symbol* sym); 207 void _return(); 208 209 void load_string(Symbol* sym); 210 void load(BasicType bt, u4 index); 211 void _return(BasicType bt); 212 }; 213 214 #endif // SHARE_VM_CLASSFILE_BYTECODEASSEMBLER_HPP