Refactoring of array generation

This commit is contained in:
konsoletyper 2013-12-01 21:57:41 +04:00
parent ce56214ed5
commit ac0df0ca6b
26 changed files with 290 additions and 38 deletions

View File

@ -39,7 +39,7 @@ public class SystemNativeGenerator implements Generator, DependencyPlugin {
String destPos = context.getParameterName(4); String destPos = context.getParameterName(4);
String length = context.getParameterName(5); String length = context.getParameterName(5);
writer.append("for (var i = 0; i < " + length + "; i = (i + 1) | 0) {").indent().newLine(); 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(); writer.outdent().append("}").newLine();
} }

View File

@ -0,0 +1,17 @@
package org.teavm.classlib.java.lang;
/**
*
* @author Alexey Andreev <konsoletyper@gmail.com>
*/
public class TArrayStoreException extends TRuntimeException {
private static final long serialVersionUID = 3911921304974631232L;
public TArrayStoreException() {
super();
}
public TArrayStoreException(TString message) {
super(message);
}
}

View File

@ -15,12 +15,12 @@ public final class TSystem extends TObject {
if (src == null || dest == null) { if (src == null || dest == null) {
throw new TNullPointerException(TString.wrap("Either src or dest is null")); throw new TNullPointerException(TString.wrap("Either src or dest is null"));
} }
if (src.getClass0() != dest.getClass0()) { if (src.getClass() != dest.getClass()) {
throw new ArrayStoreException(); throw new TArrayStoreException();
} }
if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > TArray.getLength(src) || if (srcPos < 0 || destPos < 0 || length < 0 || srcPos + length > TArray.getLength(src) ||
destPos + length > TArray.getLength(dest)) { destPos + length > TArray.getLength(dest)) {
throw new IndexOutOfBoundsException(); throw new TIndexOutOfBoundsException();
} }
doArrayCopy(src, srcPos, dest, destPos, length); doArrayCopy(src, srcPos, dest, destPos, length);
} }

View File

@ -14,22 +14,45 @@ public class TThrowable extends RuntimeException {
private TString message; private TString message;
private TThrowable cause; private TThrowable cause;
@Rename("fakeInit")
public TThrowable() { public TThrowable() {
}
@Rename("<init>")
private void init() {
fillInStackTrace(); fillInStackTrace();
} }
public TThrowable(TString message) { @Rename("fakeInit")
public TThrowable(@SuppressWarnings("unused") TString message) {
}
@Rename("<init>")
private void init(TString message) {
fillInStackTrace(); fillInStackTrace();
this.message = message; this.message = message;
} }
@SuppressWarnings("unused")
@Rename("fakeInit")
public TThrowable(TString message, TThrowable cause) { public TThrowable(TString message, TThrowable cause) {
}
@Rename("<init>")
private void init(TString message, TThrowable cause) {
fillInStackTrace(); fillInStackTrace();
this.message = message; this.message = message;
this.cause = cause; this.cause = cause;
} }
@SuppressWarnings("unused")
@Rename("fakeInit")
public TThrowable(TThrowable cause) { public TThrowable(TThrowable cause) {
}
@Rename("<init>")
private void init(TThrowable cause) {
fillInStackTrace();
this.cause = cause; this.cause = cause;
} }

View File

@ -40,7 +40,7 @@ public class TArrayNativeGenerator implements Generator, DependencyPlugin {
MethodReference cons = new MethodReference(clsName, new MethodDescriptor("<init>", ValueType.VOID)); MethodReference cons = new MethodReference(clsName, new MethodDescriptor("<init>", ValueType.VOID));
writer.append("$rt_throw(").appendClass(clsName).append(".").appendMethod(cons).append("());").newLine(); writer.append("$rt_throw(").appendClass(clsName).append(".").appendMethod(cons).append("());").newLine();
writer.outdent().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) { private void achieveGetLength(final DependencyChecker checker, MethodReference methodRef) {

View File

@ -121,7 +121,7 @@ public class DependencyChecker {
exceptionOccured.set(null); exceptionOccured.set(null);
while (true) { while (true) {
try { try {
if (executor.getActiveCount() == 0 || executor.awaitTermination(1, TimeUnit.SECONDS)) { if (executor.getActiveCount() == 0 || executor.awaitTermination(10, TimeUnit.MILLISECONDS)) {
break; break;
} }
} catch (InterruptedException e) { } catch (InterruptedException e) {
@ -197,7 +197,7 @@ public class DependencyChecker {
} }
final MethodGraph graph = new MethodGraph(parameterNodes, paramCount, resultNode, this); final MethodGraph graph = new MethodGraph(parameterNodes, paramCount, resultNode, this);
final MethodHolder currentMethod = method; final MethodHolder currentMethod = method;
executor.submit(new Runnable() { schedule(new Runnable() {
@Override public void run() { @Override public void run() {
DependencyGraphBuilder graphBuilder = new DependencyGraphBuilder(DependencyChecker.this); DependencyGraphBuilder graphBuilder = new DependencyGraphBuilder(DependencyChecker.this);
graphBuilder.buildGraph(currentMethod, graph); graphBuilder.buildGraph(currentMethod, graph);

View File

@ -174,6 +174,13 @@ class DependencyGraphBuilder {
arrayNode.getArrayItemNode().connect(receiverNode); 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 @Override
public void visit(CloneArrayInstruction insn) { public void visit(CloneArrayInstruction insn) {
DependencyNode arrayNode = nodes[insn.getArray().getIndex()]; DependencyNode arrayNode = nodes[insn.getArray().getIndex()];

View File

@ -147,6 +147,15 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor {
resultExpr = Expr.subscript(array, index); 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 @Override
public void visit(InvocationExpr expr) { public void visit(InvocationExpr expr) {
Expr[] args = new Expr[expr.getArguments().size()]; Expr[] args = new Expr[expr.getArguments().size()];

View File

@ -63,6 +63,11 @@ class ReadWriteStatsBuilder implements StatementVisitor, ExprVisitor {
expr.getIndex().acceptVisitor(this); expr.getIndex().acceptVisitor(this);
} }
@Override
public void visit(UnwrapArrayExpr expr) {
expr.getArray().acceptVisitor(this);
}
@Override @Override
public void visit(InvocationExpr expr) { public void visit(InvocationExpr expr) {
for (Expr arg : expr.getArguments()) { for (Expr arg : expr.getArguments()) {

View File

@ -48,6 +48,7 @@ public class Renderer implements ExprVisitor, StatementVisitor {
public void renderRuntime() { public void renderRuntime() {
renderRuntimeCls(); renderRuntimeCls();
renderRuntimeString(); renderRuntimeString();
renderRuntimeObjcls();
} }
private void renderRuntimeCls() { private void renderRuntimeCls() {
@ -72,14 +73,19 @@ public class Renderer implements ExprVisitor, StatementVisitor {
ValueType.arrayOf(ValueType.CHARACTER), ValueType.VOID)); ValueType.arrayOf(ValueType.CHARACTER), ValueType.VOID));
writer.append("$rt_str = function(str) {").indent().newLine(); writer.append("$rt_str = function(str) {").indent().newLine();
writer.append("var characters = $rt_createNumericArray($rt_charcls(), str.length);").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("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.outdent().append("}").newLine();
writer.append("return ").appendClass("java.lang.String").append(".") writer.append("return ").appendClass("java.lang.String").append(".")
.appendMethod(stringCons).append("(characters);").newLine(); .appendMethod(stringCons).append("(characters);").newLine();
writer.outdent().append("}").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) { public void render(ClassNode cls) {
writer.appendClass(cls.getName()).append(" = function() {").indent().newLine(); writer.appendClass(cls.getName()).append(" = function() {").indent().newLine();
for (FieldNode field : cls.getFields()) { for (FieldNode field : cls.getFields()) {
@ -375,9 +381,9 @@ public class Renderer implements ExprVisitor, StatementVisitor {
@Override @Override
public void visit(ThrowStatement statement) { public void visit(ThrowStatement statement) {
writer.append("throw "); writer.append("$rt_throw(");
statement.getException().acceptVisitor(this); statement.getException().acceptVisitor(this);
writer.append(";").newLine(); writer.append(");").newLine();
} }
@Override @Override
@ -722,6 +728,12 @@ public class Renderer implements ExprVisitor, StatementVisitor {
writer.append(']'); writer.append(']');
} }
@Override
public void visit(UnwrapArrayExpr expr) {
expr.getArray().acceptVisitor(this);
writer.append(".data");
}
@Override @Override
public void visit(InvocationExpr expr) { public void visit(InvocationExpr expr) {
String className = naming.getNameFor(expr.getMethod().getClassName()); String className = naming.getNameFor(expr.getMethod().getClassName());

View File

@ -437,6 +437,13 @@ public class StatementGenerator implements InstructionVisitor {
assign(Expr.unary(UnaryOperation.LENGTH, Expr.var(insn.getArray().getIndex())), insn.getReceiver().getIndex()); 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 @Override
public void visit(CloneArrayInstruction insn) { public void visit(CloneArrayInstruction insn) {
MethodDescriptor cloneMethodDesc = new MethodDescriptor("clone", ValueType.object("java.lang.Object")); MethodDescriptor cloneMethodDesc = new MethodDescriptor("clone", ValueType.object("java.lang.Object"));

View File

@ -155,6 +155,11 @@ class UnusedVariableEliminator implements ExprVisitor, StatementVisitor {
expr.getIndex().acceptVisitor(this); expr.getIndex().acceptVisitor(this);
} }
@Override
public void visit(UnwrapArrayExpr expr) {
expr.getArray().acceptVisitor(this);
}
@Override @Override
public void visit(InvocationExpr expr) { public void visit(InvocationExpr expr) {
for (Expr arg : expr.getArguments()) { for (Expr arg : expr.getArguments()) {

View File

@ -32,6 +32,8 @@ public interface ExprVisitor {
void visit(SubscriptExpr expr); void visit(SubscriptExpr expr);
void visit(UnwrapArrayExpr expr);
void visit(InvocationExpr expr); void visit(InvocationExpr expr);
void visit(QualificationExpr expr); void visit(QualificationExpr expr);

View File

@ -44,6 +44,11 @@ public class RenamingVisitor implements StatementVisitor, ExprVisitor {
expr.getIndex().acceptVisitor(this); expr.getIndex().acceptVisitor(this);
} }
@Override
public void visit(UnwrapArrayExpr expr) {
expr.getArray().acceptVisitor(this);
}
@Override @Override
public void visit(InvocationExpr expr) { public void visit(InvocationExpr expr) {
for (Expr arg : expr.getArguments()) { for (Expr arg : expr.getArguments()) {

View File

@ -0,0 +1,45 @@
package org.teavm.javascript.ast;
import java.util.Map;
import org.teavm.model.instructions.ArrayElementType;
/**
*
* @author Alexey Andreev <konsoletyper@gmail.com>
*/
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<Expr, Expr> 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;
}
}

View File

@ -0,0 +1,16 @@
package org.teavm.model.instructions;
/**
*
* @author Alexey Andreev <konsoletyper@gmail.com>
*/
public enum ArrayElementType {
CHAR,
BYTE,
SHORT,
INT,
LONG,
FLOAT,
DOUBLE,
OBJECT
}

View File

@ -57,6 +57,8 @@ public interface InstructionVisitor {
void visit(CloneArrayInstruction insn); void visit(CloneArrayInstruction insn);
void visit(UnwrapArrayInstruction insn);
void visit(GetElementInstruction insn); void visit(GetElementInstruction insn);
void visit(PutElementInstruction insn); void visit(PutElementInstruction insn);

View File

@ -1,9 +0,0 @@
package org.teavm.model.instructions;
/**
*
* @author Alexey Andreev
*/
public enum UnaryInstructionType {
NEGATE
}

View File

@ -0,0 +1,43 @@
package org.teavm.model.instructions;
import org.teavm.model.Instruction;
import org.teavm.model.Variable;
/**
*
* @author Alexey Andreev <konsoletyper@gmail.com>
*/
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);
}
}

View File

@ -223,6 +223,10 @@ class ClassRefsRenamer implements InstructionVisitor {
public void visit(PutElementInstruction insn) { public void visit(PutElementInstruction insn) {
} }
@Override
public void visit(UnwrapArrayInstruction insn) {
}
@Override @Override
public void visit(InvokeInstruction insn) { public void visit(InvokeInstruction insn) {
String className = classNameMapper.map(insn.getMethod().getClassName()); String className = classNameMapper.map(insn.getMethod().getClassName());

View File

@ -124,6 +124,11 @@ public class DefinitionExtractor implements InstructionVisitor {
definedVariables = new Variable[0]; definedVariables = new Variable[0];
} }
@Override
public void visit(UnwrapArrayInstruction insn) {
definedVariables = new Variable[] { insn.getReceiver() };
}
@Override @Override
public void visit(GetElementInstruction insn) { public void visit(GetElementInstruction insn) {
definedVariables = new Variable[] { insn.getReceiver() }; definedVariables = new Variable[] { insn.getReceiver() };

View File

@ -307,9 +307,15 @@ public class InstructionStringifier implements InstructionVisitor {
.append(" to ").append(insn.getTargetType()); .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 @Override
public void visit(ArrayLengthInstruction insn) { 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"); .append(insn.getArray().getIndex()).append(".length");
} }

View File

@ -165,6 +165,11 @@ public class InstructionTransitionExtractor implements InstructionVisitor {
targets = null; targets = null;
} }
@Override
public void visit(UnwrapArrayInstruction insn) {
targets = null;
}
@Override @Override
public void visit(CloneArrayInstruction insn) { public void visit(CloneArrayInstruction insn) {
targets = null; targets = null;

View File

@ -698,11 +698,15 @@ public class ProgramParser {
builder.add(insn); builder.add(insn);
} }
private void loadArrayElement(int sz) { private void loadArrayElement(int sz, ArrayElementType type) {
int arrIndex = --currentDepth; int arrIndex = --currentDepth;
int array = --currentDepth; int array = --currentDepth;
int var = currentDepth; int var = currentDepth;
currentDepth += sz; currentDepth += sz;
UnwrapArrayInstruction unwrapInsn = new UnwrapArrayInstruction(type);
unwrapInsn.setArray(getVariable(array));
unwrapInsn.setReceiver(unwrapInsn.getArray());
builder.add(unwrapInsn);
GetElementInstruction insn = new GetElementInstruction(); GetElementInstruction insn = new GetElementInstruction();
insn.setArray(getVariable(array)); insn.setArray(getVariable(array));
insn.setIndex(getVariable(arrIndex)); insn.setIndex(getVariable(arrIndex));
@ -710,11 +714,15 @@ public class ProgramParser {
builder.add(insn); builder.add(insn);
} }
private void storeArrayElement(int sz) { private void storeArrayElement(int sz, ArrayElementType type) {
currentDepth -= sz; currentDepth -= sz;
int value = currentDepth; int value = currentDepth;
int arrIndex = --currentDepth; int arrIndex = --currentDepth;
int array = --currentDepth; int array = --currentDepth;
UnwrapArrayInstruction unwrapInsn = new UnwrapArrayInstruction(type);
unwrapInsn.setArray(getVariable(array));
unwrapInsn.setReceiver(unwrapInsn.getArray());
builder.add(unwrapInsn);
PutElementInstruction insn = new PutElementInstruction(); PutElementInstruction insn = new PutElementInstruction();
insn.setArray(getVariable(array)); insn.setArray(getVariable(array));
insn.setIndex(getVariable(arrIndex)); insn.setIndex(getVariable(arrIndex));
@ -775,28 +783,52 @@ public class ProgramParser {
pushConstant(2F); pushConstant(2F);
break; break;
case Opcodes.BALOAD: case Opcodes.BALOAD:
loadArrayElement(1, ArrayElementType.BYTE);
break;
case Opcodes.IALOAD: case Opcodes.IALOAD:
loadArrayElement(1, ArrayElementType.INT);
break;
case Opcodes.FALOAD: case Opcodes.FALOAD:
loadArrayElement(1, ArrayElementType.FLOAT);
break;
case Opcodes.SALOAD: case Opcodes.SALOAD:
loadArrayElement(1, ArrayElementType.SHORT);
break;
case Opcodes.CALOAD: case Opcodes.CALOAD:
loadArrayElement(1, ArrayElementType.CHAR);
break;
case Opcodes.AALOAD: case Opcodes.AALOAD:
loadArrayElement(1); loadArrayElement(1, ArrayElementType.OBJECT);
break; break;
case Opcodes.DALOAD: case Opcodes.DALOAD:
loadArrayElement(2, ArrayElementType.DOUBLE);
break;
case Opcodes.LALOAD: case Opcodes.LALOAD:
loadArrayElement(2); loadArrayElement(2, ArrayElementType.LONG);
break; break;
case Opcodes.BASTORE: case Opcodes.BASTORE:
storeArrayElement(1, ArrayElementType.BYTE);
break;
case Opcodes.IASTORE: case Opcodes.IASTORE:
storeArrayElement(1, ArrayElementType.INT);
break;
case Opcodes.FASTORE: case Opcodes.FASTORE:
storeArrayElement(1, ArrayElementType.FLOAT);
break;
case Opcodes.SASTORE: case Opcodes.SASTORE:
storeArrayElement(1, ArrayElementType.SHORT);
break;
case Opcodes.CASTORE: case Opcodes.CASTORE:
storeArrayElement(1, ArrayElementType.CHAR);
break;
case Opcodes.AASTORE: case Opcodes.AASTORE:
storeArrayElement(1); storeArrayElement(1, ArrayElementType.OBJECT);
break; break;
case Opcodes.DASTORE: case Opcodes.DASTORE:
storeArrayElement(2, ArrayElementType.DOUBLE);
break;
case Opcodes.LASTORE: case Opcodes.LASTORE:
storeArrayElement(2); storeArrayElement(2, ArrayElementType.LONG);
break; break;
case Opcodes.POP: case Opcodes.POP:
--currentDepth; --currentDepth;
@ -1243,6 +1275,10 @@ public class ProgramParser {
} }
case Opcodes.ARRAYLENGTH: { case Opcodes.ARRAYLENGTH: {
int a = currentDepth - 1; 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(); ArrayLengthInstruction insn = new ArrayLengthInstruction();
insn.setArray(getVariable(a)); insn.setArray(getVariable(a));
insn.setReceiver(getVariable(a)); insn.setReceiver(getVariable(a));

View File

@ -357,6 +357,12 @@ public class SSATransformer {
insn.setReceiver(define(insn.getReceiver())); insn.setReceiver(define(insn.getReceiver()));
} }
@Override
public void visit(UnwrapArrayInstruction insn) {
insn.setArray(use(insn.getArray()));
insn.setReceiver(define(insn.getReceiver()));
}
@Override @Override
public void visit(CloneArrayInstruction insn) { public void visit(CloneArrayInstruction insn) {
insn.setArray(use(insn.getArray())); insn.setArray(use(insn.getArray()));

View File

@ -21,36 +21,37 @@ $rt_isAssignable = function(from, to) {
return false; return false;
} }
$rt_createArray = function(cls, sz) { $rt_createArray = function(cls, sz) {
var arr = new Array(sz); var data = new Array(sz);
arr.$class = $rt_arraycls(cls); var arr = new ($rt_arraycls(cls))(data);
arr.$id = $rt_lastObjectId++; arr.$id = $rt_nextId();
for (var i = 0; i < sz; i = (i + 1) | 0) { for (var i = 0; i < sz; i = (i + 1) | 0) {
arr[i] = null; arr.data[i] = null;
} }
return arr; return arr;
} }
$rt_createNumericArray = function(cls, sz) { $rt_createNumericArray = function(cls, sz) {
var arr = $rt_createArray(cls, sz); var arr = $rt_createArray(cls, sz);
for (var i = 0; i < sz; i = (i + 1) | 0) { for (var i = 0; i < sz; i = (i + 1) | 0) {
arr[i] = 0; arr.data[i] = 0;
} }
return arr; return arr;
} }
$rt_createLongArray = function(sz) { $rt_createLongArray = function(sz) {
var arr = $rt.createArray($rt_longcls(), sz); var arr = $rt.createArray($rt_longcls(), sz);
for (var i = 0; i < sz; i = (i + 1) | 0) { for (var i = 0; i < sz; i = (i + 1) | 0) {
arr[i] = Long.ZERO; arr.data[i] = Long.ZERO;
} }
return arr; return arr;
}, },
$rt_arraycls = function(cls) { $rt_arraycls = function(cls) {
if (cls.$array == undefined) { if (cls.$array == undefined) {
cls.$array = { var arraycls = function(data) {
$meta : { item : cls }, this.data = data;
this.$cls = arraycls;
}; };
if ($rt.objcls) { arraycls.prototype = new ($rt_objcls())();
cls.$array.$meta.supertypes = [$rt.objcls()]; arraycls.$meta = { item : cls, supertypes : [$rt_objcls()] };
} cls.$array = arraycls;
} }
return cls.$array; return cls.$array;
} }