webruby 0.2.5 → 0.2.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/webruby.rb +0 -4
- data/lib/webruby/app.rb +4 -0
- data/lib/webruby/rake/files.rake +2 -1
- data/lib/webruby/rake/mruby.rake +1 -1
- data/modules/emscripten/AUTHORS +1 -0
- data/modules/emscripten/ChangeLog +34 -1
- data/modules/emscripten/cmake/Platform/Emscripten.cmake +30 -9
- data/modules/emscripten/emcc +61 -28
- data/modules/emscripten/emrun +15 -11
- data/modules/emscripten/emscripten.py +3 -0
- data/modules/emscripten/src/closure-externs.js +110 -0
- data/modules/emscripten/src/intertyper.js +1 -1
- data/modules/emscripten/src/jsifier.js +7 -21
- data/modules/emscripten/src/library.js +2 -1
- data/modules/emscripten/src/library_browser.js +16 -5
- data/modules/emscripten/src/library_fs.js +3 -1
- data/modules/emscripten/src/library_gl.js +691 -591
- data/modules/emscripten/src/library_glut.js +2 -0
- data/modules/emscripten/src/library_sdl.js +29 -5
- data/modules/emscripten/src/library_uuid.js +140 -0
- data/modules/emscripten/src/modules.js +1 -1
- data/modules/emscripten/src/parseTools.js +29 -19
- data/modules/emscripten/src/postamble.js +3 -4
- data/modules/emscripten/src/preamble.js +17 -1
- data/modules/emscripten/src/relooper/Relooper.cpp +8 -8
- data/modules/emscripten/src/relooper/Relooper.h +5 -5
- data/modules/emscripten/src/relooper/test.txt +2 -2
- data/modules/emscripten/src/runtime.js +1 -1
- data/modules/emscripten/src/settings.js +3 -0
- data/modules/emscripten/src/struct_info.json +12 -0
- data/modules/emscripten/system/include/uuid/uuid.h +35 -0
- data/modules/emscripten/tools/js-optimizer.js +191 -142
- data/modules/emscripten/tools/js_optimizer.py +3 -29
- data/modules/emscripten/tools/shared.py +43 -6
- data/modules/mruby/include/mruby/value.h +3 -2
- data/modules/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c +5 -9
- data/modules/mruby/mrbgems/mruby-bin-mruby/tools/mruby/mruby.c +3 -5
- data/modules/mruby/mrbgems/mruby-hash-ext/src/hash-ext.c +0 -3
- data/modules/mruby/mrbgems/mruby-numeric-ext/src/numeric_ext.c +0 -1
- data/modules/mruby/mrbgems/mruby-random/src/mt19937ar.c +0 -1
- data/modules/mruby/mrbgems/mruby-range-ext/src/range.c +2 -6
- data/modules/mruby/mrbgems/mruby-sprintf/src/sprintf.c +0 -4
- data/modules/mruby/mrbgems/mruby-string-ext/mrblib/string.rb +22 -0
- data/modules/mruby/mrbgems/mruby-string-ext/src/string.c +2 -2
- data/modules/mruby/mrbgems/mruby-string-ext/test/string.rb +21 -2
- data/modules/mruby/mrbgems/mruby-string-utf8/mrbgem.rake +4 -0
- data/modules/mruby/mrbgems/mruby-string-utf8/src/string.c +297 -0
- data/modules/mruby/mrbgems/mruby-string-utf8/test/string.rb +27 -0
- data/modules/mruby/mrbgems/mruby-struct/src/struct.c +0 -1
- data/modules/mruby/mrblib/init_mrblib.c +0 -3
- data/modules/mruby/src/array.c +22 -8
- data/modules/mruby/src/backtrace.c +12 -9
- data/modules/mruby/src/class.c +3 -3
- data/modules/mruby/src/codegen.c +17 -5
- data/modules/mruby/src/dump.c +5 -6
- data/modules/mruby/src/error.c +0 -2
- data/modules/mruby/src/etc.c +0 -2
- data/modules/mruby/src/gc.c +4 -8
- data/modules/mruby/src/load.c +1 -6
- data/modules/mruby/src/numeric.c +0 -6
- data/modules/mruby/src/object.c +3 -5
- data/modules/mruby/src/parse.y +37 -38
- data/modules/mruby/src/proc.c +8 -1
- data/modules/mruby/src/range.c +3 -7
- data/modules/mruby/src/state.c +0 -1
- data/modules/mruby/src/string.c +2 -17
- data/modules/mruby/src/symbol.c +0 -1
- data/modules/mruby/src/variable.c +3 -22
- data/modules/mruby/src/vm.c +9 -8
- data/modules/mruby/tasks/mrbgem_spec.rake +13 -5
- data/modules/mruby/tasks/mrbgems_test.rake +3 -3
- data/modules/mruby/tasks/mruby_build_commands.rake +2 -2
- data/modules/mruby/tasks/mruby_build_gem.rake +3 -3
- data/modules/mruby/test/init_mrbtest.c +0 -3
- data/modules/mruby/test/t/array.rb +12 -1
- data/modules/mruby/test/t/class.rb +67 -0
- data/modules/mruby/test/t/exception.rb +12 -0
- data/modules/mruby/test/t/kernel.rb +75 -1
- data/modules/mruby/test/t/syntax.rb +115 -0
- data/scripts/gen_require.rb +12 -1
- metadata +8 -2
|
@@ -250,7 +250,7 @@ var Runtime = {
|
|
|
250
250
|
prev = curr;
|
|
251
251
|
return curr;
|
|
252
252
|
});
|
|
253
|
-
if (type.name_[0] === '[') {
|
|
253
|
+
if (type.name_ && type.name_[0] === '[') {
|
|
254
254
|
// arrays have 2 elements, so we get the proper difference. then we scale here. that way we avoid
|
|
255
255
|
// allocating a potentially huge array for [999999 x i8] etc.
|
|
256
256
|
type.flatSize = parseInt(type.name_.substr(1))*type.flatSize/2;
|
|
@@ -123,6 +123,7 @@ var PRECISE_F32 = 0; // 0: Use JS numbers for floating-point values. These are 6
|
|
|
123
123
|
// 2: Model C++ floats precisely using Math.fround if available in the JS engine, otherwise
|
|
124
124
|
// use an empty polyfill. This will have less of a speed penalty than using the full
|
|
125
125
|
// polyfill in cases where engine support is not present.
|
|
126
|
+
var SIMD = 0; // Whether to emit SIMD code ( https://github.com/johnmccutchan/ecmascript_simd )
|
|
126
127
|
|
|
127
128
|
var CLOSURE_ANNOTATIONS = 0; // If set, the generated code will be annotated for the closure
|
|
128
129
|
// compiler. This potentially lets closure optimize the code better.
|
|
@@ -156,6 +157,8 @@ var OUTLINING_LIMIT = 0; // A function size above which we try to automatically
|
|
|
156
157
|
// with, but something around 20,000 to 100,000 might make sense.
|
|
157
158
|
// (The unit size is number of AST nodes.)
|
|
158
159
|
|
|
160
|
+
var AGGRESSIVE_VARIABLE_ELIMINATION = 0; // Run aggressiveVariableElimination in js-optimizer.js
|
|
161
|
+
|
|
159
162
|
// Generated code debugging options
|
|
160
163
|
var SAFE_HEAP = 0; // Check each write to the heap, for example, this will give a clear
|
|
161
164
|
// error on what would be segfaults in a native build (like deferencing
|
|
@@ -1061,5 +1061,17 @@
|
|
|
1061
1061
|
"patch"
|
|
1062
1062
|
]
|
|
1063
1063
|
}
|
|
1064
|
+
},
|
|
1065
|
+
{
|
|
1066
|
+
"file": "uuid/uuid.h",
|
|
1067
|
+
"defines": [
|
|
1068
|
+
"UUID_VARIANT_NCS",
|
|
1069
|
+
"UUID_VARIANT_DCE",
|
|
1070
|
+
"UUID_VARIANT_MICROSOFT",
|
|
1071
|
+
"UUID_VARIANT_OTHER",
|
|
1072
|
+
"UUID_TYPE_DCE_TIME",
|
|
1073
|
+
"UUID_TYPE_DCE_RANDOM"
|
|
1074
|
+
],
|
|
1075
|
+
"structs": {}
|
|
1064
1076
|
}
|
|
1065
1077
|
]
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
|
|
2
|
+
#ifndef _UUID_H
|
|
3
|
+
#define _UUID_H
|
|
4
|
+
|
|
5
|
+
typedef unsigned char uuid_t[16];
|
|
6
|
+
|
|
7
|
+
#define UUID_VARIANT_NCS 0
|
|
8
|
+
#define UUID_VARIANT_DCE 1
|
|
9
|
+
#define UUID_VARIANT_MICROSOFT 2
|
|
10
|
+
#define UUID_VARIANT_OTHER 3
|
|
11
|
+
|
|
12
|
+
#define UUID_TYPE_DCE_TIME 1
|
|
13
|
+
#define UUID_TYPE_DCE_RANDOM 4
|
|
14
|
+
|
|
15
|
+
#ifdef __cplusplus
|
|
16
|
+
extern "C" {
|
|
17
|
+
#endif
|
|
18
|
+
|
|
19
|
+
void uuid_clear(uuid_t uu);
|
|
20
|
+
int uuid_compare(const uuid_t uu1, const uuid_t uu2);
|
|
21
|
+
void uuid_copy(uuid_t dst, const uuid_t src);
|
|
22
|
+
void uuid_generate(uuid_t out);
|
|
23
|
+
int uuid_is_null(const uuid_t uu);
|
|
24
|
+
int uuid_parse(const char *in, uuid_t uu);
|
|
25
|
+
void uuid_unparse(const uuid_t uu, char *out);
|
|
26
|
+
void uuid_unparse_lower(const uuid_t uu, char *out);
|
|
27
|
+
void uuid_unparse_upper(const uuid_t uu, char *out);
|
|
28
|
+
int uuid_type(const uuid_t uu);
|
|
29
|
+
int uuid_variant(const uuid_t uu);
|
|
30
|
+
|
|
31
|
+
#ifdef __cplusplus
|
|
32
|
+
}
|
|
33
|
+
#endif
|
|
34
|
+
|
|
35
|
+
#endif /* _UUID_H */
|
|
@@ -1743,6 +1743,36 @@ function getStackBumpSize(ast) {
|
|
|
1743
1743
|
return node ? node[3][2][3][1] : 0;
|
|
1744
1744
|
}
|
|
1745
1745
|
|
|
1746
|
+
// Name minification
|
|
1747
|
+
|
|
1748
|
+
var RESERVED = set('do', 'if', 'in', 'for', 'new', 'try', 'var', 'env', 'let');
|
|
1749
|
+
var VALID_MIN_INITS = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_$';
|
|
1750
|
+
var VALID_MIN_LATERS = VALID_MIN_INITS + '0123456789';
|
|
1751
|
+
|
|
1752
|
+
var minifiedNames = [];
|
|
1753
|
+
var minifiedState = [0];
|
|
1754
|
+
|
|
1755
|
+
function ensureMinifiedNames(n) { // make sure the nth index in minifiedNames exists. done 100% deterministically
|
|
1756
|
+
while (minifiedNames.length < n+1) {
|
|
1757
|
+
// generate the current name
|
|
1758
|
+
var name = VALID_MIN_INITS[minifiedState[0]];
|
|
1759
|
+
for (var i = 1; i < minifiedState.length; i++) {
|
|
1760
|
+
name += VALID_MIN_LATERS[minifiedState[i]];
|
|
1761
|
+
}
|
|
1762
|
+
if (!(name in RESERVED)) minifiedNames.push(name);
|
|
1763
|
+
// increment the state
|
|
1764
|
+
var i = 0;
|
|
1765
|
+
while (1) {
|
|
1766
|
+
minifiedState[i]++;
|
|
1767
|
+
if (minifiedState[i] < (i === 0 ? VALID_MIN_INITS : VALID_MIN_LATERS).length) break;
|
|
1768
|
+
// overflow
|
|
1769
|
+
minifiedState[i] = 0;
|
|
1770
|
+
i++;
|
|
1771
|
+
if (i === minifiedState.length) minifiedState.push(-1); // will become 0 after increment in next loop head
|
|
1772
|
+
}
|
|
1773
|
+
}
|
|
1774
|
+
}
|
|
1775
|
+
|
|
1746
1776
|
// Very simple 'registerization', coalescing of variables into a smaller number,
|
|
1747
1777
|
// as part of minification. Globals-level minification began in a previous pass,
|
|
1748
1778
|
// we receive extraInfo which tells us how to rename globals. (Only in asm.js.)
|
|
@@ -1853,14 +1883,14 @@ function registerize(ast) {
|
|
|
1853
1883
|
return ret;
|
|
1854
1884
|
}
|
|
1855
1885
|
// find the next free minified name that is not used by a global that shows up in this function
|
|
1856
|
-
while (
|
|
1857
|
-
|
|
1886
|
+
while (1) {
|
|
1887
|
+
ensureMinifiedNames(nextRegName);
|
|
1888
|
+
var ret = minifiedNames[nextRegName++];
|
|
1858
1889
|
if (!usedGlobals[ret]) {
|
|
1859
1890
|
regTypes[ret] = type;
|
|
1860
1891
|
return ret;
|
|
1861
1892
|
}
|
|
1862
1893
|
}
|
|
1863
|
-
assert('ran out of names');
|
|
1864
1894
|
}
|
|
1865
1895
|
// Find the # of uses of each variable.
|
|
1866
1896
|
// While doing so, check if all a variable's uses are dominated in a simple
|
|
@@ -2847,16 +2877,16 @@ function minifyGlobals(ast) {
|
|
|
2847
2877
|
var vars = node[1];
|
|
2848
2878
|
for (var i = 0; i < vars.length; i++) {
|
|
2849
2879
|
var name = vars[i][0];
|
|
2850
|
-
|
|
2851
|
-
vars[i][0] = minified[name] =
|
|
2880
|
+
ensureMinifiedNames(next);
|
|
2881
|
+
vars[i][0] = minified[name] = minifiedNames[next++];
|
|
2852
2882
|
}
|
|
2853
2883
|
}
|
|
2854
2884
|
});
|
|
2855
2885
|
// add all globals in function chunks, i.e. not here but passed to us
|
|
2856
2886
|
for (var i = 0; i < extraInfo.globals.length; i++) {
|
|
2857
2887
|
name = extraInfo.globals[i];
|
|
2858
|
-
|
|
2859
|
-
minified[name] =
|
|
2888
|
+
ensureMinifiedNames(next);
|
|
2889
|
+
minified[name] = minifiedNames[next++];
|
|
2860
2890
|
}
|
|
2861
2891
|
// apply minification
|
|
2862
2892
|
traverse(ast, function(node, type) {
|
|
@@ -2930,162 +2960,180 @@ function relocate(ast) {
|
|
|
2930
2960
|
var NODES_WITHOUT_ELIMINATION_SENSITIVITY = set('name', 'num', 'binary', 'unary-prefix');
|
|
2931
2961
|
var FAST_ELIMINATION_BINARIES = setUnion(setUnion(USEFUL_BINARY_OPS, COMPARE_OPS), set('+'));
|
|
2932
2962
|
|
|
2933
|
-
function
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
}
|
|
2941
|
-
|
|
2942
|
-
function aggressiveVariableElimination(func, asmData) {
|
|
2943
|
-
// This removes as many variables as possible. This is often not the best thing because it increases
|
|
2944
|
-
// code size, but it is far preferable to the risk of split functions needing to do more spilling. Specifically,
|
|
2945
|
-
// it finds 'trivial' variables: ones with 1 definition, and that definition is not sensitive to any changes: it
|
|
2946
|
-
// only depends on constants and local variables that are themselves trivial. We can unquestionably eliminate
|
|
2947
|
-
// such variables in a trivial manner.
|
|
2948
|
-
|
|
2949
|
-
var assignments = {};
|
|
2950
|
-
var appearances = {};
|
|
2951
|
-
var defs = {};
|
|
2952
|
-
var considered = {};
|
|
2963
|
+
function measureSize(ast) {
|
|
2964
|
+
var size = 0;
|
|
2965
|
+
traverse(ast, function() {
|
|
2966
|
+
size++;
|
|
2967
|
+
});
|
|
2968
|
+
return size;
|
|
2969
|
+
}
|
|
2953
2970
|
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
|
|
2962
|
-
|
|
2963
|
-
|
|
2964
|
-
|
|
2965
|
-
|
|
2966
|
-
|
|
2967
|
-
|
|
2968
|
-
|
|
2969
|
-
|
|
2970
|
-
|
|
2971
|
+
function aggressiveVariableEliminationInternal(func, asmData) {
|
|
2972
|
+
// This removes as many variables as possible. This is often not the best thing because it increases
|
|
2973
|
+
// code size, but it is far preferable to the risk of split functions needing to do more spilling, so
|
|
2974
|
+
// we use it when outlining.
|
|
2975
|
+
// Specifically, this finds 'trivial' variables: ones with 1 definition, and that definition is not sensitive to any changes: it
|
|
2976
|
+
// only depends on constants and local variables that are themselves trivial. We can unquestionably eliminate
|
|
2977
|
+
// such variables in a trivial manner.
|
|
2978
|
+
|
|
2979
|
+
var assignments = {};
|
|
2980
|
+
var appearances = {};
|
|
2981
|
+
var defs = {};
|
|
2982
|
+
var considered = {};
|
|
2983
|
+
|
|
2984
|
+
traverse(func, function(node, type) {
|
|
2985
|
+
if (type == 'assign' && node[2][0] == 'name') {
|
|
2986
|
+
var name = node[2][1];
|
|
2987
|
+
if (name in asmData.vars) {
|
|
2988
|
+
assignments[name] = (assignments[name] || 0) + 1;
|
|
2989
|
+
appearances[name] = (appearances[name] || 0) - 1; // this appearance is a definition, offset the counting later
|
|
2990
|
+
defs[name] = node;
|
|
2991
|
+
} else {
|
|
2992
|
+
if (name in asmData.params) {
|
|
2993
|
+
assignments[name] = (assignments[name] || 1) + 1; // init to 1 for initial parameter assignment
|
|
2994
|
+
considered[name] = true; // this parameter is not ssa, it must be in a hand-optimized function, so it is not trivial
|
|
2971
2995
|
}
|
|
2972
2996
|
}
|
|
2973
|
-
})
|
|
2997
|
+
} else if (type == 'name') {
|
|
2998
|
+
var name = node[1];
|
|
2999
|
+
if (name in asmData.vars) {
|
|
3000
|
+
appearances[name] = (appearances[name] || 0) + 1;
|
|
3001
|
+
}
|
|
3002
|
+
}
|
|
3003
|
+
});
|
|
2974
3004
|
|
|
2975
|
-
|
|
2976
|
-
|
|
2977
|
-
|
|
2978
|
-
|
|
2979
|
-
|
|
2980
|
-
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
|
|
2987
|
-
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
|
|
2993
|
-
|
|
2994
|
-
|
|
2995
|
-
|
|
2996
|
-
|
|
2997
|
-
|
|
3005
|
+
var allTrivials = {}; // key of a trivial var => size of its (expanded) value, at least 1
|
|
3006
|
+
|
|
3007
|
+
// three levels of variables:
|
|
3008
|
+
// 1. trivial: 1 def (or less), uses nothing sensitive, can be eliminated
|
|
3009
|
+
// 2. safe: 1 def (or less), can be used in a trivial, but cannot itself be eliminated
|
|
3010
|
+
// 3. sensitive: uses a global or memory or something else that prevents trivial elimination.
|
|
3011
|
+
|
|
3012
|
+
function assessTriviality(name) {
|
|
3013
|
+
// only care about vars with 0-1 assignments of (0 for parameters), and can ignore label (which is not explicitly initialized, but cannot be eliminated ever anyhow)
|
|
3014
|
+
if (assignments[name] > 1 || (!(name in asmData.vars) && !(name in asmData.params)) || name == 'label') return false;
|
|
3015
|
+
if (considered[name]) return allTrivials[name];
|
|
3016
|
+
considered[name] = true;
|
|
3017
|
+
var sensitive = false;
|
|
3018
|
+
var size = 0, originalSize = 0;
|
|
3019
|
+
var def = defs[name];
|
|
3020
|
+
if (def) {
|
|
3021
|
+
var value = def[3];
|
|
3022
|
+
originalSize = measureSize(value);
|
|
3023
|
+
if (value) {
|
|
3024
|
+
traverse(value, function recurseValue(node, type) {
|
|
3025
|
+
var one = node[1];
|
|
3026
|
+
if (!(type in NODES_WITHOUT_ELIMINATION_SENSITIVITY)) { // || (type == 'binary' && !(one in FAST_ELIMINATION_BINARIES))) {
|
|
3027
|
+
sensitive = true;
|
|
3028
|
+
return true;
|
|
3029
|
+
}
|
|
3030
|
+
if (type == 'name' && !assessTriviality(one)) {
|
|
3031
|
+
if (assignments[one] > 1 || (!(one in asmData.vars) && !(one in asmData.params))) {
|
|
3032
|
+
sensitive = true; // directly using something sensitive
|
|
2998
3033
|
return true;
|
|
2999
|
-
}
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
} // otherwise, not trivial, but at least safe.
|
|
3005
|
-
}
|
|
3006
|
-
// if this is a name, it must be a trivial variable (or a safe one) and we know its size
|
|
3007
|
-
size += ((type == 'name') ? allTrivials[one] : 1) || 1;
|
|
3008
|
-
});
|
|
3009
|
-
}
|
|
3010
|
-
}
|
|
3011
|
-
if (!sensitive) {
|
|
3012
|
-
size = size || 1;
|
|
3013
|
-
originalSize = originalSize || 1;
|
|
3014
|
-
var factor = ((appearances[name] - 1) || 0) * (size - originalSize); // If no size change or just one appearance, always ok to trivially eliminate. otherwise, tradeoff
|
|
3015
|
-
if (factor <= 12) {
|
|
3016
|
-
allTrivials[name] = size; // trivial!
|
|
3017
|
-
return true;
|
|
3018
|
-
}
|
|
3034
|
+
} // otherwise, not trivial, but at least safe.
|
|
3035
|
+
}
|
|
3036
|
+
// if this is a name, it must be a trivial variable (or a safe one) and we know its size
|
|
3037
|
+
size += ((type == 'name') ? allTrivials[one] : 1) || 1;
|
|
3038
|
+
});
|
|
3019
3039
|
}
|
|
3020
|
-
return false;
|
|
3021
3040
|
}
|
|
3022
|
-
|
|
3023
|
-
|
|
3041
|
+
if (!sensitive) {
|
|
3042
|
+
size = size || 1;
|
|
3043
|
+
originalSize = originalSize || 1;
|
|
3044
|
+
var factor = ((appearances[name] - 1) || 0) * (size - originalSize); // If no size change or just one appearance, always ok to trivially eliminate. otherwise, tradeoff
|
|
3045
|
+
if (factor <= 12) {
|
|
3046
|
+
allTrivials[name] = size; // trivial!
|
|
3047
|
+
return true;
|
|
3048
|
+
}
|
|
3024
3049
|
}
|
|
3025
|
-
|
|
3050
|
+
return false;
|
|
3051
|
+
}
|
|
3052
|
+
for (var name in asmData.vars) {
|
|
3053
|
+
assessTriviality(name);
|
|
3054
|
+
}
|
|
3055
|
+
var trivials = {};
|
|
3026
3056
|
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
|
|
3057
|
+
for (var name in allTrivials) { // from now on, ignore parameters
|
|
3058
|
+
if (name in asmData.vars) trivials[name] = true;
|
|
3059
|
+
}
|
|
3030
3060
|
|
|
3031
|
-
|
|
3061
|
+
allTrivials = {};
|
|
3032
3062
|
|
|
3033
|
-
|
|
3063
|
+
var values = {}, recursives = {};
|
|
3034
3064
|
|
|
3035
|
-
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
} else {
|
|
3048
|
-
traverse(node, function(node, type) {
|
|
3049
|
-
if (type == 'name') {
|
|
3050
|
-
var name2 = node[1];
|
|
3051
|
-
if (name2 in trivials) {
|
|
3052
|
-
return evaluate(name2);
|
|
3053
|
-
}
|
|
3054
|
-
}
|
|
3055
|
-
});
|
|
3065
|
+
function evaluate(name) {
|
|
3066
|
+
var node = values[name];
|
|
3067
|
+
if (node) return node;
|
|
3068
|
+
values[name] = null; // prevent infinite recursion
|
|
3069
|
+
var def = defs[name];
|
|
3070
|
+
if (def) {
|
|
3071
|
+
node = def[3];
|
|
3072
|
+
if (node[0] == 'name') {
|
|
3073
|
+
var name2 = node[1];
|
|
3074
|
+
assert(name2 !== name);
|
|
3075
|
+
if (name2 in trivials) {
|
|
3076
|
+
node = evaluate(name2);
|
|
3056
3077
|
}
|
|
3057
|
-
|
|
3078
|
+
} else {
|
|
3079
|
+
traverse(node, function(node, type) {
|
|
3080
|
+
if (type == 'name') {
|
|
3081
|
+
var name2 = node[1];
|
|
3082
|
+
if (name2 === name) {
|
|
3083
|
+
recursives[name] = 1;
|
|
3084
|
+
return false;
|
|
3085
|
+
}
|
|
3086
|
+
if (name2 in trivials) {
|
|
3087
|
+
return evaluate(name2);
|
|
3088
|
+
}
|
|
3089
|
+
}
|
|
3090
|
+
});
|
|
3058
3091
|
}
|
|
3059
|
-
|
|
3092
|
+
values[name] = node;
|
|
3060
3093
|
}
|
|
3094
|
+
return node;
|
|
3095
|
+
}
|
|
3096
|
+
|
|
3097
|
+
for (var name in trivials) {
|
|
3098
|
+
evaluate(name);
|
|
3099
|
+
}
|
|
3100
|
+
for (var name in recursives) {
|
|
3101
|
+
delete trivials[name];
|
|
3102
|
+
}
|
|
3061
3103
|
|
|
3062
|
-
|
|
3063
|
-
|
|
3104
|
+
for (var name in trivials) {
|
|
3105
|
+
var def = defs[name];
|
|
3106
|
+
if (def) {
|
|
3107
|
+
def.length = 0;
|
|
3108
|
+
def[0] = 'toplevel';
|
|
3109
|
+
def[1] = [];
|
|
3064
3110
|
}
|
|
3111
|
+
delete asmData.vars[name];
|
|
3112
|
+
}
|
|
3065
3113
|
|
|
3066
|
-
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
3114
|
+
// Perform replacements TODO: save list of uses objects before, replace directly, avoid extra traverse
|
|
3115
|
+
traverse(func, function(node, type) {
|
|
3116
|
+
if (type == 'name') {
|
|
3117
|
+
var name = node[1];
|
|
3118
|
+
if (name in trivials) {
|
|
3119
|
+
var value = values[name];
|
|
3120
|
+
if (!value) throw 'missing value: ' + [func[1], name, values[name]] + ' - faulty reliance on asm zero-init?';
|
|
3121
|
+
return copy(value); // must copy, or else the same object can be used multiple times
|
|
3072
3122
|
}
|
|
3073
|
-
delete asmData.vars[name];
|
|
3074
3123
|
}
|
|
3124
|
+
});
|
|
3125
|
+
}
|
|
3075
3126
|
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
}
|
|
3085
|
-
}
|
|
3086
|
-
});
|
|
3087
|
-
}
|
|
3127
|
+
function aggressiveVariableElimination(ast) {
|
|
3128
|
+
assert(asm, 'need ASM_JS for aggressive variable elimination');
|
|
3129
|
+
traverseGeneratedFunctions(ast, function(func, type) {
|
|
3130
|
+
var asmData = normalizeAsm(func);
|
|
3131
|
+
aggressiveVariableEliminationInternal(func, asmData);
|
|
3132
|
+
denormalizeAsm(func, asmData);
|
|
3133
|
+
});
|
|
3134
|
+
}
|
|
3088
3135
|
|
|
3136
|
+
function outline(ast) {
|
|
3089
3137
|
// Try to flatten out code as much as possible, to make outlining more feasible.
|
|
3090
3138
|
function flatten(func, asmData) {
|
|
3091
3139
|
var minSize = extraInfo.sizeToOutline/4;
|
|
@@ -3740,7 +3788,7 @@ function outline(ast) {
|
|
|
3740
3788
|
var size = measureSize(func);
|
|
3741
3789
|
if (size >= extraInfo.sizeToOutline && maxTotalFunctions > 0) {
|
|
3742
3790
|
maxTotalFunctions--;
|
|
3743
|
-
|
|
3791
|
+
aggressiveVariableEliminationInternal(func, asmData);
|
|
3744
3792
|
flatten(func, asmData);
|
|
3745
3793
|
analyzeFunction(func, asmData);
|
|
3746
3794
|
calculateThreshold(func, asmData);
|
|
@@ -3921,6 +3969,7 @@ var passes = {
|
|
|
3921
3969
|
registerize: registerize,
|
|
3922
3970
|
eliminate: eliminate,
|
|
3923
3971
|
eliminateMemSafe: eliminateMemSafe,
|
|
3972
|
+
aggressiveVariableElimination: aggressiveVariableElimination,
|
|
3924
3973
|
minifyGlobals: minifyGlobals,
|
|
3925
3974
|
relocate: relocate,
|
|
3926
3975
|
outline: outline,
|