nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/AsmCompilerSupport.java
changeset 18311 312f05b0462d
parent 18310 6b514cf7a2c3
parent 17815 b72ae39e1329
child 18312 c940914e1849
equal deleted inserted replaced
18310:6b514cf7a2c3 18311:312f05b0462d
     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 }