Skip to content

Commit 67ac388

Browse files
committed
feat: add wasm/memory
1 parent 583452c commit 67ac388

File tree

17 files changed

+1292
-0
lines changed

17 files changed

+1292
-0
lines changed
Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
<!--
2+
3+
@license Apache-2.0
4+
5+
Copyright (c) 2024 The Stdlib Authors.
6+
7+
Licensed under the Apache License, Version 2.0 (the "License");
8+
you may not use this file except in compliance with the License.
9+
You may obtain a copy of the License at
10+
11+
http://www.apache.org/licenses/LICENSE-2.0
12+
13+
Unless required by applicable law or agreed to in writing, software
14+
distributed under the License is distributed on an "AS IS" BASIS,
15+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
See the License for the specific language governing permissions and
17+
limitations under the License.
18+
19+
-->
20+
21+
# Memory
22+
23+
> WebAssembly [memory][mdn-webassembly-memory] constructor.
24+
25+
<!-- Section to include introductory text. Make sure to keep an empty line after the intro `section` element and another before the `/section` close. -->
26+
27+
<section class="intro">
28+
29+
</section>
30+
31+
<!-- /.intro -->
32+
33+
<!-- Package usage documentation. -->
34+
35+
<section class="usage">
36+
37+
## Usage
38+
39+
```javascript
40+
var Memory = require( '@stdlib/wasm/memory' );
41+
```
42+
43+
#### Memory( descriptor )
44+
45+
Returns a new WebAssembly [memory][mdn-webassembly-memory] instance.
46+
47+
```javascript
48+
var mem = new Memory({
49+
'initial': 0
50+
});
51+
// returns <Memory>
52+
```
53+
54+
The `descriptor` argument is an object which supports the following properties:
55+
56+
- **initial**: (_required_) initial memory size in units of WebAssembly pages (i.e., 64KiB).
57+
- **maximum**: maximum memory size in units of WebAssembly pages (i.e., 64KiB).
58+
- **shared**: boolean indicating whether the memory is shared. Default: `false`.
59+
60+
* * *
61+
62+
<a name="prop-buffer"></a>
63+
64+
#### Memory.prototype.buffer
65+
66+
**Read-only** property which returns the [`ArrayBuffer`][@stdlib/array/buffer] (or [`SharedArrayBuffer`][@stdlib/array/shared-buffer]) referenced by memory instance.
67+
68+
```javascript
69+
var mem = new Memory({
70+
'initial': 0
71+
});
72+
73+
var buf = mem.buffer;
74+
// returns <ArrayBuffer>
75+
```
76+
77+
* * *
78+
79+
### Methods
80+
81+
<a name="method-grow"></a>
82+
83+
#### Memory.prototype.grow( delta )
84+
85+
Increases the size of the memory instance by a specified number of WebAssembly pages (i.e., 64KiB).
86+
87+
```javascript
88+
var mem = new Memory({
89+
'initial': 0
90+
});
91+
92+
// ...
93+
94+
var prevSize = mem.grow( 1 );
95+
```
96+
97+
The method returns the size of the previous [`ArrayBuffer`][@stdlib/array/buffer] (or [`SharedArrayBuffer`][@stdlib/array/shared-buffer]).
98+
99+
</section>
100+
101+
<!-- /.usage -->
102+
103+
* * *
104+
105+
<!-- Package usage notes. Make sure to keep an empty line after the `section` element and another before the `/section` close. -->
106+
107+
<section class="notes">
108+
109+
## Notes
110+
111+
- Upon increasing the size, the previous [`ArrayBuffer`][@stdlib/array/buffer] is detached, thus invalidating any typed arrays which were views over the previous [`ArrayBuffer`][@stdlib/array/buffer].
112+
- **Detachment** means that the previous [`ArrayBuffer`][@stdlib/array/buffer] byte length becomes zero, and it no longer has bytes accessible to JavaScript.
113+
- When calling `grow`, [`ArrayBuffer`][@stdlib/array/buffer] detachment applies even when `delta` is zero.
114+
- Detachment only applies for non-shared memory instances. For a shared memory instance, the initial buffer (which is a [`SharedArrayBuffer`][@stdlib/array/shared-buffer]) will not become detached and, instead, its length will not be updated.
115+
- Accesses to the `buffer` property after growing a [`SharedArrayBuffer`][@stdlib/array/shared-buffer] will yield a larger [`SharedArrayBuffer`][@stdlib/array/shared-buffer] which may access a larger span of memory than the buffer before growing memory.
116+
- Every [`SharedArrayBuffer`][@stdlib/array/shared-buffer] accessed via the `buffer` property will always refer to the start of the same memory address range and thus manipulate the same data.
117+
118+
</section>
119+
120+
<!-- /.notes -->
121+
122+
<!-- Package usage examples. -->
123+
124+
<section class="examples">
125+
126+
## Examples
127+
128+
<!-- eslint no-undef: "error" -->
129+
130+
```javascript
131+
var hasWebAssemblySupport = require( '@stdlib/assert/has-wasm-support' );
132+
var DataView = require( '@stdlib/array/dataview' );
133+
var Memory = require( '@stdlib/wasm/memory' );
134+
135+
function main() {
136+
var view;
137+
var mem;
138+
var v;
139+
if ( !hasWebAssemblySupport() ) {
140+
console.error( 'Environment does not support WebAssembly.' );
141+
return;
142+
}
143+
mem = new Memory({
144+
'initial': 1
145+
});
146+
view = new DataView( mem.buffer );
147+
148+
view.setFloat64( 0, 3.14 );
149+
150+
// ...
151+
152+
v = view.getFloat64( 0 );
153+
console.log( v );
154+
// => 3.14
155+
}
156+
157+
main();
158+
```
159+
160+
</section>
161+
162+
<!-- /.examples -->
163+
164+
<!-- Section to include cited references. If references are included, add a horizontal rule *before* the section. Make sure to keep an empty line after the `section` element and another before the `/section` close. -->
165+
166+
<section class="references">
167+
168+
</section>
169+
170+
<!-- /.references -->
171+
172+
<!-- Section for related `stdlib` packages. Do not manually edit this section, as it is automatically populated. -->
173+
174+
<section class="related">
175+
176+
</section>
177+
178+
<!-- /.related -->
179+
180+
<!-- Section for all links. Make sure to keep an empty line after the `section` element and another before the `/section` close. -->
181+
182+
<section class="links">
183+
184+
[mdn-webassembly-memory]: https://developer.mozilla.org/en-US/docs/WebAssembly/JavaScript_interface/Memory
185+
186+
[@stdlib/array/buffer]: https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/array/buffer
187+
188+
[@stdlib/array/shared-buffer]: https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/array/shared-buffer
189+
190+
</section>
191+
192+
<!-- /.links -->
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/**
2+
* @license Apache-2.0
3+
*
4+
* Copyright (c) 2024 The Stdlib Authors.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
'use strict';
20+
21+
// MODULES //
22+
23+
var bench = require( '@stdlib/bench' );
24+
var isNonNegativeInteger = require( '@stdlib/assert/is-nonnegative-integer' ).isPrimitive;
25+
var pkg = require( './../package.json' ).name;
26+
var Memory = require( './../lib' );
27+
28+
29+
// MAIN //
30+
31+
bench( pkg+':grow', function benchmark( b ) {
32+
var opts;
33+
var mem;
34+
var v;
35+
var i;
36+
37+
opts = {
38+
'initial': 0
39+
};
40+
mem = [
41+
new Memory( opts ),
42+
new Memory( opts ),
43+
new Memory( opts ),
44+
new Memory( opts ),
45+
new Memory( opts ),
46+
new Memory( opts ),
47+
new Memory( opts ),
48+
new Memory( opts ),
49+
new Memory( opts ),
50+
new Memory( opts )
51+
];
52+
53+
b.tic();
54+
for ( i = 0; i < b.iterations; i++ ) {
55+
v = mem[ i%mem.length ].grow( 0 );
56+
if ( v !== v ) {
57+
b.fail( 'unexpected result' );
58+
}
59+
}
60+
b.toc();
61+
if ( !isNonNegativeInteger( v ) ) {
62+
b.fail( 'should be a nonnegative integer' );
63+
}
64+
b.pass( 'benchmark finished' );
65+
b.end();
66+
});
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/**
2+
* @license Apache-2.0
3+
*
4+
* Copyright (c) 2024 The Stdlib Authors.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
'use strict';
20+
21+
// MODULES //
22+
23+
var bench = require( '@stdlib/bench' );
24+
var pkg = require( './../package.json' ).name;
25+
var Memory = require( './../lib' );
26+
27+
28+
// MAIN //
29+
30+
bench( pkg+'::constructor', function benchmark( b ) {
31+
var mem;
32+
var i;
33+
34+
b.tic();
35+
for ( i = 0; i < b.iterations; i++ ) {
36+
mem = new Memory({
37+
'initial': 0
38+
});
39+
if ( typeof mem !== 'object' ) {
40+
b.fail( 'should return an object' );
41+
}
42+
}
43+
b.toc();
44+
if ( typeof mem !== 'object' ) {
45+
b.fail( 'should return an object' );
46+
}
47+
b.pass( 'benchmark finished' );
48+
b.end();
49+
});
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/**
2+
* @license Apache-2.0
3+
*
4+
* Copyright (c) 2024 The Stdlib Authors.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
'use strict';
20+
21+
// MODULES //
22+
23+
var bench = require( '@stdlib/bench' );
24+
var isArrayBuffer = require( '@stdlib/assert/is-arraybuffer' );
25+
var pkg = require( './../package.json' ).name;
26+
var Memory = require( './../lib' );
27+
28+
29+
// MAIN //
30+
31+
bench( pkg+'::get:buffer', function benchmark( b ) {
32+
var mem;
33+
var v;
34+
var i;
35+
36+
mem = new Memory({
37+
'initial': 1
38+
});
39+
40+
b.tic();
41+
for ( i = 0; i < b.iterations; i++ ) {
42+
// Note: the following may be optimized away due to loop invariant code motion and/or other compiler optimizations, rendering this benchmark meaningless...
43+
v = mem.buffer;
44+
if ( typeof v !== 'object' ) {
45+
b.fail( 'should return an object' );
46+
}
47+
}
48+
b.toc();
49+
if ( !isArrayBuffer( v ) ) {
50+
b.fail( 'should return an ArrayBuffer' );
51+
}
52+
b.pass( 'benchmark finished' );
53+
b.end();
54+
});

0 commit comments

Comments
 (0)