Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#392 Move Class-Initialization Status into data-segment #393

Merged
merged 5 commits into from
May 1, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,11 @@

import de.mirkosertic.bytecoder.api.EmulatedByRuntime;
import de.mirkosertic.bytecoder.api.Export;
import de.mirkosertic.bytecoder.api.Import;

import java.lang.invoke.ConstantCallSite;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodType;
import java.text.DecimalFormatSymbols;
import java.util.Comparator;
import java.util.Locale;

public class VM {
Expand Down Expand Up @@ -204,8 +202,6 @@ public static void setClassMember(final Class clz, final String name, final Obje

public static final char NEWLINE = '\n';

public static Comparator DEFAULT = (o1, o2) -> ((Comparable) o1).compareTo(o2);

public static long stringToLong(final String aString) {
long theResult = 0;
int theMultiplier = 1;
Expand Down Expand Up @@ -294,7 +290,4 @@ public static Locale defaultLocale() {

@EmulatedByRuntime
public static native boolean reinterpretAsBoolean(final Object o);

@Import(module = "env", name = "debug")
public static native void debug(int aValue);
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,37 @@ static <T> int partition(final T[] array, final int begin, final int end, final
return counter;
}

static <T> int partitionComparable(final T[] array, final int begin, final int end) {
final int pivot = end;

int counter = begin;
for (int i = begin; i < end; i++) {
if (((Comparable) array[i]).compareTo(array[pivot]) < 0) {
final T temp = array[counter];
array[counter] = array[i];
array[i] = temp;
counter++;
}
}
final T temp = array[pivot];
array[pivot] = array[counter];
array[counter] = temp;

return counter;
}

public static <T> void quickSort(final T[] array, final int begin, final int end, final Comparator<T> comparator) {
if (end <= begin) return;
final int pivot = partition(array, begin, end, comparator);
quickSort(array, begin, pivot-1, comparator);
quickSort(array, pivot+1, end, comparator);
}

public static <T> void quickSortComparable(final T[] array, final int begin, final int end) {
if (end <= begin) return;
final int pivot = partitionComparable(array, begin, end);
quickSortComparable(array, begin, pivot-1);
quickSortComparable(array, pivot+1, end);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
public class TArrays {

public static <T> void sort(final T[] aData, final int aStart, final int aEnd) {
Quicksort.quickSort(aData, aStart, aEnd, VM.DEFAULT);
Quicksort.quickSortComparable(aData, aStart, aEnd);
}

public static <T> void sort(final T[] aData, final int aStart, final int aEnd, final Comparator<T> c) {
Expand All @@ -39,7 +39,7 @@ public static <T> void sort(final T[] aData, final Comparator<T> c) {
}

public static <T> void sort(final T[] aData) {
Quicksort.quickSort(aData, 0, aData.length - 1, VM.DEFAULT);
Quicksort.quickSortComparable(aData, 0, aData.length - 1);
}

public static <T> List<T> asList(final T... aValues) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,9 @@
import de.mirkosertic.bytecoder.classlib.Address;
import de.mirkosertic.bytecoder.classlib.Array;
import de.mirkosertic.bytecoder.classlib.MemoryManager;
import de.mirkosertic.bytecoder.classlib.VM;
import de.mirkosertic.bytecoder.classlib.java.util.Quicksort;
import de.mirkosertic.bytecoder.core.BytecodeAnnotation;
import de.mirkosertic.bytecoder.core.BytecodeClass;
import de.mirkosertic.bytecoder.core.BytecodeImportedLink;
import de.mirkosertic.bytecoder.core.BytecodeLinkedClass;
import de.mirkosertic.bytecoder.core.BytecodeLinkerContext;
Expand Down Expand Up @@ -77,10 +78,12 @@
public class LLVMCompilerBackend implements CompileBackend<LLVMCompileResult> {

private static class CallSite {
private final BytecodeLinkedClass owningClass;
private final Program program;
private final RegionNode bootstrapMethod;

private CallSite(final Program aProgram, final RegionNode aBootstrapMethod) {
private CallSite(final BytecodeLinkedClass aOwningClass, final Program aProgram, final RegionNode aBootstrapMethod) {
this.owningClass = aOwningClass;
this.program = aProgram;
this.bootstrapMethod = aBootstrapMethod;
}
Expand Down Expand Up @@ -150,10 +153,10 @@ public String globalFromStringPool(final String aValue) {
}

@Override
public String resolveCallsiteBootstrapFor(final BytecodeClass owningClass, final String callsiteId, final Program program, final RegionNode bootstrapMethod) {
public String resolveCallsiteBootstrapFor(final BytecodeLinkedClass owningClass, final String callsiteId, final Program program, final RegionNode bootstrapMethod) {
CallSite callSite = callsites.get(callsiteId);
if (callSite == null) {
callSite = new CallSite(program, bootstrapMethod);
callSite = new CallSite(owningClass, program, bootstrapMethod);
callsites.put(callsiteId, callSite);
}
return "resolvecallsite" + System.identityHashCode(callSite);
Expand Down Expand Up @@ -796,6 +799,12 @@ public String methodHandleDelegateFor(final MethodHandleExpression e) {
pw.println(" = private global i32 0");
pw.println();

pw.print("@");
pw.print(theClassName);
pw.print(LLVMWriter.RUNTIMECLASSINITSTATUSSUFFIX);
pw.println(" = private global i32 0");
pw.println();

if (theLinkedClass != theClassLinkedCass) {
final BytecodeVTable theVtable = theSymbolResolver.vtableFor(theLinkedClass);
final List<BytecodeVTable.Slot> theSlots = theVtable.sortedSlots();
Expand Down Expand Up @@ -890,13 +899,15 @@ public String methodHandleDelegateFor(final MethodHandleExpression e) {
pw.print(" %class = load i32, i32* @");
pw.print(theClassName);
pw.println(LLVMWriter.RUNTIMECLASSSUFFIX);
pw.println(" %status = add i32 %class, 8");
pw.println(" %statusptr = inttoptr i32 %status to i32*");
pw.println(" %value = load i32, i32* %statusptr");
pw.print(" %value = load i32, i32* @");
pw.print(theClassName);
pw.println(LLVMWriter.RUNTIMECLASSINITSTATUSSUFFIX);
pw.println(" %initialized_compare = icmp eq i32 %value, 1");
pw.println(" br i1 %initialized_compare, label %done, label %unitialized");
pw.println("unitialized:");
pw.println(" store i32 1,i32* %statusptr");
pw.print(" store i32 1,i32* @");
pw.print(theClassName);
pw.println(LLVMWriter.RUNTIMECLASSINITSTATUSSUFFIX);

// Call superclass init
if (!theLinkedClass.getClassName().name().equals(Object.class.getName())) {
Expand Down Expand Up @@ -1242,7 +1253,7 @@ public String methodHandleDelegateFor(final MethodHandleExpression e) {
}

try (final LLVMWriter theWriter = new LLVMWriter(pw, memoryLayouter, aLinkerContext, theSymbolResolver)) {
theWriter.write(theSSAProgram, subProgram);
theWriter.write(theLinkedClass, theSSAProgram, subProgram);
}

pw.println("}");
Expand Down Expand Up @@ -1351,7 +1362,7 @@ public String methodHandleDelegateFor(final MethodHandleExpression e) {
final LLVMDebugInformation.SubProgram subProgram = compileUnit.subProgram(theSSAProgram, "/resolvecallsite" + callsite, new BytecodeMethodSignature(BytecodePrimitiveTypeRef.INT, new BytecodeTypeRef[0]));

// Run optimizer
// We use a special LLVM optimizer, which does only stuff LLVM CANNOT do, such
// We use a special optimizer, which does only stuff LLVM CANNOT do, such
// as virtual method invocation optimization. All other optimization work
// is done by LLVM!
KnownOptimizer.LLVM.optimize(theSSAProgram.getControlFlowGraph(), aLinkerContext);
Expand Down Expand Up @@ -1383,7 +1394,7 @@ public String methodHandleDelegateFor(final MethodHandleExpression e) {
pw.println(" {");

try (final LLVMWriter theWriter = new LLVMWriter(pw, memoryLayouter, aLinkerContext, theSymbolResolver)) {
theWriter.write(theEntry.getValue().program, subProgram);
theWriter.write(theEntry.getValue().owningClass, theEntry.getValue().program, subProgram);
}

pw.println("}");
Expand Down Expand Up @@ -1579,6 +1590,24 @@ public String methodHandleDelegateFor(final MethodHandleExpression e) {
pw.println(i);
}

// Some initialization logic
aLinkerContext.linkedClasses()
.map(t -> t.targetNode())
.filter(t -> {
if (t.getClassName().name().equals(VM.class.getName()) ||
t.getClassName().name().equals(Quicksort.class.getName())) {
return true;
}
return false;
}).forEach(theClass -> {
pw.print(" %");
pw.print(LLVMWriterUtils.runtimeClassVariableName(theClass.getClassName()));
pw.print(" = call i32 @");
pw.print(LLVMWriterUtils.toClassName(theClass.getClassName()));
pw.print(LLVMWriter.CLASSINITSUFFIX);
pw.println("()");
});

pw.println(" ret void");
pw.println("}");
pw.println();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
import de.mirkosertic.bytecoder.backend.NativeMemoryLayouter;
import de.mirkosertic.bytecoder.classlib.Array;
import de.mirkosertic.bytecoder.classlib.MemoryManager;
import de.mirkosertic.bytecoder.core.BytecodeClass;
import de.mirkosertic.bytecoder.classlib.VM;
import de.mirkosertic.bytecoder.classlib.java.util.Quicksort;
import de.mirkosertic.bytecoder.core.BytecodeLinkedClass;
import de.mirkosertic.bytecoder.core.BytecodeLinkerContext;
import de.mirkosertic.bytecoder.core.BytecodeMethod;
Expand Down Expand Up @@ -132,6 +133,7 @@ public class LLVMWriter implements AutoCloseable {

public static final String INSTANCEOFSUFFIX = "__instanceof";
public static final String RUNTIMECLASSSUFFIX = "__runtimeclass";
public static final String RUNTIMECLASSINITSTATUSSUFFIX = "__runtimeclassinitstatus";
public static final String NEWINSTANCE_METHOD_NAME = "$newInstance";
public static final String CLASSINITSUFFIX = "__init";
public static final String VTABLESUFFIX = "__vtable";
Expand All @@ -143,7 +145,7 @@ interface SymbolResolver {

String globalFromStringPool(final String aValue);

String resolveCallsiteBootstrapFor(BytecodeClass owningClass, String callsiteId, Program program, RegionNode bootstrapMethod);
String resolveCallsiteBootstrapFor(BytecodeLinkedClass owningClass, String callsiteId, Program program, RegionNode bootstrapMethod);

String methodTypeFactoryNameFor(final BytecodeMethodSignature aSignature);

Expand Down Expand Up @@ -220,7 +222,7 @@ private List<PHIValuePair> phiValuePairFor(final RegionNode aTarget, final PHIVa
return theResult;
}

public void write(final Program aProgram, final LLVMDebugInformation.SubProgram aSubProgram) {
public void write(final BytecodeLinkedClass aOwningClass, final Program aProgram, final LLVMDebugInformation.SubProgram aSubProgram) {
final ControlFlowGraph theGraph = aProgram.getControlFlowGraph();
final RegionNode theStart = theGraph.startNode();
final GraphDFSOrder<RegionNode> order = new GraphDFSOrder(theStart,
Expand All @@ -238,10 +240,25 @@ public void write(final Program aProgram, final LLVMDebugInformation.SubProgram
if (!theClass.getClassName().name().equals(MemoryManager.class.getName())) {
target.print(" %");
target.print(LLVMWriterUtils.runtimeClassVariableName(theClass.getClassName()));
target.print(" = call i32 @");
target.print(LLVMWriterUtils.toClassName(theClass.getClassName()));
target.print(LLVMWriter.CLASSINITSUFFIX);
target.println("()");
// We know the following JVM classes were initialized by the bootstrap,
// so we can safely access them without init invocation
if (theClass.getClassName().name().equals(String.class.getName()) ||
theClass.getClassName().name().equals(Array.class.getName()) ||
theClass.getClassName().name().equals(VM.class.getName()) ||
theClass.getClassName().name().equals(Quicksort.class.getName())) {

aProgram.getLinkerContext().getStatistics().context("ClassInitialization")
.counter("Avoided initializations").increment();

target.print(" = load i32, i32* @");
target.print(LLVMWriterUtils.toClassName(theClass.getClassName()));
target.println(LLVMWriter.RUNTIMECLASSSUFFIX);
} else {
target.print(" = call i32 @");
target.print(LLVMWriterUtils.toClassName(theClass.getClassName()));
target.print(LLVMWriter.CLASSINITSUFFIX);
target.println("()");
}
}
}

Expand Down Expand Up @@ -1800,8 +1817,9 @@ private void write(final FloatingPointCeilExpression e) {
}

private void write(final ResolveCallsiteObjectExpression e) {
final BytecodeLinkedClass theOwningClass = linkerContext.resolveClass(BytecodeObjectTypeRef.fromUtf8Constant(e.getOwningClass().getThisInfo().getConstant()));
target.print("call i32 @");
target.print(symbolResolver.resolveCallsiteBootstrapFor(e.getOwningClass(),
target.print(symbolResolver.resolveCallsiteBootstrapFor(theOwningClass,
e.getCallsiteId(),
e.getProgram(),
e.getBootstrapMethod()
Expand Down