# HG changeset patch # User Doug Simon # Date 1448495221 -3600 # Node ID 22110ef74a402548fb2cabe78c9d0ce0af955076 # Parent f41ed1d87d68c7ad193e7d4afeccfe2425e71c6c 8144083 [JVMCI] CompilationResult should be finalized by JVMCI compiler and made effectively final diff -r f41ed1d87d68 -r 22110ef74a40 jvmci/jdk.vm.ci.code/src/jdk/vm/ci/code/CompilationResult.java --- a/jvmci/jdk.vm.ci.code/src/jdk/vm/ci/code/CompilationResult.java Wed Nov 25 20:41:26 2015 +0100 +++ b/jvmci/jdk.vm.ci.code/src/jdk/vm/ci/code/CompilationResult.java Thu Nov 26 00:47:01 2015 +0100 @@ -498,6 +498,8 @@ } } + private boolean closed; + private int entryBCI = -1; private final DataSection dataSection = new DataSection(); @@ -598,6 +600,7 @@ * @param entryBCI the entryBCI to set */ public void setEntryBCI(int entryBCI) { + checkOpen(); this.entryBCI = entryBCI; } @@ -605,11 +608,14 @@ * Sets the assumptions made during compilation. */ public void setAssumptions(Assumption[] assumptions) { + checkOpen(); this.assumptions = assumptions; } /** * Gets the assumptions made during compilation. + * + * The caller must not modify the contents of the returned array. */ public Assumption[] getAssumptions() { return assumptions; @@ -622,6 +628,7 @@ * @param inlinedMethods the methods inlined during compilation */ public void setMethods(ResolvedJavaMethod rootMethod, Collection inlinedMethods) { + checkOpen(); assert rootMethod != null; assert inlinedMethods != null; if (inlinedMethods.contains(rootMethod)) { @@ -649,6 +656,8 @@ /** * Gets the methods whose bytecodes were used as input to the compilation. * + * The caller must not modify the contents of the returned array. + * * @return {@code null} if the compilation did not record method dependencies otherwise the * methods whose bytecodes were used as input to the compilation with the first element * being the root method of the compilation @@ -658,6 +667,7 @@ } public void setBytecodeSize(int bytecodeSize) { + checkOpen(); this.bytecodeSize = bytecodeSize; } @@ -687,6 +697,7 @@ * @param size the size of the frame in bytes */ public void setTotalFrameSize(int size) { + checkOpen(); totalFrameSize = size; } @@ -697,6 +708,7 @@ * @param size the size of the machine code */ public void setTargetCode(byte[] code, int size) { + checkOpen(); targetCode = code; targetCodeSize = size; } @@ -710,6 +722,7 @@ * @param ref The reference that should be inserted in the code. */ public void recordDataPatch(int codePos, Reference ref) { + checkOpen(); assert codePos >= 0 && ref != null; dataPatches.add(new DataPatch(codePos, ref)); } @@ -724,6 +737,7 @@ * @param direct specifies if this is a {@linkplain Call#direct direct} call */ public void recordCall(int codePos, int size, InvokeTarget target, DebugInfo debugInfo, boolean direct) { + checkOpen(); final Call call = new Call(target, codePos, size, direct, debugInfo); addInfopoint(call); } @@ -735,6 +749,7 @@ * @param handlerPos the position of the handler */ public void recordExceptionHandler(int codePos, int handlerPos) { + checkOpen(); assert validateExceptionHandlerAdd(codePos, handlerPos) : String.format("Duplicate exception handler for pc 0x%x handlerPos 0x%x", codePos, handlerPos); exceptionHandlers.add(new ExceptionHandler(codePos, handlerPos)); } @@ -785,6 +800,7 @@ * @param infopoint the infopoint to record, usually a derived class from {@link Infopoint} */ public void addInfopoint(Infopoint infopoint) { + checkOpen(); infopoints.add(infopoint); } @@ -795,6 +811,7 @@ * @param markId the identifier for this mark */ public Mark recordMark(int codePos, Object markId) { + checkOpen(); Mark mark = new Mark(codePos, markId); marks.add(mark); return mark; @@ -814,6 +831,7 @@ * @param offset */ public void setCustomStackAreaOffset(int offset) { + checkOpen(); customStackAreaOffset = offset; } @@ -842,6 +860,7 @@ } public void addAnnotation(CodeAnnotation annotation) { + checkOpen(); assert annotation != null; if (annotations == null) { annotations = new ArrayList<>(); @@ -924,10 +943,46 @@ } public void setHasUnsafeAccess(boolean hasUnsafeAccess) { + checkOpen(); this.hasUnsafeAccess = hasUnsafeAccess; } public boolean hasUnsafeAccess() { return hasUnsafeAccess; } + + /** + * Clears the information in this object pertaining to generating code. That is, the + * {@linkplain #getMarks() marks}, {@linkplain #getInfopoints() infopoints}, + * {@linkplain #getExceptionHandlers() exception handlers}, {@linkplain #getDataPatches() data + * patches} and {@linkplain #getAnnotations() annotations} recorded in this object are cleared. + */ + public void resetForEmittingCode() { + checkOpen(); + infopoints.clear(); + dataPatches.clear(); + exceptionHandlers.clear(); + marks.clear(); + dataSection.clear(); + if (annotations != null) { + annotations.clear(); + } + } + + private void checkOpen() { + if (closed) { + throw new IllegalStateException(); + } + } + + /** + * Closes this compilation result to future updates. + */ + public void close() { + if (closed) { + throw new IllegalStateException("Cannot re-close compilation result " + this); + } + dataSection.close(); + closed = true; + } } diff -r f41ed1d87d68 -r 22110ef74a40 jvmci/jdk.vm.ci.code/src/jdk/vm/ci/code/DataSection.java --- a/jvmci/jdk.vm.ci.code/src/jdk/vm/ci/code/DataSection.java Wed Nov 25 20:41:26 2015 +0100 +++ b/jvmci/jdk.vm.ci.code/src/jdk/vm/ci/code/DataSection.java Thu Nov 26 00:47:01 2015 +0100 @@ -141,7 +141,7 @@ private final ArrayList dataItems = new ArrayList<>(); - private boolean finalLayout; + private boolean closed; private int sectionAlignment; private int sectionSize; @@ -163,7 +163,7 @@ } if (obj instanceof DataSection) { DataSection that = (DataSection) obj; - if (this.finalLayout == that.finalLayout && this.sectionAlignment == that.sectionAlignment && this.sectionSize == that.sectionSize && Objects.equals(this.dataItems, that.dataItems)) { + if (this.closed == that.closed && this.sectionAlignment == that.sectionAlignment && this.sectionSize == that.sectionSize && Objects.equals(this.dataItems, that.dataItems)) { return true; } } @@ -171,14 +171,14 @@ } /** - * Insert a {@link Data} item into the data section. If the item is already in the data section, - * the same {@link DataSectionReference} is returned. + * Inserts a {@link Data} item into the data section. If the item is already in the data + * section, the same {@link DataSectionReference} is returned. * * @param data the {@link Data} item to be inserted * @return a unique {@link DataSectionReference} identifying the {@link Data} item */ public DataSectionReference insertData(Data data) { - assert !finalLayout; + checkOpen(); synchronized (data) { if (data.ref == null) { data.ref = new DataSectionReference(); @@ -193,7 +193,8 @@ * {@link DataSection}, and empties the other section. */ public void addAll(DataSection other) { - assert !finalLayout && !other.finalLayout; + checkOpen(); + other.checkOpen(); for (Data data : other.dataItems) { assert data.ref != null; @@ -203,12 +204,20 @@ } /** - * Compute the layout of the data section. This can be called only once, and after it has been - * called, the data section can no longer be modified. + * Determines if this object has been {@link #close() closed}. */ - public void finalizeLayout() { - assert !finalLayout; - finalLayout = true; + public boolean closed() { + return closed; + } + + /** + * Computes the layout of the data section and closes this object to further updates. + * + * This must be called exactly once. + */ + void close() { + checkOpen(); + closed = true; // simple heuristic: put items with larger alignment requirement first dataItems.sort((a, b) -> a.alignment - b.alignment); @@ -227,37 +236,38 @@ sectionSize = position; } - public boolean isFinalized() { - return finalLayout; - } - /** - * Get the size of the data section. Can only be called after {@link #finalizeLayout}. + * Gets the size of the data section. + * + * This must only be called once this object has been {@linkplain #closed() closed}. */ public int getSectionSize() { - assert finalLayout; + checkClosed(); return sectionSize; } /** - * Get the minimum alignment requirement of the data section. Can only be called after - * {@link #finalizeLayout}. + * Gets the minimum alignment requirement of the data section. + * + * This must only be called once this object has been {@linkplain #closed() closed}. */ public int getSectionAlignment() { - assert finalLayout; + checkClosed(); return sectionAlignment; } /** - * Build the data section. Can only be called after {@link #finalizeLayout}. + * Builds the data section into a given buffer. + * + * This must only be called once this object has been {@linkplain #closed() closed}. * - * @param buffer The {@link ByteBuffer} where the data section should be built. The buffer must + * @param buffer the {@link ByteBuffer} where the data section should be built. The buffer must * hold at least {@link #getSectionSize()} bytes. - * @param patch A {@link Consumer} to receive {@link DataPatch data patches} for relocations in - * the data section. + * @param patch a {@link Consumer} to receive {@link DataPatch data patches} for relocations in + * the data section */ public void buildDataSection(ByteBuffer buffer, Consumer patch) { - assert finalLayout; + checkClosed(); for (Data d : dataItems) { buffer.position(d.ref.getOffset()); d.builder.emit(buffer, patch); @@ -300,8 +310,20 @@ return ((position + alignment - 1) / alignment) * alignment; } + private void checkClosed() { + if (!closed) { + throw new IllegalStateException(); + } + } + + private void checkOpen() { + if (closed) { + throw new IllegalStateException(); + } + } + public void clear() { - assert !finalLayout; + checkOpen(); this.dataItems.clear(); this.sectionAlignment = 0; this.sectionSize = 0; diff -r f41ed1d87d68 -r 22110ef74a40 jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompiledCode.java --- a/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompiledCode.java Wed Nov 25 20:41:26 2015 +0100 +++ b/jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotCompiledCode.java Thu Nov 26 00:47:01 2015 +0100 @@ -121,7 +121,6 @@ targetCodeSize = compResult.getTargetCodeSize(); DataSection data = compResult.getDataSection(); - assert data.isFinalized() : "data section needs to be finalized before code installation"; dataSection = new byte[data.getSectionSize()]; ByteBuffer buffer = ByteBuffer.wrap(dataSection).order(ByteOrder.nativeOrder());