UNPKG

@awayfl/avm2

Version:

Virtual machine for executing AS3 code

594 lines (593 loc) 17.1 kB
import { assert } from '@awayjs/graphics'; import { release } from '@awayfl/swf-loader'; var bytecodeNames = [ '', 'BKPT', 'NOP', 'THROW', 'GETSUPER', 'SETSUPER', 'DXNS', 'DXNSLATE', 'KILL', 'LABEL', 'LF32X4', 'SF32X4', 'IFNLT', 'IFNLE', 'IFNGT', 'IFNGE', 'JUMP', 'IFTRUE', 'IFFALSE', 'IFEQ', 'IFNE', 'IFLT', 'IFLE', 'IFGT', 'IFGE', 'IFSTRICTEQ', 'IFSTRICTNE', 'LOOKUPSWITCH', 'PUSHWITH', 'POPSCOPE', 'NEXTNAME', 'HASNEXT', 'PUSHNULL', 'PUSHUNDEFINED', 'PUSHFLOAT', 'NEXTVALUE', 'PUSHBYTE', 'PUSHSHORT', 'PUSHTRUE', 'PUSHFALSE', 'PUSHNAN', 'POP', 'DUP', 'SWAP', 'PUSHSTRING', 'PUSHINT', 'PUSHUINT', 'PUSHDOUBLE', 'PUSHSCOPE', 'PUSHNAMESPACE', 'HASNEXT2', 'UNUSED_33', 'UNUSED_34', 'LI8', 'LI16', 'LI32', 'LF32', 'LF64', 'SI8', 'SI16', 'SI32', 'SF32', 'SF64', 'UNUSED_3F', 'NEWFUNCTION', 'CALL', 'CONSTRUCT', 'CALLMETHOD', 'CALLSTATIC', 'CALLSUPER', 'CALLPROPERTY', 'RETURNVOID', 'RETURNVALUE', 'CONSTRUCTSUPER', 'CONSTRUCTPROP', 'CALLSUPERID', 'CALLPROPLEX', 'CALLINTERFACE', 'CALLSUPERVOID', 'CALLPROPVOID', 'SXI1', 'SXI8', 'SXI16', 'APPLYTYPE', 'PUSHFLOAT4', 'NEWOBJECT', 'NEWARRAY', 'NEWACTIVATION', 'NEWCLASS', 'GETDESCENDANTS', 'NEWCATCH', 'UNUSED_5B', 'UNUSED_5C', 'FINDPROPSTRICT', 'FINDPROPERTY', 'FINDDEF', 'GETLEX', 'SETPROPERTY', 'GETLOCAL', 'SETLOCAL', 'GETGLOBALSCOPE', 'GETSCOPEOBJECT', 'GETPROPERTY', 'GETOUTERSCOPE', 'INITPROPERTY', 'UNUSED_69', 'DELETEPROPERTY', 'UNUSED_6B', 'GETSLOT', 'SETSLOT', 'GETGLOBALSLOT', 'SETGLOBALSLOT', 'CONVERT_S', 'ESC_XELEM', 'ESC_XATTR', 'CONVERT_I', 'CONVERT_U', 'CONVERT_D', 'CONVERT_B', 'CONVERT_O', 'CHECKFILTER', 'CONVERT_F', 'UNPLUS', 'CONVERT_F4', 'BC_7C', 'BC_7D', 'BC_7E', 'BC_7F', 'COERCE', 'COERCE_B', 'COERCE_A', 'COERCE_I', 'COERCE_D', 'COERCE_S', 'ASTYPE', 'ASTYPELATE', 'COERCE_U', 'COERCE_O', 'UNUSED_8A', 'UNUSED_8B', 'UNUSED_8C', 'UNUSED_8D', 'UNUSED_8E', 'UNUSED_8F', 'NEGATE', 'INCREMENT', 'INCLOCAL', 'DECREMENT', 'DECLOCAL', 'TYPEOF', 'NOT', 'BITNOT', 'UNUSED_98', 'UNUSED_99', 'UNUSED_9A', 'UNUSED_9B', 'UNUSED_9C', 'UNUSED_9D', 'UNUSED_9E', 'UNUSED_9F', 'ADD', 'SUBTRACT', 'MULTIPLY', 'DIVIDE', 'MODULO', 'LSHIFT', 'RSHIFT', 'URSHIFT', 'BITAND', 'BITOR', 'BITXOR', 'EQUALS', 'STRICTEQUALS', 'LESSTHAN', 'LESSEQUALS', 'GREATERTHAN', 'GREATEREQUALS', 'INSTANCEOF', 'ISTYPE', 'ISTYPELATE', 'IN', 'UNUSED_B5', 'UNUSED_B6', 'UNUSED_B7', 'UNUSED_B8', 'UNUSED_B9', 'UNUSED_BA', 'UNUSED_BB', 'UNUSED_BC', 'UNUSED_BD', 'UNUSED_BE', 'UNUSED_BF', 'INCREMENT_I', 'DECREMENT_I', 'INCLOCAL_I', 'DECLOCAL_I', 'NEGATE_I', 'ADD_I', 'SUBTRACT_I', 'MULTIPLY_I', 'UNUSED_C8', 'UNUSED_C9', 'UNUSED_CA', 'UNUSED_CB', 'UNUSED_CC', 'UNUSED_CD', 'UNUSED_CE', 'UNUSED_CF', 'GETLOCAL0', 'GETLOCAL1', 'GETLOCAL2', 'GETLOCAL3', 'SETLOCAL0', 'SETLOCAL1', 'SETLOCAL2', 'SETLOCAL3', 'UNUSED_D8', 'UNUSED_D9', 'UNUSED_DA', 'UNUSED_DB', 'UNUSED_DC', 'UNUSED_DD', 'UNUSED_DE', 'UNUSED_DF', 'UNUSED_E0', 'UNUSED_E1', 'UNUSED_E2', 'UNUSED_E3', 'UNUSED_E4', 'UNUSED_E5', 'UNUSED_E6', 'UNUSED_E7', 'UNUSED_E8', 'UNUSED_E9', 'UNUSED_EA', 'UNUSED_EB', 'UNUSED_EC', 'INVALID', 'UNUSED_EE', 'DEBUG', 'DEBUGLINE', 'DEBUGFILE', 'BKPTLINE', 'TIMESTAMP', 'RESTARGC', 'RESTARG', 'UNUSED_F6', 'UNUSED_F7', 'UNUSED_F8', 'UNUSED_F9', 'UNUSED_FA', 'UNUSED_FB', 'UNUSED_FC', 'UNUSED_FD', 'UNUSED_FE', 'END' ]; export function getBytecodeName(bytecode) { return release ? 'Bytecode: ' + bytecode : bytecodeNames[bytecode]; } /** * A array that maps from a bytecode value to the set of {@link OPFlags} for the corresponding instruction. */ export var BytecodeFlags = new Uint32Array(256); export var BytecodeFormat = new Array(256); function define(bytecode, format, flags) { if (flags === void 0) { flags = 0; } BytecodeFlags[bytecode] = flags; BytecodeFormat[bytecode] = format; } /** * Only call this before the compiler is used. */ export function defineBytecodes() { define(1 /* Bytecode.BKPT */, ''); define(2 /* Bytecode.NOP */, ''); define(3 /* Bytecode.THROW */, ''); define(4 /* Bytecode.GETSUPER */, 'e'); define(5 /* Bytecode.SETSUPER */, 'e'); define(6 /* Bytecode.DXNS */, 'e'); define(7 /* Bytecode.DXNSLATE */, ''); define(8 /* Bytecode.KILL */, 'e'); define(9 /* Bytecode.LABEL */, ''); define(10 /* Bytecode.LF32X4 */, ''); define(11 /* Bytecode.SF32X4 */, ''); define(12 /* Bytecode.IFNLT */, 'd'); define(13 /* Bytecode.IFNLE */, 'd'); define(14 /* Bytecode.IFNGT */, 'd'); define(15 /* Bytecode.IFNGE */, 'd'); define(16 /* Bytecode.JUMP */, 'd'); define(17 /* Bytecode.IFTRUE */, 'd'); define(18 /* Bytecode.IFFALSE */, 'd'); define(19 /* Bytecode.IFEQ */, 'd'); define(20 /* Bytecode.IFNE */, 'd'); define(21 /* Bytecode.IFLT */, 'd'); define(22 /* Bytecode.IFLE */, 'd'); define(23 /* Bytecode.IFGT */, 'd'); define(24 /* Bytecode.IFGE */, 'd'); define(25 /* Bytecode.IFSTRICTEQ */, 'd'); define(26 /* Bytecode.IFSTRICTNE */, 'd'); define(27 /* Bytecode.LOOKUPSWITCH */, ''); define(28 /* Bytecode.PUSHWITH */, ''); define(29 /* Bytecode.POPSCOPE */, ''); define(30 /* Bytecode.NEXTNAME */, ''); define(31 /* Bytecode.HASNEXT */, ''); define(32 /* Bytecode.PUSHNULL */, ''); define(33 /* Bytecode.PUSHUNDEFINED */, ''); define(35 /* Bytecode.NEXTVALUE */, ''); define(36 /* Bytecode.PUSHBYTE */, 'b'); define(37 /* Bytecode.PUSHSHORT */, 'c'); define(38 /* Bytecode.PUSHTRUE */, ''); define(39 /* Bytecode.PUSHFALSE */, ''); define(40 /* Bytecode.PUSHNAN */, ''); define(41 /* Bytecode.POP */, ''); define(42 /* Bytecode.DUP */, ''); define(43 /* Bytecode.SWAP */, ''); define(44 /* Bytecode.PUSHSTRING */, 'e'); define(45 /* Bytecode.PUSHINT */, 'e'); define(46 /* Bytecode.PUSHUINT */, 'e'); define(47 /* Bytecode.PUSHDOUBLE */, 'e'); define(48 /* Bytecode.PUSHSCOPE */, ''); define(49 /* Bytecode.PUSHNAMESPACE */, 'e'); define(50 /* Bytecode.HASNEXT2 */, 'ee'); // define(Bytecode.UNDEFINED, ""); // define(Bytecode.UNDEFINED, ""); define(53 /* Bytecode.LI8 */, ''); define(54 /* Bytecode.LI16 */, ''); define(55 /* Bytecode.LI32 */, ''); define(56 /* Bytecode.LF32 */, ''); define(57 /* Bytecode.LF64 */, ''); define(58 /* Bytecode.SI8 */, ''); define(59 /* Bytecode.SI16 */, ''); define(60 /* Bytecode.SI32 */, ''); define(61 /* Bytecode.SF32 */, ''); define(62 /* Bytecode.SF64 */, ''); define(64 /* Bytecode.NEWFUNCTION */, 'e'); define(65 /* Bytecode.CALL */, 'e'); define(66 /* Bytecode.CONSTRUCT */, 'e'); define(67 /* Bytecode.CALLMETHOD */, 'ee'); define(68 /* Bytecode.CALLSTATIC */, 'ee'); define(69 /* Bytecode.CALLSUPER */, 'ee'); define(70 /* Bytecode.CALLPROPERTY */, 'ee'); define(71 /* Bytecode.RETURNVOID */, ''); define(72 /* Bytecode.RETURNVALUE */, ''); define(73 /* Bytecode.CONSTRUCTSUPER */, 'e'); define(74 /* Bytecode.CONSTRUCTPROP */, 'ee'); define(75 /* Bytecode.CALLSUPERID */, ''); define(76 /* Bytecode.CALLPROPLEX */, 'ee'); define(77 /* Bytecode.CALLINTERFACE */, ''); define(78 /* Bytecode.CALLSUPERVOID */, 'ee'); define(79 /* Bytecode.CALLPROPVOID */, 'ee'); define(80 /* Bytecode.SXI1 */, ''); define(81 /* Bytecode.SXI8 */, ''); define(82 /* Bytecode.SXI16 */, ''); define(83 /* Bytecode.APPLYTYPE */, 'e'); define(84 /* Bytecode.PUSHFLOAT4 */, ''); define(85 /* Bytecode.NEWOBJECT */, 'e'); define(86 /* Bytecode.NEWARRAY */, 'e'); define(87 /* Bytecode.NEWACTIVATION */, ''); define(88 /* Bytecode.NEWCLASS */, 'e'); define(89 /* Bytecode.GETDESCENDANTS */, 'e'); define(90 /* Bytecode.NEWCATCH */, 'e'); // define(Bytecode.UNDEFINED, ""); // define(Bytecode.UNDEFINED, ""); define(93 /* Bytecode.FINDPROPSTRICT */, 'e'); define(94 /* Bytecode.FINDPROPERTY */, 'e'); define(95 /* Bytecode.FINDDEF */, ''); define(96 /* Bytecode.GETLEX */, 'e'); define(97 /* Bytecode.SETPROPERTY */, 'e'); define(98 /* Bytecode.GETLOCAL */, 'e'); define(99 /* Bytecode.SETLOCAL */, 'e'); define(100 /* Bytecode.GETGLOBALSCOPE */, ''); define(101 /* Bytecode.GETSCOPEOBJECT */, 'e'); define(102 /* Bytecode.GETPROPERTY */, 'e'); define(103 /* Bytecode.GETOUTERSCOPE */, ''); define(104 /* Bytecode.INITPROPERTY */, 'e'); define(106 /* Bytecode.DELETEPROPERTY */, 'e'); define(108 /* Bytecode.GETSLOT */, 'e'); define(109 /* Bytecode.SETSLOT */, 'e'); define(110 /* Bytecode.GETGLOBALSLOT */, 'e'); define(111 /* Bytecode.SETGLOBALSLOT */, 'e'); define(112 /* Bytecode.CONVERT_S */, ''); define(113 /* Bytecode.ESC_XELEM */, ''); define(114 /* Bytecode.ESC_XATTR */, ''); define(115 /* Bytecode.CONVERT_I */, ''); define(116 /* Bytecode.CONVERT_U */, ''); define(117 /* Bytecode.CONVERT_D */, ''); define(118 /* Bytecode.CONVERT_B */, ''); define(119 /* Bytecode.CONVERT_O */, ''); define(120 /* Bytecode.CHECKFILTER */, ''); define(121 /* Bytecode.CONVERT_F */, ''); define(122 /* Bytecode.UNPLUS */, ''); define(123 /* Bytecode.CONVERT_F4 */, ''); define(128 /* Bytecode.COERCE */, 'e'); define(129 /* Bytecode.COERCE_B */, ''); define(130 /* Bytecode.COERCE_A */, ''); define(131 /* Bytecode.COERCE_I */, ''); define(132 /* Bytecode.COERCE_D */, ''); define(133 /* Bytecode.COERCE_S */, ''); define(134 /* Bytecode.ASTYPE */, 'e'); define(135 /* Bytecode.ASTYPELATE */, ''); define(136 /* Bytecode.COERCE_U */, ''); define(137 /* Bytecode.COERCE_O */, ''); define(144 /* Bytecode.NEGATE */, ''); define(145 /* Bytecode.INCREMENT */, ''); define(146 /* Bytecode.INCLOCAL */, 'e'); define(147 /* Bytecode.DECREMENT */, ''); define(148 /* Bytecode.DECLOCAL */, 'e'); define(149 /* Bytecode.TYPEOF */, ''); define(150 /* Bytecode.NOT */, ''); define(151 /* Bytecode.BITNOT */, ''); define(160 /* Bytecode.ADD */, ''); define(161 /* Bytecode.SUBTRACT */, ''); define(162 /* Bytecode.MULTIPLY */, ''); define(163 /* Bytecode.DIVIDE */, ''); define(164 /* Bytecode.MODULO */, ''); define(165 /* Bytecode.LSHIFT */, ''); define(166 /* Bytecode.RSHIFT */, ''); define(167 /* Bytecode.URSHIFT */, ''); define(168 /* Bytecode.BITAND */, ''); define(169 /* Bytecode.BITOR */, ''); define(170 /* Bytecode.BITXOR */, ''); define(171 /* Bytecode.EQUALS */, ''); define(172 /* Bytecode.STRICTEQUALS */, ''); define(173 /* Bytecode.LESSTHAN */, ''); define(174 /* Bytecode.LESSEQUALS */, ''); define(175 /* Bytecode.GREATERTHAN */, ''); define(176 /* Bytecode.GREATEREQUALS */, ''); define(177 /* Bytecode.INSTANCEOF */, ''); define(178 /* Bytecode.ISTYPE */, 'e'); define(179 /* Bytecode.ISTYPELATE */, ''); define(180 /* Bytecode.IN */, ''); define(192 /* Bytecode.INCREMENT_I */, ''); define(193 /* Bytecode.DECREMENT_I */, ''); define(194 /* Bytecode.INCLOCAL_I */, 'e'); define(195 /* Bytecode.DECLOCAL_I */, 'e'); define(196 /* Bytecode.NEGATE_I */, ''); define(197 /* Bytecode.ADD_I */, ''); define(198 /* Bytecode.SUBTRACT_I */, ''); define(199 /* Bytecode.MULTIPLY_I */, ''); define(208 /* Bytecode.GETLOCAL0 */, ''); define(209 /* Bytecode.GETLOCAL1 */, ''); define(210 /* Bytecode.GETLOCAL2 */, ''); define(211 /* Bytecode.GETLOCAL3 */, ''); define(212 /* Bytecode.SETLOCAL0 */, ''); define(213 /* Bytecode.SETLOCAL1 */, ''); define(214 /* Bytecode.SETLOCAL2 */, ''); define(215 /* Bytecode.SETLOCAL3 */, ''); define(237 /* Bytecode.INVALID */, ''); define(239 /* Bytecode.DEBUG */, 'aeae'); define(240 /* Bytecode.DEBUGLINE */, 'e'); define(241 /* Bytecode.DEBUGFILE */, 'e'); define(242 /* Bytecode.BKPTLINE */, 'e'); define(243 /* Bytecode.TIMESTAMP */, ''); // define(Bytecode.UNUSED_6B, "", Flags.NONE); // define(Bytecode.UNUSED_DE, "", Flags.NONE); // define(Bytecode.UNUSED_BB, "", Flags.NONE); } defineBytecodes(); var Bytes = /** @class */ (function () { function Bytes() { } Bytes.u8 = function (code, i) { return code[i]; }; Bytes.s32 = function (code, i) { var result = code[i]; if (result & 0x80) { result = result & 0x7f | code[i + 1] << 7; if (result & 0x4000) { result = result & 0x3fff | code[i + 2] << 14; if (result & 0x200000) { result = result & 0x1fffff | code[i + 3] << 21; if (result & 0x10000000) { result = result & 0x0fffffff | code[i + 4] << 28; result = result & 0xffffffff; } } } } return result; }; Bytes.u32 = function (code, i) { return Bytes.s32(code, i) >>> 0; }; Bytes.u30 = function (code, i) { return Bytes.u32(code, i); }; Bytes.s32Length = function (code, i) { var result = code[i]; if (result & 0x80) { result = result & 0x7f | code[i + 1] << 7; if (result & 0x4000) { result = result & 0x3fff | code[i + 2] << 14; if (result & 0x200000) { result = result & 0x1fffff | code[i + 3] << 21; if (result & 0x10000000) { return 5; } return 4; } return 3; } return 2; } return 1; }; return Bytes; }()); export { Bytes }; function lengthAt(code, i) { var l = 1; var bytecode = code[i]; if (bytecode === 27 /* Bytecode.LOOKUPSWITCH */) { l += 3; // Default offset. var n = Bytes.u30(code, i + l) + 1; // Offsets l += Bytes.s32Length(code, i + l); l += n * 3; return l; } var format = BytecodeFormat[bytecode]; if (format === '') { return l; } assert(format, 'OP: ' + getBytecodeName(bytecode)); for (var j = 0; j < format.length; j++) { var f = format[j].charCodeAt(0) - 97; switch (f) { case 0 /* Sizes.u08 */: case 1 /* Sizes.s08 */: l += 1; continue; case 3 /* Sizes.s24 */: l += 3; continue; case 2 /* Sizes.s16 */: case 4 /* Sizes.u30 */: case 5 /* Sizes.u32 */: l += Bytes.s32Length(code, i + l); continue; } } return l; } var BytecodeStream = /** @class */ (function () { function BytecodeStream(code) { this._code = code; this.setBCI(0); } BytecodeStream.prototype.next = function () { this.setBCI(this._nextBCI); }; BytecodeStream.prototype.endBCI = function () { return this._code.length; }; Object.defineProperty(BytecodeStream.prototype, "nextBCI", { get: function () { return this._nextBCI; }, enumerable: false, configurable: true }); Object.defineProperty(BytecodeStream.prototype, "currentBCI", { get: function () { return this._currentBCI; }, enumerable: false, configurable: true }); BytecodeStream.prototype.currentBytecode = function () { return this._bytecode; }; BytecodeStream.prototype.nextBC = function () { return Bytes.u8(this._code, this._nextBCI); }; BytecodeStream.prototype.setBCI = function (bci) { this._currentBCI = bci; if (this._currentBCI < this._code.length) { this._bytecode = Bytes.u8(this._code, bci); var l = lengthAt(this._code, bci); this._nextBCI = bci + l; } else { this._bytecode = 255 /* Bytecode.END */; this._nextBCI = this._currentBCI; } }; return BytecodeStream; }()); export { BytecodeStream };