diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/SystemNativeGenerator.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/SystemNativeGenerator.java index e7a86748f..b480807e8 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/SystemNativeGenerator.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/SystemNativeGenerator.java @@ -39,7 +39,7 @@ public class SystemNativeGenerator implements Generator, DependencyPlugin { String destPos = context.getParameterName(4); String length = context.getParameterName(5); writer.append("for (var i = 0; i < " + length + "; i = (i + 1) | 0) {").indent().newLine(); - writer.append(dest + "[" + srcPos + "++] = " + src + "[" + destPos + "++];").newLine(); + writer.append(dest + ".data[" + srcPos + "++] = " + src + ".data[" + destPos + "++];").newLine(); writer.outdent().append("}").newLine(); } diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TArrayStoreException.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TArrayStoreException.java new file mode 100644 index 000000000..35d8873c0 --- /dev/null +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TArrayStoreException.java @@ -0,0 +1,17 @@ +package org.teavm.classlib.java.lang; + +/** + * + * @author Alexey Andreev + */ +public class TArrayStoreException extends TRuntimeException { + private static final long serialVersionUID = 3911921304974631232L; + + public TArrayStoreException() { + super(); + } + + public TArrayStoreException(TString message) { + super(message); + } +} diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TSystem.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TSystem.java index dffc22154..1aff72f4d 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TSystem.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TSystem.java @@ -15,12 +15,12 @@ public final class TSystem extends TObject { if (src == null || dest == null) { throw new TNullPointerException(TString.wrap("Either src or dest is null")); } - if (src.getClass0() != dest.getClass0()) { - throw new ArrayStoreException(); + if (src.getClass() != dest.getClass()) { + throw new TArrayStoreException(); } if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > TArray.getLength(src) || destPos + length > TArray.getLength(dest)) { - throw new IndexOutOfBoundsException(); + throw new TIndexOutOfBoundsException(); } doArrayCopy(src, srcPos, dest, destPos, length); } diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TThrowable.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TThrowable.java index 452daccf9..1704e0e99 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TThrowable.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TThrowable.java @@ -14,22 +14,45 @@ public class TThrowable extends RuntimeException { private TString message; private TThrowable cause; + @Rename("fakeInit") public TThrowable() { + } + + @Rename("") + private void init() { fillInStackTrace(); } - public TThrowable(TString message) { + @Rename("fakeInit") + public TThrowable(@SuppressWarnings("unused") TString message) { + } + + @Rename("") + private void init(TString message) { fillInStackTrace(); this.message = message; } + @SuppressWarnings("unused") + @Rename("fakeInit") public TThrowable(TString message, TThrowable cause) { + } + + @Rename("") + private void init(TString message, TThrowable cause) { fillInStackTrace(); this.message = message; this.cause = cause; } + @SuppressWarnings("unused") + @Rename("fakeInit") public TThrowable(TThrowable cause) { + } + + @Rename("") + private void init(TThrowable cause) { + fillInStackTrace(); this.cause = cause; } diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/reflect/TArrayNativeGenerator.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/reflect/TArrayNativeGenerator.java index 2c808980a..1d518251d 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/reflect/TArrayNativeGenerator.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/reflect/TArrayNativeGenerator.java @@ -40,7 +40,7 @@ public class TArrayNativeGenerator implements Generator, DependencyPlugin { MethodReference cons = new MethodReference(clsName, new MethodDescriptor("", ValueType.VOID)); writer.append("$rt_throw(").appendClass(clsName).append(".").appendMethod(cons).append("());").newLine(); writer.outdent().append("}").newLine(); - writer.append("return array.length"); + writer.append("return " + array + ".data.length;").newLine(); } private void achieveGetLength(final DependencyChecker checker, MethodReference methodRef) { diff --git a/teavm-core/src/main/java/org/teavm/dependency/DependencyChecker.java b/teavm-core/src/main/java/org/teavm/dependency/DependencyChecker.java index c1cc353e0..94e4568fb 100644 --- a/teavm-core/src/main/java/org/teavm/dependency/DependencyChecker.java +++ b/teavm-core/src/main/java/org/teavm/dependency/DependencyChecker.java @@ -121,7 +121,7 @@ public class DependencyChecker { exceptionOccured.set(null); while (true) { try { - if (executor.getActiveCount() == 0 || executor.awaitTermination(1, TimeUnit.SECONDS)) { + if (executor.getActiveCount() == 0 || executor.awaitTermination(10, TimeUnit.MILLISECONDS)) { break; } } catch (InterruptedException e) { @@ -197,7 +197,7 @@ public class DependencyChecker { } final MethodGraph graph = new MethodGraph(parameterNodes, paramCount, resultNode, this); final MethodHolder currentMethod = method; - executor.submit(new Runnable() { + schedule(new Runnable() { @Override public void run() { DependencyGraphBuilder graphBuilder = new DependencyGraphBuilder(DependencyChecker.this); graphBuilder.buildGraph(currentMethod, graph); diff --git a/teavm-core/src/main/java/org/teavm/dependency/DependencyGraphBuilder.java b/teavm-core/src/main/java/org/teavm/dependency/DependencyGraphBuilder.java index 7634c3476..8c91df7f0 100644 --- a/teavm-core/src/main/java/org/teavm/dependency/DependencyGraphBuilder.java +++ b/teavm-core/src/main/java/org/teavm/dependency/DependencyGraphBuilder.java @@ -174,6 +174,13 @@ class DependencyGraphBuilder { arrayNode.getArrayItemNode().connect(receiverNode); } + @Override + public void visit(UnwrapArrayInstruction insn) { + DependencyNode arrayNode = nodes[insn.getArray().getIndex()]; + DependencyNode receiverNode = nodes[insn.getReceiver().getIndex()]; + arrayNode.connect(receiverNode); + } + @Override public void visit(CloneArrayInstruction insn) { DependencyNode arrayNode = nodes[insn.getArray().getIndex()]; diff --git a/teavm-core/src/main/java/org/teavm/javascript/OptimizingVisitor.java b/teavm-core/src/main/java/org/teavm/javascript/OptimizingVisitor.java index a3372a4ca..c82e5db9f 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/OptimizingVisitor.java +++ b/teavm-core/src/main/java/org/teavm/javascript/OptimizingVisitor.java @@ -147,6 +147,15 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor { resultExpr = Expr.subscript(array, index); } + @Override + public void visit(UnwrapArrayExpr expr) { + expr.getArray().acceptVisitor(this); + Expr arrayExpr = resultExpr; + UnwrapArrayExpr result = new UnwrapArrayExpr(expr.getElementType()); + result.setArray(arrayExpr); + resultExpr = result; + } + @Override public void visit(InvocationExpr expr) { Expr[] args = new Expr[expr.getArguments().size()]; diff --git a/teavm-core/src/main/java/org/teavm/javascript/ReadWriteStatsBuilder.java b/teavm-core/src/main/java/org/teavm/javascript/ReadWriteStatsBuilder.java index 235d84e9c..6a1fa952d 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/ReadWriteStatsBuilder.java +++ b/teavm-core/src/main/java/org/teavm/javascript/ReadWriteStatsBuilder.java @@ -63,6 +63,11 @@ class ReadWriteStatsBuilder implements StatementVisitor, ExprVisitor { expr.getIndex().acceptVisitor(this); } + @Override + public void visit(UnwrapArrayExpr expr) { + expr.getArray().acceptVisitor(this); + } + @Override public void visit(InvocationExpr expr) { for (Expr arg : expr.getArguments()) { diff --git a/teavm-core/src/main/java/org/teavm/javascript/Renderer.java b/teavm-core/src/main/java/org/teavm/javascript/Renderer.java index c45dc0712..36f4821c4 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/Renderer.java +++ b/teavm-core/src/main/java/org/teavm/javascript/Renderer.java @@ -48,6 +48,7 @@ public class Renderer implements ExprVisitor, StatementVisitor { public void renderRuntime() { renderRuntimeCls(); renderRuntimeString(); + renderRuntimeObjcls(); } private void renderRuntimeCls() { @@ -72,14 +73,19 @@ public class Renderer implements ExprVisitor, StatementVisitor { ValueType.arrayOf(ValueType.CHARACTER), ValueType.VOID)); writer.append("$rt_str = function(str) {").indent().newLine(); writer.append("var characters = $rt_createNumericArray($rt_charcls(), str.length);").newLine(); + writer.append("var charsBuffer = characters.data;").newLine(); writer.append("for (var i = 0; i < str.length; i = (i + 1) | 0) {").indent().newLine(); - writer.append("characters[i] = str.charCodeAt(i);").newLine(); + writer.append("charsBuffer[i] = str.charCodeAt(i);").newLine(); writer.outdent().append("}").newLine(); writer.append("return ").appendClass("java.lang.String").append(".") .appendMethod(stringCons).append("(characters);").newLine(); writer.outdent().append("}").newLine(); } + private void renderRuntimeObjcls() { + writer.append("$rt_objcls = function() { return ").appendClass("java.lang.Object").append("; }").newLine(); + } + public void render(ClassNode cls) { writer.appendClass(cls.getName()).append(" = function() {").indent().newLine(); for (FieldNode field : cls.getFields()) { @@ -375,9 +381,9 @@ public class Renderer implements ExprVisitor, StatementVisitor { @Override public void visit(ThrowStatement statement) { - writer.append("throw "); + writer.append("$rt_throw("); statement.getException().acceptVisitor(this); - writer.append(";").newLine(); + writer.append(");").newLine(); } @Override @@ -722,6 +728,12 @@ public class Renderer implements ExprVisitor, StatementVisitor { writer.append(']'); } + @Override + public void visit(UnwrapArrayExpr expr) { + expr.getArray().acceptVisitor(this); + writer.append(".data"); + } + @Override public void visit(InvocationExpr expr) { String className = naming.getNameFor(expr.getMethod().getClassName()); diff --git a/teavm-core/src/main/java/org/teavm/javascript/StatementGenerator.java b/teavm-core/src/main/java/org/teavm/javascript/StatementGenerator.java index 4382439a5..0a0f60317 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/StatementGenerator.java +++ b/teavm-core/src/main/java/org/teavm/javascript/StatementGenerator.java @@ -437,6 +437,13 @@ public class StatementGenerator implements InstructionVisitor { assign(Expr.unary(UnaryOperation.LENGTH, Expr.var(insn.getArray().getIndex())), insn.getReceiver().getIndex()); } + @Override + public void visit(UnwrapArrayInstruction insn) { + UnwrapArrayExpr unwrapExpr = new UnwrapArrayExpr(insn.getElementType()); + unwrapExpr.setArray(Expr.var(insn.getArray().getIndex())); + assign(unwrapExpr, insn.getReceiver().getIndex()); + } + @Override public void visit(CloneArrayInstruction insn) { MethodDescriptor cloneMethodDesc = new MethodDescriptor("clone", ValueType.object("java.lang.Object")); diff --git a/teavm-core/src/main/java/org/teavm/javascript/UnusedVariableEliminator.java b/teavm-core/src/main/java/org/teavm/javascript/UnusedVariableEliminator.java index 18e5fd88c..7b9f1d8e6 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/UnusedVariableEliminator.java +++ b/teavm-core/src/main/java/org/teavm/javascript/UnusedVariableEliminator.java @@ -155,6 +155,11 @@ class UnusedVariableEliminator implements ExprVisitor, StatementVisitor { expr.getIndex().acceptVisitor(this); } + @Override + public void visit(UnwrapArrayExpr expr) { + expr.getArray().acceptVisitor(this); + } + @Override public void visit(InvocationExpr expr) { for (Expr arg : expr.getArguments()) { diff --git a/teavm-core/src/main/java/org/teavm/javascript/ast/ExprVisitor.java b/teavm-core/src/main/java/org/teavm/javascript/ast/ExprVisitor.java index c4a003e85..a56efd896 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/ast/ExprVisitor.java +++ b/teavm-core/src/main/java/org/teavm/javascript/ast/ExprVisitor.java @@ -32,6 +32,8 @@ public interface ExprVisitor { void visit(SubscriptExpr expr); + void visit(UnwrapArrayExpr expr); + void visit(InvocationExpr expr); void visit(QualificationExpr expr); diff --git a/teavm-core/src/main/java/org/teavm/javascript/ast/RenamingVisitor.java b/teavm-core/src/main/java/org/teavm/javascript/ast/RenamingVisitor.java index fa92fc2a5..b3890e565 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/ast/RenamingVisitor.java +++ b/teavm-core/src/main/java/org/teavm/javascript/ast/RenamingVisitor.java @@ -44,6 +44,11 @@ public class RenamingVisitor implements StatementVisitor, ExprVisitor { expr.getIndex().acceptVisitor(this); } + @Override + public void visit(UnwrapArrayExpr expr) { + expr.getArray().acceptVisitor(this); + } + @Override public void visit(InvocationExpr expr) { for (Expr arg : expr.getArguments()) { diff --git a/teavm-core/src/main/java/org/teavm/javascript/ast/UnwrapArrayExpr.java b/teavm-core/src/main/java/org/teavm/javascript/ast/UnwrapArrayExpr.java new file mode 100644 index 000000000..2bab1d05c --- /dev/null +++ b/teavm-core/src/main/java/org/teavm/javascript/ast/UnwrapArrayExpr.java @@ -0,0 +1,45 @@ +package org.teavm.javascript.ast; + +import java.util.Map; +import org.teavm.model.instructions.ArrayElementType; + +/** + * + * @author Alexey Andreev + */ +public class UnwrapArrayExpr extends Expr { + private ArrayElementType elementType; + private Expr array; + + public UnwrapArrayExpr(ArrayElementType elementType) { + this.elementType = elementType; + } + + public ArrayElementType getElementType() { + return elementType; + } + + public Expr getArray() { + return array; + } + + public void setArray(Expr array) { + this.array = array; + } + + @Override + public void acceptVisitor(ExprVisitor visitor) { + visitor.visit(this); + } + + @Override + protected UnwrapArrayExpr clone(Map cache) { + UnwrapArrayExpr copy = (UnwrapArrayExpr)cache.get(this); + if (copy == null) { + copy = new UnwrapArrayExpr(elementType); + copy.array = array != null ? array.clone(cache) : null; + cache.put(copy, copy); + } + return copy; + } +} diff --git a/teavm-core/src/main/java/org/teavm/model/instructions/ArrayElementType.java b/teavm-core/src/main/java/org/teavm/model/instructions/ArrayElementType.java new file mode 100644 index 000000000..9b43c6204 --- /dev/null +++ b/teavm-core/src/main/java/org/teavm/model/instructions/ArrayElementType.java @@ -0,0 +1,16 @@ +package org.teavm.model.instructions; + +/** + * + * @author Alexey Andreev + */ +public enum ArrayElementType { + CHAR, + BYTE, + SHORT, + INT, + LONG, + FLOAT, + DOUBLE, + OBJECT +} diff --git a/teavm-core/src/main/java/org/teavm/model/instructions/InstructionVisitor.java b/teavm-core/src/main/java/org/teavm/model/instructions/InstructionVisitor.java index f649c2ee1..35529be9d 100644 --- a/teavm-core/src/main/java/org/teavm/model/instructions/InstructionVisitor.java +++ b/teavm-core/src/main/java/org/teavm/model/instructions/InstructionVisitor.java @@ -57,6 +57,8 @@ public interface InstructionVisitor { void visit(CloneArrayInstruction insn); + void visit(UnwrapArrayInstruction insn); + void visit(GetElementInstruction insn); void visit(PutElementInstruction insn); diff --git a/teavm-core/src/main/java/org/teavm/model/instructions/UnaryInstructionType.java b/teavm-core/src/main/java/org/teavm/model/instructions/UnaryInstructionType.java deleted file mode 100644 index 4efa99dab..000000000 --- a/teavm-core/src/main/java/org/teavm/model/instructions/UnaryInstructionType.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.teavm.model.instructions; - -/** - * - * @author Alexey Andreev - */ -public enum UnaryInstructionType { - NEGATE -} diff --git a/teavm-core/src/main/java/org/teavm/model/instructions/UnwrapArrayInstruction.java b/teavm-core/src/main/java/org/teavm/model/instructions/UnwrapArrayInstruction.java new file mode 100644 index 000000000..7c97630f1 --- /dev/null +++ b/teavm-core/src/main/java/org/teavm/model/instructions/UnwrapArrayInstruction.java @@ -0,0 +1,43 @@ +package org.teavm.model.instructions; + +import org.teavm.model.Instruction; +import org.teavm.model.Variable; + +/** + * + * @author Alexey Andreev + */ +public class UnwrapArrayInstruction extends Instruction { + private Variable array; + private Variable receiver; + private ArrayElementType elementType; + + public UnwrapArrayInstruction(ArrayElementType elementType) { + this.elementType = elementType; + } + + public Variable getArray() { + return array; + } + + public void setArray(Variable array) { + this.array = array; + } + + public Variable getReceiver() { + return receiver; + } + + public void setReceiver(Variable receiver) { + this.receiver = receiver; + } + + public ArrayElementType getElementType() { + return elementType; + } + + @Override + public void acceptVisitor(InstructionVisitor visitor) { + visitor.visit(this); + } +} diff --git a/teavm-core/src/main/java/org/teavm/model/resource/ClassRefsRenamer.java b/teavm-core/src/main/java/org/teavm/model/resource/ClassRefsRenamer.java index d945dd1dc..9aa421f2c 100644 --- a/teavm-core/src/main/java/org/teavm/model/resource/ClassRefsRenamer.java +++ b/teavm-core/src/main/java/org/teavm/model/resource/ClassRefsRenamer.java @@ -223,6 +223,10 @@ class ClassRefsRenamer implements InstructionVisitor { public void visit(PutElementInstruction insn) { } + @Override + public void visit(UnwrapArrayInstruction insn) { + } + @Override public void visit(InvokeInstruction insn) { String className = classNameMapper.map(insn.getMethod().getClassName()); diff --git a/teavm-core/src/main/java/org/teavm/model/util/DefinitionExtractor.java b/teavm-core/src/main/java/org/teavm/model/util/DefinitionExtractor.java index 662963d63..048bf9076 100644 --- a/teavm-core/src/main/java/org/teavm/model/util/DefinitionExtractor.java +++ b/teavm-core/src/main/java/org/teavm/model/util/DefinitionExtractor.java @@ -124,6 +124,11 @@ public class DefinitionExtractor implements InstructionVisitor { definedVariables = new Variable[0]; } + @Override + public void visit(UnwrapArrayInstruction insn) { + definedVariables = new Variable[] { insn.getReceiver() }; + } + @Override public void visit(GetElementInstruction insn) { definedVariables = new Variable[] { insn.getReceiver() }; diff --git a/teavm-core/src/main/java/org/teavm/model/util/InstructionStringifier.java b/teavm-core/src/main/java/org/teavm/model/util/InstructionStringifier.java index e0d77b5e0..768d2d0aa 100644 --- a/teavm-core/src/main/java/org/teavm/model/util/InstructionStringifier.java +++ b/teavm-core/src/main/java/org/teavm/model/util/InstructionStringifier.java @@ -307,9 +307,15 @@ public class InstructionStringifier implements InstructionVisitor { .append(" to ").append(insn.getTargetType()); } + @Override + public void visit(UnwrapArrayInstruction insn) { + sb.append("@").append(insn.getReceiver().getIndex()).append("@").append(" := @") + .append(insn.getArray()).append(".data"); + } + @Override public void visit(ArrayLengthInstruction insn) { - sb.append("@").append(insn.getReceiver().getIndex()).append("@") + sb.append("@").append(insn.getReceiver().getIndex()).append(" := @") .append(insn.getArray().getIndex()).append(".length"); } diff --git a/teavm-core/src/main/java/org/teavm/model/util/InstructionTransitionExtractor.java b/teavm-core/src/main/java/org/teavm/model/util/InstructionTransitionExtractor.java index f23bbb0e0..dd7ca72fe 100644 --- a/teavm-core/src/main/java/org/teavm/model/util/InstructionTransitionExtractor.java +++ b/teavm-core/src/main/java/org/teavm/model/util/InstructionTransitionExtractor.java @@ -165,6 +165,11 @@ public class InstructionTransitionExtractor implements InstructionVisitor { targets = null; } + @Override + public void visit(UnwrapArrayInstruction insn) { + targets = null; + } + @Override public void visit(CloneArrayInstruction insn) { targets = null; diff --git a/teavm-core/src/main/java/org/teavm/parsing/ProgramParser.java b/teavm-core/src/main/java/org/teavm/parsing/ProgramParser.java index f5106b956..6b3607c64 100644 --- a/teavm-core/src/main/java/org/teavm/parsing/ProgramParser.java +++ b/teavm-core/src/main/java/org/teavm/parsing/ProgramParser.java @@ -698,11 +698,15 @@ public class ProgramParser { builder.add(insn); } - private void loadArrayElement(int sz) { + private void loadArrayElement(int sz, ArrayElementType type) { int arrIndex = --currentDepth; int array = --currentDepth; int var = currentDepth; currentDepth += sz; + UnwrapArrayInstruction unwrapInsn = new UnwrapArrayInstruction(type); + unwrapInsn.setArray(getVariable(array)); + unwrapInsn.setReceiver(unwrapInsn.getArray()); + builder.add(unwrapInsn); GetElementInstruction insn = new GetElementInstruction(); insn.setArray(getVariable(array)); insn.setIndex(getVariable(arrIndex)); @@ -710,11 +714,15 @@ public class ProgramParser { builder.add(insn); } - private void storeArrayElement(int sz) { + private void storeArrayElement(int sz, ArrayElementType type) { currentDepth -= sz; int value = currentDepth; int arrIndex = --currentDepth; int array = --currentDepth; + UnwrapArrayInstruction unwrapInsn = new UnwrapArrayInstruction(type); + unwrapInsn.setArray(getVariable(array)); + unwrapInsn.setReceiver(unwrapInsn.getArray()); + builder.add(unwrapInsn); PutElementInstruction insn = new PutElementInstruction(); insn.setArray(getVariable(array)); insn.setIndex(getVariable(arrIndex)); @@ -775,28 +783,52 @@ public class ProgramParser { pushConstant(2F); break; case Opcodes.BALOAD: + loadArrayElement(1, ArrayElementType.BYTE); + break; case Opcodes.IALOAD: + loadArrayElement(1, ArrayElementType.INT); + break; case Opcodes.FALOAD: + loadArrayElement(1, ArrayElementType.FLOAT); + break; case Opcodes.SALOAD: + loadArrayElement(1, ArrayElementType.SHORT); + break; case Opcodes.CALOAD: + loadArrayElement(1, ArrayElementType.CHAR); + break; case Opcodes.AALOAD: - loadArrayElement(1); + loadArrayElement(1, ArrayElementType.OBJECT); break; case Opcodes.DALOAD: + loadArrayElement(2, ArrayElementType.DOUBLE); + break; case Opcodes.LALOAD: - loadArrayElement(2); + loadArrayElement(2, ArrayElementType.LONG); break; case Opcodes.BASTORE: + storeArrayElement(1, ArrayElementType.BYTE); + break; case Opcodes.IASTORE: + storeArrayElement(1, ArrayElementType.INT); + break; case Opcodes.FASTORE: + storeArrayElement(1, ArrayElementType.FLOAT); + break; case Opcodes.SASTORE: + storeArrayElement(1, ArrayElementType.SHORT); + break; case Opcodes.CASTORE: + storeArrayElement(1, ArrayElementType.CHAR); + break; case Opcodes.AASTORE: - storeArrayElement(1); + storeArrayElement(1, ArrayElementType.OBJECT); break; case Opcodes.DASTORE: + storeArrayElement(2, ArrayElementType.DOUBLE); + break; case Opcodes.LASTORE: - storeArrayElement(2); + storeArrayElement(2, ArrayElementType.LONG); break; case Opcodes.POP: --currentDepth; @@ -1243,6 +1275,10 @@ public class ProgramParser { } case Opcodes.ARRAYLENGTH: { int a = currentDepth - 1; + UnwrapArrayInstruction unwrapInsn = new UnwrapArrayInstruction(ArrayElementType.OBJECT); + unwrapInsn.setArray(getVariable(a)); + unwrapInsn.setReceiver(getVariable(a)); + builder.add(unwrapInsn); ArrayLengthInstruction insn = new ArrayLengthInstruction(); insn.setArray(getVariable(a)); insn.setReceiver(getVariable(a)); diff --git a/teavm-core/src/main/java/org/teavm/parsing/SSATransformer.java b/teavm-core/src/main/java/org/teavm/parsing/SSATransformer.java index ef5f10d04..377bb94af 100644 --- a/teavm-core/src/main/java/org/teavm/parsing/SSATransformer.java +++ b/teavm-core/src/main/java/org/teavm/parsing/SSATransformer.java @@ -357,6 +357,12 @@ public class SSATransformer { insn.setReceiver(define(insn.getReceiver())); } + @Override + public void visit(UnwrapArrayInstruction insn) { + insn.setArray(use(insn.getArray())); + insn.setReceiver(define(insn.getReceiver())); + } + @Override public void visit(CloneArrayInstruction insn) { insn.setArray(use(insn.getArray())); diff --git a/teavm-core/src/main/resources/org/teavm/javascript/runtime.js b/teavm-core/src/main/resources/org/teavm/javascript/runtime.js index 30ec320b7..537e74268 100644 --- a/teavm-core/src/main/resources/org/teavm/javascript/runtime.js +++ b/teavm-core/src/main/resources/org/teavm/javascript/runtime.js @@ -21,36 +21,37 @@ $rt_isAssignable = function(from, to) { return false; } $rt_createArray = function(cls, sz) { - var arr = new Array(sz); - arr.$class = $rt_arraycls(cls); - arr.$id = $rt_lastObjectId++; + var data = new Array(sz); + var arr = new ($rt_arraycls(cls))(data); + arr.$id = $rt_nextId(); for (var i = 0; i < sz; i = (i + 1) | 0) { - arr[i] = null; + arr.data[i] = null; } return arr; } $rt_createNumericArray = function(cls, sz) { var arr = $rt_createArray(cls, sz); for (var i = 0; i < sz; i = (i + 1) | 0) { - arr[i] = 0; + arr.data[i] = 0; } return arr; } $rt_createLongArray = function(sz) { var arr = $rt.createArray($rt_longcls(), sz); for (var i = 0; i < sz; i = (i + 1) | 0) { - arr[i] = Long.ZERO; + arr.data[i] = Long.ZERO; } return arr; }, $rt_arraycls = function(cls) { if (cls.$array == undefined) { - cls.$array = { - $meta : { item : cls }, + var arraycls = function(data) { + this.data = data; + this.$cls = arraycls; }; - if ($rt.objcls) { - cls.$array.$meta.supertypes = [$rt.objcls()]; - } + arraycls.prototype = new ($rt_objcls())(); + arraycls.$meta = { item : cls, supertypes : [$rt_objcls()] }; + cls.$array = arraycls; } return cls.$array; }