hotspot/test/compiler/jvmci/code/TestAssembler.java
changeset 38126 c3706b502779
parent 37761 82b8d12a553f
parent 38079 fd24ad51113a
child 38127 2ab00cd4556e
equal deleted inserted replaced
37761:82b8d12a553f 38126:c3706b502779
     1 /*
       
     2  * Copyright (c) 2015, 2016, 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 package compiler.jvmci.code;
       
    25 
       
    26 import java.nio.ByteBuffer;
       
    27 import java.nio.ByteOrder;
       
    28 import java.util.ArrayList;
       
    29 import java.util.Arrays;
       
    30 
       
    31 import jdk.vm.ci.code.CodeCacheProvider;
       
    32 import jdk.vm.ci.code.DebugInfo;
       
    33 import jdk.vm.ci.code.Register;
       
    34 import jdk.vm.ci.code.StackSlot;
       
    35 import jdk.vm.ci.code.site.Call;
       
    36 import jdk.vm.ci.code.site.ConstantReference;
       
    37 import jdk.vm.ci.code.site.DataPatch;
       
    38 import jdk.vm.ci.code.site.DataSectionReference;
       
    39 import jdk.vm.ci.code.site.Infopoint;
       
    40 import jdk.vm.ci.code.site.InfopointReason;
       
    41 import jdk.vm.ci.code.site.Mark;
       
    42 import jdk.vm.ci.code.site.Reference;
       
    43 import jdk.vm.ci.code.site.Site;
       
    44 import jdk.vm.ci.hotspot.HotSpotCompiledCode;
       
    45 import jdk.vm.ci.hotspot.HotSpotCompiledCode.Comment;
       
    46 import jdk.vm.ci.hotspot.HotSpotCompiledNmethod;
       
    47 import jdk.vm.ci.hotspot.HotSpotConstant;
       
    48 import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
       
    49 import jdk.vm.ci.meta.Assumptions.Assumption;
       
    50 import jdk.vm.ci.meta.InvokeTarget;
       
    51 import jdk.vm.ci.meta.LIRKind;
       
    52 import jdk.vm.ci.meta.PlatformKind;
       
    53 import jdk.vm.ci.meta.ResolvedJavaMethod;
       
    54 import jdk.vm.ci.meta.VMConstant;
       
    55 
       
    56 /**
       
    57  * Simple assembler used by the code installation tests.
       
    58  */
       
    59 public abstract class TestAssembler {
       
    60 
       
    61     /**
       
    62      * Emit the method prologue code (e.g. building the new stack frame).
       
    63      */
       
    64     public abstract void emitPrologue();
       
    65 
       
    66     /**
       
    67      * Emit the method epilogue code (e.g. the deopt handler).
       
    68      */
       
    69     public abstract void emitEpilogue();
       
    70 
       
    71     /**
       
    72      * Emit code to grow the stack frame.
       
    73      *
       
    74      * @param size the size in bytes that the stack should grow
       
    75      */
       
    76     public abstract void emitGrowStack(int size);
       
    77 
       
    78     /**
       
    79      * Get the register containing the first 32-bit integer argument.
       
    80      */
       
    81     public abstract Register emitIntArg0();
       
    82 
       
    83     /**
       
    84      * Get the register containing the second 32-bit integer argument.
       
    85      */
       
    86     public abstract Register emitIntArg1();
       
    87 
       
    88     /**
       
    89      * Emit code to add two 32-bit integer registers. May reuse one of the argument registers.
       
    90      */
       
    91     public abstract Register emitIntAdd(Register a, Register b);
       
    92 
       
    93     /**
       
    94      * Emit code to load a constant 32-bit integer to a register.
       
    95      */
       
    96     public abstract Register emitLoadInt(int value);
       
    97 
       
    98     /**
       
    99      * Emit code to load a constant 64-bit integer to a register.
       
   100      */
       
   101     public abstract Register emitLoadLong(long value);
       
   102 
       
   103     /**
       
   104      * Emit code to load a constant single-precision float to a register.
       
   105      */
       
   106     public abstract Register emitLoadFloat(float value);
       
   107 
       
   108     /**
       
   109      * Emit code to load a constant oop or metaspace pointer to a register. The pointer may be wide
       
   110      * or narrow, depending on {@link HotSpotConstant#isCompressed() c.isCompressed()}.
       
   111      */
       
   112     public abstract Register emitLoadPointer(HotSpotConstant c);
       
   113 
       
   114     /**
       
   115      * Emit code to load a wide pointer from the {@link HotSpotCompiledCode#dataSection} to a
       
   116      * register.
       
   117      */
       
   118     public abstract Register emitLoadPointer(DataSectionReference ref);
       
   119 
       
   120     /**
       
   121      * Emit code to load a narrow pointer from the {@link HotSpotCompiledCode#dataSection} to a
       
   122      * register.
       
   123      */
       
   124     public abstract Register emitLoadNarrowPointer(DataSectionReference ref);
       
   125 
       
   126     /**
       
   127      * Emit code to load a (wide) pointer from a memory location to a register.
       
   128      */
       
   129     public abstract Register emitLoadPointer(Register base, int offset);
       
   130 
       
   131     /**
       
   132      * Emit code to store a 32-bit integer from a register to a new stack slot.
       
   133      */
       
   134     public abstract StackSlot emitIntToStack(Register a);
       
   135 
       
   136     /**
       
   137      * Emit code to store a 64-bit integer from a register to a new stack slot.
       
   138      */
       
   139     public abstract StackSlot emitLongToStack(Register a);
       
   140 
       
   141     /**
       
   142      * Emit code to store a single-precision float from a register to a new stack slot.
       
   143      */
       
   144     public abstract StackSlot emitFloatToStack(Register a);
       
   145 
       
   146     /**
       
   147      * Emit code to store a wide pointer from a register to a new stack slot.
       
   148      */
       
   149     public abstract StackSlot emitPointerToStack(Register a);
       
   150 
       
   151     /**
       
   152      * Emit code to store a narrow pointer from a register to a new stack slot.
       
   153      */
       
   154     public abstract StackSlot emitNarrowPointerToStack(Register a);
       
   155 
       
   156     /**
       
   157      * Emit code to uncompress a narrow pointer. The input pointer is guaranteed to be non-null.
       
   158      */
       
   159     public abstract Register emitUncompressPointer(Register compressed, long base, int shift);
       
   160 
       
   161     /**
       
   162      * Emit code to return from a function, returning a 32-bit integer.
       
   163      */
       
   164     public abstract void emitIntRet(Register a);
       
   165 
       
   166     /**
       
   167      * Emit code to return from a function, returning a wide oop pointer.
       
   168      */
       
   169     public abstract void emitPointerRet(Register a);
       
   170 
       
   171     /**
       
   172      * Emit code that traps, forcing a deoptimization.
       
   173      */
       
   174     public abstract void emitTrap(DebugInfo info);
       
   175 
       
   176     public final LIRKind narrowOopKind;
       
   177 
       
   178     protected final Buffer code;
       
   179     protected final Buffer data;
       
   180     private final ArrayList<Site> sites;
       
   181     private final ArrayList<DataPatch> dataPatches;
       
   182 
       
   183     protected final CodeCacheProvider codeCache;
       
   184 
       
   185     private final Register[] registers;
       
   186     private int nextRegister;
       
   187 
       
   188     protected int frameSize;
       
   189     private int stackAlignment;
       
   190     private int curStackSlot;
       
   191 
       
   192     private StackSlot deoptRescue;
       
   193 
       
   194     protected TestAssembler(CodeCacheProvider codeCache, int initialFrameSize, int stackAlignment, PlatformKind narrowOopKind, Register... registers) {
       
   195         this.narrowOopKind = LIRKind.reference(narrowOopKind);
       
   196 
       
   197         this.code = new Buffer();
       
   198         this.data = new Buffer();
       
   199         this.sites = new ArrayList<>();
       
   200         this.dataPatches = new ArrayList<>();
       
   201 
       
   202         this.codeCache = codeCache;
       
   203 
       
   204         this.registers = registers;
       
   205         this.nextRegister = 0;
       
   206 
       
   207         this.frameSize = initialFrameSize;
       
   208         this.stackAlignment = stackAlignment;
       
   209         this.curStackSlot = initialFrameSize;
       
   210     }
       
   211 
       
   212     protected Register newRegister() {
       
   213         return registers[nextRegister++];
       
   214     }
       
   215 
       
   216     protected StackSlot newStackSlot(LIRKind kind) {
       
   217         curStackSlot += kind.getPlatformKind().getSizeInBytes();
       
   218         if (curStackSlot > frameSize) {
       
   219             int newFrameSize = curStackSlot;
       
   220             if (newFrameSize % stackAlignment != 0) {
       
   221                 newFrameSize += stackAlignment - (newFrameSize % stackAlignment);
       
   222             }
       
   223             emitGrowStack(newFrameSize - frameSize);
       
   224             frameSize = newFrameSize;
       
   225         }
       
   226         return StackSlot.get(kind, -curStackSlot, true);
       
   227     }
       
   228 
       
   229     protected void setDeoptRescueSlot(StackSlot deoptRescue) {
       
   230         this.deoptRescue = deoptRescue;
       
   231     }
       
   232 
       
   233     protected void recordCall(InvokeTarget target, int size, boolean direct, DebugInfo debugInfo) {
       
   234         sites.add(new Call(target, code.position(), size, direct, debugInfo));
       
   235     }
       
   236 
       
   237     protected void recordMark(Object id) {
       
   238         sites.add(new Mark(code.position(), id));
       
   239     }
       
   240 
       
   241     protected void recordImplicitException(DebugInfo info) {
       
   242         sites.add(new Infopoint(code.position(), info, InfopointReason.IMPLICIT_EXCEPTION));
       
   243     }
       
   244 
       
   245     protected void recordDataPatchInCode(Reference ref) {
       
   246         sites.add(new DataPatch(code.position(), ref));
       
   247     }
       
   248 
       
   249     protected void recordDataPatchInData(Reference ref) {
       
   250         dataPatches.add(new DataPatch(data.position(), ref));
       
   251     }
       
   252 
       
   253     public DataSectionReference emitDataItem(HotSpotConstant c) {
       
   254         DataSectionReference ref = new DataSectionReference();
       
   255         ref.setOffset(data.position());
       
   256 
       
   257         recordDataPatchInData(new ConstantReference((VMConstant) c));
       
   258         if (c.isCompressed()) {
       
   259             data.emitInt(0xDEADDEAD);
       
   260         } else {
       
   261             data.emitLong(0xDEADDEADDEADDEADL);
       
   262         }
       
   263 
       
   264         return ref;
       
   265     }
       
   266 
       
   267     public HotSpotCompiledCode finish(HotSpotResolvedJavaMethod method) {
       
   268         int id = method.allocateCompileId(0);
       
   269         byte[] finishedCode = code.finish();
       
   270         Site[] finishedSites = sites.toArray(new Site[0]);
       
   271         byte[] finishedData = data.finish();
       
   272         DataPatch[] finishedDataPatches = dataPatches.toArray(new DataPatch[0]);
       
   273         return new HotSpotCompiledNmethod(method.getName(), finishedCode, finishedCode.length, finishedSites, new Assumption[0], new ResolvedJavaMethod[]{method}, new Comment[0], finishedData, 16,
       
   274                         finishedDataPatches, false, frameSize, deoptRescue, method, 0, id, 0L, false);
       
   275     }
       
   276 
       
   277     protected static class Buffer {
       
   278 
       
   279         private ByteBuffer data = ByteBuffer.allocate(32).order(ByteOrder.nativeOrder());
       
   280 
       
   281         private void ensureSize(int length) {
       
   282             if (length >= data.limit()) {
       
   283                 byte[] newBuf = Arrays.copyOf(data.array(), length * 4);
       
   284                 ByteBuffer newData = ByteBuffer.wrap(newBuf);
       
   285                 newData.order(data.order());
       
   286                 newData.position(data.position());
       
   287                 data = newData;
       
   288             }
       
   289         }
       
   290 
       
   291         public int position() {
       
   292             return data.position();
       
   293         }
       
   294 
       
   295         public void emitByte(int b) {
       
   296             ensureSize(data.position() + 1);
       
   297             data.put((byte) (b & 0xFF));
       
   298         }
       
   299 
       
   300         public void emitShort(int b) {
       
   301             ensureSize(data.position() + 2);
       
   302             data.putShort((short) b);
       
   303         }
       
   304 
       
   305         public void emitInt(int b) {
       
   306             ensureSize(data.position() + 4);
       
   307             data.putInt(b);
       
   308         }
       
   309 
       
   310         public void emitLong(long b) {
       
   311             ensureSize(data.position() + 8);
       
   312             data.putLong(b);
       
   313         }
       
   314 
       
   315         public void emitFloat(float f) {
       
   316             ensureSize(data.position() + 4);
       
   317             data.putFloat(f);
       
   318         }
       
   319 
       
   320         public void align(int alignment) {
       
   321             int pos = data.position();
       
   322             int misaligned = pos % alignment;
       
   323             if (misaligned != 0) {
       
   324                 pos += alignment - misaligned;
       
   325                 data.position(pos);
       
   326             }
       
   327         }
       
   328 
       
   329         private byte[] finish() {
       
   330             return Arrays.copyOf(data.array(), data.position());
       
   331         }
       
   332     }
       
   333 }