@typeberry/lib 0.2.0-0303f5b → 0.2.0-3f440a7

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.
Files changed (4) hide show
  1. package/index.cjs +2412 -1731
  2. package/index.d.ts +2101 -1909
  3. package/index.js +2410 -1729
  4. package/package.json +1 -1
package/index.cjs CHANGED
@@ -3,6 +3,7 @@
3
3
  var assert = require('node:assert');
4
4
  var fs = require('node:fs');
5
5
  var os = require('node:os');
6
+ var node_url = require('node:url');
6
7
 
7
8
  var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
8
9
  var GpVersion;
@@ -10,44 +11,40 @@ var GpVersion;
10
11
  GpVersion["V0_6_7"] = "0.6.7";
11
12
  GpVersion["V0_7_0"] = "0.7.0";
12
13
  GpVersion["V0_7_1"] = "0.7.1";
13
- GpVersion["V0_7_2"] = "0.7.2-preview";
14
+ GpVersion["V0_7_2"] = "0.7.2";
14
15
  })(GpVersion || (GpVersion = {}));
15
16
  var TestSuite;
16
17
  (function (TestSuite) {
17
18
  TestSuite["W3F_DAVXY"] = "w3f-davxy";
18
19
  TestSuite["JAMDUNA"] = "jamduna";
19
20
  })(TestSuite || (TestSuite = {}));
21
+ const ALL_VERSIONS_IN_ORDER = [GpVersion.V0_6_7, GpVersion.V0_7_0, GpVersion.V0_7_1, GpVersion.V0_7_2];
20
22
  const DEFAULT_SUITE = TestSuite.W3F_DAVXY;
21
- const DEFAULT_VERSION = GpVersion.V0_7_1;
23
+ const DEFAULT_VERSION = GpVersion.V0_7_2;
22
24
  const env$1 = typeof process === "undefined" ? {} : process.env;
23
25
  let CURRENT_VERSION = parseCurrentVersion(env$1.GP_VERSION) ?? DEFAULT_VERSION;
24
26
  let CURRENT_SUITE = parseCurrentSuite(env$1.TEST_SUITE) ?? DEFAULT_SUITE;
25
- const ALL_VERSIONS_IN_ORDER = [GpVersion.V0_6_7, GpVersion.V0_7_0, GpVersion.V0_7_1, GpVersion.V0_7_2];
26
27
  function parseCurrentVersion(env) {
27
28
  if (env === undefined) {
28
29
  return undefined;
29
30
  }
30
- switch (env) {
31
- case GpVersion.V0_6_7:
32
- case GpVersion.V0_7_0:
33
- case GpVersion.V0_7_1:
34
- case GpVersion.V0_7_2:
35
- return env;
36
- default:
37
- throw new Error(`Configured environment variable GP_VERSION is unknown: '${env}'. Use one of: ${ALL_VERSIONS_IN_ORDER}`);
31
+ for (const v of Object.values(GpVersion)) {
32
+ if (env === v) {
33
+ return v;
34
+ }
38
35
  }
36
+ throw new Error(`Configured environment variable GP_VERSION is unknown: '${env}'. Use one of: ${ALL_VERSIONS_IN_ORDER}`);
39
37
  }
40
38
  function parseCurrentSuite(env) {
41
39
  if (env === undefined) {
42
40
  return undefined;
43
41
  }
44
- switch (env) {
45
- case TestSuite.W3F_DAVXY:
46
- case TestSuite.JAMDUNA:
47
- return env;
48
- default:
49
- throw new Error(`Configured environment variable TEST_SUITE is unknown: '${env}'. Use one of: ${Object.values(TestSuite)}`);
42
+ for (const s of Object.values(TestSuite)) {
43
+ if (env === s) {
44
+ return s;
45
+ }
50
46
  }
47
+ throw new Error(`Configured environment variable TEST_SUITE is unknown: '${env}'. Use one of: ${Object.values(TestSuite)}`);
51
48
  }
52
49
  class Compatibility {
53
50
  static override(version) {
@@ -207,6 +204,13 @@ class WithDebug {
207
204
  return inspect(this);
208
205
  }
209
206
  }
207
+ function lazyInspect(obj) {
208
+ return {
209
+ toString() {
210
+ return inspect(obj);
211
+ },
212
+ };
213
+ }
210
214
 
211
215
  const env = typeof process === "undefined" ? {} : process.env;
212
216
  /**
@@ -601,6 +605,7 @@ var index$u = /*#__PURE__*/Object.freeze({
601
605
  deepEqual: deepEqual,
602
606
  inspect: inspect,
603
607
  isBrowser: isBrowser,
608
+ lazyInspect: lazyInspect,
604
609
  measure: measure,
605
610
  resultToString: resultToString,
606
611
  safeAllocUint8Array: safeAllocUint8Array,
@@ -5174,6 +5179,17 @@ class Bootnode {
5174
5179
  }
5175
5180
  }
5176
5181
 
5182
+ /** Implemented PVM Backends names in THE SAME ORDER as enum. */
5183
+ const PvmBackendNames = ["built-in", "ananas"];
5184
+ /** Implemented PVM Backends to choose from. */
5185
+ var PvmBackend;
5186
+ (function (PvmBackend) {
5187
+ /** Built-in aka. Typeberry 🫐 interpreter. */
5188
+ PvmBackend[PvmBackend["BuiltIn"] = 0] = "BuiltIn";
5189
+ /** Ananas 🍍 interpreter. */
5190
+ PvmBackend[PvmBackend["Ananas"] = 1] = "Ananas";
5191
+ })(PvmBackend || (PvmBackend = {}));
5192
+
5177
5193
  var index$m = /*#__PURE__*/Object.freeze({
5178
5194
  __proto__: null,
5179
5195
  Bootnode: Bootnode,
@@ -5183,6 +5199,8 @@ var index$m = /*#__PURE__*/Object.freeze({
5183
5199
  EST_EPOCH_LENGTH: EST_EPOCH_LENGTH,
5184
5200
  EST_VALIDATORS: EST_VALIDATORS,
5185
5201
  EST_VALIDATORS_SUPER_MAJORITY: EST_VALIDATORS_SUPER_MAJORITY,
5202
+ get PvmBackend () { return PvmBackend; },
5203
+ PvmBackendNames: PvmBackendNames,
5186
5204
  fullChainSpec: fullChainSpec,
5187
5205
  tinyChainSpec: tinyChainSpec
5188
5206
  });
@@ -7730,7 +7748,8 @@ const DEV_CONFIG = "dev";
7730
7748
  const DEFAULT_CONFIG = "default";
7731
7749
  const NODE_DEFAULTS = {
7732
7750
  name: isBrowser() ? "browser" : os.hostname(),
7733
- config: DEFAULT_CONFIG,
7751
+ config: [DEFAULT_CONFIG],
7752
+ pvm: PvmBackend.BuiltIn,
7734
7753
  };
7735
7754
  /** Chain spec chooser. */
7736
7755
  var KnownChainSpec;
@@ -7782,24 +7801,136 @@ class NodeConfiguration {
7782
7801
  this.authorship = authorship;
7783
7802
  }
7784
7803
  }
7785
- function loadConfig(configPath) {
7786
- if (configPath === DEFAULT_CONFIG) {
7787
- logger$5.log `🔧 Loading DEFAULT config`;
7788
- return parseFromJson(configs.default, NodeConfiguration.fromJson);
7789
- }
7790
- if (configPath === DEV_CONFIG) {
7791
- logger$5.log `🔧 Loading DEV config`;
7792
- return parseFromJson(configs.dev, NodeConfiguration.fromJson);
7804
+ function loadConfig(config, withRelPath) {
7805
+ logger$5.log `🔧 Loading config`;
7806
+ let mergedJson = {};
7807
+ for (const entry of config) {
7808
+ logger$5.log `🔧 Applying '${entry}'`;
7809
+ if (entry === DEV_CONFIG) {
7810
+ mergedJson = structuredClone(configs.dev); // clone to avoid mutating the original config. not doing a merge since dev and default should theoretically replace all properties.
7811
+ continue;
7812
+ }
7813
+ if (entry === DEFAULT_CONFIG) {
7814
+ mergedJson = structuredClone(configs.default);
7815
+ continue;
7816
+ }
7817
+ // try to parse as JSON
7818
+ try {
7819
+ const parsed = JSON.parse(entry);
7820
+ deepMerge(mergedJson, parsed);
7821
+ continue;
7822
+ }
7823
+ catch { }
7824
+ // if not, try to load as file
7825
+ if (entry.indexOf("=") === -1 && entry.endsWith(".json")) {
7826
+ try {
7827
+ const configFile = fs.readFileSync(withRelPath(entry), "utf8");
7828
+ const parsed = JSON.parse(configFile);
7829
+ deepMerge(mergedJson, parsed);
7830
+ }
7831
+ catch (e) {
7832
+ throw new Error(`Unable to load config from ${entry}: ${e}`);
7833
+ }
7834
+ }
7835
+ else {
7836
+ // finally try to process as a pseudo-jq query
7837
+ try {
7838
+ processQuery(mergedJson, entry, withRelPath);
7839
+ }
7840
+ catch (e) {
7841
+ throw new Error(`Error while processing '${entry}': ${e}`);
7842
+ }
7843
+ }
7793
7844
  }
7794
7845
  try {
7795
- logger$5.log `🔧 Loading config from ${configPath}`;
7796
- const configFile = fs.readFileSync(configPath, "utf8");
7797
- const parsed = JSON.parse(configFile);
7798
- return parseFromJson(parsed, NodeConfiguration.fromJson);
7846
+ const parsed = parseFromJson(mergedJson, NodeConfiguration.fromJson);
7847
+ logger$5.log `🔧 Config ready`;
7848
+ return parsed;
7799
7849
  }
7800
7850
  catch (e) {
7801
- throw new Error(`Unable to load config file from ${configPath}: ${e}`);
7851
+ throw new Error(`Unable to parse config: ${e}`);
7852
+ }
7853
+ }
7854
+ function deepMerge(target, source) {
7855
+ if (!isJsonObject(source)) {
7856
+ throw new Error(`Expected object, got ${source}`);
7857
+ }
7858
+ for (const key in source) {
7859
+ if (isJsonObject(source[key])) {
7860
+ if (!isJsonObject(target[key])) {
7861
+ target[key] = {};
7862
+ }
7863
+ deepMerge(target[key], source[key]);
7864
+ }
7865
+ else {
7866
+ target[key] = source[key];
7867
+ }
7868
+ }
7869
+ }
7870
+ /**
7871
+ * Caution: updates input directly.
7872
+ * Processes a pseudo-jq query. Syntax:
7873
+ * .path.to.value = { ... } - updates value with the specified object by replacement
7874
+ * .path.to.value += { ... } - updates value with the specified object by merging
7875
+ * .path.to.value = file.json - updates value with the contents of file.json
7876
+ * .path.to.value += file.json - merges the contents of file.json onto value
7877
+ */
7878
+ function processQuery(input, query, withRelPath) {
7879
+ const queryParts = query.split("=");
7880
+ if (queryParts.length === 2) {
7881
+ let [path, value] = queryParts.map((part) => part.trim());
7882
+ let merge = false;
7883
+ // detect += syntax
7884
+ if (path.endsWith("+")) {
7885
+ merge = true;
7886
+ path = path.slice(0, -1);
7887
+ }
7888
+ let parsedValue;
7889
+ if (value.endsWith(".json")) {
7890
+ try {
7891
+ const configFile = fs.readFileSync(withRelPath(value), "utf8");
7892
+ const parsed = JSON.parse(configFile);
7893
+ parsedValue = parsed;
7894
+ }
7895
+ catch (e) {
7896
+ throw new Error(`Unable to load config from ${value}: ${e}`);
7897
+ }
7898
+ }
7899
+ else {
7900
+ try {
7901
+ parsedValue = JSON.parse(value);
7902
+ }
7903
+ catch (e) {
7904
+ throw new Error(`Unrecognized syntax '${value}': ${e}`);
7905
+ }
7906
+ }
7907
+ let pathParts = path.split(".");
7908
+ // allow leading dot in path
7909
+ if (pathParts[0] === "") {
7910
+ pathParts = pathParts.slice(1);
7911
+ }
7912
+ let target = input;
7913
+ for (let i = 0; i < pathParts.length; i++) {
7914
+ const part = pathParts[i];
7915
+ if (!isJsonObject(target[part])) {
7916
+ target[part] = {};
7917
+ }
7918
+ if (i === pathParts.length - 1) {
7919
+ if (merge) {
7920
+ deepMerge(target[part], parsedValue);
7921
+ }
7922
+ else {
7923
+ target[part] = parsedValue;
7924
+ }
7925
+ return;
7926
+ }
7927
+ target = target[part];
7928
+ }
7802
7929
  }
7930
+ throw new Error("Unrecognized syntax.");
7931
+ }
7932
+ function isJsonObject(value) {
7933
+ return typeof value === "object" && value !== null && !Array.isArray(value);
7803
7934
  }
7804
7935
 
7805
7936
  var index$h = /*#__PURE__*/Object.freeze({
@@ -8943,26 +9074,6 @@ class InMemoryStateView {
8943
9074
  }
8944
9075
  }
8945
9076
 
8946
- /** Dictionary entry of services that auto-accumulate every block. */
8947
- class AutoAccumulate {
8948
- service;
8949
- gasLimit;
8950
- static Codec = codec$1.Class(AutoAccumulate, {
8951
- service: codec$1.u32.asOpaque(),
8952
- gasLimit: codec$1.u64.asOpaque(),
8953
- });
8954
- static create({ service, gasLimit }) {
8955
- return new AutoAccumulate(service, gasLimit);
8956
- }
8957
- constructor(
8958
- /** Service id that auto-accumulates. */
8959
- service,
8960
- /** Gas limit for auto-accumulation. */
8961
- gasLimit) {
8962
- this.service = service;
8963
- this.gasLimit = gasLimit;
8964
- }
8965
- }
8966
9077
  /**
8967
9078
  * https://graypaper.fluffylabs.dev/#/ab2cdbd/114402114402?v=0.7.2
8968
9079
  */
@@ -8980,7 +9091,9 @@ class PrivilegedServices {
8980
9091
  registrar: Compatibility.isGreaterOrEqual(GpVersion.V0_7_1)
8981
9092
  ? codec$1.u32.asOpaque()
8982
9093
  : ignoreValueWithDefault(tryAsServiceId(2 ** 32 - 1)),
8983
- autoAccumulateServices: readonlyArray(codec$1.sequenceVarLen(AutoAccumulate.Codec)),
9094
+ autoAccumulateServices: codec$1.dictionary(codec$1.u32.asOpaque(), codec$1.u64.asOpaque(), {
9095
+ sortKeys: (a, b) => a - b,
9096
+ }),
8984
9097
  });
8985
9098
  static create(a) {
8986
9099
  return new PrivilegedServices(a.manager, a.delegator, a.registrar, a.assigners, a.autoAccumulateServices);
@@ -9585,7 +9698,7 @@ class InMemoryState extends WithDebug {
9585
9698
  assigners: tryAsPerCore(new Array(spec.coresCount).fill(tryAsServiceId(0)), spec),
9586
9699
  delegator: tryAsServiceId(0),
9587
9700
  registrar: tryAsServiceId(MAX_VALUE),
9588
- autoAccumulateServices: [],
9701
+ autoAccumulateServices: new Map(),
9589
9702
  }),
9590
9703
  accumulationOutputLog: SortedArray.fromArray(accumulationOutputComparator, []),
9591
9704
  services: new Map(),
@@ -9608,7 +9721,6 @@ var index$g = /*#__PURE__*/Object.freeze({
9608
9721
  __proto__: null,
9609
9722
  AUTHORIZATION_QUEUE_SIZE: AUTHORIZATION_QUEUE_SIZE,
9610
9723
  AccumulationOutput: AccumulationOutput,
9611
- AutoAccumulate: AutoAccumulate,
9612
9724
  AvailabilityAssignment: AvailabilityAssignment,
9613
9725
  BASE_SERVICE_BALANCE: BASE_SERVICE_BALANCE,
9614
9726
  BlockState: BlockState,
@@ -12280,18 +12392,41 @@ class PendingTransfer {
12280
12392
  }
12281
12393
  }
12282
12394
 
12395
+ /** Attempt to convert given number into U32 gas representation. */
12396
+ const tryAsSmallGas = (v) => asOpaqueType(tryAsU32(v));
12397
+ /** Attempt to convert given number into U64 gas representation. */
12398
+ const tryAsBigGas = (v) => asOpaqueType(tryAsU64(v));
12399
+ /** Attempt to convert given number into gas. */
12400
+ const tryAsGas = (v) => typeof v === "number" && v < 2 ** 32 ? tryAsSmallGas(v) : tryAsBigGas(v);
12401
+
12402
+ const MAX_MEMORY_INDEX = 0xffff_ffff;
12403
+ const MEMORY_SIZE = MAX_MEMORY_INDEX + 1;
12404
+ const PAGE_SIZE_SHIFT$1 = 12;
12405
+ function getPageStartAddress(address) {
12406
+ return tryAsU32(((address >>> PAGE_SIZE_SHIFT$1) << PAGE_SIZE_SHIFT$1) >>> 0);
12407
+ }
12408
+
12409
+ const NO_OF_REGISTERS$1 = 13;
12410
+ const REGISTER_BYTE_SIZE = 8;
12411
+
12283
12412
  /**
12284
- * Inner status codes for the PVM
12413
+ * Result codes for the PVM execution.
12285
12414
  *
12286
- * https://graypaper.fluffylabs.dev/#/85129da/2cae022cae02?v=0.6.3
12415
+ * https://graypaper.fluffylabs.dev/#/ab2cdbd/2e43002e4300?v=0.7.2
12287
12416
  */
12288
12417
  var Status;
12289
12418
  (function (Status) {
12419
+ /** Continue */
12290
12420
  Status[Status["OK"] = 255] = "OK";
12421
+ /** Finished */
12291
12422
  Status[Status["HALT"] = 0] = "HALT";
12423
+ /** Panic */
12292
12424
  Status[Status["PANIC"] = 1] = "PANIC";
12425
+ /** Page-fault */
12293
12426
  Status[Status["FAULT"] = 2] = "FAULT";
12427
+ /** Host-call */
12294
12428
  Status[Status["HOST"] = 3] = "HOST";
12429
+ /** Out of gas */
12295
12430
  Status[Status["OOG"] = 4] = "OOG";
12296
12431
  })(Status || (Status = {}));
12297
12432
 
@@ -12688,6 +12823,9 @@ function writeServiceIdAsLeBytes(serviceId, destination) {
12688
12823
  function clampU64ToU32(value) {
12689
12824
  return value > MAX_U32_BIG_INT ? MAX_U32 : tryAsU32(Number(value));
12690
12825
  }
12826
+ function emptyRegistersBuffer() {
12827
+ return safeAllocUint8Array(NO_OF_REGISTERS$1 * REGISTER_BYTE_SIZE);
12828
+ }
12691
12829
 
12692
12830
  var index$9 = /*#__PURE__*/Object.freeze({
12693
12831
  __proto__: null,
@@ -12716,6 +12854,7 @@ var index$9 = /*#__PURE__*/Object.freeze({
12716
12854
  get UpdatePrivilegesError () { return UpdatePrivilegesError; },
12717
12855
  get ZeroVoidError () { return ZeroVoidError; },
12718
12856
  clampU64ToU32: clampU64ToU32,
12857
+ emptyRegistersBuffer: emptyRegistersBuffer,
12719
12858
  getServiceId: getServiceId,
12720
12859
  getServiceIdOrCurrent: getServiceIdOrCurrent,
12721
12860
  slotsToPreimageStatus: slotsToPreimageStatus,
@@ -12847,8 +12986,7 @@ var index$8 = /*#__PURE__*/Object.freeze({
12847
12986
  MerkleMountainRange: MerkleMountainRange
12848
12987
  });
12849
12988
 
12850
- const NO_OF_REGISTERS$1 = 13;
12851
- const REGISTER_SIZE_SHIFT = 3;
12989
+ const REGISTER_SIZE_SHIFT = 3; // x << 3 === x * 8
12852
12990
  const tryAsRegisterIndex = (index) => {
12853
12991
  check `${index >= 0 && index < NO_OF_REGISTERS$1} Incorrect register index: ${index}!`;
12854
12992
  return asOpaqueType(index);
@@ -12863,6 +13001,13 @@ class Registers {
12863
13001
  this.asSigned = new BigInt64Array(bytes.buffer, bytes.byteOffset);
12864
13002
  this.asUnsigned = new BigUint64Array(bytes.buffer, bytes.byteOffset);
12865
13003
  }
13004
+ getAllEncoded() {
13005
+ return this.bytes;
13006
+ }
13007
+ setAllEncoded(bytes) {
13008
+ check `${bytes.length === this.bytes.length} Incorrect size of input registers. Got: ${bytes.length}, need: ${this.bytes.length}`;
13009
+ this.bytes.set(bytes, 0);
13010
+ }
12866
13011
  static fromBytes(bytes) {
12867
13012
  check `${bytes.length === NO_OF_REGISTERS$1 << REGISTER_SIZE_SHIFT} Invalid size of registers array.`;
12868
13013
  return new Registers(bytes);
@@ -12871,9 +13016,6 @@ class Registers {
12871
13016
  const offset = index << REGISTER_SIZE_SHIFT;
12872
13017
  return this.bytes.subarray(offset, offset + len);
12873
13018
  }
12874
- getAllBytesAsLittleEndian() {
12875
- return this.bytes;
12876
- }
12877
13019
  copyFrom(regs) {
12878
13020
  const array = regs instanceof BigUint64Array ? regs : regs.asUnsigned;
12879
13021
  this.asUnsigned.set(array);
@@ -12945,1051 +13087,271 @@ function traceRegisters(...regs) {
12945
13087
  return regs.map(tryAsRegisterIndex);
12946
13088
  }
12947
13089
 
12948
- /** Attempt to convert given number into U32 gas representation. */
12949
- const tryAsSmallGas = (v) => asOpaqueType(tryAsU32(v));
12950
- /** Attempt to convert given number into U64 gas representation. */
12951
- const tryAsBigGas = (v) => asOpaqueType(tryAsU64(v));
12952
- /** Attempt to convert given number into gas. */
12953
- const tryAsGas = (v) => typeof v === "number" && v < 2 ** 32 ? tryAsSmallGas(v) : tryAsBigGas(v);
12954
- /** Create a new gas counter instance depending on the gas value. */
12955
- function gasCounter(gas) {
12956
- return new GasCounterU64(tryAsU64(gas));
12957
- }
12958
- class GasCounterU64 {
12959
- gas;
12960
- constructor(gas) {
12961
- this.gas = gas;
12962
- }
12963
- set(g) {
12964
- this.gas = tryAsU64(g);
12965
- }
12966
- get() {
12967
- return tryAsGas(this.gas);
13090
+ class HostCallMemory {
13091
+ memory;
13092
+ constructor(memory) {
13093
+ this.memory = memory;
12968
13094
  }
12969
- sub(g) {
12970
- const result = this.gas - tryAsU64(g);
12971
- if (result >= 0n) {
12972
- this.gas = tryAsU64(result);
12973
- return false;
13095
+ /**
13096
+ * Save some bytes into memory under given address.
13097
+ *
13098
+ * NOTE: Given address is U64 (pure register value),
13099
+ * but we use only lower 32-bits.
13100
+ */
13101
+ storeFrom(regAddress, bytes) {
13102
+ if (bytes.length === 0) {
13103
+ return Result$1.ok(OK);
12974
13104
  }
12975
- this.gas = tryAsU64(0n);
12976
- return true;
13105
+ // NOTE: We always take lower 32 bits from register value.
13106
+ //
13107
+ // https://graypaper.fluffylabs.dev/#/ab2cdbd/25ed0025ed00?v=0.7.2
13108
+ const address = tryAsU32(Number(regAddress & 0xffffffffn));
13109
+ return this.memory.store(address, bytes);
12977
13110
  }
12978
- }
12979
-
12980
- /**
12981
- * Upper bound of instruction distance - it is equal to max value of GP's skip function + 1
12982
- */
12983
- const MAX_INSTRUCTION_DISTANCE = 25;
12984
- /**
12985
- * Mask class is an implementation of skip function defined in GP.
12986
- *
12987
- * https://graypaper.fluffylabs.dev/#/5f542d7/237201239801
12988
- */
12989
- class Mask {
12990
13111
  /**
12991
- * The lookup table will have `0` at the index which corresponds to an instruction on the same index in the bytecode.
12992
- * In case the value is non-zero it signifies the offset to the index with next instruction.
13112
+ * Read some bytes from memory under given address.
12993
13113
  *
12994
- * Example:
12995
- * ```
12996
- * 0..1..2..3..4..5..6..7..8..9 # Indices
12997
- * 0..2..1..0..1..0..3..2..1..0 # lookupTable forward values
12998
- * ```
12999
- * There are instructions at indices `0, 3, 5, 9`.
13114
+ * NOTE: Given address is U64 (pure register value),
13115
+ * but we use only lower 32-bits.
13000
13116
  */
13001
- lookupTableForward;
13002
- constructor(mask) {
13003
- this.lookupTableForward = this.buildLookupTableForward(mask);
13004
- }
13005
- isInstruction(index) {
13006
- return this.lookupTableForward[index] === 0;
13007
- }
13008
- getNoOfBytesToNextInstruction(index) {
13009
- check `${index >= 0} index (${index}) cannot be a negative number`;
13010
- return Math.min(this.lookupTableForward[index] ?? 0, MAX_INSTRUCTION_DISTANCE);
13011
- }
13012
- buildLookupTableForward(mask) {
13013
- const table = safeAllocUint8Array(mask.bitLength);
13014
- let lastInstructionOffset = 0;
13015
- for (let i = mask.bitLength - 1; i >= 0; i--) {
13016
- if (mask.isSet(i)) {
13017
- lastInstructionOffset = 0;
13018
- }
13019
- else {
13020
- lastInstructionOffset++;
13021
- }
13022
- table[i] = lastInstructionOffset;
13117
+ loadInto(output, regAddress) {
13118
+ if (output.length === 0) {
13119
+ return Result$1.ok(OK);
13023
13120
  }
13024
- return table;
13025
- }
13026
- static empty() {
13027
- return new Mask(BitVec.empty(0));
13121
+ // https://graypaper.fluffylabs.dev/#/ab2cdbd/25ed0025ed00?v=0.7.2
13122
+ //
13123
+ // NOTE we are taking the the lower U32 part of the register, hence it's safe.
13124
+ const address = tryAsU32(Number(regAddress & 0xffffffffn));
13125
+ return this.memory.read(address, output);
13028
13126
  }
13029
13127
  }
13030
13128
 
13031
- var ArgumentType;
13032
- (function (ArgumentType) {
13033
- ArgumentType[ArgumentType["NO_ARGUMENTS"] = 0] = "NO_ARGUMENTS";
13034
- ArgumentType[ArgumentType["ONE_IMMEDIATE"] = 1] = "ONE_IMMEDIATE";
13035
- ArgumentType[ArgumentType["TWO_IMMEDIATES"] = 2] = "TWO_IMMEDIATES";
13036
- ArgumentType[ArgumentType["ONE_OFFSET"] = 3] = "ONE_OFFSET";
13037
- ArgumentType[ArgumentType["ONE_REGISTER_ONE_IMMEDIATE"] = 4] = "ONE_REGISTER_ONE_IMMEDIATE";
13038
- ArgumentType[ArgumentType["ONE_REGISTER_TWO_IMMEDIATES"] = 5] = "ONE_REGISTER_TWO_IMMEDIATES";
13039
- ArgumentType[ArgumentType["ONE_REGISTER_ONE_IMMEDIATE_ONE_OFFSET"] = 6] = "ONE_REGISTER_ONE_IMMEDIATE_ONE_OFFSET";
13040
- ArgumentType[ArgumentType["TWO_REGISTERS"] = 7] = "TWO_REGISTERS";
13041
- ArgumentType[ArgumentType["TWO_REGISTERS_ONE_IMMEDIATE"] = 8] = "TWO_REGISTERS_ONE_IMMEDIATE";
13042
- ArgumentType[ArgumentType["TWO_REGISTERS_ONE_OFFSET"] = 9] = "TWO_REGISTERS_ONE_OFFSET";
13043
- ArgumentType[ArgumentType["TWO_REGISTERS_TWO_IMMEDIATES"] = 10] = "TWO_REGISTERS_TWO_IMMEDIATES";
13044
- ArgumentType[ArgumentType["THREE_REGISTERS"] = 11] = "THREE_REGISTERS";
13045
- ArgumentType[ArgumentType["ONE_REGISTER_ONE_EXTENDED_WIDTH_IMMEDIATE"] = 12] = "ONE_REGISTER_ONE_EXTENDED_WIDTH_IMMEDIATE";
13046
- })(ArgumentType || (ArgumentType = {}));
13047
-
13048
- const BUFFER_SIZE = 8;
13049
- const IMMEDIATE_SIZE$1 = 4;
13050
- const U32_INDEX = 0;
13051
- const U64_INDEX = 0;
13052
- class ImmediateDecoder {
13053
- u32;
13054
- i32;
13055
- u64;
13056
- i64;
13057
- view;
13129
+ class HostCallRegisters {
13058
13130
  bytes;
13059
- constructor() {
13060
- const buffer = new ArrayBuffer(BUFFER_SIZE);
13061
- this.u32 = new Uint32Array(buffer);
13062
- this.i32 = new Int32Array(buffer);
13063
- this.u64 = new BigUint64Array(buffer);
13064
- this.i64 = new BigInt64Array(buffer);
13065
- this.view = new DataView(buffer);
13066
- this.bytes = new Uint8Array(buffer);
13067
- }
13068
- setBytes(bytes) {
13069
- const n = bytes.length;
13070
- const msb = n > 0 ? bytes[n - 1] & 0x80 : 0;
13071
- const noOfBytes = Math.min(n, BUFFER_SIZE);
13072
- const prefix = msb !== 0 ? 0xff : 0x00;
13073
- for (let i = 0; i < noOfBytes; i++) {
13074
- this.view.setUint8(i, bytes[i]);
13075
- }
13076
- for (let i = n; i < BUFFER_SIZE; i++) {
13077
- this.view.setUint8(i, prefix);
13078
- }
13079
- }
13080
- /**
13081
- * @deprecated Use getU32 instead
13082
- */
13083
- getUnsigned() {
13084
- return this.u32[U32_INDEX];
13085
- }
13086
- /**
13087
- * @deprecated Use getI32 instead
13088
- */
13089
- getSigned() {
13090
- return this.i32[U32_INDEX];
13091
- }
13092
- getU32() {
13093
- return this.u32[U32_INDEX];
13094
- }
13095
- getI32() {
13096
- return this.i32[U32_INDEX];
13097
- }
13098
- getU64() {
13099
- return this.u64[U64_INDEX];
13131
+ registers;
13132
+ constructor(bytes) {
13133
+ this.bytes = bytes;
13134
+ this.registers = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
13100
13135
  }
13101
- getI64() {
13102
- return this.i64[U64_INDEX];
13136
+ /** Get U64 register value. */
13137
+ get(registerIndex) {
13138
+ return tryAsU64(this.registers.getBigUint64(registerIndex * REGISTER_BYTE_SIZE, true));
13103
13139
  }
13104
- getBytesAsLittleEndian() {
13105
- return this.bytes.subarray(0, IMMEDIATE_SIZE$1);
13140
+ /** Set U64 register value. */
13141
+ set(registerIndex, value) {
13142
+ this.registers.setBigUint64(registerIndex * REGISTER_BYTE_SIZE, value, true);
13106
13143
  }
13107
- getExtendedBytesAsLittleEndian() {
13144
+ /** Get all registers encoded into little-endian bytes. */
13145
+ getEncoded() {
13108
13146
  return this.bytes;
13109
13147
  }
13110
13148
  }
13111
13149
 
13112
- const MAX_REGISTER_INDEX = NO_OF_REGISTERS$1 - 1;
13113
- const MAX_LENGTH = 4;
13114
- class NibblesDecoder {
13115
- byte = new Int8Array(1);
13116
- setByte(byte) {
13117
- this.byte[0] = byte;
13118
- }
13119
- getHighNibble() {
13120
- return (this.byte[0] & 0xf0) >>> 4;
13121
- }
13122
- getLowNibble() {
13123
- return this.byte[0] & 0x0f;
13150
+ class ReturnValue {
13151
+ consumedGas;
13152
+ status;
13153
+ memorySlice;
13154
+ constructor(consumedGas, status, memorySlice) {
13155
+ this.consumedGas = consumedGas;
13156
+ this.status = status;
13157
+ this.memorySlice = memorySlice;
13158
+ check `
13159
+ ${(status === null && memorySlice !== null) || (status !== null && memorySlice === null)}
13160
+ 'status' and 'memorySlice' must not both be null or both be non-null — exactly one must be provided
13161
+ `;
13124
13162
  }
13125
- getHighNibbleAsRegisterIndex() {
13126
- return Math.min(this.getHighNibble(), MAX_REGISTER_INDEX);
13163
+ static fromStatus(consumedGas, status) {
13164
+ return new ReturnValue(consumedGas, status, null);
13127
13165
  }
13128
- getLowNibbleAsRegisterIndex() {
13129
- return Math.min(this.getLowNibble(), MAX_REGISTER_INDEX);
13166
+ static fromMemorySlice(consumedGas, memorySlice) {
13167
+ return new ReturnValue(consumedGas, null, memorySlice);
13130
13168
  }
13131
- getHighNibbleAsLength() {
13132
- return Math.min(this.getHighNibble(), MAX_LENGTH);
13169
+ hasMemorySlice() {
13170
+ return this.memorySlice instanceof Uint8Array && this.status === null;
13133
13171
  }
13134
- getLowNibbleAsLength() {
13135
- return Math.min(this.getLowNibble(), MAX_LENGTH);
13172
+ hasStatus() {
13173
+ return !this.hasMemorySlice();
13136
13174
  }
13137
13175
  }
13138
-
13139
- const IMMEDIATE_AND_OFFSET_MAX_LENGTH = 4;
13140
- class ArgsDecoder {
13141
- nibblesDecoder = new NibblesDecoder();
13142
- offsetDecoder = new ImmediateDecoder();
13143
- code = new Uint8Array();
13144
- mask = Mask.empty();
13145
- reset(code, mask) {
13146
- this.code = code;
13147
- this.mask = mask;
13176
+ class HostCalls {
13177
+ pvmInstanceManager;
13178
+ hostCalls;
13179
+ constructor(pvmInstanceManager, hostCalls) {
13180
+ this.pvmInstanceManager = pvmInstanceManager;
13181
+ this.hostCalls = hostCalls;
13148
13182
  }
13149
- fillArgs(pc, result) {
13150
- const nextInstructionDistance = 1 + this.mask.getNoOfBytesToNextInstruction(pc + 1);
13151
- result.noOfBytesToSkip = nextInstructionDistance;
13152
- switch (result.type) {
13153
- case ArgumentType.NO_ARGUMENTS:
13154
- break;
13155
- case ArgumentType.ONE_IMMEDIATE: {
13156
- const immediateLength = Math.min(IMMEDIATE_AND_OFFSET_MAX_LENGTH, nextInstructionDistance - 1);
13157
- const argsStartIndex = pc + 1;
13158
- result.immediateDecoder.setBytes(this.code.subarray(argsStartIndex, argsStartIndex + immediateLength));
13159
- break;
13160
- }
13161
- case ArgumentType.THREE_REGISTERS: {
13162
- const firstByte = this.code[pc + 1];
13163
- const secondByte = this.code[pc + 2];
13164
- this.nibblesDecoder.setByte(firstByte);
13165
- result.firstRegisterIndex = this.nibblesDecoder.getLowNibbleAsRegisterIndex();
13166
- result.secondRegisterIndex = this.nibblesDecoder.getHighNibbleAsRegisterIndex();
13167
- this.nibblesDecoder.setByte(secondByte);
13168
- result.thirdRegisterIndex = this.nibblesDecoder.getLowNibbleAsRegisterIndex();
13169
- break;
13170
- }
13171
- case ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE: {
13172
- const firstByte = this.code[pc + 1];
13173
- this.nibblesDecoder.setByte(firstByte);
13174
- result.firstRegisterIndex = this.nibblesDecoder.getLowNibbleAsRegisterIndex();
13175
- result.secondRegisterIndex = this.nibblesDecoder.getHighNibbleAsRegisterIndex();
13176
- const immediateLength = Math.min(IMMEDIATE_AND_OFFSET_MAX_LENGTH, Math.max(0, nextInstructionDistance - 2));
13177
- const immediateStartIndex = pc + 2;
13178
- const immediateEndIndex = immediateStartIndex + immediateLength;
13179
- result.immediateDecoder.setBytes(this.code.subarray(immediateStartIndex, immediateEndIndex));
13180
- break;
13181
- }
13182
- case ArgumentType.ONE_REGISTER_ONE_IMMEDIATE_ONE_OFFSET: {
13183
- const firstByte = this.code[pc + 1];
13184
- this.nibblesDecoder.setByte(firstByte);
13185
- result.registerIndex = this.nibblesDecoder.getLowNibbleAsRegisterIndex();
13186
- const immediateLength = this.nibblesDecoder.getHighNibbleAsLength();
13187
- const immediateStartIndex = pc + 2;
13188
- const immediateEndIndex = immediateStartIndex + immediateLength;
13189
- result.immediateDecoder.setBytes(this.code.subarray(immediateStartIndex, immediateEndIndex));
13190
- const offsetLength = Math.min(IMMEDIATE_AND_OFFSET_MAX_LENGTH, Math.max(0, nextInstructionDistance - 2 - immediateLength));
13191
- const offsetStartIndex = pc + 2 + immediateLength;
13192
- const offsetEndIndex = offsetStartIndex + offsetLength;
13193
- this.offsetDecoder.setBytes(this.code.subarray(offsetStartIndex, offsetEndIndex));
13194
- result.nextPc = pc + this.offsetDecoder.getSigned();
13195
- break;
13196
- }
13197
- case ArgumentType.TWO_REGISTERS_ONE_OFFSET: {
13198
- const firstByte = this.code[pc + 1];
13199
- this.nibblesDecoder.setByte(firstByte);
13200
- result.firstRegisterIndex = this.nibblesDecoder.getLowNibbleAsRegisterIndex();
13201
- result.secondRegisterIndex = this.nibblesDecoder.getHighNibbleAsRegisterIndex();
13202
- const offsetLength = Math.min(IMMEDIATE_AND_OFFSET_MAX_LENGTH, Math.max(0, nextInstructionDistance - 2));
13203
- const offsetStartIndex = pc + 2;
13204
- const offsetEndIndex = offsetStartIndex + offsetLength;
13205
- this.offsetDecoder.setBytes(this.code.subarray(offsetStartIndex, offsetEndIndex));
13206
- result.nextPc = pc + this.offsetDecoder.getSigned();
13207
- break;
13208
- }
13209
- case ArgumentType.TWO_REGISTERS: {
13210
- const firstByte = this.code[pc + 1];
13211
- this.nibblesDecoder.setByte(firstByte);
13212
- result.firstRegisterIndex = this.nibblesDecoder.getHighNibbleAsRegisterIndex();
13213
- result.secondRegisterIndex = this.nibblesDecoder.getLowNibbleAsRegisterIndex();
13214
- break;
13183
+ getReturnValue(status, pvmInstance) {
13184
+ const gasConsumed = pvmInstance.gas.used();
13185
+ if (status === Status.OOG) {
13186
+ return ReturnValue.fromStatus(gasConsumed, status);
13187
+ }
13188
+ if (status === Status.HALT) {
13189
+ const regs = new HostCallRegisters(pvmInstance.registers.getAllEncoded());
13190
+ const memory = new HostCallMemory(pvmInstance.memory);
13191
+ const address = regs.get(7);
13192
+ // NOTE we are taking the the lower U32 part of the register, hence it's safe.
13193
+ const length = Number(regs.get(8) & 0xffffffffn);
13194
+ const result = safeAllocUint8Array(length);
13195
+ const loadResult = memory.loadInto(result, address);
13196
+ if (loadResult.isError) {
13197
+ return ReturnValue.fromMemorySlice(gasConsumed, new Uint8Array());
13215
13198
  }
13216
- case ArgumentType.ONE_OFFSET: {
13217
- const offsetLength = Math.min(IMMEDIATE_AND_OFFSET_MAX_LENGTH, nextInstructionDistance - 1);
13218
- const offsetStartIndex = pc + 1;
13219
- const offsetEndIndex = offsetStartIndex + offsetLength;
13220
- const offsetBytes = this.code.subarray(offsetStartIndex, offsetEndIndex);
13221
- this.offsetDecoder.setBytes(offsetBytes);
13222
- const offsetValue = this.offsetDecoder.getSigned();
13223
- result.nextPc = pc + offsetValue;
13224
- break;
13199
+ return ReturnValue.fromMemorySlice(gasConsumed, result);
13200
+ }
13201
+ return ReturnValue.fromStatus(gasConsumed, Status.PANIC);
13202
+ }
13203
+ async execute(pvmInstance) {
13204
+ pvmInstance.runProgram();
13205
+ for (;;) {
13206
+ let status = pvmInstance.getStatus();
13207
+ if (status !== Status.HOST) {
13208
+ return this.getReturnValue(status, pvmInstance);
13225
13209
  }
13226
- case ArgumentType.ONE_REGISTER_ONE_IMMEDIATE: {
13227
- const firstByte = this.code[pc + 1];
13228
- this.nibblesDecoder.setByte(firstByte);
13229
- result.registerIndex = this.nibblesDecoder.getLowNibbleAsRegisterIndex();
13230
- const immediateLength = Math.min(IMMEDIATE_AND_OFFSET_MAX_LENGTH, Math.max(0, nextInstructionDistance - 2));
13231
- const immediateStartIndex = pc + 2;
13232
- const immediateEndIndex = immediateStartIndex + immediateLength;
13233
- const immediateBytes = this.code.subarray(immediateStartIndex, immediateEndIndex);
13234
- result.immediateDecoder.setBytes(immediateBytes);
13235
- break;
13210
+ check `
13211
+ ${pvmInstance.getExitParam() !== null}
13212
+ "We know that the exit param is not null, because the status is 'Status.HOST'
13213
+ `;
13214
+ const hostCallIndex = pvmInstance.getExitParam() ?? -1;
13215
+ const gas = pvmInstance.gas;
13216
+ const regs = new HostCallRegisters(pvmInstance.registers.getAllEncoded());
13217
+ const memory = new HostCallMemory(pvmInstance.memory);
13218
+ const index = tryAsHostCallIndex(hostCallIndex);
13219
+ const hostCall = this.hostCalls.get(index);
13220
+ const gasBefore = gas.get();
13221
+ // NOTE: `basicGasCost(regs)` function is for compatibility reasons: pre GP 0.7.2
13222
+ const basicGasCost = typeof hostCall.basicGasCost === "number" ? hostCall.basicGasCost : hostCall.basicGasCost(regs);
13223
+ const underflow = gas.sub(basicGasCost);
13224
+ const pcLog = `[PC: ${pvmInstance.getPC()}]`;
13225
+ if (underflow) {
13226
+ this.hostCalls.traceHostCall(`${pcLog} OOG`, index, hostCall, regs, gas.get());
13227
+ return ReturnValue.fromStatus(gas.used(), Status.OOG);
13236
13228
  }
13237
- case ArgumentType.TWO_IMMEDIATES: {
13238
- const firstByte = this.code[pc + 1];
13239
- this.nibblesDecoder.setByte(firstByte);
13240
- const firstImmediateLength = this.nibblesDecoder.getLowNibbleAsLength();
13241
- const firstImmediateStartIndex = pc + 2;
13242
- const firstImmediateEndIndex = firstImmediateStartIndex + firstImmediateLength;
13243
- const firstImmediateBytes = this.code.subarray(firstImmediateStartIndex, firstImmediateEndIndex);
13244
- result.firstImmediateDecoder.setBytes(firstImmediateBytes);
13245
- const secondImmediateLength = Math.min(IMMEDIATE_AND_OFFSET_MAX_LENGTH, Math.max(0, nextInstructionDistance - 2 - firstImmediateLength));
13246
- const secondImmediateStartIndex = firstImmediateEndIndex;
13247
- const secondImmediateEndIndex = secondImmediateStartIndex + secondImmediateLength;
13248
- const secondImmediateBytes = this.code.subarray(secondImmediateStartIndex, secondImmediateEndIndex);
13249
- result.secondImmediateDecoder.setBytes(secondImmediateBytes);
13250
- break;
13229
+ this.hostCalls.traceHostCall(`${pcLog} Invoking`, index, hostCall, regs, gasBefore);
13230
+ const result = await hostCall.execute(gas, regs, memory);
13231
+ this.hostCalls.traceHostCall(result === undefined ? `${pcLog} Result` : `${pcLog} Status(${PvmExecution[result]})`, index, hostCall, regs, gas.get());
13232
+ pvmInstance.registers.setAllEncoded(regs.getEncoded());
13233
+ if (result === PvmExecution.Halt) {
13234
+ status = Status.HALT;
13235
+ return this.getReturnValue(status, pvmInstance);
13251
13236
  }
13252
- case ArgumentType.ONE_REGISTER_TWO_IMMEDIATES: {
13253
- const firstByte = this.code[pc + 1];
13254
- this.nibblesDecoder.setByte(firstByte);
13255
- result.registerIndex = this.nibblesDecoder.getLowNibbleAsRegisterIndex();
13256
- const firstImmediateLength = this.nibblesDecoder.getHighNibbleAsLength();
13257
- const firstImmediateStartIndex = pc + 2;
13258
- const firstImmediateEndIndex = firstImmediateStartIndex + firstImmediateLength;
13259
- const firstImmediateBytes = this.code.subarray(firstImmediateStartIndex, firstImmediateEndIndex);
13260
- result.firstImmediateDecoder.setBytes(firstImmediateBytes);
13261
- const secondImmediateLength = Math.min(IMMEDIATE_AND_OFFSET_MAX_LENGTH, Math.max(0, nextInstructionDistance - 2 - firstImmediateLength));
13262
- const secondImmediateStartIndex = firstImmediateEndIndex;
13263
- const secondImmediateEndIndex = secondImmediateStartIndex + secondImmediateLength;
13264
- const secondImmediateBytes = this.code.subarray(secondImmediateStartIndex, secondImmediateEndIndex);
13265
- result.secondImmediateDecoder.setBytes(secondImmediateBytes);
13266
- break;
13237
+ if (result === PvmExecution.Panic) {
13238
+ status = Status.PANIC;
13239
+ return this.getReturnValue(status, pvmInstance);
13267
13240
  }
13268
- case ArgumentType.TWO_REGISTERS_TWO_IMMEDIATES: {
13269
- const firstByte = this.code[pc + 1];
13270
- this.nibblesDecoder.setByte(firstByte);
13271
- result.firstRegisterIndex = this.nibblesDecoder.getLowNibbleAsRegisterIndex();
13272
- result.secondRegisterIndex = this.nibblesDecoder.getHighNibbleAsRegisterIndex();
13273
- const secondByte = this.code[pc + 2];
13274
- this.nibblesDecoder.setByte(secondByte);
13275
- const firstImmediateLength = this.nibblesDecoder.getLowNibbleAsLength();
13276
- const firstImmediateStartIndex = pc + 3;
13277
- const firstImmediateEndIndex = firstImmediateStartIndex + firstImmediateLength;
13278
- const firstImmediateBytes = this.code.subarray(firstImmediateStartIndex, firstImmediateEndIndex);
13279
- result.firstImmediateDecoder.setBytes(firstImmediateBytes);
13280
- const secondImmediateLength = Math.min(IMMEDIATE_AND_OFFSET_MAX_LENGTH, Math.max(0, nextInstructionDistance - 3 - firstImmediateLength));
13281
- const secondImmediateStartIndex = firstImmediateEndIndex;
13282
- const secondImmediateEndIndex = secondImmediateStartIndex + secondImmediateLength;
13283
- const secondImmediateBytes = this.code.subarray(secondImmediateStartIndex, secondImmediateEndIndex);
13284
- result.secondImmediateDecoder.setBytes(secondImmediateBytes);
13285
- break;
13241
+ if (result === PvmExecution.OOG) {
13242
+ status = Status.OOG;
13243
+ return this.getReturnValue(status, pvmInstance);
13286
13244
  }
13287
- case ArgumentType.ONE_REGISTER_ONE_EXTENDED_WIDTH_IMMEDIATE: {
13288
- const firstByte = this.code[pc + 1];
13289
- this.nibblesDecoder.setByte(firstByte);
13290
- result.registerIndex = this.nibblesDecoder.getLowNibbleAsRegisterIndex();
13291
- const immediateStartIndex = pc + 2;
13292
- const immediateEndIndex = immediateStartIndex + 8;
13293
- const immediateBytes = this.code.subarray(immediateStartIndex, immediateEndIndex);
13294
- result.immediateDecoder.setBytes(immediateBytes);
13295
- break;
13245
+ if (result === undefined) {
13246
+ pvmInstance.runProgram();
13247
+ status = pvmInstance.getStatus();
13248
+ continue;
13296
13249
  }
13250
+ assertNever(result);
13251
+ }
13252
+ }
13253
+ async runProgram(program, args, initialPc, initialGas) {
13254
+ const pvmInstance = await this.pvmInstanceManager.getInstance();
13255
+ pvmInstance.resetJam(program, args, initialPc, initialGas);
13256
+ try {
13257
+ return await this.execute(pvmInstance);
13258
+ }
13259
+ finally {
13260
+ this.pvmInstanceManager.releaseInstance(pvmInstance);
13297
13261
  }
13298
13262
  }
13299
13263
  }
13300
13264
 
13301
- const IMMEDIATE_SIZE = 8;
13302
- class ExtendedWitdthImmediateDecoder {
13303
- unsignedImmediate;
13304
- bytes;
13305
- constructor() {
13306
- const buffer = new ArrayBuffer(IMMEDIATE_SIZE);
13307
- this.unsignedImmediate = new BigUint64Array(buffer);
13308
- this.bytes = new Uint8Array(buffer);
13309
- }
13310
- setBytes(bytes) {
13311
- let i = 0;
13312
- for (; i < bytes.length; i++) {
13313
- this.bytes[i] = bytes[i];
13314
- }
13315
- for (; i < IMMEDIATE_SIZE; i++) {
13316
- this.bytes[i] = 0;
13265
+ const logger$3 = Logger.new(undefined, "host-calls-pvm");
13266
+ /** Container for all available host calls. */
13267
+ class HostCallsManager {
13268
+ hostCalls = new Map();
13269
+ missing;
13270
+ constructor({ missing, handlers = [], }) {
13271
+ this.missing = missing;
13272
+ for (const handler of handlers) {
13273
+ check `${this.hostCalls.get(handler.index) === undefined} Overwriting host call handler at index ${handler.index}`;
13274
+ this.hostCalls.set(handler.index, handler);
13317
13275
  }
13318
13276
  }
13319
- getValue() {
13320
- return this.unsignedImmediate[0];
13277
+ /** Get a host call by index. */
13278
+ get(hostCallIndex) {
13279
+ return this.hostCalls.get(hostCallIndex) ?? this.missing;
13321
13280
  }
13322
- getBytesAsLittleEndian() {
13323
- return this.bytes.subarray(0, IMMEDIATE_SIZE);
13281
+ traceHostCall(context, hostCallIndex, hostCallHandler, registers, gas) {
13282
+ const { currentServiceId } = hostCallHandler;
13283
+ const requested = hostCallIndex !== hostCallHandler.index ? ` (${hostCallIndex})` : "";
13284
+ const name = `${hostCallHandler.constructor.name}:${hostCallHandler.index}`;
13285
+ const registerValues = hostCallHandler.tracedRegisters
13286
+ .map((idx) => [idx.toString().padStart(2, "0"), registers.get(idx)])
13287
+ .filter((v) => v[1] !== 0n)
13288
+ .map(([idx, value]) => {
13289
+ return `r${idx}=${value} (0x${value.toString(16)})`;
13290
+ })
13291
+ .join(", ");
13292
+ logger$3.insane `[${currentServiceId}] ${context} ${name}${requested}. Gas: ${gas}. Regs: ${registerValues}.`;
13324
13293
  }
13325
13294
  }
13326
13295
 
13327
- const ARGUMENT_TYPE_LENGTH = Object.keys(ArgumentType).length / 2;
13328
- const createResults = () => {
13329
- const results = new Array(ARGUMENT_TYPE_LENGTH);
13330
- results[ArgumentType.NO_ARGUMENTS] = {
13331
- type: ArgumentType.NO_ARGUMENTS,
13332
- noOfBytesToSkip: 1,
13333
- };
13334
- results[ArgumentType.ONE_IMMEDIATE] = {
13335
- type: ArgumentType.ONE_IMMEDIATE,
13336
- noOfBytesToSkip: 1,
13337
- immediateDecoder: new ImmediateDecoder(),
13338
- };
13339
- results[ArgumentType.TWO_REGISTERS] = {
13340
- type: ArgumentType.TWO_REGISTERS,
13341
- noOfBytesToSkip: 1,
13342
- firstRegisterIndex: 0,
13343
- secondRegisterIndex: 0,
13344
- };
13345
- results[ArgumentType.THREE_REGISTERS] = {
13346
- type: ArgumentType.THREE_REGISTERS,
13347
- noOfBytesToSkip: 1,
13348
- firstRegisterIndex: 0,
13349
- secondRegisterIndex: 0,
13350
- thirdRegisterIndex: 0,
13351
- };
13352
- results[ArgumentType.ONE_REGISTER_ONE_IMMEDIATE_ONE_OFFSET] = {
13353
- type: ArgumentType.ONE_REGISTER_ONE_IMMEDIATE_ONE_OFFSET,
13354
- noOfBytesToSkip: 1,
13355
- registerIndex: 0,
13356
- immediateDecoder: new ImmediateDecoder(),
13357
- nextPc: 0,
13358
- };
13359
- results[ArgumentType.TWO_REGISTERS_ONE_OFFSET] = {
13360
- type: ArgumentType.TWO_REGISTERS_ONE_OFFSET,
13361
- noOfBytesToSkip: 1,
13362
- firstRegisterIndex: 0,
13363
- secondRegisterIndex: 0,
13364
- nextPc: 0,
13365
- };
13366
- results[ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE] = {
13367
- type: ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE,
13368
- noOfBytesToSkip: 1,
13369
- firstRegisterIndex: 0,
13370
- secondRegisterIndex: 0,
13371
- immediateDecoder: new ImmediateDecoder(),
13372
- };
13373
- results[ArgumentType.ONE_REGISTER_ONE_IMMEDIATE] = {
13374
- type: ArgumentType.ONE_REGISTER_ONE_IMMEDIATE,
13375
- noOfBytesToSkip: 1,
13376
- registerIndex: 0,
13377
- immediateDecoder: new ImmediateDecoder(),
13378
- };
13379
- results[ArgumentType.ONE_REGISTER_TWO_IMMEDIATES] = {
13380
- type: ArgumentType.ONE_REGISTER_TWO_IMMEDIATES,
13381
- noOfBytesToSkip: 1,
13382
- registerIndex: 0,
13383
- firstImmediateDecoder: new ImmediateDecoder(),
13384
- secondImmediateDecoder: new ImmediateDecoder(),
13385
- };
13386
- results[ArgumentType.ONE_OFFSET] = {
13387
- type: ArgumentType.ONE_OFFSET,
13388
- noOfBytesToSkip: 1,
13389
- nextPc: 0,
13390
- };
13391
- results[ArgumentType.TWO_IMMEDIATES] = {
13392
- type: ArgumentType.TWO_IMMEDIATES,
13393
- noOfBytesToSkip: 1,
13394
- firstImmediateDecoder: new ImmediateDecoder(),
13395
- secondImmediateDecoder: new ImmediateDecoder(),
13396
- };
13397
- results[ArgumentType.TWO_REGISTERS_TWO_IMMEDIATES] = {
13398
- type: ArgumentType.TWO_REGISTERS_TWO_IMMEDIATES,
13399
- noOfBytesToSkip: 1,
13400
- firstImmediateDecoder: new ImmediateDecoder(),
13401
- secondImmediateDecoder: new ImmediateDecoder(),
13402
- firstRegisterIndex: 0,
13403
- secondRegisterIndex: 0,
13404
- };
13405
- results[ArgumentType.ONE_REGISTER_ONE_EXTENDED_WIDTH_IMMEDIATE] = {
13406
- type: ArgumentType.ONE_REGISTER_ONE_EXTENDED_WIDTH_IMMEDIATE,
13407
- noOfBytesToSkip: 9,
13408
- registerIndex: 0,
13409
- immediateDecoder: new ExtendedWitdthImmediateDecoder(),
13410
- };
13411
- return results;
13296
+ /** Create a new gas counter instance depending on the gas value. */
13297
+ function gasCounter(gas) {
13298
+ return new GasCounterU64(tryAsU64(gas));
13299
+ }
13300
+ class GasCounterU64 {
13301
+ gas;
13302
+ initialGas;
13303
+ constructor(gas) {
13304
+ this.gas = gas;
13305
+ this.initialGas = tryAsGas(gas);
13306
+ }
13307
+ set(g) {
13308
+ this.gas = tryAsU64(g);
13309
+ }
13310
+ get() {
13311
+ return tryAsGas(this.gas);
13312
+ }
13313
+ sub(g) {
13314
+ const result = this.gas - tryAsU64(g);
13315
+ if (result >= 0n) {
13316
+ this.gas = tryAsU64(result);
13317
+ return false;
13318
+ }
13319
+ this.gas = tryAsU64(0n);
13320
+ return true;
13321
+ }
13322
+ used() {
13323
+ const gasConsumed = tryAsU64(this.initialGas) - this.gas;
13324
+ // In we have less than zero left we assume that all gas has been consumed.
13325
+ if (gasConsumed < 0) {
13326
+ return this.initialGas;
13327
+ }
13328
+ return tryAsGas(gasConsumed);
13329
+ }
13330
+ }
13331
+
13332
+ const tryAsMemoryIndex = (index) => {
13333
+ check `${index >= 0 && index <= MAX_MEMORY_INDEX} Incorrect memory index: ${index}!`;
13334
+ return asOpaqueType(index);
13335
+ };
13336
+ const tryAsSbrkIndex = (index) => {
13337
+ check `${index >= 0 && index <= MAX_MEMORY_INDEX + 1} Incorrect sbrk index: ${index}!`;
13338
+ return asOpaqueType(index);
13412
13339
  };
13413
13340
 
13414
- var Instruction;
13415
- (function (Instruction) {
13416
- Instruction[Instruction["TRAP"] = 0] = "TRAP";
13417
- Instruction[Instruction["FALLTHROUGH"] = 1] = "FALLTHROUGH";
13418
- Instruction[Instruction["ECALLI"] = 10] = "ECALLI";
13419
- Instruction[Instruction["LOAD_IMM_64"] = 20] = "LOAD_IMM_64";
13420
- Instruction[Instruction["STORE_IMM_U8"] = 30] = "STORE_IMM_U8";
13421
- Instruction[Instruction["STORE_IMM_U16"] = 31] = "STORE_IMM_U16";
13422
- Instruction[Instruction["STORE_IMM_U32"] = 32] = "STORE_IMM_U32";
13423
- Instruction[Instruction["STORE_IMM_U64"] = 33] = "STORE_IMM_U64";
13424
- Instruction[Instruction["JUMP"] = 40] = "JUMP";
13425
- Instruction[Instruction["JUMP_IND"] = 50] = "JUMP_IND";
13426
- Instruction[Instruction["LOAD_IMM"] = 51] = "LOAD_IMM";
13427
- Instruction[Instruction["LOAD_U8"] = 52] = "LOAD_U8";
13428
- Instruction[Instruction["LOAD_I8"] = 53] = "LOAD_I8";
13429
- Instruction[Instruction["LOAD_U16"] = 54] = "LOAD_U16";
13430
- Instruction[Instruction["LOAD_I16"] = 55] = "LOAD_I16";
13431
- Instruction[Instruction["LOAD_U32"] = 56] = "LOAD_U32";
13432
- Instruction[Instruction["LOAD_I32"] = 57] = "LOAD_I32";
13433
- Instruction[Instruction["LOAD_U64"] = 58] = "LOAD_U64";
13434
- Instruction[Instruction["STORE_U8"] = 59] = "STORE_U8";
13435
- Instruction[Instruction["STORE_U16"] = 60] = "STORE_U16";
13436
- Instruction[Instruction["STORE_U32"] = 61] = "STORE_U32";
13437
- Instruction[Instruction["STORE_U64"] = 62] = "STORE_U64";
13438
- Instruction[Instruction["STORE_IMM_IND_U8"] = 70] = "STORE_IMM_IND_U8";
13439
- Instruction[Instruction["STORE_IMM_IND_U16"] = 71] = "STORE_IMM_IND_U16";
13440
- Instruction[Instruction["STORE_IMM_IND_U32"] = 72] = "STORE_IMM_IND_U32";
13441
- Instruction[Instruction["STORE_IMM_IND_U64"] = 73] = "STORE_IMM_IND_U64";
13442
- Instruction[Instruction["LOAD_IMM_JUMP"] = 80] = "LOAD_IMM_JUMP";
13443
- Instruction[Instruction["BRANCH_EQ_IMM"] = 81] = "BRANCH_EQ_IMM";
13444
- Instruction[Instruction["BRANCH_NE_IMM"] = 82] = "BRANCH_NE_IMM";
13445
- Instruction[Instruction["BRANCH_LT_U_IMM"] = 83] = "BRANCH_LT_U_IMM";
13446
- Instruction[Instruction["BRANCH_LE_U_IMM"] = 84] = "BRANCH_LE_U_IMM";
13447
- Instruction[Instruction["BRANCH_GE_U_IMM"] = 85] = "BRANCH_GE_U_IMM";
13448
- Instruction[Instruction["BRANCH_GT_U_IMM"] = 86] = "BRANCH_GT_U_IMM";
13449
- Instruction[Instruction["BRANCH_LT_S_IMM"] = 87] = "BRANCH_LT_S_IMM";
13450
- Instruction[Instruction["BRANCH_LE_S_IMM"] = 88] = "BRANCH_LE_S_IMM";
13451
- Instruction[Instruction["BRANCH_GE_S_IMM"] = 89] = "BRANCH_GE_S_IMM";
13452
- Instruction[Instruction["BRANCH_GT_S_IMM"] = 90] = "BRANCH_GT_S_IMM";
13453
- Instruction[Instruction["MOVE_REG"] = 100] = "MOVE_REG";
13454
- Instruction[Instruction["SBRK"] = 101] = "SBRK";
13455
- Instruction[Instruction["COUNT_SET_BITS_64"] = 102] = "COUNT_SET_BITS_64";
13456
- Instruction[Instruction["COUNT_SET_BITS_32"] = 103] = "COUNT_SET_BITS_32";
13457
- Instruction[Instruction["LEADING_ZERO_BITS_64"] = 104] = "LEADING_ZERO_BITS_64";
13458
- Instruction[Instruction["LEADING_ZERO_BITS_32"] = 105] = "LEADING_ZERO_BITS_32";
13459
- Instruction[Instruction["TRAILING_ZERO_BITS_64"] = 106] = "TRAILING_ZERO_BITS_64";
13460
- Instruction[Instruction["TRAILING_ZERO_BITS_32"] = 107] = "TRAILING_ZERO_BITS_32";
13461
- Instruction[Instruction["SIGN_EXTEND_8"] = 108] = "SIGN_EXTEND_8";
13462
- Instruction[Instruction["SIGN_EXTEND_16"] = 109] = "SIGN_EXTEND_16";
13463
- Instruction[Instruction["ZERO_EXTEND_16"] = 110] = "ZERO_EXTEND_16";
13464
- Instruction[Instruction["REVERSE_BYTES"] = 111] = "REVERSE_BYTES";
13465
- Instruction[Instruction["STORE_IND_U8"] = 120] = "STORE_IND_U8";
13466
- Instruction[Instruction["STORE_IND_U16"] = 121] = "STORE_IND_U16";
13467
- Instruction[Instruction["STORE_IND_U32"] = 122] = "STORE_IND_U32";
13468
- Instruction[Instruction["STORE_IND_U64"] = 123] = "STORE_IND_U64";
13469
- Instruction[Instruction["LOAD_IND_U8"] = 124] = "LOAD_IND_U8";
13470
- Instruction[Instruction["LOAD_IND_I8"] = 125] = "LOAD_IND_I8";
13471
- Instruction[Instruction["LOAD_IND_U16"] = 126] = "LOAD_IND_U16";
13472
- Instruction[Instruction["LOAD_IND_I16"] = 127] = "LOAD_IND_I16";
13473
- Instruction[Instruction["LOAD_IND_U32"] = 128] = "LOAD_IND_U32";
13474
- Instruction[Instruction["LOAD_IND_I32"] = 129] = "LOAD_IND_I32";
13475
- Instruction[Instruction["LOAD_IND_U64"] = 130] = "LOAD_IND_U64";
13476
- Instruction[Instruction["ADD_IMM_32"] = 131] = "ADD_IMM_32";
13477
- Instruction[Instruction["AND_IMM"] = 132] = "AND_IMM";
13478
- Instruction[Instruction["XOR_IMM"] = 133] = "XOR_IMM";
13479
- Instruction[Instruction["OR_IMM"] = 134] = "OR_IMM";
13480
- Instruction[Instruction["MUL_IMM_32"] = 135] = "MUL_IMM_32";
13481
- Instruction[Instruction["SET_LT_U_IMM"] = 136] = "SET_LT_U_IMM";
13482
- Instruction[Instruction["SET_LT_S_IMM"] = 137] = "SET_LT_S_IMM";
13483
- Instruction[Instruction["SHLO_L_IMM_32"] = 138] = "SHLO_L_IMM_32";
13484
- Instruction[Instruction["SHLO_R_IMM_32"] = 139] = "SHLO_R_IMM_32";
13485
- Instruction[Instruction["SHAR_R_IMM_32"] = 140] = "SHAR_R_IMM_32";
13486
- Instruction[Instruction["NEG_ADD_IMM_32"] = 141] = "NEG_ADD_IMM_32";
13487
- Instruction[Instruction["SET_GT_U_IMM"] = 142] = "SET_GT_U_IMM";
13488
- Instruction[Instruction["SET_GT_S_IMM"] = 143] = "SET_GT_S_IMM";
13489
- Instruction[Instruction["SHLO_L_IMM_ALT_32"] = 144] = "SHLO_L_IMM_ALT_32";
13490
- Instruction[Instruction["SHLO_R_IMM_ALT_32"] = 145] = "SHLO_R_IMM_ALT_32";
13491
- Instruction[Instruction["SHAR_R_IMM_ALT_32"] = 146] = "SHAR_R_IMM_ALT_32";
13492
- Instruction[Instruction["CMOV_IZ_IMM"] = 147] = "CMOV_IZ_IMM";
13493
- Instruction[Instruction["CMOV_NZ_IMM"] = 148] = "CMOV_NZ_IMM";
13494
- Instruction[Instruction["ADD_IMM_64"] = 149] = "ADD_IMM_64";
13495
- Instruction[Instruction["MUL_IMM_64"] = 150] = "MUL_IMM_64";
13496
- Instruction[Instruction["SHLO_L_IMM_64"] = 151] = "SHLO_L_IMM_64";
13497
- Instruction[Instruction["SHLO_R_IMM_64"] = 152] = "SHLO_R_IMM_64";
13498
- Instruction[Instruction["SHAR_R_IMM_64"] = 153] = "SHAR_R_IMM_64";
13499
- Instruction[Instruction["NEG_ADD_IMM_64"] = 154] = "NEG_ADD_IMM_64";
13500
- Instruction[Instruction["SHLO_L_IMM_ALT_64"] = 155] = "SHLO_L_IMM_ALT_64";
13501
- Instruction[Instruction["SHLO_R_IMM_ALT_64"] = 156] = "SHLO_R_IMM_ALT_64";
13502
- Instruction[Instruction["SHAR_R_IMM_ALT_64"] = 157] = "SHAR_R_IMM_ALT_64";
13503
- Instruction[Instruction["ROT_R_64_IMM"] = 158] = "ROT_R_64_IMM";
13504
- Instruction[Instruction["ROT_R_64_IMM_ALT"] = 159] = "ROT_R_64_IMM_ALT";
13505
- Instruction[Instruction["ROT_R_32_IMM"] = 160] = "ROT_R_32_IMM";
13506
- Instruction[Instruction["ROT_R_32_IMM_ALT"] = 161] = "ROT_R_32_IMM_ALT";
13507
- Instruction[Instruction["BRANCH_EQ"] = 170] = "BRANCH_EQ";
13508
- Instruction[Instruction["BRANCH_NE"] = 171] = "BRANCH_NE";
13509
- Instruction[Instruction["BRANCH_LT_U"] = 172] = "BRANCH_LT_U";
13510
- Instruction[Instruction["BRANCH_LT_S"] = 173] = "BRANCH_LT_S";
13511
- Instruction[Instruction["BRANCH_GE_U"] = 174] = "BRANCH_GE_U";
13512
- Instruction[Instruction["BRANCH_GE_S"] = 175] = "BRANCH_GE_S";
13513
- Instruction[Instruction["LOAD_IMM_JUMP_IND"] = 180] = "LOAD_IMM_JUMP_IND";
13514
- Instruction[Instruction["ADD_32"] = 190] = "ADD_32";
13515
- Instruction[Instruction["SUB_32"] = 191] = "SUB_32";
13516
- Instruction[Instruction["MUL_32"] = 192] = "MUL_32";
13517
- Instruction[Instruction["DIV_U_32"] = 193] = "DIV_U_32";
13518
- Instruction[Instruction["DIV_S_32"] = 194] = "DIV_S_32";
13519
- Instruction[Instruction["REM_U_32"] = 195] = "REM_U_32";
13520
- Instruction[Instruction["REM_S_32"] = 196] = "REM_S_32";
13521
- Instruction[Instruction["SHLO_L_32"] = 197] = "SHLO_L_32";
13522
- Instruction[Instruction["SHLO_R_32"] = 198] = "SHLO_R_32";
13523
- Instruction[Instruction["SHAR_R_32"] = 199] = "SHAR_R_32";
13524
- Instruction[Instruction["ADD_64"] = 200] = "ADD_64";
13525
- Instruction[Instruction["SUB_64"] = 201] = "SUB_64";
13526
- Instruction[Instruction["MUL_64"] = 202] = "MUL_64";
13527
- Instruction[Instruction["DIV_U_64"] = 203] = "DIV_U_64";
13528
- Instruction[Instruction["DIV_S_64"] = 204] = "DIV_S_64";
13529
- Instruction[Instruction["REM_U_64"] = 205] = "REM_U_64";
13530
- Instruction[Instruction["REM_S_64"] = 206] = "REM_S_64";
13531
- Instruction[Instruction["SHLO_L_64"] = 207] = "SHLO_L_64";
13532
- Instruction[Instruction["SHLO_R_64"] = 208] = "SHLO_R_64";
13533
- Instruction[Instruction["SHAR_R_64"] = 209] = "SHAR_R_64";
13534
- Instruction[Instruction["AND"] = 210] = "AND";
13535
- Instruction[Instruction["XOR"] = 211] = "XOR";
13536
- Instruction[Instruction["OR"] = 212] = "OR";
13537
- Instruction[Instruction["MUL_UPPER_S_S"] = 213] = "MUL_UPPER_S_S";
13538
- Instruction[Instruction["MUL_UPPER_U_U"] = 214] = "MUL_UPPER_U_U";
13539
- Instruction[Instruction["MUL_UPPER_S_U"] = 215] = "MUL_UPPER_S_U";
13540
- Instruction[Instruction["SET_LT_U"] = 216] = "SET_LT_U";
13541
- Instruction[Instruction["SET_LT_S"] = 217] = "SET_LT_S";
13542
- Instruction[Instruction["CMOV_IZ"] = 218] = "CMOV_IZ";
13543
- Instruction[Instruction["CMOV_NZ"] = 219] = "CMOV_NZ";
13544
- Instruction[Instruction["ROT_L_64"] = 220] = "ROT_L_64";
13545
- Instruction[Instruction["ROT_L_32"] = 221] = "ROT_L_32";
13546
- Instruction[Instruction["ROT_R_64"] = 222] = "ROT_R_64";
13547
- Instruction[Instruction["ROT_R_32"] = 223] = "ROT_R_32";
13548
- Instruction[Instruction["AND_INV"] = 224] = "AND_INV";
13549
- Instruction[Instruction["OR_INV"] = 225] = "OR_INV";
13550
- Instruction[Instruction["XNOR"] = 226] = "XNOR";
13551
- Instruction[Instruction["MAX"] = 227] = "MAX";
13552
- Instruction[Instruction["MAX_U"] = 228] = "MAX_U";
13553
- Instruction[Instruction["MIN"] = 229] = "MIN";
13554
- Instruction[Instruction["MIN_U"] = 230] = "MIN_U";
13555
- })(Instruction || (Instruction = {}));
13556
- const HIGHEST_INSTRUCTION_NUMBER = Instruction.MIN_U;
13557
-
13558
- const instructionArgumentTypeMap = (() => {
13559
- const instructionArgumentTypeMap = new Array(HIGHEST_INSTRUCTION_NUMBER + 1);
13560
- instructionArgumentTypeMap[Instruction.TRAP] = ArgumentType.NO_ARGUMENTS;
13561
- instructionArgumentTypeMap[Instruction.FALLTHROUGH] = ArgumentType.NO_ARGUMENTS;
13562
- instructionArgumentTypeMap[Instruction.ECALLI] = ArgumentType.ONE_IMMEDIATE;
13563
- instructionArgumentTypeMap[Instruction.LOAD_IMM_64] = ArgumentType.ONE_REGISTER_ONE_EXTENDED_WIDTH_IMMEDIATE;
13564
- instructionArgumentTypeMap[Instruction.STORE_IMM_U8] = ArgumentType.TWO_IMMEDIATES;
13565
- instructionArgumentTypeMap[Instruction.STORE_IMM_U16] = ArgumentType.TWO_IMMEDIATES;
13566
- instructionArgumentTypeMap[Instruction.STORE_IMM_U32] = ArgumentType.TWO_IMMEDIATES;
13567
- instructionArgumentTypeMap[Instruction.STORE_IMM_U64] = ArgumentType.TWO_IMMEDIATES;
13568
- instructionArgumentTypeMap[Instruction.JUMP] = ArgumentType.ONE_OFFSET;
13569
- instructionArgumentTypeMap[Instruction.JUMP_IND] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE;
13570
- instructionArgumentTypeMap[Instruction.LOAD_IMM] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE;
13571
- instructionArgumentTypeMap[Instruction.LOAD_U8] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE;
13572
- instructionArgumentTypeMap[Instruction.LOAD_I8] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE;
13573
- instructionArgumentTypeMap[Instruction.LOAD_U16] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE;
13574
- instructionArgumentTypeMap[Instruction.LOAD_I16] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE;
13575
- instructionArgumentTypeMap[Instruction.LOAD_U32] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE;
13576
- instructionArgumentTypeMap[Instruction.LOAD_I32] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE;
13577
- instructionArgumentTypeMap[Instruction.LOAD_U64] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE;
13578
- instructionArgumentTypeMap[Instruction.STORE_U8] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE;
13579
- instructionArgumentTypeMap[Instruction.STORE_U16] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE;
13580
- instructionArgumentTypeMap[Instruction.STORE_U32] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE;
13581
- instructionArgumentTypeMap[Instruction.STORE_U64] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE;
13582
- instructionArgumentTypeMap[Instruction.STORE_IMM_IND_U8] = ArgumentType.ONE_REGISTER_TWO_IMMEDIATES;
13583
- instructionArgumentTypeMap[Instruction.STORE_IMM_IND_U16] = ArgumentType.ONE_REGISTER_TWO_IMMEDIATES;
13584
- instructionArgumentTypeMap[Instruction.STORE_IMM_IND_U32] = ArgumentType.ONE_REGISTER_TWO_IMMEDIATES;
13585
- instructionArgumentTypeMap[Instruction.STORE_IMM_IND_U64] = ArgumentType.ONE_REGISTER_TWO_IMMEDIATES;
13586
- instructionArgumentTypeMap[Instruction.LOAD_IMM_JUMP] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE_ONE_OFFSET;
13587
- instructionArgumentTypeMap[Instruction.BRANCH_EQ_IMM] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE_ONE_OFFSET;
13588
- instructionArgumentTypeMap[Instruction.BRANCH_NE_IMM] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE_ONE_OFFSET;
13589
- instructionArgumentTypeMap[Instruction.BRANCH_LT_U_IMM] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE_ONE_OFFSET;
13590
- instructionArgumentTypeMap[Instruction.BRANCH_LE_U_IMM] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE_ONE_OFFSET;
13591
- instructionArgumentTypeMap[Instruction.BRANCH_GE_U_IMM] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE_ONE_OFFSET;
13592
- instructionArgumentTypeMap[Instruction.BRANCH_GT_U_IMM] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE_ONE_OFFSET;
13593
- instructionArgumentTypeMap[Instruction.BRANCH_LT_S_IMM] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE_ONE_OFFSET;
13594
- instructionArgumentTypeMap[Instruction.BRANCH_LE_S_IMM] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE_ONE_OFFSET;
13595
- instructionArgumentTypeMap[Instruction.BRANCH_GE_S_IMM] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE_ONE_OFFSET;
13596
- instructionArgumentTypeMap[Instruction.BRANCH_GT_S_IMM] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE_ONE_OFFSET;
13597
- instructionArgumentTypeMap[Instruction.MOVE_REG] = ArgumentType.TWO_REGISTERS;
13598
- instructionArgumentTypeMap[Instruction.SBRK] = ArgumentType.TWO_REGISTERS;
13599
- instructionArgumentTypeMap[Instruction.COUNT_SET_BITS_64] = ArgumentType.TWO_REGISTERS;
13600
- instructionArgumentTypeMap[Instruction.COUNT_SET_BITS_32] = ArgumentType.TWO_REGISTERS;
13601
- instructionArgumentTypeMap[Instruction.LEADING_ZERO_BITS_64] = ArgumentType.TWO_REGISTERS;
13602
- instructionArgumentTypeMap[Instruction.LEADING_ZERO_BITS_32] = ArgumentType.TWO_REGISTERS;
13603
- instructionArgumentTypeMap[Instruction.TRAILING_ZERO_BITS_64] = ArgumentType.TWO_REGISTERS;
13604
- instructionArgumentTypeMap[Instruction.TRAILING_ZERO_BITS_32] = ArgumentType.TWO_REGISTERS;
13605
- instructionArgumentTypeMap[Instruction.SIGN_EXTEND_8] = ArgumentType.TWO_REGISTERS;
13606
- instructionArgumentTypeMap[Instruction.SIGN_EXTEND_16] = ArgumentType.TWO_REGISTERS;
13607
- instructionArgumentTypeMap[Instruction.ZERO_EXTEND_16] = ArgumentType.TWO_REGISTERS;
13608
- instructionArgumentTypeMap[Instruction.REVERSE_BYTES] = ArgumentType.TWO_REGISTERS;
13609
- instructionArgumentTypeMap[Instruction.STORE_IND_U8] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
13610
- instructionArgumentTypeMap[Instruction.STORE_IND_U16] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
13611
- instructionArgumentTypeMap[Instruction.STORE_IND_U32] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
13612
- instructionArgumentTypeMap[Instruction.STORE_IND_U64] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
13613
- instructionArgumentTypeMap[Instruction.LOAD_IND_U8] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
13614
- instructionArgumentTypeMap[Instruction.LOAD_IND_I8] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
13615
- instructionArgumentTypeMap[Instruction.LOAD_IND_U16] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
13616
- instructionArgumentTypeMap[Instruction.LOAD_IND_I16] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
13617
- instructionArgumentTypeMap[Instruction.LOAD_IND_U32] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
13618
- instructionArgumentTypeMap[Instruction.LOAD_IND_I32] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
13619
- instructionArgumentTypeMap[Instruction.LOAD_IND_U64] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
13620
- instructionArgumentTypeMap[Instruction.ADD_IMM_32] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
13621
- instructionArgumentTypeMap[Instruction.ADD_IMM_64] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
13622
- instructionArgumentTypeMap[Instruction.AND_IMM] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
13623
- instructionArgumentTypeMap[Instruction.XOR_IMM] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
13624
- instructionArgumentTypeMap[Instruction.OR_IMM] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
13625
- instructionArgumentTypeMap[Instruction.MUL_IMM_32] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
13626
- instructionArgumentTypeMap[Instruction.MUL_IMM_64] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
13627
- instructionArgumentTypeMap[Instruction.SET_LT_U_IMM] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
13628
- instructionArgumentTypeMap[Instruction.SET_LT_S_IMM] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
13629
- instructionArgumentTypeMap[Instruction.SHLO_L_IMM_32] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
13630
- instructionArgumentTypeMap[Instruction.SHLO_R_IMM_32] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
13631
- instructionArgumentTypeMap[Instruction.SHAR_R_IMM_32] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
13632
- instructionArgumentTypeMap[Instruction.NEG_ADD_IMM_32] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
13633
- instructionArgumentTypeMap[Instruction.SHLO_L_IMM_64] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
13634
- instructionArgumentTypeMap[Instruction.SHLO_R_IMM_64] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
13635
- instructionArgumentTypeMap[Instruction.SHAR_R_IMM_64] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
13636
- instructionArgumentTypeMap[Instruction.NEG_ADD_IMM_64] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
13637
- instructionArgumentTypeMap[Instruction.SET_GT_U_IMM] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
13638
- instructionArgumentTypeMap[Instruction.SET_GT_S_IMM] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
13639
- instructionArgumentTypeMap[Instruction.SHLO_L_IMM_ALT_32] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
13640
- instructionArgumentTypeMap[Instruction.SHLO_R_IMM_ALT_32] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
13641
- instructionArgumentTypeMap[Instruction.SHAR_R_IMM_ALT_32] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
13642
- instructionArgumentTypeMap[Instruction.SHLO_L_IMM_ALT_64] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
13643
- instructionArgumentTypeMap[Instruction.SHLO_R_IMM_ALT_64] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
13644
- instructionArgumentTypeMap[Instruction.SHAR_R_IMM_ALT_64] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
13645
- instructionArgumentTypeMap[Instruction.CMOV_IZ_IMM] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
13646
- instructionArgumentTypeMap[Instruction.CMOV_NZ_IMM] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
13647
- instructionArgumentTypeMap[Instruction.ROT_R_64_IMM] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
13648
- instructionArgumentTypeMap[Instruction.ROT_R_64_IMM_ALT] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
13649
- instructionArgumentTypeMap[Instruction.ROT_R_32_IMM] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
13650
- instructionArgumentTypeMap[Instruction.ROT_R_32_IMM_ALT] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
13651
- instructionArgumentTypeMap[Instruction.BRANCH_EQ] = ArgumentType.TWO_REGISTERS_ONE_OFFSET;
13652
- instructionArgumentTypeMap[Instruction.BRANCH_NE] = ArgumentType.TWO_REGISTERS_ONE_OFFSET;
13653
- instructionArgumentTypeMap[Instruction.BRANCH_LT_U] = ArgumentType.TWO_REGISTERS_ONE_OFFSET;
13654
- instructionArgumentTypeMap[Instruction.BRANCH_LT_S] = ArgumentType.TWO_REGISTERS_ONE_OFFSET;
13655
- instructionArgumentTypeMap[Instruction.BRANCH_GE_U] = ArgumentType.TWO_REGISTERS_ONE_OFFSET;
13656
- instructionArgumentTypeMap[Instruction.BRANCH_GE_S] = ArgumentType.TWO_REGISTERS_ONE_OFFSET;
13657
- instructionArgumentTypeMap[Instruction.LOAD_IMM_JUMP_IND] = ArgumentType.TWO_REGISTERS_TWO_IMMEDIATES;
13658
- instructionArgumentTypeMap[Instruction.ADD_32] = ArgumentType.THREE_REGISTERS;
13659
- instructionArgumentTypeMap[Instruction.ADD_64] = ArgumentType.THREE_REGISTERS;
13660
- instructionArgumentTypeMap[Instruction.SUB_32] = ArgumentType.THREE_REGISTERS;
13661
- instructionArgumentTypeMap[Instruction.SUB_64] = ArgumentType.THREE_REGISTERS;
13662
- instructionArgumentTypeMap[Instruction.AND] = ArgumentType.THREE_REGISTERS;
13663
- instructionArgumentTypeMap[Instruction.XOR] = ArgumentType.THREE_REGISTERS;
13664
- instructionArgumentTypeMap[Instruction.OR] = ArgumentType.THREE_REGISTERS;
13665
- instructionArgumentTypeMap[Instruction.MUL_32] = ArgumentType.THREE_REGISTERS;
13666
- instructionArgumentTypeMap[Instruction.MUL_64] = ArgumentType.THREE_REGISTERS;
13667
- instructionArgumentTypeMap[Instruction.MUL_UPPER_S_S] = ArgumentType.THREE_REGISTERS;
13668
- instructionArgumentTypeMap[Instruction.MUL_UPPER_U_U] = ArgumentType.THREE_REGISTERS;
13669
- instructionArgumentTypeMap[Instruction.MUL_UPPER_S_U] = ArgumentType.THREE_REGISTERS;
13670
- instructionArgumentTypeMap[Instruction.DIV_U_32] = ArgumentType.THREE_REGISTERS;
13671
- instructionArgumentTypeMap[Instruction.DIV_S_32] = ArgumentType.THREE_REGISTERS;
13672
- instructionArgumentTypeMap[Instruction.REM_U_32] = ArgumentType.THREE_REGISTERS;
13673
- instructionArgumentTypeMap[Instruction.REM_S_32] = ArgumentType.THREE_REGISTERS;
13674
- instructionArgumentTypeMap[Instruction.DIV_U_64] = ArgumentType.THREE_REGISTERS;
13675
- instructionArgumentTypeMap[Instruction.DIV_S_64] = ArgumentType.THREE_REGISTERS;
13676
- instructionArgumentTypeMap[Instruction.REM_U_64] = ArgumentType.THREE_REGISTERS;
13677
- instructionArgumentTypeMap[Instruction.REM_S_64] = ArgumentType.THREE_REGISTERS;
13678
- instructionArgumentTypeMap[Instruction.SET_LT_U] = ArgumentType.THREE_REGISTERS;
13679
- instructionArgumentTypeMap[Instruction.SET_LT_S] = ArgumentType.THREE_REGISTERS;
13680
- instructionArgumentTypeMap[Instruction.SHLO_L_32] = ArgumentType.THREE_REGISTERS;
13681
- instructionArgumentTypeMap[Instruction.SHLO_R_32] = ArgumentType.THREE_REGISTERS;
13682
- instructionArgumentTypeMap[Instruction.SHAR_R_32] = ArgumentType.THREE_REGISTERS;
13683
- instructionArgumentTypeMap[Instruction.SHLO_L_64] = ArgumentType.THREE_REGISTERS;
13684
- instructionArgumentTypeMap[Instruction.SHLO_R_64] = ArgumentType.THREE_REGISTERS;
13685
- instructionArgumentTypeMap[Instruction.SHAR_R_64] = ArgumentType.THREE_REGISTERS;
13686
- instructionArgumentTypeMap[Instruction.CMOV_IZ] = ArgumentType.THREE_REGISTERS;
13687
- instructionArgumentTypeMap[Instruction.CMOV_NZ] = ArgumentType.THREE_REGISTERS;
13688
- instructionArgumentTypeMap[Instruction.ROT_L_64] = ArgumentType.THREE_REGISTERS;
13689
- instructionArgumentTypeMap[Instruction.ROT_L_32] = ArgumentType.THREE_REGISTERS;
13690
- instructionArgumentTypeMap[Instruction.ROT_R_64] = ArgumentType.THREE_REGISTERS;
13691
- instructionArgumentTypeMap[Instruction.ROT_R_32] = ArgumentType.THREE_REGISTERS;
13692
- instructionArgumentTypeMap[Instruction.AND_INV] = ArgumentType.THREE_REGISTERS;
13693
- instructionArgumentTypeMap[Instruction.OR_INV] = ArgumentType.THREE_REGISTERS;
13694
- instructionArgumentTypeMap[Instruction.XNOR] = ArgumentType.THREE_REGISTERS;
13695
- instructionArgumentTypeMap[Instruction.MAX] = ArgumentType.THREE_REGISTERS;
13696
- instructionArgumentTypeMap[Instruction.MAX_U] = ArgumentType.THREE_REGISTERS;
13697
- instructionArgumentTypeMap[Instruction.MIN] = ArgumentType.THREE_REGISTERS;
13698
- instructionArgumentTypeMap[Instruction.MIN_U] = ArgumentType.THREE_REGISTERS;
13699
- return instructionArgumentTypeMap;
13341
+ const PAGE_SIZE_SHIFT = 12;
13342
+ // PAGE_SIZE has to be a power of 2
13343
+ const PAGE_SIZE$1 = 1 << PAGE_SIZE_SHIFT;
13344
+ const MIN_ALLOCATION_SHIFT = (() => {
13345
+ const MIN_ALLOCATION_SHIFT = 7;
13346
+ check `${MIN_ALLOCATION_SHIFT < PAGE_SIZE_SHIFT} incorrect minimal allocation shift`;
13347
+ return MIN_ALLOCATION_SHIFT;
13700
13348
  })();
13701
-
13702
- const instructionsWithoutArgs = [
13703
- [Instruction.TRAP, 1],
13704
- [Instruction.FALLTHROUGH, 1],
13705
- ];
13706
- const instructionsWithOneImmediate = [[Instruction.ECALLI, 1]];
13707
- const instructionsWithOneRegisterAndOneExtendedWidthImmediate = [[Instruction.LOAD_IMM_64, 1]];
13708
- const instructionsWithTwoImmediates = [
13709
- [Instruction.STORE_IMM_U8, 1],
13710
- [Instruction.STORE_IMM_U16, 1],
13711
- [Instruction.STORE_IMM_U32, 1],
13712
- [Instruction.STORE_IMM_U64, 1],
13713
- ];
13714
- const instructionsWithOneOffset = [[Instruction.JUMP, 1]];
13715
- const instructionsWithOneRegisterAndOneImmediate = [
13716
- [Instruction.JUMP_IND, 1],
13717
- [Instruction.LOAD_IMM, 1],
13718
- [Instruction.LOAD_U8, 1],
13719
- [Instruction.LOAD_I8, 1],
13720
- [Instruction.LOAD_U16, 1],
13721
- [Instruction.LOAD_I16, 1],
13722
- [Instruction.LOAD_U32, 1],
13723
- [Instruction.LOAD_I32, 1],
13724
- [Instruction.LOAD_U64, 1],
13725
- [Instruction.STORE_U8, 1],
13726
- [Instruction.STORE_U16, 1],
13727
- [Instruction.STORE_U32, 1],
13728
- [Instruction.STORE_U64, 1],
13729
- ];
13730
- const instructionsWithOneRegisterAndTwoImmediate = [
13731
- [Instruction.STORE_IMM_IND_U8, 1],
13732
- [Instruction.STORE_IMM_IND_U16, 1],
13733
- [Instruction.STORE_IMM_IND_U32, 1],
13734
- [Instruction.STORE_IMM_IND_U64, 1],
13735
- ];
13736
- const instructionsWithOneRegisterOneImmediateAndOneOffset = [
13737
- [Instruction.LOAD_IMM_JUMP, 1],
13738
- [Instruction.BRANCH_EQ_IMM, 1],
13739
- [Instruction.BRANCH_NE_IMM, 1],
13740
- [Instruction.BRANCH_LT_U_IMM, 1],
13741
- [Instruction.BRANCH_LE_U_IMM, 1],
13742
- [Instruction.BRANCH_GE_U_IMM, 1],
13743
- [Instruction.BRANCH_GT_U_IMM, 1],
13744
- [Instruction.BRANCH_LT_S_IMM, 1],
13745
- [Instruction.BRANCH_LE_S_IMM, 1],
13746
- [Instruction.BRANCH_GE_S_IMM, 1],
13747
- [Instruction.BRANCH_GT_S_IMM, 1],
13748
- ];
13749
- const instructionsWithTwoRegisters = [
13750
- [Instruction.MOVE_REG, 1],
13751
- [Instruction.SBRK, 1],
13752
- [Instruction.COUNT_SET_BITS_64, 1],
13753
- [Instruction.COUNT_SET_BITS_32, 1],
13754
- [Instruction.LEADING_ZERO_BITS_64, 1],
13755
- [Instruction.LEADING_ZERO_BITS_32, 1],
13756
- [Instruction.TRAILING_ZERO_BITS_64, 1],
13757
- [Instruction.TRAILING_ZERO_BITS_32, 1],
13758
- [Instruction.SIGN_EXTEND_8, 1],
13759
- [Instruction.SIGN_EXTEND_16, 1],
13760
- [Instruction.ZERO_EXTEND_16, 1],
13761
- [Instruction.REVERSE_BYTES, 1],
13762
- ];
13763
- const instructionsWithTwoRegistersAndOneImmediate = [
13764
- [Instruction.STORE_IND_U8, 1],
13765
- [Instruction.STORE_IND_U16, 1],
13766
- [Instruction.STORE_IND_U32, 1],
13767
- [Instruction.STORE_IND_U64, 1],
13768
- [Instruction.LOAD_IND_U8, 1],
13769
- [Instruction.LOAD_IND_I8, 1],
13770
- [Instruction.LOAD_IND_U16, 1],
13771
- [Instruction.LOAD_IND_I16, 1],
13772
- [Instruction.LOAD_IND_U32, 1],
13773
- [Instruction.LOAD_IND_I32, 1],
13774
- [Instruction.LOAD_IND_U64, 1],
13775
- [Instruction.ADD_IMM_32, 1],
13776
- [Instruction.AND_IMM, 1],
13777
- [Instruction.XOR_IMM, 1],
13778
- [Instruction.OR_IMM, 1],
13779
- [Instruction.MUL_IMM_32, 1],
13780
- [Instruction.SET_LT_U_IMM, 1],
13781
- [Instruction.SET_LT_S_IMM, 1],
13782
- [Instruction.SHLO_L_IMM_32, 1],
13783
- [Instruction.SHLO_R_IMM_32, 1],
13784
- [Instruction.SHAR_R_IMM_32, 1],
13785
- [Instruction.NEG_ADD_IMM_32, 1],
13786
- [Instruction.SET_GT_U_IMM, 1],
13787
- [Instruction.SET_GT_S_IMM, 1],
13788
- [Instruction.SHLO_L_IMM_ALT_32, 1],
13789
- [Instruction.SHLO_R_IMM_ALT_32, 1],
13790
- [Instruction.SHAR_R_IMM_ALT_32, 1],
13791
- [Instruction.CMOV_IZ_IMM, 1],
13792
- [Instruction.CMOV_NZ_IMM, 1],
13793
- [Instruction.ADD_IMM_64, 1],
13794
- [Instruction.MUL_IMM_64, 1],
13795
- [Instruction.SHLO_L_IMM_64, 1],
13796
- [Instruction.SHLO_R_IMM_64, 1],
13797
- [Instruction.SHAR_R_IMM_64, 1],
13798
- [Instruction.NEG_ADD_IMM_64, 1],
13799
- [Instruction.SHLO_L_IMM_ALT_64, 1],
13800
- [Instruction.SHLO_R_IMM_ALT_64, 1],
13801
- [Instruction.SHAR_R_IMM_ALT_64, 1],
13802
- [Instruction.ROT_R_64_IMM, 1],
13803
- [Instruction.ROT_R_64_IMM_ALT, 1],
13804
- [Instruction.ROT_R_32_IMM, 1],
13805
- [Instruction.ROT_R_32_IMM_ALT, 1],
13806
- ];
13807
- const instructionsWithTwoRegistersAndOneOffset = [
13808
- [Instruction.BRANCH_EQ, 1],
13809
- [Instruction.BRANCH_NE, 1],
13810
- [Instruction.BRANCH_LT_U, 1],
13811
- [Instruction.BRANCH_LT_S, 1],
13812
- [Instruction.BRANCH_GE_U, 1],
13813
- [Instruction.BRANCH_GE_S, 1],
13814
- ];
13815
- const instructionWithTwoRegistersAndTwoImmediates = [[Instruction.LOAD_IMM_JUMP_IND, 1]];
13816
- const instructionsWithThreeRegisters = [
13817
- [Instruction.ADD_32, 1],
13818
- [Instruction.SUB_32, 1],
13819
- [Instruction.MUL_32, 1],
13820
- [Instruction.DIV_U_32, 1],
13821
- [Instruction.DIV_S_32, 1],
13822
- [Instruction.REM_U_32, 1],
13823
- [Instruction.REM_S_32, 1],
13824
- [Instruction.SHLO_L_32, 1],
13825
- [Instruction.SHLO_R_32, 1],
13826
- [Instruction.SHAR_R_32, 1],
13827
- [Instruction.ADD_64, 1],
13828
- [Instruction.SUB_64, 1],
13829
- [Instruction.MUL_64, 1],
13830
- [Instruction.DIV_U_64, 1],
13831
- [Instruction.DIV_S_64, 1],
13832
- [Instruction.REM_U_64, 1],
13833
- [Instruction.REM_S_64, 1],
13834
- [Instruction.SHLO_L_64, 1],
13835
- [Instruction.SHLO_R_64, 1],
13836
- [Instruction.SHAR_R_64, 1],
13837
- [Instruction.AND, 1],
13838
- [Instruction.XOR, 1],
13839
- [Instruction.OR, 1],
13840
- [Instruction.MUL_UPPER_S_S, 1],
13841
- [Instruction.MUL_UPPER_U_U, 1],
13842
- [Instruction.MUL_UPPER_S_U, 1],
13843
- [Instruction.SET_LT_U, 1],
13844
- [Instruction.SET_LT_S, 1],
13845
- [Instruction.CMOV_IZ, 1],
13846
- [Instruction.CMOV_NZ, 1],
13847
- [Instruction.ROT_L_64, 1],
13848
- [Instruction.ROT_L_32, 1],
13849
- [Instruction.ROT_R_64, 1],
13850
- [Instruction.ROT_R_32, 1],
13851
- [Instruction.AND_INV, 1],
13852
- [Instruction.OR_INV, 1],
13853
- [Instruction.XNOR, 1],
13854
- [Instruction.MAX, 1],
13855
- [Instruction.MAX_U, 1],
13856
- [Instruction.MIN, 1],
13857
- [Instruction.MIN_U, 1],
13858
- ];
13859
- const instructions = [
13860
- ...instructionsWithoutArgs,
13861
- ...instructionsWithOneImmediate,
13862
- ...instructionsWithOneRegisterAndOneExtendedWidthImmediate,
13863
- ...instructionsWithTwoImmediates,
13864
- ...instructionsWithOneOffset,
13865
- ...instructionsWithOneRegisterAndOneImmediate,
13866
- ...instructionsWithOneRegisterAndTwoImmediate,
13867
- ...instructionsWithOneRegisterOneImmediateAndOneOffset,
13868
- ...instructionsWithTwoRegisters,
13869
- ...instructionsWithTwoRegistersAndOneImmediate,
13870
- ...instructionsWithTwoRegistersAndOneOffset,
13871
- ...instructionWithTwoRegistersAndTwoImmediates,
13872
- ...instructionsWithThreeRegisters,
13873
- ];
13874
- const createOpCodeEntry = ([byte, gas]) => [byte, { gas: tryAsSmallGas(gas) }];
13875
- const byteToOpCodeMap = instructions.reduce((acc, instruction) => {
13876
- const [byte, opCode] = createOpCodeEntry(instruction);
13877
- acc[byte] = opCode;
13878
- return acc;
13879
- }, {});
13880
- function assemblify(program, mask) {
13881
- return program.reduce((acc, byte, index) => {
13882
- if (mask.isInstruction(index)) {
13883
- acc.push([Instruction[byte]]);
13884
- }
13885
- else {
13886
- acc[acc.length - 1].push(byte);
13887
- }
13888
- return acc;
13889
- }, []);
13890
- }
13891
-
13892
- const terminationInstructions = (() => {
13893
- const terminationInstructions = new Array(HIGHEST_INSTRUCTION_NUMBER + 1);
13894
- terminationInstructions.fill(false);
13895
- terminationInstructions[Instruction.TRAP] = true;
13896
- terminationInstructions[Instruction.FALLTHROUGH] = true;
13897
- terminationInstructions[Instruction.JUMP] = true;
13898
- terminationInstructions[Instruction.JUMP_IND] = true;
13899
- terminationInstructions[Instruction.LOAD_IMM_JUMP] = true;
13900
- terminationInstructions[Instruction.LOAD_IMM_JUMP_IND] = true;
13901
- terminationInstructions[Instruction.BRANCH_EQ] = true;
13902
- terminationInstructions[Instruction.BRANCH_NE] = true;
13903
- terminationInstructions[Instruction.BRANCH_GE_U] = true;
13904
- terminationInstructions[Instruction.BRANCH_GE_S] = true;
13905
- terminationInstructions[Instruction.BRANCH_LT_U] = true;
13906
- terminationInstructions[Instruction.BRANCH_LT_S] = true;
13907
- terminationInstructions[Instruction.BRANCH_EQ_IMM] = true;
13908
- terminationInstructions[Instruction.BRANCH_NE_IMM] = true;
13909
- terminationInstructions[Instruction.BRANCH_LT_U_IMM] = true;
13910
- terminationInstructions[Instruction.BRANCH_LT_S_IMM] = true;
13911
- terminationInstructions[Instruction.BRANCH_LE_U_IMM] = true;
13912
- terminationInstructions[Instruction.BRANCH_LE_S_IMM] = true;
13913
- terminationInstructions[Instruction.BRANCH_GE_U_IMM] = true;
13914
- terminationInstructions[Instruction.BRANCH_GE_S_IMM] = true;
13915
- terminationInstructions[Instruction.BRANCH_GT_U_IMM] = true;
13916
- terminationInstructions[Instruction.BRANCH_GT_S_IMM] = true;
13917
- return terminationInstructions;
13918
- })();
13919
-
13920
- class BasicBlocks {
13921
- basicBlocks = new Set();
13922
- reset(code, mask) {
13923
- this.basicBlocks.clear();
13924
- this.basicBlocks.add(0);
13925
- const codeLength = code.length;
13926
- const isBasicBlockTermination = (index) => mask.isInstruction(index) && terminationInstructions[code[index]];
13927
- for (let i = 0; i < codeLength; i++) {
13928
- if (mask.isInstruction(i) && isBasicBlockTermination(i)) {
13929
- this.basicBlocks.add(i + 1 + mask.getNoOfBytesToNextInstruction(i + 1));
13930
- }
13931
- }
13932
- }
13933
- isBeginningOfBasicBlock(index) {
13934
- return this.basicBlocks.has(index);
13935
- }
13936
- }
13937
-
13938
- const instructionGasMap = (() => {
13939
- const instructionGasMap = new Array(HIGHEST_INSTRUCTION_NUMBER + 1);
13940
- for (let i = 0; i < HIGHEST_INSTRUCTION_NUMBER + 1; i++) {
13941
- const gas = byteToOpCodeMap[i]?.gas;
13942
- instructionGasMap[i] = gas;
13943
- }
13944
- return instructionGasMap;
13945
- })();
13946
-
13947
- class InstructionResult {
13948
- nextPc = 0;
13949
- status = null;
13950
- /**
13951
- * A numeric exit parameter of the PVM.
13952
- *
13953
- * In case of a `status === Result.FAULT` this will be the memory address
13954
- * that triggered the fault.
13955
- * In case of a `status === Result.HOST` this will be the host call index
13956
- * that should be invoked.
13957
- *
13958
- * In any other circumstance the value should be `null`.
13959
- */
13960
- exitParam = null;
13961
- reset() {
13962
- this.nextPc = 0;
13963
- this.status = null;
13964
- this.exitParam = null;
13965
- }
13966
- }
13967
-
13968
- const MAX_MEMORY_INDEX = 0xffff_ffff;
13969
- const MEMORY_SIZE = MAX_MEMORY_INDEX + 1;
13970
- const PAGE_SIZE_SHIFT = 12;
13971
- // PAGE_SIZE has to be a power of 2
13972
- const PAGE_SIZE$1 = 1 << PAGE_SIZE_SHIFT;
13973
- const MIN_ALLOCATION_SHIFT = (() => {
13974
- const MIN_ALLOCATION_SHIFT = 7;
13975
- check `${MIN_ALLOCATION_SHIFT < PAGE_SIZE_SHIFT} incorrect minimal allocation shift`;
13976
- return MIN_ALLOCATION_SHIFT;
13977
- })();
13978
- const MIN_ALLOCATION_LENGTH = PAGE_SIZE$1 >> MIN_ALLOCATION_SHIFT;
13979
- const LAST_PAGE_NUMBER = (MEMORY_SIZE - PAGE_SIZE$1) / PAGE_SIZE$1;
13980
- /** https://graypaper.fluffylabs.dev/#/68eaa1f/35a60235a602?v=0.6.4 */
13981
- const RESERVED_NUMBER_OF_PAGES = 16;
13982
- /** https://graypaper.fluffylabs.dev/#/68eaa1f/35a60235a602?v=0.6.4 */
13983
- const MAX_NUMBER_OF_PAGES = MEMORY_SIZE / PAGE_SIZE$1;
13984
-
13985
- const tryAsMemoryIndex = (index) => {
13986
- check `${index >= 0 && index <= MAX_MEMORY_INDEX} Incorrect memory index: ${index}!`;
13987
- return asOpaqueType(index);
13988
- };
13989
- const tryAsSbrkIndex = (index) => {
13990
- check `${index >= 0 && index <= MAX_MEMORY_INDEX + 1} Incorrect sbrk index: ${index}!`;
13991
- return asOpaqueType(index);
13992
- };
13349
+ const MIN_ALLOCATION_LENGTH = PAGE_SIZE$1 >> MIN_ALLOCATION_SHIFT;
13350
+ const LAST_PAGE_NUMBER = (MEMORY_SIZE - PAGE_SIZE$1) / PAGE_SIZE$1;
13351
+ /** https://graypaper.fluffylabs.dev/#/68eaa1f/35a60235a602?v=0.6.4 */
13352
+ const RESERVED_NUMBER_OF_PAGES = 16;
13353
+ /** https://graypaper.fluffylabs.dev/#/68eaa1f/35a60235a602?v=0.6.4 */
13354
+ const MAX_NUMBER_OF_PAGES = MEMORY_SIZE / PAGE_SIZE$1;
13993
13355
 
13994
13356
  /** Ensure that given memory `index` is within `[0...PAGE_SIZE)` and can be used to index a page */
13995
13357
  const tryAsPageIndex = (index) => {
@@ -14040,17 +13402,12 @@ class PageFault {
14040
13402
  static fromPageNumber(maybePageNumber, isAccessFault = false) {
14041
13403
  const pageNumber = tryAsPageNumber(maybePageNumber);
14042
13404
  const startPageIndex = getStartPageIndexFromPageNumber(pageNumber);
14043
- return new PageFault(startPageIndex, isAccessFault);
13405
+ return new PageFault(tryAsU32(startPageIndex), isAccessFault);
14044
13406
  }
14045
13407
  static fromMemoryIndex(maybeMemoryIndex, isAccessFault = false) {
14046
13408
  const memoryIndex = tryAsMemoryIndex(maybeMemoryIndex % MEMORY_SIZE);
14047
13409
  const startPageIndex = getStartPageIndex(memoryIndex);
14048
- return new PageFault(startPageIndex, isAccessFault);
14049
- }
14050
- }
14051
- class OutOfBounds extends Error {
14052
- constructor() {
14053
- super("Out of bounds");
13410
+ return new PageFault(tryAsU32(startPageIndex), isAccessFault);
14054
13411
  }
14055
13412
  }
14056
13413
  class IncorrectSbrkIndex extends Error {
@@ -14291,277 +13648,1459 @@ class WriteablePage extends MemoryPage {
14291
13648
  const newLength = Math.min(PAGE_SIZE$1, Math.max(MIN_ALLOCATION_LENGTH, startIndex + bytes.length));
14292
13649
  this.buffer.resize(newLength);
14293
13650
  }
14294
- this.view.set(bytes, startIndex);
14295
- return Result$1.ok(OK);
14296
- }
14297
- setData(pageIndex, data) {
14298
- if (this.buffer.byteLength < pageIndex + data.length && this.buffer.byteLength < PAGE_SIZE$1) {
14299
- const newLength = Math.min(PAGE_SIZE$1, Math.max(MIN_ALLOCATION_LENGTH, pageIndex + data.length));
14300
- this.buffer.resize(newLength);
13651
+ this.view.set(bytes, startIndex);
13652
+ return Result$1.ok(OK);
13653
+ }
13654
+ setData(pageIndex, data) {
13655
+ if (this.buffer.byteLength < pageIndex + data.length && this.buffer.byteLength < PAGE_SIZE$1) {
13656
+ const newLength = Math.min(PAGE_SIZE$1, Math.max(MIN_ALLOCATION_LENGTH, pageIndex + data.length));
13657
+ this.buffer.resize(newLength);
13658
+ }
13659
+ this.view.set(data, pageIndex);
13660
+ }
13661
+ isWriteable() {
13662
+ return true;
13663
+ }
13664
+ getPageDump() {
13665
+ return this.view;
13666
+ }
13667
+ }
13668
+
13669
+ var AccessType;
13670
+ (function (AccessType) {
13671
+ AccessType[AccessType["READ"] = 0] = "READ";
13672
+ AccessType[AccessType["WRITE"] = 1] = "WRITE";
13673
+ })(AccessType || (AccessType = {}));
13674
+ const logger$2 = Logger.new(undefined, "pvm:mem");
13675
+ class Memory {
13676
+ sbrkIndex;
13677
+ virtualSbrkIndex;
13678
+ endHeapIndex;
13679
+ memory;
13680
+ static fromInitialMemory(initialMemoryState) {
13681
+ return new Memory(initialMemoryState?.sbrkIndex, initialMemoryState?.sbrkIndex, initialMemoryState?.endHeapIndex, initialMemoryState?.memory);
13682
+ }
13683
+ constructor(sbrkIndex = tryAsSbrkIndex(RESERVED_MEMORY_RANGE.end), virtualSbrkIndex = tryAsSbrkIndex(RESERVED_MEMORY_RANGE.end), endHeapIndex = tryAsSbrkIndex(MAX_MEMORY_INDEX), memory = new Map()) {
13684
+ this.sbrkIndex = sbrkIndex;
13685
+ this.virtualSbrkIndex = virtualSbrkIndex;
13686
+ this.endHeapIndex = endHeapIndex;
13687
+ this.memory = memory;
13688
+ }
13689
+ store(address, bytes) {
13690
+ return this.storeFrom(tryAsMemoryIndex(address), bytes);
13691
+ }
13692
+ read(address, output) {
13693
+ return this.loadInto(output, tryAsMemoryIndex(address));
13694
+ }
13695
+ reset() {
13696
+ this.sbrkIndex = tryAsSbrkIndex(RESERVED_MEMORY_RANGE.end);
13697
+ this.virtualSbrkIndex = tryAsSbrkIndex(RESERVED_MEMORY_RANGE.end);
13698
+ this.endHeapIndex = tryAsSbrkIndex(MAX_MEMORY_INDEX);
13699
+ this.memory = new Map(); // TODO [MaSi]: We should keep allocated pages somewhere and reuse it when it is possible
13700
+ }
13701
+ copyFrom(memory) {
13702
+ this.sbrkIndex = memory.sbrkIndex;
13703
+ this.virtualSbrkIndex = memory.virtualSbrkIndex;
13704
+ this.endHeapIndex = memory.endHeapIndex;
13705
+ this.memory = memory.memory;
13706
+ }
13707
+ storeFrom(address, bytes) {
13708
+ if (bytes.length === 0) {
13709
+ return Result$1.ok(OK);
13710
+ }
13711
+ logger$2.insane `MEM[${address}] <- ${BytesBlob.blobFrom(bytes)}`;
13712
+ const pagesResult = this.getPages(address, bytes.length, AccessType.WRITE);
13713
+ if (pagesResult.isError) {
13714
+ return Result$1.error(pagesResult.error, pagesResult.details);
13715
+ }
13716
+ const pages = pagesResult.ok;
13717
+ let currentPosition = address;
13718
+ let bytesLeft = bytes.length;
13719
+ for (const page of pages) {
13720
+ const pageStartIndex = tryAsPageIndex(currentPosition % PAGE_SIZE$1);
13721
+ const bytesToWrite = Math.min(PAGE_SIZE$1 - pageStartIndex, bytesLeft);
13722
+ const sourceStartIndex = currentPosition - address;
13723
+ const source = bytes.subarray(sourceStartIndex, sourceStartIndex + bytesToWrite);
13724
+ page.storeFrom(pageStartIndex, source);
13725
+ currentPosition += bytesToWrite;
13726
+ bytesLeft -= bytesToWrite;
13727
+ }
13728
+ return Result$1.ok(OK);
13729
+ }
13730
+ getPages(startAddress, length, accessType) {
13731
+ if (length === 0) {
13732
+ return Result$1.ok([]);
13733
+ }
13734
+ const memoryRange = MemoryRange.fromStartAndLength(startAddress, length);
13735
+ const pageRange = PageRange.fromMemoryRange(memoryRange);
13736
+ const pages = [];
13737
+ for (const pageNumber of pageRange) {
13738
+ if (pageNumber < RESERVED_NUMBER_OF_PAGES) {
13739
+ return Result$1.error(PageFault.fromPageNumber(pageNumber, true), () => `Page fault: attempted to access reserved page ${pageNumber}`);
13740
+ }
13741
+ const page = this.memory.get(pageNumber);
13742
+ if (page === undefined) {
13743
+ return Result$1.error(PageFault.fromPageNumber(pageNumber), () => `Page fault: page ${pageNumber} not allocated`);
13744
+ }
13745
+ if (accessType === AccessType.WRITE && !page.isWriteable()) {
13746
+ return Result$1.error(PageFault.fromPageNumber(pageNumber, true), () => `Page fault: attempted to write to read-only page ${pageNumber}`);
13747
+ }
13748
+ pages.push(page);
13749
+ }
13750
+ return Result$1.ok(pages);
13751
+ }
13752
+ /**
13753
+ * Read content of the memory at `[address, address + result.length)` and
13754
+ * write the result into the `result` buffer.
13755
+ *
13756
+ * Returns `null` if the data was read successfully or `PageFault` otherwise.
13757
+ */
13758
+ loadInto(result, startAddress) {
13759
+ if (result.length === 0) {
13760
+ return Result$1.ok(OK);
13761
+ }
13762
+ const pagesResult = this.getPages(startAddress, result.length, AccessType.READ);
13763
+ if (pagesResult.isError) {
13764
+ return Result$1.error(pagesResult.error, pagesResult.details);
13765
+ }
13766
+ const pages = pagesResult.ok;
13767
+ let currentPosition = startAddress;
13768
+ let bytesLeft = result.length;
13769
+ for (const page of pages) {
13770
+ const pageStartIndex = tryAsPageIndex(currentPosition % PAGE_SIZE$1);
13771
+ const bytesToRead = Math.min(PAGE_SIZE$1 - pageStartIndex, bytesLeft);
13772
+ const destinationStartIndex = currentPosition - startAddress;
13773
+ const destination = result.subarray(destinationStartIndex);
13774
+ page.loadInto(destination, pageStartIndex, bytesToRead);
13775
+ currentPosition += bytesToRead;
13776
+ bytesLeft -= bytesToRead;
13777
+ }
13778
+ logger$2.insane `MEM[${startAddress}] => ${BytesBlob.blobFrom(result)}`;
13779
+ return Result$1.ok(OK);
13780
+ }
13781
+ sbrk(length) {
13782
+ const currentSbrkIndex = this.sbrkIndex;
13783
+ const currentVirtualSbrkIndex = this.virtualSbrkIndex;
13784
+ // new sbrk index is bigger than 2 ** 32 or endHeapIndex
13785
+ if (MAX_MEMORY_INDEX < currentVirtualSbrkIndex + length || currentVirtualSbrkIndex + length > this.endHeapIndex) {
13786
+ throw new OutOfMemory();
13787
+ }
13788
+ const newVirtualSbrkIndex = tryAsSbrkIndex(this.virtualSbrkIndex + length);
13789
+ // no alllocation needed
13790
+ if (newVirtualSbrkIndex <= currentSbrkIndex) {
13791
+ this.virtualSbrkIndex = newVirtualSbrkIndex;
13792
+ return currentVirtualSbrkIndex;
13793
+ }
13794
+ // standard allocation using "Writeable" pages
13795
+ const newSbrkIndex = tryAsSbrkIndex(alignToPageSize$1(newVirtualSbrkIndex));
13796
+ // TODO [MaSi]: `getPageNumber` works incorrectly for SbrkIndex. Sbrk index should be changed to MemoryIndex
13797
+ const firstPageNumber = getPageNumber(currentSbrkIndex);
13798
+ const pagesToAllocate = (newSbrkIndex - currentSbrkIndex) / PAGE_SIZE$1;
13799
+ const rangeToAllocate = PageRange.fromStartAndLength(firstPageNumber, pagesToAllocate);
13800
+ for (const pageNumber of rangeToAllocate) {
13801
+ const page = new WriteablePage(pageNumber);
13802
+ this.memory.set(pageNumber, page);
13803
+ }
13804
+ this.virtualSbrkIndex = newVirtualSbrkIndex;
13805
+ this.sbrkIndex = newSbrkIndex;
13806
+ return currentVirtualSbrkIndex;
13807
+ }
13808
+ getPageDump(pageNumber) {
13809
+ const page = this.memory.get(pageNumber);
13810
+ return page?.getPageDump() ?? null;
13811
+ }
13812
+ getDirtyPages() {
13813
+ return this.memory.keys();
13814
+ }
13815
+ }
13816
+
13817
+ class MemoryBuilder {
13818
+ initialMemory = new Map();
13819
+ isFinalized = false;
13820
+ ensureNotFinalized() {
13821
+ if (this.isFinalized) {
13822
+ throw new FinalizedBuilderModification();
13823
+ }
13824
+ }
13825
+ ensureNoReservedMemoryUsage(range) {
13826
+ if (range.overlapsWith(RESERVED_MEMORY_RANGE)) {
13827
+ throw new ReservedMemoryFault();
13828
+ }
13829
+ }
13830
+ /**
13831
+ * Create entire readable pages to handle the `[start, end)` range.
13832
+ *
13833
+ * Note that both `start` and `end` must be multiple of the `PAGE_SIZE`, i.e.
13834
+ * they need to be the start indices of the pages.
13835
+ *
13836
+ * The data passed will be placed at `start`, but might be shorter than the requested range,
13837
+ * prepend it with zeros if you don't wish to have it at the beginning of the page.
13838
+ */
13839
+ setReadablePages(start, end, data = new Uint8Array()) {
13840
+ this.ensureNotFinalized();
13841
+ check `${start < end} end has to be bigger than start`;
13842
+ check `${start % PAGE_SIZE$1 === 0} start needs to be a multiple of page size (${PAGE_SIZE$1})`;
13843
+ check `${end % PAGE_SIZE$1 === 0} end needs to be a multiple of page size (${PAGE_SIZE$1})`;
13844
+ check `${data.length <= end - start} the initial data is longer than address range`;
13845
+ const length = end - start;
13846
+ const range = MemoryRange.fromStartAndLength(start, length);
13847
+ this.ensureNoReservedMemoryUsage(range);
13848
+ const pages = Array.from(PageRange.fromMemoryRange(range));
13849
+ const noOfPages = pages.length;
13850
+ for (let i = 0; i < noOfPages; i++) {
13851
+ const pageNumber = pages[i];
13852
+ const dataChunk = data.subarray(i * PAGE_SIZE$1, (i + 1) * PAGE_SIZE$1);
13853
+ const page = new ReadablePage(pageNumber, dataChunk);
13854
+ this.initialMemory.set(pageNumber, page);
13855
+ }
13856
+ return this;
13857
+ }
13858
+ /**
13859
+ * Create entire writeable pages to handle the `[start, end)` range.
13860
+ *
13861
+ * Note that both `start` and `end` must be multiple of the `PAGE_SIZE`, i.e.
13862
+ * they need to be the start indices of the pages.
13863
+ *
13864
+ * The data passed will be placed at `start`, but might be shorter than the requested range,
13865
+ * prepend it with zeros if you don't wish to have it at the beginning of the page.
13866
+ */
13867
+ setWriteablePages(start, end, data = new Uint8Array()) {
13868
+ this.ensureNotFinalized();
13869
+ check `${start < end} end has to be bigger than start`;
13870
+ check `${start % PAGE_SIZE$1 === 0} start needs to be a multiple of page size (${PAGE_SIZE$1})`;
13871
+ check `${end % PAGE_SIZE$1 === 0} end needs to be a multiple of page size (${PAGE_SIZE$1})`;
13872
+ check `${data.length <= end - start} the initial data is longer than address range`;
13873
+ const length = end - start;
13874
+ const range = MemoryRange.fromStartAndLength(start, length);
13875
+ this.ensureNoReservedMemoryUsage(range);
13876
+ const pages = Array.from(PageRange.fromMemoryRange(range));
13877
+ const noOfPages = pages.length;
13878
+ for (let i = 0; i < noOfPages; i++) {
13879
+ const pageNumber = pages[i];
13880
+ const dataChunk = data.subarray(i * PAGE_SIZE$1, (i + 1) * PAGE_SIZE$1);
13881
+ const page = new WriteablePage(pageNumber, dataChunk);
13882
+ this.initialMemory.set(pageNumber, page);
13883
+ }
13884
+ return this;
13885
+ }
13886
+ /**
13887
+ * This function can be useful when page map and initial memory data are provided separatelly.
13888
+ * You can use setWriteablePages/setReadablePages to create empty pages and then setData to fill them
13889
+ */
13890
+ setData(start, data) {
13891
+ this.ensureNotFinalized();
13892
+ const pageOffset = start % PAGE_SIZE$1;
13893
+ const remainingSpaceOnPage = PAGE_SIZE$1 - pageOffset;
13894
+ check `${data.length <= remainingSpaceOnPage} The data has to fit into a single page.`;
13895
+ const length = data.length;
13896
+ const range = MemoryRange.fromStartAndLength(start, length);
13897
+ this.ensureNoReservedMemoryUsage(range);
13898
+ const pageNumber = getPageNumber(start);
13899
+ const page = this.initialMemory.get(pageNumber);
13900
+ if (page === undefined) {
13901
+ throw new PageNotExist();
13902
+ }
13903
+ const startPageIndex = tryAsPageIndex(start - page.start);
13904
+ page.setData(startPageIndex, data);
13905
+ return this;
13906
+ }
13907
+ finalize(startHeapIndex, endHeapIndex) {
13908
+ check `
13909
+ ${startHeapIndex <= endHeapIndex}
13910
+ startHeapIndex (${startHeapIndex}) has to be less than or equal to endHeapIndex (${endHeapIndex})
13911
+ `;
13912
+ this.ensureNotFinalized();
13913
+ const heapRange = MemoryRange.fromStartAndLength(startHeapIndex, endHeapIndex - startHeapIndex);
13914
+ const heapPagesRange = PageRange.fromMemoryRange(heapRange);
13915
+ const initializedPageNumbers = Array.from(this.initialMemory.keys());
13916
+ for (const pageNumber of initializedPageNumbers) {
13917
+ if (heapPagesRange.isInRange(pageNumber)) {
13918
+ throw new IncorrectSbrkIndex();
13919
+ }
13920
+ }
13921
+ const memory = Memory.fromInitialMemory({
13922
+ memory: this.initialMemory,
13923
+ sbrkIndex: tryAsSbrkIndex(startHeapIndex),
13924
+ endHeapIndex,
13925
+ });
13926
+ this.isFinalized = true;
13927
+ return memory;
13928
+ }
13929
+ }
13930
+
13931
+ // GP reference: https://graypaper.fluffylabs.dev/#/7e6ff6a/2d32002d3200?v=0.6.7
13932
+ const PAGE_SIZE = 2 ** 12; // Z_P from GP
13933
+ const SEGMENT_SIZE = 2 ** 16; // Z_Z from GP
13934
+ const DATA_LEGNTH = 2 ** 24; // Z_I from GP
13935
+ const STACK_SEGMENT = 0xfe_fe_00_00; // 2^32 - 2Z_Z - Z_I from GP
13936
+ const ARGS_SEGMENT = 0xfe_ff_00_00; // 2^32 - Z_Z - Z_I from GP
13937
+ const LAST_PAGE = 0xff_ff_00_00;
13938
+
13939
+ // GP reference: https://graypaper.fluffylabs.dev/#/579bd12/2bd2022bd202
13940
+ function alignToSegmentSize(size) {
13941
+ // Q(x) from GP
13942
+ return SEGMENT_SIZE * Math.ceil(size / SEGMENT_SIZE);
13943
+ }
13944
+ function alignToPageSize(size) {
13945
+ // P(x) from GP
13946
+ return PAGE_SIZE * Math.ceil(size / PAGE_SIZE);
13947
+ }
13948
+
13949
+ const NO_OF_REGISTERS = 13;
13950
+ class MemorySegment extends WithDebug {
13951
+ start;
13952
+ end;
13953
+ data;
13954
+ static from({ start, end, data }) {
13955
+ return new MemorySegment(start, end, data);
13956
+ }
13957
+ constructor(start, end, data) {
13958
+ super();
13959
+ this.start = start;
13960
+ this.end = end;
13961
+ this.data = data;
13962
+ }
13963
+ }
13964
+ class SpiMemory extends WithDebug {
13965
+ readable;
13966
+ writeable;
13967
+ sbrkIndex;
13968
+ heapEnd;
13969
+ constructor(readable, writeable, sbrkIndex, heapEnd) {
13970
+ super();
13971
+ this.readable = readable;
13972
+ this.writeable = writeable;
13973
+ this.sbrkIndex = sbrkIndex;
13974
+ this.heapEnd = heapEnd;
13975
+ }
13976
+ }
13977
+ class SpiProgram extends WithDebug {
13978
+ code;
13979
+ memory;
13980
+ registers;
13981
+ constructor(code, memory, registers) {
13982
+ super();
13983
+ this.code = code;
13984
+ this.memory = memory;
13985
+ this.registers = registers;
13986
+ }
13987
+ }
13988
+ /**
13989
+ * program = E_3(|o|) ++ E_3(|w|) ++ E_2(z) ++ E_3(s) ++ o ++ w ++ E_4(|c|) ++ c
13990
+ *
13991
+ * E_n - little endian encoding, n - length
13992
+ * o - initial read only data
13993
+ * w - initial heap
13994
+ * z - heap pages filled with zeros
13995
+ * s - stack size
13996
+ * c - program code
13997
+ *
13998
+ * https://graypaper.fluffylabs.dev/#/579bd12/2b92022b9202
13999
+ */
14000
+ function decodeStandardProgram(program, args) {
14001
+ const decoder = Decoder.fromBlob(program);
14002
+ const oLength = decoder.u24();
14003
+ const wLength = decoder.u24();
14004
+ check `${args.length <= DATA_LEGNTH} Incorrect arguments length`;
14005
+ check `${oLength <= DATA_LEGNTH} Incorrect readonly segment length`;
14006
+ const readOnlyLength = oLength;
14007
+ check `${wLength <= DATA_LEGNTH} Incorrect heap segment length`;
14008
+ const heapLength = wLength;
14009
+ const noOfHeapZerosPages = decoder.u16();
14010
+ const stackSize = decoder.u24();
14011
+ const readOnlyMemory = decoder.bytes(readOnlyLength).raw;
14012
+ const initialHeap = decoder.bytes(heapLength).raw;
14013
+ const codeLength = decoder.u32();
14014
+ const code = decoder.bytes(codeLength).raw;
14015
+ decoder.finish();
14016
+ const readonlyDataStart = SEGMENT_SIZE;
14017
+ const readonlyDataEnd = SEGMENT_SIZE + alignToPageSize(readOnlyLength);
14018
+ const heapDataStart = 2 * SEGMENT_SIZE + alignToSegmentSize(readOnlyLength);
14019
+ const heapDataEnd = heapDataStart + alignToPageSize(heapLength);
14020
+ const heapZerosEnd = heapDataStart + alignToPageSize(heapLength) + noOfHeapZerosPages * PAGE_SIZE;
14021
+ const stackStart = STACK_SEGMENT - alignToPageSize(stackSize);
14022
+ const stackEnd = STACK_SEGMENT;
14023
+ const argsStart = ARGS_SEGMENT;
14024
+ const argsEnd = argsStart + alignToPageSize(args.length);
14025
+ const argsZerosEnd = argsEnd + alignToPageSize(args.length);
14026
+ function nonEmpty(s) {
14027
+ return s !== false;
14028
+ }
14029
+ const readableMemory = [
14030
+ readOnlyLength > 0 && getMemorySegment(readonlyDataStart, readonlyDataEnd, readOnlyMemory),
14031
+ args.length > 0 && getMemorySegment(argsStart, argsEnd, args),
14032
+ argsEnd < argsZerosEnd && getMemorySegment(argsEnd, argsZerosEnd),
14033
+ ].filter(nonEmpty);
14034
+ const writeableMemory = [
14035
+ heapLength > 0 && getMemorySegment(heapDataStart, heapDataEnd, initialHeap),
14036
+ heapDataEnd < heapZerosEnd && getMemorySegment(heapDataEnd, heapZerosEnd),
14037
+ stackStart < stackEnd && getMemorySegment(stackStart, stackEnd),
14038
+ ].filter(nonEmpty);
14039
+ return new SpiProgram(code, new SpiMemory(readableMemory, writeableMemory, heapZerosEnd, stackStart), getRegisters(args.length));
14040
+ }
14041
+ function getMemorySegment(start, end, data = null) {
14042
+ return new MemorySegment(start, end, data);
14043
+ }
14044
+ function getRegisters(argsLength) {
14045
+ const regs = new BigUint64Array(NO_OF_REGISTERS);
14046
+ // GP reference: https://graypaper.fluffylabs.dev/#/579bd12/2c7c012cb101
14047
+ regs[0] = BigInt(LAST_PAGE);
14048
+ regs[1] = BigInt(STACK_SEGMENT);
14049
+ regs[7] = BigInt(ARGS_SEGMENT);
14050
+ regs[8] = BigInt(argsLength);
14051
+ return regs;
14052
+ }
14053
+
14054
+ var index$7 = /*#__PURE__*/Object.freeze({
14055
+ __proto__: null,
14056
+ MemorySegment: MemorySegment,
14057
+ SpiMemory: SpiMemory,
14058
+ SpiProgram: SpiProgram,
14059
+ decodeStandardProgram: decodeStandardProgram
14060
+ });
14061
+
14062
+ class Program {
14063
+ code;
14064
+ registers;
14065
+ memory;
14066
+ metadata;
14067
+ static fromSpi(blob, args, hasMetadata) {
14068
+ const { code: spiCode, metadata } = hasMetadata ? extractCodeAndMetadata(blob) : { code: blob };
14069
+ const { code, memory: rawMemory, registers } = decodeStandardProgram(spiCode, args);
14070
+ const regs = new Registers();
14071
+ regs.copyFrom(registers);
14072
+ const memoryBuilder = new MemoryBuilder();
14073
+ for (const { start, end, data } of rawMemory.readable) {
14074
+ const startIndex = tryAsMemoryIndex(start);
14075
+ const endIndex = tryAsMemoryIndex(end);
14076
+ memoryBuilder.setReadablePages(startIndex, endIndex, data ?? new Uint8Array());
14077
+ }
14078
+ for (const { start, end, data } of rawMemory.writeable) {
14079
+ const startIndex = tryAsMemoryIndex(start);
14080
+ const endIndex = tryAsMemoryIndex(end);
14081
+ memoryBuilder.setWriteablePages(startIndex, endIndex, data ?? new Uint8Array());
14082
+ }
14083
+ const heapStart = tryAsMemoryIndex(rawMemory.sbrkIndex);
14084
+ const heapEnd = tryAsSbrkIndex(rawMemory.heapEnd);
14085
+ const memory = memoryBuilder.finalize(heapStart, heapEnd);
14086
+ return new Program(code, regs, memory, metadata);
14087
+ }
14088
+ static fromGeneric(blob, hasMetadata) {
14089
+ const { code, metadata } = hasMetadata ? extractCodeAndMetadata(blob) : { code: blob };
14090
+ const regs = new Registers();
14091
+ const memory = new Memory();
14092
+ return new Program(code, regs, memory, metadata);
14093
+ }
14094
+ constructor(code, registers, memory, metadata = new Uint8Array()) {
14095
+ this.code = code;
14096
+ this.registers = registers;
14097
+ this.memory = memory;
14098
+ this.metadata = metadata;
14099
+ }
14100
+ }
14101
+ /**
14102
+ * A function that splits preimage into metadata and code.
14103
+ *
14104
+ * https://graypaper.fluffylabs.dev/#/cc517d7/109a01109a01?v=0.6.5
14105
+ */
14106
+ function extractCodeAndMetadata(blobWithMetadata) {
14107
+ const decoder = Decoder.fromBlob(blobWithMetadata);
14108
+ const metadata = decoder.bytesBlob().raw;
14109
+ const code = decoder.remainingBytes().raw;
14110
+ return { metadata, code };
14111
+ }
14112
+
14113
+ var index$6 = /*#__PURE__*/Object.freeze({
14114
+ __proto__: null,
14115
+ Program: Program,
14116
+ extractCodeAndMetadata: extractCodeAndMetadata
14117
+ });
14118
+
14119
+ /**
14120
+ * Upper bound of instruction distance - it is equal to max value of GP's skip function + 1
14121
+ */
14122
+ const MAX_INSTRUCTION_DISTANCE = 25;
14123
+ /**
14124
+ * Mask class is an implementation of skip function defined in GP.
14125
+ *
14126
+ * https://graypaper.fluffylabs.dev/#/5f542d7/237201239801
14127
+ */
14128
+ class Mask {
14129
+ /**
14130
+ * The lookup table will have `0` at the index which corresponds to an instruction on the same index in the bytecode.
14131
+ * In case the value is non-zero it signifies the offset to the index with next instruction.
14132
+ *
14133
+ * Example:
14134
+ * ```
14135
+ * 0..1..2..3..4..5..6..7..8..9 # Indices
14136
+ * 0..2..1..0..1..0..3..2..1..0 # lookupTable forward values
14137
+ * ```
14138
+ * There are instructions at indices `0, 3, 5, 9`.
14139
+ */
14140
+ lookupTableForward;
14141
+ constructor(mask) {
14142
+ this.lookupTableForward = this.buildLookupTableForward(mask);
14143
+ }
14144
+ isInstruction(index) {
14145
+ return this.lookupTableForward[index] === 0;
14146
+ }
14147
+ getNoOfBytesToNextInstruction(index) {
14148
+ check `${index >= 0} index (${index}) cannot be a negative number`;
14149
+ return Math.min(this.lookupTableForward[index] ?? 0, MAX_INSTRUCTION_DISTANCE);
14150
+ }
14151
+ buildLookupTableForward(mask) {
14152
+ const table = safeAllocUint8Array(mask.bitLength);
14153
+ let lastInstructionOffset = 0;
14154
+ for (let i = mask.bitLength - 1; i >= 0; i--) {
14155
+ if (mask.isSet(i)) {
14156
+ lastInstructionOffset = 0;
14157
+ }
14158
+ else {
14159
+ lastInstructionOffset++;
14160
+ }
14161
+ table[i] = lastInstructionOffset;
14162
+ }
14163
+ return table;
14164
+ }
14165
+ static empty() {
14166
+ return new Mask(BitVec.empty(0));
14167
+ }
14168
+ }
14169
+
14170
+ var ArgumentType;
14171
+ (function (ArgumentType) {
14172
+ ArgumentType[ArgumentType["NO_ARGUMENTS"] = 0] = "NO_ARGUMENTS";
14173
+ ArgumentType[ArgumentType["ONE_IMMEDIATE"] = 1] = "ONE_IMMEDIATE";
14174
+ ArgumentType[ArgumentType["TWO_IMMEDIATES"] = 2] = "TWO_IMMEDIATES";
14175
+ ArgumentType[ArgumentType["ONE_OFFSET"] = 3] = "ONE_OFFSET";
14176
+ ArgumentType[ArgumentType["ONE_REGISTER_ONE_IMMEDIATE"] = 4] = "ONE_REGISTER_ONE_IMMEDIATE";
14177
+ ArgumentType[ArgumentType["ONE_REGISTER_TWO_IMMEDIATES"] = 5] = "ONE_REGISTER_TWO_IMMEDIATES";
14178
+ ArgumentType[ArgumentType["ONE_REGISTER_ONE_IMMEDIATE_ONE_OFFSET"] = 6] = "ONE_REGISTER_ONE_IMMEDIATE_ONE_OFFSET";
14179
+ ArgumentType[ArgumentType["TWO_REGISTERS"] = 7] = "TWO_REGISTERS";
14180
+ ArgumentType[ArgumentType["TWO_REGISTERS_ONE_IMMEDIATE"] = 8] = "TWO_REGISTERS_ONE_IMMEDIATE";
14181
+ ArgumentType[ArgumentType["TWO_REGISTERS_ONE_OFFSET"] = 9] = "TWO_REGISTERS_ONE_OFFSET";
14182
+ ArgumentType[ArgumentType["TWO_REGISTERS_TWO_IMMEDIATES"] = 10] = "TWO_REGISTERS_TWO_IMMEDIATES";
14183
+ ArgumentType[ArgumentType["THREE_REGISTERS"] = 11] = "THREE_REGISTERS";
14184
+ ArgumentType[ArgumentType["ONE_REGISTER_ONE_EXTENDED_WIDTH_IMMEDIATE"] = 12] = "ONE_REGISTER_ONE_EXTENDED_WIDTH_IMMEDIATE";
14185
+ })(ArgumentType || (ArgumentType = {}));
14186
+
14187
+ const BUFFER_SIZE = 8;
14188
+ const IMMEDIATE_SIZE$1 = 4;
14189
+ const U32_INDEX = 0;
14190
+ const U64_INDEX = 0;
14191
+ class ImmediateDecoder {
14192
+ u32;
14193
+ i32;
14194
+ u64;
14195
+ i64;
14196
+ view;
14197
+ bytes;
14198
+ constructor() {
14199
+ const buffer = new ArrayBuffer(BUFFER_SIZE);
14200
+ this.u32 = new Uint32Array(buffer);
14201
+ this.i32 = new Int32Array(buffer);
14202
+ this.u64 = new BigUint64Array(buffer);
14203
+ this.i64 = new BigInt64Array(buffer);
14204
+ this.view = new DataView(buffer);
14205
+ this.bytes = new Uint8Array(buffer);
14206
+ }
14207
+ setBytes(bytes) {
14208
+ const n = bytes.length;
14209
+ const msb = n > 0 ? bytes[n - 1] & 0x80 : 0;
14210
+ const noOfBytes = Math.min(n, BUFFER_SIZE);
14211
+ const prefix = msb !== 0 ? 0xff : 0x00;
14212
+ for (let i = 0; i < noOfBytes; i++) {
14213
+ this.view.setUint8(i, bytes[i]);
14214
+ }
14215
+ for (let i = n; i < BUFFER_SIZE; i++) {
14216
+ this.view.setUint8(i, prefix);
14217
+ }
14218
+ }
14219
+ /**
14220
+ * @deprecated Use getU32 instead
14221
+ */
14222
+ getUnsigned() {
14223
+ return this.u32[U32_INDEX];
14224
+ }
14225
+ /**
14226
+ * @deprecated Use getI32 instead
14227
+ */
14228
+ getSigned() {
14229
+ return this.i32[U32_INDEX];
14230
+ }
14231
+ getU32() {
14232
+ return this.u32[U32_INDEX];
14233
+ }
14234
+ getI32() {
14235
+ return this.i32[U32_INDEX];
14236
+ }
14237
+ getU64() {
14238
+ return this.u64[U64_INDEX];
14239
+ }
14240
+ getI64() {
14241
+ return this.i64[U64_INDEX];
14242
+ }
14243
+ getBytesAsLittleEndian() {
14244
+ return this.bytes.subarray(0, IMMEDIATE_SIZE$1);
14245
+ }
14246
+ getExtendedBytesAsLittleEndian() {
14247
+ return this.bytes;
14248
+ }
14249
+ }
14250
+
14251
+ const MAX_REGISTER_INDEX = NO_OF_REGISTERS$1 - 1;
14252
+ const MAX_LENGTH = 4;
14253
+ class NibblesDecoder {
14254
+ byte = new Int8Array(1);
14255
+ setByte(byte) {
14256
+ this.byte[0] = byte;
14257
+ }
14258
+ getHighNibble() {
14259
+ return (this.byte[0] & 0xf0) >>> 4;
14260
+ }
14261
+ getLowNibble() {
14262
+ return this.byte[0] & 0x0f;
14263
+ }
14264
+ getHighNibbleAsRegisterIndex() {
14265
+ return Math.min(this.getHighNibble(), MAX_REGISTER_INDEX);
14266
+ }
14267
+ getLowNibbleAsRegisterIndex() {
14268
+ return Math.min(this.getLowNibble(), MAX_REGISTER_INDEX);
14269
+ }
14270
+ getHighNibbleAsLength() {
14271
+ return Math.min(this.getHighNibble(), MAX_LENGTH);
14272
+ }
14273
+ getLowNibbleAsLength() {
14274
+ return Math.min(this.getLowNibble(), MAX_LENGTH);
14275
+ }
14276
+ }
14277
+
14278
+ const IMMEDIATE_AND_OFFSET_MAX_LENGTH = 4;
14279
+ class ArgsDecoder {
14280
+ nibblesDecoder = new NibblesDecoder();
14281
+ offsetDecoder = new ImmediateDecoder();
14282
+ code = new Uint8Array();
14283
+ mask = Mask.empty();
14284
+ reset(code, mask) {
14285
+ this.code = code;
14286
+ this.mask = mask;
14287
+ }
14288
+ fillArgs(pc, result) {
14289
+ const nextInstructionDistance = 1 + this.mask.getNoOfBytesToNextInstruction(pc + 1);
14290
+ result.noOfBytesToSkip = nextInstructionDistance;
14291
+ switch (result.type) {
14292
+ case ArgumentType.NO_ARGUMENTS:
14293
+ break;
14294
+ case ArgumentType.ONE_IMMEDIATE: {
14295
+ const immediateLength = Math.min(IMMEDIATE_AND_OFFSET_MAX_LENGTH, nextInstructionDistance - 1);
14296
+ const argsStartIndex = pc + 1;
14297
+ result.immediateDecoder.setBytes(this.code.subarray(argsStartIndex, argsStartIndex + immediateLength));
14298
+ break;
14299
+ }
14300
+ case ArgumentType.THREE_REGISTERS: {
14301
+ const firstByte = this.code[pc + 1];
14302
+ const secondByte = this.code[pc + 2];
14303
+ this.nibblesDecoder.setByte(firstByte);
14304
+ result.firstRegisterIndex = this.nibblesDecoder.getLowNibbleAsRegisterIndex();
14305
+ result.secondRegisterIndex = this.nibblesDecoder.getHighNibbleAsRegisterIndex();
14306
+ this.nibblesDecoder.setByte(secondByte);
14307
+ result.thirdRegisterIndex = this.nibblesDecoder.getLowNibbleAsRegisterIndex();
14308
+ break;
14309
+ }
14310
+ case ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE: {
14311
+ const firstByte = this.code[pc + 1];
14312
+ this.nibblesDecoder.setByte(firstByte);
14313
+ result.firstRegisterIndex = this.nibblesDecoder.getLowNibbleAsRegisterIndex();
14314
+ result.secondRegisterIndex = this.nibblesDecoder.getHighNibbleAsRegisterIndex();
14315
+ const immediateLength = Math.min(IMMEDIATE_AND_OFFSET_MAX_LENGTH, Math.max(0, nextInstructionDistance - 2));
14316
+ const immediateStartIndex = pc + 2;
14317
+ const immediateEndIndex = immediateStartIndex + immediateLength;
14318
+ result.immediateDecoder.setBytes(this.code.subarray(immediateStartIndex, immediateEndIndex));
14319
+ break;
14320
+ }
14321
+ case ArgumentType.ONE_REGISTER_ONE_IMMEDIATE_ONE_OFFSET: {
14322
+ const firstByte = this.code[pc + 1];
14323
+ this.nibblesDecoder.setByte(firstByte);
14324
+ result.registerIndex = this.nibblesDecoder.getLowNibbleAsRegisterIndex();
14325
+ const immediateLength = this.nibblesDecoder.getHighNibbleAsLength();
14326
+ const immediateStartIndex = pc + 2;
14327
+ const immediateEndIndex = immediateStartIndex + immediateLength;
14328
+ result.immediateDecoder.setBytes(this.code.subarray(immediateStartIndex, immediateEndIndex));
14329
+ const offsetLength = Math.min(IMMEDIATE_AND_OFFSET_MAX_LENGTH, Math.max(0, nextInstructionDistance - 2 - immediateLength));
14330
+ const offsetStartIndex = pc + 2 + immediateLength;
14331
+ const offsetEndIndex = offsetStartIndex + offsetLength;
14332
+ this.offsetDecoder.setBytes(this.code.subarray(offsetStartIndex, offsetEndIndex));
14333
+ result.nextPc = pc + this.offsetDecoder.getSigned();
14334
+ break;
14335
+ }
14336
+ case ArgumentType.TWO_REGISTERS_ONE_OFFSET: {
14337
+ const firstByte = this.code[pc + 1];
14338
+ this.nibblesDecoder.setByte(firstByte);
14339
+ result.firstRegisterIndex = this.nibblesDecoder.getLowNibbleAsRegisterIndex();
14340
+ result.secondRegisterIndex = this.nibblesDecoder.getHighNibbleAsRegisterIndex();
14341
+ const offsetLength = Math.min(IMMEDIATE_AND_OFFSET_MAX_LENGTH, Math.max(0, nextInstructionDistance - 2));
14342
+ const offsetStartIndex = pc + 2;
14343
+ const offsetEndIndex = offsetStartIndex + offsetLength;
14344
+ this.offsetDecoder.setBytes(this.code.subarray(offsetStartIndex, offsetEndIndex));
14345
+ result.nextPc = pc + this.offsetDecoder.getSigned();
14346
+ break;
14347
+ }
14348
+ case ArgumentType.TWO_REGISTERS: {
14349
+ const firstByte = this.code[pc + 1];
14350
+ this.nibblesDecoder.setByte(firstByte);
14351
+ result.firstRegisterIndex = this.nibblesDecoder.getHighNibbleAsRegisterIndex();
14352
+ result.secondRegisterIndex = this.nibblesDecoder.getLowNibbleAsRegisterIndex();
14353
+ break;
14354
+ }
14355
+ case ArgumentType.ONE_OFFSET: {
14356
+ const offsetLength = Math.min(IMMEDIATE_AND_OFFSET_MAX_LENGTH, nextInstructionDistance - 1);
14357
+ const offsetStartIndex = pc + 1;
14358
+ const offsetEndIndex = offsetStartIndex + offsetLength;
14359
+ const offsetBytes = this.code.subarray(offsetStartIndex, offsetEndIndex);
14360
+ this.offsetDecoder.setBytes(offsetBytes);
14361
+ const offsetValue = this.offsetDecoder.getSigned();
14362
+ result.nextPc = pc + offsetValue;
14363
+ break;
14364
+ }
14365
+ case ArgumentType.ONE_REGISTER_ONE_IMMEDIATE: {
14366
+ const firstByte = this.code[pc + 1];
14367
+ this.nibblesDecoder.setByte(firstByte);
14368
+ result.registerIndex = this.nibblesDecoder.getLowNibbleAsRegisterIndex();
14369
+ const immediateLength = Math.min(IMMEDIATE_AND_OFFSET_MAX_LENGTH, Math.max(0, nextInstructionDistance - 2));
14370
+ const immediateStartIndex = pc + 2;
14371
+ const immediateEndIndex = immediateStartIndex + immediateLength;
14372
+ const immediateBytes = this.code.subarray(immediateStartIndex, immediateEndIndex);
14373
+ result.immediateDecoder.setBytes(immediateBytes);
14374
+ break;
14375
+ }
14376
+ case ArgumentType.TWO_IMMEDIATES: {
14377
+ const firstByte = this.code[pc + 1];
14378
+ this.nibblesDecoder.setByte(firstByte);
14379
+ const firstImmediateLength = this.nibblesDecoder.getLowNibbleAsLength();
14380
+ const firstImmediateStartIndex = pc + 2;
14381
+ const firstImmediateEndIndex = firstImmediateStartIndex + firstImmediateLength;
14382
+ const firstImmediateBytes = this.code.subarray(firstImmediateStartIndex, firstImmediateEndIndex);
14383
+ result.firstImmediateDecoder.setBytes(firstImmediateBytes);
14384
+ const secondImmediateLength = Math.min(IMMEDIATE_AND_OFFSET_MAX_LENGTH, Math.max(0, nextInstructionDistance - 2 - firstImmediateLength));
14385
+ const secondImmediateStartIndex = firstImmediateEndIndex;
14386
+ const secondImmediateEndIndex = secondImmediateStartIndex + secondImmediateLength;
14387
+ const secondImmediateBytes = this.code.subarray(secondImmediateStartIndex, secondImmediateEndIndex);
14388
+ result.secondImmediateDecoder.setBytes(secondImmediateBytes);
14389
+ break;
14390
+ }
14391
+ case ArgumentType.ONE_REGISTER_TWO_IMMEDIATES: {
14392
+ const firstByte = this.code[pc + 1];
14393
+ this.nibblesDecoder.setByte(firstByte);
14394
+ result.registerIndex = this.nibblesDecoder.getLowNibbleAsRegisterIndex();
14395
+ const firstImmediateLength = this.nibblesDecoder.getHighNibbleAsLength();
14396
+ const firstImmediateStartIndex = pc + 2;
14397
+ const firstImmediateEndIndex = firstImmediateStartIndex + firstImmediateLength;
14398
+ const firstImmediateBytes = this.code.subarray(firstImmediateStartIndex, firstImmediateEndIndex);
14399
+ result.firstImmediateDecoder.setBytes(firstImmediateBytes);
14400
+ const secondImmediateLength = Math.min(IMMEDIATE_AND_OFFSET_MAX_LENGTH, Math.max(0, nextInstructionDistance - 2 - firstImmediateLength));
14401
+ const secondImmediateStartIndex = firstImmediateEndIndex;
14402
+ const secondImmediateEndIndex = secondImmediateStartIndex + secondImmediateLength;
14403
+ const secondImmediateBytes = this.code.subarray(secondImmediateStartIndex, secondImmediateEndIndex);
14404
+ result.secondImmediateDecoder.setBytes(secondImmediateBytes);
14405
+ break;
14406
+ }
14407
+ case ArgumentType.TWO_REGISTERS_TWO_IMMEDIATES: {
14408
+ const firstByte = this.code[pc + 1];
14409
+ this.nibblesDecoder.setByte(firstByte);
14410
+ result.firstRegisterIndex = this.nibblesDecoder.getLowNibbleAsRegisterIndex();
14411
+ result.secondRegisterIndex = this.nibblesDecoder.getHighNibbleAsRegisterIndex();
14412
+ const secondByte = this.code[pc + 2];
14413
+ this.nibblesDecoder.setByte(secondByte);
14414
+ const firstImmediateLength = this.nibblesDecoder.getLowNibbleAsLength();
14415
+ const firstImmediateStartIndex = pc + 3;
14416
+ const firstImmediateEndIndex = firstImmediateStartIndex + firstImmediateLength;
14417
+ const firstImmediateBytes = this.code.subarray(firstImmediateStartIndex, firstImmediateEndIndex);
14418
+ result.firstImmediateDecoder.setBytes(firstImmediateBytes);
14419
+ const secondImmediateLength = Math.min(IMMEDIATE_AND_OFFSET_MAX_LENGTH, Math.max(0, nextInstructionDistance - 3 - firstImmediateLength));
14420
+ const secondImmediateStartIndex = firstImmediateEndIndex;
14421
+ const secondImmediateEndIndex = secondImmediateStartIndex + secondImmediateLength;
14422
+ const secondImmediateBytes = this.code.subarray(secondImmediateStartIndex, secondImmediateEndIndex);
14423
+ result.secondImmediateDecoder.setBytes(secondImmediateBytes);
14424
+ break;
14425
+ }
14426
+ case ArgumentType.ONE_REGISTER_ONE_EXTENDED_WIDTH_IMMEDIATE: {
14427
+ const firstByte = this.code[pc + 1];
14428
+ this.nibblesDecoder.setByte(firstByte);
14429
+ result.registerIndex = this.nibblesDecoder.getLowNibbleAsRegisterIndex();
14430
+ const immediateStartIndex = pc + 2;
14431
+ const immediateEndIndex = immediateStartIndex + 8;
14432
+ const immediateBytes = this.code.subarray(immediateStartIndex, immediateEndIndex);
14433
+ result.immediateDecoder.setBytes(immediateBytes);
14434
+ break;
14435
+ }
14436
+ }
14437
+ }
14438
+ }
14439
+
14440
+ const IMMEDIATE_SIZE = 8;
14441
+ class ExtendedWitdthImmediateDecoder {
14442
+ unsignedImmediate;
14443
+ bytes;
14444
+ constructor() {
14445
+ const buffer = new ArrayBuffer(IMMEDIATE_SIZE);
14446
+ this.unsignedImmediate = new BigUint64Array(buffer);
14447
+ this.bytes = new Uint8Array(buffer);
14448
+ }
14449
+ setBytes(bytes) {
14450
+ let i = 0;
14451
+ for (; i < bytes.length; i++) {
14452
+ this.bytes[i] = bytes[i];
14453
+ }
14454
+ for (; i < IMMEDIATE_SIZE; i++) {
14455
+ this.bytes[i] = 0;
14456
+ }
14457
+ }
14458
+ getValue() {
14459
+ return this.unsignedImmediate[0];
14460
+ }
14461
+ getBytesAsLittleEndian() {
14462
+ return this.bytes.subarray(0, IMMEDIATE_SIZE);
14463
+ }
14464
+ }
14465
+
14466
+ const ARGUMENT_TYPE_LENGTH = Object.keys(ArgumentType).length / 2;
14467
+ const createResults = () => {
14468
+ const results = new Array(ARGUMENT_TYPE_LENGTH);
14469
+ results[ArgumentType.NO_ARGUMENTS] = {
14470
+ type: ArgumentType.NO_ARGUMENTS,
14471
+ noOfBytesToSkip: 1,
14472
+ };
14473
+ results[ArgumentType.ONE_IMMEDIATE] = {
14474
+ type: ArgumentType.ONE_IMMEDIATE,
14475
+ noOfBytesToSkip: 1,
14476
+ immediateDecoder: new ImmediateDecoder(),
14477
+ };
14478
+ results[ArgumentType.TWO_REGISTERS] = {
14479
+ type: ArgumentType.TWO_REGISTERS,
14480
+ noOfBytesToSkip: 1,
14481
+ firstRegisterIndex: 0,
14482
+ secondRegisterIndex: 0,
14483
+ };
14484
+ results[ArgumentType.THREE_REGISTERS] = {
14485
+ type: ArgumentType.THREE_REGISTERS,
14486
+ noOfBytesToSkip: 1,
14487
+ firstRegisterIndex: 0,
14488
+ secondRegisterIndex: 0,
14489
+ thirdRegisterIndex: 0,
14490
+ };
14491
+ results[ArgumentType.ONE_REGISTER_ONE_IMMEDIATE_ONE_OFFSET] = {
14492
+ type: ArgumentType.ONE_REGISTER_ONE_IMMEDIATE_ONE_OFFSET,
14493
+ noOfBytesToSkip: 1,
14494
+ registerIndex: 0,
14495
+ immediateDecoder: new ImmediateDecoder(),
14496
+ nextPc: 0,
14497
+ };
14498
+ results[ArgumentType.TWO_REGISTERS_ONE_OFFSET] = {
14499
+ type: ArgumentType.TWO_REGISTERS_ONE_OFFSET,
14500
+ noOfBytesToSkip: 1,
14501
+ firstRegisterIndex: 0,
14502
+ secondRegisterIndex: 0,
14503
+ nextPc: 0,
14504
+ };
14505
+ results[ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE] = {
14506
+ type: ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE,
14507
+ noOfBytesToSkip: 1,
14508
+ firstRegisterIndex: 0,
14509
+ secondRegisterIndex: 0,
14510
+ immediateDecoder: new ImmediateDecoder(),
14511
+ };
14512
+ results[ArgumentType.ONE_REGISTER_ONE_IMMEDIATE] = {
14513
+ type: ArgumentType.ONE_REGISTER_ONE_IMMEDIATE,
14514
+ noOfBytesToSkip: 1,
14515
+ registerIndex: 0,
14516
+ immediateDecoder: new ImmediateDecoder(),
14517
+ };
14518
+ results[ArgumentType.ONE_REGISTER_TWO_IMMEDIATES] = {
14519
+ type: ArgumentType.ONE_REGISTER_TWO_IMMEDIATES,
14520
+ noOfBytesToSkip: 1,
14521
+ registerIndex: 0,
14522
+ firstImmediateDecoder: new ImmediateDecoder(),
14523
+ secondImmediateDecoder: new ImmediateDecoder(),
14524
+ };
14525
+ results[ArgumentType.ONE_OFFSET] = {
14526
+ type: ArgumentType.ONE_OFFSET,
14527
+ noOfBytesToSkip: 1,
14528
+ nextPc: 0,
14529
+ };
14530
+ results[ArgumentType.TWO_IMMEDIATES] = {
14531
+ type: ArgumentType.TWO_IMMEDIATES,
14532
+ noOfBytesToSkip: 1,
14533
+ firstImmediateDecoder: new ImmediateDecoder(),
14534
+ secondImmediateDecoder: new ImmediateDecoder(),
14535
+ };
14536
+ results[ArgumentType.TWO_REGISTERS_TWO_IMMEDIATES] = {
14537
+ type: ArgumentType.TWO_REGISTERS_TWO_IMMEDIATES,
14538
+ noOfBytesToSkip: 1,
14539
+ firstImmediateDecoder: new ImmediateDecoder(),
14540
+ secondImmediateDecoder: new ImmediateDecoder(),
14541
+ firstRegisterIndex: 0,
14542
+ secondRegisterIndex: 0,
14543
+ };
14544
+ results[ArgumentType.ONE_REGISTER_ONE_EXTENDED_WIDTH_IMMEDIATE] = {
14545
+ type: ArgumentType.ONE_REGISTER_ONE_EXTENDED_WIDTH_IMMEDIATE,
14546
+ noOfBytesToSkip: 9,
14547
+ registerIndex: 0,
14548
+ immediateDecoder: new ExtendedWitdthImmediateDecoder(),
14549
+ };
14550
+ return results;
14551
+ };
14552
+
14553
+ var Instruction;
14554
+ (function (Instruction) {
14555
+ Instruction[Instruction["TRAP"] = 0] = "TRAP";
14556
+ Instruction[Instruction["FALLTHROUGH"] = 1] = "FALLTHROUGH";
14557
+ Instruction[Instruction["ECALLI"] = 10] = "ECALLI";
14558
+ Instruction[Instruction["LOAD_IMM_64"] = 20] = "LOAD_IMM_64";
14559
+ Instruction[Instruction["STORE_IMM_U8"] = 30] = "STORE_IMM_U8";
14560
+ Instruction[Instruction["STORE_IMM_U16"] = 31] = "STORE_IMM_U16";
14561
+ Instruction[Instruction["STORE_IMM_U32"] = 32] = "STORE_IMM_U32";
14562
+ Instruction[Instruction["STORE_IMM_U64"] = 33] = "STORE_IMM_U64";
14563
+ Instruction[Instruction["JUMP"] = 40] = "JUMP";
14564
+ Instruction[Instruction["JUMP_IND"] = 50] = "JUMP_IND";
14565
+ Instruction[Instruction["LOAD_IMM"] = 51] = "LOAD_IMM";
14566
+ Instruction[Instruction["LOAD_U8"] = 52] = "LOAD_U8";
14567
+ Instruction[Instruction["LOAD_I8"] = 53] = "LOAD_I8";
14568
+ Instruction[Instruction["LOAD_U16"] = 54] = "LOAD_U16";
14569
+ Instruction[Instruction["LOAD_I16"] = 55] = "LOAD_I16";
14570
+ Instruction[Instruction["LOAD_U32"] = 56] = "LOAD_U32";
14571
+ Instruction[Instruction["LOAD_I32"] = 57] = "LOAD_I32";
14572
+ Instruction[Instruction["LOAD_U64"] = 58] = "LOAD_U64";
14573
+ Instruction[Instruction["STORE_U8"] = 59] = "STORE_U8";
14574
+ Instruction[Instruction["STORE_U16"] = 60] = "STORE_U16";
14575
+ Instruction[Instruction["STORE_U32"] = 61] = "STORE_U32";
14576
+ Instruction[Instruction["STORE_U64"] = 62] = "STORE_U64";
14577
+ Instruction[Instruction["STORE_IMM_IND_U8"] = 70] = "STORE_IMM_IND_U8";
14578
+ Instruction[Instruction["STORE_IMM_IND_U16"] = 71] = "STORE_IMM_IND_U16";
14579
+ Instruction[Instruction["STORE_IMM_IND_U32"] = 72] = "STORE_IMM_IND_U32";
14580
+ Instruction[Instruction["STORE_IMM_IND_U64"] = 73] = "STORE_IMM_IND_U64";
14581
+ Instruction[Instruction["LOAD_IMM_JUMP"] = 80] = "LOAD_IMM_JUMP";
14582
+ Instruction[Instruction["BRANCH_EQ_IMM"] = 81] = "BRANCH_EQ_IMM";
14583
+ Instruction[Instruction["BRANCH_NE_IMM"] = 82] = "BRANCH_NE_IMM";
14584
+ Instruction[Instruction["BRANCH_LT_U_IMM"] = 83] = "BRANCH_LT_U_IMM";
14585
+ Instruction[Instruction["BRANCH_LE_U_IMM"] = 84] = "BRANCH_LE_U_IMM";
14586
+ Instruction[Instruction["BRANCH_GE_U_IMM"] = 85] = "BRANCH_GE_U_IMM";
14587
+ Instruction[Instruction["BRANCH_GT_U_IMM"] = 86] = "BRANCH_GT_U_IMM";
14588
+ Instruction[Instruction["BRANCH_LT_S_IMM"] = 87] = "BRANCH_LT_S_IMM";
14589
+ Instruction[Instruction["BRANCH_LE_S_IMM"] = 88] = "BRANCH_LE_S_IMM";
14590
+ Instruction[Instruction["BRANCH_GE_S_IMM"] = 89] = "BRANCH_GE_S_IMM";
14591
+ Instruction[Instruction["BRANCH_GT_S_IMM"] = 90] = "BRANCH_GT_S_IMM";
14592
+ Instruction[Instruction["MOVE_REG"] = 100] = "MOVE_REG";
14593
+ Instruction[Instruction["SBRK"] = 101] = "SBRK";
14594
+ Instruction[Instruction["COUNT_SET_BITS_64"] = 102] = "COUNT_SET_BITS_64";
14595
+ Instruction[Instruction["COUNT_SET_BITS_32"] = 103] = "COUNT_SET_BITS_32";
14596
+ Instruction[Instruction["LEADING_ZERO_BITS_64"] = 104] = "LEADING_ZERO_BITS_64";
14597
+ Instruction[Instruction["LEADING_ZERO_BITS_32"] = 105] = "LEADING_ZERO_BITS_32";
14598
+ Instruction[Instruction["TRAILING_ZERO_BITS_64"] = 106] = "TRAILING_ZERO_BITS_64";
14599
+ Instruction[Instruction["TRAILING_ZERO_BITS_32"] = 107] = "TRAILING_ZERO_BITS_32";
14600
+ Instruction[Instruction["SIGN_EXTEND_8"] = 108] = "SIGN_EXTEND_8";
14601
+ Instruction[Instruction["SIGN_EXTEND_16"] = 109] = "SIGN_EXTEND_16";
14602
+ Instruction[Instruction["ZERO_EXTEND_16"] = 110] = "ZERO_EXTEND_16";
14603
+ Instruction[Instruction["REVERSE_BYTES"] = 111] = "REVERSE_BYTES";
14604
+ Instruction[Instruction["STORE_IND_U8"] = 120] = "STORE_IND_U8";
14605
+ Instruction[Instruction["STORE_IND_U16"] = 121] = "STORE_IND_U16";
14606
+ Instruction[Instruction["STORE_IND_U32"] = 122] = "STORE_IND_U32";
14607
+ Instruction[Instruction["STORE_IND_U64"] = 123] = "STORE_IND_U64";
14608
+ Instruction[Instruction["LOAD_IND_U8"] = 124] = "LOAD_IND_U8";
14609
+ Instruction[Instruction["LOAD_IND_I8"] = 125] = "LOAD_IND_I8";
14610
+ Instruction[Instruction["LOAD_IND_U16"] = 126] = "LOAD_IND_U16";
14611
+ Instruction[Instruction["LOAD_IND_I16"] = 127] = "LOAD_IND_I16";
14612
+ Instruction[Instruction["LOAD_IND_U32"] = 128] = "LOAD_IND_U32";
14613
+ Instruction[Instruction["LOAD_IND_I32"] = 129] = "LOAD_IND_I32";
14614
+ Instruction[Instruction["LOAD_IND_U64"] = 130] = "LOAD_IND_U64";
14615
+ Instruction[Instruction["ADD_IMM_32"] = 131] = "ADD_IMM_32";
14616
+ Instruction[Instruction["AND_IMM"] = 132] = "AND_IMM";
14617
+ Instruction[Instruction["XOR_IMM"] = 133] = "XOR_IMM";
14618
+ Instruction[Instruction["OR_IMM"] = 134] = "OR_IMM";
14619
+ Instruction[Instruction["MUL_IMM_32"] = 135] = "MUL_IMM_32";
14620
+ Instruction[Instruction["SET_LT_U_IMM"] = 136] = "SET_LT_U_IMM";
14621
+ Instruction[Instruction["SET_LT_S_IMM"] = 137] = "SET_LT_S_IMM";
14622
+ Instruction[Instruction["SHLO_L_IMM_32"] = 138] = "SHLO_L_IMM_32";
14623
+ Instruction[Instruction["SHLO_R_IMM_32"] = 139] = "SHLO_R_IMM_32";
14624
+ Instruction[Instruction["SHAR_R_IMM_32"] = 140] = "SHAR_R_IMM_32";
14625
+ Instruction[Instruction["NEG_ADD_IMM_32"] = 141] = "NEG_ADD_IMM_32";
14626
+ Instruction[Instruction["SET_GT_U_IMM"] = 142] = "SET_GT_U_IMM";
14627
+ Instruction[Instruction["SET_GT_S_IMM"] = 143] = "SET_GT_S_IMM";
14628
+ Instruction[Instruction["SHLO_L_IMM_ALT_32"] = 144] = "SHLO_L_IMM_ALT_32";
14629
+ Instruction[Instruction["SHLO_R_IMM_ALT_32"] = 145] = "SHLO_R_IMM_ALT_32";
14630
+ Instruction[Instruction["SHAR_R_IMM_ALT_32"] = 146] = "SHAR_R_IMM_ALT_32";
14631
+ Instruction[Instruction["CMOV_IZ_IMM"] = 147] = "CMOV_IZ_IMM";
14632
+ Instruction[Instruction["CMOV_NZ_IMM"] = 148] = "CMOV_NZ_IMM";
14633
+ Instruction[Instruction["ADD_IMM_64"] = 149] = "ADD_IMM_64";
14634
+ Instruction[Instruction["MUL_IMM_64"] = 150] = "MUL_IMM_64";
14635
+ Instruction[Instruction["SHLO_L_IMM_64"] = 151] = "SHLO_L_IMM_64";
14636
+ Instruction[Instruction["SHLO_R_IMM_64"] = 152] = "SHLO_R_IMM_64";
14637
+ Instruction[Instruction["SHAR_R_IMM_64"] = 153] = "SHAR_R_IMM_64";
14638
+ Instruction[Instruction["NEG_ADD_IMM_64"] = 154] = "NEG_ADD_IMM_64";
14639
+ Instruction[Instruction["SHLO_L_IMM_ALT_64"] = 155] = "SHLO_L_IMM_ALT_64";
14640
+ Instruction[Instruction["SHLO_R_IMM_ALT_64"] = 156] = "SHLO_R_IMM_ALT_64";
14641
+ Instruction[Instruction["SHAR_R_IMM_ALT_64"] = 157] = "SHAR_R_IMM_ALT_64";
14642
+ Instruction[Instruction["ROT_R_64_IMM"] = 158] = "ROT_R_64_IMM";
14643
+ Instruction[Instruction["ROT_R_64_IMM_ALT"] = 159] = "ROT_R_64_IMM_ALT";
14644
+ Instruction[Instruction["ROT_R_32_IMM"] = 160] = "ROT_R_32_IMM";
14645
+ Instruction[Instruction["ROT_R_32_IMM_ALT"] = 161] = "ROT_R_32_IMM_ALT";
14646
+ Instruction[Instruction["BRANCH_EQ"] = 170] = "BRANCH_EQ";
14647
+ Instruction[Instruction["BRANCH_NE"] = 171] = "BRANCH_NE";
14648
+ Instruction[Instruction["BRANCH_LT_U"] = 172] = "BRANCH_LT_U";
14649
+ Instruction[Instruction["BRANCH_LT_S"] = 173] = "BRANCH_LT_S";
14650
+ Instruction[Instruction["BRANCH_GE_U"] = 174] = "BRANCH_GE_U";
14651
+ Instruction[Instruction["BRANCH_GE_S"] = 175] = "BRANCH_GE_S";
14652
+ Instruction[Instruction["LOAD_IMM_JUMP_IND"] = 180] = "LOAD_IMM_JUMP_IND";
14653
+ Instruction[Instruction["ADD_32"] = 190] = "ADD_32";
14654
+ Instruction[Instruction["SUB_32"] = 191] = "SUB_32";
14655
+ Instruction[Instruction["MUL_32"] = 192] = "MUL_32";
14656
+ Instruction[Instruction["DIV_U_32"] = 193] = "DIV_U_32";
14657
+ Instruction[Instruction["DIV_S_32"] = 194] = "DIV_S_32";
14658
+ Instruction[Instruction["REM_U_32"] = 195] = "REM_U_32";
14659
+ Instruction[Instruction["REM_S_32"] = 196] = "REM_S_32";
14660
+ Instruction[Instruction["SHLO_L_32"] = 197] = "SHLO_L_32";
14661
+ Instruction[Instruction["SHLO_R_32"] = 198] = "SHLO_R_32";
14662
+ Instruction[Instruction["SHAR_R_32"] = 199] = "SHAR_R_32";
14663
+ Instruction[Instruction["ADD_64"] = 200] = "ADD_64";
14664
+ Instruction[Instruction["SUB_64"] = 201] = "SUB_64";
14665
+ Instruction[Instruction["MUL_64"] = 202] = "MUL_64";
14666
+ Instruction[Instruction["DIV_U_64"] = 203] = "DIV_U_64";
14667
+ Instruction[Instruction["DIV_S_64"] = 204] = "DIV_S_64";
14668
+ Instruction[Instruction["REM_U_64"] = 205] = "REM_U_64";
14669
+ Instruction[Instruction["REM_S_64"] = 206] = "REM_S_64";
14670
+ Instruction[Instruction["SHLO_L_64"] = 207] = "SHLO_L_64";
14671
+ Instruction[Instruction["SHLO_R_64"] = 208] = "SHLO_R_64";
14672
+ Instruction[Instruction["SHAR_R_64"] = 209] = "SHAR_R_64";
14673
+ Instruction[Instruction["AND"] = 210] = "AND";
14674
+ Instruction[Instruction["XOR"] = 211] = "XOR";
14675
+ Instruction[Instruction["OR"] = 212] = "OR";
14676
+ Instruction[Instruction["MUL_UPPER_S_S"] = 213] = "MUL_UPPER_S_S";
14677
+ Instruction[Instruction["MUL_UPPER_U_U"] = 214] = "MUL_UPPER_U_U";
14678
+ Instruction[Instruction["MUL_UPPER_S_U"] = 215] = "MUL_UPPER_S_U";
14679
+ Instruction[Instruction["SET_LT_U"] = 216] = "SET_LT_U";
14680
+ Instruction[Instruction["SET_LT_S"] = 217] = "SET_LT_S";
14681
+ Instruction[Instruction["CMOV_IZ"] = 218] = "CMOV_IZ";
14682
+ Instruction[Instruction["CMOV_NZ"] = 219] = "CMOV_NZ";
14683
+ Instruction[Instruction["ROT_L_64"] = 220] = "ROT_L_64";
14684
+ Instruction[Instruction["ROT_L_32"] = 221] = "ROT_L_32";
14685
+ Instruction[Instruction["ROT_R_64"] = 222] = "ROT_R_64";
14686
+ Instruction[Instruction["ROT_R_32"] = 223] = "ROT_R_32";
14687
+ Instruction[Instruction["AND_INV"] = 224] = "AND_INV";
14688
+ Instruction[Instruction["OR_INV"] = 225] = "OR_INV";
14689
+ Instruction[Instruction["XNOR"] = 226] = "XNOR";
14690
+ Instruction[Instruction["MAX"] = 227] = "MAX";
14691
+ Instruction[Instruction["MAX_U"] = 228] = "MAX_U";
14692
+ Instruction[Instruction["MIN"] = 229] = "MIN";
14693
+ Instruction[Instruction["MIN_U"] = 230] = "MIN_U";
14694
+ })(Instruction || (Instruction = {}));
14695
+ const HIGHEST_INSTRUCTION_NUMBER = Instruction.MIN_U;
14696
+
14697
+ const instructionArgumentTypeMap = (() => {
14698
+ const instructionArgumentTypeMap = new Array(HIGHEST_INSTRUCTION_NUMBER + 1);
14699
+ instructionArgumentTypeMap[Instruction.TRAP] = ArgumentType.NO_ARGUMENTS;
14700
+ instructionArgumentTypeMap[Instruction.FALLTHROUGH] = ArgumentType.NO_ARGUMENTS;
14701
+ instructionArgumentTypeMap[Instruction.ECALLI] = ArgumentType.ONE_IMMEDIATE;
14702
+ instructionArgumentTypeMap[Instruction.LOAD_IMM_64] = ArgumentType.ONE_REGISTER_ONE_EXTENDED_WIDTH_IMMEDIATE;
14703
+ instructionArgumentTypeMap[Instruction.STORE_IMM_U8] = ArgumentType.TWO_IMMEDIATES;
14704
+ instructionArgumentTypeMap[Instruction.STORE_IMM_U16] = ArgumentType.TWO_IMMEDIATES;
14705
+ instructionArgumentTypeMap[Instruction.STORE_IMM_U32] = ArgumentType.TWO_IMMEDIATES;
14706
+ instructionArgumentTypeMap[Instruction.STORE_IMM_U64] = ArgumentType.TWO_IMMEDIATES;
14707
+ instructionArgumentTypeMap[Instruction.JUMP] = ArgumentType.ONE_OFFSET;
14708
+ instructionArgumentTypeMap[Instruction.JUMP_IND] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE;
14709
+ instructionArgumentTypeMap[Instruction.LOAD_IMM] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE;
14710
+ instructionArgumentTypeMap[Instruction.LOAD_U8] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE;
14711
+ instructionArgumentTypeMap[Instruction.LOAD_I8] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE;
14712
+ instructionArgumentTypeMap[Instruction.LOAD_U16] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE;
14713
+ instructionArgumentTypeMap[Instruction.LOAD_I16] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE;
14714
+ instructionArgumentTypeMap[Instruction.LOAD_U32] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE;
14715
+ instructionArgumentTypeMap[Instruction.LOAD_I32] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE;
14716
+ instructionArgumentTypeMap[Instruction.LOAD_U64] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE;
14717
+ instructionArgumentTypeMap[Instruction.STORE_U8] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE;
14718
+ instructionArgumentTypeMap[Instruction.STORE_U16] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE;
14719
+ instructionArgumentTypeMap[Instruction.STORE_U32] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE;
14720
+ instructionArgumentTypeMap[Instruction.STORE_U64] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE;
14721
+ instructionArgumentTypeMap[Instruction.STORE_IMM_IND_U8] = ArgumentType.ONE_REGISTER_TWO_IMMEDIATES;
14722
+ instructionArgumentTypeMap[Instruction.STORE_IMM_IND_U16] = ArgumentType.ONE_REGISTER_TWO_IMMEDIATES;
14723
+ instructionArgumentTypeMap[Instruction.STORE_IMM_IND_U32] = ArgumentType.ONE_REGISTER_TWO_IMMEDIATES;
14724
+ instructionArgumentTypeMap[Instruction.STORE_IMM_IND_U64] = ArgumentType.ONE_REGISTER_TWO_IMMEDIATES;
14725
+ instructionArgumentTypeMap[Instruction.LOAD_IMM_JUMP] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE_ONE_OFFSET;
14726
+ instructionArgumentTypeMap[Instruction.BRANCH_EQ_IMM] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE_ONE_OFFSET;
14727
+ instructionArgumentTypeMap[Instruction.BRANCH_NE_IMM] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE_ONE_OFFSET;
14728
+ instructionArgumentTypeMap[Instruction.BRANCH_LT_U_IMM] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE_ONE_OFFSET;
14729
+ instructionArgumentTypeMap[Instruction.BRANCH_LE_U_IMM] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE_ONE_OFFSET;
14730
+ instructionArgumentTypeMap[Instruction.BRANCH_GE_U_IMM] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE_ONE_OFFSET;
14731
+ instructionArgumentTypeMap[Instruction.BRANCH_GT_U_IMM] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE_ONE_OFFSET;
14732
+ instructionArgumentTypeMap[Instruction.BRANCH_LT_S_IMM] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE_ONE_OFFSET;
14733
+ instructionArgumentTypeMap[Instruction.BRANCH_LE_S_IMM] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE_ONE_OFFSET;
14734
+ instructionArgumentTypeMap[Instruction.BRANCH_GE_S_IMM] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE_ONE_OFFSET;
14735
+ instructionArgumentTypeMap[Instruction.BRANCH_GT_S_IMM] = ArgumentType.ONE_REGISTER_ONE_IMMEDIATE_ONE_OFFSET;
14736
+ instructionArgumentTypeMap[Instruction.MOVE_REG] = ArgumentType.TWO_REGISTERS;
14737
+ instructionArgumentTypeMap[Instruction.SBRK] = ArgumentType.TWO_REGISTERS;
14738
+ instructionArgumentTypeMap[Instruction.COUNT_SET_BITS_64] = ArgumentType.TWO_REGISTERS;
14739
+ instructionArgumentTypeMap[Instruction.COUNT_SET_BITS_32] = ArgumentType.TWO_REGISTERS;
14740
+ instructionArgumentTypeMap[Instruction.LEADING_ZERO_BITS_64] = ArgumentType.TWO_REGISTERS;
14741
+ instructionArgumentTypeMap[Instruction.LEADING_ZERO_BITS_32] = ArgumentType.TWO_REGISTERS;
14742
+ instructionArgumentTypeMap[Instruction.TRAILING_ZERO_BITS_64] = ArgumentType.TWO_REGISTERS;
14743
+ instructionArgumentTypeMap[Instruction.TRAILING_ZERO_BITS_32] = ArgumentType.TWO_REGISTERS;
14744
+ instructionArgumentTypeMap[Instruction.SIGN_EXTEND_8] = ArgumentType.TWO_REGISTERS;
14745
+ instructionArgumentTypeMap[Instruction.SIGN_EXTEND_16] = ArgumentType.TWO_REGISTERS;
14746
+ instructionArgumentTypeMap[Instruction.ZERO_EXTEND_16] = ArgumentType.TWO_REGISTERS;
14747
+ instructionArgumentTypeMap[Instruction.REVERSE_BYTES] = ArgumentType.TWO_REGISTERS;
14748
+ instructionArgumentTypeMap[Instruction.STORE_IND_U8] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
14749
+ instructionArgumentTypeMap[Instruction.STORE_IND_U16] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
14750
+ instructionArgumentTypeMap[Instruction.STORE_IND_U32] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
14751
+ instructionArgumentTypeMap[Instruction.STORE_IND_U64] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
14752
+ instructionArgumentTypeMap[Instruction.LOAD_IND_U8] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
14753
+ instructionArgumentTypeMap[Instruction.LOAD_IND_I8] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
14754
+ instructionArgumentTypeMap[Instruction.LOAD_IND_U16] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
14755
+ instructionArgumentTypeMap[Instruction.LOAD_IND_I16] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
14756
+ instructionArgumentTypeMap[Instruction.LOAD_IND_U32] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
14757
+ instructionArgumentTypeMap[Instruction.LOAD_IND_I32] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
14758
+ instructionArgumentTypeMap[Instruction.LOAD_IND_U64] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
14759
+ instructionArgumentTypeMap[Instruction.ADD_IMM_32] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
14760
+ instructionArgumentTypeMap[Instruction.ADD_IMM_64] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
14761
+ instructionArgumentTypeMap[Instruction.AND_IMM] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
14762
+ instructionArgumentTypeMap[Instruction.XOR_IMM] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
14763
+ instructionArgumentTypeMap[Instruction.OR_IMM] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
14764
+ instructionArgumentTypeMap[Instruction.MUL_IMM_32] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
14765
+ instructionArgumentTypeMap[Instruction.MUL_IMM_64] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
14766
+ instructionArgumentTypeMap[Instruction.SET_LT_U_IMM] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
14767
+ instructionArgumentTypeMap[Instruction.SET_LT_S_IMM] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
14768
+ instructionArgumentTypeMap[Instruction.SHLO_L_IMM_32] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
14769
+ instructionArgumentTypeMap[Instruction.SHLO_R_IMM_32] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
14770
+ instructionArgumentTypeMap[Instruction.SHAR_R_IMM_32] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
14771
+ instructionArgumentTypeMap[Instruction.NEG_ADD_IMM_32] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
14772
+ instructionArgumentTypeMap[Instruction.SHLO_L_IMM_64] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
14773
+ instructionArgumentTypeMap[Instruction.SHLO_R_IMM_64] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
14774
+ instructionArgumentTypeMap[Instruction.SHAR_R_IMM_64] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
14775
+ instructionArgumentTypeMap[Instruction.NEG_ADD_IMM_64] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
14776
+ instructionArgumentTypeMap[Instruction.SET_GT_U_IMM] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
14777
+ instructionArgumentTypeMap[Instruction.SET_GT_S_IMM] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
14778
+ instructionArgumentTypeMap[Instruction.SHLO_L_IMM_ALT_32] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
14779
+ instructionArgumentTypeMap[Instruction.SHLO_R_IMM_ALT_32] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
14780
+ instructionArgumentTypeMap[Instruction.SHAR_R_IMM_ALT_32] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
14781
+ instructionArgumentTypeMap[Instruction.SHLO_L_IMM_ALT_64] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
14782
+ instructionArgumentTypeMap[Instruction.SHLO_R_IMM_ALT_64] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
14783
+ instructionArgumentTypeMap[Instruction.SHAR_R_IMM_ALT_64] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
14784
+ instructionArgumentTypeMap[Instruction.CMOV_IZ_IMM] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
14785
+ instructionArgumentTypeMap[Instruction.CMOV_NZ_IMM] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
14786
+ instructionArgumentTypeMap[Instruction.ROT_R_64_IMM] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
14787
+ instructionArgumentTypeMap[Instruction.ROT_R_64_IMM_ALT] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
14788
+ instructionArgumentTypeMap[Instruction.ROT_R_32_IMM] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
14789
+ instructionArgumentTypeMap[Instruction.ROT_R_32_IMM_ALT] = ArgumentType.TWO_REGISTERS_ONE_IMMEDIATE;
14790
+ instructionArgumentTypeMap[Instruction.BRANCH_EQ] = ArgumentType.TWO_REGISTERS_ONE_OFFSET;
14791
+ instructionArgumentTypeMap[Instruction.BRANCH_NE] = ArgumentType.TWO_REGISTERS_ONE_OFFSET;
14792
+ instructionArgumentTypeMap[Instruction.BRANCH_LT_U] = ArgumentType.TWO_REGISTERS_ONE_OFFSET;
14793
+ instructionArgumentTypeMap[Instruction.BRANCH_LT_S] = ArgumentType.TWO_REGISTERS_ONE_OFFSET;
14794
+ instructionArgumentTypeMap[Instruction.BRANCH_GE_U] = ArgumentType.TWO_REGISTERS_ONE_OFFSET;
14795
+ instructionArgumentTypeMap[Instruction.BRANCH_GE_S] = ArgumentType.TWO_REGISTERS_ONE_OFFSET;
14796
+ instructionArgumentTypeMap[Instruction.LOAD_IMM_JUMP_IND] = ArgumentType.TWO_REGISTERS_TWO_IMMEDIATES;
14797
+ instructionArgumentTypeMap[Instruction.ADD_32] = ArgumentType.THREE_REGISTERS;
14798
+ instructionArgumentTypeMap[Instruction.ADD_64] = ArgumentType.THREE_REGISTERS;
14799
+ instructionArgumentTypeMap[Instruction.SUB_32] = ArgumentType.THREE_REGISTERS;
14800
+ instructionArgumentTypeMap[Instruction.SUB_64] = ArgumentType.THREE_REGISTERS;
14801
+ instructionArgumentTypeMap[Instruction.AND] = ArgumentType.THREE_REGISTERS;
14802
+ instructionArgumentTypeMap[Instruction.XOR] = ArgumentType.THREE_REGISTERS;
14803
+ instructionArgumentTypeMap[Instruction.OR] = ArgumentType.THREE_REGISTERS;
14804
+ instructionArgumentTypeMap[Instruction.MUL_32] = ArgumentType.THREE_REGISTERS;
14805
+ instructionArgumentTypeMap[Instruction.MUL_64] = ArgumentType.THREE_REGISTERS;
14806
+ instructionArgumentTypeMap[Instruction.MUL_UPPER_S_S] = ArgumentType.THREE_REGISTERS;
14807
+ instructionArgumentTypeMap[Instruction.MUL_UPPER_U_U] = ArgumentType.THREE_REGISTERS;
14808
+ instructionArgumentTypeMap[Instruction.MUL_UPPER_S_U] = ArgumentType.THREE_REGISTERS;
14809
+ instructionArgumentTypeMap[Instruction.DIV_U_32] = ArgumentType.THREE_REGISTERS;
14810
+ instructionArgumentTypeMap[Instruction.DIV_S_32] = ArgumentType.THREE_REGISTERS;
14811
+ instructionArgumentTypeMap[Instruction.REM_U_32] = ArgumentType.THREE_REGISTERS;
14812
+ instructionArgumentTypeMap[Instruction.REM_S_32] = ArgumentType.THREE_REGISTERS;
14813
+ instructionArgumentTypeMap[Instruction.DIV_U_64] = ArgumentType.THREE_REGISTERS;
14814
+ instructionArgumentTypeMap[Instruction.DIV_S_64] = ArgumentType.THREE_REGISTERS;
14815
+ instructionArgumentTypeMap[Instruction.REM_U_64] = ArgumentType.THREE_REGISTERS;
14816
+ instructionArgumentTypeMap[Instruction.REM_S_64] = ArgumentType.THREE_REGISTERS;
14817
+ instructionArgumentTypeMap[Instruction.SET_LT_U] = ArgumentType.THREE_REGISTERS;
14818
+ instructionArgumentTypeMap[Instruction.SET_LT_S] = ArgumentType.THREE_REGISTERS;
14819
+ instructionArgumentTypeMap[Instruction.SHLO_L_32] = ArgumentType.THREE_REGISTERS;
14820
+ instructionArgumentTypeMap[Instruction.SHLO_R_32] = ArgumentType.THREE_REGISTERS;
14821
+ instructionArgumentTypeMap[Instruction.SHAR_R_32] = ArgumentType.THREE_REGISTERS;
14822
+ instructionArgumentTypeMap[Instruction.SHLO_L_64] = ArgumentType.THREE_REGISTERS;
14823
+ instructionArgumentTypeMap[Instruction.SHLO_R_64] = ArgumentType.THREE_REGISTERS;
14824
+ instructionArgumentTypeMap[Instruction.SHAR_R_64] = ArgumentType.THREE_REGISTERS;
14825
+ instructionArgumentTypeMap[Instruction.CMOV_IZ] = ArgumentType.THREE_REGISTERS;
14826
+ instructionArgumentTypeMap[Instruction.CMOV_NZ] = ArgumentType.THREE_REGISTERS;
14827
+ instructionArgumentTypeMap[Instruction.ROT_L_64] = ArgumentType.THREE_REGISTERS;
14828
+ instructionArgumentTypeMap[Instruction.ROT_L_32] = ArgumentType.THREE_REGISTERS;
14829
+ instructionArgumentTypeMap[Instruction.ROT_R_64] = ArgumentType.THREE_REGISTERS;
14830
+ instructionArgumentTypeMap[Instruction.ROT_R_32] = ArgumentType.THREE_REGISTERS;
14831
+ instructionArgumentTypeMap[Instruction.AND_INV] = ArgumentType.THREE_REGISTERS;
14832
+ instructionArgumentTypeMap[Instruction.OR_INV] = ArgumentType.THREE_REGISTERS;
14833
+ instructionArgumentTypeMap[Instruction.XNOR] = ArgumentType.THREE_REGISTERS;
14834
+ instructionArgumentTypeMap[Instruction.MAX] = ArgumentType.THREE_REGISTERS;
14835
+ instructionArgumentTypeMap[Instruction.MAX_U] = ArgumentType.THREE_REGISTERS;
14836
+ instructionArgumentTypeMap[Instruction.MIN] = ArgumentType.THREE_REGISTERS;
14837
+ instructionArgumentTypeMap[Instruction.MIN_U] = ArgumentType.THREE_REGISTERS;
14838
+ return instructionArgumentTypeMap;
14839
+ })();
14840
+
14841
+ const instructionsWithoutArgs = [
14842
+ [Instruction.TRAP, 1],
14843
+ [Instruction.FALLTHROUGH, 1],
14844
+ ];
14845
+ const instructionsWithOneImmediate = [[Instruction.ECALLI, 1]];
14846
+ const instructionsWithOneRegisterAndOneExtendedWidthImmediate = [[Instruction.LOAD_IMM_64, 1]];
14847
+ const instructionsWithTwoImmediates = [
14848
+ [Instruction.STORE_IMM_U8, 1],
14849
+ [Instruction.STORE_IMM_U16, 1],
14850
+ [Instruction.STORE_IMM_U32, 1],
14851
+ [Instruction.STORE_IMM_U64, 1],
14852
+ ];
14853
+ const instructionsWithOneOffset = [[Instruction.JUMP, 1]];
14854
+ const instructionsWithOneRegisterAndOneImmediate = [
14855
+ [Instruction.JUMP_IND, 1],
14856
+ [Instruction.LOAD_IMM, 1],
14857
+ [Instruction.LOAD_U8, 1],
14858
+ [Instruction.LOAD_I8, 1],
14859
+ [Instruction.LOAD_U16, 1],
14860
+ [Instruction.LOAD_I16, 1],
14861
+ [Instruction.LOAD_U32, 1],
14862
+ [Instruction.LOAD_I32, 1],
14863
+ [Instruction.LOAD_U64, 1],
14864
+ [Instruction.STORE_U8, 1],
14865
+ [Instruction.STORE_U16, 1],
14866
+ [Instruction.STORE_U32, 1],
14867
+ [Instruction.STORE_U64, 1],
14868
+ ];
14869
+ const instructionsWithOneRegisterAndTwoImmediate = [
14870
+ [Instruction.STORE_IMM_IND_U8, 1],
14871
+ [Instruction.STORE_IMM_IND_U16, 1],
14872
+ [Instruction.STORE_IMM_IND_U32, 1],
14873
+ [Instruction.STORE_IMM_IND_U64, 1],
14874
+ ];
14875
+ const instructionsWithOneRegisterOneImmediateAndOneOffset = [
14876
+ [Instruction.LOAD_IMM_JUMP, 1],
14877
+ [Instruction.BRANCH_EQ_IMM, 1],
14878
+ [Instruction.BRANCH_NE_IMM, 1],
14879
+ [Instruction.BRANCH_LT_U_IMM, 1],
14880
+ [Instruction.BRANCH_LE_U_IMM, 1],
14881
+ [Instruction.BRANCH_GE_U_IMM, 1],
14882
+ [Instruction.BRANCH_GT_U_IMM, 1],
14883
+ [Instruction.BRANCH_LT_S_IMM, 1],
14884
+ [Instruction.BRANCH_LE_S_IMM, 1],
14885
+ [Instruction.BRANCH_GE_S_IMM, 1],
14886
+ [Instruction.BRANCH_GT_S_IMM, 1],
14887
+ ];
14888
+ const instructionsWithTwoRegisters = [
14889
+ [Instruction.MOVE_REG, 1],
14890
+ [Instruction.SBRK, 1],
14891
+ [Instruction.COUNT_SET_BITS_64, 1],
14892
+ [Instruction.COUNT_SET_BITS_32, 1],
14893
+ [Instruction.LEADING_ZERO_BITS_64, 1],
14894
+ [Instruction.LEADING_ZERO_BITS_32, 1],
14895
+ [Instruction.TRAILING_ZERO_BITS_64, 1],
14896
+ [Instruction.TRAILING_ZERO_BITS_32, 1],
14897
+ [Instruction.SIGN_EXTEND_8, 1],
14898
+ [Instruction.SIGN_EXTEND_16, 1],
14899
+ [Instruction.ZERO_EXTEND_16, 1],
14900
+ [Instruction.REVERSE_BYTES, 1],
14901
+ ];
14902
+ const instructionsWithTwoRegistersAndOneImmediate = [
14903
+ [Instruction.STORE_IND_U8, 1],
14904
+ [Instruction.STORE_IND_U16, 1],
14905
+ [Instruction.STORE_IND_U32, 1],
14906
+ [Instruction.STORE_IND_U64, 1],
14907
+ [Instruction.LOAD_IND_U8, 1],
14908
+ [Instruction.LOAD_IND_I8, 1],
14909
+ [Instruction.LOAD_IND_U16, 1],
14910
+ [Instruction.LOAD_IND_I16, 1],
14911
+ [Instruction.LOAD_IND_U32, 1],
14912
+ [Instruction.LOAD_IND_I32, 1],
14913
+ [Instruction.LOAD_IND_U64, 1],
14914
+ [Instruction.ADD_IMM_32, 1],
14915
+ [Instruction.AND_IMM, 1],
14916
+ [Instruction.XOR_IMM, 1],
14917
+ [Instruction.OR_IMM, 1],
14918
+ [Instruction.MUL_IMM_32, 1],
14919
+ [Instruction.SET_LT_U_IMM, 1],
14920
+ [Instruction.SET_LT_S_IMM, 1],
14921
+ [Instruction.SHLO_L_IMM_32, 1],
14922
+ [Instruction.SHLO_R_IMM_32, 1],
14923
+ [Instruction.SHAR_R_IMM_32, 1],
14924
+ [Instruction.NEG_ADD_IMM_32, 1],
14925
+ [Instruction.SET_GT_U_IMM, 1],
14926
+ [Instruction.SET_GT_S_IMM, 1],
14927
+ [Instruction.SHLO_L_IMM_ALT_32, 1],
14928
+ [Instruction.SHLO_R_IMM_ALT_32, 1],
14929
+ [Instruction.SHAR_R_IMM_ALT_32, 1],
14930
+ [Instruction.CMOV_IZ_IMM, 1],
14931
+ [Instruction.CMOV_NZ_IMM, 1],
14932
+ [Instruction.ADD_IMM_64, 1],
14933
+ [Instruction.MUL_IMM_64, 1],
14934
+ [Instruction.SHLO_L_IMM_64, 1],
14935
+ [Instruction.SHLO_R_IMM_64, 1],
14936
+ [Instruction.SHAR_R_IMM_64, 1],
14937
+ [Instruction.NEG_ADD_IMM_64, 1],
14938
+ [Instruction.SHLO_L_IMM_ALT_64, 1],
14939
+ [Instruction.SHLO_R_IMM_ALT_64, 1],
14940
+ [Instruction.SHAR_R_IMM_ALT_64, 1],
14941
+ [Instruction.ROT_R_64_IMM, 1],
14942
+ [Instruction.ROT_R_64_IMM_ALT, 1],
14943
+ [Instruction.ROT_R_32_IMM, 1],
14944
+ [Instruction.ROT_R_32_IMM_ALT, 1],
14945
+ ];
14946
+ const instructionsWithTwoRegistersAndOneOffset = [
14947
+ [Instruction.BRANCH_EQ, 1],
14948
+ [Instruction.BRANCH_NE, 1],
14949
+ [Instruction.BRANCH_LT_U, 1],
14950
+ [Instruction.BRANCH_LT_S, 1],
14951
+ [Instruction.BRANCH_GE_U, 1],
14952
+ [Instruction.BRANCH_GE_S, 1],
14953
+ ];
14954
+ const instructionWithTwoRegistersAndTwoImmediates = [[Instruction.LOAD_IMM_JUMP_IND, 1]];
14955
+ const instructionsWithThreeRegisters = [
14956
+ [Instruction.ADD_32, 1],
14957
+ [Instruction.SUB_32, 1],
14958
+ [Instruction.MUL_32, 1],
14959
+ [Instruction.DIV_U_32, 1],
14960
+ [Instruction.DIV_S_32, 1],
14961
+ [Instruction.REM_U_32, 1],
14962
+ [Instruction.REM_S_32, 1],
14963
+ [Instruction.SHLO_L_32, 1],
14964
+ [Instruction.SHLO_R_32, 1],
14965
+ [Instruction.SHAR_R_32, 1],
14966
+ [Instruction.ADD_64, 1],
14967
+ [Instruction.SUB_64, 1],
14968
+ [Instruction.MUL_64, 1],
14969
+ [Instruction.DIV_U_64, 1],
14970
+ [Instruction.DIV_S_64, 1],
14971
+ [Instruction.REM_U_64, 1],
14972
+ [Instruction.REM_S_64, 1],
14973
+ [Instruction.SHLO_L_64, 1],
14974
+ [Instruction.SHLO_R_64, 1],
14975
+ [Instruction.SHAR_R_64, 1],
14976
+ [Instruction.AND, 1],
14977
+ [Instruction.XOR, 1],
14978
+ [Instruction.OR, 1],
14979
+ [Instruction.MUL_UPPER_S_S, 1],
14980
+ [Instruction.MUL_UPPER_U_U, 1],
14981
+ [Instruction.MUL_UPPER_S_U, 1],
14982
+ [Instruction.SET_LT_U, 1],
14983
+ [Instruction.SET_LT_S, 1],
14984
+ [Instruction.CMOV_IZ, 1],
14985
+ [Instruction.CMOV_NZ, 1],
14986
+ [Instruction.ROT_L_64, 1],
14987
+ [Instruction.ROT_L_32, 1],
14988
+ [Instruction.ROT_R_64, 1],
14989
+ [Instruction.ROT_R_32, 1],
14990
+ [Instruction.AND_INV, 1],
14991
+ [Instruction.OR_INV, 1],
14992
+ [Instruction.XNOR, 1],
14993
+ [Instruction.MAX, 1],
14994
+ [Instruction.MAX_U, 1],
14995
+ [Instruction.MIN, 1],
14996
+ [Instruction.MIN_U, 1],
14997
+ ];
14998
+ const instructions = [
14999
+ ...instructionsWithoutArgs,
15000
+ ...instructionsWithOneImmediate,
15001
+ ...instructionsWithOneRegisterAndOneExtendedWidthImmediate,
15002
+ ...instructionsWithTwoImmediates,
15003
+ ...instructionsWithOneOffset,
15004
+ ...instructionsWithOneRegisterAndOneImmediate,
15005
+ ...instructionsWithOneRegisterAndTwoImmediate,
15006
+ ...instructionsWithOneRegisterOneImmediateAndOneOffset,
15007
+ ...instructionsWithTwoRegisters,
15008
+ ...instructionsWithTwoRegistersAndOneImmediate,
15009
+ ...instructionsWithTwoRegistersAndOneOffset,
15010
+ ...instructionWithTwoRegistersAndTwoImmediates,
15011
+ ...instructionsWithThreeRegisters,
15012
+ ];
15013
+ const createOpCodeEntry = ([byte, gas]) => [byte, { gas: tryAsSmallGas(gas) }];
15014
+ const byteToOpCodeMap = instructions.reduce((acc, instruction) => {
15015
+ const [byte, opCode] = createOpCodeEntry(instruction);
15016
+ acc[byte] = opCode;
15017
+ return acc;
15018
+ }, {});
15019
+ function assemblify(program, mask) {
15020
+ return program.reduce((acc, byte, index) => {
15021
+ if (mask.isInstruction(index)) {
15022
+ acc.push([Instruction[byte]]);
15023
+ }
15024
+ else {
15025
+ acc[acc.length - 1].push(byte);
14301
15026
  }
14302
- this.view.set(data, pageIndex);
14303
- }
14304
- isWriteable() {
14305
- return true;
14306
- }
14307
- getPageDump() {
14308
- return this.view;
14309
- }
15027
+ return acc;
15028
+ }, []);
14310
15029
  }
14311
15030
 
14312
- var AccessType;
14313
- (function (AccessType) {
14314
- AccessType[AccessType["READ"] = 0] = "READ";
14315
- AccessType[AccessType["WRITE"] = 1] = "WRITE";
14316
- })(AccessType || (AccessType = {}));
14317
- const logger$3 = Logger.new(undefined, "pvm:mem");
14318
- class Memory {
14319
- sbrkIndex;
14320
- virtualSbrkIndex;
14321
- endHeapIndex;
14322
- memory;
14323
- static fromInitialMemory(initialMemoryState) {
14324
- return new Memory(initialMemoryState?.sbrkIndex, initialMemoryState?.sbrkIndex, initialMemoryState?.endHeapIndex, initialMemoryState?.memory);
14325
- }
14326
- constructor(sbrkIndex = tryAsSbrkIndex(RESERVED_MEMORY_RANGE.end), virtualSbrkIndex = tryAsSbrkIndex(RESERVED_MEMORY_RANGE.end), endHeapIndex = tryAsSbrkIndex(MAX_MEMORY_INDEX), memory = new Map()) {
14327
- this.sbrkIndex = sbrkIndex;
14328
- this.virtualSbrkIndex = virtualSbrkIndex;
14329
- this.endHeapIndex = endHeapIndex;
14330
- this.memory = memory;
14331
- }
14332
- reset() {
14333
- this.sbrkIndex = tryAsSbrkIndex(RESERVED_MEMORY_RANGE.end);
14334
- this.virtualSbrkIndex = tryAsSbrkIndex(RESERVED_MEMORY_RANGE.end);
14335
- this.endHeapIndex = tryAsSbrkIndex(MAX_MEMORY_INDEX);
14336
- this.memory = new Map(); // TODO [MaSi]: We should keep allocated pages somewhere and reuse it when it is possible
14337
- }
14338
- copyFrom(memory) {
14339
- this.sbrkIndex = memory.sbrkIndex;
14340
- this.virtualSbrkIndex = memory.virtualSbrkIndex;
14341
- this.endHeapIndex = memory.endHeapIndex;
14342
- this.memory = memory.memory;
14343
- }
14344
- storeFrom(address, bytes) {
14345
- if (bytes.length === 0) {
14346
- return Result$1.ok(OK);
14347
- }
14348
- logger$3.insane `MEM[${address}] <- ${BytesBlob.blobFrom(bytes)}`;
14349
- const pagesResult = this.getPages(address, bytes.length, AccessType.WRITE);
14350
- if (pagesResult.isError) {
14351
- return Result$1.error(pagesResult.error, pagesResult.details);
14352
- }
14353
- const pages = pagesResult.ok;
14354
- let currentPosition = address;
14355
- let bytesLeft = bytes.length;
14356
- for (const page of pages) {
14357
- const pageStartIndex = tryAsPageIndex(currentPosition % PAGE_SIZE$1);
14358
- const bytesToWrite = Math.min(PAGE_SIZE$1 - pageStartIndex, bytesLeft);
14359
- const sourceStartIndex = currentPosition - address;
14360
- const source = bytes.subarray(sourceStartIndex, sourceStartIndex + bytesToWrite);
14361
- page.storeFrom(pageStartIndex, source);
14362
- currentPosition += bytesToWrite;
14363
- bytesLeft -= bytesToWrite;
14364
- }
14365
- return Result$1.ok(OK);
14366
- }
14367
- getPages(startAddress, length, accessType) {
14368
- if (length === 0) {
14369
- return Result$1.ok([]);
14370
- }
14371
- const memoryRange = MemoryRange.fromStartAndLength(startAddress, length);
14372
- const pageRange = PageRange.fromMemoryRange(memoryRange);
14373
- const pages = [];
14374
- for (const pageNumber of pageRange) {
14375
- if (pageNumber < RESERVED_NUMBER_OF_PAGES) {
14376
- return Result$1.error(PageFault.fromPageNumber(pageNumber, true), () => `Page fault: attempted to access reserved page ${pageNumber}`);
14377
- }
14378
- const page = this.memory.get(pageNumber);
14379
- if (page === undefined) {
14380
- return Result$1.error(PageFault.fromPageNumber(pageNumber), () => `Page fault: page ${pageNumber} not allocated`);
14381
- }
14382
- if (accessType === AccessType.WRITE && !page.isWriteable()) {
14383
- return Result$1.error(PageFault.fromPageNumber(pageNumber, true), () => `Page fault: attempted to write to read-only page ${pageNumber}`);
15031
+ const terminationInstructions = (() => {
15032
+ const terminationInstructions = new Array(HIGHEST_INSTRUCTION_NUMBER + 1);
15033
+ terminationInstructions.fill(false);
15034
+ terminationInstructions[Instruction.TRAP] = true;
15035
+ terminationInstructions[Instruction.FALLTHROUGH] = true;
15036
+ terminationInstructions[Instruction.JUMP] = true;
15037
+ terminationInstructions[Instruction.JUMP_IND] = true;
15038
+ terminationInstructions[Instruction.LOAD_IMM_JUMP] = true;
15039
+ terminationInstructions[Instruction.LOAD_IMM_JUMP_IND] = true;
15040
+ terminationInstructions[Instruction.BRANCH_EQ] = true;
15041
+ terminationInstructions[Instruction.BRANCH_NE] = true;
15042
+ terminationInstructions[Instruction.BRANCH_GE_U] = true;
15043
+ terminationInstructions[Instruction.BRANCH_GE_S] = true;
15044
+ terminationInstructions[Instruction.BRANCH_LT_U] = true;
15045
+ terminationInstructions[Instruction.BRANCH_LT_S] = true;
15046
+ terminationInstructions[Instruction.BRANCH_EQ_IMM] = true;
15047
+ terminationInstructions[Instruction.BRANCH_NE_IMM] = true;
15048
+ terminationInstructions[Instruction.BRANCH_LT_U_IMM] = true;
15049
+ terminationInstructions[Instruction.BRANCH_LT_S_IMM] = true;
15050
+ terminationInstructions[Instruction.BRANCH_LE_U_IMM] = true;
15051
+ terminationInstructions[Instruction.BRANCH_LE_S_IMM] = true;
15052
+ terminationInstructions[Instruction.BRANCH_GE_U_IMM] = true;
15053
+ terminationInstructions[Instruction.BRANCH_GE_S_IMM] = true;
15054
+ terminationInstructions[Instruction.BRANCH_GT_U_IMM] = true;
15055
+ terminationInstructions[Instruction.BRANCH_GT_S_IMM] = true;
15056
+ return terminationInstructions;
15057
+ })();
15058
+
15059
+ class BasicBlocks {
15060
+ basicBlocks = new Set();
15061
+ reset(code, mask) {
15062
+ this.basicBlocks.clear();
15063
+ this.basicBlocks.add(0);
15064
+ const codeLength = code.length;
15065
+ const isBasicBlockTermination = (index) => mask.isInstruction(index) && terminationInstructions[code[index]];
15066
+ for (let i = 0; i < codeLength; i++) {
15067
+ if (mask.isInstruction(i) && isBasicBlockTermination(i)) {
15068
+ this.basicBlocks.add(i + 1 + mask.getNoOfBytesToNextInstruction(i + 1));
14384
15069
  }
14385
- pages.push(page);
14386
- }
14387
- return Result$1.ok(pages);
14388
- }
14389
- /**
14390
- * Read content of the memory at `[address, address + result.length)` and
14391
- * write the result into the `result` buffer.
14392
- *
14393
- * Returns `null` if the data was read successfully or `PageFault` otherwise.
14394
- */
14395
- loadInto(result, startAddress) {
14396
- if (result.length === 0) {
14397
- return Result$1.ok(OK);
14398
- }
14399
- const pagesResult = this.getPages(startAddress, result.length, AccessType.READ);
14400
- if (pagesResult.isError) {
14401
- return Result$1.error(pagesResult.error, pagesResult.details);
14402
- }
14403
- const pages = pagesResult.ok;
14404
- let currentPosition = startAddress;
14405
- let bytesLeft = result.length;
14406
- for (const page of pages) {
14407
- const pageStartIndex = tryAsPageIndex(currentPosition % PAGE_SIZE$1);
14408
- const bytesToRead = Math.min(PAGE_SIZE$1 - pageStartIndex, bytesLeft);
14409
- const destinationStartIndex = currentPosition - startAddress;
14410
- const destination = result.subarray(destinationStartIndex);
14411
- page.loadInto(destination, pageStartIndex, bytesToRead);
14412
- currentPosition += bytesToRead;
14413
- bytesLeft -= bytesToRead;
14414
- }
14415
- logger$3.insane `MEM[${startAddress}] => ${BytesBlob.blobFrom(result)}`;
14416
- return Result$1.ok(OK);
14417
- }
14418
- sbrk(length) {
14419
- const currentSbrkIndex = this.sbrkIndex;
14420
- const currentVirtualSbrkIndex = this.virtualSbrkIndex;
14421
- // new sbrk index is bigger than 2 ** 32 or endHeapIndex
14422
- if (MAX_MEMORY_INDEX < currentVirtualSbrkIndex + length || currentVirtualSbrkIndex + length > this.endHeapIndex) {
14423
- throw new OutOfMemory();
14424
- }
14425
- const newVirtualSbrkIndex = tryAsSbrkIndex(this.virtualSbrkIndex + length);
14426
- // no alllocation needed
14427
- if (newVirtualSbrkIndex <= currentSbrkIndex) {
14428
- this.virtualSbrkIndex = newVirtualSbrkIndex;
14429
- return currentVirtualSbrkIndex;
14430
- }
14431
- // standard allocation using "Writeable" pages
14432
- const newSbrkIndex = tryAsSbrkIndex(alignToPageSize$1(newVirtualSbrkIndex));
14433
- // TODO [MaSi]: `getPageNumber` works incorrectly for SbrkIndex. Sbrk index should be changed to MemoryIndex
14434
- const firstPageNumber = getPageNumber(currentSbrkIndex);
14435
- const pagesToAllocate = (newSbrkIndex - currentSbrkIndex) / PAGE_SIZE$1;
14436
- const rangeToAllocate = PageRange.fromStartAndLength(firstPageNumber, pagesToAllocate);
14437
- for (const pageNumber of rangeToAllocate) {
14438
- const page = new WriteablePage(pageNumber);
14439
- this.memory.set(pageNumber, page);
14440
15070
  }
14441
- this.virtualSbrkIndex = newVirtualSbrkIndex;
14442
- this.sbrkIndex = newSbrkIndex;
14443
- return currentVirtualSbrkIndex;
14444
- }
14445
- getPageDump(pageNumber) {
14446
- const page = this.memory.get(pageNumber);
14447
- return page?.getPageDump() ?? null;
14448
15071
  }
14449
- getDirtyPages() {
14450
- return this.memory.keys();
15072
+ isBeginningOfBasicBlock(index) {
15073
+ return this.basicBlocks.has(index);
14451
15074
  }
14452
15075
  }
14453
-
14454
- class MemoryBuilder {
14455
- initialMemory = new Map();
14456
- isFinalized = false;
14457
- ensureNotFinalized() {
14458
- if (this.isFinalized) {
14459
- throw new FinalizedBuilderModification();
14460
- }
14461
- }
14462
- ensureNoReservedMemoryUsage(range) {
14463
- if (range.overlapsWith(RESERVED_MEMORY_RANGE)) {
14464
- throw new ReservedMemoryFault();
14465
- }
14466
- }
14467
- /**
14468
- * Create entire readable pages to handle the `[start, end)` range.
14469
- *
14470
- * Note that both `start` and `end` must be multiple of the `PAGE_SIZE`, i.e.
14471
- * they need to be the start indices of the pages.
14472
- *
14473
- * The data passed will be placed at `start`, but might be shorter than the requested range,
14474
- * prepend it with zeros if you don't wish to have it at the beginning of the page.
14475
- */
14476
- setReadablePages(start, end, data = new Uint8Array()) {
14477
- this.ensureNotFinalized();
14478
- check `${start < end} end has to be bigger than start`;
14479
- check `${start % PAGE_SIZE$1 === 0} start needs to be a multiple of page size (${PAGE_SIZE$1})`;
14480
- check `${end % PAGE_SIZE$1 === 0} end needs to be a multiple of page size (${PAGE_SIZE$1})`;
14481
- check `${data.length <= end - start} the initial data is longer than address range`;
14482
- const length = end - start;
14483
- const range = MemoryRange.fromStartAndLength(start, length);
14484
- this.ensureNoReservedMemoryUsage(range);
14485
- const pages = Array.from(PageRange.fromMemoryRange(range));
14486
- const noOfPages = pages.length;
14487
- for (let i = 0; i < noOfPages; i++) {
14488
- const pageNumber = pages[i];
14489
- const dataChunk = data.subarray(i * PAGE_SIZE$1, (i + 1) * PAGE_SIZE$1);
14490
- const page = new ReadablePage(pageNumber, dataChunk);
14491
- this.initialMemory.set(pageNumber, page);
14492
- }
14493
- return this;
15076
+
15077
+ const instructionGasMap = (() => {
15078
+ const instructionGasMap = new Array(HIGHEST_INSTRUCTION_NUMBER + 1);
15079
+ for (let i = 0; i < HIGHEST_INSTRUCTION_NUMBER + 1; i++) {
15080
+ const gas = byteToOpCodeMap[i]?.gas;
15081
+ instructionGasMap[i] = gas;
14494
15082
  }
15083
+ return instructionGasMap;
15084
+ })();
15085
+
15086
+ class InstructionResult {
15087
+ nextPc = 0;
15088
+ status = null;
14495
15089
  /**
14496
- * Create entire writeable pages to handle the `[start, end)` range.
15090
+ * A numeric exit parameter of the PVM.
14497
15091
  *
14498
- * Note that both `start` and `end` must be multiple of the `PAGE_SIZE`, i.e.
14499
- * they need to be the start indices of the pages.
15092
+ * In case of a `status === Result.FAULT` this will be the memory address
15093
+ * that triggered the fault.
15094
+ * In case of a `status === Result.HOST` this will be the host call index
15095
+ * that should be invoked.
14500
15096
  *
14501
- * The data passed will be placed at `start`, but might be shorter than the requested range,
14502
- * prepend it with zeros if you don't wish to have it at the beginning of the page.
14503
- */
14504
- setWriteablePages(start, end, data = new Uint8Array()) {
14505
- this.ensureNotFinalized();
14506
- check `${start < end} end has to be bigger than start`;
14507
- check `${start % PAGE_SIZE$1 === 0} start needs to be a multiple of page size (${PAGE_SIZE$1})`;
14508
- check `${end % PAGE_SIZE$1 === 0} end needs to be a multiple of page size (${PAGE_SIZE$1})`;
14509
- check `${data.length <= end - start} the initial data is longer than address range`;
14510
- const length = end - start;
14511
- const range = MemoryRange.fromStartAndLength(start, length);
14512
- this.ensureNoReservedMemoryUsage(range);
14513
- const pages = Array.from(PageRange.fromMemoryRange(range));
14514
- const noOfPages = pages.length;
14515
- for (let i = 0; i < noOfPages; i++) {
14516
- const pageNumber = pages[i];
14517
- const dataChunk = data.subarray(i * PAGE_SIZE$1, (i + 1) * PAGE_SIZE$1);
14518
- const page = new WriteablePage(pageNumber, dataChunk);
14519
- this.initialMemory.set(pageNumber, page);
14520
- }
14521
- return this;
14522
- }
14523
- /**
14524
- * This function can be useful when page map and initial memory data are provided separatelly.
14525
- * You can use setWriteablePages/setReadablePages to create empty pages and then setData to fill them
15097
+ * In any other circumstance the value should be `null`.
14526
15098
  */
14527
- setData(start, data) {
14528
- this.ensureNotFinalized();
14529
- const pageOffset = start % PAGE_SIZE$1;
14530
- const remainingSpaceOnPage = PAGE_SIZE$1 - pageOffset;
14531
- check `${data.length <= remainingSpaceOnPage} The data has to fit into a single page.`;
14532
- const length = data.length;
14533
- const range = MemoryRange.fromStartAndLength(start, length);
14534
- this.ensureNoReservedMemoryUsage(range);
14535
- const pageNumber = getPageNumber(start);
14536
- const page = this.initialMemory.get(pageNumber);
14537
- if (page === undefined) {
14538
- throw new PageNotExist();
14539
- }
14540
- const startPageIndex = tryAsPageIndex(start - page.start);
14541
- page.setData(startPageIndex, data);
14542
- return this;
14543
- }
14544
- finalize(startHeapIndex, endHeapIndex) {
14545
- check `
14546
- ${startHeapIndex <= endHeapIndex}
14547
- startHeapIndex (${startHeapIndex}) has to be less than or equal to endHeapIndex (${endHeapIndex})
14548
- `;
14549
- this.ensureNotFinalized();
14550
- const heapRange = MemoryRange.fromStartAndLength(startHeapIndex, endHeapIndex - startHeapIndex);
14551
- const heapPagesRange = PageRange.fromMemoryRange(heapRange);
14552
- const initializedPageNumbers = Array.from(this.initialMemory.keys());
14553
- for (const pageNumber of initializedPageNumbers) {
14554
- if (heapPagesRange.isInRange(pageNumber)) {
14555
- throw new IncorrectSbrkIndex();
14556
- }
14557
- }
14558
- const memory = Memory.fromInitialMemory({
14559
- memory: this.initialMemory,
14560
- sbrkIndex: tryAsSbrkIndex(startHeapIndex),
14561
- endHeapIndex,
14562
- });
14563
- this.isFinalized = true;
14564
- return memory;
15099
+ exitParam = null;
15100
+ reset() {
15101
+ this.nextPc = 0;
15102
+ this.status = null;
15103
+ this.exitParam = null;
14565
15104
  }
14566
15105
  }
14567
15106
 
@@ -15500,7 +16039,7 @@ class StoreOps {
15500
16039
  }
15501
16040
  else {
15502
16041
  this.instructionResult.status = Result.FAULT;
15503
- this.instructionResult.exitParam = getStartPageIndex(storeResult.error.address);
16042
+ this.instructionResult.exitParam = getStartPageIndex(tryAsMemoryIndex(storeResult.error.address));
15504
16043
  }
15505
16044
  }
15506
16045
  }
@@ -16152,7 +16691,7 @@ class JumpTable {
16152
16691
  }
16153
16692
  }
16154
16693
 
16155
- const logger$2 = Logger.new(undefined, "pvm-interpreter");
16694
+ const logger$1 = Logger.new(undefined, "pvm-interpreter");
16156
16695
  var ProgramDecoderError;
16157
16696
  (function (ProgramDecoderError) {
16158
16697
  ProgramDecoderError[ProgramDecoderError["InvalidProgramError"] = 0] = "InvalidProgramError";
@@ -16202,21 +16741,21 @@ class ProgramDecoder {
16202
16741
  return Result$1.ok(new ProgramDecoder(program));
16203
16742
  }
16204
16743
  catch (e) {
16205
- logger$2.error `Invalid program: ${e}`;
16744
+ logger$1.error `Invalid program: ${e}`;
16206
16745
  return Result$1.error(ProgramDecoderError.InvalidProgramError, () => `Program decoder error: ${e}`);
16207
16746
  }
16208
16747
  }
16209
16748
  }
16210
16749
 
16211
- const logger$1 = Logger.new(undefined, "pvm");
16750
+ const logger = Logger.new(undefined, "pvm");
16212
16751
  class Interpreter {
16213
16752
  useSbrkGas;
16214
16753
  registers = new Registers();
16754
+ memory = new Memory();
16755
+ gas = gasCounter(tryAsGas(0));
16215
16756
  code = new Uint8Array();
16216
16757
  mask = Mask.empty();
16217
16758
  pc = 0;
16218
- gas = gasCounter(tryAsGas(0));
16219
- initialGas = gasCounter(tryAsGas(0));
16220
16759
  argsDecoder;
16221
16760
  threeRegsDispatcher;
16222
16761
  twoRegsOneImmDispatcher;
@@ -16226,7 +16765,6 @@ class Interpreter {
16226
16765
  oneOffsetDispatcher;
16227
16766
  oneRegOneImmDispatcher;
16228
16767
  instructionResult = new InstructionResult();
16229
- memory = new Memory();
16230
16768
  twoImmsDispatcher;
16231
16769
  oneRegTwoImmsDispatcher;
16232
16770
  noArgsDispatcher;
@@ -16268,14 +16806,17 @@ class Interpreter {
16268
16806
  this.oneImmDispatcher = new OneImmDispatcher(hostCallOps);
16269
16807
  this.oneRegOneExtImmDispatcher = new OneRegOneExtImmDispatcher(loadOps);
16270
16808
  }
16271
- reset(rawProgram, pc, gas, maybeRegisters, maybeMemory) {
16809
+ resetJam(program, args, pc, gas) {
16810
+ const p = Program.fromSpi(program, args, true);
16811
+ this.resetGeneric(p.code, pc, gas, p.registers, p.memory);
16812
+ }
16813
+ resetGeneric(rawProgram, pc, gas, maybeRegisters, maybeMemory) {
16272
16814
  const programDecoder = new ProgramDecoder(rawProgram);
16273
16815
  this.code = programDecoder.getCode();
16274
16816
  this.mask = programDecoder.getMask();
16275
16817
  this.jumpTable.copyFrom(programDecoder.getJumpTable());
16276
16818
  this.pc = pc;
16277
16819
  this.gas = gasCounter(gas);
16278
- this.initialGas = gasCounter(gas);
16279
16820
  this.status = Status.OK;
16280
16821
  this.argsDecoder.reset(this.code, this.mask);
16281
16822
  this.basicBlocks.reset(this.code, this.mask);
@@ -16327,7 +16868,7 @@ class Interpreter {
16327
16868
  const argsType = instructionArgumentTypeMap[currentInstruction] ?? ArgumentType.NO_ARGUMENTS;
16328
16869
  const argsResult = this.argsDecodingResults[argsType];
16329
16870
  this.argsDecoder.fillArgs(this.pc, argsResult);
16330
- logger$1.insane `[PC: ${this.pc}] ${Instruction[currentInstruction]}`;
16871
+ logger.insane `[PC: ${this.pc}] ${Instruction[currentInstruction]}`;
16331
16872
  if (!isValidInstruction) {
16332
16873
  this.instructionResult.status = Result.PANIC;
16333
16874
  }
@@ -16399,34 +16940,18 @@ class Interpreter {
16399
16940
  this.status = Status.HOST;
16400
16941
  break;
16401
16942
  }
16402
- logger$1.insane `[PC: ${this.pc}] Status: ${Result[this.instructionResult.status]}`;
16943
+ logger.insane `[PC: ${this.pc}] Status: ${Result[this.instructionResult.status]}`;
16403
16944
  return this.status;
16404
16945
  }
16405
16946
  this.pc = this.instructionResult.nextPc;
16406
16947
  return this.status;
16407
16948
  }
16408
- getRegisters() {
16409
- return this.registers;
16410
- }
16411
16949
  getPC() {
16412
16950
  return this.pc;
16413
16951
  }
16414
16952
  setNextPC(nextPc) {
16415
16953
  this.pc = nextPc;
16416
16954
  }
16417
- getGas() {
16418
- return this.gas.get();
16419
- }
16420
- getGasConsumed() {
16421
- const gasConsumed = tryAsBigGas(this.initialGas.get()) - tryAsBigGas(this.gas.get());
16422
- if (gasConsumed < 0) {
16423
- return this.initialGas.get();
16424
- }
16425
- return tryAsBigGas(gasConsumed);
16426
- }
16427
- getGasCounter() {
16428
- return this.gas;
16429
- }
16430
16955
  getStatus() {
16431
16956
  return this.status;
16432
16957
  }
@@ -16434,9 +16959,6 @@ class Interpreter {
16434
16959
  const p = this.instructionResult.exitParam;
16435
16960
  return p !== null ? tryAsU32(p) : p;
16436
16961
  }
16437
- getMemory() {
16438
- return this.memory;
16439
- }
16440
16962
  getMemoryPage(pageNumber) {
16441
16963
  return this.memory.getPageDump(tryAsPageNumber(pageNumber));
16442
16964
  }
@@ -16460,212 +16982,560 @@ class Interpreter {
16460
16982
  }
16461
16983
  }
16462
16984
 
16463
- var index$7 = /*#__PURE__*/Object.freeze({
16985
+ var index$5 = /*#__PURE__*/Object.freeze({
16464
16986
  __proto__: null,
16465
16987
  Interpreter: Interpreter,
16466
16988
  Memory: Memory,
16467
16989
  MemoryBuilder: MemoryBuilder,
16468
16990
  Registers: Registers,
16469
16991
  gasCounter: gasCounter,
16470
- tryAsBigGas: tryAsBigGas,
16471
- tryAsGas: tryAsGas,
16472
16992
  tryAsMemoryIndex: tryAsMemoryIndex,
16473
- tryAsSbrkIndex: tryAsSbrkIndex,
16474
- tryAsSmallGas: tryAsSmallGas
16993
+ tryAsSbrkIndex: tryAsSbrkIndex
16475
16994
  });
16476
16995
 
16477
- class HostCallMemory {
16478
- memory;
16479
- constructor(memory) {
16480
- this.memory = memory;
16481
- }
16482
- storeFrom(address, bytes) {
16483
- if (bytes.length === 0) {
16484
- return Result$1.ok(OK);
16485
- }
16486
- if (address + tryAsU64(bytes.length) > MEMORY_SIZE) {
16487
- return Result$1.error(new OutOfBounds(), () => `Memory access out of bounds: address ${address} + length ${bytes.length} exceeds memory size`);
16488
- }
16489
- return this.memory.storeFrom(tryAsMemoryIndex(Number(address)), bytes);
16490
- }
16491
- loadInto(result, startAddress) {
16492
- if (result.length === 0) {
16493
- return Result$1.ok(OK);
16494
- }
16495
- if (startAddress + tryAsU64(result.length) > MEMORY_SIZE) {
16496
- return Result$1.error(new OutOfBounds(), () => `Memory access out of bounds: address ${startAddress} + length ${result.length} exceeds memory size`);
16497
- }
16498
- return this.memory.loadInto(result, tryAsMemoryIndex(Number(startAddress)));
16996
+ async function instantiate(module, imports = {}) {
16997
+ const adaptedImports = {
16998
+ env: Object.setPrototypeOf({
16999
+ abort(message, fileName, lineNumber, columnNumber) {
17000
+ // ~lib/builtins/abort(~lib/string/String | null?, ~lib/string/String | null?, u32?, u32?) => void
17001
+ message = __liftString(message >>> 0);
17002
+ fileName = __liftString(fileName >>> 0);
17003
+ lineNumber = lineNumber >>> 0;
17004
+ columnNumber = columnNumber >>> 0;
17005
+ (() => {
17006
+ // @external.js
17007
+ throw Error(`${message} in ${fileName}:${lineNumber}:${columnNumber}`);
17008
+ })();
17009
+ },
17010
+ "console.log"(text) {
17011
+ // ~lib/bindings/dom/console.log(~lib/string/String) => void
17012
+ text = __liftString(text >>> 0);
17013
+ console.log(text);
17014
+ },
17015
+ }, Object.assign(Object.create(globalThis), imports.env || {})),
17016
+ };
17017
+ const { exports } = await WebAssembly.instantiate(module, adaptedImports);
17018
+ const memory = exports.memory || imports.env.memory;
17019
+ const adaptedExports = Object.setPrototypeOf({
17020
+ getAssembly(p) {
17021
+ // assembly/api-internal/getAssembly(assembly/program/Program) => ~lib/string/String
17022
+ p = __lowerInternref(p) || __notnull();
17023
+ return __liftString(exports.getAssembly(p) >>> 0);
17024
+ },
17025
+ wrapAsProgram(bytecode) {
17026
+ // assembly/program-build/wrapAsProgram(~lib/typedarray/Uint8Array) => ~lib/typedarray/Uint8Array
17027
+ bytecode = __lowerTypedArray(Uint8Array, 10, 0, bytecode) || __notnull();
17028
+ return __liftTypedArray(Uint8Array, exports.wrapAsProgram(bytecode) >>> 0);
17029
+ },
17030
+ resetJAM(program, pc, initialGas, args, hasMetadata) {
17031
+ // assembly/api-debugger/resetJAM(~lib/array/Array<u8>, f64, i64, ~lib/array/Array<u8>, bool?) => void
17032
+ program = __retain(__lowerArray(__setU8, 6, 0, program) || __notnull());
17033
+ initialGas = initialGas || 0n;
17034
+ args = __lowerArray(__setU8, 6, 0, args) || __notnull();
17035
+ hasMetadata = hasMetadata ? 1 : 0;
17036
+ try {
17037
+ exports.__setArgumentsLength(arguments.length);
17038
+ exports.resetJAM(program, pc, initialGas, args, hasMetadata);
17039
+ } finally {
17040
+ __release(program);
17041
+ }
17042
+ },
17043
+ resetGeneric(program, flatRegisters, initialGas, hasMetadata) {
17044
+ // assembly/api-debugger/resetGeneric(~lib/array/Array<u8>, ~lib/array/Array<u8>, i64, bool?) => void
17045
+ program = __retain(__lowerArray(__setU8, 6, 0, program) || __notnull());
17046
+ flatRegisters = __lowerArray(__setU8, 6, 0, flatRegisters) || __notnull();
17047
+ initialGas = initialGas || 0n;
17048
+ hasMetadata = hasMetadata ? 1 : 0;
17049
+ try {
17050
+ exports.__setArgumentsLength(arguments.length);
17051
+ exports.resetGeneric(program, flatRegisters, initialGas, hasMetadata);
17052
+ } finally {
17053
+ __release(program);
17054
+ }
17055
+ },
17056
+ resetGenericWithMemory(program, flatRegisters, pageMap, chunks, initialGas, hasMetadata) {
17057
+ // assembly/api-debugger/resetGenericWithMemory(~lib/array/Array<u8>, ~lib/array/Array<u8>, ~lib/typedarray/Uint8Array, ~lib/typedarray/Uint8Array, i64, bool?) => void
17058
+ program = __retain(__lowerArray(__setU8, 6, 0, program) || __notnull());
17059
+ flatRegisters = __retain(__lowerArray(__setU8, 6, 0, flatRegisters) || __notnull());
17060
+ pageMap = __retain(__lowerTypedArray(Uint8Array, 10, 0, pageMap) || __notnull());
17061
+ chunks = __lowerTypedArray(Uint8Array, 10, 0, chunks) || __notnull();
17062
+ initialGas = initialGas || 0n;
17063
+ hasMetadata = hasMetadata ? 1 : 0;
17064
+ try {
17065
+ exports.__setArgumentsLength(arguments.length);
17066
+ exports.resetGenericWithMemory(program, flatRegisters, pageMap, chunks, initialGas, hasMetadata);
17067
+ } finally {
17068
+ __release(program);
17069
+ __release(flatRegisters);
17070
+ __release(pageMap);
17071
+ }
17072
+ },
17073
+ nextStep() {
17074
+ // assembly/api-debugger/nextStep() => bool
17075
+ return exports.nextStep() != 0;
17076
+ },
17077
+ nSteps(steps) {
17078
+ // assembly/api-debugger/nSteps(u32) => bool
17079
+ return exports.nSteps(steps) != 0;
17080
+ },
17081
+ getProgramCounter() {
17082
+ // assembly/api-debugger/getProgramCounter() => u32
17083
+ return exports.getProgramCounter() >>> 0;
17084
+ },
17085
+ getExitArg() {
17086
+ // assembly/api-debugger/getExitArg() => u32
17087
+ return exports.getExitArg() >>> 0;
17088
+ },
17089
+ setGasLeft(gas) {
17090
+ // assembly/api-debugger/setGasLeft(i64) => void
17091
+ gas = gas || 0n;
17092
+ exports.setGasLeft(gas);
17093
+ },
17094
+ getRegisters() {
17095
+ // assembly/api-debugger/getRegisters() => ~lib/typedarray/Uint8Array
17096
+ return __liftTypedArray(Uint8Array, exports.getRegisters() >>> 0);
17097
+ },
17098
+ setRegisters(flatRegisters) {
17099
+ // assembly/api-debugger/setRegisters(~lib/array/Array<u8>) => void
17100
+ flatRegisters = __lowerArray(__setU8, 6, 0, flatRegisters) || __notnull();
17101
+ exports.setRegisters(flatRegisters);
17102
+ },
17103
+ getPageDump(index) {
17104
+ // assembly/api-debugger/getPageDump(u32) => ~lib/typedarray/Uint8Array
17105
+ return __liftTypedArray(Uint8Array, exports.getPageDump(index) >>> 0);
17106
+ },
17107
+ getMemory(address, length) {
17108
+ // assembly/api-debugger/getMemory(u32, u32) => ~lib/typedarray/Uint8Array | null
17109
+ return __liftTypedArray(Uint8Array, exports.getMemory(address, length) >>> 0);
17110
+ },
17111
+ setMemory(address, data) {
17112
+ // assembly/api-debugger/setMemory(u32, ~lib/typedarray/Uint8Array) => bool
17113
+ data = __lowerTypedArray(Uint8Array, 10, 0, data) || __notnull();
17114
+ return exports.setMemory(address, data) != 0;
17115
+ },
17116
+ InputKind: (values => (
17117
+ // assembly/api-utils/InputKind
17118
+ values[values.Generic = exports["InputKind.Generic"].valueOf()] = "Generic",
17119
+ values[values.SPI = exports["InputKind.SPI"].valueOf()] = "SPI",
17120
+ values
17121
+ ))({}),
17122
+ HasMetadata: (values => (
17123
+ // assembly/api-utils/HasMetadata
17124
+ values[values.Yes = exports["HasMetadata.Yes"].valueOf()] = "Yes",
17125
+ values[values.No = exports["HasMetadata.No"].valueOf()] = "No",
17126
+ values
17127
+ ))({}),
17128
+ getGasCosts(input, kind, withMetadata) {
17129
+ // assembly/api-utils/getGasCosts(~lib/array/Array<u8>, i32, i32) => ~lib/array/Array<assembly/gas-costs/BlockGasCost>
17130
+ input = __lowerArray(__setU8, 6, 0, input) || __notnull();
17131
+ return __liftArray(pointer => __liftRecord50(__getU32(pointer)), 2, exports.getGasCosts(input, kind, withMetadata) >>> 0);
17132
+ },
17133
+ disassemble(input, kind, withMetadata) {
17134
+ // assembly/api-utils/disassemble(~lib/array/Array<u8>, i32, i32) => ~lib/string/String
17135
+ input = __lowerArray(__setU8, 6, 0, input) || __notnull();
17136
+ return __liftString(exports.disassemble(input, kind, withMetadata) >>> 0);
17137
+ },
17138
+ prepareProgram(kind, hasMetadata, program, initialRegisters, initialPageMap, initialMemory, args) {
17139
+ // assembly/api-utils/prepareProgram(i32, i32, ~lib/array/Array<u8>, ~lib/array/Array<u64>, ~lib/array/Array<assembly/api-internal/InitialPage>, ~lib/array/Array<assembly/api-internal/InitialChunk>, ~lib/array/Array<u8>) => assembly/spi/StandardProgram
17140
+ program = __retain(__lowerArray(__setU8, 6, 0, program) || __notnull());
17141
+ initialRegisters = __retain(__lowerArray(__setU64, 52, 3, initialRegisters) || __notnull());
17142
+ initialPageMap = __retain(__lowerArray((pointer, value) => { __setU32(pointer, __lowerRecord46(value) || __notnull()); }, 47, 2, initialPageMap) || __notnull());
17143
+ initialMemory = __retain(__lowerArray((pointer, value) => { __setU32(pointer, __lowerRecord48(value) || __notnull()); }, 49, 2, initialMemory) || __notnull());
17144
+ args = __lowerArray(__setU8, 6, 0, args) || __notnull();
17145
+ try {
17146
+ return __liftInternref(exports.prepareProgram(kind, hasMetadata, program, initialRegisters, initialPageMap, initialMemory, args) >>> 0);
17147
+ } finally {
17148
+ __release(program);
17149
+ __release(initialRegisters);
17150
+ __release(initialPageMap);
17151
+ __release(initialMemory);
17152
+ }
17153
+ },
17154
+ runProgram(program, initialGas, programCounter, logs, useSbrkGas) {
17155
+ // assembly/api-utils/runProgram(assembly/spi/StandardProgram, i64?, u32?, bool?, bool?) => assembly/api-internal/VmOutput
17156
+ program = __lowerInternref(program) || __notnull();
17157
+ initialGas = initialGas || 0n;
17158
+ logs = logs ? 1 : 0;
17159
+ useSbrkGas = useSbrkGas ? 1 : 0;
17160
+ exports.__setArgumentsLength(arguments.length);
17161
+ return __liftRecord55(exports.runProgram(program, initialGas, programCounter, logs, useSbrkGas) >>> 0);
17162
+ },
17163
+ }, exports);
17164
+ function __liftRecord50(pointer) {
17165
+ // assembly/gas-costs/BlockGasCost
17166
+ // Hint: Opt-out from lifting as a record by providing an empty constructor
17167
+ if (!pointer) return null;
17168
+ return {
17169
+ pc: __getU32(pointer + 0),
17170
+ gas: __getU64(pointer + 8),
17171
+ };
17172
+ }
17173
+ function __lowerRecord46(value) {
17174
+ // assembly/api-internal/InitialPage
17175
+ // Hint: Opt-out from lowering as a record by providing an empty constructor
17176
+ if (value == null) return 0;
17177
+ const pointer = exports.__pin(exports.__new(12, 46));
17178
+ __setU32(pointer + 0, value.address);
17179
+ __setU32(pointer + 4, value.length);
17180
+ __setU32(pointer + 8, value.access);
17181
+ exports.__unpin(pointer);
17182
+ return pointer;
17183
+ }
17184
+ function __lowerRecord48(value) {
17185
+ // assembly/api-internal/InitialChunk
17186
+ // Hint: Opt-out from lowering as a record by providing an empty constructor
17187
+ if (value == null) return 0;
17188
+ const pointer = exports.__pin(exports.__new(8, 48));
17189
+ __setU32(pointer + 0, value.address);
17190
+ __setU32(pointer + 4, __lowerArray(__setU8, 6, 0, value.data) || __notnull());
17191
+ exports.__unpin(pointer);
17192
+ return pointer;
17193
+ }
17194
+ function __liftRecord48(pointer) {
17195
+ // assembly/api-internal/InitialChunk
17196
+ // Hint: Opt-out from lifting as a record by providing an empty constructor
17197
+ if (!pointer) return null;
17198
+ return {
17199
+ address: __getU32(pointer + 0),
17200
+ data: __liftArray(__getU8, 0, __getU32(pointer + 4)),
17201
+ };
17202
+ }
17203
+ function __liftRecord55(pointer) {
17204
+ // assembly/api-internal/VmOutput
17205
+ // Hint: Opt-out from lifting as a record by providing an empty constructor
17206
+ if (!pointer) return null;
17207
+ return {
17208
+ status: __getI32(pointer + 0),
17209
+ registers: __liftArray(pointer => BigInt.asUintN(64, __getU64(pointer)), 3, __getU32(pointer + 4)),
17210
+ pc: __getU32(pointer + 8),
17211
+ memory: __liftArray(pointer => __liftRecord48(__getU32(pointer)), 2, __getU32(pointer + 12)),
17212
+ gas: __getI64(pointer + 16),
17213
+ exitCode: __getU32(pointer + 24),
17214
+ };
17215
+ }
17216
+ function __liftString(pointer) {
17217
+ if (!pointer) return null;
17218
+ const
17219
+ end = pointer + new Uint32Array(memory.buffer)[pointer - 4 >>> 2] >>> 1,
17220
+ memoryU16 = new Uint16Array(memory.buffer);
17221
+ let
17222
+ start = pointer >>> 1,
17223
+ string = "";
17224
+ while (end - start > 1024) string += String.fromCharCode(...memoryU16.subarray(start, start += 1024));
17225
+ return string + String.fromCharCode(...memoryU16.subarray(start, end));
17226
+ }
17227
+ function __liftArray(liftElement, align, pointer) {
17228
+ if (!pointer) return null;
17229
+ const
17230
+ dataStart = __getU32(pointer + 4),
17231
+ length = __dataview.getUint32(pointer + 12, true),
17232
+ values = new Array(length);
17233
+ for (let i = 0; i < length; ++i) values[i] = liftElement(dataStart + (i << align >>> 0));
17234
+ return values;
17235
+ }
17236
+ function __lowerArray(lowerElement, id, align, values) {
17237
+ if (values == null) return 0;
17238
+ const
17239
+ length = values.length,
17240
+ buffer = exports.__pin(exports.__new(length << align, 1)) >>> 0,
17241
+ header = exports.__pin(exports.__new(16, id)) >>> 0;
17242
+ __setU32(header + 0, buffer);
17243
+ __dataview.setUint32(header + 4, buffer, true);
17244
+ __dataview.setUint32(header + 8, length << align, true);
17245
+ __dataview.setUint32(header + 12, length, true);
17246
+ for (let i = 0; i < length; ++i) lowerElement(buffer + (i << align >>> 0), values[i]);
17247
+ exports.__unpin(buffer);
17248
+ exports.__unpin(header);
17249
+ return header;
17250
+ }
17251
+ function __liftTypedArray(constructor, pointer) {
17252
+ if (!pointer) return null;
17253
+ return new constructor(
17254
+ memory.buffer,
17255
+ __getU32(pointer + 4),
17256
+ __dataview.getUint32(pointer + 8, true) / constructor.BYTES_PER_ELEMENT
17257
+ ).slice();
17258
+ }
17259
+ function __lowerTypedArray(constructor, id, align, values) {
17260
+ if (values == null) return 0;
17261
+ const
17262
+ length = values.length,
17263
+ buffer = exports.__pin(exports.__new(length << align, 1)) >>> 0,
17264
+ header = exports.__new(12, id) >>> 0;
17265
+ __setU32(header + 0, buffer);
17266
+ __dataview.setUint32(header + 4, buffer, true);
17267
+ __dataview.setUint32(header + 8, length << align, true);
17268
+ new constructor(memory.buffer, buffer, length).set(values);
17269
+ exports.__unpin(buffer);
17270
+ return header;
17271
+ }
17272
+ class Internref extends Number {}
17273
+ const registry = new FinalizationRegistry(__release);
17274
+ function __liftInternref(pointer) {
17275
+ if (!pointer) return null;
17276
+ const sentinel = new Internref(__retain(pointer));
17277
+ registry.register(sentinel, pointer);
17278
+ return sentinel;
17279
+ }
17280
+ function __lowerInternref(value) {
17281
+ if (value == null) return 0;
17282
+ if (value instanceof Internref) return value.valueOf();
17283
+ throw TypeError("internref expected");
17284
+ }
17285
+ const refcounts = new Map();
17286
+ function __retain(pointer) {
17287
+ if (pointer) {
17288
+ const refcount = refcounts.get(pointer);
17289
+ if (refcount) refcounts.set(pointer, refcount + 1);
17290
+ else refcounts.set(exports.__pin(pointer), 1);
17291
+ }
17292
+ return pointer;
17293
+ }
17294
+ function __release(pointer) {
17295
+ if (pointer) {
17296
+ const refcount = refcounts.get(pointer);
17297
+ if (refcount === 1) exports.__unpin(pointer), refcounts.delete(pointer);
17298
+ else if (refcount) refcounts.set(pointer, refcount - 1);
17299
+ else throw Error(`invalid refcount '${refcount}' for reference '${pointer}'`);
17300
+ }
17301
+ }
17302
+ function __notnull() {
17303
+ throw TypeError("value must not be null");
17304
+ }
17305
+ let __dataview = new DataView(memory.buffer);
17306
+ function __setU8(pointer, value) {
17307
+ try {
17308
+ __dataview.setUint8(pointer, value, true);
17309
+ } catch {
17310
+ __dataview = new DataView(memory.buffer);
17311
+ __dataview.setUint8(pointer, value, true);
16499
17312
  }
16500
- }
16501
-
16502
- class HostCallRegisters {
16503
- registers;
16504
- constructor(registers) {
16505
- this.registers = registers;
17313
+ }
17314
+ function __setU32(pointer, value) {
17315
+ try {
17316
+ __dataview.setUint32(pointer, value, true);
17317
+ } catch {
17318
+ __dataview = new DataView(memory.buffer);
17319
+ __dataview.setUint32(pointer, value, true);
16506
17320
  }
16507
- get(registerIndex) {
16508
- return tryAsU64(this.registers.getU64(registerIndex));
17321
+ }
17322
+ function __setU64(pointer, value) {
17323
+ try {
17324
+ __dataview.setBigUint64(pointer, value, true);
17325
+ } catch {
17326
+ __dataview = new DataView(memory.buffer);
17327
+ __dataview.setBigUint64(pointer, value, true);
16509
17328
  }
16510
- set(registerIndex, value) {
16511
- this.registers.setU64(registerIndex, value);
17329
+ }
17330
+ function __getU8(pointer) {
17331
+ try {
17332
+ return __dataview.getUint8(pointer, true);
17333
+ } catch {
17334
+ __dataview = new DataView(memory.buffer);
17335
+ return __dataview.getUint8(pointer, true);
16512
17336
  }
16513
- }
16514
-
16515
- class ReturnValue {
16516
- consumedGas;
16517
- status;
16518
- memorySlice;
16519
- constructor(consumedGas, status, memorySlice) {
16520
- this.consumedGas = consumedGas;
16521
- this.status = status;
16522
- this.memorySlice = memorySlice;
16523
- check `
16524
- ${(status === null && memorySlice !== null) || (status !== null && memorySlice === null)}
16525
- 'status' and 'memorySlice' must not both be null or both be non-null — exactly one must be provided
16526
- `;
17337
+ }
17338
+ function __getI32(pointer) {
17339
+ try {
17340
+ return __dataview.getInt32(pointer, true);
17341
+ } catch {
17342
+ __dataview = new DataView(memory.buffer);
17343
+ return __dataview.getInt32(pointer, true);
16527
17344
  }
16528
- static fromStatus(consumedGas, status) {
16529
- return new ReturnValue(consumedGas, status, null);
17345
+ }
17346
+ function __getU32(pointer) {
17347
+ try {
17348
+ return __dataview.getUint32(pointer, true);
17349
+ } catch {
17350
+ __dataview = new DataView(memory.buffer);
17351
+ return __dataview.getUint32(pointer, true);
16530
17352
  }
16531
- static fromMemorySlice(consumedGas, memorySlice) {
16532
- return new ReturnValue(consumedGas, null, memorySlice);
17353
+ }
17354
+ function __getI64(pointer) {
17355
+ try {
17356
+ return __dataview.getBigInt64(pointer, true);
17357
+ } catch {
17358
+ __dataview = new DataView(memory.buffer);
17359
+ return __dataview.getBigInt64(pointer, true);
16533
17360
  }
16534
- hasMemorySlice() {
16535
- return this.memorySlice instanceof Uint8Array && this.status === null;
17361
+ }
17362
+ function __getU64(pointer) {
17363
+ try {
17364
+ return __dataview.getBigUint64(pointer, true);
17365
+ } catch {
17366
+ __dataview = new DataView(memory.buffer);
17367
+ return __dataview.getBigUint64(pointer, true);
17368
+ }
17369
+ }
17370
+ return adaptedExports;
17371
+ }
17372
+
17373
+ // TODO [ToDr] Temporary solution. We need to inline WASM files for the final build.
17374
+ const wasmPath = node_url.fileURLToPath(new URL(undefined("@fluffylabs/anan-as/release-mini.wasm"), (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href))));
17375
+ const wasmBuffer = fs.readFileSync(wasmPath);
17376
+ // Max u32 value
17377
+ const INF_STEPS = 2 ** 32 - 1;
17378
+ class AnanasRegisters {
17379
+ instance;
17380
+ constructor(instance) {
17381
+ this.instance = instance;
17382
+ }
17383
+ getAllEncoded() {
17384
+ return this.instance.getRegisters();
17385
+ }
17386
+ setAllEncoded(bytes) {
17387
+ check `${bytes.length === NO_OF_REGISTERS$1 * REGISTER_BYTE_SIZE}
17388
+ Incorrect size of input registers. Got: ${bytes.length},
17389
+ need: ${NO_OF_REGISTERS$1 * REGISTER_BYTE_SIZE}`;
17390
+ this.instance.setRegisters(lowerBytes(bytes));
16536
17391
  }
16537
- hasStatus() {
16538
- return !this.hasMemorySlice();
17392
+ getAllU64() {
17393
+ const bytes = this.getAllEncoded();
17394
+ return new BigUint64Array(bytes.buffer, bytes.byteOffset);
16539
17395
  }
16540
17396
  }
16541
- class HostCalls {
16542
- pvmInstanceManager;
16543
- hostCalls;
16544
- constructor(pvmInstanceManager, hostCalls) {
16545
- this.pvmInstanceManager = pvmInstanceManager;
16546
- this.hostCalls = hostCalls;
17397
+ class AnanasMemory {
17398
+ instance;
17399
+ constructor(instance) {
17400
+ this.instance = instance;
16547
17401
  }
16548
- getReturnValue(status, pvmInstance) {
16549
- const gasConsumed = pvmInstance.getGasConsumed();
16550
- if (status === Status.OOG) {
16551
- return ReturnValue.fromStatus(gasConsumed, status);
16552
- }
16553
- if (status === Status.HALT) {
16554
- const memory = pvmInstance.getMemory();
16555
- const regs = pvmInstance.getRegisters();
16556
- const maybeAddress = regs.getLowerU32(7);
16557
- const maybeLength = regs.getLowerU32(8);
16558
- const result = safeAllocUint8Array(maybeLength);
16559
- const startAddress = tryAsMemoryIndex(maybeAddress);
16560
- const loadResult = memory.loadInto(result, startAddress);
16561
- if (loadResult.isError) {
16562
- return ReturnValue.fromMemorySlice(gasConsumed, new Uint8Array());
16563
- }
16564
- return ReturnValue.fromMemorySlice(gasConsumed, result);
17402
+ store(address, bytes) {
17403
+ if (this.instance.setMemory(address, bytes)) {
17404
+ return Result$1.ok(OK);
16565
17405
  }
16566
- return ReturnValue.fromStatus(gasConsumed, Status.PANIC);
17406
+ return Result$1.error({ address: getPageStartAddress(address) }, () => "Memory is unwritable!");
16567
17407
  }
16568
- async execute(pvmInstance) {
16569
- pvmInstance.runProgram();
16570
- for (;;) {
16571
- let status = pvmInstance.getStatus();
16572
- if (status !== Status.HOST) {
16573
- return this.getReturnValue(status, pvmInstance);
16574
- }
16575
- check `
16576
- ${pvmInstance.getExitParam() !== null}
16577
- "We know that the exit param is not null, because the status is 'Status.HOST'
16578
- `;
16579
- const hostCallIndex = pvmInstance.getExitParam() ?? -1;
16580
- const gas = pvmInstance.getGasCounter();
16581
- const regs = new HostCallRegisters(pvmInstance.getRegisters());
16582
- const memory = new HostCallMemory(pvmInstance.getMemory());
16583
- const index = tryAsHostCallIndex(hostCallIndex);
16584
- const hostCall = this.hostCalls.get(index);
16585
- const gasBefore = gas.get();
16586
- // NOTE: `basicGasCost(regs)` function is for compatibility reasons: pre GP 0.7.2
16587
- const basicGasCost = typeof hostCall.basicGasCost === "number" ? hostCall.basicGasCost : hostCall.basicGasCost(regs);
16588
- const underflow = gas.sub(basicGasCost);
16589
- const pcLog = `[PC: ${pvmInstance.getPC()}]`;
16590
- if (underflow) {
16591
- this.hostCalls.traceHostCall(`${pcLog} OOG`, index, hostCall, regs, gas.get());
16592
- return ReturnValue.fromStatus(pvmInstance.getGasConsumed(), Status.OOG);
16593
- }
16594
- this.hostCalls.traceHostCall(`${pcLog} Invoking`, index, hostCall, regs, gasBefore);
16595
- const result = await hostCall.execute(gas, regs, memory);
16596
- this.hostCalls.traceHostCall(result === undefined ? `${pcLog} Result` : `${pcLog} Status(${PvmExecution[result]})`, index, hostCall, regs, gas.get());
16597
- if (result === PvmExecution.Halt) {
16598
- status = Status.HALT;
16599
- return this.getReturnValue(status, pvmInstance);
16600
- }
16601
- if (result === PvmExecution.Panic) {
16602
- status = Status.PANIC;
16603
- return this.getReturnValue(status, pvmInstance);
16604
- }
16605
- if (result === PvmExecution.OOG) {
16606
- status = Status.OOG;
16607
- return this.getReturnValue(status, pvmInstance);
16608
- }
16609
- if (result === undefined) {
16610
- pvmInstance.runProgram();
16611
- status = pvmInstance.getStatus();
16612
- continue;
16613
- }
16614
- assertNever(result);
17408
+ read(address, result) {
17409
+ if (result.length === 0) {
17410
+ return Result$1.ok(OK);
16615
17411
  }
17412
+ const newResult = this.instance.getMemory(address, result.length);
17413
+ if (newResult === null) {
17414
+ return Result$1.error({ address: getPageStartAddress(address) }, () => "Memory is inaccessible!");
17415
+ }
17416
+ result.set(newResult, 0);
17417
+ return Result$1.ok(OK);
16616
17418
  }
16617
- async runProgram(rawProgram, initialPc, initialGas, maybeRegisters, maybeMemory) {
16618
- const pvmInstance = await this.pvmInstanceManager.getInstance();
16619
- pvmInstance.reset(rawProgram, initialPc, initialGas, maybeRegisters, maybeMemory);
16620
- try {
16621
- return await this.execute(pvmInstance);
17419
+ }
17420
+ class AnanasGasCounter {
17421
+ instance;
17422
+ initialGas = tryAsGas(0n);
17423
+ constructor(instance) {
17424
+ this.instance = instance;
17425
+ }
17426
+ get() {
17427
+ return tryAsGas(this.instance.getGasLeft());
17428
+ }
17429
+ set(g) {
17430
+ this.instance.setGasLeft(BigInt(g));
17431
+ }
17432
+ sub(g) {
17433
+ const result = this.instance.getGasLeft() - BigInt(g);
17434
+ if (result >= 0n) {
17435
+ this.instance.setGasLeft(result);
17436
+ return false;
16622
17437
  }
16623
- finally {
16624
- this.pvmInstanceManager.releaseInstance(pvmInstance);
17438
+ this.instance.setGasLeft(0n);
17439
+ return true;
17440
+ }
17441
+ used() {
17442
+ const gasConsumed = BigInt(this.initialGas) - BigInt(this.get());
17443
+ if (gasConsumed < 0) {
17444
+ return this.initialGas;
16625
17445
  }
17446
+ return tryAsBigGas(gasConsumed);
16626
17447
  }
16627
17448
  }
16628
-
16629
- const logger = Logger.new(undefined, "host-calls-pvm");
16630
- /** Container for all available host calls. */
16631
- class HostCallsManager {
16632
- hostCalls = new Map();
16633
- missing;
16634
- constructor({ missing, handlers = [], }) {
16635
- this.missing = missing;
16636
- for (const handler of handlers) {
16637
- check `${this.hostCalls.get(handler.index) === undefined} Overwriting host call handler at index ${handler.index}`;
16638
- this.hostCalls.set(handler.index, handler);
17449
+ class AnanasInterpreter {
17450
+ instance;
17451
+ registers;
17452
+ memory;
17453
+ gas;
17454
+ constructor(instance) {
17455
+ this.instance = instance;
17456
+ this.registers = new AnanasRegisters(instance);
17457
+ this.memory = new AnanasMemory(instance);
17458
+ this.gas = new AnanasGasCounter(instance);
17459
+ }
17460
+ static async new() {
17461
+ const wasmModule = await WebAssembly.compile(wasmBuffer);
17462
+ const instance = await instantiate(wasmModule, {
17463
+ env: {
17464
+ abort: () => {
17465
+ throw new Error("Abort called from WASM");
17466
+ },
17467
+ },
17468
+ });
17469
+ return new AnanasInterpreter(instance);
17470
+ }
17471
+ resetJam(program, args, pc, gas) {
17472
+ const programArr = lowerBytes(program);
17473
+ const argsArr = lowerBytes(args);
17474
+ this.gas.initialGas = gas;
17475
+ this.instance.resetJAM(programArr, pc, BigInt(gas), argsArr, true);
17476
+ }
17477
+ resetGeneric(program, _pc, gas) {
17478
+ const programArr = lowerBytes(program);
17479
+ const emptyRegisters = Array(13 * 8).fill(0);
17480
+ const pageMap = new Uint8Array();
17481
+ const chunks = new Uint8Array();
17482
+ this.gas.initialGas = gas;
17483
+ this.instance.resetGenericWithMemory(programArr, emptyRegisters, pageMap, chunks, BigInt(gas), false);
17484
+ }
17485
+ nextStep() {
17486
+ return this.instance.nextStep();
17487
+ }
17488
+ runProgram() {
17489
+ // NOTE Setting max value u32 in nNextSteps making ananas running until finished
17490
+ // without comming back and forth between JS <-> WASM
17491
+ while (this.instance.nSteps(INF_STEPS)) { }
17492
+ }
17493
+ getStatus() {
17494
+ const status = this.instance.getStatus();
17495
+ if (status < 0) {
17496
+ return Status.OK;
16639
17497
  }
17498
+ check `${Status[status] !== undefined} Invalid status returned: ${status}`;
17499
+ return status;
16640
17500
  }
16641
- /** Get a host call by index. */
16642
- get(hostCallIndex) {
16643
- return this.hostCalls.get(hostCallIndex) ?? this.missing;
17501
+ getPC() {
17502
+ return this.instance.getProgramCounter();
16644
17503
  }
16645
- traceHostCall(context, hostCallIndex, hostCallHandler, registers, gas) {
16646
- const { currentServiceId } = hostCallHandler;
16647
- const requested = hostCallIndex !== hostCallHandler.index ? ` (${hostCallIndex})` : "";
16648
- const name = `${hostCallHandler.constructor.name}:${hostCallHandler.index}`;
16649
- const registerValues = hostCallHandler.tracedRegisters
16650
- .map((idx) => [idx.toString().padStart(2, "0"), registers.get(idx)])
16651
- .filter((v) => v[1] !== 0n)
16652
- .map(([idx, value]) => {
16653
- return `r${idx}=${value} (0x${value.toString(16)})`;
16654
- })
16655
- .join(", ");
16656
- logger.insane `[${currentServiceId}] ${context} ${name}${requested}. Gas: ${gas}. Regs: ${registerValues}.`;
17504
+ getExitParam() {
17505
+ return tryAsU32(this.instance.getExitArg());
17506
+ }
17507
+ }
17508
+ /** Convert `Uint8Array` to `number[]` */
17509
+ function lowerBytes(data) {
17510
+ const r = new Array(data.length);
17511
+ for (let i = 0; i < data.length; i++) {
17512
+ r[i] = data[i];
16657
17513
  }
17514
+ return r;
16658
17515
  }
16659
17516
 
17517
+ // TODO [MaSo] Delete this & also make host calls independent from intepreters.
16660
17518
  class InterpreterInstanceManager {
16661
- instances = [];
17519
+ instances;
16662
17520
  waitingQueue = [];
16663
- constructor(noOfPvmInstances) {
16664
- for (let i = 0; i < noOfPvmInstances; i++) {
16665
- this.instances.push(new Interpreter({
16666
- useSbrkGas: false,
16667
- }));
17521
+ constructor(instances) {
17522
+ this.instances = instances;
17523
+ }
17524
+ static async new(interpreter) {
17525
+ const instances = [];
17526
+ switch (interpreter) {
17527
+ case PvmBackend.BuiltIn:
17528
+ instances.push(new Interpreter({
17529
+ useSbrkGas: false,
17530
+ }));
17531
+ break;
17532
+ case PvmBackend.Ananas:
17533
+ instances.push(await AnanasInterpreter.new());
17534
+ break;
17535
+ default:
17536
+ assertNever(interpreter);
16668
17537
  }
17538
+ return new InterpreterInstanceManager(instances);
16669
17539
  }
16670
17540
  async getInstance() {
16671
17541
  const instance = this.instances.pop();
@@ -16685,7 +17555,7 @@ class InterpreterInstanceManager {
16685
17555
  }
16686
17556
  }
16687
17557
 
16688
- var index$6 = /*#__PURE__*/Object.freeze({
17558
+ var index$4 = /*#__PURE__*/Object.freeze({
16689
17559
  __proto__: null,
16690
17560
  HostCallMemory: HostCallMemory,
16691
17561
  HostCallRegisters: HostCallRegisters,
@@ -16697,194 +17567,6 @@ var index$6 = /*#__PURE__*/Object.freeze({
16697
17567
  tryAsHostCallIndex: tryAsHostCallIndex
16698
17568
  });
16699
17569
 
16700
- // GP reference: https://graypaper.fluffylabs.dev/#/7e6ff6a/2d32002d3200?v=0.6.7
16701
- const PAGE_SIZE = 2 ** 12; // Z_P from GP
16702
- const SEGMENT_SIZE = 2 ** 16; // Z_Z from GP
16703
- const DATA_LEGNTH = 2 ** 24; // Z_I from GP
16704
- const STACK_SEGMENT = 0xfe_fe_00_00; // 2^32 - 2Z_Z - Z_I from GP
16705
- const ARGS_SEGMENT = 0xfe_ff_00_00; // 2^32 - Z_Z - Z_I from GP
16706
- const LAST_PAGE = 0xff_ff_00_00;
16707
-
16708
- // GP reference: https://graypaper.fluffylabs.dev/#/579bd12/2bd2022bd202
16709
- function alignToSegmentSize(size) {
16710
- // Q(x) from GP
16711
- return SEGMENT_SIZE * Math.ceil(size / SEGMENT_SIZE);
16712
- }
16713
- function alignToPageSize(size) {
16714
- // P(x) from GP
16715
- return PAGE_SIZE * Math.ceil(size / PAGE_SIZE);
16716
- }
16717
-
16718
- const NO_OF_REGISTERS = 13;
16719
- class MemorySegment extends WithDebug {
16720
- start;
16721
- end;
16722
- data;
16723
- static from({ start, end, data }) {
16724
- return new MemorySegment(start, end, data);
16725
- }
16726
- constructor(start, end, data) {
16727
- super();
16728
- this.start = start;
16729
- this.end = end;
16730
- this.data = data;
16731
- }
16732
- }
16733
- class SpiMemory extends WithDebug {
16734
- readable;
16735
- writeable;
16736
- sbrkIndex;
16737
- heapEnd;
16738
- constructor(readable, writeable, sbrkIndex, heapEnd) {
16739
- super();
16740
- this.readable = readable;
16741
- this.writeable = writeable;
16742
- this.sbrkIndex = sbrkIndex;
16743
- this.heapEnd = heapEnd;
16744
- }
16745
- }
16746
- class SpiProgram extends WithDebug {
16747
- code;
16748
- memory;
16749
- registers;
16750
- constructor(code, memory, registers) {
16751
- super();
16752
- this.code = code;
16753
- this.memory = memory;
16754
- this.registers = registers;
16755
- }
16756
- }
16757
- /**
16758
- * program = E_3(|o|) ++ E_3(|w|) ++ E_2(z) ++ E_3(s) ++ o ++ w ++ E_4(|c|) ++ c
16759
- *
16760
- * E_n - little endian encoding, n - length
16761
- * o - initial read only data
16762
- * w - initial heap
16763
- * z - heap pages filled with zeros
16764
- * s - stack size
16765
- * c - program code
16766
- *
16767
- * https://graypaper.fluffylabs.dev/#/579bd12/2b92022b9202
16768
- */
16769
- function decodeStandardProgram(program, args) {
16770
- const decoder = Decoder.fromBlob(program);
16771
- const oLength = decoder.u24();
16772
- const wLength = decoder.u24();
16773
- check `${args.length <= DATA_LEGNTH} Incorrect arguments length`;
16774
- check `${oLength <= DATA_LEGNTH} Incorrect readonly segment length`;
16775
- const readOnlyLength = oLength;
16776
- check `${wLength <= DATA_LEGNTH} Incorrect heap segment length`;
16777
- const heapLength = wLength;
16778
- const noOfHeapZerosPages = decoder.u16();
16779
- const stackSize = decoder.u24();
16780
- const readOnlyMemory = decoder.bytes(readOnlyLength).raw;
16781
- const initialHeap = decoder.bytes(heapLength).raw;
16782
- const codeLength = decoder.u32();
16783
- const code = decoder.bytes(codeLength).raw;
16784
- decoder.finish();
16785
- const readonlyDataStart = SEGMENT_SIZE;
16786
- const readonlyDataEnd = SEGMENT_SIZE + alignToPageSize(readOnlyLength);
16787
- const heapDataStart = 2 * SEGMENT_SIZE + alignToSegmentSize(readOnlyLength);
16788
- const heapDataEnd = heapDataStart + alignToPageSize(heapLength);
16789
- const heapZerosEnd = heapDataStart + alignToPageSize(heapLength) + noOfHeapZerosPages * PAGE_SIZE;
16790
- const stackStart = STACK_SEGMENT - alignToPageSize(stackSize);
16791
- const stackEnd = STACK_SEGMENT;
16792
- const argsStart = ARGS_SEGMENT;
16793
- const argsEnd = argsStart + alignToPageSize(args.length);
16794
- const argsZerosEnd = argsEnd + alignToPageSize(args.length);
16795
- function nonEmpty(s) {
16796
- return s !== false;
16797
- }
16798
- const readableMemory = [
16799
- readOnlyLength > 0 && getMemorySegment(readonlyDataStart, readonlyDataEnd, readOnlyMemory),
16800
- args.length > 0 && getMemorySegment(argsStart, argsEnd, args),
16801
- argsEnd < argsZerosEnd && getMemorySegment(argsEnd, argsZerosEnd),
16802
- ].filter(nonEmpty);
16803
- const writeableMemory = [
16804
- heapLength > 0 && getMemorySegment(heapDataStart, heapDataEnd, initialHeap),
16805
- heapDataEnd < heapZerosEnd && getMemorySegment(heapDataEnd, heapZerosEnd),
16806
- stackStart < stackEnd && getMemorySegment(stackStart, stackEnd),
16807
- ].filter(nonEmpty);
16808
- return new SpiProgram(code, new SpiMemory(readableMemory, writeableMemory, heapZerosEnd, stackStart), getRegisters(args.length));
16809
- }
16810
- function getMemorySegment(start, end, data = null) {
16811
- return new MemorySegment(start, end, data);
16812
- }
16813
- function getRegisters(argsLength) {
16814
- const regs = new BigUint64Array(NO_OF_REGISTERS);
16815
- // GP reference: https://graypaper.fluffylabs.dev/#/579bd12/2c7c012cb101
16816
- regs[0] = BigInt(LAST_PAGE);
16817
- regs[1] = BigInt(STACK_SEGMENT);
16818
- regs[7] = BigInt(ARGS_SEGMENT);
16819
- regs[8] = BigInt(argsLength);
16820
- return regs;
16821
- }
16822
-
16823
- var index$5 = /*#__PURE__*/Object.freeze({
16824
- __proto__: null,
16825
- MemorySegment: MemorySegment,
16826
- SpiMemory: SpiMemory,
16827
- SpiProgram: SpiProgram,
16828
- decodeStandardProgram: decodeStandardProgram
16829
- });
16830
-
16831
- class Program {
16832
- code;
16833
- registers;
16834
- memory;
16835
- metadata;
16836
- static fromSpi(blob, args, hasMetadata) {
16837
- const { code: spiCode, metadata } = hasMetadata ? extractCodeAndMetadata(blob) : { code: blob };
16838
- const { code, memory: rawMemory, registers } = decodeStandardProgram(spiCode, args);
16839
- const regs = new Registers();
16840
- regs.copyFrom(registers);
16841
- const memoryBuilder = new MemoryBuilder();
16842
- for (const { start, end, data } of rawMemory.readable) {
16843
- const startIndex = tryAsMemoryIndex(start);
16844
- const endIndex = tryAsMemoryIndex(end);
16845
- memoryBuilder.setReadablePages(startIndex, endIndex, data ?? new Uint8Array());
16846
- }
16847
- for (const { start, end, data } of rawMemory.writeable) {
16848
- const startIndex = tryAsMemoryIndex(start);
16849
- const endIndex = tryAsMemoryIndex(end);
16850
- memoryBuilder.setWriteablePages(startIndex, endIndex, data ?? new Uint8Array());
16851
- }
16852
- const heapStart = tryAsMemoryIndex(rawMemory.sbrkIndex);
16853
- const heapEnd = tryAsSbrkIndex(rawMemory.heapEnd);
16854
- const memory = memoryBuilder.finalize(heapStart, heapEnd);
16855
- return new Program(code, regs, memory, metadata);
16856
- }
16857
- static fromGeneric(blob, hasMetadata) {
16858
- const { code, metadata } = hasMetadata ? extractCodeAndMetadata(blob) : { code: blob };
16859
- const regs = new Registers();
16860
- const memory = new Memory();
16861
- return new Program(code, regs, memory, metadata);
16862
- }
16863
- constructor(code, registers, memory, metadata = new Uint8Array()) {
16864
- this.code = code;
16865
- this.registers = registers;
16866
- this.memory = memory;
16867
- this.metadata = metadata;
16868
- }
16869
- }
16870
- /**
16871
- * A function that splits preimage into metadata and code.
16872
- *
16873
- * https://graypaper.fluffylabs.dev/#/cc517d7/109a01109a01?v=0.6.5
16874
- */
16875
- function extractCodeAndMetadata(blobWithMetadata) {
16876
- const decoder = Decoder.fromBlob(blobWithMetadata);
16877
- const metadata = decoder.bytesBlob().raw;
16878
- const code = decoder.remainingBytes().raw;
16879
- return { metadata, code };
16880
- }
16881
-
16882
- var index$4 = /*#__PURE__*/Object.freeze({
16883
- __proto__: null,
16884
- Program: Program,
16885
- extractCodeAndMetadata: extractCodeAndMetadata
16886
- });
16887
-
16888
17570
  class DebuggerAdapter {
16889
17571
  pvm;
16890
17572
  constructor(useSbrkGas = false) {
@@ -16895,10 +17577,10 @@ class DebuggerAdapter {
16895
17577
  return this.pvm;
16896
17578
  }
16897
17579
  resetGeneric(rawProgram, flatRegisters, initialGas) {
16898
- this.pvm.reset(rawProgram, 0, tryAsGas(initialGas), new Registers(flatRegisters));
17580
+ this.pvm.resetGeneric(rawProgram, 0, tryAsGas(initialGas), new Registers(flatRegisters));
16899
17581
  }
16900
17582
  reset(rawProgram, pc, gas, maybeRegisters, maybeMemory) {
16901
- this.pvm.reset(rawProgram, pc, tryAsGas(gas), maybeRegisters, maybeMemory);
17583
+ this.pvm.resetGeneric(rawProgram, pc, tryAsGas(gas), maybeRegisters, maybeMemory);
16902
17584
  }
16903
17585
  getPageDump(pageNumber) {
16904
17586
  const page = this.pvm.getMemoryPage(pageNumber);
@@ -16916,7 +17598,7 @@ class DebuggerAdapter {
16916
17598
  return fullPage;
16917
17599
  }
16918
17600
  setMemory(address, value) {
16919
- this.pvm.getMemory().storeFrom(tryAsMemoryIndex(address), value);
17601
+ this.pvm.memory.storeFrom(tryAsMemoryIndex(address), value);
16920
17602
  }
16921
17603
  getExitArg() {
16922
17604
  return this.pvm.getExitParam() ?? 0;
@@ -16938,10 +17620,10 @@ class DebuggerAdapter {
16938
17620
  return true;
16939
17621
  }
16940
17622
  getRegisters() {
16941
- return this.pvm.getRegisters().getAllU64();
17623
+ return this.pvm.registers.getAllU64();
16942
17624
  }
16943
17625
  setRegisters(registers) {
16944
- this.pvm.getRegisters().copyFrom(new Registers(registers));
17626
+ this.pvm.registers.copyFrom(new Registers(registers));
16945
17627
  }
16946
17628
  getProgramCounter() {
16947
17629
  return this.pvm.getPC();
@@ -16950,10 +17632,10 @@ class DebuggerAdapter {
16950
17632
  this.pvm.setNextPC(nextPc);
16951
17633
  }
16952
17634
  getGasLeft() {
16953
- return BigInt(this.pvm.getGas());
17635
+ return BigInt(this.pvm.gas.get());
16954
17636
  }
16955
17637
  setGasLeft(gas) {
16956
- this.pvm.getGasCounter().set(tryAsGas(gas));
17638
+ this.pvm.gas.set(tryAsGas(gas));
16957
17639
  }
16958
17640
  }
16959
17641
 
@@ -17012,14 +17694,16 @@ var index$3 = /*#__PURE__*/Object.freeze({
17012
17694
  clampU64ToU32: clampU64ToU32,
17013
17695
  createResults: createResults,
17014
17696
  decodeStandardProgram: decodeStandardProgram,
17697
+ emptyRegistersBuffer: emptyRegistersBuffer,
17015
17698
  extractCodeAndMetadata: extractCodeAndMetadata,
17016
17699
  getServiceId: getServiceId,
17017
17700
  getServiceIdOrCurrent: getServiceIdOrCurrent,
17018
17701
  hash: index$o,
17019
17702
  inspect: inspect,
17020
17703
  instructionArgumentTypeMap: instructionArgumentTypeMap,
17021
- interpreter: index$7,
17704
+ interpreter: index$5,
17022
17705
  isBrowser: isBrowser,
17706
+ lazyInspect: lazyInspect,
17023
17707
  measure: measure,
17024
17708
  numbers: index$r,
17025
17709
  resultToString: resultToString,
@@ -17426,10 +18110,7 @@ const fullStateDumpFromJson = (spec) => json.object({
17426
18110
  chi_a: json.array("number"),
17427
18111
  chi_v: "number",
17428
18112
  chi_r: json.optional("number"),
17429
- chi_g: json.nullable(json.array({
17430
- service: "number",
17431
- gasLimit: json.fromNumber((v) => tryAsServiceGas(v)),
17432
- })),
18113
+ chi_g: json.nullable(json.map("number", json.fromNumber((v) => tryAsServiceGas(v)))),
17433
18114
  },
17434
18115
  pi: JsonStatisticsData.fromJson,
17435
18116
  omega: json.array(json.array(notYetAccumulatedFromJson)),
@@ -17470,7 +18151,7 @@ const fullStateDumpFromJson = (spec) => json.object({
17470
18151
  assigners: chi.chi_a,
17471
18152
  delegator: chi.chi_v,
17472
18153
  registrar: chi.chi_r ?? tryAsServiceId(2 ** 32 - 1),
17473
- autoAccumulateServices: chi.chi_g ?? [],
18154
+ autoAccumulateServices: chi.chi_g ?? new Map(),
17474
18155
  }),
17475
18156
  statistics: JsonStatisticsData.toStatisticsData(spec, pi),
17476
18157
  accumulationQueue: omega,
@@ -17644,10 +18325,10 @@ exports.mmr = index$8;
17644
18325
  exports.numbers = index$r;
17645
18326
  exports.ordering = index$t;
17646
18327
  exports.pvm = index$3;
17647
- exports.pvm_host_calls = index$6;
17648
- exports.pvm_interpreter = index$7;
17649
- exports.pvm_program = index$4;
17650
- exports.pvm_spi_decoder = index$5;
18328
+ exports.pvm_host_calls = index$4;
18329
+ exports.pvm_interpreter = index$5;
18330
+ exports.pvm_program = index$6;
18331
+ exports.pvm_spi_decoder = index$7;
17651
18332
  exports.shuffling = index$2;
17652
18333
  exports.state = index$g;
17653
18334
  exports.state_json = index$1;