From 7551cd1ec6898173edf66286c1b3e4a6c9642146 Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Fri, 5 Apr 2019 13:08:16 +0300 Subject: [PATCH] C: fix bugs in GC --- .../java/org/teavm/backend/c/CTarget.java | 2 +- .../backend/c/generate/ClassGenerator.java | 3 ++- .../c/generate/CodeGenerationVisitor.java | 15 ++++++++--- .../lowlevel/GCShadowStackContributor.java | 2 +- .../RedundantNullCheckElimination.java | 2 +- .../java/org/teavm/model/util/PhiUpdater.java | 11 ++++---- core/src/main/java/org/teavm/vm/TeaVM.java | 4 ++- .../main/java/org/teavm/interop/NoGcRoot.java | 26 +++++++++++++++++++ .../plugin/MetadataProviderTransformer.java | 2 ++ 9 files changed, 53 insertions(+), 14 deletions(-) create mode 100644 interop/core/src/main/java/org/teavm/interop/NoGcRoot.java diff --git a/core/src/main/java/org/teavm/backend/c/CTarget.java b/core/src/main/java/org/teavm/backend/c/CTarget.java index e928301a3..fbdaf861d 100644 --- a/core/src/main/java/org/teavm/backend/c/CTarget.java +++ b/core/src/main/java/org/teavm/backend/c/CTarget.java @@ -592,7 +592,7 @@ public class CTarget implements TeaVMTarget, TeaVMCHost { String mainMethod = names.forMethod(entryPoint.getMethod()); context.writer().print(mainMethod + "("); context.emit(invocation.getArguments().get(0)); - context.writer().println(");"); + context.writer().print(")"); } } diff --git a/core/src/main/java/org/teavm/backend/c/generate/ClassGenerator.java b/core/src/main/java/org/teavm/backend/c/generate/ClassGenerator.java index 9addac4e0..7c1156165 100644 --- a/core/src/main/java/org/teavm/backend/c/generate/ClassGenerator.java +++ b/core/src/main/java/org/teavm/backend/c/generate/ClassGenerator.java @@ -32,6 +32,7 @@ import org.teavm.dependency.DependencyInfo; import org.teavm.diagnostics.Diagnostics; import org.teavm.interop.Address; import org.teavm.interop.DelegateTo; +import org.teavm.interop.NoGcRoot; import org.teavm.interop.Structure; import org.teavm.model.AnnotationHolder; import org.teavm.model.ClassHolder; @@ -278,7 +279,7 @@ public class ClassGenerator { String fieldName = context.getNames().forStaticField(field.getReference()); fieldsWriter.print("static ").printStrictType(field.getType()).print(" ").print(fieldName) .println(";"); - if (isReferenceType(field.getType())) { + if (isReferenceType(field.getType()) && field.getAnnotations().get(NoGcRoot.class.getName()) == null) { staticFields[staticIndex++] = field.getReference(); } diff --git a/core/src/main/java/org/teavm/backend/c/generate/CodeGenerationVisitor.java b/core/src/main/java/org/teavm/backend/c/generate/CodeGenerationVisitor.java index 6b2f40f3f..cf818dab6 100644 --- a/core/src/main/java/org/teavm/backend/c/generate/CodeGenerationVisitor.java +++ b/core/src/main/java/org/teavm/backend/c/generate/CodeGenerationVisitor.java @@ -102,7 +102,6 @@ public class CodeGenerationVisitor implements ExprVisitor, StatementVisitor { private int[] maxTemporaryVariableLevel = new int[5]; private MethodReference callingMethod; private Set includes; - private int currentPart; private boolean end; private boolean async; @@ -384,7 +383,11 @@ public class CodeGenerationVisitor implements ExprVisitor, StatementVisitor { writer.print(", "); MethodReader method = context.getClassSource().resolve(expr.getMethod()); - writer.print(names.forMethod(method.getReference())); + MethodReference reference = expr.getMethod(); + if (method != null) { + reference = method.getReference(); + } + writer.print(names.forMethod(reference)); writer.print("(" + receiver); for (Expr arg : expr.getArguments()) { @@ -400,10 +403,14 @@ public class CodeGenerationVisitor implements ExprVisitor, StatementVisitor { case SPECIAL: case STATIC: { MethodReader method = context.getClassSource().resolve(expr.getMethod()); - if (isWrappedNativeCall(method)) { + if (method != null && isWrappedNativeCall(method)) { generateWrappedNativeCall(method, expr); } else { - writer.print(names.forMethod(method.getReference())); + MethodReference reference = expr.getMethod(); + if (method != null) { + reference = method.getReference(); + } + writer.print(names.forMethod(reference)); writer.print("("); if (!expr.getArguments().isEmpty()) { diff --git a/core/src/main/java/org/teavm/model/lowlevel/GCShadowStackContributor.java b/core/src/main/java/org/teavm/model/lowlevel/GCShadowStackContributor.java index f6aa5e2d6..b548f67fe 100644 --- a/core/src/main/java/org/teavm/model/lowlevel/GCShadowStackContributor.java +++ b/core/src/main/java/org/teavm/model/lowlevel/GCShadowStackContributor.java @@ -81,7 +81,7 @@ public class GCShadowStackContributor { int usedColors = 0; for (int var = 0; var < colors.length; ++var) { if (spilled[var]) { - usedColors = Math.max(usedColors, colors[var]); + usedColors = Math.max(usedColors, colors[var] + 1); colors[var]--; } } diff --git a/core/src/main/java/org/teavm/model/optimization/RedundantNullCheckElimination.java b/core/src/main/java/org/teavm/model/optimization/RedundantNullCheckElimination.java index e740c842c..7dffcc878 100644 --- a/core/src/main/java/org/teavm/model/optimization/RedundantNullCheckElimination.java +++ b/core/src/main/java/org/teavm/model/optimization/RedundantNullCheckElimination.java @@ -50,7 +50,7 @@ public class RedundantNullCheckElimination implements MethodOptimization { } else if (nullness.isNull(nullCheck.getValue())) { block.detachSuccessors(); while (nullCheck.getNext() != null) { - nullCheck.delete(); + nullCheck.getNext().delete(); } nullCheck.insertPreviousAll(ProgramUtils.createThrowNPEInstructions( diff --git a/core/src/main/java/org/teavm/model/util/PhiUpdater.java b/core/src/main/java/org/teavm/model/util/PhiUpdater.java index ba21ded67..a13c1b646 100644 --- a/core/src/main/java/org/teavm/model/util/PhiUpdater.java +++ b/core/src/main/java/org/teavm/model/util/PhiUpdater.java @@ -479,11 +479,12 @@ public class PhiUpdater { return; } - boolean exists = frontierBlock.getPhis().stream() - .flatMap(phi -> phi.getIncomings().stream()) - .anyMatch(incoming -> incoming.getSource() == block && incoming.getValue() == var); - if (exists) { - return; + for (Phi phi : frontierBlock.getPhis()) { + for (Incoming incoming : phi.getIncomings()) { + if (incoming.getSource() == block && incoming.getValue() == var) { + return; + } + } } Phi phi = phiMap[frontier][var.getIndex()]; diff --git a/core/src/main/java/org/teavm/vm/TeaVM.java b/core/src/main/java/org/teavm/vm/TeaVM.java index c8a25b661..82f73959b 100644 --- a/core/src/main/java/org/teavm/vm/TeaVM.java +++ b/core/src/main/java/org/teavm/vm/TeaVM.java @@ -977,7 +977,9 @@ public class TeaVM implements TeaVMHost, ServiceRepository { ListableClassReaderSourceAdapter(ClassReaderSource classSource, Set classes) { this.classSource = classSource; - this.classes = Collections.unmodifiableSet(classes); + this.classes = Collections.unmodifiableSet(classes.stream() + .filter(className -> classSource.get(className) != null) + .collect(Collectors.toSet())); } @Override diff --git a/interop/core/src/main/java/org/teavm/interop/NoGcRoot.java b/interop/core/src/main/java/org/teavm/interop/NoGcRoot.java new file mode 100644 index 000000000..339d2f8f0 --- /dev/null +++ b/interop/core/src/main/java/org/teavm/interop/NoGcRoot.java @@ -0,0 +1,26 @@ +/* + * Copyright 2019 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.interop; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface NoGcRoot { +} diff --git a/platform/src/main/java/org/teavm/platform/plugin/MetadataProviderTransformer.java b/platform/src/main/java/org/teavm/platform/plugin/MetadataProviderTransformer.java index 0d97359e2..8eec2b74d 100644 --- a/platform/src/main/java/org/teavm/platform/plugin/MetadataProviderTransformer.java +++ b/platform/src/main/java/org/teavm/platform/plugin/MetadataProviderTransformer.java @@ -18,6 +18,7 @@ package org.teavm.platform.plugin; import java.util.HashSet; import java.util.Set; import org.teavm.backend.javascript.spi.GeneratedBy; +import org.teavm.interop.NoGcRoot; import org.teavm.interop.NoSideEffects; import org.teavm.model.AccessLevel; import org.teavm.model.AnnotationHolder; @@ -56,6 +57,7 @@ class MetadataProviderTransformer implements ClassHolderTransformer { field.setType(method.getResultType()); field.setLevel(AccessLevel.PRIVATE); field.getModifiers().add(ElementModifier.STATIC); + field.getAnnotations().add(new AnnotationHolder(NoGcRoot.class.getName())); cls.addField(field); MethodHolder createMethod = new MethodHolder(method.getName() + "$$create", method.getSignature());