< prev index next >
src/java.base/share/classes/jdk/internal/jimage/BasicImageWriter.java
Print this page
*** 23,250 ****
* questions.
*/
package jdk.internal.jimage;
- import java.io.PrintStream;
import java.nio.ByteOrder;
import java.util.ArrayList;
- import java.util.Arrays;
import java.util.List;
public final class BasicImageWriter {
private final static int RETRY_LIMIT = 1000;
private ByteOrder byteOrder;
! private ImageStrings strings;
! private int count;
private int[] redirect;
! private ImageLocation[] locations;
! private List<ImageLocation> input;
private ImageStream headerStream;
private ImageStream redirectStream;
private ImageStream locationOffsetStream;
private ImageStream locationStream;
private ImageStream allIndexStream;
- static class ImageBucket implements Comparable<ImageBucket> {
- final List<ImageLocation> list;
-
- ImageBucket() {
- this.list = new ArrayList<>();
- }
-
- void add(ImageLocation location) {
- list.add(location);
- }
-
- int getSize() {
- return list.size();
- }
-
- List<ImageLocation> getList() {
- return list;
- }
-
- ImageLocation getFirst() {
- assert !list.isEmpty() : "bucket should never be empty";
- return list.get(0);
- }
-
- @Override
- public int hashCode() {
- return getFirst().hashCode();
- }
-
- @Override
- public boolean equals(Object obj) {
- return this == obj;
- }
-
- @Override
- public int compareTo(ImageBucket o) {
- return o.getSize() - getSize();
- }
- }
-
public BasicImageWriter() {
this(ByteOrder.nativeOrder());
}
public BasicImageWriter(ByteOrder byteOrder) {
this.byteOrder = byteOrder;
this.input = new ArrayList<>();
! this.strings = new ImageStrings();
this.headerStream = new ImageStream(byteOrder);
this.redirectStream = new ImageStream(byteOrder);
this.locationOffsetStream = new ImageStream(byteOrder);
this.locationStream = new ImageStream(byteOrder);
this.allIndexStream = new ImageStream(byteOrder);
}
public int addString(String string) {
return addString(new UTF8String(string));
}
public int addString(UTF8String string) {
return strings.add(string);
}
! public void addLocation(String fullname, long contentOffset, long compressedSize, long uncompressedSize) {
! ImageLocation location = ImageLocation.newLocation(new UTF8String(fullname), strings, contentOffset, compressedSize, uncompressedSize);
! input.add(location);
! count++;
}
! private void generatePerfectHash() {
! redo:
! while(true) {
! redirect = new int[count];
! locations = new ImageLocation[count];
!
! ImageBucket[] sorted = createBuckets();
!
! int free = 0;
!
! for (ImageBucket bucket : sorted) {
! if (bucket.getSize() != 1) {
! if (!packCollidedEntries(bucket, count)) {
! count = (count + 1) | 1;
!
! continue redo;
! }
! } else {
! for ( ; free < count && locations[free] != null; free++) {}
! assert free < count : "no free slots";
! locations[free] = bucket.getFirst();
! redirect[bucket.hashCode() % count] = -1 - free;
! free++;
! }
! }
!
! break;
! }
}
! private ImageBucket[] createBuckets() {
! ImageBucket[] buckets = new ImageBucket[count];
!
! input.stream().forEach((location) -> {
! int index = location.hashCode() % count;
! ImageBucket bucket = buckets[index];
!
! if (bucket == null) {
! buckets[index] = bucket = new ImageBucket();
}
! bucket.add(location);
! });
!
! ImageBucket[] sorted = Arrays.asList(buckets).stream()
! .filter((bucket) -> (bucket != null))
! .sorted()
! .toArray(ImageBucket[]::new);
!
! return sorted;
}
! private boolean packCollidedEntries(ImageBucket bucket, int count) {
! List<Integer> undo = new ArrayList<>();
! int base = UTF8String.HASH_MULTIPLIER + 1;
!
! int retry = 0;
!
! redo:
! while (true) {
! for (ImageLocation location : bucket.getList()) {
! int index = location.hashCode(base) % count;
! if (locations[index] != null) {
! undo.stream().forEach((i) -> {
! locations[i] = null;
});
! undo.clear();
! base++;
! if (base == 0) {
! base = 1;
! }
! if (++retry > RETRY_LIMIT) {
! return false;
}
-
- continue redo;
- }
-
- locations[index] = location;
- undo.add(index);
- }
-
- redirect[bucket.hashCode() % count] = base;
-
- break;
- }
-
- return true;
}
private void prepareStringBytes() {
strings.getStream().align(2);
}
private void prepareRedirectBytes() {
! for (int i = 0; i < count; i++) {
redirectStream.putInt(redirect[i]);
}
}
private void prepareLocationBytes() {
// Reserve location offset zero for empty locations
! locationStream.put(ImageLocation.ATTRIBUTE_END << 3);
! for (int i = 0; i < count; i++) {
! ImageLocation location = locations[i];
if (location != null) {
location.writeTo(locationStream);
}
}
locationStream.align(2);
}
private void prepareOffsetBytes() {
! for (int i = 0; i < count; i++) {
! ImageLocation location = locations[i];
! locationOffsetStream.putInt(location != null ? location.getLocationOffset() : 0);
}
}
private void prepareHeaderBytes() {
! ImageHeader header = new ImageHeader(count, locationStream.getSize(), strings.getSize());
header.writeTo(headerStream);
}
private void prepareTableBytes() {
allIndexStream.put(headerStream);
--- 23,163 ----
* questions.
*/
package jdk.internal.jimage;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.List;
public final class BasicImageWriter {
+
+ public static final String IMAGE_EXT = ".jimage";
+ public static final String BOOT_NAME = "bootmodules";
+ public static final String BOOT_IMAGE_NAME = BOOT_NAME + IMAGE_EXT;
+
private final static int RETRY_LIMIT = 1000;
private ByteOrder byteOrder;
! private ImageStringsWriter strings;
! private int length;
private int[] redirect;
! private ImageLocationWriter[] locations;
! private List<ImageLocationWriter> input;
private ImageStream headerStream;
private ImageStream redirectStream;
private ImageStream locationOffsetStream;
private ImageStream locationStream;
private ImageStream allIndexStream;
public BasicImageWriter() {
this(ByteOrder.nativeOrder());
}
public BasicImageWriter(ByteOrder byteOrder) {
this.byteOrder = byteOrder;
this.input = new ArrayList<>();
! this.strings = new ImageStringsWriter();
this.headerStream = new ImageStream(byteOrder);
this.redirectStream = new ImageStream(byteOrder);
this.locationOffsetStream = new ImageStream(byteOrder);
this.locationStream = new ImageStream(byteOrder);
this.allIndexStream = new ImageStream(byteOrder);
}
+ public ByteOrder getByteOrder() {
+ return byteOrder;
+ }
+
public int addString(String string) {
return addString(new UTF8String(string));
}
public int addString(UTF8String string) {
return strings.add(string);
}
! public String getString(int offset) {
! UTF8String utf8 = strings.get(offset);
! return utf8 != null? utf8.toString() : null;
}
! public void addLocation(String fullname, long contentOffset,
! long compressedSize, long uncompressedSize) {
! ImageLocationWriter location =
! ImageLocationWriter.newLocation(new UTF8String(fullname), strings,
! contentOffset, compressedSize, uncompressedSize);
! input.add(location);
! length++;
}
! ImageLocationWriter[] getLocations() {
! return locations;
}
! int getLocationsCount() {
! return input.size();
}
! private void generatePerfectHash() {
! PerfectHashBuilder<ImageLocationWriter> builder =
! new PerfectHashBuilder<>(
! new PerfectHashBuilder.Entry<ImageLocationWriter>().getClass(),
! new PerfectHashBuilder.Bucket<ImageLocationWriter>().getClass());
! input.forEach((location) -> {
! builder.put(location.getFullName(), location);
});
! builder.generate();
! length = builder.getCount();
! redirect = builder.getRedirect();
! PerfectHashBuilder.Entry<ImageLocationWriter>[] order = builder.getOrder();
! locations = new ImageLocationWriter[length];
! for (int i = 0; i < length; i++) {
! locations[i] = order[i].getValue();
}
}
private void prepareStringBytes() {
strings.getStream().align(2);
}
private void prepareRedirectBytes() {
! for (int i = 0; i < length; i++) {
redirectStream.putInt(redirect[i]);
}
}
private void prepareLocationBytes() {
// Reserve location offset zero for empty locations
! locationStream.put(ImageLocationWriter.ATTRIBUTE_END << 3);
! for (int i = 0; i < length; i++) {
! ImageLocationWriter location = locations[i];
if (location != null) {
location.writeTo(locationStream);
}
}
locationStream.align(2);
}
private void prepareOffsetBytes() {
! for (int i = 0; i < length; i++) {
! ImageLocationWriter location = locations[i];
! int offset = location != null ? location.getLocationOffset() : 0;
! locationOffsetStream.putInt(offset);
}
}
private void prepareHeaderBytes() {
! ImageHeader header = new ImageHeader(input.size(), length,
! locationStream.getSize(), strings.getSize());
header.writeTo(headerStream);
}
private void prepareTableBytes() {
allIndexStream.put(headerStream);
*** 266,300 ****
}
return allIndexStream.toArray();
}
! ImageLocation find(UTF8String key) {
! int index = key.hashCode() % count;
! index = redirect[index];
if (index < 0) {
index = -index - 1;
- ImageLocation location = locations[index];
-
- return location;
} else {
! index = key.hashCode(index) % count;
! ImageLocation location = locations[index];
!
! return location;
! }
}
! public void statistics() {
! getBytes();
! PrintStream out = System.out;
! out.println("Count: " + count);
! out.println("Header bytes size: " + headerStream.getSize());
! out.println("Redirect bytes size: " + redirectStream.getSize());
! out.println("Offset bytes size: " + locationOffsetStream.getSize());
! out.println("Location bytes size: " + locationStream.getSize());
! out.println("String count: " + strings.getCount());
! out.println("String bytes size: " + strings.getSize());
! out.println("Total bytes size: " + allIndexStream.getSize());
}
}
--- 179,195 ----
}
return allIndexStream.toArray();
}
! ImageLocationWriter find(UTF8String key) {
! int index = redirect[key.hashCode() % length];
if (index < 0) {
index = -index - 1;
} else {
! index = key.hashCode(index) % length;
}
! return locations[index];
}
}
< prev index next >