1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
|
var EmJVM = {
debug: false,
nextId: 0,
objects: {},
classNames: {}, // class name => singleton object
addObject: function(o) {
var ret = EmJVM.nextId++;
EmJVM.objects[ret] = o;
o.id = ret;
o.refs = 1;
o.nextMethodId = 0;
// XXX Module.print('add object ' + JSON.stringify(o).substr(0, 80) + (ret > 5285 ? new Error().stack : ''));
return ret;
},
addSingletonObject: function(o) {
EmJVM.classNames[o.name] = o;
return EmJVM.addObject(o);
},
createString: function(data) {
return EmJVM.addObject({ name: 'string', value: data });
},
createByteArray: function(data) {
return EmJVM.addObject({ name: 'byteArray', value: data });
},
};
function widecharToString(ptr, len) {
var nullTerminated = typeof(len) == "undefined";
var ret = "";
var i = 0;
var t;
while (1) {
t = getValue(ptr + 2 * i, 'i16');
if (nullTerminated && t == 0) break;
if (t != 0) {
ret += String.fromCharCode(t);
}
++i;
if (!nullTerminated && i == len) break;
};
return ret;
}
function _emjvm_newString(chars, len) {
return EmJVM.createString(widecharToString(chars, len));
}
function _emjvm_getStringUTFChars(jniEnv, string, isCopy) {
var obj = EmJVM.objects[string];
assert(obj.name == 'string');
if (isCopy) setValue(isCopy, 'i8', 1);
var buffer = _malloc(obj.value.length+1);
writeStringToMemory(obj.value, buffer);
return buffer;
}
function _emjvm_getStringUTFLength(jniEnv, string) {
var obj = EmJVM.objects[string];
if (obj.value) {
return obj.value.length;
}
return 0;
}
function _emjvm_releaseStringUTFChars(jniEnv, string, utf) {
}
function _emjvm_getObjectClass(env, jobject) {
if (EmJVM.debug) {
console.log('EMJVM_GetObjectClass+AddLocalRef: ' + [jobject]);
}
var obj = EmJVM.objects[jobject];
obj.refs++;
return jobject;
}
function _emjvm_getMethodID(jclass, name, sig) {
if (EmJVM.debug) {
console.log('EMJVM_GetMethodID: ' + [jclass, Pointer_stringify(name), Pointer_stringify(sig)]);
console.log('EMJVM_GetMethodID: ' + [EmJVM.objects[jclass].name]);
}
// assumes class <--> object, just called on singletons
name = Pointer_stringify(name);
var obj = EmJVM.objects[jclass];
if (!obj[name]) {
throw 'missing implementation for ' + obj.name + '::' + name + ' : ' + new Error().stack;
}
if (!obj[name + '__methodId']) {
var methodId = obj.nextMethodId++;
obj[name + '__methodId'] = methodId;
obj['method__' + methodId] = obj[name];
obj['methodName__' + methodId] = name;
}
return obj[name + '__methodId'];
}
function _emjvm_getStaticMethodID(jniEnv, jclass, name, sig) {
// Pretend this to be the same as looking up a non-static method
return _emjvm_getMethodID(jclass, name, sig);
}
function _emjvm_callObjectMethod(jniEnv, jobject, methodId, varargs) {
if (EmJVM.debug) {
console.log('EMJVM_CallObjectMethod: ' + [jobject, EmJVM.objects[jobject].name, methodId, EmJVM.objects[jobject]['methodName__' + methodId]]);
}
return EmJVM.objects[jobject]['method__' + methodId](varargs);
}
function _emjvm_callStaticObjectMethod(jniEnv, jclass, methodId, varargs) {
// Pretend this to be the same as calling a non-static method
return _emjvm_callObjectMethod(jniEnv, jclass, methodId, varargs);
}
function _emjvm_callStaticBooleanMethod(jniEnv, jclass, methodId, varargs) {
// Only differs in return type
return _emjvm_callStaticObjectMethod(jniEnv, jclass, methodId, varargs);
}
function _emjvm_callBooleanMethod(jniEnv, jobject, methodId, varargs) {
// Pretend this to be the same as calling a non-static method
return _emjvm_callStaticBooleanMethod(jniEnv, jobject, methodId, varargs);
}
function _emjvm_callVoidMethod(jniEnv, jobject, methodId, varargs) {
_emjvm_callObjectMethod(jniEnv, jobject, methodId, varargs);
}
function _emjvm_callIntMethod(jniEnv, jobject, methodId, varargs) {
return _emjvm_callObjectMethod(jniEnv, jobject, methodId, varargs);
}
function _emjvm_deleteLocalRef(jniEnv, jobject) {
if (EmJVM.debug) {
console.log('EMJVM_DeleteLocalRef: ' + [jobject]);
}
var obj = EmJVM.objects[jobject];
obj.refs--;
if (obj.refs == 0) {
if (EmJVM.debug) {
console.log('EMJVM_DeleteLocalRef: remove ' + obj.name);
}
delete EmJVM.objects[jobject];
}
}
function _emjvm_getArrayLength(jniEnv, jobject) {
var obj = EmJVM.objects[jobject];
assert(obj.name == 'byteArray');
return obj.value.length;
}
function _emjvm_getByteArrayRegion(jniEnv, jobject, start, len, buf) {
var obj = EmJVM.objects[jobject];
assert(obj.name == 'byteArray');
assert(obj.value); // we set this to null below and assume we are never called again
if (EmJVM.debug) {
console.log('emjvm_getByteArrayRegion: ' + [jobject, obj.value.length, start, len, buf]);
}
assert(start + len <= obj.value.length);
assert(len == obj.value.length); // we assume users read it all, and we can now copy it all with set() and then free it
HEAPU8.set(obj.value, buf);
obj.value = null; // XXX assume byte arrays are one-shot
}
function _emjvm_findClass(env, name) {
name = Pointer_stringify(name);
if (EmJVM.debug) {
console.log('emjvm_findClass: ' + [name]);
}
var obj = EmJVM.classNames[name];
assert(obj);
return obj.id;
}
|