Primitive bump allocator, more ops.

This commit is contained in:
Michael Bebenita 2015-05-08 21:14:44 -07:00
Родитель b1c576b982
Коммит fa3fe83ca3
8 изменённых файлов: 366 добавлений и 236 удалений

403
int.ts
Просмотреть файл

@ -1,29 +1,33 @@
module J2ME {
declare var ASM;
declare var ASM;
var buffer = ASM.buffer;
var bufferView: DataView = new DataView(buffer);
var i32: Int32Array = ASM.HEAP32;
var u32: Uint32Array = ASM.HEAPU32;
var f32: Float32Array = ASM.HEAPF32;
var ref = J2ME.ArrayUtilities.makeDenseArray(buffer.byteLength >> 2, null);
module J2ME {
import assert = Debug.assert;
import Bytecodes = Bytecode.Bytecodes;
import toHEX = IntegerUtilities.toHEX;
var buffer = ASM.buffer;
var i32: Int32Array = ASM.HEAP32;
var u32: Uint32Array = ASM.HEAPU32;
var f32: Float32Array = ASM.HEAPF32;
var ref = ArrayUtilities.makeDenseArray(buffer.byteLength >> 2, null);
function toName(o) {
if (o instanceof MethodInfo) {
return o.implKey;
}
function getObjectInfo(o) {
return fromUTF8(o.klass.classInfo.utf8Name) + " " + (o._address ? toHEX(o._address) : "");
}
if (o && o.klass === Klasses.java.lang.Class) {
return "[" + fromUTF8(o.klass.classInfo.utf8Name) + "] " + o.runtimeKlass.templateKlass.classInfo.getClassNameSlow();
return "[" + getObjectInfo(o) + "] " + o.runtimeKlass.templateKlass.classInfo.getClassNameSlow();
}
if (o && o.klass === Klasses.java.lang.String) {
return "[" + fromUTF8(o.klass.classInfo.utf8Name) + "] \"" + fromJavaString(o) + "\"";
return "[" + getObjectInfo(o) + "] \"" + fromJavaString(o) + "\"";
}
return o ? ("[" + fromUTF8(o.klass.classInfo.utf8Name) + "]") : "null";
return o ? ("[" + getObjectInfo(o) + "]") : "null";
}
/**
@ -217,7 +221,7 @@ module J2ME {
view: FrameView;
constructor(ctx: Context) {
this.tp = ASM._malloc(1024 * 128);
this.tp = ASM._gcMalloc(1024 * 128);
this.bp = this.tp;
this.fp = this.bp;
this.sp = this.fp;
@ -349,8 +353,8 @@ module J2ME {
var tag: TAGS;
var type, size;
var value, index, array, object, result, constant, targetPC, returnValue, kind;
var ia = 0, ib = 0; // Integer Operands
var ll = 0, lh = 0; // Long Low / High
var fa = 0, fb = 0; // Float / Double Operands
var classInfo: ClassInfo;
@ -512,6 +516,50 @@ module J2ME {
}
}
function pushKindFromAddress(kind: Kind, address: number) {
switch (kind) {
case Kind.Reference:
ref[sp++] = ref[address >> 2];
return;
case Kind.Int:
case Kind.Char:
case Kind.Short:
case Kind.Boolean:
case Kind.Float:
i32[sp++] = i32[address >> 2];
return;
case Kind.Long:
case Kind.Double:
i32[sp++] = i32[address >> 2];
i32[sp++] = i32[address + 4 >> 2];
return;
default:
Debug.assert(false, "Cannot Push Kind: " + Kind[kind]);
}
}
function popKindIntoAddress(kind: Kind, address: number) {
switch (kind) {
case Kind.Reference:
ref[address >> 2] = ref[--sp];
return;
case Kind.Int:
case Kind.Char:
case Kind.Short:
case Kind.Boolean:
case Kind.Float:
i32[address >> 2] = i32[--sp];
break;
case Kind.Long:
case Kind.Double:
i32[address + 4 >> 2] = i32[--sp];
i32[address >> 2] = i32[--sp];
break;
default:
Debug.assert(false, "Cannot Pop Kind: " + Kind[kind]);
}
}
function classInitAndUnwindCheck(classInfo: ClassInfo, pc: number) {
saveThreadState();
classInitCheck(classInfo);
@ -522,6 +570,8 @@ module J2ME {
//}
}
// HEAD
while (true) {
// saveThreadState();
@ -536,7 +586,12 @@ module J2ME {
var opPC = pc;
var op = code[pc++];
// traceWriter.writeLn(bytecodeCount++ + " " + mi.implKey + ": PC: " + opPC + ", FP: " + fp + ", " + Bytecodes[op]);
if (traceWriter) {
//traceWriter.writeLn(bytecodeCount++ + " " + mi.implKey + ": PC: " + opPC + ", FP: " + fp + ", " + Bytecodes[op]);
frame.set(fp, sp, opPC);
// frameView.traceStack(traceWriter);
// frame.trace(traceWriter, fieldInfo);
}
try {
switch (op) {
@ -559,10 +614,14 @@ module J2ME {
case Bytecodes.FCONST_2:
i32[sp++] = op - Bytecodes.FCONST_0;
continue;
// case Bytecodes.DCONST_0:
// case Bytecodes.DCONST_1:
// stack.push2(op - Bytecodes.DCONST_0);
// break;
case Bytecodes.DCONST_0:
i32[sp++] = 0;
i32[sp++] = 0;
continue;
case Bytecodes.DCONST_1:
i32[sp++] = 0;
i32[sp++] = 1072693248;
continue;
case Bytecodes.LCONST_0:
case Bytecodes.LCONST_1:
i32[sp++] = op - Bytecodes.LCONST_0;
@ -674,16 +733,37 @@ module J2ME {
}
i32[sp++] = array[index];
continue;
// case Bytecodes.FALOAD:
// case Bytecodes.AALOAD:
// break;
// case Bytecodes.LALOAD:
case Bytecodes.FALOAD:
index = i32[--sp];
array = ref[--sp];
if ((index >>> 0) >= (array.length >>> 0)) {
throw $.newArrayIndexOutOfBoundsException(String(index));
}
f32[sp++] = array[index];
continue;
case Bytecodes.AALOAD:
index = i32[--sp];
array = ref[--sp];
if ((index >>> 0) >= (array.length >>> 0)) {
throw $.newArrayIndexOutOfBoundsException(String(index));
}
ref[sp++] = array[index];
continue;
// case Bytecodes.DALOAD:
// index = stack.pop();
// array = stack.pop();
// checkArrayBounds(array, index);
// stack.push2(array[index]);
// break;
case Bytecodes.DALOAD:
index = i32[--sp];
array = ref[--sp];
if ((index >>> 0) >= (array.length >>> 0)) {
throw $.newArrayIndexOutOfBoundsException(String(index));
}
bufferView.setFloat64(sp << 2, array[index]);
sp += 2;
continue;
case Bytecodes.ISTORE:
case Bytecodes.FSTORE:
i32[lp + code[pc++]] = i32[--sp];
@ -739,7 +819,7 @@ module J2ME {
array[index] = value;
continue;
case Bytecodes.FASTORE:
value = i32[--sp];
value = f32[--sp];
index = i32[--sp];
array = ref[--sp];
if ((index >>> 0) >= (array.length >>> 0)) {
@ -774,22 +854,46 @@ module J2ME {
}
array[index] = value;
continue;
// case Bytecodes.LASTORE:
// case Bytecodes.DASTORE:
// value = stack.pop2();
// index = stack.pop();
// array = stack.pop();
// checkArrayBounds(array, index);
// array[index] = value;
// break;
// case Bytecodes.AASTORE:
// value = stack.pop();
// index = stack.pop();
// array = stack.pop();
// checkArrayBounds(array, index);
// checkArrayStore(array, value);
// array[index] = value;
// break;
case Bytecodes.LASTORE:
lh = i32[--sp];
ll = i32[--sp];
index = i32[--sp];
array = ref[--sp];
if ((index >>> 0) >= (array.length >>> 0)) {
throw $.newArrayIndexOutOfBoundsException(String(index));
}
array.value[index << 2 ] = ll;
array.value[index << 2 + 1] = lh;
continue;
case Bytecodes.LALOAD:
index = i32[--sp];
array = ref[--sp];
if ((index >>> 0) >= (array.length >>> 0)) {
throw $.newArrayIndexOutOfBoundsException(String(index));
}
i32[sp++] = array.value[index << 2 ];
i32[sp++] = array.value[index << 2 + 1];
continue;
case Bytecodes.DASTORE:
sp -= 2;
value = bufferView.getFloat64(sp << 2);
index = i32[--sp];
array = ref[--sp];
if ((index >>> 0) >= (array.length >>> 0)) {
throw $.newArrayIndexOutOfBoundsException(String(index));
}
array[index] = value;
continue;
case Bytecodes.AASTORE:
value = ref[--sp];
index = i32[--sp];
array = ref[--sp];
if ((index >>> 0) >= (array.length >>> 0)) {
throw $.newArrayIndexOutOfBoundsException(String(index));
}
checkArrayStore(array, value);
array[index] = value;
break;
case Bytecodes.POP:
--sp;
continue;
@ -914,11 +1018,11 @@ module J2ME {
}
ASM._lDiv((sp - 4) >> 2, (sp - 4) >> 2, (sp - 2) >> 2); sp -= 2;
continue;
// case Bytecodes.FDIV:
// b = stack.pop();
// a = stack.pop();
// stack.push(Math.fround(a / b));
// break;
case Bytecodes.FDIV:
fb = f32[--sp];
fa = f32[--sp];
f32[sp++] = Math.fround(fa / fb);
break;
case Bytecodes.DDIV:
fb = popF64();
fa = popF64();
@ -936,11 +1040,11 @@ module J2ME {
}
ASM._lRem((sp - 4) >> 2, (sp - 4) >> 2, (sp - 2) >> 2); sp -= 2;
continue;
// case Bytecodes.FREM:
// b = stack.pop();
// a = stack.pop();
// stack.push(Math.fround(a % b));
// break;
case Bytecodes.FREM:
fb = f32[--sp];
fa = f32[--sp];
f32[sp++] = Math.fround(fa % fb);
break;
// case Bytecodes.DREM:
// b = stack.pop2();
// a = stack.pop2();
@ -1000,69 +1104,38 @@ module J2ME {
// case Bytecodes.LXOR:
// stack.push2(stack.pop2().xor(stack.pop2()));
// break;
// case Bytecodes.LCMP:
// b = stack.pop2();
// a = stack.pop2();
// if (a.greaterThan(b)) {
// stack.push(1);
// } else if (a.lessThan(b)) {
// stack.push(-1);
// } else {
// stack.push(0);
// }
// break;
// case Bytecodes.FCMPL:
// b = stack.pop();
// a = stack.pop();
// if (isNaN(a) || isNaN(b)) {
// stack.push(-1);
// } else if (a > b) {
// stack.push(1);
// } else if (a < b) {
// stack.push(-1);
// } else {
// stack.push(0);
// }
// break;
// case Bytecodes.FCMPG:
// b = stack.pop();
// a = stack.pop();
// if (isNaN(a) || isNaN(b)) {
// stack.push(1);
// } else if (a > b) {
// stack.push(1);
// } else if (a < b) {
// stack.push(-1);
// } else {
// stack.push(0);
// }
// break;
// case Bytecodes.DCMPL:
// b = stack.pop2();
// a = stack.pop2();
// if (isNaN(a) || isNaN(b)) {
// stack.push(-1);
// } else if (a > b) {
// stack.push(1);
// } else if (a < b) {
// stack.push(-1);
// } else {
// stack.push(0);
// }
// break;
// case Bytecodes.DCMPG:
// b = stack.pop2();
// a = stack.pop2();
// if (isNaN(a) || isNaN(b)) {
// stack.push(1);
// } else if (a > b) {
// stack.push(1);
// } else if (a < b) {
// stack.push(-1);
// } else {
// stack.push(0);
// }
// break;
case Bytecodes.LCMP:
ASM._lCmp((sp - 4) >> 2, (sp - 4) >> 2, (sp - 2) >> 2); sp -= 3;
break;
case Bytecodes.FCMPL:
case Bytecodes.FCMPG:
fb = f32[--sp];
fa = f32[--sp];
if (isNaN(fa) || isNaN(fb)) {
i32[sp++] = op === Bytecodes.FCMPL ? -1 : 1;
} else if (fa > fb) {
i32[sp++] = 1;
} else if (fa < fb) {
i32[sp++] = -1;
} else {
i32[sp++] = 0;
}
break;
case Bytecodes.DCMPL:
case Bytecodes.DCMPG:
fb = bufferView.getFloat64(sp - 2 << 2);
fa = bufferView.getFloat64(sp - 4 << 2);
sp -= 4;
if (isNaN(fa) || isNaN(fb)) {
i32[sp++] = op === Bytecodes.DCMPL ? -1 : 1;
} else if (fa > fb) {
i32[sp++] = 1;
} else if (fa < fb) {
i32[sp++] = -1;
} else {
i32[sp++] = 0;
}
break;
case Bytecodes.IFEQ:
targetPC = opPC + (code[pc++] << 8 | code[pc ++]) << 16 >> 16;
if (i32[--sp] === 0) {
@ -1240,70 +1313,50 @@ module J2ME {
size = i32[--sp];
ref[sp++] = newArray(classInfo.klass, size);
continue;
// case Bytecodes.MULTIANEWARRAY:
// index = frame.read16();
// classInfo = resolveClass(index, mi.classInfo);
// var dimensions = frame.read8();
// var lengths = new Array(dimensions);
// for (var i = 0; i < dimensions; i++)
// lengths[i] = stack.pop();
// stack.push(J2ME.newMultiArray(classInfo.klass, lengths.reverse()));
// break;
case Bytecodes.MULTIANEWARRAY:
index = readU16();
classInfo = resolveClass(index, ci);
var dimensions = code[pc++];
var lengths = new Array(dimensions);
for (var i = 0; i < dimensions; i++) {
lengths[i] = i32[--sp];
}
ref[sp++] = J2ME.newMultiArray(classInfo.klass, lengths.reverse());
break;
case Bytecodes.ARRAYLENGTH:
array = ref[--sp];
i32[sp++] = array.length;
continue;
// case Bytecodes.ARRAYLENGTH_IF_ICMPGE:
// array = stack.pop();
// stack.push(array.length);
// frame.pc ++;
// pc = frame.readTargetPC();
// if (stack.pop() <= stack.pop()) {
// frame.pc = pc;
// }
// break;
case Bytecodes.GETFIELD:
index = readI16();
fieldInfo = cp.resolveField(index, false);
object = ref[--sp];
pushKind(fieldInfo.kind, fieldInfo.get(object), 0);
continue;
// case Bytecodes.RESOLVED_GETFIELD:
// fieldInfo = <FieldInfo><any>rp[frame.read16()];
// object = stack.pop();
// stack.pushKind(fieldInfo.kind, fieldInfo.get(object));
// break;
case Bytecodes.PUTFIELD:
index = readI16();
fieldInfo = cp.resolveField(index, false);
value = popKind(fieldInfo.kind);
object = ref[--sp];
fieldInfo.set(object, value);
// frame.patch(3, Bytecodes.PUTFIELD, Bytecodes.RESOLVED_PUTFIELD);
continue;
// case Bytecodes.RESOLVED_PUTFIELD:
// fieldInfo = <FieldInfo><any>rp[frame.read16()];
// value = stack.popKind(fieldInfo.kind);
// object = stack.pop();
// fieldInfo.set(object, value);
// break;
case Bytecodes.GETSTATIC:
index = readI16();
fieldInfo = cp.resolveField(index, true);
classInitAndUnwindCheck(fieldInfo.classInfo, opPC);
//if (U) {
// return;
//}
pushKind(fieldInfo.kind, fieldInfo.getStatic(), 0);
fieldInfo = cp.resolveField(index, false);
if (op === Bytecodes.GETSTATIC) {
classInitAndUnwindCheck(fieldInfo.classInfo, opPC);
//if (U) {
// return;
//}
object = fieldInfo.classInfo.getStaticObject($.ctx);
} else {
object = ref[--sp];
}
pushKindFromAddress(fieldInfo.kind, object._address + fieldInfo.byteOffset);
continue;
case Bytecodes.PUTFIELD:
case Bytecodes.PUTSTATIC:
index = readI16();
fieldInfo = cp.resolveField(index, true);
classInitAndUnwindCheck(fieldInfo.classInfo, opPC);
//if (U) {
// return;
//}
fieldInfo.setStatic(popKind(fieldInfo.kind));
fieldInfo = cp.resolveField(index, false);
if (op === Bytecodes.PUTSTATIC) {
classInitAndUnwindCheck(fieldInfo.classInfo, opPC);
//if (U) {
// return;
//}
object = fieldInfo.classInfo.getStaticObject($.ctx);
popKindIntoAddress(fieldInfo.kind, object._address + fieldInfo.byteOffset);
} else {
popKindIntoAddress(fieldInfo.kind, ref[sp - (isTwoSlot(fieldInfo.kind) ? 3 : 2)]._address + fieldInfo.byteOffset);
sp--;
}
continue;
case Bytecodes.NEW:
index = readI16();
@ -1396,7 +1449,7 @@ module J2ME {
// Resolve method and do the class init check if necessary.
var calleeMethodInfo = cp.resolved[index] || cp.resolveMethod(index, isStatic);
var calleeTargetMethodInfo = calleeMethodInfo;
var calleeTargetMethodInfo = null;
var callee = null;
object = null;
@ -1407,13 +1460,13 @@ module J2ME {
case Bytecodes.INVOKESPECIAL:
checkNull(object);
case Bytecodes.INVOKESTATIC:
callee = calleeMethodInfo.fn || getLinkedMethod(calleeMethodInfo);
calleeTargetMethodInfo = calleeMethodInfo;
break;
case Bytecodes.INVOKEVIRTUAL:
calleeTargetMethodInfo = object.klass.classInfo.vTable[calleeMethodInfo.vTableIndex];
break;
case Bytecodes.INVOKEINTERFACE:
var name = op === Bytecodes.INVOKEVIRTUAL ? calleeMethodInfo.virtualName : calleeMethodInfo.mangledName;
callee = object[name];
calleeTargetMethodInfo = object.klass.classInfo.iTable[calleeMethodInfo.mangledName];
break;
default:
traceWriter && traceWriter.writeLn("Not Implemented: " + Bytecodes[op]);
@ -1427,6 +1480,7 @@ module J2ME {
--sp; // Pop Reference
}
saveThreadState();
callee = calleeTargetMethodInfo.fn || getLinkedMethod(calleeTargetMethodInfo);
result = callee.apply(object, args);
loadThreadState();
if (calleeMethodInfo.returnKind !== Kind.Void) {
@ -1463,7 +1517,9 @@ module J2ME {
continue;
}
} catch (e) {
// traceWriter.writeLn(jsGlobal.getBacktrace());
traceWriter && traceWriter.writeLn("XXXXXX " + e);
traceWriter && traceWriter.writeLn(e.stack);
// traceWriter && traceWriter.writeLn(jsGlobal.getBacktrace());
e = translateException(e);
if (!e.klass) {
// A non-java exception was thrown. Rethrow so it is not handled by tryCatch.
@ -1481,9 +1537,6 @@ module J2ME {
code = mi.codeAttribute.code;
continue;
}
//frame.set(fp, sp, opPC);
// frameView.traceStack(traceWriter);
// frame.trace(traceWriter, fieldInfo);
}
}
}

Просмотреть файл

@ -63,15 +63,15 @@ module J2ME {
}
}
}
// Emit class initializer.
writer.enter("function " + mangledClassName + "() {");
writer.writeLn("this._address = ASM._gcMalloc(" + classInfo.sizeOfFields + ");");
//
// Should we or should we not generate hash codes at this point? Eager or lazy, we should at least
// initialize it zero to keep object shapes fixed.
// writer.writeLn("this._hashCode = $.nextHashCode(this);");
writer.writeLn("this._hashCode = 0;");
emitFields(classInfo.fTable, false);
//writer.writeLn("this._hashCode = 0;");
//emitFields(classInfo.fTable, false);
writer.leave("}");
if (emitter.klassHeaderOnly) {

Просмотреть файл

@ -429,17 +429,18 @@ Native["java/lang/Double.longBitsToDouble.(J)D"] = (function() {
Native["java/lang/Throwable.fillInStackTrace.()V"] = function() {
this.stackTrace = [];
$.ctx.frames.forEach(function(frame) {
if (!frame.methodInfo)
return;
var methodInfo = frame.methodInfo;
var methodName = methodInfo.name;
if (!methodName)
return;
var classInfo = methodInfo.classInfo;
var className = classInfo.getClassNameSlow();
this.stackTrace.unshift({ className: className, methodName: methodName, methodSignature: methodInfo.signature, offset: frame.bci });
}.bind(this));
J2ME.traceWriter && J2ME.traceWriter.writeLn("REDUX");
//$.ctx.frames.forEach(function(frame) {
// if (!frame.methodInfo)
// return;
// var methodInfo = frame.methodInfo;
// var methodName = methodInfo.name;
// if (!methodName)
// return;
// var classInfo = methodInfo.classInfo;
// var className = classInfo.getClassNameSlow();
// this.stackTrace.unshift({ className: className, methodName: methodName, methodSignature: methodInfo.signature, offset: frame.bci });
//}.bind(this));
};
Native["java/lang/Throwable.obtainBackTrace.()Ljava/lang/Object;"] = function() {

Просмотреть файл

@ -80,6 +80,13 @@ module J2ME {
}
}
export function kindSize(kind: Kind): number {
if (isTwoSlot(kind)) {
return 8;
}
return 4;
}
export function kindCharacter(kind: Kind): string {
switch (kind) {
case Kind.Boolean:

Просмотреть файл

@ -3,7 +3,7 @@
all: native.cpp
# Make sure emcc in your path.
emcc -Oz native.cpp -DNDEBUG -o native.raw.js --memory-init-file 0 -s TOTAL_STACK=16384 -s TOTAL_MEMORY=33554432 -s NO_FILESYSTEM=1 -s NO_BROWSER=1 -O3 \
-s 'EXPORTED_FUNCTIONS=["_main", "_lAdd", "_lSub", "_lShl", "_lShr", "_lUshr", "_lMul", "_lDiv", "_lRem"]' \
-s 'EXPORTED_FUNCTIONS=["_main", "_lAdd", "_lSub", "_lShl", "_lShr", "_lUshr", "_lMul", "_lDiv", "_lRem", "_lCmp", "_gcMalloc"]' \
-s 'DEFAULT_LIBRARY_FUNCS_TO_INCLUDE=["memcpy", "memset", "malloc", "free", "puts"]'
echo "var ASM = (function(Module) {" >> native.js
cat native.raw.js >> native.js

Просмотреть файл

@ -1,6 +1,7 @@
#include <stdint.h>
#include <stdlib.h>
int main() {}
uintptr_t heap = 0, bump = 0;
extern "C" {
void lAdd(int64_t *result, int64_t *l, int64_t *r) {
@ -27,6 +28,21 @@ extern "C" {
void lUshr(int64_t *result, int64_t *l, int32_t v) {
*result = (uint64_t)*l >> v;
}
void lCmp(int32_t *result, int64_t *l, int64_t *r) {
if (l > r) {
*result = 1;
} else if (l < r) {
*result = -1;
} else {
*result = 0;
}
}
uintptr_t gcMalloc(int32_t size) {
return bump += (size + 3) & ~0x03;
}
}
int main() {
bump = heap = (uintptr_t)malloc(1024 * 1024 * 16);
}

Просмотреть файл

@ -584,6 +584,7 @@ module J2ME {
public classInfo: ClassInfo;
public kind: Kind;
public name: string;
public byteOffset: number = 0;
public utf8Name: Uint8Array;
public utf8Signature: Uint8Array;
public mangledName: string = null;
@ -607,21 +608,31 @@ module J2ME {
return !!(this.accessFlags & ACCESS_FLAGS.ACC_STATIC);
}
public get(object: java.lang.Object) {
return object[this.mangledName];
}
//public get(object: java.lang.Object) {
// return object[this.mangledName];
//}
//
public set(object: java.lang.Object, value: any) {
object[this.mangledName] = value
}
public getStatic() {
return this.get(this.classInfo.getStaticObject($.ctx));
}
public setStatic(value: any) {
return this.set(this.classInfo.getStaticObject($.ctx), value);
switch (this.kind) {
case Kind.Int:
i32[object._address + this.byteOffset >> 2] = value;
break;
case Kind.Reference:
ref[object._address + this.byteOffset >> 2] = value;
break;
default:
Debug.assert(false, Kind[this.kind]);
}
// object[this.mangledName] = value
}
//
//public getStatic() {
// return this.get(this.classInfo.getStaticObject($.ctx));
//}
//
//public setStatic(value: any) {
// return this.set(this.classInfo.getStaticObject($.ctx), value);
//}
private scanFieldInfoAttributes() {
var s = this;
@ -980,6 +991,8 @@ module J2ME {
accessFlags: number = 0;
vTable: MethodInfo [] = null;
// This is not really a table per se, but rather a map.
iTable: { [name: string]: MethodInfo; } = Object.create(null);
// Custom hash map to make vTable name lookups quicker. It maps utf8 method names to indices in
// the vTable. A zero value indicate no method by that name exists, while a value > 0 indicates
@ -990,6 +1003,9 @@ module J2ME {
fTable: FieldInfo [] = null;
sizeOfFields: number = 0;
sizeOfStaticFields: number = 0;
klass: Klass = null;
private resolvedFlags: ResolvedFlags = ResolvedFlags.None;
private fields: (number | FieldInfo) [] = null;
@ -1119,6 +1135,7 @@ module J2ME {
public complete() {
if (!this.isInterface) {
this.buildVTable();
this.buildITable();
this.buildFTable();
}
loadWriter && this.trace(loadWriter);
@ -1176,7 +1193,27 @@ module J2ME {
}
}
private buildITable() {
var vTable = this.vTable;
var iTable = this.iTable;
for (var i = 0; i < vTable.length; i++) {
var methodInfo = vTable[i];
if (methodInfo.implementsInterface) {
release || assert(methodInfo.mangledName);
release || assert(!iTable[methodInfo.mangledName]);
iTable[methodInfo.mangledName] = methodInfo;
}
}
}
private buildFTable() {
if (this.superClass === null) {
this.sizeOfFields = 0;
this.sizeOfStaticFields = 0;
} else {
this.sizeOfFields = this.superClass.sizeOfFields;
this.sizeOfStaticFields = this.superClass.sizeOfStaticFields;
}
var superClassFTable = this.superClass ? this.superClass.fTable : null;
var fTable = this.fTable = superClassFTable ? superClassFTable.slice() : [];
var fields = this.fields;
@ -1189,8 +1226,12 @@ module J2ME {
fieldInfo.fTableIndex = fTable.length;
fTable.push(fieldInfo); // Append
fieldInfo.mangledName = "f" + fieldInfo.fTableIndex;
fieldInfo.byteOffset = this.sizeOfFields;
this.sizeOfFields += kindSize(fieldInfo.kind);
} else {
fieldInfo.mangledName = "s" + i;
fieldInfo.byteOffset = this.sizeOfStaticFields;
this.sizeOfStaticFields += kindSize(fieldInfo.kind);
}
}
}

Просмотреть файл

@ -212,14 +212,9 @@ module J2ME {
long: null
};
function Int64Array(size: number) {
var array = Array(size);
for (var i = 0; i < size; i++) {
array[i] = Long.ZERO;
}
// We can't put the klass on the prototype.
(<any>array).klass = Klasses.long;
return array;
function Int64Array(length: number) {
this.value = new Int32Array(length * 2);
this.length = length;
}
var arrays = {
@ -857,6 +852,9 @@ module J2ME {
}
export class RuntimeKlass {
_address: number;
templateKlass: Klass;
/**
@ -871,6 +869,7 @@ module J2ME {
// isRuntimeKlass: boolean;
constructor(templateKlass: Klass) {
this._address = ASM._gcMalloc(templateKlass.classInfo.sizeOfStaticFields);
this.templateKlass = templateKlass;
}
}
@ -899,26 +898,27 @@ module J2ME {
$.setClassInitialized(runtimeKlass);
return;
}
var fields = runtimeKlass.templateKlass.classInfo.getFields();
for (var i = 0; i < fields.length; i++) {
var field = fields[i];
if (field.isStatic) {
var kind = getSignatureKind(field.utf8Signature);
var defaultValue;
switch (kind) {
case Kind.Reference:
defaultValue = null;
break;
case Kind.Long:
defaultValue = Long.ZERO;
break;
default:
defaultValue = 0;
break;
}
field.set(<java.lang.Object><any>runtimeKlass, defaultValue);
}
}
//REDUX: No need.
//var fields = runtimeKlass.templateKlass.classInfo.getFields();
//for (var i = 0; i < fields.length; i++) {
// var field = fields[i];
// if (field.isStatic) {
// var kind = getSignatureKind(field.utf8Signature);
// var defaultValue;
// switch (kind) {
// case Kind.Reference:
// defaultValue = null;
// break;
// case Kind.Long:
// defaultValue = Long.ZERO;
// break;
// default:
// defaultValue = 0;
// break;
// }
// field.set(<java.lang.Object><any>runtimeKlass, defaultValue);
// }
//}
}
/**
@ -1296,10 +1296,22 @@ module J2ME {
release || assert(!field.isStatic, "Static field was defined as instance in BindingsMap");
var object = field.isStatic ? klass : klass.prototype;
release || assert (!object.hasOwnProperty(fieldName), "Should not overwrite existing properties.");
var getter = FunctionUtilities.makeForwardingGetter(field.mangledName);
var getter;
var setter;
if (release) {
setter = FunctionUtilities.makeForwardingSetter(field.mangledName);
if (true || release) {
switch (field.kind) {
case Kind.Reference:
setter = new Function("value", "ref[this._address + " + field.byteOffset + " >> 2] = value;");
getter = new Function("return ref[this._address + " + field.byteOffset + " >> 2];");
break;
case Kind.Int:
setter = new Function("value", "i32[this._address + " + field.byteOffset + " >> 2] = value;");
getter = new Function("return i32[this._address + " + field.byteOffset + " >> 2];");
break;
default:
Debug.assert(false, Kind[field.kind]);
break;
}
} else {
setter = FunctionUtilities.makeDebugForwardingSetter(field.mangledName, getKindCheck(field.kind));
}
@ -1405,7 +1417,7 @@ module J2ME {
}
linkKlass(methodInfo.classInfo);
linkKlassMethod(methodInfo.classInfo.klass, methodInfo);
assert (methodInfo.fn);
release || assert (methodInfo.fn);
return methodInfo.fn;
}