Skip to content

Commit

Permalink
#160 Replace Class assertionStatus Management with Intrinsic (#164)
Browse files Browse the repository at this point in the history
* #160 Replace Class assertionStatus Management with Intrinsic
  • Loading branch information
mirkosertic authored Jun 14, 2019
1 parent 6d30c0f commit d128d96
Show file tree
Hide file tree
Showing 9 changed files with 180 additions and 142 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -306,9 +306,7 @@ public JSCompileResult generateCodeFor(final CompileOptions aOptions, final Byte

theWriter.text("};").newLine();

final String theGetClassMethodName = theMinifier.toMethodName("getClass", new BytecodeMethodSignature(BytecodeObjectTypeRef.fromRuntimeClass(Class.class), new BytecodeTypeRef[0]));
final String theGetNameMethodName = theMinifier.toMethodName("getName", new BytecodeMethodSignature(BytecodeObjectTypeRef.fromRuntimeClass(String.class), new BytecodeTypeRef[0]));
final String theDesiredAssertionStatusMethodName = theMinifier.toMethodName("desiredAssertionStatus", new BytecodeMethodSignature(BytecodePrimitiveTypeRef.BOOLEAN, new BytecodeTypeRef[0]));
final String theGetEnumConstantsMethodName = theMinifier.toMethodName("getEnumConstants", new BytecodeMethodSignature(new BytecodeArrayTypeRef(BytecodeObjectTypeRef.fromRuntimeClass(Object.class),1), new BytecodeTypeRef[0]));

final ConstantPool thePool = new ConstantPool();
Expand Down Expand Up @@ -342,16 +340,18 @@ public JSCompileResult generateCodeFor(final CompileOptions aOptions, final Byte
final BytecodeResolvedFields theStaticFields = theLinkedClass.resolvedFields();
theStaticFields.streamForStaticFields().forEach(
aFieldEntry -> {
final BytecodeTypeRef theFieldType = aFieldEntry.getValue().getTypeRef();
if (theFieldType.isPrimitive()) {
final BytecodePrimitiveTypeRef thePrimitive = (BytecodePrimitiveTypeRef) theFieldType;
if (thePrimitive == BytecodePrimitiveTypeRef.BOOLEAN) {
theWriter.tab().symbol(aFieldEntry.getValue().getName().stringValue(), null).colon().text("false,").newLine();
if (!"$assertionsDisabled".equals(aFieldEntry.getValue().getName().stringValue())) {
final BytecodeTypeRef theFieldType = aFieldEntry.getValue().getTypeRef();
if (theFieldType.isPrimitive()) {
final BytecodePrimitiveTypeRef thePrimitive = (BytecodePrimitiveTypeRef) theFieldType;
if (thePrimitive == BytecodePrimitiveTypeRef.BOOLEAN) {
theWriter.tab().symbol(aFieldEntry.getValue().getName().stringValue(), null).colon().text("false,").newLine();
} else {
theWriter.tab().symbol(aFieldEntry.getValue().getName().stringValue(), null).colon().text("0,").newLine();
}
} else {
theWriter.tab().symbol(aFieldEntry.getValue().getName().stringValue(), null).colon().text("0,").newLine();
theWriter.tab().symbol(aFieldEntry.getValue().getName().stringValue(), null).colon().text("null,").newLine();
}
} else {
theWriter.tab().symbol(aFieldEntry.getValue().getName().stringValue(), null).colon().text("null,").newLine();
}
});

Expand Down Expand Up @@ -383,10 +383,6 @@ public JSCompileResult generateCodeFor(final CompileOptions aOptions, final Byte
theWriter.tab(2).text("return ").text(theJSClassName).text(".__implementedTypes.includes(aType.__typeId);").newLine();
theWriter.tab().text("},").newLine();

theWriter.tab().text(theGetClassMethodName).colon().text("function()").space().text("{").newLine();
theWriter.tab(2).text("return ").text(theJSClassName).text(";").newLine();
theWriter.tab().text("},").newLine();

theWriter.tab().text(theGetNameMethodName).colon().text("function(_tr)").space().text("{").newLine();
if (!theLinkedClass.getClassName().name().equals("java.lang.Class")) {
theWriter.tab(2).text("return bytecoder.stringpool[").text("" + thePool.register(new StringValue(ConstantPool.simpleClassName(theLinkedClass.getClassName().name())))).text("];").newLine();
Expand All @@ -395,10 +391,6 @@ public JSCompileResult generateCodeFor(final CompileOptions aOptions, final Byte
}
theWriter.tab().text("},").newLine();

theWriter.tab().text(theDesiredAssertionStatusMethodName).colon().text("function()").space().text("{").newLine();
theWriter.tab(2).text("return false;").newLine();
theWriter.tab().text("},").newLine();

theWriter.tab().text(theGetEnumConstantsMethodName).colon().text("function(aClazz)").space().text("{").newLine();
theWriter.tab(2).text("return aClazz.").symbol("$VALUES", null).text(";").newLine();
theWriter.tab().text("},").newLine();
Expand Down Expand Up @@ -542,7 +534,7 @@ public JSCompileResult generateCodeFor(final CompileOptions aOptions, final Byte
// Only in case this class can be instantiated of course
theWriter.tab(2).text("var p").assign().text(theJSClassName).text(".C.prototype;").newLine();
theWriter.tab(2).text("p.iof").assign().text(theJSClassName).text(".iof;").newLine();
theWriter.tab(2).text("p.").text(theGetClassMethodName).assign().text(theJSClassName).text(".").text(theGetClassMethodName).text(";").newLine();
theWriter.tab(2).text("p.clz").assign().text(theJSClassName).text(";").newLine();

final List<BytecodeResolvedMethods.MethodEntry> theEntries = theMethods.stream().collect(Collectors.toList());
final Set<String> theVisitedMethods = new HashSet<>();
Expand All @@ -555,7 +547,9 @@ public JSCompileResult generateCodeFor(final CompileOptions aOptions, final Byte
if (!theMethod.getAccessFlags().isStatic() &&
!theMethod.getAccessFlags().isAbstract() &&
!theMethod.isConstructor() &&
!theMethod.isClassInitializer()) {
!theMethod.isClassInitializer() &&
!"desiredAssertionStatus".equals(theMethod.getName().stringValue()) &&
!"getClass".equals(theMethod.getName().stringValue())) {

if (theVisitedMethods.add(theMethodName)) {
theWriter.tab(2).text("p.").text(theMethodName).assign().text(theMinifier.toClassName(aEntry.getProvidingClass().getClassName())).text(".").text(theMethodName).text(";").newLine();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,101 +15,21 @@
*/
package de.mirkosertic.bytecoder.backend.js;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import de.mirkosertic.bytecoder.api.Import;
import de.mirkosertic.bytecoder.api.OpaqueIndexed;
import de.mirkosertic.bytecoder.api.OpaqueMethod;
import de.mirkosertic.bytecoder.api.OpaqueProperty;
import de.mirkosertic.bytecoder.backend.CompileOptions;
import de.mirkosertic.bytecoder.backend.ConstantPool;
import de.mirkosertic.bytecoder.classlib.Array;
import de.mirkosertic.bytecoder.core.BytecodeAnnotation;
import de.mirkosertic.bytecoder.core.BytecodeFieldRefConstant;
import de.mirkosertic.bytecoder.core.BytecodeLinkedClass;
import de.mirkosertic.bytecoder.core.BytecodeLinkerContext;
import de.mirkosertic.bytecoder.core.BytecodeMethod;
import de.mirkosertic.bytecoder.core.BytecodeMethodSignature;
import de.mirkosertic.bytecoder.core.BytecodeObjectTypeRef;
import de.mirkosertic.bytecoder.core.BytecodeOpcodeAddress;
import de.mirkosertic.bytecoder.core.BytecodeResolvedFields;
import de.mirkosertic.bytecoder.core.BytecodeResolvedMethods;
import de.mirkosertic.bytecoder.core.BytecodeTypeRef;
import de.mirkosertic.bytecoder.core.BytecodeUtf8Constant;
import de.mirkosertic.bytecoder.core.BytecodeVirtualMethodIdentifier;
import de.mirkosertic.bytecoder.core.*;
import de.mirkosertic.bytecoder.relooper.Relooper;
import de.mirkosertic.bytecoder.ssa.ArrayEntryExpression;
import de.mirkosertic.bytecoder.ssa.ArrayLengthExpression;
import de.mirkosertic.bytecoder.ssa.ArrayStoreExpression;
import de.mirkosertic.bytecoder.ssa.BinaryExpression;
import de.mirkosertic.bytecoder.ssa.BreakExpression;
import de.mirkosertic.bytecoder.ssa.ByteValue;
import de.mirkosertic.bytecoder.ssa.CheckCastExpression;
import de.mirkosertic.bytecoder.ssa.ClassReferenceValue;
import de.mirkosertic.bytecoder.ssa.CompareExpression;
import de.mirkosertic.bytecoder.ssa.ComputedMemoryLocationReadExpression;
import de.mirkosertic.bytecoder.ssa.ComputedMemoryLocationWriteExpression;
import de.mirkosertic.bytecoder.ssa.ContinueExpression;
import de.mirkosertic.bytecoder.ssa.CurrentExceptionExpression;
import de.mirkosertic.bytecoder.ssa.DebugPosition;
import de.mirkosertic.bytecoder.ssa.DirectInvokeMethodExpression;
import de.mirkosertic.bytecoder.ssa.DoubleValue;
import de.mirkosertic.bytecoder.ssa.Expression;
import de.mirkosertic.bytecoder.ssa.ExpressionList;
import de.mirkosertic.bytecoder.ssa.FixedBinaryExpression;
import de.mirkosertic.bytecoder.ssa.FloatValue;
import de.mirkosertic.bytecoder.ssa.FloatingPointCeilExpression;
import de.mirkosertic.bytecoder.ssa.FloatingPointFloorExpression;
import de.mirkosertic.bytecoder.ssa.FloorExpression;
import de.mirkosertic.bytecoder.ssa.GetFieldExpression;
import de.mirkosertic.bytecoder.ssa.GetStaticExpression;
import de.mirkosertic.bytecoder.ssa.GotoExpression;
import de.mirkosertic.bytecoder.ssa.IFExpression;
import de.mirkosertic.bytecoder.ssa.InstanceOfExpression;
import de.mirkosertic.bytecoder.ssa.IntegerValue;
import de.mirkosertic.bytecoder.ssa.InvokeStaticMethodExpression;
import de.mirkosertic.bytecoder.ssa.InvokeVirtualMethodExpression;
import de.mirkosertic.bytecoder.ssa.LongValue;
import de.mirkosertic.bytecoder.ssa.LookupSwitchExpression;
import de.mirkosertic.bytecoder.ssa.MaxExpression;
import de.mirkosertic.bytecoder.ssa.MemorySizeExpression;
import de.mirkosertic.bytecoder.ssa.MethodHandlesGeneratedLookupExpression;
import de.mirkosertic.bytecoder.ssa.MethodParameterValue;
import de.mirkosertic.bytecoder.ssa.MethodRefExpression;
import de.mirkosertic.bytecoder.ssa.MethodTypeExpression;
import de.mirkosertic.bytecoder.ssa.MinExpression;
import de.mirkosertic.bytecoder.ssa.NegatedExpression;
import de.mirkosertic.bytecoder.ssa.NewArrayExpression;
import de.mirkosertic.bytecoder.ssa.NewMultiArrayExpression;
import de.mirkosertic.bytecoder.ssa.NewObjectExpression;
import de.mirkosertic.bytecoder.ssa.NullValue;
import de.mirkosertic.bytecoder.ssa.Program;
import de.mirkosertic.bytecoder.ssa.PutFieldExpression;
import de.mirkosertic.bytecoder.ssa.PutStaticExpression;
import de.mirkosertic.bytecoder.ssa.RegionNode;
import de.mirkosertic.bytecoder.ssa.ResolveCallsiteObjectExpression;
import de.mirkosertic.bytecoder.ssa.ReturnExpression;
import de.mirkosertic.bytecoder.ssa.ReturnValueExpression;
import de.mirkosertic.bytecoder.ssa.RuntimeGeneratedTypeExpression;
import de.mirkosertic.bytecoder.ssa.SelfReferenceParameterValue;
import de.mirkosertic.bytecoder.ssa.SetMemoryLocationExpression;
import de.mirkosertic.bytecoder.ssa.ShortValue;
import de.mirkosertic.bytecoder.ssa.SqrtExpression;
import de.mirkosertic.bytecoder.ssa.StackTopExpression;
import de.mirkosertic.bytecoder.ssa.StringValue;
import de.mirkosertic.bytecoder.ssa.TableSwitchExpression;
import de.mirkosertic.bytecoder.ssa.ThrowExpression;
import de.mirkosertic.bytecoder.ssa.TypeConversionExpression;
import de.mirkosertic.bytecoder.ssa.TypeOfExpression;
import de.mirkosertic.bytecoder.ssa.TypeRef;
import de.mirkosertic.bytecoder.ssa.UnknownExpression;
import de.mirkosertic.bytecoder.ssa.UnreachableExpression;
import de.mirkosertic.bytecoder.ssa.Value;
import de.mirkosertic.bytecoder.ssa.Variable;
import de.mirkosertic.bytecoder.ssa.VariableAssignmentExpression;
import de.mirkosertic.bytecoder.ssa.*;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

public class JSSSAWriter {

Expand Down Expand Up @@ -269,7 +189,7 @@ private void print(final SqrtExpression aValue) {

private void print(final TypeOfExpression aValue) {
print(aValue.incomingDataFlows().get(0));
writer.text(".").text(minifier.toMethodName("getClass", new BytecodeMethodSignature(BytecodeObjectTypeRef.fromRuntimeClass(Class.class), new BytecodeTypeRef[0]))).text("()");
writer.text(".").text("clz");
}

private void print(final StackTopExpression aValue) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -235,9 +235,6 @@ public WASMCompileResult generateCodeFor(
classGetName.flow.ret(call(weakFunctionReference("STRINGPOOL_GLOBAL_BY_INDEX", null), theGetArguments, null), null);
}

final ExportableFunction classDesiredAssertionStatus = module.getFunctions().newFunction("jlClass_BOOLEANdesiredAssertionStatus", Collections.singletonList(param("thisRef", PrimitiveType.i32)), PrimitiveType.i32).toTable();
classDesiredAssertionStatus.flow.ret(i32.c(0, null), null);

final ConstantPool theConstantPool = new ConstantPool();

final Map<String, WASMSSAASTCompilerBackend.CallSite> theCallsites = new HashMap<>();
Expand Down Expand Up @@ -288,8 +285,6 @@ public Function resolveCallsiteBootstrapFor(final BytecodeClass owningClass, fin
block.flow.unreachable(null);
} else if (Objects.equals("hashCode", theMethod.getName().stringValue())) {
block.flow.unreachable(null);
} else if (Objects.equals("desiredAssertionStatus", theMethod.getName().stringValue())) {
block.flow.ret(i32.c(module.getTables().funcTable().indexOf(classDesiredAssertionStatus), null), null);
} else if (Objects.equals("getEnumConstants", theMethod.getName().stringValue())) {
block.flow.ret(i32.c(module.getTables().funcTable().indexOf(classGetEnumConstants), null), null);
} else {
Expand Down Expand Up @@ -413,7 +408,8 @@ public Function resolveCallsiteBootstrapFor(final BytecodeClass owningClass, fin
if (!theMethod.getAccessFlags().isStatic() &&
!theMethod.isConstructor() &&
!theMethod.getAccessFlags().isAbstract() &&
(theMethod != BytecodeLinkedClass.GET_CLASS_PLACEHOLDER)) {
(theMethod != BytecodeLinkedClass.GET_CLASS_PLACEHOLDER) &&
!"desiredAssertionStatus".equals(theMethod.getName().stringValue())) {

final BytecodeVirtualMethodIdentifier theMethodIdentifier = aLinkerContext.getMethodCollection()
.identifierFor(theMethod);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
public class BytecodeLinkedClass extends Node {

public static final BytecodeMethodSignature GET_CLASS_SIGNATURE = new BytecodeMethodSignature(BytecodeObjectTypeRef.fromRuntimeClass(Class.class), new BytecodeTypeRef[0]);
public static final BytecodeMethodSignature DESIRED_ASSERTION_STATUS_SIGNATURE = new BytecodeMethodSignature(BytecodePrimitiveTypeRef.BOOLEAN, new BytecodeTypeRef[0]);
public static final BytecodeMethod GET_CLASS_PLACEHOLDER = new BytecodeMethod(new BytecodeAccessFlags(0x0001), null, null, null) {
@Override
public BytecodeUtf8Constant getName() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,7 @@
*/
package de.mirkosertic.bytecoder.intrinsics;

import de.mirkosertic.bytecoder.core.BytecodeInstructionINVOKESPECIAL;
import de.mirkosertic.bytecoder.core.BytecodeInstructionINVOKESTATIC;
import de.mirkosertic.bytecoder.core.BytecodeObjectTypeRef;
import de.mirkosertic.bytecoder.core.*;
import de.mirkosertic.bytecoder.ssa.*;

import java.util.List;
Expand All @@ -35,4 +33,17 @@ public boolean intrinsify(final Program aProgram, final BytecodeInstructionINVOK
return false;
}

public boolean intrinsify(final Program aProgram, final BytecodeInstructionINVOKEVIRTUAL aInstruction, final String aMethodName,
final List<Value> aArguments,
final Value aTarget, final RegionNode aTargetBlock, final ParsingHelper aHelper) {
return false;
}

public boolean intrinsify(final Program aProgram, final BytecodeInstructionGETSTATIC aInstruction, final String aFieldName, final BytecodeObjectTypeRef aTtargetType, final RegionNode aTargetBlock, final ParsingHelper aHelper) {
return false;
}

public boolean intrinsify(final Program aProgram, final BytecodeInstructionPUTSTATIC aInstruction, final String aFieldName, final BytecodeObjectTypeRef aTtargetType, final Value aValue, final RegionNode aTargetBlock, final ParsingHelper aHelper) {
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,7 @@
*/
package de.mirkosertic.bytecoder.intrinsics;

import de.mirkosertic.bytecoder.core.BytecodeInstructionINVOKESPECIAL;
import de.mirkosertic.bytecoder.core.BytecodeInstructionINVOKESTATIC;
import de.mirkosertic.bytecoder.core.BytecodeObjectTypeRef;
import de.mirkosertic.bytecoder.core.*;
import de.mirkosertic.bytecoder.ssa.*;

import java.util.ArrayList;
Expand Down Expand Up @@ -65,4 +63,37 @@ public boolean intrinsify(final Program aProgram, final BytecodeInstructionINVOK
return false;
}

public boolean intrinsify(final Program aProgram, final BytecodeInstructionINVOKEVIRTUAL aInstruction,
final List<Value> aArguments,
final Value aTarget, final RegionNode aTargetBlock, final ParsingHelper aHelper) {
final String theMethodName = aInstruction.getMethodReference().getNameAndTypeIndex().getNameAndType().getNameIndex().getName().stringValue();
for (final Intrinsic intrinsic : intrinsics) {
if (intrinsic.intrinsify(aProgram, aInstruction, theMethodName, aArguments, aTarget, aTargetBlock, aHelper)) {
return true;
}
}
return false;
}

public boolean intrinsify(final Program aProgram, final BytecodeInstructionGETSTATIC aInstruction, final RegionNode aTargetBlock, final ParsingHelper aHelper) {
final String theFieldName = aInstruction.getConstant().getNameAndTypeIndex().getNameAndType().getNameIndex().getName().stringValue();
final BytecodeObjectTypeRef theTargetType = BytecodeObjectTypeRef.fromUtf8Constant(aInstruction.getConstant().getClassIndex().getClassConstant().getConstant());
for (final Intrinsic intrinsic : intrinsics) {
if (intrinsic.intrinsify(aProgram, aInstruction, theFieldName, theTargetType, aTargetBlock, aHelper)) {
return true;
}
}
return false;
}

public boolean intrinsify(final Program aProgram, final BytecodeInstructionPUTSTATIC aInstruction, final Value aValue, final RegionNode aTargetBlock, final ParsingHelper aHelper) {
final String theFieldName = aInstruction.getConstant().getNameAndTypeIndex().getNameAndType().getNameIndex().getName().stringValue();
final BytecodeObjectTypeRef theTargetType = BytecodeObjectTypeRef.fromUtf8Constant(aInstruction.getConstant().getClassIndex().getClassConstant().getConstant());
for (final Intrinsic intrinsic : intrinsics) {
if (intrinsic.intrinsify(aProgram, aInstruction, theFieldName, theTargetType, aValue, aTargetBlock, aHelper)) {
return true;
}
}
return false;
}
}
Loading

0 comments on commit d128d96

Please sign in to comment.