diff --git a/core/src/main/java/de/mirkosertic/bytecoder/backend/js/JSSSACompilerBackend.java b/core/src/main/java/de/mirkosertic/bytecoder/backend/js/JSSSACompilerBackend.java index 0f92376b7..9779d0bd3 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/backend/js/JSSSACompilerBackend.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/backend/js/JSSSACompilerBackend.java @@ -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(); @@ -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(); } }); @@ -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(); @@ -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(); @@ -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 theEntries = theMethods.stream().collect(Collectors.toList()); final Set theVisitedMethods = new HashSet<>(); @@ -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(); diff --git a/core/src/main/java/de/mirkosertic/bytecoder/backend/js/JSSSAWriter.java b/core/src/main/java/de/mirkosertic/bytecoder/backend/js/JSSSAWriter.java index 489bf1b0a..08684e5ac 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/backend/js/JSSSAWriter.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/backend/js/JSSSAWriter.java @@ -15,11 +15,6 @@ */ 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; @@ -27,89 +22,14 @@ 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 { @@ -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) { diff --git a/core/src/main/java/de/mirkosertic/bytecoder/backend/wasm/WASMSSAASTCompilerBackend.java b/core/src/main/java/de/mirkosertic/bytecoder/backend/wasm/WASMSSAASTCompilerBackend.java index 000f765ca..48cf3d675 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/backend/wasm/WASMSSAASTCompilerBackend.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/backend/wasm/WASMSSAASTCompilerBackend.java @@ -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 theCallsites = new HashMap<>(); @@ -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 { @@ -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); diff --git a/core/src/main/java/de/mirkosertic/bytecoder/core/BytecodeLinkedClass.java b/core/src/main/java/de/mirkosertic/bytecoder/core/BytecodeLinkedClass.java index 6d03deff9..fae3b4a47 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/core/BytecodeLinkedClass.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/core/BytecodeLinkedClass.java @@ -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() { diff --git a/core/src/main/java/de/mirkosertic/bytecoder/intrinsics/Intrinsic.java b/core/src/main/java/de/mirkosertic/bytecoder/intrinsics/Intrinsic.java index 4d1eb5de0..b6333395e 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/intrinsics/Intrinsic.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/intrinsics/Intrinsic.java @@ -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; @@ -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 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; + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/intrinsics/Intrinsics.java b/core/src/main/java/de/mirkosertic/bytecoder/intrinsics/Intrinsics.java index 1761971f1..c445a602a 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/intrinsics/Intrinsics.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/intrinsics/Intrinsics.java @@ -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; @@ -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 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; + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/intrinsics/RuntimeClassIntrinsic.java b/core/src/main/java/de/mirkosertic/bytecoder/intrinsics/RuntimeClassIntrinsic.java index 332593b69..be7434d51 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/intrinsics/RuntimeClassIntrinsic.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/intrinsics/RuntimeClassIntrinsic.java @@ -15,10 +15,7 @@ */ package de.mirkosertic.bytecoder.intrinsics; -import de.mirkosertic.bytecoder.core.BytecodeInstructionINVOKESPECIAL; -import de.mirkosertic.bytecoder.core.BytecodeLinkedClass; -import de.mirkosertic.bytecoder.core.BytecodeMethodSignature; -import de.mirkosertic.bytecoder.core.BytecodeObjectTypeRef; +import de.mirkosertic.bytecoder.core.*; import de.mirkosertic.bytecoder.ssa.*; import java.util.List; @@ -39,4 +36,38 @@ public boolean intrinsify(final Program aProgram, final BytecodeInstructionINVOK } return false; } + + @Override + public boolean intrinsify(final Program aProgram, final BytecodeInstructionINVOKEVIRTUAL aInstruction, final String aMethodName, final List aArguments, final Value aTarget, final RegionNode aTargetBlock, final ParsingHelper aHelper) { + final BytecodeMethodSignature theSignature = aInstruction.getMethodReference().getNameAndTypeIndex().getNameAndType().getDescriptorIndex().methodSignature(); + if (theSignature.matchesExactlyTo(BytecodeLinkedClass.GET_CLASS_SIGNATURE) && "getClass".equals(aMethodName)) { + final Value theValue = new TypeOfExpression(aProgram, aInstruction.getOpcodeAddress(), aTarget); + final Variable theNewVariable = aTargetBlock.newVariable(aInstruction.getOpcodeAddress(), TypeRef.toType(theSignature.getReturnType()), theValue); + aHelper.push(theNewVariable); + return true; + } + if (theSignature.matchesExactlyTo(BytecodeLinkedClass.DESIRED_ASSERTION_STATUS_SIGNATURE) && "desiredAssertionStatus".equals(aMethodName)) { + // Status is always false + aHelper.push(new IntegerValue(0)); + return true; + } + return false; + } + + @Override + public boolean intrinsify(final Program aProgram, final BytecodeInstructionGETSTATIC aInstruction, final String aFieldName, final BytecodeObjectTypeRef aTtargetType, final RegionNode aTargetBlock, final ParsingHelper aHelper) { + if ("$assertionsDisabled".equals(aFieldName)) { + aHelper.push(new IntegerValue(1)); + return true; + } + return false; + } + + @Override + public boolean intrinsify(final Program aProgram, final BytecodeInstructionPUTSTATIC aInstruction, final String aFieldName, final BytecodeObjectTypeRef aTtargetType, final Value aValue, final RegionNode aTargetBlock, final ParsingHelper aHelper) { + if ("$assertionsDisabled".equals(aFieldName)) { + return true; + } + return false; + } } diff --git a/core/src/main/java/de/mirkosertic/bytecoder/ssa/NaiveProgramGenerator.java b/core/src/main/java/de/mirkosertic/bytecoder/ssa/NaiveProgramGenerator.java index c5c3277f6..56514b39d 100644 --- a/core/src/main/java/de/mirkosertic/bytecoder/ssa/NaiveProgramGenerator.java +++ b/core/src/main/java/de/mirkosertic/bytecoder/ssa/NaiveProgramGenerator.java @@ -104,7 +104,6 @@ import de.mirkosertic.bytecoder.core.BytecodeIntegerConstant; import de.mirkosertic.bytecoder.core.BytecodeInvokeDynamicConstant; import de.mirkosertic.bytecoder.core.BytecodeLineNumberTableAttributeInfo; -import de.mirkosertic.bytecoder.core.BytecodeLinkedClass; import de.mirkosertic.bytecoder.core.BytecodeLinkerContext; import de.mirkosertic.bytecoder.core.BytecodeLocalVariableTableAttributeInfo; import de.mirkosertic.bytecoder.core.BytecodeLocalVariableTableEntry; @@ -583,9 +582,11 @@ private void initializeBlockWith(final BytecodeClass aOwningClass, } } else if (theInstruction instanceof BytecodeInstructionGETSTATIC) { final BytecodeInstructionGETSTATIC theINS = (BytecodeInstructionGETSTATIC) theInstruction; - final GetStaticExpression theValue = new GetStaticExpression(aProgram, theInstruction.getOpcodeAddress(), theINS.getConstant()); - final Variable theVariable = aTargetBlock.newVariable(theInstruction.getOpcodeAddress(), TypeRef.toType(theINS.getConstant().getNameAndTypeIndex().getNameAndType().getDescriptorIndex().fieldType()), theValue); - aHelper.push(theVariable); + if (!intrinsics.intrinsify(aProgram, theINS, aTargetBlock, aHelper)) { + final GetStaticExpression theValue = new GetStaticExpression(aProgram, theInstruction.getOpcodeAddress(), theINS.getConstant()); + final Variable theVariable = aTargetBlock.newVariable(theInstruction.getOpcodeAddress(), TypeRef.toType(theINS.getConstant().getNameAndTypeIndex().getNameAndType().getDescriptorIndex().fieldType()), theValue); + aHelper.push(theVariable); + } } else if (theInstruction instanceof BytecodeInstructionASTORE) { final BytecodeInstructionASTORE theINS = (BytecodeInstructionASTORE) theInstruction; final Value theValue = aHelper.pop(); @@ -645,7 +646,9 @@ private void initializeBlockWith(final BytecodeClass aOwningClass, } else if (theInstruction instanceof BytecodeInstructionPUTSTATIC) { final BytecodeInstructionPUTSTATIC theINS = (BytecodeInstructionPUTSTATIC) theInstruction; final Value theValue = aHelper.pop(); - aTargetBlock.getExpressions().add(new PutStaticExpression(aProgram, theInstruction.getOpcodeAddress(), theINS.getConstant(), theValue)); + if (!intrinsics.intrinsify(aProgram, theINS, theValue, aTargetBlock, aHelper)) { + aTargetBlock.getExpressions().add(new PutStaticExpression(aProgram, theInstruction.getOpcodeAddress(), theINS.getConstant(), theValue)); + } } else if (theInstruction instanceof BytecodeInstructionGenericLDC) { final BytecodeInstructionGenericLDC theINS = (BytecodeInstructionGenericLDC) theInstruction; final BytecodeConstant theConstant = theINS.constant(); @@ -1028,13 +1031,6 @@ private void initializeBlockWith(final BytecodeClass aOwningClass, final BytecodeInstructionINVOKEVIRTUAL theINS = (BytecodeInstructionINVOKEVIRTUAL) theInstruction; final BytecodeMethodSignature theSignature = theINS.getMethodReference().getNameAndTypeIndex().getNameAndType().getDescriptorIndex().methodSignature(); - if (theSignature.matchesExactlyTo(BytecodeLinkedClass.GET_CLASS_SIGNATURE) && "getClass".equals(theINS.getMethodReference().getNameAndTypeIndex().getNameAndType().getNameIndex().getName().stringValue())) { - final Value theValue = new TypeOfExpression(aProgram, theInstruction.getOpcodeAddress(), aHelper.pop()); - final Variable theNewVariable = aTargetBlock.newVariable(theInstruction.getOpcodeAddress(), TypeRef.toType(theSignature.getReturnType()), theValue); - aHelper.push(theNewVariable); - continue; - } - final List theArguments = new ArrayList<>(); final BytecodeTypeRef[] theArgumentTypes = theSignature.getArguments(); for (final BytecodeTypeRef theArgumentType : theArgumentTypes) { @@ -1043,13 +1039,17 @@ private void initializeBlockWith(final BytecodeClass aOwningClass, Collections.reverse(theArguments); final Value theTarget = aHelper.pop(); - final InvokeVirtualMethodExpression theExpression = new InvokeVirtualMethodExpression(aProgram, theInstruction.getOpcodeAddress(), theINS.getMethodReference().getNameAndTypeIndex().getNameAndType(), theTarget, theArguments, false); - if (theSignature.getReturnType().isVoid()) { - aTargetBlock.getExpressions().add(theExpression); - } else { - final Variable theNewVariable = aTargetBlock.newVariable(theInstruction.getOpcodeAddress(), TypeRef.toType(theSignature.getReturnType()), theExpression); - aHelper.push(theNewVariable); + + if (!intrinsics.intrinsify(aProgram, theINS, theArguments, theTarget, aTargetBlock, aHelper)) { + final InvokeVirtualMethodExpression theExpression = new InvokeVirtualMethodExpression(aProgram, theInstruction.getOpcodeAddress(), theINS.getMethodReference().getNameAndTypeIndex().getNameAndType(), theTarget, theArguments, false); + if (theSignature.getReturnType().isVoid()) { + aTargetBlock.getExpressions().add(theExpression); + } else { + final Variable theNewVariable = aTargetBlock.newVariable(theInstruction.getOpcodeAddress(), TypeRef.toType(theSignature.getReturnType()), theExpression); + aHelper.push(theNewVariable); + } } + } else if (theInstruction instanceof BytecodeInstructionINVOKEINTERFACE) { final BytecodeInstructionINVOKEINTERFACE theINS = (BytecodeInstructionINVOKEINTERFACE) theInstruction; final BytecodeMethodSignature theSignature = theINS.getMethodDescriptor().getNameAndTypeIndex().getNameAndType().getDescriptorIndex().methodSignature(); diff --git a/core/src/test/resources/classtest.html b/core/src/test/resources/classtest.html new file mode 100644 index 000000000..0584bdf95 --- /dev/null +++ b/core/src/test/resources/classtest.html @@ -0,0 +1,54 @@ + + + + + \ No newline at end of file