diff options
author | Alon Zakai <alonzakai@gmail.com> | 2011-12-03 21:22:03 -0800 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2011-12-03 21:22:03 -0800 |
commit | 122b5bba34dd024a54b790caf5aabeec42a779d3 (patch) | |
tree | 9b2d6419684f23fc07f8944e591c78d0579f8291 | |
parent | 556decb19a4bcb32daad1569402fcc385d49b1d4 (diff) |
various minor compiler optimizations
-rw-r--r-- | src/analyzer.js | 7 | ||||
-rw-r--r-- | src/intertyper.js | 29 | ||||
-rw-r--r-- | src/jsifier.js | 11 | ||||
-rw-r--r-- | src/modules.js | 1 | ||||
-rw-r--r-- | src/parseTools.js | 23 |
5 files changed, 48 insertions, 23 deletions
diff --git a/src/analyzer.js b/src/analyzer.js index 5b34c665..677b61b0 100644 --- a/src/analyzer.js +++ b/src/analyzer.js @@ -15,6 +15,12 @@ function cleanFunc(func) { }); } +// Handy sets + +var BRANCH_INVOKE = set('branch', 'invoke'); + +// Analyzer + function analyzer(data) { // Substrate var substrate = new Substrate('Analyzer'); @@ -728,7 +734,6 @@ function analyzer(data) { } }); - var BRANCH_INVOKE = set('branch', 'invoke'); function operateOnLabels(line, func) { function process(item, id) { ['label', 'labelTrue', 'labelFalse', 'toLabel', 'unwindLabel', 'defaultLabel'].forEach(function(id) { diff --git a/src/intertyper.js b/src/intertyper.js index 834345bf..03fbf072 100644 --- a/src/intertyper.js +++ b/src/intertyper.js @@ -9,6 +9,20 @@ function tokenize(text) { return tokenizer.processItem({ lineText: text }, true); } +// Handy sets + +var ENCLOSER_STARTERS = set('[', '(', '<'); +var ENCLOSER_ENDERS = { + '[': ']', + '(': ')', + '<': '>' +}; +var MATHOPS = set(['add', 'sub', 'sdiv', 'udiv', 'mul', 'icmp', 'zext', 'urem', 'srem', 'fadd', 'fsub', 'fmul', 'fdiv', 'fcmp', 'uitofp', 'sitofp', 'fpext', 'fptrunc', 'fptoui', 'fptosi', 'trunc', 'sext', 'select', 'shl', 'shr', 'ashl', 'ashr', 'lshr', 'lshl', 'xor', 'or', 'and', 'ptrtoint', 'inttoptr']); +var ZEROINIT_UNDEF = set('zeroinitializer', 'undef'); +var NSW_NUW = set('nsw', 'nuw'); + +// Intertyper + function intertyper(data, sidePass, baseLineNum) { var mainPass = !sidePass; baseLineNum = baseLineNum || 0; @@ -124,13 +138,6 @@ function intertyper(data, sidePass, baseLineNum) { } }); - var ENCLOSER_STARTERS = set('[', '(', '<'); - var ENCLOSER_ENDERS = { - '[': ']', - '(': ')', - '<': '>' - }; - // Line tokenizer tokenizer = substrate.addActor('Tokenizer', { processItem: function _tokenizer(item, inner) { @@ -280,8 +287,6 @@ function intertyper(data, sidePass, baseLineNum) { } }); - var MATHOPS = set(['add', 'sub', 'sdiv', 'udiv', 'mul', 'icmp', 'zext', 'urem', 'srem', 'fadd', 'fsub', 'fmul', 'fdiv', 'fcmp', 'uitofp', 'sitofp', 'fpext', 'fptrunc', 'fptoui', 'fptosi', 'trunc', 'sext', 'select', 'shl', 'shr', 'ashl', 'ashr', 'lshr', 'lshl', 'xor', 'or', 'and', 'ptrtoint', 'inttoptr']); - substrate.addActor('Triager', { processItem: function _triager(item) { function triage() { @@ -407,7 +412,7 @@ function intertyper(data, sidePass, baseLineNum) { Types.needAnalysis[type] = 0; if (Runtime.isNumberType(type) || pointingLevels(type) >= 1) { return { value: toNiceIdent(value.text), type: type }; - } else if (value.text in set('zeroinitializer', 'undef')) { // undef doesn't really need initting, but why not + } else if (value.text in ZEROINIT_UNDEF) { // undef doesn't really need initting, but why not return { intertype: 'emptystruct', type: type }; } else if (value.text && value.text[0] == '"') { return { intertype: 'string', text: value.text.substr(1, value.text.length-2) }; @@ -519,7 +524,7 @@ function intertyper(data, sidePass, baseLineNum) { var funcHeader = substrate.addActor('FuncHeader', { processItem: function(item) { item.tokens = item.tokens.filter(function(token) { - return !(token.text in LLVM.LINKAGES || token.text in LLVM.PARAM_ATTR || token.text in set('hidden', 'nounwind', 'define', 'inlinehint', '{') || token.text in LLVM.CALLING_CONVENTIONS); + return !(token.text in LLVM.LINKAGES || token.text in LLVM.PARAM_ATTR || token.text in LLVM.FUNC_ATTR || token.text in LLVM.CALLING_CONVENTIONS); }); var params = parseParamTokens(item.tokens[2].item.tokens); return [{ @@ -776,7 +781,7 @@ function intertyper(data, sidePass, baseLineNum) { item.intertype = 'mathop'; item.op = item.tokens[0].text; item.variant = null; - while (item.tokens[1].text in set('nsw', 'nuw')) item.tokens.splice(1, 1); + while (item.tokens[1].text in NSW_NUW) item.tokens.splice(1, 1); if (['icmp', 'fcmp'].indexOf(item.op) != -1) { item.variant = item.tokens[1].text; item.tokens.splice(1, 1); diff --git a/src/jsifier.js b/src/jsifier.js index 2cb4dee9..df2ae43f 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -3,7 +3,12 @@ // Convert analyzed data to javascript. Everything has already been calculated // before this stage, which just does the final conversion to JavaScript. -// Main function +// Handy sets + +var STRUCT_LIST = set('struct', 'list'); +var UNDERSCORE_OPENPARENS = set('_', '('); + +// JSifier function JSify(data, functionsOnly, givenFunctions) { var mainPass = !functionsOnly; @@ -195,7 +200,7 @@ function JSify(data, functionsOnly, givenFunctions) { ret = makeEmptyStruct(segment.type); } else if (segment.intertype in PARSABLE_LLVM_FUNCTIONS) { ret = finalizeLLVMFunctionCall(segment); - } else if (segment.intertype in set('struct', 'list')) { + } else if (segment.intertype in STRUCT_LIST) { ret = alignStruct(handleSegments(segment.contents), segment.type); } else if (segment.intertype === 'string') { ret = parseLLVMString(segment.text); // + ' /* ' + text + '*/'; @@ -237,7 +242,7 @@ function JSify(data, functionsOnly, givenFunctions) { substrate.addActor('GlobalVariable', { processItem: function(item) { function needsPostSet(value) { - return value[0] in set('_', '(') || value.substr(0, 14) === 'CHECK_OVERFLOW'; + return value[0] in UNDERSCORE_OPENPARENS || value.substr(0, 14) === 'CHECK_OVERFLOW'; } item.intertype = 'GlobalVariableStub'; diff --git a/src/modules.js b/src/modules.js index 411bc66f..3ce4a541 100644 --- a/src/modules.js +++ b/src/modules.js @@ -10,6 +10,7 @@ var LLVM = { 'weak_odr', 'externally_visible', 'dllimport', 'dllexport', 'unnamed_addr'), VISIBILITIES: set('default', 'hidden', 'protected'), PARAM_ATTR: set('noalias', 'signext', 'zeroext', 'inreg', 'sret', 'nocapture', 'nest'), + FUNC_ATTR: set('hidden', 'nounwind', 'define', 'inlinehint', '{'), CALLING_CONVENTIONS: set('ccc', 'fastcc', 'coldcc', 'cc10', 'x86_fastcallcc', 'x86_stdcallcc'), ACCESS_OPTIONS: set('volatile', 'atomic'), INVOKE_MODIFIERS: set('alignstack', 'alwaysinline', 'inlinehint', 'naked', 'noimplicitfloat', 'noinline', 'alwaysinline attribute.', 'noredzone', 'noreturn', 'nounwind', 'optsize', 'readnone', 'readonly', 'ssp', 'sspreq'), diff --git a/src/parseTools.js b/src/parseTools.js index 800d6b8b..3eaf3577 100644 --- a/src/parseTools.js +++ b/src/parseTools.js @@ -225,6 +225,8 @@ function findTokenText(item, text) { return -1; } +var SPLIT_TOKEN_LIST_SPLITTERS = set(',', 'to'); // 'to' can separate parameters as well... + // Splits a list of tokens separated by commas. For example, a list of arguments in a function call function splitTokenList(tokens) { if (tokens.length == 0) return []; @@ -232,10 +234,9 @@ function splitTokenList(tokens) { if (tokens.slice(-1)[0].text != ',') tokens.push({text:','}); var ret = []; var seg = []; - var SPLITTERS = set(',', 'to'); // 'to' can separate parameters as well... for (var i = 0; i < tokens.length; i++) { var token = tokens[i]; - if (token.text in SPLITTERS) { + if (token.text in SPLIT_TOKEN_LIST_SPLITTERS) { ret.push(seg); seg = []; } else if (token.text == ';') { @@ -1013,12 +1014,14 @@ function makeSetValue(ptr, pos, value, type, noNeedFirst, ignore, align) { var UNROLL_LOOP_MAX = 5; +var ZERO_ONE = set(0, 1); + function makeSetValues(ptr, pos, value, type, num) { function safety(where) { where = where || getFastValue(ptr, '+', pos) + '+mspi'; return ';' + (SAFE_HEAP ? 'SAFE_HEAP_ACCESS(' + where + ', ' + type + ', 1)' : ''); } - if (USE_TYPED_ARRAYS in set(0, 1)) { + if (USE_TYPED_ARRAYS in ZERO_ONE) { if (isNumber(num)) { if (parseInt(num) <= UNROLL_LOOP_MAX) { return range(num).map(function(i) { @@ -1134,6 +1137,10 @@ function makeCopyValues(dest, src, num, type, modifier) { return null; } +var PLUS_MUL = set('+', '*'); +var MUL_DIV = set('*', '/'); +var PLUS_MINUS = set('+', '-'); + // Given two values and an operation, returns the result of that operation. // Tries to do as much as possible at compile time. function getFastValue(a, op, b, type) { @@ -1142,12 +1149,12 @@ function getFastValue(a, op, b, type) { if (isNumber(a) && isNumber(b)) { return eval(a + op + b).toString(); } - if (op in set('+', '*') && isNumber(a)) { // if one of them is a number, keep it last + if (op in PLUS_MUL && isNumber(a)) { // if one of them is a number, keep it last var c = b; b = a; a = c; } - if (op in set('*', '/')) { + if (op in MUL_DIV) { if (op == '*') { if (a == 0 || b == 0) { return '0'; @@ -1168,7 +1175,7 @@ function getFastValue(a, op, b, type) { return a; } // Doing shifts for division is problematic, as getting the rounding right on negatives is tricky } - } else if (op in set('+', '-')) { + } else if (op in PLUS_MINUS) { if (b[0] == '-') { op = op == '+' ? '-' : '+'; b = b.substr(1); @@ -1212,9 +1219,11 @@ function makeGetPos(ptr) { return ptr; } +var IHEAP_FHEAP = set('IHEAP', 'FHEAP'); + function makePointer(slab, pos, allocator, type) { assert(type, 'makePointer requires type info'); - if (slab.substr(0, 4) === 'HEAP' || (USE_TYPED_ARRAYS == 1 && slab in set('IHEAP', 'FHEAP'))) return pos; + if (slab.substr(0, 4) === 'HEAP' || (USE_TYPED_ARRAYS == 1 && slab in IHEAP_FHEAP)) return pos; var types = generateStructTypes(type); // compress type info and data if possible var de; |