diff options
author | Alon Zakai <alonzakai@gmail.com> | 2013-03-22 16:22:16 -0700 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2013-03-22 16:22:16 -0700 |
commit | a8e4801c7d38033fff760ea26a4579aa324e303e (patch) | |
tree | 01c8c9862f7a6e1b60569aa9be97fd2751be8709 | |
parent | 669c786e3554b280e31dcb7bd92931482547dae0 (diff) | |
parent | f99012f271c056ddc171f6a4ec011ad31ad936cd (diff) |
Merge branch 'incoming'
-rwxr-xr-x | emcc | 5 | ||||
-rwxr-xr-x | emscripten.py | 1 | ||||
-rw-r--r-- | src/analyzer.js | 3 | ||||
-rw-r--r-- | src/compiler.js | 2 | ||||
-rw-r--r-- | src/jsifier.js | 17 | ||||
-rw-r--r-- | src/library.js | 12 | ||||
-rw-r--r-- | src/library_browser.js | 2 | ||||
-rw-r--r-- | src/library_glut.js | 2 | ||||
-rw-r--r-- | src/library_openal.js | 28 | ||||
-rw-r--r-- | src/parseTools.js | 2 | ||||
-rw-r--r-- | src/postamble.js | 20 | ||||
-rw-r--r-- | src/settings.js | 6 | ||||
-rw-r--r-- | src/utility.js | 7 | ||||
-rw-r--r-- | tests/cases/floatreturningfuncptr.ll | 18 | ||||
-rw-r--r-- | tests/emscripten_api_browser_infloop.cpp | 12 | ||||
-rwxr-xr-x | tests/runner.py | 8 | ||||
-rw-r--r-- | third_party/jni/emjvm.js | 333 | ||||
-rw-r--r-- | tools/shared.py | 2 |
18 files changed, 254 insertions, 226 deletions
@@ -993,6 +993,8 @@ try: # Apply effects from settings if shared.Settings.ASM_JS: + assert opt_level == 2, 'asm.js requires -O2' + if closure: print >> sys.stderr, 'emcc: warning: disabling closure because it is not compatible with asm.js code generation' closure = False @@ -1228,7 +1230,8 @@ try: shutil.move(temp_files[0], in_temp(target_basename + '.bc')) final = in_temp(target_basename + '.bc') else: - final = input_files[0] + final = in_temp(input_files[0]) + shutil.copyfile(input_files[0], final) if DEBUG: print >> sys.stderr, 'emcc: saving intermediate processing steps to %s' % shared.EMSCRIPTEN_TEMP_DIR diff --git a/emscripten.py b/emscripten.py index c9d8505d..1b62d977 100755 --- a/emscripten.py +++ b/emscripten.py @@ -161,6 +161,7 @@ def emscript(infile, settings, outfile, libraries=[], compiler_engine=None, open(pre_file, 'w').write(pre_input) out = jsrun.run_js(compiler, compiler_engine, [settings_file, pre_file, 'pre'] + libraries, stdout=subprocess.PIPE, cwd=path_from_root('src')) + assert '//FORWARDED_DATA:' in out, 'Did not receive forwarded data in pre output - process failed?' if jcache: if DEBUG: print >> sys.stderr, ' saving pre to jcache' jcache.set(shortkey, keys, out) diff --git a/src/analyzer.js b/src/analyzer.js index 92b7d8cf..b1991c3f 100644 --- a/src/analyzer.js +++ b/src/analyzer.js @@ -979,6 +979,9 @@ function analyzer(data, sidePass) { if (variable.origin === 'alloca') { variable.allocatedNum = item.allocatedNum; } + if (variable.origin === 'call') { + variable.type = getReturnType(variable.type); + } } }); diff --git a/src/compiler.js b/src/compiler.js index bb72c7dd..7cf43f09 100644 --- a/src/compiler.js +++ b/src/compiler.js @@ -178,7 +178,7 @@ assert(!(USE_TYPED_ARRAYS === 2 && QUANTUM_SIZE !== 4), 'For USE_TYPED_ARRAYS == if (ASM_JS) { assert(!ALLOW_MEMORY_GROWTH, 'Cannot grow asm.js heap'); assert((TOTAL_MEMORY&(TOTAL_MEMORY-1)) == 0, 'asm.js heap must be power of 2'); - assert(DISABLE_EXCEPTION_CATCHING == 1, 'asm.js does not support C++ exceptions yet'); + assert(DISABLE_EXCEPTION_CATCHING == 1, 'asm.js does not support C++ exceptions yet, you must compile with -s DISABLE_EXCEPTION_CATCHING=1'); } assert(!(!NAMED_GLOBALS && BUILD_AS_SHARED_LIB)); // shared libraries must have named globals diff --git a/src/jsifier.js b/src/jsifier.js index 7db2ee70..c55072b4 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -495,10 +495,10 @@ function JSify(data, functionsOnly, givenFunctions) { EXPORTED_FUNCTIONS[ident] = 1; delete Functions.libraryFunctions[ident.substr(1)]; } - } else { - if (EXPORT_ALL || (ident in EXPORTED_FUNCTIONS)) { - contentText += '\nModule["' + ident + '"] = ' + ident + ';'; - } + } + if ((!ASM_JS || phase == 'pre') && + (EXPORT_ALL || (ident in EXPORTED_FUNCTIONS))) { + contentText += '\nModule["' + ident + '"] = ' + ident + ';'; } return depsText + contentText; } @@ -515,7 +515,7 @@ function JSify(data, functionsOnly, givenFunctions) { if (!(item.ident in DEAD_FUNCTIONS) && !UNRESOLVED_AS_DEAD) { item.JS = 'var ' + item.ident + '; // stub for ' + item.ident; if (ASM_JS) { - throw 'Unresolved symbol: ' + item.ident + ', this must be corrected for asm.js validation to succeed. Consider adding it to DEAD_FUNCTIONS.'; + error('Unresolved symbol: ' + item.ident + ', this must be corrected for asm.js validation to succeed. Consider adding it to DEAD_FUNCTIONS.'); } else if (WARN_ON_UNDEFINED_SYMBOLS) { warn('Unresolved symbol: ' + item.ident); } @@ -1167,6 +1167,11 @@ function JSify(data, functionsOnly, givenFunctions) { return ret + ';'; }); makeFuncLineActor('resume', function(item) { + if (item.ident == 0) { + // No exception to resume, so we can just bail. + // This is related to issue #917 and http://llvm.org/PR15518 + return (EXCEPTION_DEBUG ? 'Module.print("no exception to resume")' : '') + ';'; + } // If there is no current exception, set this one as it (during a resume, the current exception can be wiped out) var ptr = makeStructuralAccess(item.ident, 0); return (EXCEPTION_DEBUG ? 'Module.print("Resuming exception");' : '') + @@ -1566,6 +1571,8 @@ function JSify(data, functionsOnly, givenFunctions) { } } + if (abortExecution) throw 'Aborting compilation due to previous warnings'; + if (phase == 'pre' || phase == 'funcs') { PassManager.serialize(); return; diff --git a/src/library.js b/src/library.js index aebad63b..f8ea67ba 100644 --- a/src/library.js +++ b/src/library.js @@ -2061,24 +2061,19 @@ LibraryManager.library = { // void _exit(int status); // http://pubs.opengroup.org/onlinepubs/000095399/functions/exit.html -#if CATCH_EXIT_CODE function ExitStatus() { this.name = "ExitStatus"; this.message = "Program terminated with exit(" + status + ")"; this.status = status; + Module.print('Exit Status: ' + status); }; ExitStatus.prototype = new Error(); ExitStatus.prototype.constructor = ExitStatus; -#endif exitRuntime(); ABORT = true; -#if CATCH_EXIT_CODE throw new ExitStatus(); -#else - throw 'exit(' + status + ') called, at ' + new Error().stack; -#endif }, fork__deps: ['__setErrNo', '$ERRNO_CODES'], fork: function() { @@ -3717,6 +3712,11 @@ LibraryManager.library = { __exit(status); }, + _ZSt9terminatev__deps: ['exit'], + _ZSt9terminatev: function() { + _exit(-1234); + }, + atexit: function(func, arg) { __ATEXIT__.unshift({ func: func, arg: arg }); }, diff --git a/src/library_browser.js b/src/library_browser.js index e61f84b5..b1e4190b 100644 --- a/src/library_browser.js +++ b/src/library_browser.js @@ -637,7 +637,7 @@ mergeInto(LibraryManager.library, { Browser.mainLoop.scheduler(); if (simulateInfiniteLoop) { - throw 'emscripten_set_main_loop simulating infinite loop by throwing so we get right into the JS event loop'; + throw 'SimulateInfiniteLoop'; } }, diff --git a/src/library_glut.js b/src/library_glut.js index bb4dfefa..49380367 100644 --- a/src/library_glut.js +++ b/src/library_glut.js @@ -433,7 +433,7 @@ var LibraryGLUT = { glutMainLoop: function() { _glutReshapeWindow(Module['canvas'].width, Module['canvas'].height); _glutPostRedisplay(); - throw 'GLUT mainloop called, simulating infinite loop by throwing so we get right into the JS event loop'; + throw 'SimulateInfiniteLoop'; }, }; diff --git a/src/library_openal.js b/src/library_openal.js index 719d8cf8..df1d15db 100644 --- a/src/library_openal.js +++ b/src/library_openal.js @@ -57,7 +57,6 @@ var LibraryOpenAL = { } if (ctx) { - ctx.listener.panningModel = "equalpower"; AL.contexts.push({ctx: ctx, err: 0, src: [], buf: []}); return AL.contexts.length; } else { @@ -73,6 +72,12 @@ var LibraryOpenAL = { } }, + alcGetError__deps: ['alGetError'], + alcGetError: function(device) { + // We have only one audio device, so just return alGetError. + return _alGetError(); + }, + alDeleteSources: function(count, sources) { if (!AL.currentContext) { @@ -97,14 +102,9 @@ var LibraryOpenAL = { for (var i = 0; i < count; ++i) { var gain = AL.currentContext.ctx.createGain(); var panner = AL.currentContext.ctx.createPanner(); - if (typeof(webkitAudioContext) == 'function') { - gain.connect(panner); - panner.connect(AL.currentContext.ctx.destination); - } else { - // Work around a Firefox bug (bug 849916) - gain.connect(AL.currentContext.ctx.destination); - } - gain.gain.value = 1; // work around a Firefox bug (bug 850970) + panner.panningModel = "equalpower"; + gain.connect(panner); + panner.connect(AL.currentContext.ctx.destination); AL.currentContext.src.push({ loop: false, buffer: null, @@ -404,8 +404,7 @@ var LibraryOpenAL = { src.buffer = AL.currentContext.src[source - 1].buffer; src.connect(AL.currentContext.src[source - 1].gain); src.start(0, offset); - // Work around Firefox bug 851338 - AL.currentContext.src[source - 1].playTime = AL.currentContext.ctx.currentTime || 0; + AL.currentContext.src[source - 1].playTime = AL.currentContext.ctx.currentTime; AL.currentContext.src[source - 1].paused = false; AL.currentContext.src[source - 1]['src'] = src; }, @@ -445,8 +444,7 @@ var LibraryOpenAL = { if ("src" in AL.currentContext.src[source - 1] && !AL.currentContext.src[source - 1].paused) { AL.currentContext.src[source - 1].paused = true; - // Work around Firefox bug 851338 - AL.currentContext.src[source - 1].pausedTime = AL.currentContext.ctx.currentTime || 0; + AL.currentContext.src[source - 1].pausedTime = AL.currentContext.ctx.currentTime; AL.currentContext.src[source - 1]["src"].stop(0); delete AL.currentContext.src[source - 1].src; } @@ -572,10 +570,6 @@ var LibraryOpenAL = { alcGetProcAddress: function(device, fname) { return 0; }, - - alcGetError: function(device) { - return 0; - }, }; autoAddDeps(LibraryOpenAL, '$AL'); diff --git a/src/parseTools.js b/src/parseTools.js index 9fddacbb..d0d3e89f 100644 --- a/src/parseTools.js +++ b/src/parseTools.js @@ -999,7 +999,7 @@ function getHeapOffset(offset, type, forceAsm) { offset = '(' + offset + ')'; if (shifts != 0) { if (CHECK_HEAP_ALIGN) { - return '(CHECK_ALIGN_' + sz + '(' + offset + ')>>' + shifts + ')'; + return '(CHECK_ALIGN_' + sz + '(' + offset + '|0)>>' + shifts + ')'; } else { return '(' + offset + '>>' + shifts + ')'; } diff --git a/src/postamble.js b/src/postamble.js index 00205abc..dd4f4f37 100644 --- a/src/postamble.js +++ b/src/postamble.js @@ -23,18 +23,21 @@ Module.callMain = function callMain(args) { var ret; -#if CATCH_EXIT_CODE var initialStackTop = STACKTOP; try { ret = Module['_main'](argc, argv, 0); } - catch(e) { if (e.name == "ExitStatus") return e.status; throw e; } - finally { + catch(e) { + if (e.name == 'ExitStatus') { + return e.status; + } else if (e == 'SimulateInfiniteLoop') { + Module['noExitRuntime'] = true; + } else { + throw e; + } + } finally { STACKTOP = initialStackTop; } -#else - ret = Module['_main'](argc, argv, 0); -#endif #if BENCHMARK Module.realPrint('main() took ' + (Date.now() - start) + ' milliseconds'); @@ -121,10 +124,7 @@ if (Module['noInitialRun']) { } if (shouldRunNow) { - var ret = run(); -#if CATCH_EXIT_CODE - Module.print('Exit Status: ' + ret); -#endif + run(); } // {{POST_RUN_ADDITIONS}} diff --git a/src/settings.js b/src/settings.js index 97963ac5..9ed87bd6 100644 --- a/src/settings.js +++ b/src/settings.js @@ -113,12 +113,6 @@ var INLINING_LIMIT = 0; // A limit on inlining. If 0, we will inline normally i // we will prevent inlining of functions of this size or larger // in closure. 50 is a reasonable setting if you do not want // inlining -var CATCH_EXIT_CODE = 0; // If set, causes exit() to throw an exception object which is caught - // in a try..catch block and results in the exit status being - // returned from run(). If zero (the default), the program is just - // terminated with an error message, that is, the exception thrown - // by exit() is not handled in any way (in particular, the stack - // position will not be reset). // Generated code debugging options var SAFE_HEAP = 0; // Check each write to the heap, for example, this will give a clear diff --git a/src/utility.js b/src/utility.js index 19444675..b67e6c21 100644 --- a/src/utility.js +++ b/src/utility.js @@ -85,6 +85,13 @@ function warnOnce(a, msg) { } } +var abortExecution = false; + +function error(msg) { + abortExecution = true; + printErr('Error: ' + msg); +} + function dedup(items, ident) { var seen = {}; if (ident) { diff --git a/tests/cases/floatreturningfuncptr.ll b/tests/cases/floatreturningfuncptr.ll new file mode 100644 index 00000000..e07e97b3 --- /dev/null +++ b/tests/cases/floatreturningfuncptr.ll @@ -0,0 +1,18 @@ +; ModuleID = 'tests/hello_world.bc' +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32-S128" +target triple = "i386-pc-linux-gnu" + +@.str = private unnamed_addr constant [15 x i8] c"hello, world!\0A\00", align 1 ; [#uses=1 type=[15 x i8]*] + +; [#uses=0] +define i32 @main() { +entry: + %retval = alloca i32, align 4 ; [#uses=1 type=i32*] + store i32 0, i32* %retval + %call = call float (i8*, ...)* @printf(i8* getelementptr inbounds ([15 x i8]* @.str, i32 0, i32 0)) ; [#uses=0 type=i32] + %call2 = call float (i8*, ...)* @printf(i8* getelementptr inbounds ([15 x i8]* @.str, i32 0, i32 0), float %call) ; [#uses=0 type=i32] + ret i32 1 +} + +; [#uses=1] +declare float @printf(i8*, ...) diff --git a/tests/emscripten_api_browser_infloop.cpp b/tests/emscripten_api_browser_infloop.cpp index 0fd41922..1e9808da 100644 --- a/tests/emscripten_api_browser_infloop.cpp +++ b/tests/emscripten_api_browser_infloop.cpp @@ -8,17 +8,15 @@ struct Class { int x; Class() : x(0) {} + ~Class() { x = -9999; } void print() { - char buf[18]; - memset(buf, 0, 18); // clear stack. if we did not simulate infinite loop, this clears x and is a bug! - x += buf[7]; - printf("waka %d\n", x++); - if (x == 7) { + if (x == 7 || x < 0) { int result = x; REPORT_RESULT(); + emscripten_cancel_main_loop(); } } @@ -28,7 +26,9 @@ struct Class { void start() { instance = this; - emscripten_set_main_loop(Class::callback, 3, 1); // important if we simulate an infinite loop here or not + // important if we simulate an infinite loop here or not. With an infinite loop, the + // destructor should *NOT* have been called + emscripten_set_main_loop(Class::callback, 3, 1); } }; diff --git a/tests/runner.py b/tests/runner.py index 168567d2..f0b5445c 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -2716,7 +2716,6 @@ Exiting setjmp function, level: 0, prev_jmp: -1 if Settings.ASM_JS: return self.skip('uses report_stack without exporting') Settings.INLINING_LIMIT = 50 - Settings.CATCH_EXIT_CODE = 1 src = r''' #include <stdio.h> @@ -2757,7 +2756,7 @@ Exiting setjmp function, level: 0, prev_jmp: -1 ''') self.emcc_args += ['--pre-js', 'pre.js'] - self.do_run(src, '''reported\npostRun\nok.\nExit Status: 1\n''') + self.do_run(src, '''reported\nExit Status: 1\npostRun\nok.\n''') def test_class(self): src = ''' @@ -8673,8 +8672,6 @@ def process(filename): Settings.CORRECT_SIGNS = 0 def test_exit_status(self): - Settings.CATCH_EXIT_CODE = 1 - src = r''' #include <stdio.h> #include <stdlib.h> @@ -8869,7 +8866,6 @@ class %s(T): Settings.INCLUDE_FULL_LIBRARY = 0 Settings.BUILD_AS_SHARED_LIB = 0 Settings.RUNTIME_LINKED_LIBS = [] - Settings.CATCH_EXIT_CODE = 0 Settings.EMULATE_UNALIGNED_ACCESSES = int(Settings.USE_TYPED_ARRAYS == 2 and Building.LLVM_OPTS == 2) Settings.DOUBLE_MODE = 1 if Settings.USE_TYPED_ARRAYS and Building.LLVM_OPTS == 0 else 0 Settings.PRECISE_I64_MATH = 0 @@ -10079,7 +10075,7 @@ f.close() (1, 0, 3, 2), (1, 1, 3, 4) ]: print asm, linkable, chunks, js_chunks - output, err = Popen([PYTHON, EMCC, path_from_root('tests', 'hello_libcxx.cpp'), '-O1', '-s', 'LINKABLE=%d' % linkable, '-s', 'ASM_JS=%d' % asm, '-s', 'UNRESOLVED_AS_DEAD=1'], stdout=PIPE, stderr=PIPE).communicate() + output, err = Popen([PYTHON, EMCC, path_from_root('tests', 'hello_libcxx.cpp'), '-O1', '-s', 'LINKABLE=%d' % linkable, '-s', 'ASM_JS=%d' % asm, '-s', 'UNRESOLVED_AS_DEAD=1'] + (['-O2'] if asm else []), stdout=PIPE, stderr=PIPE).communicate() ok = False for c in range(chunks, chunks+2): ok = ok or ('phase 2 working on %d chunks' % c in err) diff --git a/third_party/jni/emjvm.js b/third_party/jni/emjvm.js index e422d208..6a8da080 100644 --- a/third_party/jni/emjvm.js +++ b/third_party/jni/emjvm.js @@ -1,180 +1,185 @@ +mergeInto(LibraryManager.library, { + $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 }); + }, + + // utils + + widecharToString: function(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; + }, + }, -var EmJVM = { - debug: false, + emjvm_newString__deps: ['$EmJVM'], + emjvm_newString: function(chars, len) { + return EmJVM.createString(EmJVM.widecharToString(chars, len)); + }, - nextId: 0, - objects: {}, - classNames: {}, // class name => singleton object + emjvm_getStringUTFChars: function(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; + }, - 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; + emjvm_getStringUTFLength: function(jniEnv, string) { + var obj = EmJVM.objects[string]; + if (obj.value) { + return obj.value.length; + } + return 0; }, - addSingletonObject: function(o) { - EmJVM.classNames[o.name] = o; - return EmJVM.addObject(o); + emjvm_releaseStringUTFChars: function(jniEnv, string, utf) { }, - createString: function(data) { - return EmJVM.addObject({ name: 'string', value: data }); + emjvm_getObjectClass__deps: ['$EmJVM'], + emjvm_getObjectClass: function(env, jobject) { + if (EmJVM.debug) { + console.log('EMJVM_GetObjectClass+AddLocalRef: ' + [jobject]); + } + var obj = EmJVM.objects[jobject]; + obj.refs++; + return jobject; }, - createByteArray: function(data) { - return EmJVM.addObject({ name: 'byteArray', value: data }); + emjvm_getMethodID: function(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 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); + emjvm_getStaticMethodID: function(jniEnv, jclass, name, sig) { + // Pretend this to be the same as looking up a non-static method + return _emjvm_getMethodID(jclass, name, sig); + }, + + emjvm_callObjectMethod: function(jniEnv, jobject, methodId, varargs) { + if (EmJVM.debug) { + console.log('EMJVM_CallObjectMethod: ' + [jobject, EmJVM.objects[jobject].name, methodId, EmJVM.objects[jobject]['methodName__' + methodId]]); } - ++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 EmJVM.objects[jobject]['method__' + methodId](varargs); + }, + + emjvm_callStaticObjectMethod: function(jniEnv, jclass, methodId, varargs) { + // Pretend this to be the same as calling a non-static method + return _emjvm_callObjectMethod(jniEnv, jclass, methodId, varargs); + }, + + emjvm_callStaticBooleanMethod: function(jniEnv, jclass, methodId, varargs) { + // Only differs in return type + return _emjvm_callStaticObjectMethod(jniEnv, jclass, methodId, varargs); + }, + + emjvm_callBooleanMethod: function(jniEnv, jobject, methodId, varargs) { + // Pretend this to be the same as calling a non-static method + return _emjvm_callStaticBooleanMethod(jniEnv, jobject, methodId, varargs); + }, + + emjvm_callVoidMethod: function(jniEnv, jobject, methodId, varargs) { + _emjvm_callObjectMethod(jniEnv, jobject, methodId, varargs); + }, + + emjvm_callIntMethod: function(jniEnv, jobject, methodId, varargs) { + return _emjvm_callObjectMethod(jniEnv, jobject, methodId, varargs); + }, + + emjvm_deleteLocalRef: function(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]; + } + }, + + emjvm_getArrayLength: function(jniEnv, jobject) { + var obj = EmJVM.objects[jobject]; + assert(obj.name == 'byteArray'); 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) { + }, + + emjvm_getByteArrayRegion: function(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_DeleteLocalRef: remove ' + obj.name); + console.log('emjvm_getByteArrayRegion: ' + [jobject, obj.value.length, start, len, buf]); } - 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; -} + 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 + }, + + emjvm_findClass: function(env, name) { + name = Pointer_stringify(name); + if (EmJVM.debug) { + console.log('emjvm_findClass: ' + [name]); + } + var obj = EmJVM.classNames[name]; + assert(obj); + return obj.id; + }, +}); diff --git a/tools/shared.py b/tools/shared.py index 3d0f90b9..49b456f9 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -181,7 +181,7 @@ def check_node_version(): # we re-check sanity when the settings are changed) # We also re-check sanity and clear the cache when the version changes -EMSCRIPTEN_VERSION = '1.3.1' +EMSCRIPTEN_VERSION = '1.3.2' def check_sanity(force=False): try: |