Assemblyscript: 如何在内存上共享 u16/u32/f64... 等?

创建于 2018-12-12  ·  4评论  ·  资料来源: AssemblyScript/assemblyscript

我只是使用MDN Example 之类的代码从 AS 和 JS 访问内存。
但是除了 u8/i8 之外,所有的测试模式都失败了,我看到 JS 显示的数据与 AS 显示的数据不同。

如何将数据存储在浮点数中?

我的代码如下:

```index.ts
// 程序集/index.ts

导出函数 readMemoryU8(offset: usize): u8 {
返回负载(抵消)
}

导出函数 writeMemoryU8(offset: usize, value: u8): void {
店铺(偏移量,值)
}

导出函数 readMemoryU16(offset: usize): u16 {
返回负载(抵消)
}

导出函数 writeMemoryU16(offset: usize, value: u16): void {
店铺(偏移量,值)
}

导出函数 readMemoryF64(offset: usize): f64 {
返回负载(抵消)
}

导出函数 writeMemoryF64(offset: usize, value: f64): void {
店铺(偏移量,值)
}

// ...

```index.js
// index.js

const fs = require("fs");
const compiled = new WebAssembly.Module(fs.readFileSync(__dirname + "/build/optimized.wasm"));
const imports = {};
Object.defineProperty(module, "exports", {
  get: () => new WebAssembly.Instance(compiled, imports).exports
});

```index.test.js
// __tests__/index.test.js

const wasm = require('../index');
常量内存 = wasm.memory;

describe('测试 WASM', () => {
beforeAll(() => {
const mem = new Uint8Array(memory.buffer);
如果(mem.length < 1){
内存.增长(1);
}
wasm.memory.grow(1);
});

test('读/写 uint8', () => {
const mem = new Uint8Array(memory.buffer);

mem.set([1, 3, 5]);
console.log([0, 1, 2, 3, 4, 5].map(wasm.readMemoryU8));
// [ 1, 3, 5, 0, 0, 0 ]
console.log(mem.subarray(0, 6));
//Uint8Array [ 1, 3, 5, 0, 0, 0 ]
expect(wasm.readMemoryU8(1)).toBe(3);
wasm.writeMemoryU8(1, 6);
expect(wasm.readMemoryU8(1)).toBe(6);
expect(mem[1]).toBe(6);
expect(wasm.readMemoryU8(0)).toBe(1);
expect(wasm.readMemoryU8(2)).toBe(5);

});

test('读/写 uint16', () => {
const mem = new Uint16Array(memory.buffer);

mem.set([1, 3, 257]);
console.log([0, 1, 2, 3, 4, 5].map(wasm.readMemoryU16)); 
// [ 1, 768, 3, 256, 257 ]
console.log(mem.subarray(0, 6)); 
// Uint16Array [ 1, 3, 257, 0, 0, 0 ]
expect(wasm.readMemoryU16(0)).toBe(1);
expect(wasm.readMemoryU16(1)).toBe(3); // failed
wasm.writeMemoryU16(1, 6);
expect(wasm.readMemoryU16(1)).toBe(6);
expect(mem[1]).toBe(6);
expect(wasm.readMemoryU16(2)).toBe(5);

});

test('读/写 float64', () => {
const mem = new Float64Array(memory.buffer);

mem.set([1, -3.2, 25.8]);

console.log([0, 1, 2, 3, 4, 5].map(wasm.readMemoryF64));
// [ 1,
//  -3.0065162379579438e-182,
//  -2.413170169815393e-185,
//  -2.3536706995205933e-185,
//  -2.3534382797147542e-185,
//  -2.3534373718248877e-185 ]
console.log(mem.subarray(0, 6));
// Float64Array [ 1, -3.2, 25.8, 0, 0, 0 ]
expect(wasm.readMemoryF64(0)).toBe(1);
expect(wasm.readMemoryF64(1)).toBe(-3.2); // failed
wasm.writeMemoryI16(1, -6.5);
expect(wasm.readMemoryF64(1)).toBe(-6.5);
expect(mem[1]).toBe(-6.5);
expect(wasm.readMemoryI16(2)).toBe(25.8);

});
});

```

最有用的评论

您的情况中的offset是确切的内存位置,但是您正在传递索引,该索引需要相乘。 使用f64时,您必须将偏移量增加8个字节(这是一个 64 位值),以便这些值不会相互覆盖,例如

export function readMemoryF64(index: u32): f64 {
  return load<f64>(index << alignof<f64>());
}

export function writeMemoryF64(index: u32, value: f64): void {
  store<f64>(index << alignof<f64>(), value);
}

所有4条评论

看起来偏移量的增量总是1 ,这对于 8 位值是正确的,但对于 16 位值应该是2 ,对于 32 位值应该是 $# 4等等,这会导致值相互覆盖的情况。

@dcodeIO
这就是问题所在。 当store<f64>(0, 1.5) ,然后store<f64>(1, 2.7) ,此时load<f64>(0)将返回一个奇怪的值。 但是load<f64>(1)将返回2.7

您的情况中的offset是确切的内存位置,但是您正在传递索引,该索引需要相乘。 使用f64时,您必须将偏移量增加8个字节(这是一个 64 位值),以便这些值不会相互覆盖,例如

export function readMemoryF64(index: u32): f64 {
  return load<f64>(index << alignof<f64>());
}

export function writeMemoryF64(index: u32, value: f64): void {
  store<f64>(index << alignof<f64>(), value);
}

@dcodeIO
通过测试!
非常感谢!

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

kungfooman picture kungfooman  ·  5评论

lastmjs picture lastmjs  ·  4评论

drachehavoc picture drachehavoc  ·  6评论

Iainmon picture Iainmon  ·  3评论

kyegupov picture kyegupov  ·  3评论