From 8a2ed216de965feae01f3899ca7ce0b751633064 Mon Sep 17 00:00:00 2001 From: David Grove Date: Thu, 9 Dec 2021 20:03:04 -0500 Subject: [PATCH] remove Clone node and use class lib implementation Fixes #744. Fixes #674. --- .../org/qbicc/graph/BasicBlockBuilder.java | 2 - .../src/main/java/org/qbicc/graph/Clone.java | 60 ------------------- .../graph/DelegatingBasicBlockBuilder.java | 4 -- .../src/main/java/org/qbicc/graph/Node.java | 5 -- .../qbicc/graph/SimpleBasicBlockBuilder.java | 4 -- .../java/org/qbicc/graph/ValueVisitor.java | 8 --- .../org/qbicc/interpreter/impl/Frame.java | 8 --- .../org/qbicc/interpreter/impl/VmImpl.java | 11 ++++ .../org/qbicc/plugin/dot/DotNodeVisitor.java | 14 ----- .../plugin/gc/nogc/NoGcBasicBlockBuilder.java | 42 ------------- .../intrinsics/core/CoreIntrinsics.java | 27 --------- 11 files changed, 11 insertions(+), 174 deletions(-) delete mode 100644 compiler/src/main/java/org/qbicc/graph/Clone.java diff --git a/compiler/src/main/java/org/qbicc/graph/BasicBlockBuilder.java b/compiler/src/main/java/org/qbicc/graph/BasicBlockBuilder.java index 012f48bf1a..735b01361e 100644 --- a/compiler/src/main/java/org/qbicc/graph/BasicBlockBuilder.java +++ b/compiler/src/main/java/org/qbicc/graph/BasicBlockBuilder.java @@ -389,8 +389,6 @@ default ValueHandle pointerHandle(Value pointer) { Value multiNewArray(ArrayTypeDescriptor desc, List dimensions); - Value clone(Value object); - default Value load(ValueHandle handle) { return load(handle, SinglePlain); } diff --git a/compiler/src/main/java/org/qbicc/graph/Clone.java b/compiler/src/main/java/org/qbicc/graph/Clone.java deleted file mode 100644 index 3cfad99b97..0000000000 --- a/compiler/src/main/java/org/qbicc/graph/Clone.java +++ /dev/null @@ -1,60 +0,0 @@ -package org.qbicc.graph; - -import org.qbicc.type.ValueType; -import org.qbicc.type.definition.element.ExecutableElement; - -/** - * - */ -public class Clone extends AbstractValue implements UnaryValue, OrderedNode { - private final Node dependency; - private final Value original; - - Clone(final Node callSite, final ExecutableElement element, final int line, final int bci, final Node dependency, final Value original) { - super(callSite, element, line, bci); - this.dependency = dependency; - this.original = original; - } - - int calcHashCode() { - return dependency.hashCode() * 19 + original.hashCode(); - } - - @Override - String getNodeName() { - return "Clone"; - } - - public ValueType getType() { - return original.getType(); - } - - public Value getInput() { - return original; - } - - public boolean equals(final Object other) { - return other instanceof Clone && equals((Clone) other); - } - - public boolean equals(final Clone other) { - return this == other || other != null && dependency.equals(other.dependency) && original.equals(other.original); - } - - public int getValueDependencyCount() { - return 1; - } - - public Value getValueDependency(final int index) throws IndexOutOfBoundsException { - return index == 0 ? original : Util.throwIndexOutOfBounds(index); - } - - @Override - public Node getDependency() { - return dependency; - } - - public R accept(final ValueVisitor visitor, final T param) { - return visitor.visit(param, this); - } -} diff --git a/compiler/src/main/java/org/qbicc/graph/DelegatingBasicBlockBuilder.java b/compiler/src/main/java/org/qbicc/graph/DelegatingBasicBlockBuilder.java index fa97cfa7fd..494744b7eb 100644 --- a/compiler/src/main/java/org/qbicc/graph/DelegatingBasicBlockBuilder.java +++ b/compiler/src/main/java/org/qbicc/graph/DelegatingBasicBlockBuilder.java @@ -320,10 +320,6 @@ public Value multiNewArray(final ArrayTypeDescriptor desc, final List dim return getDelegate().multiNewArray(desc, dimensions); } - public Value clone(final Value object) { - return getDelegate().clone(object); - } - public Value load(final ValueHandle handle, final ReadAccessMode accessMode) { return getDelegate().load(handle, accessMode); } diff --git a/compiler/src/main/java/org/qbicc/graph/Node.java b/compiler/src/main/java/org/qbicc/graph/Node.java index f3aa5d874f..774079850b 100644 --- a/compiler/src/main/java/org/qbicc/graph/Node.java +++ b/compiler/src/main/java/org/qbicc/graph/Node.java @@ -504,11 +504,6 @@ public Value visit(final Copier param, final ClassOf node) { return param.getBlockBuilder().classOf(param.copyValue(node.getInput()), param.copyValue(node.getDimensions())); } - public Value visit(final Copier param, final Clone node) { - param.copyNode(node.getDependency()); - return param.getBlockBuilder().clone(param.copyValue(node.getInput())); - } - public Value visit(final Copier param, final CountLeadingZeros node) { return param.getBlockBuilder().countLeadingZeros(param.copyValue(node.getInput())); } diff --git a/compiler/src/main/java/org/qbicc/graph/SimpleBasicBlockBuilder.java b/compiler/src/main/java/org/qbicc/graph/SimpleBasicBlockBuilder.java index debc403938..791904f652 100644 --- a/compiler/src/main/java/org/qbicc/graph/SimpleBasicBlockBuilder.java +++ b/compiler/src/main/java/org/qbicc/graph/SimpleBasicBlockBuilder.java @@ -609,10 +609,6 @@ public Value multiNewArray(final ArrayTypeDescriptor desc, final List dim throw new IllegalStateException("New of unresolved array type"); } - public Value clone(final Value object) { - return asDependency(new Clone(callSite, element, line, bci, requireDependency(), object)); - } - public Value load(final ValueHandle handle, final ReadAccessMode mode) { return asDependency(new Load(callSite, element, line, bci, requireDependency(), handle, mode)); } diff --git a/compiler/src/main/java/org/qbicc/graph/ValueVisitor.java b/compiler/src/main/java/org/qbicc/graph/ValueVisitor.java index 9d72d0b337..a508a29f71 100644 --- a/compiler/src/main/java/org/qbicc/graph/ValueVisitor.java +++ b/compiler/src/main/java/org/qbicc/graph/ValueVisitor.java @@ -84,10 +84,6 @@ default R visit(T param, ClassOf node) { return visitUnknown(param, node); } - default R visit(T param, Clone node) { - return visitUnknown(param, node); - } - default R visit(T param, Comp node) { return visitUnknown(param, node); } @@ -455,10 +451,6 @@ default R visit(T param, ClassOf node) { return getDelegateValueVisitor().visit(param, node); } - default R visit(T param, Clone node) { - return getDelegateValueVisitor().visit(param, node); - } - default R visit(T param, Comp node) { return getDelegateValueVisitor().visit(param, node); } diff --git a/interpreter/src/main/java/org/qbicc/interpreter/impl/Frame.java b/interpreter/src/main/java/org/qbicc/interpreter/impl/Frame.java index d56ad0e53f..5510e3f6f0 100644 --- a/interpreter/src/main/java/org/qbicc/interpreter/impl/Frame.java +++ b/interpreter/src/main/java/org/qbicc/interpreter/impl/Frame.java @@ -27,7 +27,6 @@ import org.qbicc.graph.CheckCast; import org.qbicc.graph.InitCheck; import org.qbicc.graph.ClassOf; -import org.qbicc.graph.Clone; import org.qbicc.graph.Cmp; import org.qbicc.graph.CmpAndSwap; import org.qbicc.graph.CmpG; @@ -1454,13 +1453,6 @@ public Void visit(VmThreadImpl thread, InitCheck node) { throw new UnsupportedOperationException(); } - @Override - public Object visit(VmThreadImpl thread, Clone node) { - // todo: implement according to #674 - VmObjectImpl original = (VmObjectImpl) require(node.getInput()); - return original.clone(); - } - public Object visit(final VmThreadImpl param, final Comp node) { Value input = node.getInput(); ValueType inputType = input.getType(); diff --git a/interpreter/src/main/java/org/qbicc/interpreter/impl/VmImpl.java b/interpreter/src/main/java/org/qbicc/interpreter/impl/VmImpl.java index ce7323cdeb..d6a4935572 100644 --- a/interpreter/src/main/java/org/qbicc/interpreter/impl/VmImpl.java +++ b/interpreter/src/main/java/org/qbicc/interpreter/impl/VmImpl.java @@ -44,6 +44,7 @@ import org.qbicc.interpreter.VmReferenceArray; import org.qbicc.interpreter.VmString; import org.qbicc.interpreter.VmThread; +import org.qbicc.interpreter.VmThrowable; import org.qbicc.machine.arch.Platform; import org.qbicc.plugin.coreclasses.CoreClasses; import org.qbicc.plugin.layout.Layout; @@ -383,6 +384,16 @@ public void initialize() { // Object VmClassImpl objectClass = bootstrapClassLoader.loadClass("java/lang/Object"); + objectClass.registerInvokable("clone", (thread, target, args) -> { + VmClassImpl cloneableClass = bootstrapClassLoader.loadClass("java/lang/Cloneable"); + if (!target.getVmClass().getTypeDefinition().isSubtypeOf(cloneableClass.getTypeDefinition())) { + VmClassImpl cnse = bootstrapClassLoader.loadClass("java/lang/CloneNotSupportedException"); + VmThrowable throwable = manuallyInitialize((VmThrowable) cnse.newInstance()); + ((VmThreadImpl)thread).setThrown(throwable); + throw new Thrown(throwable); + } + return ((VmObjectImpl)target).clone(); + }); objectClass.registerInvokable("wait", 0, (thread, target, args) -> { try { ((VmObjectImpl)target).getCondition().await(); diff --git a/plugins/dot/src/main/java/org/qbicc/plugin/dot/DotNodeVisitor.java b/plugins/dot/src/main/java/org/qbicc/plugin/dot/DotNodeVisitor.java index cdda2114e8..b45fe80b81 100644 --- a/plugins/dot/src/main/java/org/qbicc/plugin/dot/DotNodeVisitor.java +++ b/plugins/dot/src/main/java/org/qbicc/plugin/dot/DotNodeVisitor.java @@ -27,7 +27,6 @@ import org.qbicc.graph.CastValue; import org.qbicc.graph.InitCheck; import org.qbicc.graph.ClassOf; -import org.qbicc.graph.Clone; import org.qbicc.graph.Cmp; import org.qbicc.graph.CmpAndSwap; import org.qbicc.graph.CmpG; @@ -844,19 +843,6 @@ public String visit(final Appendable param, final ClassOf node) { return name; } - public String visit(final Appendable param, final Clone node) { - String name = register(node); - appendTo(param, name); - attr(param, "shape", "rectangle"); - attr(param, "label", "clone"); - attr(param, "fixedsize", "shape"); - nl(param); - dependencyList.add(name); - processDependency(param, node.getDependency()); - addEdge(param, node, node.getInput(), EdgeType.VALUE_DEPENDENCY); - return name; - } - public String visit(final Appendable param, final Comp node) { return node(param, "~", node); } diff --git a/plugins/gc/nogc/src/main/java/org/qbicc/plugin/gc/nogc/NoGcBasicBlockBuilder.java b/plugins/gc/nogc/src/main/java/org/qbicc/plugin/gc/nogc/NoGcBasicBlockBuilder.java index aa6490b942..8d0d6ce025 100644 --- a/plugins/gc/nogc/src/main/java/org/qbicc/plugin/gc/nogc/NoGcBasicBlockBuilder.java +++ b/plugins/gc/nogc/src/main/java/org/qbicc/plugin/gc/nogc/NoGcBasicBlockBuilder.java @@ -4,7 +4,6 @@ import org.qbicc.context.CompilationContext; import org.qbicc.graph.BasicBlockBuilder; -import org.qbicc.graph.BlockEarlyTermination; import org.qbicc.graph.DelegatingBasicBlockBuilder; import org.qbicc.graph.Value; import org.qbicc.graph.literal.IntegerLiteral; @@ -14,19 +13,14 @@ import org.qbicc.plugin.coreclasses.CoreClasses; import org.qbicc.plugin.layout.Layout; import org.qbicc.plugin.layout.LayoutInfo; -import org.qbicc.type.ArrayObjectType; import org.qbicc.type.ClassObjectType; import org.qbicc.type.CompoundType; import org.qbicc.type.IntegerType; import org.qbicc.type.PrimitiveArrayObjectType; import org.qbicc.type.ReferenceArrayObjectType; -import org.qbicc.type.ValueType; -import org.qbicc.type.WordType; import org.qbicc.type.definition.LoadedTypeDefinition; import org.qbicc.type.definition.element.MethodElement; -import static org.qbicc.graph.atomic.AccessModes.GlobalRelease; - /** * */ @@ -108,40 +102,4 @@ private Value allocateArray(CompoundType compoundType, Value size, long elementS return ptrVal; } - - public Value clone(final Value object) { - ValueType objType = object.getType(); - NoGc noGc = NoGc.get(ctxt); - Layout layout = Layout.get(ctxt); - if (objType instanceof ClassObjectType) { - // TODO: This implementation is actually not correct, because it is cloning based - // on the static type of the value; not the actual runtime type. - // I would remove it entirely, except it is actually needed to pass one of our - // integration tests (which is using Enums). - ClassObjectType type = (ClassObjectType) objType; - LayoutInfo info = layout.getInstanceLayoutInfo(type.getDefinition()); - LiteralFactory lf = ctxt.getLiteralFactory(); - CompoundType compoundType = info.getCompoundType(); - IntegerLiteral size = lf.literalOf(compoundType.getSize()); - IntegerLiteral align = lf.literalOf(compoundType.getAlign()); - Value ptrVal; - if (type.isSubtypeOf(noGc.getStackObjectType())) { - ptrVal = stackAllocate(compoundType, lf.literalOf(1), align); - } else { - MethodElement method = noGc.getAllocateMethod(); - ptrVal = notNull(call(staticMethod(method, method.getDescriptor(), method.getType()), List.of(size, align))); - } - // TODO: replace with field-by-field copy once we have a redundant assignment elimination optimization - // TODO: if/when we put a thinlock, default hashcode, or GC state bits in the object header we need to properly initialize them. - MethodElement method = noGc.getCopyMethod(); - call(staticMethod(method, method.getDescriptor(), method.getType()), List.of(ptrVal, valueConvert(object, (WordType) ptrVal.getType()), size)); - fence(GlobalRelease); - return valueConvert(ptrVal, type.getReference()); - } else if (objType instanceof ArrayObjectType) { - ctxt.error(getLocation(), "Array allocations not supported until layout supports arrays"); - throw new BlockEarlyTermination(unreachable()); - } else { - return super.clone(object); - } - } } diff --git a/plugins/intrinsics/src/main/java/org/qbicc/plugin/intrinsics/core/CoreIntrinsics.java b/plugins/intrinsics/src/main/java/org/qbicc/plugin/intrinsics/core/CoreIntrinsics.java index 9cf42bf4e0..5b79538765 100644 --- a/plugins/intrinsics/src/main/java/org/qbicc/plugin/intrinsics/core/CoreIntrinsics.java +++ b/plugins/intrinsics/src/main/java/org/qbicc/plugin/intrinsics/core/CoreIntrinsics.java @@ -1028,33 +1028,6 @@ public static void registerJavaLangObjectIntrinsics(CompilationContext ctxt) { ctxt.getLiteralFactory().zeroInitializerLiteralOfType(ctxt.getTypeSystem().getVoidType()); // Do nothing intrinsics.registerIntrinsic(objDesc, "notifyAll", notifyAllDesc, notifyAllIntrinsic); - InstanceIntrinsic clone = (builder, instance, target, arguments) -> { - ValueType instanceType = instance.getType(); - if (instanceType instanceof ReferenceType) { - ReferenceType referenceType = (ReferenceType) instanceType; - InterfaceObjectType cloneable = classContext.findDefinedType("java/lang/Cloneable").load().getInterfaceType(); - if (! referenceType.instanceOf(cloneable)) { - // synthesize a run time check - BlockLabel goAhead = new BlockLabel(); - BlockLabel throwIt = new BlockLabel(); - builder.if_(builder.instanceOf(instance, cloneable, 0), goAhead, throwIt); - try { - builder.begin(throwIt); - ClassTypeDescriptor cnseDesc = ClassTypeDescriptor.synthesize(classContext, "java/lang/CloneNotSupportedException"); - Value cnse = builder.getFirstBuilder().new_(cnseDesc); - builder.call(builder.getFirstBuilder().constructorOf(cnse, cnseDesc, MethodDescriptor.VOID_METHOD_DESCRIPTOR), List.of()); - builder.throw_(cnse); - } catch (BlockEarlyTermination ignored) { - // continue - } - builder.begin(goAhead); - } - } - return builder.clone(instance); - }; - - intrinsics.registerIntrinsic(objDesc, "clone", MethodDescriptor.synthesize(classContext, objDesc, List.of()), clone); - // stub - public final native void wait(long timeoutMillis) MethodDescriptor waitDesc = MethodDescriptor.synthesize(classContext, BaseTypeDescriptor.V, List.of(BaseTypeDescriptor.J)); InstanceIntrinsic wait = (builder, instance, target, arguments) -> ctxt.getLiteralFactory().zeroInitializerLiteralOfType(target.getExecutable().getType().getReturnType());