aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler.js6
-rw-r--r--src/jsifier.js43
-rw-r--r--src/library.js74
-rw-r--r--src/library_gc.js7
-rw-r--r--src/parseTools.js5
-rw-r--r--src/postamble.js6
-rw-r--r--src/preamble.js59
-rw-r--r--src/runtime.js17
-rw-r--r--src/settings.js3
-rw-r--r--tests/cases/gepoverflow.txt2
-rw-r--r--tests/fcntl/output.txt2
-rw-r--r--tests/fcntl/src.c2
-rwxr-xr-xtests/runner.py10
13 files changed, 132 insertions, 104 deletions
diff --git a/src/compiler.js b/src/compiler.js
index 313fd5f7..8b9606f1 100644
--- a/src/compiler.js
+++ b/src/compiler.js
@@ -184,6 +184,7 @@ if (ASM_JS) {
assert((TOTAL_MEMORY&(TOTAL_MEMORY-1)) == 0, 'asm.js heap must be power of 2');
}
assert(!(!NAMED_GLOBALS && BUILD_AS_SHARED_LIB)); // shared libraries must have named globals
+assert(!BUILD_AS_SHARED_LIB, 'shared libs are deprecated');
// Output some info and warnings based on settings
@@ -208,7 +209,10 @@ load('parseTools.js');
load('intertyper.js');
load('analyzer.js');
load('jsifier.js');
-if (RELOOP) load(RELOOPER)
+if (RELOOP) {
+ load(RELOOPER);
+ assert(typeof Relooper != 'undefined');
+}
globalEval(processMacros(preprocess(read('runtime.js'))));
Runtime.QUANTUM_SIZE = QUANTUM_SIZE;
diff --git a/src/jsifier.js b/src/jsifier.js
index c21e7995..8270b443 100644
--- a/src/jsifier.js
+++ b/src/jsifier.js
@@ -1546,13 +1546,9 @@ function JSify(data, functionsOnly, givenFunctions) {
if (!mainPass) {
if (phase == 'pre' && !Variables.generatedGlobalBase) {
Variables.generatedGlobalBase = true;
- if (Variables.nextIndexedOffset > 0) {
- // Variables have been calculated, get to base stuff before we print them
- // GLOBAL_BASE is statically known to be equal to STACK_MAX and to TOTAL_STACK, assert on this
- print('assert(STATICTOP == STACK_MAX); assert(STACK_MAX == TOTAL_STACK);\n');
- print('STATICTOP += ' + Variables.nextIndexedOffset + ';\n');
- print('assert(STATICTOP < TOTAL_MEMORY);\n');
- }
+ // Globals are done, here is the rest of static memory
+ print('STATIC_BASE = ' + Runtime.GLOBAL_BASE + ';\n');
+ print('STATICTOP = STATIC_BASE + ' + Runtime.alignMemory(Variables.nextIndexedOffset) + ';\n');
}
var generated = itemsDict.function.concat(itemsDict.type).concat(itemsDict.GlobalVariableStub).concat(itemsDict.GlobalVariable);
print(generated.map(function(item) { return item.JS }).join('\n'));
@@ -1573,13 +1569,13 @@ function JSify(data, functionsOnly, givenFunctions) {
// possibly function table {{{ FT_* }}} etc.
if (value.indexOf('{{ ') < 0) return true;
}
- writeInt8s(memoryInitialization, target - TOTAL_STACK, value, type);
+ writeInt8s(memoryInitialization, target - Runtime.GLOBAL_BASE, value, type);
return false;
}
return true;
});
// write out the singleton big memory initialization value
- print('/* memory initializer */ ' + makePointer(memoryInitialization, null, 'ALLOC_NONE', 'i8', 'TOTAL_STACK', true)); // we assert on TOTAL_STACK == GLOBAL_BASE
+ print('/* memory initializer */ ' + makePointer(memoryInitialization, null, 'ALLOC_NONE', 'i8', 'Runtime.GLOBAL_BASE', true));
} else {
print('/* no memory initializer */'); // test purposes
}
@@ -1589,6 +1585,27 @@ function JSify(data, functionsOnly, givenFunctions) {
print(itemsDict.GlobalVariablePostSet.map(function(item) { return item.JS }).join('\n'));
print('}\n');
print('if (!awaitingMemoryInitializer) runPostSets();\n'); // if we load the memory initializer, this is done later
+
+ if (USE_TYPED_ARRAYS == 2) {
+ print('var tempDoublePtr = Runtime.alignMemory(allocate(12, "i8", ALLOC_STATIC), 8);\n');
+ print('assert(tempDoublePtr % 8 == 0);\n');
+ print('function copyTempFloat(ptr) { // functions, because inlining this code increases code size too much\n');
+ print(' HEAP8[tempDoublePtr] = HEAP8[ptr];\n');
+ print(' HEAP8[tempDoublePtr+1] = HEAP8[ptr+1];\n');
+ print(' HEAP8[tempDoublePtr+2] = HEAP8[ptr+2];\n');
+ print(' HEAP8[tempDoublePtr+3] = HEAP8[ptr+3];\n');
+ print('}\n');
+ print('function copyTempDouble(ptr) {\n');
+ print(' HEAP8[tempDoublePtr] = HEAP8[ptr];\n');
+ print(' HEAP8[tempDoublePtr+1] = HEAP8[ptr+1];\n');
+ print(' HEAP8[tempDoublePtr+2] = HEAP8[ptr+2];\n');
+ print(' HEAP8[tempDoublePtr+3] = HEAP8[ptr+3];\n');
+ print(' HEAP8[tempDoublePtr+4] = HEAP8[ptr+4];\n');
+ print(' HEAP8[tempDoublePtr+5] = HEAP8[ptr+5];\n');
+ print(' HEAP8[tempDoublePtr+6] = HEAP8[ptr+6];\n');
+ print(' HEAP8[tempDoublePtr+7] = HEAP8[ptr+7];\n');
+ print('}\n');
+ }
}
return;
@@ -1622,6 +1639,12 @@ function JSify(data, functionsOnly, givenFunctions) {
legalizedI64s = legalizedI64sDefault;
+ print('STACK_BASE = STACKTOP = Runtime.alignMemory(STATICTOP);\n');
+ print('staticSealed = true; // seal the static portion of memory\n');
+ print('STACK_MAX = STACK_BASE + ' + TOTAL_STACK + ';\n');
+ print('DYNAMIC_BASE = DYNAMICTOP = Runtime.alignMemory(STACK_MAX);\n');
+ print('assert(DYNAMIC_BASE < TOTAL_MEMORY); // Stack must fit in TOTAL_MEMORY; allocations from here on may enlarge TOTAL_MEMORY\n');
+
if (asmLibraryFunctions.length > 0) {
print('// ASM_LIBRARY FUNCTIONS');
function fix(f) { // fix indenting to not confuse js optimizer
@@ -1631,6 +1654,7 @@ function JSify(data, functionsOnly, givenFunctions) {
}
print(asmLibraryFunctions.map(fix).join('\n'));
}
+
} else {
if (singlePhase) {
assert(data.unparsedGlobalss[0].lines.length == 0, dump([phase, data.unparsedGlobalss]));
@@ -1664,6 +1688,7 @@ function JSify(data, functionsOnly, givenFunctions) {
assert(typeof dep == 'function');
var text = dep();
assert(text.indexOf('\n') < 0);
+ text = text.replace('ALLOC_STATIC', 'ALLOC_DYNAMIC');
print('/* PRE_ASM */ ' + text + '\n');
});
}
diff --git a/src/library.js b/src/library.js
index dc0dcdd2..e984b1eb 100644
--- a/src/library.js
+++ b/src/library.js
@@ -15,16 +15,18 @@
// object. For convenience, the short name appears here. Note that if you add a
// new function with an '_', it will not be found.
+// Memory allocated during startup, in postsets, should only be ALLOC_STATIC
+
LibraryManager.library = {
// ==========================================================================
// File system base.
// ==========================================================================
// keep this low in memory, because we flatten arrays with them in them
- stdin: 'allocate(1, "i32*", ALLOC_STACK)',
- stdout: 'allocate(1, "i32*", ALLOC_STACK)',
- stderr: 'allocate(1, "i32*", ALLOC_STACK)',
- _impure_ptr: 'allocate(1, "i32*", ALLOC_STACK)',
+ stdin: 'allocate(1, "i32*", ALLOC_STATIC)',
+ stdout: 'allocate(1, "i32*", ALLOC_STATIC)',
+ stderr: 'allocate(1, "i32*", ALLOC_STATIC)',
+ _impure_ptr: 'allocate(1, "i32*", ALLOC_STATIC)',
$FS__deps: ['$ERRNO_CODES', '__setErrNo', 'stdin', 'stdout', 'stderr', '_impure_ptr'],
$FS__postset: '__ATINIT__.unshift({ func: function() { if (!Module["noFSInit"] && !FS.init.initialized) FS.init() } });' +
@@ -573,7 +575,7 @@ LibraryManager.library = {
eof: false,
ungotten: []
};
- assert(Math.max(_stdin, _stdout, _stderr) < 1024); // make sure these are low, we flatten arrays with these
+ // TODO: put these low in memory like we used to assert on: assert(Math.max(_stdin, _stdout, _stderr) < 15000); // make sure these are low, we flatten arrays with these
{{{ makeSetValue(makeGlobalUse('_stdin'), 0, 1, 'void*') }}};
{{{ makeSetValue(makeGlobalUse('_stdout'), 0, 2, 'void*') }}};
{{{ makeSetValue(makeGlobalUse('_stderr'), 0, 3, 'void*') }}};
@@ -590,11 +592,11 @@ LibraryManager.library = {
FS.streams[_stderr] = FS.streams[3];
#if ASSERTIONS
FS.checkStreams();
- assert(FS.streams.length < 1024); // at this early stage, we should not have a large set of file descriptors - just a few
+ // see previous TODO on stdin etc.: assert(FS.streams.length < 1024); // at this early stage, we should not have a large set of file descriptors - just a few
#endif
allocate([ allocate(
{{{ Runtime.QUANTUM_SIZE === 4 ? '[0, 0, 0, 0, _stdin, 0, 0, 0, _stdout, 0, 0, 0, _stderr, 0, 0, 0]' : '[0, _stdin, _stdout, _stderr]' }}},
- 'void*', ALLOC_STATIC) ], 'void*', ALLOC_NONE, {{{ makeGlobalUse('__impure_ptr') }}});
+ 'void*', ALLOC_DYNAMIC) ], 'void*', ALLOC_NONE, {{{ makeGlobalUse('__impure_ptr') }}});
},
quit: function() {
@@ -2425,22 +2427,17 @@ LibraryManager.library = {
// Implement a Linux-like 'memory area' for our 'process'.
// Changes the size of the memory area by |bytes|; returns the
// address of the previous top ('break') of the memory area
-
- // We need to make sure no one else allocates unfreeable memory!
- // We must control this entirely. So we don't even need to do
- // unfreeable allocations - the HEAP is ours, from STATICTOP up.
- // TODO: We could in theory slice off the top of the HEAP when
- // sbrk gets a negative increment in |bytes|...
+ // We control the "dynamic" memory - DYNAMIC_BASE to DYNAMICTOP
var self = _sbrk;
if (!self.called) {
- STATICTOP = alignMemoryPage(STATICTOP); // make sure we start out aligned
+ DYNAMICTOP = alignMemoryPage(DYNAMICTOP); // make sure we start out aligned
self.called = true;
-#if GC_SUPPORT
- _sbrk.DYNAMIC_START = STATICTOP;
-#endif
+ assert(Runtime.dynamicAlloc);
+ self.alloc = Runtime.dynamicAlloc;
+ Runtime.dynamicAlloc = function() { abort('cannot dynamically allocate, sbrk now has control') };
}
- var ret = STATICTOP;
- if (bytes != 0) Runtime.staticAlloc(bytes);
+ var ret = DYNAMICTOP;
+ if (bytes != 0) self.alloc(bytes);
return ret; // Previous break location.
},
open64: 'open',
@@ -3007,16 +3004,20 @@ LibraryManager.library = {
}
case 's': {
// String.
- var arg = getNextArg('i8*') || nullString;
- var argLength = _strlen(arg);
+ var arg = getNextArg('i8*');
+ var argLength = arg ? _strlen(arg) : '(null)'.length;
if (precisionSet) argLength = Math.min(argLength, precision);
if (!flagLeftAlign) {
while (argLength < width--) {
ret.push({{{ charCode(' ') }}});
}
}
- for (var i = 0; i < argLength; i++) {
- ret.push({{{ makeGetValue('arg++', 0, 'i8', null, true) }}});
+ if (arg) {
+ for (var i = 0; i < argLength; i++) {
+ ret.push({{{ makeGetValue('arg++', 0, 'i8', null, true) }}});
+ }
+ } else {
+ ret = ret.concat(intArrayFromString('(null)'.substr(0, argLength), true));
}
if (flagLeftAlign) {
while (argLength < width--) {
@@ -3750,7 +3751,7 @@ LibraryManager.library = {
* implementation (replaced by dlmalloc normally) so
* not an issue.
*/
- var ptr = Runtime.staticAlloc(bytes + 8);
+ var ptr = Runtime.dynamicAlloc(bytes + 8);
return (ptr+8) & 0xFFFFFFF8;
},
free: function(){},
@@ -4029,7 +4030,7 @@ LibraryManager.library = {
_free(temp);
},
- environ: 'allocate(1, "i32*", ALLOC_STACK)',
+ environ: 'allocate(1, "i32*", ALLOC_STATIC)',
__environ__deps: ['environ'],
__environ: '_environ',
__buildEnvironment__deps: ['__environ'],
@@ -4925,7 +4926,7 @@ LibraryManager.library = {
}
return 8;
}
- return 'var ctlz_i8 = allocate([' + range(256).map(function(x) { return ctlz(x) }).join(',') + '], "i8", ALLOC_STACK);';
+ return 'var ctlz_i8 = allocate([' + range(256).map(function(x) { return ctlz(x) }).join(',') + '], "i8", ALLOC_STATIC);';
}],
llvm_ctlz_i32__asm: true,
llvm_ctlz_i32__sig: 'ii',
@@ -4961,7 +4962,7 @@ LibraryManager.library = {
}
return 8;
}
- return 'var cttz_i8 = allocate([' + range(256).map(function(x) { return cttz(x) }).join(',') + '], "i8", ALLOC_STACK);';
+ return 'var cttz_i8 = allocate([' + range(256).map(function(x) { return cttz(x) }).join(',') + '], "i8", ALLOC_STATIC);';
}],
llvm_cttz_i32__asm: true,
llvm_cttz_i32__sig: 'ii',
@@ -5919,11 +5920,11 @@ LibraryManager.library = {
['i32', 'tm_gmtoff'],
['i32', 'tm_zone']]),
// Statically allocated time struct.
- __tm_current: 'allocate({{{ Runtime.QUANTUM_SIZE }}}*26, "i8", ALLOC_STACK)',
+ __tm_current: 'allocate({{{ Runtime.QUANTUM_SIZE }}}*26, "i8", ALLOC_STATIC)',
// Statically allocated timezone strings.
__tm_timezones: {},
// Statically allocated time strings.
- __tm_formatted: 'allocate({{{ Runtime.QUANTUM_SIZE }}}*26, "i8", ALLOC_STACK)',
+ __tm_formatted: 'allocate({{{ Runtime.QUANTUM_SIZE }}}*26, "i8", ALLOC_STATIC)',
mktime__deps: ['__tm_struct_layout', 'tzset'],
mktime: function(tmPtr) {
@@ -6057,9 +6058,9 @@ LibraryManager.library = {
// TODO: Initialize these to defaults on startup from system settings.
// Note: glibc has one fewer underscore for all of these. Also used in other related functions (timegm)
- _tzname: 'allocate({{{ 2*Runtime.QUANTUM_SIZE }}}, "i32*", ALLOC_STACK)',
- _daylight: 'allocate(1, "i32*", ALLOC_STACK)',
- _timezone: 'allocate(1, "i32*", ALLOC_STACK)',
+ _tzname: 'allocate({{{ 2*Runtime.QUANTUM_SIZE }}}, "i32*", ALLOC_STATIC)',
+ _daylight: 'allocate(1, "i32*", ALLOC_STATIC)',
+ _timezone: 'allocate(1, "i32*", ALLOC_STATIC)',
tzset__deps: ['_tzname', '_daylight', '_timezone'],
tzset: function() {
// TODO: Use (malleable) environment variables instead of system settings.
@@ -6756,15 +6757,18 @@ LibraryManager.library = {
26: 'Text file busy',
18: 'Invalid cross-device link'
},
- __setErrNo__postset: '___setErrNo(0);',
__setErrNo: function(value) {
// For convenient setting and returning of errno.
- if (!___setErrNo.ret) ___setErrNo.ret = allocate([0], 'i32', ALLOC_STATIC);
+ if (!___setErrNo.ret) ___setErrNo.ret = allocate([0], 'i32', ALLOC_NORMAL);
{{{ makeSetValue('___setErrNo.ret', '0', 'value', 'i32') }}}
return value;
},
__errno_location__deps: ['__setErrNo'],
__errno_location: function() {
+ if (!___setErrNo.ret) {
+ ___setErrNo.ret = allocate([0], 'i32', ALLOC_NORMAL);
+ {{{ makeSetValue('___setErrNo.ret', '0', '0', 'i32') }}}
+ }
return ___setErrNo.ret;
},
__errno: '__errno_location',
@@ -6877,7 +6881,7 @@ LibraryManager.library = {
void **restrict stackaddr, size_t *restrict stacksize); */
/*FIXME: assumes that there is only one thread, and that attr is the
current thread*/
- {{{ makeSetValue('stackaddr', '0', 'STACK_ROOT', 'i8*') }}}
+ {{{ makeSetValue('stackaddr', '0', 'STACK_BASE', 'i8*') }}}
{{{ makeSetValue('stacksize', '0', 'TOTAL_STACK', 'i32') }}}
return 0;
},
diff --git a/src/library_gc.js b/src/library_gc.js
index f6db74d8..2a164250 100644
--- a/src/library_gc.js
+++ b/src/library_gc.js
@@ -148,12 +148,9 @@ if (GC_SUPPORT) {
prep: function() { // Clear reachables and scan for roots
GC.reachable = {}; // 1 if reachable. XXX
GC.reachableList = []; // each reachable is added once to this. XXX
- // static data areas
- var staticStart = STACK_MAX;
- var staticEnd = _sbrk.DYNAMIC_START || STATICTOP; // after DYNAMIC_START, sbrk manages it (but it might not exist yet)
- GC.scan(staticStart, staticEnd);
+ GC.scan(STATIC_BASE, STATICTOP);
// TODO: scan stack and registers. Currently we assume we run from a timeout or such, so no stack/regs
- // stack: STACK_ROOT to STACKTOP
+ // stack: STACK_BASE to STACKTOP
// registers: call scanners
},
diff --git a/src/parseTools.js b/src/parseTools.js
index 5cbefdb1..db834206 100644
--- a/src/parseTools.js
+++ b/src/parseTools.js
@@ -465,8 +465,7 @@ function makeGlobalUse(ident) {
UNINDEXABLE_GLOBALS[ident] = 1;
return ident;
}
- // We know and assert on TOTAL_STACK being equal to GLOBAL_BASE
- return (TOTAL_STACK + index).toString();
+ return (Runtime.GLOBAL_BASE + index).toString();
}
return ident;
}
@@ -1594,7 +1593,7 @@ function makePointer(slab, pos, allocator, type, ptr, finalMemoryInitialization)
// writing out into memory, without a normal allocation. We put all of these into a single big chunk.
assert(typeof slab == 'object');
assert(slab.length % QUANTUM_SIZE == 0, slab.length); // must be aligned already
- var offset = ptr - TOTAL_STACK; // we assert on GLOBAL_BASE being equal to TOTAL_STACK
+ var offset = ptr - Runtime.GLOBAL_BASE;
for (var i = 0; i < slab.length; i++) {
memoryInitialization[offset + i] = slab[i];
}
diff --git a/src/postamble.js b/src/postamble.js
index 8dd01589..12471a19 100644
--- a/src/postamble.js
+++ b/src/postamble.js
@@ -15,14 +15,14 @@ Module.callMain = function callMain(args) {
argv.push(0);
}
}
- var argv = [allocate(intArrayFromString("/bin/this.program"), 'i8', ALLOC_STATIC) ];
+ var argv = [allocate(intArrayFromString("/bin/this.program"), 'i8', ALLOC_NORMAL) ];
pad();
for (var i = 0; i < argc-1; i = i + 1) {
- argv.push(allocate(intArrayFromString(args[i]), 'i8', ALLOC_STATIC));
+ argv.push(allocate(intArrayFromString(args[i]), 'i8', ALLOC_NORMAL));
pad();
}
argv.push(0);
- argv = allocate(argv, 'i32', ALLOC_STATIC);
+ argv = allocate(argv, 'i32', ALLOC_NORMAL);
#if BENCHMARK
var start = Date.now();
diff --git a/src/preamble.js b/src/preamble.js
index cac0be4c..d10771e3 100644
--- a/src/preamble.js
+++ b/src/preamble.js
@@ -38,14 +38,14 @@ var ACCEPTABLE_SAFE_HEAP_ERRORS = 0;
function SAFE_HEAP_ACCESS(dest, type, store, ignore, storeValue) {
//if (dest === A_NUMBER) Module.print ([dest, type, store, ignore, storeValue] + ' ' + new Error().stack); // Something like this may be useful, in debugging
- assert(dest >= STACK_ROOT, 'segmentation fault: null pointer, or below normal memory');
+ assert(dest > 0, 'segmentation fault');
#if USE_TYPED_ARRAYS
// When using typed arrays, reads over the top of TOTAL_MEMORY will fail silently, so we must
// correct that by growing TOTAL_MEMORY as needed. Without typed arrays, memory is a normal
// JS array so it will work (potentially slowly, depending on the engine).
- assert(ignore || dest < STATICTOP);
- assert(ignore || STATICTOP <= TOTAL_MEMORY);
+ assert(ignore || dest < Math.max(DYNAMICTOP, STATICTOP));
+ assert(ignore || DYNAMICTOP <= TOTAL_MEMORY);
#endif
#if USE_TYPED_ARRAYS == 2
@@ -417,10 +417,12 @@ Module['getValue'] = getValue;
var ALLOC_NORMAL = 0; // Tries to use _malloc()
var ALLOC_STACK = 1; // Lives for the duration of the current function call
var ALLOC_STATIC = 2; // Cannot be freed
-var ALLOC_NONE = 3; // Do not allocate
+var ALLOC_DYNAMIC = 3; // Cannot be freed except through sbrk
+var ALLOC_NONE = 4; // Do not allocate
Module['ALLOC_NORMAL'] = ALLOC_NORMAL;
Module['ALLOC_STACK'] = ALLOC_STACK;
Module['ALLOC_STATIC'] = ALLOC_STATIC;
+Module['ALLOC_DYNAMIC'] = ALLOC_DYNAMIC;
Module['ALLOC_NONE'] = ALLOC_NONE;
// allocate(): This is for internal use. You can use it yourself as well, but the interface
@@ -452,7 +454,7 @@ function allocate(slab, types, allocator, ptr) {
if (allocator == ALLOC_NONE) {
ret = ptr;
} else {
- ret = [_malloc, Runtime.stackAlloc, Runtime.staticAlloc][allocator === undefined ? ALLOC_STATIC : allocator](Math.max(size, singleType ? 1 : types.length));
+ ret = [_malloc, Runtime.stackAlloc, Runtime.staticAlloc, Runtime.dynamicAlloc][allocator === undefined ? ALLOC_STATIC : allocator](Math.max(size, singleType ? 1 : types.length));
}
if (zeroinit) {
@@ -573,8 +575,10 @@ var FHEAP;
var HEAP8, HEAPU8, HEAP16, HEAPU16, HEAP32, HEAPU32, HEAPF32, HEAPF64;
#endif
-var STACK_ROOT, STACKTOP, STACK_MAX;
-var STATICTOP;
+var STATIC_BASE = 0, STATICTOP = 0, staticSealed = false; // static area
+var STACK_BASE = 0, STACKTOP = 0, STACK_MAX = 0; // stack area
+var DYNAMIC_BASE = 0, DYNAMICTOP = 0; // dynamic area handled by sbrk
+
#if USE_TYPED_ARRAYS
function enlargeMemory() {
#if ALLOW_MEMORY_GROWTH == 0
@@ -584,13 +588,13 @@ function enlargeMemory() {
abort('Cannot enlarge memory arrays in asm.js. Either (1) compile with -s TOTAL_MEMORY=X with X higher than the current value, or (2) set Module.TOTAL_MEMORY before the program runs.');
#endif
#else
- // TOTAL_MEMORY is the current size of the actual array, and STATICTOP is the new top.
+ // TOTAL_MEMORY is the current size of the actual array, and DYNAMICTOP is the new top.
#if ASSERTIONS
- Module.printErr('Warning: Enlarging memory arrays, this is not fast, and ALLOW_MEMORY_GROWTH is not fully tested with all optimizations on! ' + [STATICTOP, TOTAL_MEMORY]); // We perform safe elimination instead of elimination in this mode, but if you see this error, try to disable it and other optimizations entirely
- assert(STATICTOP >= TOTAL_MEMORY);
+ Module.printErr('Warning: Enlarging memory arrays, this is not fast, and ALLOW_MEMORY_GROWTH is not fully tested with all optimizations on! ' + [DYNAMICTOP, TOTAL_MEMORY]); // We perform safe elimination instead of elimination in this mode, but if you see this error, try to disable it and other optimizations entirely
+ assert(DYNAMICTOP >= TOTAL_MEMORY);
assert(TOTAL_MEMORY > 4); // So the loop below will not be infinite
#endif
- while (TOTAL_MEMORY <= STATICTOP) { // Simple heuristic. Override enlargeMemory() if your program has something more optimal for it
+ while (TOTAL_MEMORY <= DYNAMICTOP) { // Simple heuristic. Override enlargeMemory() if your program has something more optimal for it
TOTAL_MEMORY = alignMemoryPage(2*TOTAL_MEMORY);
}
assert(TOTAL_MEMORY <= Math.pow(2, 30)); // 2^30==1GB is a practical maximum - 2^31 is already close to possible negative numbers etc.
@@ -680,35 +684,6 @@ Module['HEAPF32'] = HEAPF32;
Module['HEAPF64'] = HEAPF64;
#endif
-STACK_ROOT = STACKTOP = Runtime.alignMemory(1);
-STACK_MAX = TOTAL_STACK; // we lose a little stack here, but TOTAL_STACK is nice and round so use that as the max
-
-#if USE_TYPED_ARRAYS == 2
-var tempDoublePtr = Runtime.alignMemory(allocate(12, 'i8', ALLOC_STACK), 8);
-assert(tempDoublePtr % 8 == 0);
-function copyTempFloat(ptr) { // functions, because inlining this code increases code size too much
- HEAP8[tempDoublePtr] = HEAP8[ptr];
- HEAP8[tempDoublePtr+1] = HEAP8[ptr+1];
- HEAP8[tempDoublePtr+2] = HEAP8[ptr+2];
- HEAP8[tempDoublePtr+3] = HEAP8[ptr+3];
-}
-function copyTempDouble(ptr) {
- HEAP8[tempDoublePtr] = HEAP8[ptr];
- HEAP8[tempDoublePtr+1] = HEAP8[ptr+1];
- HEAP8[tempDoublePtr+2] = HEAP8[ptr+2];
- HEAP8[tempDoublePtr+3] = HEAP8[ptr+3];
- HEAP8[tempDoublePtr+4] = HEAP8[ptr+4];
- HEAP8[tempDoublePtr+5] = HEAP8[ptr+5];
- HEAP8[tempDoublePtr+6] = HEAP8[ptr+6];
- HEAP8[tempDoublePtr+7] = HEAP8[ptr+7];
-}
-#endif
-
-STATICTOP = STACK_MAX;
-assert(STATICTOP < TOTAL_MEMORY); // Stack must fit in TOTAL_MEMORY; allocations from here on may enlarge TOTAL_MEMORY
-
-var nullString = allocate(intArrayFromString('(null)'), 'i8', ALLOC_STACK);
-
function callRuntimeCallbacks(callbacks) {
while(callbacks.length > 0) {
var callback = callbacks.shift();
@@ -907,9 +882,9 @@ var awaitingMemoryInitializer = false;
function loadMemoryInitializer(filename) {
function applyData(data) {
#if USE_TYPED_ARRAYS == 2
- HEAPU8.set(data, TOTAL_STACK);
+ HEAPU8.set(data, STATIC_BASE);
#else
- allocate(data, 'i8', ALLOC_NONE, TOTAL_STACK);
+ allocate(data, 'i8', ALLOC_NONE, STATIC_BASE);
#endif
runPostSets();
}
diff --git a/src/runtime.js b/src/runtime.js
index 9daab820..9bedfe68 100644
--- a/src/runtime.js
+++ b/src/runtime.js
@@ -61,8 +61,16 @@ var RuntimeGenerator = {
// An allocation that cannot normally be free'd (except through sbrk, which once
// called, takes control of STATICTOP)
staticAlloc: function(size) {
+ if (ASSERTIONS) size = '(assert(!staticSealed),' + size + ')'; // static area must not be sealed
var ret = RuntimeGenerator.alloc(size, 'STATIC', INIT_HEAP);
- if (USE_TYPED_ARRAYS) ret += '; if (STATICTOP >= TOTAL_MEMORY) enlargeMemory();'
+ return ret;
+ },
+
+ // allocation on the top of memory, adjusted dynamically by sbrk
+ dynamicAlloc: function(size) {
+ if (ASSERTIONS) size = '(assert(DYNAMICTOP > 0),' + size + ')'; // dynamic area must be ready
+ var ret = RuntimeGenerator.alloc(size, 'DYNAMIC', INIT_HEAP);
+ if (USE_TYPED_ARRAYS) ret += '; if (DYNAMICTOP >= TOTAL_MEMORY) enlargeMemory();'
return ret;
},
@@ -466,6 +474,7 @@ var Runtime = {
Runtime.stackAlloc = unInline('stackAlloc', ['size']);
Runtime.staticAlloc = unInline('staticAlloc', ['size']);
+Runtime.dynamicAlloc = unInline('dynamicAlloc', ['size']);
Runtime.alignMemory = unInline('alignMemory', ['size', 'quantum']);
Runtime.makeBigInt = unInline('makeBigInt', ['low', 'high', 'unsigned']);
@@ -529,3 +538,9 @@ function reSign(value, bits, ignore, sig) {
return value;
}
+// The address globals begin at. Very low in memory, for code size and optimization opportunities.
+// Above 0 is static memory, starting with globals.
+// Then the stack.
+// Then 'dynamic' memory for sbrk.
+Runtime.GLOBAL_BASE = Runtime.alignMemory(1);
+
diff --git a/src/settings.js b/src/settings.js
index 2e4c2550..ba1f6a83 100644
--- a/src/settings.js
+++ b/src/settings.js
@@ -279,7 +279,8 @@ var PRINT_SPLIT_FILE_MARKER = 0; // Prints markers in Javascript generation to s
var BUILD_AS_SHARED_LIB = 0; // Whether to build the code as a shared library
// 0 here means this is not a shared lib: It is a main file.
- // 1 means this is a normal shared lib, load it with dlopen().
+ // All shared library options (1 and 2) are currently deprecated XXX
+ // 1 means this is a normal shared lib, load it with dlopen()
// 2 means this is a shared lib that will be linked at runtime,
// which means it will insert its functions into
// the global namespace. See STATIC_LIBS_TO_LOAD.
diff --git a/tests/cases/gepoverflow.txt b/tests/cases/gepoverflow.txt
index 31d67161..3984fc07 100644
--- a/tests/cases/gepoverflow.txt
+++ b/tests/cases/gepoverflow.txt
@@ -1,2 +1,2 @@
-*5242366,5242936*
+*-506,64*
*-514,56*
diff --git a/tests/fcntl/output.txt b/tests/fcntl/output.txt
index 1ed740e7..bad9708e 100644
--- a/tests/fcntl/output.txt
+++ b/tests/fcntl/output.txt
@@ -1,4 +1,4 @@
-F_DUPFD: 100
+F_DUPFD: 1
errno: 0
F_DUPFD/error1: -1
diff --git a/tests/fcntl/src.c b/tests/fcntl/src.c
index c8c71c8a..c60e578e 100644
--- a/tests/fcntl/src.c
+++ b/tests/fcntl/src.c
@@ -5,7 +5,7 @@
int main() {
int f = open("/test", O_RDWR, 0777);
- printf("F_DUPFD: %d\n", fcntl(f, F_DUPFD, 100));
+ printf("F_DUPFD: %d\n", fcntl(f, F_DUPFD, 100) >= 100);
printf("errno: %d\n", errno);
printf("\n");
errno = 0;
diff --git a/tests/runner.py b/tests/runner.py
index 0aefb8e1..3230fa23 100755
--- a/tests/runner.py
+++ b/tests/runner.py
@@ -3134,7 +3134,7 @@ Exiting setjmp function, level: 0, prev_jmp: -1
Settings.SAFE_HEAP = 1
- for addr in ['0', '7', 'new D2()']:
+ for addr in ['0', 'new D2()']:
print addr
src = r'''
#include <stdio.h>
@@ -5018,6 +5018,7 @@ The current type of b is: 9
self.do_run(src, '*16,0,4,8,8,12|20,0,4,4,8,12,12,16|24,0,20,0,4,4,8,12,12,16*\n*0,0,0,1,2,64,68,69,72*\n*2*')
def test_runtimelink(self):
+ return self.skip('shared libs are deprecated')
if Building.LLVM_OPTS: return self.skip('LLVM opts will optimize printf into puts in the parent, and the child will still look for puts')
if Settings.ASM_JS: return self.skip('asm does not support runtime linking')
@@ -5036,6 +5037,7 @@ The current type of b is: 9
self.do_run(main, 'supp: 54,2\nmain: 56\nsupp see: 543\nmain see: 76\nok.')
def test_dlfcn_basic(self):
+ return self.skip('shared libs are deprecated')
if Settings.ASM_JS: return self.skip('TODO: dlopen in asm')
Settings.NAMED_GLOBALS = 1
@@ -5090,6 +5092,7 @@ def process(filename):
post_build=add_pre_run_and_checks)
def test_dlfcn_qsort(self):
+ return self.skip('shared libs are deprecated')
if self.emcc_args is None: return self.skip('requires emcc')
if Settings.ASM_JS: return self.skip('TODO: dlopen in asm')
@@ -5186,6 +5189,7 @@ def process(filename):
post_build=add_pre_run_and_checks)
def test_dlfcn_data_and_fptr(self):
+ return self.skip('shared libs are deprecated')
if Settings.ASM_JS: return self.skip('TODO: dlopen in asm')
if Building.LLVM_OPTS: return self.skip('LLVM opts will optimize out parent_func')
@@ -5290,6 +5294,7 @@ def process(filename):
post_build=add_pre_run_and_checks)
def test_dlfcn_alias(self):
+ return self.skip('shared libs are deprecated')
if Settings.ASM_JS: return self.skip('TODO: dlopen in asm')
Settings.LINKABLE = 1
@@ -5347,6 +5352,7 @@ def process(filename):
Settings.INCLUDE_FULL_LIBRARY = 0
def test_dlfcn_varargs(self):
+ return self.skip('shared libs are deprecated')
if Settings.ASM_JS: return self.skip('TODO: dlopen in asm')
Settings.LINKABLE = 1
@@ -9959,6 +9965,7 @@ f.close()
self.assertContained('hello from lib', run_js(os.path.join(self.get_dir(), 'a.out.js')))
def test_runtimelink_multi(self):
+ return self.skip('shared libs are deprecated')
if Settings.ASM_JS: return self.skip('asm does not support runtime linking yet')
if SPIDERMONKEY_ENGINE not in JS_ENGINES: return self.skip('cannot run without spidermonkey due to node limitations')
@@ -12155,6 +12162,7 @@ elif 'browser' in str(sys.argv):
self.btest('perspective.c', reference='perspective.png')
def test_runtimelink(self):
+ return self.skip('shared libs are deprecated')
main, supp = self.setup_runtimelink_test()
open(self.in_dir('supp.cpp'), 'w').write(supp)