1 /* 2 * Permission is hereby granted, free of charge, to any person obtaining a copy of 3 * this software and associated documentation files (the "Software"), to deal in 4 * the Software without restriction, including without limitation the rights to 5 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 6 * of the Software, and to permit persons to whom the Software is furnished to do 7 * so, subject to the following conditions: 8 * 9 * The above copyright notice and this permission notice shall be included in all 10 * copies or substantial portions of the Software. 11 * 12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 14 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 15 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 17 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 18 * SOFTWARE. 19 */ 20 package jdk.nashorn.internal.runtime.regexp.joni; 21 22 import java.io.FileOutputStream; 23 import java.io.IOException; 24 25 import jdk.nashorn.internal.runtime.regexp.joni.constants.AsmConstants; 26 import jdk.internal.org.objectweb.asm.ClassWriter; 27 import jdk.internal.org.objectweb.asm.MethodVisitor; 28 import jdk.internal.org.objectweb.asm.Opcodes; 29 30 abstract class AsmCompilerSupport extends Compiler implements Opcodes, AsmConstants { 31 protected ClassWriter factory; // matcher allocator, also bit set, code rage and string template container 32 protected MethodVisitor factoryInit;// factory constructor 33 protected String factoryName; 34 35 protected ClassWriter machine; // matcher 36 protected MethodVisitor machineInit;// matcher constructor 37 protected MethodVisitor match; // actual matcher implementation (the matchAt method) 38 protected String machineName; 39 40 // we will? try to manage visitMaxs ourselves for efficiency 41 protected int maxStack = 1; 42 protected int maxVars = LAST_INDEX; 43 44 // for field generation 45 protected int bitsets, ranges, templates; 46 47 // simple class name postfix scheme for now 48 static int REG_NUM = 0; 49 50 // dummy class loader for now 51 private static final class DummyClassLoader extends ClassLoader { 52 public Class<?> defineClass(String name, byte[] bytes) { 53 return super.defineClass(name, bytes, 0, bytes.length); 54 } 55 }; 56 57 private static final DummyClassLoader loader = new DummyClassLoader(); 58 59 AsmCompilerSupport(Analyser analyser) { 60 super(analyser); 61 } 62 63 protected final void prepareFactory() { 64 factory = new ClassWriter(ClassWriter.COMPUTE_MAXS); 65 factoryName = "jdk/nashorn/internal/runtime/regexp/joni/MatcherFactory" + REG_NUM; 66 67 factory.visit(V1_4, ACC_PUBLIC + ACC_FINAL, factoryName, null, "jdk/nashorn/internal/runtime/regexp/joni/MatcherFactory", null); 68 69 MethodVisitor create = factory.visitMethod(ACC_SYNTHETIC, "create", "(Lorg/joni/Regex;[BII)Lorg/joni/Matcher;", null, null); 70 create.visitTypeInsn(NEW, machineName); 71 create.visitInsn(DUP); // instance 72 create.visitVarInsn(ALOAD, 1); // Regex 73 create.visitVarInsn(ALOAD, 2); // bytes[] 74 create.visitVarInsn(ILOAD, 3); // p 75 create.visitVarInsn(ILOAD, 4); // end 76 create.visitMethodInsn(INVOKESPECIAL, machineName, "<init>", "(Lorg/joni/Regex;[BII)V"); 77 create.visitInsn(ARETURN); 78 create.visitMaxs(0, 0); 79 //create.visitMaxs(6, 5); 80 create.visitEnd(); 81 } 82 83 protected final void prepareFactoryInit() { 84 factoryInit = factory.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null); 85 factoryInit.visitVarInsn(ALOAD, 0); 86 factoryInit.visitMethodInsn(INVOKESPECIAL, "jdk/nashorn/internal/runtime/regexp/joni/MatcherFactory", "<init>", "()V"); 87 } 88 89 protected final void setupFactoryInit() { 90 factoryInit.visitInsn(RETURN); 91 factoryInit.visitMaxs(0, 0); 92 //init.visitMaxs(1, 1); 93 factoryInit.visitEnd(); 94 } 95 96 protected final void prepareMachine() { 97 machine = new ClassWriter(ClassWriter.COMPUTE_MAXS); 98 machineName = "jdk/nashorn/internal/runtime/regexp/joni/NativeMachine" + REG_NUM; 99 } 100 101 protected final void prepareMachineInit() { 102 machine.visit(V1_4, ACC_PUBLIC + ACC_FINAL, machineName, null, "jdk/nashorn/internal/runtime/regexp/joni/NativeMachine", null); 103 machineInit = machine.visitMethod(ACC_PROTECTED, "<init>", "(Lorg/joni/Regex;[BII)V", null, null); 104 machineInit.visitVarInsn(ALOAD, THIS); // this 105 machineInit.visitVarInsn(ALOAD, 1); // Regex 106 machineInit.visitVarInsn(ALOAD, 2); // bytes[] 107 machineInit.visitVarInsn(ILOAD, 3); // p 108 machineInit.visitVarInsn(ILOAD, 4); // end 109 machineInit.visitMethodInsn(INVOKESPECIAL, "jdk/nashorn/internal/runtime/regexp/joni/NativeMachine", "<init>", "(Lorg/joni/Regex;[BII)V"); 110 } 111 112 protected final void setupMachineInit() { 113 if (bitsets + ranges + templates > 0) { // ok, some of these are in use, we'd like to cache the factory 114 machine.visitField(ACC_PRIVATE + ACC_FINAL, "factory", "L" + factoryName + ";", null, null); 115 machineInit.visitVarInsn(ALOAD, THIS); // this 116 machineInit.visitVarInsn(ALOAD, 1); // this, Regex 117 machineInit.visitFieldInsn(GETFIELD, "jdk/nashorn/internal/runtime/regexp/joni/Regex", "factory", "Lorg/joni/MatcherFactory;"); // this, factory 118 machineInit.visitTypeInsn(CHECKCAST, factoryName); 119 machineInit.visitFieldInsn(PUTFIELD, machineName, "factory", "L" + factoryName + ";"); // [] 120 } 121 122 machineInit.visitInsn(RETURN); 123 machineInit.visitMaxs(0, 0); 124 //init.visitMaxs(5, 5); 125 machineInit.visitEnd(); 126 } 127 128 protected final void prepareMachineMatch() { 129 match = machine.visitMethod(ACC_SYNTHETIC, "matchAt", "(III)I", null, null); 130 move(S, SSTART); // s = sstart 131 load("bytes", "[B"); // 132 astore(BYTES); // byte[]bytes = this.bytes 133 } 134 135 protected final void setupMachineMatch() { 136 match.visitInsn(ICONST_M1); 137 match.visitInsn(IRETURN); 138 139 match.visitMaxs(maxStack, maxVars); 140 match.visitEnd(); 141 } 142 143 protected final void setupClasses() { 144 byte[]factoryCode = factory.toByteArray(); 145 byte[]machineCode = machine.toByteArray(); 146 147 if (Config.DEBUG_ASM) { 148 try { 149 FileOutputStream fos; 150 fos = new FileOutputStream(factoryName.substring(factoryName.lastIndexOf('/') + 1) + ".class"); 151 fos.write(factoryCode); 152 fos.close(); 153 fos = new FileOutputStream(machineName.substring(machineName.lastIndexOf('/') + 1) + ".class"); 154 fos.write(machineCode); 155 fos.close(); 156 } catch (IOException ioe) { 157 ioe.printStackTrace(Config.err); 158 } 159 } 160 161 loader.defineClass(machineName.replace('/', '.'), machineCode); 162 Class<?> cls = loader.defineClass(factoryName.replace('/', '.'), factoryCode); 163 try { 164 regex.factory = (MatcherFactory)cls.newInstance(); 165 } catch(Exception e) { 166 e.printStackTrace(Config.err); 167 } 168 } 169 170 protected final void aload(int var) { 171 match.visitVarInsn(ALOAD, var); 172 } 173 174 protected final void astore(int var) { 175 match.visitVarInsn(ASTORE, var); 176 } 177 178 protected final void loadThis() { 179 match.visitVarInsn(ALOAD, THIS); 180 } 181 182 protected final void load(int var) { 183 match.visitVarInsn(ILOAD, var); 184 } 185 186 protected final void store(int var) { 187 match.visitVarInsn(ISTORE, var); 188 } 189 190 protected final void move(int to, int from) { 191 load(from); 192 store(to); 193 } 194 195 protected final void load(String field, String singature) { 196 loadThis(); 197 match.visitFieldInsn(GETFIELD, machineName, field, singature); 198 } 199 200 protected final void load(String field) { 201 load(field, "I"); 202 } 203 204 protected final void store(String field, String singature) { 205 loadThis(); 206 match.visitFieldInsn(PUTFIELD, machineName, field, singature); 207 } 208 209 protected final void store(String field) { 210 store(field, "I"); 211 } 212 213 protected final String installTemplate(char[] arr, int p, int length) { 214 String templateName = TEMPLATE + ++templates; 215 installArray(templateName, arr, p, length); 216 return templateName; 217 } 218 219 protected final String installCodeRange(int[]arr) { 220 String coreRangeName = CODERANGE + ++ranges; 221 installArray(coreRangeName, arr); 222 return coreRangeName; 223 } 224 225 protected final String installBitSet(int[]arr) { 226 String bitsetName = BITSET + ++bitsets; 227 installArray(bitsetName, arr); 228 return bitsetName; 229 } 230 231 private void installArray(String name, int[]arr) { 232 factory.visitField(ACC_PRIVATE + ACC_FINAL, name, "[I", null, null); 233 factoryInit.visitVarInsn(ALOAD, THIS); // this; 234 loadInt(factoryInit, arr.length); // this, length 235 factoryInit.visitIntInsn(NEWARRAY, T_INT); // this, arr 236 for (int i=0;i < arr.length; i++) buildArray(i, arr[i], IASTORE); 237 factoryInit.visitFieldInsn(PUTFIELD, factoryName, name, "[I"); 238 } 239 240 private void installArray(String name, char[]arr, int p, int length) { 241 factory.visitField(ACC_PRIVATE + ACC_FINAL, name, "[B", null, null); 242 factoryInit.visitVarInsn(ALOAD, THIS); // this; 243 loadInt(factoryInit, arr.length); // this, length 244 factoryInit.visitIntInsn(NEWARRAY, T_BYTE); // this, arr 245 for (int i=p, j=0; i < p + length; i++, j++) buildArray(j, arr[i] & 0xff, BASTORE); 246 factoryInit.visitFieldInsn(PUTFIELD, factoryName, name, "[B"); 247 } 248 249 private void buildArray(int index, int value, int type) { 250 factoryInit.visitInsn(DUP); // ... arr, arr 251 loadInt(factoryInit, index); // ... arr, arr, index 252 loadInt(factoryInit, value); // ... arr, arr, index, value 253 factoryInit.visitInsn(type); // ... arr 254 } 255 256 private void loadInt(MethodVisitor mv, int value) { 257 if (value >= -1 && value <= 5) { 258 mv.visitInsn(value + ICONST_0); // ICONST_0 == 3 259 } else if (value >= 6 && value <= 127 || value >= -128 && value <= -2) { 260 mv.visitIntInsn(BIPUSH, value); 261 } else if (value >= 128 && value <= 32767 || value >= -32768 && value <= -129) { 262 mv.visitIntInsn(SIPUSH, value); 263 } else { 264 mv.visitLdcInsn(new Integer(value)); 265 } 266 } 267 }