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