Skip to content

Commit

Permalink
Add implementation of IPInt memory and global instructions
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=259460
rdar://112802752

Reviewed by Justin Michaud.

Adds in implementations for (i32|i64|f32|f64).(load|store) instructions (including for smaller sizes), and global.get / global.set.

* JSTests/wasm/ipint-tests/ipint-test-global.js: Added.
* JSTests/wasm/ipint-tests/ipint-test-memory-read-sizes.js: Added.
(from.string_appeared_here.import.as.assert.from.string_appeared_here.let.wat.module.memory.export.string_appeared_here.1.10.func.export.string_appeared_here.result.i32.i32.const.0.i32.load.func.export.string_appeared_here.result.i32.i32.const.0.i32.load8_s.func.export.string_appeared_here.result.i32.i32.const.0.i32.load8_u.func.export.string_appeared_here.result.i32.i32.const.0.i32.load16_s.func.export.string_appeared_here.result.i32.i32.const.0.i32.load16_u.func.export.string_appeared_here.result.i64.i32.const.0.i64.load.func.export.string_appeared_here.result.i64.i32.const.0.i64.load8_s.func.export.string_appeared_here.result.i64.i32.const.0.i64.load8_u.func.export.string_appeared_here.result.i64.i32.const.0.i64.load16_s.func.export.string_appeared_here.result.i64.i32.const.0.i64.load16_u.func.export.string_appeared_here.result.i64.i32.const.0.i64.load32_s.func.export.string_appeared_here.result.i64.i32.const.0.i64.load32_u.writeToMemory):
(async test):
* JSTests/wasm/ipint-tests/ipint-test-memory-read.js: Added.
(from.string_appeared_here.import.as.assert.from.string_appeared_here.let.wat.module.memory.export.string_appeared_here.1.10.data.i32.const.0x0.string_appeared_here.func.export.string_appeared_here.param.i32.result.i32.local.0.i32.load8_u.return.writeStringToMemory):
(async test):
* JSTests/wasm/ipint-tests/ipint-test-memory-simple.js: Added.
(from.string_appeared_here.import.as.assert.from.string_appeared_here.let.wat.module.memory.export.string_appeared_here.1.10.data.i32.const.0x0.string_appeared_here.func.export.string_appeared_here.i32.const.0.i32.const.1717661556.i32.store.i32.const.4.i32.const.117.i32.store.decodeString):
(async test):
* JSTests/wasm/ipint-tests/ipint-test-memory-write-sizes.js: Added.
(from.string_appeared_here.import.as.assert.from.string_appeared_here.let.wat.module.memory.export.string_appeared_here.1.10.func.export.string_appeared_here.param.i32.i32.local.0.local.1.i32.store.func.export.string_appeared_here.param.i32.i32.local.0.local.1.i32.store8.func.export.string_appeared_here.param.i32.i32.local.0.local.1.i32.store16.func.export.string_appeared_here.param.i32.i64.local.0.local.1.i64.store.func.export.string_appeared_here.param.i32.i64.local.0.local.1.i64.store8.func.export.string_appeared_here.param.i32.i64.local.0.local.1.i64.store16.func.export.string_appeared_here.param.i32.i64.local.0.local.1.i64.store32.decodeString):
(async test):
* Source/JavaScriptCore/llint/InPlaceInterpreter.asm:
* Source/JavaScriptCore/wasm/WasmFunctionIPIntMetadataGenerator.cpp:
(JSC::Wasm::FunctionIPIntMetadataGenerator::addLEB128ConstantInt32AndLength):
(JSC::Wasm::sizeOfLEB128): Deleted.
* Source/JavaScriptCore/wasm/WasmIPIntGenerator.cpp:
(JSC::Wasm::IPIntGenerator::getLocal):
(JSC::Wasm::IPIntGenerator::setLocal):
(JSC::Wasm::IPIntGenerator::getGlobal):
(JSC::Wasm::IPIntGenerator::setGlobal):
(JSC::Wasm::IPIntGenerator::load):
(JSC::Wasm::IPIntGenerator::store):
* Source/JavaScriptCore/wasm/WasmSlowPaths.cpp:
(JSC::LLInt::doWasmIPIntCallIndirect):
(JSC::LLInt::ipintGetGlobal64B):
(JSC::LLInt::ipintSetGlobal64B):
* Source/JavaScriptCore/wasm/WasmSlowPaths.h:

Canonical link: https://commits.webkit.org/266306@main
  • Loading branch information
danlliu authored and Mark Lam committed Jul 26, 2023
1 parent a3ead67 commit f0224c3
Show file tree
Hide file tree
Showing 10 changed files with 790 additions and 79 deletions.
25 changes: 25 additions & 0 deletions JSTests/wasm/ipint-tests/ipint-test-global.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { instantiate } from "../wabt-wrapper.js"
import * as assert from "../assert.js"

let wat = `
(module
(global $value (export "value") (mut i32) (i32.const 5))
(func (export "set")
(i32.const 10)
(global.set $value)
)
(func (export "read") (result i32)
(global.get $value)
)
)
`

async function test() {
const instance = await instantiate(wat, {});
const { value, set, read } = instance.exports
assert.eq(read(), 5);
set();
assert.eq(value.value, 10);
}

assert.asyncTest(test())
98 changes: 98 additions & 0 deletions JSTests/wasm/ipint-tests/ipint-test-memory-read-sizes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import { instantiate } from "../wabt-wrapper.js"
import * as assert from "../assert.js"

let wat = `
(module
(memory (export "memory") 1 10)
(func (export "i32") (result i32)
(i32.const 0)
(i32.load)
)
(func (export "i32_8s") (result i32)
(i32.const 0)
(i32.load8_s)
)
(func (export "i32_8u") (result i32)
(i32.const 0)
(i32.load8_u)
)
(func (export "i32_16s") (result i32)
(i32.const 0)
(i32.load16_s)
)
(func (export "i32_16u") (result i32)
(i32.const 0)
(i32.load16_u)
)
(func (export "i64") (result i64)
(i32.const 0)
(i64.load)
)
(func (export "i64_8s") (result i64)
(i32.const 0)
(i64.load8_s)
)
(func (export "i64_8u") (result i64)
(i32.const 0)
(i64.load8_u)
)
(func (export "i64_16s") (result i64)
(i32.const 0)
(i64.load16_s)
)
(func (export "i64_16u") (result i64)
(i32.const 0)
(i64.load16_u)
)
(func (export "i64_32s") (result i64)
(i32.const 0)
(i64.load32_s)
)
(func (export "i64_32u") (result i64)
(i32.const 0)
(i64.load32_u)
)
)
`

function writeToMemory(m, l) {
let arr = new Uint8Array(m.buffer);
for (let i = 0; i < l; ++i) {
arr[i] = 128 + i;
}
}

async function test() {
const instance = await instantiate(wat, {});
const { memory,
i32, i32_8s, i32_8u, i32_16s, i32_16u,
i64, i64_8s, i64_8u, i64_16s, i64_16u, i64_32s, i64_32u
} = instance.exports
writeToMemory(memory, 16);

// mem = 80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f

// 0x83828180 as 2s complement
assert.eq(i32(), -2088599168);
// 0x80 as 2s complement
assert.eq(i32_8s(), -128);
assert.eq(i32_8u(), 128);
// 0x8180 as 2s complement
assert.eq(i32_16s(), -32384);
assert.eq(i32_16u(), 33152);

// 0x8786858483828180 as 2s complement
assert.eq(i64(), -8681104427521506944n);
// 0x80 as 2s complement
assert.eq(i64_8s(), -128n);
assert.eq(i64_8u(), 128n);
// 0x8180 as 2s complement
assert.eq(i64_16s(), -32384n);
assert.eq(i64_16u(), 33152n);
// 0x83828180 as 2s complement
assert.eq(i64_32s(), -2088599168n);
assert.eq(i64_32u(), 2206368128n);
}

assert.asyncTest(test())
32 changes: 32 additions & 0 deletions JSTests/wasm/ipint-tests/ipint-test-memory-read.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { instantiate } from "../wabt-wrapper.js"
import * as assert from "../assert.js"

let wat = `
(module
(memory (export "memory") 1 10)
(data (i32.const 0x0) "\x0e\xec\x53\x88")
(func (export "test") (param i32) (result i32)
(local.get 0)
(i32.load8_u)
(return)
)
)
`

function writeStringToMemory(s, m) {
let arr = new Uint8Array(m.buffer);
for (let i = 0; i < s.length; ++i) {
arr[i] = s.charCodeAt(i);
}
}

async function test() {
const instance = await instantiate(wat, {});
const { memory, test } = instance.exports
writeStringToMemory("shy little frog (@nimonyx)", memory);
assert.eq(test(0), 115);
assert.eq(test(10), 32);
assert.eq(test(17), 64);
}

assert.asyncTest(test())
36 changes: 36 additions & 0 deletions JSTests/wasm/ipint-tests/ipint-test-memory-simple.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { instantiate } from "../wabt-wrapper.js"
import * as assert from "../assert.js"

let wat = `
(module
(memory (export "memory") 1 10)
(data (i32.const 0x0) "\x0e\xec\x53\x88")
(func (export "test")
(i32.const 0)
(i32.const 1717661556)
(i32.store)
(i32.const 4)
(i32.const 117)
(i32.store)
)
)
`

function decodeString(buffer) {
let s = "";
let i = 0;
let arr = new Uint8Array(buffer);
while (arr[i] != 0) {
s += String.fromCharCode(arr[i++]);
}
return s;
}

async function test() {
const instance = await instantiate(wat, {});
const { memory, test } = instance.exports
test();
assert.eq(decodeString(memory.buffer), "toafu");
}

assert.asyncTest(test())
98 changes: 98 additions & 0 deletions JSTests/wasm/ipint-tests/ipint-test-memory-write-sizes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import { instantiate } from "../wabt-wrapper.js"
import * as assert from "../assert.js"

let wat = `
(module
(memory (export "memory") 1 10)
(func (export "i32") (param i32 i32)
(local.get 0)
(local.get 1)
(i32.store)
)
(func (export "i32_8") (param i32 i32)
(local.get 0)
(local.get 1)
(i32.store8)
)
(func (export "i32_16") (param i32 i32)
(local.get 0)
(local.get 1)
(i32.store16)
)
(func (export "i64") (param i32 i64)
(local.get 0)
(local.get 1)
(i64.store)
)
(func (export "i64_8") (param i32 i64)
(local.get 0)
(local.get 1)
(i64.store8)
)
(func (export "i64_16") (param i32 i64)
(local.get 0)
(local.get 1)
(i64.store16)
)
(func (export "i64_32") (param i32 i64)
(local.get 0)
(local.get 1)
(i64.store32)
)
)
`

function decodeString(buffer) {
let s = "";
let i = 0;
let arr = new Uint8Array(buffer);
while (arr[i] != 0) {
s += String.fromCharCode(arr[i++]);
}
return s;
}

async function test() {
const instance = await instantiate(wat, {});
const { memory,
i32, i32_8, i32_16,
i64, i64_8, i64_16, i64_32
} = instance.exports
let writeString = (s) => {
for (let i = 0; i < s.length; ++i) {
i32_8(i, s.charCodeAt(i));
}
};

i32(0, 1953719668);
assert.eq(decodeString(memory.buffer), "test");

i64(0, 8315168158489994617n);
assert.eq(decodeString(memory.buffer), "yeonbies");

i32(0, 2003789165);
assert.eq(decodeString(memory.buffer), "meowbies");

i32_16(0, 65);
assert.eq(decodeString(memory.buffer), "A");

i32_8(0, 26214);
assert.eq(decodeString(memory.buffer), "f");

i64(0, 0n);

i64_8(0, 8315168158640989549n);
assert.eq(decodeString(memory.buffer), "m");

i64_16(0, 8315168158640989549n);
assert.eq(decodeString(memory.buffer), "me");

i64_32(0, 8315168158640989549n);
assert.eq(decodeString(memory.buffer), "meow");

i64(0, 8315168158640989549n);
assert.eq(decodeString(memory.buffer), "meowbies");
}

assert.asyncTest(test())
Loading

0 comments on commit f0224c3

Please sign in to comment.