simplify heap operations in preamble with macros
This commit is contained in:
Родитель
ff4341e7d5
Коммит
149c178e2b
|
@ -72,19 +72,21 @@ function JSify(data, functionsOnly, givenTypes, givenFunctions, givenGlobalVaria
|
|||
return getFastValue(offset, '+', pos);
|
||||
}
|
||||
|
||||
function makeGetValue(ptr, pos, noNeedFirst, type) {
|
||||
// See makeSetValue
|
||||
function makeGetValue(ptr, pos, type, noNeedFirst) {
|
||||
if (isStructType(type)) {
|
||||
var typeData = TYPES[type];
|
||||
var ret = [];
|
||||
for (var i = 0; i < typeData.fields.length; i++) {
|
||||
ret.push('f' + i + ': ' + makeGetValue(ptr, pos + typeData.flatIndexes[i], noNeedFirst, typeData.fields[i]));
|
||||
ret.push('f' + i + ': ' + makeGetValue(ptr, pos + typeData.flatIndexes[i], typeData.fields[i], noNeedFirst));
|
||||
}
|
||||
return '{ ' + ret.join(', ') + ' }';
|
||||
}
|
||||
|
||||
var offset = calcFastOffset(ptr, pos, noNeedFirst);
|
||||
if (SAFE_HEAP) {
|
||||
return 'SAFE_HEAP_LOAD(' + offset + ', "' + safeQuote(type) + '")';
|
||||
if (type !== 'null') type = '"' + safeQuote(type) + '"';
|
||||
return 'SAFE_HEAP_LOAD(' + offset + ', ' + type + ')';
|
||||
} else {
|
||||
return makeGetSlabs(ptr, type)[0] + '[' + offset + ']';
|
||||
}
|
||||
|
@ -97,12 +99,22 @@ function JSify(data, functionsOnly, givenTypes, givenFunctions, givenGlobalVaria
|
|||
return value;
|
||||
}
|
||||
|
||||
function makeSetValue(ptr, pos, value, noNeedFirst, type) {
|
||||
//! @param ptr The pointer. Used to find both the slab and the offset in that slab. If the pointer
|
||||
//! is just an integer, then this is almost redundant, but in general the pointer type
|
||||
//! may in the future include information about which slab as well. So, for now it is
|
||||
//! possible to put |0| here, but if a pointer is available, that is more future-proof.
|
||||
//! @param pos The position in that slab - the offset. Added to any offset in the pointer itself.
|
||||
//! @param value The value to set.
|
||||
//! @param type A string defining the type. Used to find the slab (IHEAP, FHEAP, etc.).
|
||||
//! 'null' means, in the context of SAFE_HEAP, that we should accept all types;
|
||||
//! which means we should write to all slabs, ignore type differences if any on reads, etc.
|
||||
//! @param noNeedFirst Whether to ignore the offset in the pointer itself.
|
||||
function makeSetValue(ptr, pos, value, type, noNeedFirst) {
|
||||
if (isStructType(type)) {
|
||||
var typeData = TYPES[type];
|
||||
var ret = [];
|
||||
for (var i = 0; i < typeData.fields.length; i++) {
|
||||
ret.push(makeSetValue(ptr, pos + typeData.flatIndexes[i], value[i], noNeedFirst, typeData.fields[i]));
|
||||
ret.push(makeSetValue(ptr, pos + typeData.flatIndexes[i], value[i], typeData.fields[i], noNeedFirst));
|
||||
}
|
||||
return ret.join('; ');
|
||||
}
|
||||
|
@ -117,6 +129,13 @@ function JSify(data, functionsOnly, givenTypes, givenFunctions, givenGlobalVaria
|
|||
}
|
||||
}
|
||||
|
||||
function makeCopyValue(dest, destPos, src, srcPos, type, modifier) {
|
||||
var types = (type !== 'null' || !USE_TYPED_ARRAYS) ? [type] : ['i32', 'double'];
|
||||
return types.map(function(currType) {
|
||||
return makeSetValue(dest, destPos, makeGetValue(src, srcPos, currType) + modifier, currType);
|
||||
}).join(' ');
|
||||
}
|
||||
|
||||
function makeEmptyStruct(type) {
|
||||
var ret = [];
|
||||
var typeData = TYPES[type];
|
||||
|
@ -530,9 +549,9 @@ function JSify(data, functionsOnly, givenTypes, givenFunctions, givenGlobalVaria
|
|||
break;
|
||||
case VAR_EMULATED:
|
||||
if (item.pointer.intertype == 'value') {
|
||||
return makeSetValue(item.ident, 0, value, null, item.valueType) + ';';
|
||||
return makeSetValue(item.ident, 0, value, item.valueType) + ';';
|
||||
} else {
|
||||
return makeSetValue(0, indexizeFunctions(finalizeLLVMParameter(item.pointer)), value, null, item.valueType) + ';';
|
||||
return makeSetValue(0, indexizeFunctions(finalizeLLVMParameter(item.pointer)), value, item.valueType) + ';';
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -653,7 +672,7 @@ function JSify(data, functionsOnly, givenTypes, givenFunctions, givenGlobalVaria
|
|||
case VAR_NATIVIZED: {
|
||||
return ident; // We have the actual value here
|
||||
}
|
||||
case VAR_EMULATED: return makeGetValue(ident, null, null, item.type);
|
||||
case VAR_EMULATED: return makeGetValue(ident, null, item.type);
|
||||
default: throw "unknown [load] impl: " + impl;
|
||||
}
|
||||
});
|
||||
|
@ -954,10 +973,10 @@ function JSify(data, functionsOnly, givenTypes, givenFunctions, givenGlobalVaria
|
|||
// Optimzed intertypes
|
||||
|
||||
makeFuncLineActor('fastgetelementptrload', function(item) {
|
||||
return 'var ' + item.ident + ' = ' + makeGetValue(parseNumerical(item.value.ident), getGetElementPtrIndexes(item.value), true, item.value.valueType) + ';';
|
||||
return 'var ' + item.ident + ' = ' + makeGetValue(parseNumerical(item.value.ident), getGetElementPtrIndexes(item.value), item.value.valueType, true) + ';';
|
||||
});
|
||||
makeFuncLineActor('fastgetelementptrstore', function(item) {
|
||||
return makeSetValue(item.value.ident, getGetElementPtrIndexes(item.value), parseNumerical(item.ident), true, item.type) + ';';
|
||||
return makeSetValue(item.value.ident, getGetElementPtrIndexes(item.value), parseNumerical(item.ident), item.type, true) + ';';
|
||||
});
|
||||
|
||||
makeFuncLineActor('unreachable', function(item) { return 'throw "Reached an unreachable! Original .ll line: ' + item.lineNum + '";' });
|
||||
|
|
|
@ -33,6 +33,7 @@ function SAFE_HEAP_ACCESS(dest, type, store) {
|
|||
if (!HEAP[dest] && HEAP[dest] !== 0 && HEAP[dest] !== false) { // false can be the result of a mathop comparator
|
||||
throw('Warning: Reading an invalid value at ' + dest + ' :: ' + new Error().stack + '\n');
|
||||
}
|
||||
if (type === null) return;
|
||||
var history = HEAP_HISTORY[dest];
|
||||
if (history === null) return;
|
||||
assert(history, 'Must have a history for a safe heap load!'); // Warning - bit fields in C structs cause loads+stores for each store, so
|
||||
|
@ -139,7 +140,7 @@ function Pointer_make(slab, pos, allocator) {
|
|||
curr = Runtime.getFunctionIndex(curr);
|
||||
}
|
||||
|
||||
{{{ makeSetValue(0, 'ret+i', 'curr', null, 'null') }}}
|
||||
{{{ makeSetValue(0, 'ret+i', 'curr', 'null') }}}
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -151,7 +152,7 @@ function Pointer_stringify(ptr) {
|
|||
var i = 0;
|
||||
var t;
|
||||
while (1) {
|
||||
t = String.fromCharCode(IHEAP[ptr + i]);
|
||||
t = String.fromCharCode({{{ makeGetValue('ptr', 'i', 'i8') }}});
|
||||
if (t == "\0") { break; } else {}
|
||||
ret += t;
|
||||
i += 1;
|
||||
|
@ -195,14 +196,14 @@ function __initializeRuntime__() {
|
|||
var FAST_MEMORY = TOTAL_MEMORY/32;
|
||||
IHEAP = FHEAP = HEAP = new Array(FAST_MEMORY);
|
||||
for (var i = 0; i < FAST_MEMORY; i++) {
|
||||
HEAP[i] = 0;
|
||||
{{{ makeSetValue(0, 'i', 0, 'null') }}}
|
||||
}
|
||||
}
|
||||
|
||||
var base = intArrayFromString('(null)'); // So printing %s of NULL gives '(null)'
|
||||
// Also this ensures we leave 0 as an invalid address, 'NULL'
|
||||
for (var i = 0; i < base.length; i++) {
|
||||
IHEAP[i] = base[i];
|
||||
{{{ makeSetValue(0, 'i', 'base[i]', 'i8') }}}
|
||||
}
|
||||
|
||||
Module['HEAP'] = HEAP;
|
||||
|
@ -249,7 +250,11 @@ function __formatString() {
|
|||
ret = _arguments[argIndex];
|
||||
argIndex++;
|
||||
} else {
|
||||
ret = (isFloatArg(type) ? FHEAP : IHEAP)[argIndex];
|
||||
if (isFloatArg(type)) {
|
||||
ret = {{{ makeGetValue(0, 'argIndex', 'double') }}};
|
||||
} else {
|
||||
ret = {{{ makeGetValue(0, 'argIndex', 'i32') }}};
|
||||
}
|
||||
argIndex += type === 'l'.charCodeAt(0) ? 8 : 4; // XXX hardcoded native sizes
|
||||
}
|
||||
return ret;
|
||||
|
@ -258,8 +263,8 @@ function __formatString() {
|
|||
var ret = [];
|
||||
var curr = -1, next, currArg;
|
||||
while (curr) { // Note: should be curr != 0, technically. But this helps catch bugs with undefineds
|
||||
curr = IHEAP[textIndex];
|
||||
next = IHEAP[textIndex+1];
|
||||
curr = {{{ makeGetValue(0, 'textIndex', 'i8') }}};
|
||||
next = {{{ makeGetValue(0, 'textIndex+1', 'i8') }}};
|
||||
if (curr == '%'.charCodeAt(0)) {
|
||||
// Handle very very simply formatting, namely only %.X[f|d|u|etc.]
|
||||
var precision = -1;
|
||||
|
@ -267,17 +272,17 @@ function __formatString() {
|
|||
textIndex++;
|
||||
precision = 0;
|
||||
while(1) {
|
||||
var precisionChr = IHEAP[textIndex+1];
|
||||
var precisionChr = {{{ makeGetValue(0, 'textIndex+1', 'i8') }}};
|
||||
if (!(precisionChr >= '0'.charCodeAt(0) && precisionChr <= '9'.charCodeAt(0))) break;
|
||||
precision *= 10;
|
||||
precision += precisionChr - '0'.charCodeAt(0);
|
||||
textIndex++;
|
||||
}
|
||||
next = IHEAP[textIndex+1];
|
||||
next = {{{ makeGetValue(0, 'textIndex+1', 'i8') }}};
|
||||
}
|
||||
if (next == 'l'.charCodeAt(0)) {
|
||||
textIndex++;
|
||||
next = IHEAP[textIndex+1];
|
||||
next = {{{ makeGetValue(0, 'textIndex+1', 'i8') }}};
|
||||
}
|
||||
if (isFloatArg(next)) {
|
||||
next = 'f'.charCodeAt(0); // no support for 'e'
|
||||
|
@ -334,6 +339,7 @@ function __formatString() {
|
|||
// Copies a list of num items on the HEAP into a
|
||||
// a normal JavaScript array of numbers
|
||||
function Array_copy(ptr, num) {
|
||||
// TODO: In the SAFE_HEAP case, do some reading here, for debugging purposes - currently this is an 'unnoticed read'.
|
||||
#if USE_TYPED_ARRAYS
|
||||
return Array.prototype.slice.call(IHEAP.slice(ptr, ptr+num)); // Make a normal array out of the typed one
|
||||
// Consider making a typed array here, for speed?
|
||||
|
@ -358,18 +364,9 @@ function _atoi(s) {
|
|||
function _llvm_memcpy_i32(dest, src, num, idunno) {
|
||||
var curr;
|
||||
for (var i = 0; i < num; i++) {
|
||||
#if USE_TYPED_ARRAYS
|
||||
// TODO: optimize somehow - this is slower than without typed arrays
|
||||
IHEAP[dest + i] = IHEAP[src + i];
|
||||
FHEAP[dest + i] = FHEAP[src + i];
|
||||
#else
|
||||
curr = HEAP[src + i] || 0; // memcpy sometimes copies uninitialized areas XXX: Investigate why initializing alloc'ed memory does not fix that too
|
||||
#if SAFE_HEAP
|
||||
SAFE_HEAP_STORE(dest + i, curr, null);
|
||||
#else
|
||||
HEAP[dest + i] = curr;
|
||||
#endif
|
||||
#endif
|
||||
// TODO: optimize for the typed arrays case
|
||||
// || 0, since memcpy sometimes copies uninitialized areas XXX: Investigate why initializing alloc'ed memory does not fix that too
|
||||
{{{ makeCopyValue('dest', 'i', 'src', 'i', 'null', ' || 0') }}};
|
||||
}
|
||||
}
|
||||
_memcpy = _llvm_memcpy_i64 = _llvm_memcpy_p0i8_p0i8_i32 = _llvm_memcpy_p0i8_p0i8_i64 = _llvm_memcpy_i32;
|
||||
|
@ -386,21 +383,14 @@ _memmove = _llvm_memmove_i64 = _llvm_memmove_p0i8_p0i8_i32 = _llvm_memmove_p0i8_
|
|||
|
||||
function llvm_memset_i32(ptr, value, num) {
|
||||
for (var i = 0; i < num; i++) {
|
||||
#if USE_TYPED_ARRAYS
|
||||
IHEAP[ptr+i] = FHEAP[ptr+i] = value;
|
||||
#else
|
||||
HEAP[ptr+i] = value;
|
||||
#endif
|
||||
#if SAFE_HEAP
|
||||
SAFE_HEAP_ACCESS(ptr+i, null, true);
|
||||
#endif
|
||||
{{{ makeSetValue('ptr', 'i', 'value', 'null') }}}
|
||||
}
|
||||
}
|
||||
_memset = _llvm_memset_p0i8_i64 = _llvm_memset_p0i8_i32 = llvm_memset_i32;
|
||||
|
||||
function _strlen(ptr) {
|
||||
var i = 0;
|
||||
while (IHEAP[ptr+i]) i++; // Note: should be IHEAP[ptr+i] != 0, technically. But this helps catch bugs with undefineds
|
||||
while ({{{ makeGetValue('ptr', 'i', 'i8') }}}) i++; // Note: should be |!= 0|, technically. But this helps catch bugs with undefineds
|
||||
return i;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче