diff --git a/src/compiler.js b/src/compiler.js index a7013945a87c4..4f16986c572c1 100644 --- a/src/compiler.js +++ b/src/compiler.js @@ -213,7 +213,7 @@ load('parseTools.js'); load('intertyper.js'); load('analyzer.js'); load('jsifier.js'); -if (RELOOP) { +if (phase == 'funcs' && RELOOP) { // XXX handle !singlePhase RelooperModule = { TOTAL_MEMORY: ceilPowerOfTwo(2*RELOOPER_BUFFER_SIZE) }; load(RELOOPER); assert(typeof Relooper != 'undefined'); diff --git a/src/intertyper.js b/src/intertyper.js index 9c196803e173b..0f189863d8e91 100644 --- a/src/intertyper.js +++ b/src/intertyper.js @@ -4,151 +4,148 @@ // to be processed by the later stages. // Line tokenizer -var tokenizer = { - processItem: function _tokenizer(item, inner) { - //assert(item.lineNum != 40000); - //if (item.lineNum) print(item.lineNum); - var tokens = []; - var quotes = 0; - var lastToken = null; - var CHUNKSIZE = 64; // How much forward to peek forward. Too much means too many string segments copied - // Note: '{' is not an encloser, as its use in functions is split over many lines - var enclosers = { - '[': 0, - ']': '[', - '(': 0, - ')': '(', - '<': 0, - '>': '<' - }; - var totalEnclosing = 0; - function makeToken(text) { - if (text.length == 0) return; - // merge certain tokens - if (lastToken && ( (lastToken.text == '%' && text[0] == '"') || /^\**$/.test(text) ) ) { - lastToken.text += text; - return; - } +function tokenizer(item, inner) { + //assert(item.lineNum != 40000); + //if (item.lineNum) print(item.lineNum); + var tokens = []; + var quotes = 0; + var lastToken = null; + var CHUNKSIZE = 64; // How much forward to peek forward. Too much means too many string segments copied + // Note: '{' is not an encloser, as its use in functions is split over many lines + var enclosers = { + '[': 0, + ']': '[', + '(': 0, + ')': '(', + '<': 0, + '>': '<' + }; + var totalEnclosing = 0; + function makeToken(text) { + if (text.length == 0) return; + // merge certain tokens + if (lastToken && ( (lastToken.text == '%' && text[0] == '"') || /^\**$/.test(text) ) ) { + lastToken.text += text; + return; + } - var token = { - text: text - }; - if (text[0] in enclosers) { - token.item = tokenizer.processItem({ - lineText: text.substr(1, text.length-2) - }, true); - token.type = text[0]; - } - // merge certain tokens - if (lastToken && isType(lastToken.text) && isFunctionDef(token)) { - lastToken.text += ' ' + text; - } else if (lastToken && text[0] == '}') { // }, }*, etc. - var openBrace = tokens.length-1; - while (tokens[openBrace].text.substr(-1) != '{') openBrace --; - token = combineTokens(tokens.slice(openBrace+1)); - tokens.splice(openBrace, tokens.length-openBrace+1); - tokens.push(token); - token.type = '{'; - token.text = '{ ' + token.text + ' }'; - var pointingLevelsToAdd = pointingLevels(text) - pointingLevels(token.text); - while (pointingLevelsToAdd > 0) { - token.text += '*'; - pointingLevelsToAdd--; - } - lastToken = token; - } else { - tokens.push(token); - lastToken = token; + var token = { + text: text + }; + if (text[0] in enclosers) { + token.item = tokenizer({ + lineText: text.substr(1, text.length-2) + }, true); + token.type = text[0]; + } + // merge certain tokens + if (lastToken && isType(lastToken.text) && isFunctionDef(token)) { + lastToken.text += ' ' + text; + } else if (lastToken && text[0] == '}') { // }, }*, etc. + var openBrace = tokens.length-1; + while (tokens[openBrace].text.substr(-1) != '{') openBrace --; + token = combineTokens(tokens.slice(openBrace+1)); + tokens.splice(openBrace, tokens.length-openBrace+1); + tokens.push(token); + token.type = '{'; + token.text = '{ ' + token.text + ' }'; + var pointingLevelsToAdd = pointingLevels(text) - pointingLevels(token.text); + while (pointingLevelsToAdd > 0) { + token.text += '*'; + pointingLevelsToAdd--; } + lastToken = token; + } else { + tokens.push(token); + lastToken = token; } - // Split using meaningful characters - var lineText = item.lineText + ' '; - var re = /[\[\]\(\)<>, "]/g; - var segments = lineText.split(re); - segments.pop(); - var len = segments.length; - var i = -1; - var curr = ''; - var segment, letter; - for (var s = 0; s < len; s++) { - segment = segments[s]; - i += segment.length + 1; - letter = lineText[i]; - curr += segment; - switch (letter) { - case ' ': - if (totalEnclosing == 0 && quotes == 0) { - makeToken(curr); - curr = ''; - } else { - curr += ' '; - } - break; - case '"': - if (totalEnclosing == 0) { - if (quotes == 0) { - if (curr == '@' || curr == '%') { - curr += '"'; - } else { - makeToken(curr); - curr = '"'; - } + } + // Split using meaningful characters + var lineText = item.lineText + ' '; + var re = /[\[\]\(\)<>, "]/g; + var segments = lineText.split(re); + segments.pop(); + var len = segments.length; + var i = -1; + var curr = ''; + var segment, letter; + for (var s = 0; s < len; s++) { + segment = segments[s]; + i += segment.length + 1; + letter = lineText[i]; + curr += segment; + switch (letter) { + case ' ': + if (totalEnclosing == 0 && quotes == 0) { + makeToken(curr); + curr = ''; + } else { + curr += ' '; + } + break; + case '"': + if (totalEnclosing == 0) { + if (quotes == 0) { + if (curr == '@' || curr == '%') { + curr += '"'; } else { - makeToken(curr + '"'); - curr = ''; + makeToken(curr); + curr = '"'; } } else { - curr += '"'; + makeToken(curr + '"'); + curr = ''; } - quotes = 1-quotes; + } else { + curr += '"'; + } + quotes = 1-quotes; + break; + case ',': + if (totalEnclosing == 0 && quotes == 0) { + makeToken(curr); + curr = ''; + tokens.push({ text: ',' }); + } else { + curr += ','; + } + break; + default: + assert(letter in enclosers); + if (quotes) { + curr += letter; break; - case ',': - if (totalEnclosing == 0 && quotes == 0) { + } + if (letter in ENCLOSER_STARTERS) { + if (totalEnclosing == 0) { makeToken(curr); curr = ''; - tokens.push({ text: ',' }); - } else { - curr += ','; - } - break; - default: - assert(letter in enclosers); - if (quotes) { - curr += letter; - break; } - if (letter in ENCLOSER_STARTERS) { - if (totalEnclosing == 0) { - makeToken(curr); - curr = ''; - } - curr += letter; - enclosers[letter]++; - totalEnclosing++; + curr += letter; + enclosers[letter]++; + totalEnclosing++; + } else { + enclosers[enclosers[letter]]--; + totalEnclosing--; + if (totalEnclosing == 0) { + makeToken(curr + letter); + curr = ''; } else { - enclosers[enclosers[letter]]--; - totalEnclosing--; - if (totalEnclosing == 0) { - makeToken(curr + letter); - curr = ''; - } else { - curr += letter; - } + curr += letter; } - } + } } - var newItem = { - tokens: tokens, - indent: lineText.search(/[^ ]/), - lineNum: item.lineNum - }; - return newItem; - return null; } -}; + var newItem = { + tokens: tokens, + indent: lineText.search(/[^ ]/), + lineNum: item.lineNum + }; + return newItem; +} function tokenize(text) { - return tokenizer.processItem({ lineText: text }, true); + return tokenizer({ lineText: text }, true); } // Handy sets @@ -252,7 +249,7 @@ function intertyper(lines, sidePass, baseLineNums) { if (mainPass && /^}.*/.test(line)) { inFunction = false; if (mainPass) { - var func = funcHeaderHandler(tokenizer.processItem({ lineText: currFunctionLines[0], lineNum: currFunctionLineNum }, true)); + var func = funcHeaderHandler(tokenizer({ lineText: currFunctionLines[0], lineNum: currFunctionLineNum }, true)); if (SKIP_STACK_IN_SMALL && /emscripten_autodebug/.exec(func.ident)) { warnOnce('Disabling SKIP_STACK_IN_SMALL because we are apparently processing autodebugger data'); @@ -991,10 +988,13 @@ function intertyper(lines, sidePass, baseLineNums) { // Input - return lineSplitter().map(tokenizer.processItem).filter(function(item) { return item }).map(triager).filter(function(result) { + var ret = lineSplitter().map(tokenizer).map(triager).filter(function(result) { if (!result) return false; if (result.tokens) result.tokens = null; // We do not need tokens, past the intertyper. Clean them up as soon as possible here. return true; - }).concat(unparsedBundles).concat(extraResults); + }); + if (unparsedBundles.length > 0) ret = ret.concat(unparsedBundles); + if (extraResults.length > 0) ret = ret.concat(extraResults); + return ret; } diff --git a/src/jsifier.js b/src/jsifier.js index 53b9bb083501e..a8c8d32d14cc1 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -60,15 +60,6 @@ function JSify(data, functionsOnly, givenFunctions) { } } - // Does simple 'macro' substitution, using Django-like syntax, - // {{{ code }}} will be replaced with |eval(code)|. - function processMacros(text) { - return text.replace(/{{{[^}]+}}}/g, function(str) { - str = str.substr(3, str.length-6); - return eval(str).toString(); - }); - } - if (mainPass) { // Handle unparsed types TODO: Batch them analyzer(intertyper(data.unparsedTypess[0].lines, true), true); diff --git a/src/preamble.js b/src/preamble.js index 8e70cb7475c3d..acff665f8e629 100644 --- a/src/preamble.js +++ b/src/preamble.js @@ -908,6 +908,17 @@ function writeArrayToMemory(array, buffer) { } Module['writeArrayToMemory'] = writeArrayToMemory; +function writeAsciiToMemory(str, buffer, dontAddNull) { + for (var i = 0; i < str.length; i++) { +#if ASSERTIONS + assert(str.charCodeAt(i) === str.charCodeAt(i)&0xff); +#endif + {{{ makeSetValue('buffer', 'i', 'str.charCodeAt(i)', 'i8') }}} + } + if (!dontAddNull) {{{ makeSetValue('buffer', 'str.length', 0, 'i8') }}} +} +Module['writeAsciiToMemory'] = writeAsciiToMemory; + {{{ unSign }}} {{{ reSign }}} diff --git a/src/relooper/Relooper.cpp b/src/relooper/Relooper.cpp index afb6ecc8fb751..d79dca5a3657d 100644 --- a/src/relooper/Relooper.cpp +++ b/src/relooper/Relooper.cpp @@ -8,8 +8,6 @@ #include "ministring.h" -// TODO: move all set to unorderedset - template bool contains(const T& container, const U& contained) { return container.find(contained) != container.end(); } diff --git a/src/relooper/emscripten/glue.js b/src/relooper/emscripten/glue.js index f5b9e142b9810..587cf5295b0a9 100644 --- a/src/relooper/emscripten/glue.js +++ b/src/relooper/emscripten/glue.js @@ -19,10 +19,10 @@ RelooperGlue['addBlock'] = function(text, branchVar) { assert(this.r); assert(text.length+1 < TBUFFER_SIZE, 'buffer too small, increase RELOOPER_BUFFER_SIZE'); - writeStringToMemory(text, tbuffer); + writeAsciiToMemory(text, tbuffer); if (branchVar) { assert(branchVar.length+1 < VBUFFER_SIZE, 'buffer too small, increase RELOOPER_BUFFER_SIZE'); - writeStringToMemory(branchVar, vbuffer); + writeAsciiToMemory(branchVar, vbuffer); } var b = _rl_new_block(tbuffer, branchVar ? vbuffer : 0); _rl_relooper_add_block(this.r, b); @@ -32,14 +32,14 @@ assert(this.r); if (condition) { assert(condition.length+1 < TBUFFER_SIZE/2, 'buffer too small, increase RELOOPER_BUFFER_SIZE'); - writeStringToMemory(condition, tbuffer); + writeAsciiToMemory(condition, tbuffer); condition = tbuffer; } else { condition = 0; // allow undefined, null, etc. as inputs } if (code) { assert(code.length+1 < TBUFFER_SIZE/2, 'buffer too small, increase RELOOPER_BUFFER_SIZE'); - writeStringToMemory(code, tbuffer + TBUFFER_SIZE/2); + writeAsciiToMemory(code, tbuffer + TBUFFER_SIZE/2); code = tbuffer + TBUFFER_SIZE/2; } else { code = 0; // allow undefined, null, etc. as inputs diff --git a/src/runtime.js b/src/runtime.js index 6b1afd8051ba1..00031fed01852 100644 --- a/src/runtime.js +++ b/src/runtime.js @@ -145,29 +145,30 @@ var Runtime = { return l + h; }, - //! Returns the size of a type, as C/C++ would have it (in 32-bit, for now), in bytes. + //! Returns the size of a type, as C/C++ would have it (in 32-bit), in bytes. //! @param type The type, by name. - getNativeTypeSize: function(type, quantumSize) { - if (Runtime.QUANTUM_SIZE == 1) return 1; - var size = { - '%i1': 1, - '%i8': 1, - '%i16': 2, - '%i32': 4, - '%i64': 8, - "%float": 4, - "%double": 8 - }['%'+type]; // add '%' since float and double confuse Closure compiler as keys, and also spidermonkey as a compiler will remove 's from '_i8' etc - if (!size) { - if (type.charAt(type.length-1) == '*') { - size = Runtime.QUANTUM_SIZE; // A pointer - } else if (type[0] == 'i') { - var bits = parseInt(type.substr(1)); - assert(bits % 8 == 0); - size = bits/8; + getNativeTypeSize: function(type) { +#if QUANTUM_SIZE == 1 + return 1; +#else + switch (type) { + case 'i1': case 'i8': return 1; + case 'i16': return 2; + case 'i32': return 4; + case 'i64': return 8; + case 'float': return 4; + case 'double': return 8; + default: { + if (type[type.length-1] === '*') { + return Runtime.QUANTUM_SIZE; // A pointer + } else if (type[0] === 'i') { + var bits = parseInt(type.substr(1)); + assert(bits % 8 === 0); + return bits/8; + } } } - return size; +#endif }, //! Returns the size of a structure field, as C/C++ would have it (in 32-bit, diff --git a/tools/shared.py b/tools/shared.py index d605dee98380a..4e1a3ebf163fe 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -304,7 +304,7 @@ def find_temp_directory(): # 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.6.0' +EMSCRIPTEN_VERSION = '1.6.1' def generate_sanity(): return EMSCRIPTEN_VERSION + '|' + get_llvm_target() + '|' + LLVM_ROOT