partly working

This commit is contained in:
NikVolf
2017-04-24 21:43:53 +03:00
parent 0d085412cb
commit 8ca9fbe612
2 changed files with 217 additions and 74 deletions
+161 -45
View File
@@ -6,6 +6,158 @@
if (!('WebAssembly' in window)) {
alert('you need a browser with wasm support enabled :(');
}
if (!ArrayBuffer.transfer) {
ArrayBuffer.transfer = function(source, length) {
source = Object(source);
var dest = new ArrayBuffer(length);
if (!(source instanceof ArrayBuffer) || !(dest instanceof ArrayBuffer)) {
throw new TypeError('Source and destination must be ArrayBuffer instances');
}
if (dest.byteLength >= source.byteLength) {
var nextOffset = 0;
var leftBytes = source.byteLength;
var wordSizes = [8, 4, 2, 1];
wordSizes.forEach(function(_wordSize_) {
if (leftBytes >= _wordSize_) {
var done = transferWith(_wordSize_, source, dest, nextOffset, leftBytes);
nextOffset = done.nextOffset;
leftBytes = done.leftBytes;
}
});
}
return dest;
function transferWith(wordSize, source, dest, nextOffset, leftBytes) {
var ViewClass = Uint8Array;
switch (wordSize) {
case 8:
ViewClass = Float64Array;
break;
case 4:
ViewClass = Float32Array;
break;
case 2:
ViewClass = Uint16Array;
break;
case 1:
ViewClass = Uint8Array;
break;
default:
ViewClass = Uint8Array;
break;
}
var view_source = new ViewClass(source, nextOffset, Math.trunc(leftBytes / wordSize));
var view_dest = new ViewClass(dest, nextOffset, Math.trunc(leftBytes / wordSize));
for (var i = 0; i < view_dest.length; i++) {
view_dest[i] = view_source[i];
}
return {
nextOffset : view_source.byteOffset + view_source.byteLength,
leftBytes : source.byteLength - (view_source.byteOffset + view_source.byteLength)
}
}
};
}
function Storage(memoryBuf) {
var self = this;
self.size = 16 * 1024;
self.buffer = new ArrayBuffer(self.size);
self.memory = memoryBuf;
self.total = 0;
self.write = function(offset, len, ptr) {
var oldSize = false;
while (offset + len > self.size) {
oldSize || (oldSize = self.size);
self.size = self.size * 2;
}
if (oldSize != self.size) {
self.buffer = ArrayBuffer.transfer(self.buffer, self.size);
}
if (offset + len > self.total) {
self.total = offset + len;
}
let memView = new Int8Array(self.memory);
let storageView = new Int8Array(self.buffer);
for (i = 0; i < len; i++) {
storageView[offset+i] = memView[ptr+i];
}
return len;
}
self.read = function(offset, len, ptr) {
if (offset + len > self.total) {
return -1;
}
let memView = new Int8Array(self.memory);
let storageView = new Int8Array(self.buffer);
for (i = 0; i < len; i++) {
memView[ptr+i] = storageView[offset+i];
}
return len;
}
self.size = function() {
return self.total;
}
}
function set_ptr(view, offset, val) {
view[offset] = val & 0x000000ff;
view[offset+1] = (val & 0x0000ff00) >> 8;
view[offset+2] = (val & 0x00ff0000) >> 16;
view[offset+3] = (val & 0xff000000) >> 24;
}
function get_ptr(view, offset) {
return view[offset] + (view[offset] << 8) + (view[offset] << 16) + (view[offset] << 24);
}
function Runtime() {
var self = this;
self.memory = new WebAssembly.Memory({ initial: 256, maximum: 256 });
self.storage = new Storage(self.memory.buffer);
self.resolveAlloc = function(instance) {
return instance.exports._malloc;
}
self.call = function(instance, args) {
let alloc = self.resolveAlloc(instance);
// call descriptor size
let ptr = alloc(16);
let arg_ptr = alloc(args.length);
let memView = new Int8Array(self.memory);
set_ptr(memView, 0, args.length);
set_ptr(memView, 4, arg_ptr);
set_ptr(memView, 8, 0);
set_ptr(memView, 12, 0);
for (var i = 0; i < args.length; i++) {
memView[arg_ptr+i] = args[i];
}
instance.exports._call(ptr);
let result_length = get_ptr(memView, 8);
let result_ptr = get_ptr(memView, 12);
let result = [];
if (result_ptr != 0) {
for (var i = 0; i < result_length; i++) {
result.push(memVew[result_ptr + i]);
}
}
return result;
}
}
function loadWebAssembly(filename, imports) {
return fetch(filename)
@@ -18,33 +170,7 @@
imports.env.memoryBase = imports.env.memoryBase || 1024;
imports.env.tableBase = imports.env.tableBase || 0;
/* rust/emscripten imports
(import "env" "DYNAMICTOP_PTR" (global (;0;) i32))
(import "env" "STACKTOP" (global (;1;) i32))
(import "env" "STACK_MAX" (global (;2;) i32))
(import "env" "enlargeMemory" (func (;0;) (type 0)))
(import "env" "getTotalMemory" (func (;1;) (type 0)))
(import "env" "abortOnCannotGrowMemory" (func (;2;) (type 0)))
(import "env" "_abort" (func (;3;) (type 1)))
(import "env" "___setErrNo" (func (;4;) (type 2)))
(import "env" "invoke_vi" (func (;4;) (type 3)))
(import "env" "invoke_v" (func (;5;) (type 1)))
(import "env" "_rust_begin_unwind" (func (;6;) (type 4)))
(import "env" "_emscripten_memcpy_big" (func (;9;) (type 5)))
(import "env" "___gxx_personality_v0" (func (;10;) (type 6)))
(import "env" "_llvm_trap" (func (;11;) (type 0)))
(import "env" "___resumeException" (func (;12;) (type 1)))
(import "env" "___cxa_find_matching_catch_2" (func (;13;) (type 2)))
(import "env" "___gxx_personality_v0" (func (;14;) (type 7)))
(import "env" "memory" (memory (;0;) 256 256))
(import "env" "table" (table (;0;) 0 0 anyfunc))
(import "env" "memoryBase" (global (;3;) i32))
(import "env" "tableBase" (global (;4;) i32))
*/
var memory = new WebAssembly.Memory({ initial: 256, maximum: 256 });
window.runtime = new Runtime();
env.STACKTOP = env.STACKTOP || 0;
env.STACK_MAX = env.STACK_MAX || 5*1024*1024;
@@ -79,40 +205,30 @@
env.memoryBase = env.memoryBase || 0;
env.tableBase = env.tableBase || 0;
env._storage_read = runtime.storage.read;
env._storage_write = runtime.storage.write;
env._storage_size = runtime.storage.size;
env.gas = function(upd) {
console.log("used " + upd + " gas");
}
if (!imports.env.memory) {
imports.env.memory = memory;
imports.env.memory = runtime.memory;
}
if (!imports.env.table) {
imports.env.table = new WebAssembly.Table({ initial: 0, maximum: 0, element: 'anyfunc' });
imports.env.table = new WebAssembly.Table({ initial: 6, maximum: 6, element: 'anyfunc' });
}
window.testMemory = memory;
return new WebAssembly.Instance(module, imports);
});
}
loadWebAssembly('out/contract.wasm')
.then(instance => {
var exports = instance.exports;
var call = exports._call;
var malloc = exports._malloc;
// raw call context
var context_ptr = malloc(256);
// raw persistent storage
var storage_ptr = malloc(8192);
console.log("context_ptr: " + context_ptr);
console.log("storage_ptr: " + storage_ptr);
var button = document.getElementById('do-call');
button.value = 'Execute call';
button.addEventListener('click', function() {
let new_storage_ptr = call(context_ptr, storage_ptr);
console.log("Call succeded");
runtime.call(instance, []);
console.log("Call succeded");
}, false);
}
);