js-confuser-vm 0.0.5 → 0.0.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.
- package/CHANGELOG.md +112 -2
- package/README.MD +249 -106
- package/dist/build-runtime.js +22 -3
- package/dist/compiler.js +864 -801
- package/dist/runtime.js +414 -333
- package/dist/transforms/bytecode/aliasedOpcodes.js +134 -0
- package/dist/transforms/bytecode/concealConstants.js +31 -0
- package/dist/transforms/bytecode/macroOpcodes.js +37 -23
- package/dist/transforms/bytecode/microOpcodes.js +236 -0
- package/dist/transforms/bytecode/resolveContants.js +69 -12
- package/dist/transforms/bytecode/resolveLabels.js +5 -3
- package/dist/transforms/bytecode/selfModifying.js +3 -2
- package/dist/transforms/bytecode/specializedOpcodes.js +54 -39
- package/dist/transforms/runtime/aliasedOpcodes.js +134 -0
- package/dist/transforms/runtime/internalVariables.js +202 -0
- package/dist/transforms/runtime/macroOpcodes.js +30 -18
- package/dist/transforms/runtime/microOpcodes.js +76 -0
- package/dist/transforms/runtime/shuffleOpcodes.js +1 -1
- package/dist/transforms/runtime/specializedOpcodes.js +36 -29
- package/dist/utils/op-utils.js +36 -0
- package/dist/utils/random-utils.js +27 -0
- package/index.ts +11 -8
- package/jest.config.js +12 -0
- package/package.json +1 -1
- package/src/build-runtime.ts +25 -4
- package/src/compiler.ts +2482 -2069
- package/src/options.ts +3 -0
- package/src/runtime.ts +842 -771
- package/src/transforms/bytecode/aliasedOpcodes.ts +148 -0
- package/src/transforms/bytecode/concealConstants.ts +52 -0
- package/src/transforms/bytecode/macroOpcodes.ts +49 -33
- package/src/transforms/bytecode/microOpcodes.ts +291 -0
- package/src/transforms/bytecode/resolveContants.ts +82 -18
- package/src/transforms/bytecode/resolveLabels.ts +5 -4
- package/src/transforms/bytecode/selfModifying.ts +3 -3
- package/src/transforms/bytecode/specializedOpcodes.ts +85 -46
- package/src/transforms/runtime/aliasedOpcodes.ts +191 -0
- package/src/transforms/runtime/internalVariables.ts +270 -0
- package/src/transforms/runtime/macroOpcodes.ts +47 -20
- package/src/transforms/runtime/microOpcodes.ts +93 -0
- package/src/transforms/runtime/shuffleOpcodes.ts +1 -1
- package/src/transforms/runtime/specializedOpcodes.ts +56 -46
- package/src/types.ts +1 -1
- package/src/utils/op-utils.ts +46 -0
- package/src/transforms/utils/op-utils.ts +0 -26
- package/src/utilts.ts +0 -3
- /package/src/{transforms/utils → utils}/random-utils.ts +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,113 @@
|
|
|
1
|
+
## `0.0.7` Micro Opcodes
|
|
2
|
+
|
|
3
|
+
- Added new option `microOpcodes` which breaks opcodes into multiple sub-opcodes.
|
|
4
|
+
|
|
5
|
+
```js
|
|
6
|
+
// Input Code
|
|
7
|
+
console.log("Hello world!");
|
|
8
|
+
|
|
9
|
+
// Before
|
|
10
|
+
// [2, 1, 0, 0], LOAD_GLOBAL reg[1] = console 1:0-1:7
|
|
11
|
+
// [0, 2, 1, 0], LOAD_CONST reg[2] = "log" 1:0-1:27
|
|
12
|
+
// [8, 3, 1, 2], GET_PROP reg[3] = reg[1][reg[2]] 1:0-1:27
|
|
13
|
+
// [0, 4, 2, 0], LOAD_CONST reg[4] = "Hello world!" 1:12-1:26
|
|
14
|
+
// [43, 5, 1, 3, 1, 4], CALL_METHOD reg[5] = reg[3](recv=reg[1], 1 args) 1:0-1:27
|
|
15
|
+
|
|
16
|
+
// What the opcode "LOAD_CONST" looks like:
|
|
17
|
+
case OP.LOAD_CONST:
|
|
18
|
+
var dst = this._operand();
|
|
19
|
+
frame.regs[dst] = this._constant();
|
|
20
|
+
break;
|
|
21
|
+
|
|
22
|
+
// After
|
|
23
|
+
// [60, 1], MICRO_LOAD_GLOBAL_0 1 1:0-1:7
|
|
24
|
+
// [61, 0, 0], MICRO_LOAD_GLOBAL_1 [0, 0]
|
|
25
|
+
// [62], MICRO_LOAD_GLOBAL_2
|
|
26
|
+
// [63], MICRO_LOAD_GLOBAL_3
|
|
27
|
+
// [58, 2], MICRO_LOAD_CONST_0 2 1:0-1:27
|
|
28
|
+
// [59, 1, 0], MICRO_LOAD_CONST_1 [1, 0]
|
|
29
|
+
// [64, 3], MICRO_GET_PROP_0 3 1:0-1:27
|
|
30
|
+
// [65, 1], MICRO_GET_PROP_1 1
|
|
31
|
+
// [66, 2], MICRO_GET_PROP_2 2
|
|
32
|
+
// [67], MICRO_GET_PROP_3
|
|
33
|
+
// [58, 4], MICRO_LOAD_CONST_0 4 1:12-1:26
|
|
34
|
+
// [59, 2, 0], MICRO_LOAD_CONST_1 [2, 0]
|
|
35
|
+
// [43, 5, 1, 3, 1, 4], CALL_METHOD reg[5] = reg[3](recv=reg[1], 1 args) 1:0-1:27
|
|
36
|
+
|
|
37
|
+
// What the opcodes "MICRO_LOAD_CONST_0" (58) and "MICRO_LOAD_CONST_1" (59) looks like:
|
|
38
|
+
case 58:
|
|
39
|
+
// MICRO_LOAD_CONST_0
|
|
40
|
+
this._internals[0] = this._operand();
|
|
41
|
+
break;
|
|
42
|
+
case 59:
|
|
43
|
+
// MICRO_LOAD_CONST_1
|
|
44
|
+
frame.regs[this._internals[0]] = this._constant();
|
|
45
|
+
break;
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
- Fixed `Macro Opcodes` possibly clashing variables when merging opcode handlers.
|
|
49
|
+
|
|
50
|
+
- Added support for update expressions on member expressions (`object.prop++`, `object.prop--`)
|
|
51
|
+
|
|
52
|
+
- Added support for Template literals (ES6 feature added for convenience)
|
|
53
|
+
|
|
54
|
+
- Added programs [cash.min.js](https://github.com/fabiospampinato/cash/blob/master/dist/cash.min.js) and [sha256.js](https://gist.github.com/bryanchow/1649353) to the test suite
|
|
55
|
+
|
|
56
|
+
## `0.0.6` Register based
|
|
57
|
+
|
|
58
|
+
- Switched from stack-based to register-based VM.
|
|
59
|
+
|
|
60
|
+
- `Specialized Opcodes` now applies to any fixed-size instruction, instead of just singular operands.
|
|
61
|
+
- - Specialized Opcodes never applies to N-sized instructions, such as `MAKE_CLOSURE`, `BUILD_ARRAY`, `CALL`, etc.
|
|
62
|
+
|
|
63
|
+
- `Macro Opcodes` can now include jumping/terminating opcodes if it's the last instruction in the sequence.
|
|
64
|
+
|
|
65
|
+
- Added new option `aliasedOpcodes` which creates duplicate opcodes, including variants with shuffled operand order.
|
|
66
|
+
|
|
67
|
+
```js
|
|
68
|
+
// Input Code
|
|
69
|
+
console.log("Hello, world!");
|
|
70
|
+
|
|
71
|
+
// Before
|
|
72
|
+
// [2, 1, 0], LOAD_GLOBAL reg[1] = console 1:0-1:7
|
|
73
|
+
// [0, 2, 1], LOAD_CONST reg[2] = "log" 1:0-1:28
|
|
74
|
+
// [8, 3, 1, 2], GET_PROP [3, 1, 2] 1:0-1:28
|
|
75
|
+
// [0, 4, 2], LOAD_CONST reg[4] = "Hello, world!" 1:12-1:27
|
|
76
|
+
// [43, 5, 1, 3, 1, 4], CALL_METHOD reg[5] = method(recv=reg[1], fn=reg[3], 1 args)1:0-1:28
|
|
77
|
+
// [0, 1, 3], LOAD_CONST reg[1] = undefined
|
|
78
|
+
// [45, 1], RETURN reg[1]
|
|
79
|
+
|
|
80
|
+
// What the opcode "LOAD_GLOBAL" looks like:
|
|
81
|
+
case OP.LOAD_GLOBAL:
|
|
82
|
+
var dst = this._operand();
|
|
83
|
+
frame.regs[dst] = this.globals[this.constants[this._operand()]];
|
|
84
|
+
break;
|
|
85
|
+
|
|
86
|
+
// After
|
|
87
|
+
// [52040, 0, 1], ALIAS_LOAD_GLOBAL_1_0 [0, 1] 1:0-1:7
|
|
88
|
+
// [24862, 1, 2], ALIAS_LOAD_CONST_1_0 [1, 2] 1:0-1:28
|
|
89
|
+
// [25202, 1, 2, 3], ALIAS_GET_PROP_1_2_0 [1, 2, 3] 1:0-1:28
|
|
90
|
+
// [24862, 2, 4], ALIAS_LOAD_CONST_1_0 [2, 4] 1:12-1:27
|
|
91
|
+
// [43, 5, 1, 3, 1, 4], CALL_METHOD reg[5] = method(recv=reg[1], fn=reg[3], 1 args)1:0-1:28
|
|
92
|
+
// [24862, 3, 1], ALIAS_LOAD_CONST_1_0 [3, 1]
|
|
93
|
+
// [51807, 1], ALIAS_RETURN_0 1
|
|
94
|
+
|
|
95
|
+
// What the opcode "ALIAS_LOAD_GLOBAL_1_0" (52040) looks like:
|
|
96
|
+
case 52040:
|
|
97
|
+
// ALIAS_LOAD_GLOBAL_1_0 (order: [1,0])
|
|
98
|
+
let _unsortedOperands = [this._operand(), this._operand()];
|
|
99
|
+
let _operands = [_unsortedOperands[1], _unsortedOperands[0]];
|
|
100
|
+
var dst = _operands[0];
|
|
101
|
+
frame.regs[dst] = this.globals[this.constants[_operands[1]]];
|
|
102
|
+
break;
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
- Added new option `concealConstants` which XOR decrypts numbers and strings at runtime.
|
|
106
|
+
|
|
107
|
+
- Top level variables are now renamed and not exposed globally. To export a global function, you can use `window.MyGlobalFunction = function(){...}`
|
|
108
|
+
|
|
109
|
+
- Accessing an undeclared global variable will throw a ReferenceError
|
|
110
|
+
|
|
1
111
|
## `0.0.5` Generated Opcodes
|
|
2
112
|
|
|
3
113
|
- Added new option `specializedOpcodes` which creates specialized opcodes for commonly used opcode+operand pairs.
|
|
@@ -15,8 +125,8 @@ console.log("Hello world!");
|
|
|
15
125
|
// [14], POP 1:0-1:28
|
|
16
126
|
|
|
17
127
|
// What the opcode "LOAD_GLOBAL" looks like:
|
|
18
|
-
case OP.
|
|
19
|
-
this._push(this.constants[this._operand()]);
|
|
128
|
+
case OP.LOAD_GLOBAL:
|
|
129
|
+
this._push(this.globals[this.constants[this._operand()]]);
|
|
20
130
|
break;
|
|
21
131
|
|
|
22
132
|
// After
|
package/README.MD
CHANGED
|
@@ -37,10 +37,13 @@ JsConfuserVM.obfuscate(`
|
|
|
37
37
|
target: "browser", // or "node"
|
|
38
38
|
randomizeOpcodes: true, // randomize the opcode numbers?
|
|
39
39
|
shuffleOpcodes: true, // shuffle order of opcode handlers in the runtime?
|
|
40
|
-
encodeBytecode: true, // encode bytecode?
|
|
40
|
+
encodeBytecode: true, // encode the bytecode array?
|
|
41
|
+
concealConstants: true, // conceal strings and integers in the constant pool?
|
|
41
42
|
selfModifying: true, // do self-modifying bytecode for function bodies?
|
|
42
43
|
macroOpcodes: true, // create combined opcodes for repeated instruction sequences?
|
|
44
|
+
microOpcodes: true, // break opcodes into sub-opcodes?
|
|
43
45
|
specializedOpcodes: true, // create specialized opcodes for commonly used opcode+operand pairs?
|
|
46
|
+
aliasedOpcodes: true, // create duplicate opcodes for commonly used opcodes?
|
|
44
47
|
timingChecks: true, // add timing checks to detect debuggers?
|
|
45
48
|
minify: true // pass final output through Google Closure Compiler? (Renames VM class properties)
|
|
46
49
|
}).then(result => {
|
|
@@ -48,22 +51,35 @@ JsConfuserVM.obfuscate(`
|
|
|
48
51
|
})
|
|
49
52
|
|
|
50
53
|
/*
|
|
51
|
-
var
|
|
52
|
-
function
|
|
53
|
-
function
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
a.h
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
a.
|
|
62
|
-
a,
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
1,
|
|
54
|
+
var c=Symbol();function f(a,e){this.A=a;this.H=e;this.I=!1;this.J=void 0}function h(a){return a.I?a.J:a.A.h[a.H]}function k(a,e){a.I?a.J=e:a.A.h[a.H]=e}function m(a){this.v=a;this.D=[];this.prototype={}}function n(a,e,b){this.K=a;this.h=Array(a.v.L).fill(void 0);this.l=a.v.R;this.W=e!==void 0?e:void 0;this.G=b!==void 0?b:0;this.o=null;this.F=[]}function p(a,e,b,d){this.u=a;this.O=b;this.m=d;this.j=[];this.B=[];this.i=new n(new m({C:0,L:e,R:0}),void 0,0);this.g={}}
|
|
55
|
+
function v(a){return a.u[a.i.l++]}function w(a,e,b){for(var d=0;d<a.B.length;d++){var g=a.B[d];if(g.A===e&&g.H===b)return g}g=new f(e,b);a.B.push(g);return g}function x(a,e,b){e=e??v(a);b=b??v(a);a=a.O[e];if(!b)return a;if(typeof a==="number")return a^b;a=typeof Buffer!=="undefined"?Buffer.from(a,"base64"):Uint8Array.from(atob(a),function(g){return g.charCodeAt(0)});e="";for(var d=0;d<a.length/2;d++)e+=String.fromCharCode((a[d*2]|a[d*2+1]<<8)^b+d&65535);return e}
|
|
56
|
+
function z(a,e){a.B=a.B.filter(function(b){return b.A===e?(b.J=b.A.h[b.H],b.I=!0,!1):!0})}
|
|
57
|
+
function A(a){for(var e=performance.now();;){var b=a.i;if(b.l>=a.u.length)break;var d=b.l++;d=a.u[d];var g=performance.now(),D=g-e>1E3;e=g;if(D){for(d=0;d<a.u.length;d++)a.u[d]=0;b.h.fill(void 0);d=51142;b.l=a.u.length}try{switch(d){case 48376:a.g[16541]=v(a);a.g[36877]=b.h[v(a)];b.h[a.g[16541]]=a.g[36877]^b.h[v(a)];break;case 24807:a.g[32755]=v(a);a.g[30211]=b.h[v(a)];b.h[a.g[32755]]=a.g[30211]>>>b.h[v(a)];break;case 25812:a.g[11979]=3;b.h[a.g[11979]]=b.h[4];break;case 21199:a.g[16541]=4;b.h[a.g[16541]]=
|
|
58
|
+
x(a,0,19941);break;case 48511:a.g[38915]=b.h[5];z(a,b);if(a.j.length===0)return a.g[38915];b.o===null||typeof a.g[38915]==="object"&&a.g[38915]!==null||(a.g[38915]=b.o);a.g[25255]=a.j.pop();a.g[25255].h[b.G]=a.g[38915];a.i=a.g[25255];break;case 26119:a.g[16541]=v(a);a.g[3839]=b.h[v(a)];b.h[a.g[16541]]=a.g[3839]>b.h[v(a)];break;case 7802:a.g[16541]=v(a);a.g[62634]=b.h[v(a)];b.h[a.g[16541]]=a.g[62634]!==b.h[v(a)];break;case 29164:a.g[16541]=3;b.h[a.g[16541]]=x(a,0,19941);break;case 45474:a.g[19089]=
|
|
59
|
+
v(a);a.g[25428]=b.h[v(a)];a.g[7422]=b.h[v(a)];a.g[40522]=v(a);a.g[28705]=Array(a.g[40522]);for(a.g[12462]=0;a.g[12462]<a.g[40522];a.g[12462]++)a.g[28705][a.g[12462]]=b.h[v(a)];if(a.g[7422]&&a.g[7422][c]){a.g[7358]=a.g[7422][c];a.g[58907]=new n(a.g[7358],a.g[25428],a.g[19089]);for(a.g[12462]=0;a.g[12462]<a.g[28705].length;a.g[12462]++)a.g[58907].h[a.g[12462]]=a.g[28705][a.g[12462]];a.g[58907].h[a.g[7358].v.C]=a.g[28705];a.j.push(a.i);a.i=a.g[58907]}else b.h[a.g[19089]]=a.g[7422].apply(a.g[25428],a.g[28705]);
|
|
60
|
+
break;case 47786:a.g[3766]=v(a);a.g[62634]=b.h[v(a)];b.h[a.g[3766]]=a.g[62634]!=b.h[v(a)];break;case 45528:a.g[16541]=2;b.h[a.g[16541]]=b.h[5];break;case 37324:a.g[38915]=b.h[v(a)];z(a,b);if(a.j.length===0)return a.g[38915];b.o===null||typeof a.g[38915]==="object"&&a.g[38915]!==null||(a.g[38915]=b.o);a.g[23776]=a.j.pop();a.g[23776].h[b.G]=a.g[38915];a.i=a.g[23776];break;case 37593:a.g[21276]=0;b.h[a.g[21276]]=b.h[7];break;case 16492:a.g[16541]=v(a);a.g[62634]=b.h[v(a)];b.h[a.g[16541]]=a.g[62634]<=
|
|
61
|
+
b.h[v(a)];break;case 1900:b.l=13;break;case 42013:a.m[x(a)]=b.h[v(a)];break;case 63795:a.g[28560]=v(a);b.h[a.g[28560]]=v(a);break;case 54788:a.g[2920]=b.h[v(a)];a.g[37378]=b.h[v(a)];a.g[35839]=b.h[v(a)];a.g[27080]=Object.getOwnPropertyDescriptor(a.g[2920],a.g[37378]);a.g[39506]={set:a.g[35839],configurable:!0,enumerable:!0};a.g[27080]&&typeof a.g[27080].get==="function"&&(a.g[39506].get=a.g[27080].get);Object.defineProperty(a.g[2920],a.g[37378],a.g[39506]);break;case 12182:a.g[29248]=v(a);a.g[52124]=
|
|
62
|
+
b.h[v(a)];a.g[47986]=b.h[v(a)];b.h[a.g[29248]]=delete a.g[52124][a.g[47986]];break;case 3376:a.g[16541]=5;a.g[62634]=b.h[2];b.h[a.g[16541]]=a.g[62634]+b.h[3];break;case 4123:a.g[63658]=5;a.g[40080]=b.h[3];a.g[37378]=b.h[4];b.h[a.g[63658]]=a.g[40080][a.g[37378]];break;case 27100:a.g[16541]=v(a);b.h[a.g[16541]]=-b.h[v(a)];break;case 35987:a.g[16541]=3;b.h[a.g[16541]]=b.h[6];break;case 59134:a.g[11440]=5;b.h[a.g[11440]]=x(a,4,0);break;case 47879:a.g[59573]=v(a);v(a);b.h[a.g[59573]]=void 0;break;case 59967:a.g[16541]=
|
|
63
|
+
7;a.g[54385]=b.h[0];b.h[a.g[16541]]=a.g[54385]-b.h[6];break;case 37122:a.g[16541]=v(a);a.g[62634]=b.h[v(a)];b.h[a.g[16541]]=a.g[62634]>=b.h[v(a)];break;case 18522:a.g[1489]=v(a);a.g[38065]=b.h[v(a)];b.h[a.g[1489]]=a.g[38065]===b.h[v(a)];break;case 60376:a.g[19925]=b.h[3];z(a,b);if(a.j.length===0)return a.g[19925];b.o===null||typeof a.g[19925]==="object"&&a.g[19925]!==null||(a.g[19925]=b.o);a.g[53519]=a.j.pop();a.g[53519].h[b.G]=a.g[19925];a.i=a.g[53519];break;case 28102:a.g[16541]=v(a);a.g[10179]=
|
|
64
|
+
v(a);a.g[38805]=Array(a.g[10179]);for(a.g[37753]=0;a.g[37753]<a.g[10179];a.g[37753]++)a.g[38805][a.g[37753]]=b.h[v(a)];b.h[a.g[16541]]=a.g[38805];break;case 55907:a.g[249]=v(a);a.g[13793]=v(a);a.g[7488]=v(a);a.g[33443]=v(a);a.g[59975]=v(a);a.g[44466]=Array(a.g[59975]);for(a.g[33125]=0;a.g[33125]<a.g[59975];a.g[33125]++)a.g[5413]=v(a),a.g[61217]=v(a),a.g[44466][a.g[33125]]={V:a.g[5413],M:a.g[61217]};a.g[29776]={C:a.g[7488],L:a.g[33443],R:a.g[13793],X:a.g[44466]};a.g[32226]=new m(a.g[29776]);for(a.g[33125]=
|
|
65
|
+
0;a.g[33125]<a.g[44466].length;a.g[33125]++)a.g[49053]=a.g[44466][a.g[33125]],a.g[49053].V?a.g[32226].D.push(w(a,b,a.g[49053].M)):a.g[32226].D.push(b.K.D[a.g[49053].M]);var q=a;a.g[31999]=function(l){return function(){for(var t=Array.prototype.slice.call(arguments),y=new p(q.u,l.v.L,q.O,q.m),u=new n(l,this==null?q.m:this,0),r=0;r<t.length;r++)u.h[r]=t[r];u.h[l.v.C]=t;y.i=u;return A(y)}}(a.g[32226]);a.g[31999][c]=a.g[32226];a.g[31999].prototype=a.g[32226].prototype;b.h[a.g[249]]=a.g[31999];break;case 138:a.g[16541]=
|
|
66
|
+
5;b.h[a.g[16541]]=x(a,5,58082);break;case 48909:a.g[16541]=v(a);a.g[41461]=b.h[v(a)];b.h[a.g[16541]]=a.g[41461]%b.h[v(a)];break;case 13149:a.g[14138]=v(a);a.g[52124]=b.h[v(a)];a.g[37378]=b.h[v(a)];b.h[a.g[14138]]=a.g[52124][a.g[37378]];break;case 63724:a.g[55552]=4;a.g[21339]=44;b.h[a.g[55552]]||(b.l=a.g[21339]);break;case 25433:a.g[16541]=4;b.h[a.g[16541]]=b.h[5];break;case 5005:a.g[52124]=b.h[v(a)];a.g[37378]=b.h[v(a)];a.g[3547]=b.h[v(a)];Reflect.set(a.g[52124],a.g[37378],a.g[3547]);break;case 44357:b.F.push({U:v(a),
|
|
67
|
+
S:v(a),T:a.j.length});break;case 52184:a.g[16541]=v(a);b.h[a.g[16541]]=~b.h[v(a)];break;case 17926:b.F.pop();break;case 17061:a.g[16541]=v(a);b.h[a.g[16541]]=+b.h[v(a)];break;case 739:a.g[22118]=v(a);a.g[36985]=b.h[v(a)];a.g[41836]=v(a);a.g[59944]=Array(a.g[41836]);for(a.g[33125]=0;a.g[33125]<a.g[41836];a.g[33125]++)a.g[59944][a.g[33125]]=b.h[v(a)];if(a.g[36985]&&a.g[36985][c]){a.g[6850]=a.g[36985][c];a.g[30557]=Object.create(a.g[6850].prototype||null);a.g[58907]=new n(a.g[6850],a.g[30557],a.g[22118]);
|
|
68
|
+
a.g[58907].o=a.g[30557];for(a.g[33125]=0;a.g[33125]<a.g[59944].length;a.g[33125]++)a.g[58907].h[a.g[33125]]=a.g[59944][a.g[33125]];a.g[58907].h[a.g[6850].v.C]=a.g[59944];a.j.push(a.i);a.i=a.g[58907]}else b.h[a.g[22118]]=Reflect.construct(a.g[36985],a.g[59944]);break;case 16825:a.g[16541]=v(a);a.g[3993]=b.h[v(a)];b.h[a.g[16541]]=a.g[3993]in b.h[v(a)];break;case 62846:a.g[16541]=6;b.h[a.g[16541]]=x(a,0,19941);break;case 41878:a.g[16541]=v(a);a.g[35268]=b.h[v(a)];b.h[a.g[16541]]=a.g[35268]==b.h[v(a)];
|
|
69
|
+
break;case 46432:a.g[29035]=4;a.g[62634]=b.h[2];b.h[a.g[29035]]=a.g[62634]<=b.h[3];break;case 51142:b.l=v(a);break;case 29761:a.g[44199]=v(a);a.g[7487]=b.h[v(a)];b.h[a.g[44199]]=a.g[7487]>>b.h[v(a)];break;case 47732:a.g[16541]=v(a);b.h[a.g[16541]]=b.W;break;case 21541:a.g[16076]=9;a.g[21339]=75;b.h[a.g[16076]]||(b.l=a.g[21339]);break;case 14784:a.g[16541]=3;b.h[a.g[16541]]=x(a,1,30115);break;case 51607:a.g[16541]=v(a);a.g[65339]=b.h[v(a)];a.g[47106]=b.h[v(a)];if(typeof a.g[47106]==="function")b.h[a.g[16541]]=
|
|
70
|
+
a.g[65339]instanceof a.g[47106];else{a.g[5038]=a.g[47106].prototype;a.g[21339]=Object.getPrototypeOf(a.g[65339]);for(a.g[25853]=!1;a.g[21339]!==null;){if(a.g[21339]===a.g[5038]){a.g[25853]=!0;break}a.g[21339]=Object.getPrototypeOf(a.g[21339])}b.h[a.g[16541]]=a.g[25853]}break;case 55835:a.g[16541]=v(a);b.h[a.g[16541]]=h(b.K.D[v(a)]);break;case 29844:a.g[42713]=v(a);a.g[1817]=x(a);if(!(a.g[1817]in a.m))throw new ReferenceError(`${a.g[1817]} is not defined`);b.h[a.g[42713]]=a.m[a.g[1817]];break;case 24699:a.g[16541]=
|
|
71
|
+
5;a.g[62634]=b.h[2];b.h[a.g[16541]]=a.g[62634]+b.h[4];break;case 44361:a.g[16541]=v(a);a.g[52124]=b.h[v(a)];a.g[15140]=[];if(a.g[52124]!==null&&a.g[52124]!==void 0)for(a.g[23643]=Object.create(null),a.g[61494]=Object(a.g[52124]);a.g[61494]!==null;){a.g[46538]=Object.getOwnPropertyNames(a.g[61494]);for(a.g[33125]=0;a.g[33125]<a.g[46538].length;a.g[33125]++)a.g[7176]=a.g[46538][a.g[33125]],a.g[7176]in a.g[23643]||(a.g[23643][a.g[7176]]=!0,a.g[34638]=Object.getOwnPropertyDescriptor(a.g[61494],a.g[7176]),
|
|
72
|
+
a.g[34638]&&a.g[34638].enumerable&&a.g[15140].push(a.g[7176]));a.g[61494]=Object.getPrototypeOf(a.g[61494])}b.h[a.g[16541]]={N:a.g[15140],P:0};break;case 49820:a.g[16541]=v(a);b.h[a.g[16541]]=x(a);break;case 51817:a.g[38915]=b.h[4];z(a,b);if(a.j.length===0)return a.g[38915];b.o===null||typeof a.g[38915]==="object"&&a.g[38915]!==null||(a.g[38915]=b.o);a.g[23776]=a.j.pop();a.g[23776].h[b.G]=a.g[38915];a.i=a.g[23776];break;case 64967:a.g[52124]=b.h[v(a)];a.g[37378]=b.h[v(a)];a.g[11470]=b.h[v(a)];a.g[12672]=
|
|
73
|
+
Object.getOwnPropertyDescriptor(a.g[52124],a.g[37378]);a.g[60061]={get:a.g[11470],configurable:!0,enumerable:!0};a.g[12672]&&typeof a.g[12672].set==="function"&&(a.g[60061].set=a.g[12672].set);Object.defineProperty(a.g[52124],a.g[37378],a.g[60061]);break;case 45309:a.g[7138]=v(a);a.g[18365]=v(a);a.g[49429]=v(a);for(a.g[9236]=a.g[18365];a.g[9236]<a.g[49429];a.g[9236]++)a.u[a.g[7138]+(a.g[9236]-a.g[18365])]=a.u[a.g[9236]];break;case 49746:a.g[12540]=v(a);k(b.K.D[a.g[12540]],b.h[v(a)]);break;case 7780:a.g[16541]=
|
|
74
|
+
3;a.g[1817]=x(a,2,31810);if(!(a.g[1817]in a.m))throw new ReferenceError(`${a.g[1817]} is not defined`);b.h[a.g[16541]]=a.m[a.g[1817]];break;case 20641:a.g[16541]=v(a);a.g[7422]=b.h[v(a)];a.g[11407]=v(a);a.g[59944]=Array(a.g[11407]);for(a.g[33125]=0;a.g[33125]<a.g[11407];a.g[33125]++)a.g[59944][a.g[33125]]=b.h[v(a)];if(a.g[7422]&&a.g[7422][c]){a.g[7358]=a.g[7422][c];a.g[58907]=new n(a.g[7358],a.m,a.g[16541]);for(a.g[33125]=0;a.g[33125]<a.g[59944].length;a.g[33125]++)a.g[58907].h[a.g[33125]]=a.g[59944][a.g[33125]];
|
|
75
|
+
a.g[58907].h[a.g[7358].v.C]=a.g[59944];a.j.push(a.i);a.i=a.g[58907]}else b.h[a.g[16541]]=a.g[7422].apply(null,a.g[59944]);break;case 5381:a.g[16541]=v(a);a.g[14415]=b.h[v(a)];b.h[a.g[16541]]=a.g[14415]-b.h[v(a)];break;case 60964:a.g[1E3]=9;a.g[62634]=b.h[5];b.h[a.g[1E3]]=a.g[62634]>b.h[8];break;case 19072:a.g[12158]=v(a);a.g[21339]=v(a);b.h[a.g[12158]]&&(b.l=a.g[21339]);break;case 51960:a.g[16541]=3;b.h[a.g[16541]]=b.h[2];break;case 30357:a.g[16541]=v(a);a.g[63497]=b.h[v(a)];a.g[57844]=v(a);a.g[63497].P>=
|
|
76
|
+
a.g[63497].N.length?b.l=a.g[57844]:b.h[a.g[16541]]=a.g[63497].N[a.g[63497].P++];break;case 20745:a.g[16541]=v(a);a.g[62634]=b.h[v(a)];b.h[a.g[16541]]=a.g[62634]/b.h[v(a)];break;case 11726:a.g[9620]=v(a);a.g[62634]=b.h[v(a)];b.h[a.g[9620]]=a.g[62634]&b.h[v(a)];break;case 48568:a.g[5190]=3;b.h[a.g[5190]]=x(a,4,0);break;case 3645:a.g[22553]=v(a);a.g[807]=x(a);a.g[645]=Object.prototype.hasOwnProperty.call(a.m,a.g[807])?a.m[a.g[807]]:void 0;b.h[a.g[22553]]=typeof a.g[645];break;case 46061:a.g[34726]=v(a);
|
|
77
|
+
a.g[59851]=v(a);a.g[62133]={};for(a.g[33125]=0;a.g[33125]<a.g[59851];a.g[33125]++)a.g[37378]=b.h[v(a)],a.g[3547]=b.h[v(a)],a.g[62133][a.g[37378]]=a.g[3547];b.h[a.g[34726]]=a.g[62133];break;case 20491:debugger;break;case 24674:a.g[51590]=1;b.h[a.g[51590]]=b.h[3];break;case 60658:a.g[16541]=v(a);a.g[62634]=b.h[v(a)];b.h[a.g[16541]]=a.g[62634]<<b.h[v(a)];break;case 8845:a.g[16541]=2;b.h[a.g[16541]]=b.h[3];break;default:throw Error("Unknown opcode: "+d+" at pc "+(b.l-1));case 59199:a.g[16541]=v(a);a.g[62634]=
|
|
78
|
+
b.h[v(a)];b.h[a.g[16541]]=a.g[62634]+b.h[v(a)];break;case 5385:a.g[39284]=4;b.h[a.g[39284]]=x(a,3,32194);break;case 20918:a.g[16541]=v(a);a.g[16160]=b.h[v(a)];b.h[a.g[16541]]=a.g[16160]|b.h[v(a)];break;case 25652:a.g[16541]=8;b.h[a.g[16541]]=x(a,0,19941);break;case 51993:a.g[14091]=v(a);a.g[20393]=b.h[v(a)];b.h[a.g[14091]]=a.g[20393]*b.h[v(a)];break;case 29458:a.g[27021]=4;b.h[a.g[27021]]=b.h[0];break;case 38570:throw b.h[v(a)];case 21903:a.g[16541]=v(a);a.g[46842]=b.h[v(a)];b.h[a.g[16541]]=a.g[46842]<
|
|
79
|
+
b.h[v(a)];break;case 17068:a.g[16541]=5;b.h[a.g[16541]]=b.h[0];break;case 26163:a.g[55552]=v(a);a.g[16422]=v(a);b.h[a.g[55552]]||(b.l=a.g[16422]);break;case 28425:a.g[16541]=v(a);b.h[a.g[16541]]=typeof b.h[v(a)];break;case 63202:a.g[60330]=v(a);b.h[a.g[60330]]=b.h[v(a)];break;case 31805:a.g[53668]=v(a);b.h[a.g[53668]]=!b.h[v(a)];break;case 57225:b.l=59}}catch(l){b=null;for(d=a.i;;){if(d.F.length>0){b=d;break}z(a,d);if(a.j.length===0)break;d=a.j.pop();a.i=d}if(!b)throw l;d=b.F.pop();a.j.length=d.T;
|
|
80
|
+
b.h[d.S]=l;b.l=d.U;a.i=b}}}var B={},C;for(C of Object.getOwnPropertyNames(globalThis))B[C]=globalThis[C];if(typeof window!=="undefined"){B.window=window;for(C of Object.getOwnPropertyNames(window))B[C]=window[C]}B.undefined=void 0;B.Infinity=Infinity;B.NaN=NaN;
|
|
81
|
+
A(new p(function(a){a=typeof Buffer!=="undefined"?Buffer.from(a,"base64"):Uint8Array.from(atob(a),function(d){return d.charCodeAt(0)});for(var e=new Uint16Array(a.length/2),b=0;b<e.length;b++)e[b]=a[b*2]|a[b*2+1]<<8;return e}("/bAEAFIAWwCNE5aj8uz9sA2/zi2qlqqWY9r9sBEAWwBtAKFQ52DnYD0OPQ5FrTNmCVGPVRnLbEC2UZV2+Lz4vMyRB7sJb/2wJwBtAHIAtlE/58Zt/bDMkf2wMAByAHQAzJF6Hv2wNgB0AHkA3GnOLT18B2Y/5/2wPwB5AIUAB7v4vKKxBNYNv6KxPXxFrQTWY9o9fO2z/bBPAIUAiABJrVLCPXxj2gMAMgABAAoAAABiYOxxjSLAOWC17PhkHgkVGxChUAYAAQABAAIAorEHAAMABQACAAIABgD4ys9Se2DYsWwHuL3Y64oA2LF+9ZOMEnOsQn71P+rZkjRkJO4lVDANWWONItRkid9pyv7mf70="),0,
|
|
82
|
+
[19940,30138,"IXwsfCp8NnwpfCt8LXw=","rn2sfaN9",void 0,58082],B));
|
|
67
83
|
*/
|
|
68
84
|
```
|
|
69
85
|
|
|
@@ -98,6 +114,7 @@ T(new u(function(a){a=typeof Buffer!=="undefined"?Buffer.from(a,"base64"):Uint8A
|
|
|
98
114
|
- [x] try..catch
|
|
99
115
|
- [x] getter/setters
|
|
100
116
|
- [x] debugger;
|
|
117
|
+
- [x] template literals (**ES6**)
|
|
101
118
|
|
|
102
119
|
### Missing
|
|
103
120
|
|
|
@@ -114,7 +131,9 @@ T(new u(function(a){a=typeof Buffer!=="undefined"?Buffer.from(a,"base64"):Uint8A
|
|
|
114
131
|
- [ ] dead handlers
|
|
115
132
|
- [ ] dead bytecode insertion
|
|
116
133
|
- [x] macro opcodes (Combine multiple opcodes into a "macro opcode")
|
|
134
|
+
- [x] micro opcodes (Break opcodes into sub-opcodes)
|
|
117
135
|
- [x] specialized opcodes (Create specific opcodes for opcode+operand pairs)
|
|
136
|
+
- [x] aliased opcodes (Create duplicate opcodes, including variants with shuffled operand order)
|
|
118
137
|
- [x] encoded bytecode array
|
|
119
138
|
- [x] self-modifying bytecode
|
|
120
139
|
- [x] timing checks
|
|
@@ -142,10 +161,22 @@ Encodes the bytecode array.
|
|
|
142
161
|
|
|
143
162
|
```js
|
|
144
163
|
// Before
|
|
145
|
-
var BYTECODE = [
|
|
164
|
+
var BYTECODE = [2, 1, 0, 0, 2, 1, 8, 3, 1, 2, 0, 4, 2, 43, 5, 1, 3, 1, 4, 0, 1, 3, 45, 1];
|
|
146
165
|
|
|
147
166
|
// After
|
|
148
|
-
var BYTECODE = "
|
|
167
|
+
var BYTECODE = "AgABAAAAAAACAAEACAADAAEAAgAAAAQAAgArAAUAAQADAAEABAAAAAEAAwAtAAEA";
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
#### `concealConstants` (true/false)
|
|
171
|
+
|
|
172
|
+
Conceals strings and integers in the constant pool.
|
|
173
|
+
|
|
174
|
+
```js
|
|
175
|
+
// Before
|
|
176
|
+
var CONSTANTS = [/* 0 */"console", /* 1 */"log", /* 2 */"Hello world!", /* 3 */undefined];
|
|
177
|
+
|
|
178
|
+
// After
|
|
179
|
+
var CONSTANTS = [/* 0 */"DaQApB6kAqQdpB+kEaQ=", /* 1 */"TCFOIUUh", /* 2 */"kKK8orait6Kzov2iqaKwopKijaKGosKi", /* 3 */undefined];
|
|
149
180
|
```
|
|
150
181
|
|
|
151
182
|
#### `macroOpcodes` (true/false)
|
|
@@ -158,44 +189,108 @@ console.log("Hello world!");
|
|
|
158
189
|
console.log("Hello world!");
|
|
159
190
|
|
|
160
191
|
// Before
|
|
161
|
-
// [
|
|
162
|
-
// [0, 1],
|
|
163
|
-
// [
|
|
164
|
-
// [0, 2],
|
|
165
|
-
// [
|
|
166
|
-
// [
|
|
167
|
-
// [
|
|
168
|
-
// [
|
|
169
|
-
// [
|
|
170
|
-
// [
|
|
171
|
-
|
|
172
|
-
//
|
|
192
|
+
// [2, 1, 0], LOAD_GLOBAL reg[1] = console 1:0-1:7
|
|
193
|
+
// [0, 2, 1], LOAD_CONST reg[2] = "log" 1:0-1:27
|
|
194
|
+
// [8, 3, 1, 2], GET_PROP [3, 1, 2] 1:0-1:27
|
|
195
|
+
// [0, 4, 2], LOAD_CONST reg[4] = "Hello world!" 1:12-1:26
|
|
196
|
+
// [43, 5, 1, 3, 1, 4], CALL_METHOD reg[5] = method(recv=reg[1], fn=reg[3], 1 args)1:0-1:27
|
|
197
|
+
// [2, 1, 0], LOAD_GLOBAL reg[1] = console 2:0-2:7
|
|
198
|
+
// [0, 2, 1], LOAD_CONST reg[2] = "log" 2:0-2:27
|
|
199
|
+
// [8, 3, 1, 2], GET_PROP [3, 1, 2] 2:0-2:27
|
|
200
|
+
// [0, 4, 2], LOAD_CONST reg[4] = "Hello world!" 2:12-2:26
|
|
201
|
+
// [43, 5, 1, 3, 1, 4], CALL_METHOD reg[5] = method(recv=reg[1], fn=reg[3], 1 args)2:0-2:27
|
|
202
|
+
|
|
203
|
+
// After
|
|
204
|
+
// [5074, 1, 0, 2, 1, 3, 1, 2, 4, 2, 5, 1, 3, 1, 4], LOAD_GLOBAL,LOAD_CONST,GET_PROP,LOAD_CONST,CALL_METHOD [1, 0, 2, 1, 3, 1, 2, 4, 2, 5, 1, 3, 1, 4]2:0-2:7
|
|
205
|
+
// [5074, 1, 0, 2, 1, 3, 1, 2, 4, 2, 5, 1, 3, 1, 4], LOAD_GLOBAL,LOAD_CONST,GET_PROP,LOAD_CONST,CALL_METHOD [1, 0, 2, 1, 3, 1, 2, 4, 2, 5, 1, 3, 1, 4]3:0-3:7
|
|
206
|
+
|
|
207
|
+
// What the opcode "LOAD_GLOBAL,LOAD_CONST,GET_PROP,LOAD_CONST,CALL_METHOD" (5074) looks like:
|
|
208
|
+
case 5074:
|
|
209
|
+
// LOAD_GLOBAL
|
|
210
|
+
var dst = this._operand();
|
|
211
|
+
var globalName = this._constant();
|
|
212
|
+
if (!(globalName in this.globals)) {
|
|
213
|
+
throw new ReferenceError(`${globalName} is not defined`);
|
|
214
|
+
}
|
|
215
|
+
frame.regs[dst] = this.globals[globalName];
|
|
216
|
+
// LOAD_CONST
|
|
217
|
+
var dst_1 = this._operand();
|
|
218
|
+
frame.regs[dst_1] = this._constant();
|
|
219
|
+
// GET_PROP
|
|
220
|
+
// dst = regs[obj][regs[key]]
|
|
221
|
+
var dst_2 = this._operand();
|
|
222
|
+
var obj = frame.regs[this._operand()];
|
|
223
|
+
var key = frame.regs[this._operand()];
|
|
224
|
+
frame.regs[dst_2] = obj[key];
|
|
225
|
+
// LOAD_CONST
|
|
226
|
+
var dst_3 = this._operand();
|
|
227
|
+
frame.regs[dst_3] = this._constant();
|
|
228
|
+
// CALL_METHOD
|
|
229
|
+
// dst, receiverReg, calleeReg, argc, [argReg...]
|
|
230
|
+
var dst_4 = this._operand();
|
|
231
|
+
var receiver = frame.regs[this._operand()];
|
|
232
|
+
var callee = frame.regs[this._operand()];
|
|
233
|
+
var argc = this._operand();
|
|
234
|
+
var args = new Array(argc);
|
|
235
|
+
for (var i = 0; i < argc; i++) args[i] = frame.regs[this._operand()];
|
|
236
|
+
if (callee && callee[CLOSURE_SYM]) {
|
|
237
|
+
var c = callee[CLOSURE_SYM];
|
|
238
|
+
var f = new Frame(c, frame._pc, frame, receiver, dst_4);
|
|
239
|
+
for (var i = 0; i < args.length; i++) f.regs[i] = args[i];
|
|
240
|
+
f.regs[c.fn.paramCount] = args;
|
|
241
|
+
this._frameStack.push(this._currentFrame);
|
|
242
|
+
this._currentFrame = f;
|
|
243
|
+
} else {
|
|
244
|
+
frame.regs[dst_4] = callee.apply(receiver, args);
|
|
245
|
+
}
|
|
246
|
+
break;
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
#### `microOpcodes` (true/false)
|
|
250
|
+
|
|
251
|
+
Breaks opcodes into mulitple sub-opcodes.
|
|
252
|
+
|
|
253
|
+
```js
|
|
254
|
+
// Input Code
|
|
255
|
+
console.log("Hello world!");
|
|
256
|
+
|
|
257
|
+
// Before
|
|
258
|
+
// [2, 1, 0, 0], LOAD_GLOBAL reg[1] = console 1:0-1:7
|
|
259
|
+
// [0, 2, 1, 0], LOAD_CONST reg[2] = "log" 1:0-1:27
|
|
260
|
+
// [8, 3, 1, 2], GET_PROP reg[3] = reg[1][reg[2]] 1:0-1:27
|
|
261
|
+
// [0, 4, 2, 0], LOAD_CONST reg[4] = "Hello world!" 1:12-1:26
|
|
262
|
+
// [43, 5, 1, 3, 1, 4], CALL_METHOD reg[5] = reg[3](recv=reg[1], 1 args) 1:0-1:27
|
|
263
|
+
|
|
264
|
+
// What the opcode "LOAD_CONST" looks like:
|
|
265
|
+
case OP.LOAD_CONST:
|
|
266
|
+
var dst = this._operand();
|
|
267
|
+
frame.regs[dst] = this._constant();
|
|
268
|
+
break;
|
|
173
269
|
|
|
174
270
|
// After
|
|
175
|
-
// [
|
|
176
|
-
// [
|
|
177
|
-
// [
|
|
178
|
-
// [
|
|
179
|
-
// [
|
|
180
|
-
// [
|
|
181
|
-
|
|
182
|
-
//
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
//
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
//
|
|
196
|
-
|
|
271
|
+
// [60, 1], MICRO_LOAD_GLOBAL_0 1 1:0-1:7
|
|
272
|
+
// [61, 0, 0], MICRO_LOAD_GLOBAL_1 [0, 0]
|
|
273
|
+
// [62], MICRO_LOAD_GLOBAL_2
|
|
274
|
+
// [63], MICRO_LOAD_GLOBAL_3
|
|
275
|
+
// [58, 2], MICRO_LOAD_CONST_0 2 1:0-1:27
|
|
276
|
+
// [59, 1, 0], MICRO_LOAD_CONST_1 [1, 0]
|
|
277
|
+
// [64, 3], MICRO_GET_PROP_0 3 1:0-1:27
|
|
278
|
+
// [65, 1], MICRO_GET_PROP_1 1
|
|
279
|
+
// [66, 2], MICRO_GET_PROP_2 2
|
|
280
|
+
// [67], MICRO_GET_PROP_3
|
|
281
|
+
// [58, 4], MICRO_LOAD_CONST_0 4 1:12-1:26
|
|
282
|
+
// [59, 2, 0], MICRO_LOAD_CONST_1 [2, 0]
|
|
283
|
+
// [43, 5, 1, 3, 1, 4], CALL_METHOD reg[5] = reg[3](recv=reg[1], 1 args) 1:0-1:27
|
|
284
|
+
|
|
285
|
+
// What the opcodes "MICRO_LOAD_CONST_0" (58) and "MICRO_LOAD_CONST_1" (59) looks like:
|
|
286
|
+
case 58:
|
|
287
|
+
// MICRO_LOAD_CONST_0
|
|
288
|
+
this._internals[0] = this._operand();
|
|
289
|
+
break;
|
|
290
|
+
case 59:
|
|
291
|
+
// MICRO_LOAD_CONST_1
|
|
292
|
+
frame.regs[this._internals[0]] = this._constant();
|
|
197
293
|
break;
|
|
198
|
-
}
|
|
199
294
|
```
|
|
200
295
|
|
|
201
296
|
#### `specializedOpcodes` (true/false)
|
|
@@ -207,30 +302,72 @@ Creates specialized opcodes for commonly used opcode+operand pairs.
|
|
|
207
302
|
console.log("Hello world!");
|
|
208
303
|
|
|
209
304
|
// Before
|
|
210
|
-
// [
|
|
211
|
-
// [0, 1],
|
|
212
|
-
// [
|
|
213
|
-
// [0, 2],
|
|
214
|
-
// [
|
|
215
|
-
// [14], POP 1:0-1:28
|
|
305
|
+
// [2, 1, 0], LOAD_GLOBAL reg[1] = console 1:0-1:7
|
|
306
|
+
// [0, 2, 1], LOAD_CONST reg[2] = "log" 1:0-1:27
|
|
307
|
+
// [8, 3, 1, 2], GET_PROP [3, 1, 2] 1:0-1:27
|
|
308
|
+
// [0, 4, 2], LOAD_CONST reg[4] = "Hello world!" 1:12-1:26
|
|
309
|
+
// [43, 5, 1, 3, 1, 4], CALL_METHOD reg[5] = method(recv=reg[1], fn=reg[3], 1 args)1:0-1:27
|
|
216
310
|
|
|
217
311
|
// What the opcode "LOAD_GLOBAL" looks like:
|
|
218
312
|
case OP.LOAD_CONST:
|
|
219
|
-
|
|
313
|
+
var dst = this._operand();
|
|
314
|
+
frame.regs[dst] = this.constants[this._operand()];
|
|
315
|
+
break;
|
|
316
|
+
|
|
317
|
+
// After
|
|
318
|
+
// [16316], LOAD_GLOBAL_1_0 1:0-1:7
|
|
319
|
+
// [43765], LOAD_CONST_2_1 1:0-1:27
|
|
320
|
+
// [58568], GET_PROP_3_1_2 1:0-1:27
|
|
321
|
+
// [35110], LOAD_CONST_4_2 1:12-1:26
|
|
322
|
+
// [43, 5, 1, 3, 1, 4], CALL_METHOD reg[5] = method(recv=reg[1], fn=reg[3], 1 args)1:0-1:27
|
|
323
|
+
|
|
324
|
+
// What the opcode "LOAD_GLOBAL_1_0" (16316) looks like:
|
|
325
|
+
case 16316:
|
|
326
|
+
// LOAD_GLOBAL_1_0 (specialized)
|
|
327
|
+
var dst = 1;
|
|
328
|
+
frame.regs[dst] = this.globals[this.constants[0]];
|
|
329
|
+
break;
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
#### `aliasedOpcodes` (true/false)
|
|
333
|
+
|
|
334
|
+
Creates duplicate opcodes, including variants with shuffled operand order.
|
|
335
|
+
|
|
336
|
+
```js
|
|
337
|
+
// Input Code
|
|
338
|
+
console.log("Hello, world!");
|
|
339
|
+
|
|
340
|
+
// Before
|
|
341
|
+
// [2, 1, 0], LOAD_GLOBAL reg[1] = console 1:0-1:7
|
|
342
|
+
// [0, 2, 1], LOAD_CONST reg[2] = "log" 1:0-1:28
|
|
343
|
+
// [8, 3, 1, 2], GET_PROP [3, 1, 2] 1:0-1:28
|
|
344
|
+
// [0, 4, 2], LOAD_CONST reg[4] = "Hello, world!" 1:12-1:27
|
|
345
|
+
// [43, 5, 1, 3, 1, 4], CALL_METHOD reg[5] = method(recv=reg[1], fn=reg[3], 1 args)1:0-1:28
|
|
346
|
+
// [0, 1, 3], LOAD_CONST reg[1] = undefined
|
|
347
|
+
// [45, 1], RETURN reg[1]
|
|
348
|
+
|
|
349
|
+
// What the opcode "LOAD_GLOBAL" looks like:
|
|
350
|
+
case OP.LOAD_GLOBAL:
|
|
351
|
+
var dst = this._operand();
|
|
352
|
+
frame.regs[dst] = this.globals[this.constants[this._operand()]];
|
|
220
353
|
break;
|
|
221
354
|
|
|
222
355
|
// After
|
|
223
|
-
// [
|
|
224
|
-
// [
|
|
225
|
-
// [
|
|
226
|
-
// [
|
|
227
|
-
// [
|
|
228
|
-
// [
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
356
|
+
// [52040, 0, 1], ALIAS_LOAD_GLOBAL_1_0 [0, 1] 1:0-1:7
|
|
357
|
+
// [24862, 1, 2], ALIAS_LOAD_CONST_1_0 [1, 2] 1:0-1:28
|
|
358
|
+
// [25202, 1, 2, 3], ALIAS_GET_PROP_1_2_0 [1, 2, 3] 1:0-1:28
|
|
359
|
+
// [24862, 2, 4], ALIAS_LOAD_CONST_1_0 [2, 4] 1:12-1:27
|
|
360
|
+
// [43, 5, 1, 3, 1, 4], CALL_METHOD reg[5] = method(recv=reg[1], fn=reg[3], 1 args)1:0-1:28
|
|
361
|
+
// [24862, 3, 1], ALIAS_LOAD_CONST_1_0 [3, 1]
|
|
362
|
+
// [51807, 1], ALIAS_RETURN_0 1
|
|
363
|
+
|
|
364
|
+
// What the opcode "ALIAS_LOAD_GLOBAL_1_0" (52040) looks like:
|
|
365
|
+
case 52040:
|
|
366
|
+
// ALIAS_LOAD_GLOBAL_1_0 (order: [1,0])
|
|
367
|
+
let _unsortedOperands = [this._operand(), this._operand()];
|
|
368
|
+
let _operands = [_unsortedOperands[1], _unsortedOperands[0]];
|
|
369
|
+
var dst = _operands[0];
|
|
370
|
+
frame.regs[dst] = this.globals[this.constants[_operands[1]]];
|
|
234
371
|
break;
|
|
235
372
|
```
|
|
236
373
|
|
|
@@ -239,43 +376,49 @@ case 64:
|
|
|
239
376
|
Function bodies are replaced upon runtime entry to the real bytecode.
|
|
240
377
|
|
|
241
378
|
```diff
|
|
242
|
-
// Input
|
|
243
|
-
|
|
244
|
-
console.log("Hello, world!");
|
|
245
|
-
}
|
|
379
|
+
// Input Code
|
|
380
|
+
console.log("Hello, world!");
|
|
246
381
|
|
|
247
382
|
// Before
|
|
248
|
-
// [
|
|
249
|
-
// [0, 2],
|
|
250
|
-
// [
|
|
251
|
-
// [0,
|
|
252
|
-
// [
|
|
253
|
-
// [
|
|
254
|
-
// [
|
|
255
|
-
// [13], RETURN 1:0-3:1
|
|
383
|
+
// [2, 1, 0], LOAD_GLOBAL reg[1] = console 1:0-1:7
|
|
384
|
+
// [0, 2, 1], LOAD_CONST reg[2] = "log" 1:0-1:28
|
|
385
|
+
// [8, 3, 1, 2], GET_PROP [3, 1, 2] 1:0-1:28
|
|
386
|
+
// [0, 4, 2], LOAD_CONST reg[4] = "Hello, world!" 1:12-1:27
|
|
387
|
+
// [43, 5, 1, 3, 1, 4], CALL_METHOD reg[5] = method(recv=reg[1], fn=reg[3], 1 args)1:0-1:28
|
|
388
|
+
// [0, 1, 3], LOAD_CONST reg[1] = undefined
|
|
389
|
+
// [45, 1], RETURN reg[1]
|
|
256
390
|
|
|
257
391
|
// After
|
|
258
|
-
// [56,
|
|
259
|
-
-// [
|
|
260
|
-
-// [
|
|
261
|
-
-// [
|
|
262
|
-
-// [
|
|
263
|
-
-// [
|
|
264
|
-
-// [
|
|
265
|
-
-// [
|
|
266
|
-
-// [
|
|
267
|
-
-// [
|
|
268
|
-
-// [
|
|
269
|
-
-// [
|
|
270
|
-
-// [
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
392
|
+
// [56, 4, 28, 50], PATCH [4, 28, 50]
|
|
393
|
+
-// [52], FOR_IN_SETUP <-- 22 ints of garbage code
|
|
394
|
+
-// [39], JUMP
|
|
395
|
+
-// [12], SUB
|
|
396
|
+
-// [12], SUB
|
|
397
|
+
-// [2], LOAD_GLOBAL
|
|
398
|
+
-// [28], LOOSE_EQ
|
|
399
|
+
-// [12], SUB
|
|
400
|
+
-// [46], THROW
|
|
401
|
+
-// [18], BXOR
|
|
402
|
+
-// [8], GET_PROP
|
|
403
|
+
-// [5], MOVE
|
|
404
|
+
-// [55], TRY_END
|
|
405
|
+
-// [57], DEBUGGER
|
|
406
|
+
-// [46], THROW
|
|
407
|
+
-// [23], GT
|
|
408
|
+
-// [48], BUILD_ARRAY
|
|
409
|
+
-// [28], LOOSE_EQ
|
|
410
|
+
-// [18], BXOR
|
|
411
|
+
-// [2], LOAD_GLOBAL
|
|
412
|
+
-// [50], DEFINE_GETTER
|
|
413
|
+
-// [4], LOAD_THIS
|
|
414
|
+
-// [24], LTE
|
|
415
|
+
// [45, 1], RETURN reg[1]
|
|
416
|
+
+// [2, 1, 0], LOAD_GLOBAL reg[1] = console <-- 22 ints of real code
|
|
417
|
+
+// [0, 2, 1], LOAD_CONST reg[2] = "log" 1:0-1:28
|
|
418
|
+
+// [8, 3, 1, 2], GET_PROP [3, 1, 2] 1:0-1:28
|
|
419
|
+
+// [0, 4, 2], LOAD_CONST reg[4] = "Hello, world!" 1:12-1:27
|
|
420
|
+
+// [43, 5, 1, 3, 1, 4], CALL_METHOD reg[5] = method(recv=reg[1], fn=reg[3], 1 args)1:0-1:28
|
|
421
|
+
+// [0, 1, 3], LOAD_CONST reg[1] = undefined
|
|
279
422
|
```
|
|
280
423
|
|
|
281
424
|
#### `timingChecks` (true/false)
|
|
@@ -311,7 +454,7 @@ Please transpile your code down first using [Babel](https://github.com/babel/bab
|
|
|
311
454
|
|
|
312
455
|
### Project
|
|
313
456
|
|
|
314
|
-
-
|
|
457
|
+
- Register based VM
|
|
315
458
|
- Lua-style closure and upvalue model
|
|
316
459
|
- CPython-style opcodes and codegen
|
|
317
460
|
- Compiler is in src/compiler.ts
|