src/jdk.vm.ci/share/classes/jdk.vm.ci.code/src/jdk/vm/ci/code/DataSection.java

Print this page




 124         }
 125 
 126         @Override
 127         public boolean equals(Object obj) {
 128             assert ref != null;
 129             if (obj == this) {
 130                 return true;
 131             }
 132             if (obj instanceof Data) {
 133                 Data that = (Data) obj;
 134                 if (this.alignment == that.alignment && this.size == that.size && this.ref.equals(that.ref)) {
 135                     return true;
 136                 }
 137             }
 138             return false;
 139         }
 140     }
 141 
 142     private final ArrayList<Data> dataItems = new ArrayList<>();
 143 
 144     private boolean finalLayout;
 145     private int sectionAlignment;
 146     private int sectionSize;
 147 
 148     @Override
 149     public int hashCode() {
 150         // DataSection instances should not be used as hash map keys
 151         throw new UnsupportedOperationException("hashCode");
 152     }
 153 
 154     @Override
 155     public String toString() {
 156         return identityHashCodeString(this);
 157     }
 158 
 159     @Override
 160     public boolean equals(Object obj) {
 161         if (this == obj) {
 162             return true;
 163         }
 164         if (obj instanceof DataSection) {
 165             DataSection that = (DataSection) obj;
 166             if (this.finalLayout == that.finalLayout && this.sectionAlignment == that.sectionAlignment && this.sectionSize == that.sectionSize && Objects.equals(this.dataItems, that.dataItems)) {
 167                 return true;
 168             }
 169         }
 170         return false;
 171     }
 172 
 173     /**
 174      * Insert a {@link Data} item into the data section. If the item is already in the data section,
 175      * the same {@link DataSectionReference} is returned.
 176      *
 177      * @param data the {@link Data} item to be inserted
 178      * @return a unique {@link DataSectionReference} identifying the {@link Data} item
 179      */
 180     public DataSectionReference insertData(Data data) {
 181         assert !finalLayout;
 182         synchronized (data) {
 183             if (data.ref == null) {
 184                 data.ref = new DataSectionReference();
 185                 dataItems.add(data);
 186             }
 187             return data.ref;
 188         }
 189     }
 190 
 191     /**
 192      * Transfers all {@link Data} from the provided other {@link DataSection} to this
 193      * {@link DataSection}, and empties the other section.
 194      */
 195     public void addAll(DataSection other) {
 196         assert !finalLayout && !other.finalLayout;

 197 
 198         for (Data data : other.dataItems) {
 199             assert data.ref != null;
 200             dataItems.add(data);
 201         }
 202         other.dataItems.clear();
 203     }
 204 
 205     /**
 206      * Compute the layout of the data section. This can be called only once, and after it has been
 207      * called, the data section can no longer be modified.
 208      */
 209     public void finalizeLayout() {
 210         assert !finalLayout;
 211         finalLayout = true;









 212 
 213         // simple heuristic: put items with larger alignment requirement first
 214         dataItems.sort((a, b) -> a.alignment - b.alignment);
 215 
 216         int position = 0;
 217         int alignment = 1;
 218         for (Data d : dataItems) {
 219             alignment = lcm(alignment, d.alignment);
 220             position = align(position, d.alignment);
 221 
 222             d.ref.setOffset(position);
 223             position += d.size;
 224         }
 225 
 226         sectionAlignment = alignment;
 227         sectionSize = position;
 228     }
 229 
 230     public boolean isFinalized() {
 231         return finalLayout;
 232     }
 233 
 234     /**
 235      * Get the size of the data section. Can only be called after {@link #finalizeLayout}.


 236      */
 237     public int getSectionSize() {
 238         assert finalLayout;
 239         return sectionSize;
 240     }
 241 
 242     /**
 243      * Get the minimum alignment requirement of the data section. Can only be called after
 244      * {@link #finalizeLayout}.

 245      */
 246     public int getSectionAlignment() {
 247         assert finalLayout;
 248         return sectionAlignment;
 249     }
 250 
 251     /**
 252      * Build the data section. Can only be called after {@link #finalizeLayout}.


 253      *
 254      * @param buffer The {@link ByteBuffer} where the data section should be built. The buffer must
 255      *            hold at least {@link #getSectionSize()} bytes.
 256      * @param patch A {@link Consumer} to receive {@link DataPatch data patches} for relocations in
 257      *            the data section.
 258      */
 259     public void buildDataSection(ByteBuffer buffer, Consumer<DataPatch> patch) {
 260         assert finalLayout;
 261         for (Data d : dataItems) {
 262             buffer.position(d.ref.getOffset());
 263             d.builder.emit(buffer, patch);
 264         }
 265     }
 266 
 267     public Data findData(DataSectionReference ref) {
 268         for (Data d : dataItems) {
 269             if (d.ref == ref) {
 270                 return d;
 271             }
 272         }
 273         return null;
 274     }
 275 
 276     public Iterator<Data> iterator() {
 277         return dataItems.iterator();
 278     }
 279 
 280     public static int lcm(int x, int y) {


 283         } else if (y == 0) {
 284             return x;
 285         }
 286 
 287         int a = Math.max(x, y);
 288         int b = Math.min(x, y);
 289         while (b > 0) {
 290             int tmp = a % b;
 291             a = b;
 292             b = tmp;
 293         }
 294 
 295         int gcd = a;
 296         return x * y / gcd;
 297     }
 298 
 299     private static int align(int position, int alignment) {
 300         return ((position + alignment - 1) / alignment) * alignment;
 301     }
 302 












 303     public void clear() {
 304         assert !finalLayout;
 305         this.dataItems.clear();
 306         this.sectionAlignment = 0;
 307         this.sectionSize = 0;
 308     }
 309 }


 124         }
 125 
 126         @Override
 127         public boolean equals(Object obj) {
 128             assert ref != null;
 129             if (obj == this) {
 130                 return true;
 131             }
 132             if (obj instanceof Data) {
 133                 Data that = (Data) obj;
 134                 if (this.alignment == that.alignment && this.size == that.size && this.ref.equals(that.ref)) {
 135                     return true;
 136                 }
 137             }
 138             return false;
 139         }
 140     }
 141 
 142     private final ArrayList<Data> dataItems = new ArrayList<>();
 143 
 144     private boolean closed;
 145     private int sectionAlignment;
 146     private int sectionSize;
 147 
 148     @Override
 149     public int hashCode() {
 150         // DataSection instances should not be used as hash map keys
 151         throw new UnsupportedOperationException("hashCode");
 152     }
 153 
 154     @Override
 155     public String toString() {
 156         return identityHashCodeString(this);
 157     }
 158 
 159     @Override
 160     public boolean equals(Object obj) {
 161         if (this == obj) {
 162             return true;
 163         }
 164         if (obj instanceof DataSection) {
 165             DataSection that = (DataSection) obj;
 166             if (this.closed == that.closed && this.sectionAlignment == that.sectionAlignment && this.sectionSize == that.sectionSize && Objects.equals(this.dataItems, that.dataItems)) {
 167                 return true;
 168             }
 169         }
 170         return false;
 171     }
 172 
 173     /**
 174      * Inserts a {@link Data} item into the data section. If the item is already in the data
 175      * section, the same {@link DataSectionReference} is returned.
 176      *
 177      * @param data the {@link Data} item to be inserted
 178      * @return a unique {@link DataSectionReference} identifying the {@link Data} item
 179      */
 180     public DataSectionReference insertData(Data data) {
 181         checkOpen();
 182         synchronized (data) {
 183             if (data.ref == null) {
 184                 data.ref = new DataSectionReference();
 185                 dataItems.add(data);
 186             }
 187             return data.ref;
 188         }
 189     }
 190 
 191     /**
 192      * Transfers all {@link Data} from the provided other {@link DataSection} to this
 193      * {@link DataSection}, and empties the other section.
 194      */
 195     public void addAll(DataSection other) {
 196         checkOpen();
 197         other.checkOpen();
 198 
 199         for (Data data : other.dataItems) {
 200             assert data.ref != null;
 201             dataItems.add(data);
 202         }
 203         other.dataItems.clear();
 204     }
 205 
 206     /**
 207      * Determines if this object has been {@link #close() closed}.

 208      */
 209     public boolean closed() {
 210         return closed;
 211     }
 212 
 213     /**
 214      * Computes the layout of the data section and closes this object to further updates.
 215      *
 216      * This must be called exactly once.
 217      */
 218     void close() {
 219         checkOpen();
 220         closed = true;
 221 
 222         // simple heuristic: put items with larger alignment requirement first
 223         dataItems.sort((a, b) -> a.alignment - b.alignment);
 224 
 225         int position = 0;
 226         int alignment = 1;
 227         for (Data d : dataItems) {
 228             alignment = lcm(alignment, d.alignment);
 229             position = align(position, d.alignment);
 230 
 231             d.ref.setOffset(position);
 232             position += d.size;
 233         }
 234 
 235         sectionAlignment = alignment;
 236         sectionSize = position;
 237     }
 238 




 239     /**
 240      * Gets the size of the data section.
 241      *
 242      * This must only be called once this object has been {@linkplain #closed() closed}.
 243      */
 244     public int getSectionSize() {
 245         checkClosed();
 246         return sectionSize;
 247     }
 248 
 249     /**
 250      * Gets the minimum alignment requirement of the data section.
 251      *
 252      * This must only be called once this object has been {@linkplain #closed() closed}.
 253      */
 254     public int getSectionAlignment() {
 255         checkClosed();
 256         return sectionAlignment;
 257     }
 258 
 259     /**
 260      * Builds the data section into a given buffer.
 261      *
 262      * This must only be called once this object has been {@linkplain #closed() closed}.
 263      *
 264      * @param buffer the {@link ByteBuffer} where the data section should be built. The buffer must
 265      *            hold at least {@link #getSectionSize()} bytes.
 266      * @param patch a {@link Consumer} to receive {@link DataPatch data patches} for relocations in
 267      *            the data section
 268      */
 269     public void buildDataSection(ByteBuffer buffer, Consumer<DataPatch> patch) {
 270         checkClosed();
 271         for (Data d : dataItems) {
 272             buffer.position(d.ref.getOffset());
 273             d.builder.emit(buffer, patch);
 274         }
 275     }
 276 
 277     public Data findData(DataSectionReference ref) {
 278         for (Data d : dataItems) {
 279             if (d.ref == ref) {
 280                 return d;
 281             }
 282         }
 283         return null;
 284     }
 285 
 286     public Iterator<Data> iterator() {
 287         return dataItems.iterator();
 288     }
 289 
 290     public static int lcm(int x, int y) {


 293         } else if (y == 0) {
 294             return x;
 295         }
 296 
 297         int a = Math.max(x, y);
 298         int b = Math.min(x, y);
 299         while (b > 0) {
 300             int tmp = a % b;
 301             a = b;
 302             b = tmp;
 303         }
 304 
 305         int gcd = a;
 306         return x * y / gcd;
 307     }
 308 
 309     private static int align(int position, int alignment) {
 310         return ((position + alignment - 1) / alignment) * alignment;
 311     }
 312 
 313     private void checkClosed() {
 314         if (!closed) {
 315             throw new IllegalStateException();
 316         }
 317     }
 318 
 319     private void checkOpen() {
 320         if (closed) {
 321             throw new IllegalStateException();
 322         }
 323     }
 324 
 325     public void clear() {
 326         checkOpen();
 327         this.dataItems.clear();
 328         this.sectionAlignment = 0;
 329         this.sectionSize = 0;
 330     }
 331 }