Skip to content

Commit

Permalink
№115 imported memory (#4)
Browse files Browse the repository at this point in the history
* made imported memory be initialized with the exported ones

Signed-off-by: Georgi Georgiev <[email protected]>

* removed logs

Signed-off-by: Georgi Georgiev <[email protected]>

* added support for apple silicon and made the imported memory be accessible through the exports

Signed-off-by: Georgi Georgiev <[email protected]>

* small changes to the makefile

Signed-off-by: Georgi Georgiev <[email protected]>

* lfix encapsulation

Signed-off-by: Georgi Georgiev <[email protected]>

* uncomment tests

Signed-off-by: Georgi Georgiev <[email protected]>

* delete commented lines

Signed-off-by: Georgi Georgiev <[email protected]>

* remove big files

Signed-off-by: Georgi Georgiev <[email protected]>

---------

Signed-off-by: Georgi Georgiev <[email protected]>
  • Loading branch information
georg-getz authored Aug 11, 2023
1 parent 8e007ec commit c9df56d
Show file tree
Hide file tree
Showing 12 changed files with 108 additions and 29 deletions.
20 changes: 16 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,12 @@ else
endif

ARCH := $(shell uname -m)

ifeq ($(ARCH),x86_64)
build_arch = amd64
else ifeq ($(ARCH),arm64)
build_arch = arm64
else
$(error Architecture not supported yet)
$(error Architecture not supported yet)
endif
endif

Expand All @@ -30,7 +31,7 @@ build: build-headers build-rust build-java
build-rust: build-rust-$(build_arch)-$(build_os)

# Compile the Rust part.
build-rust-all-targets: build-rust-amd64-darwin build-rust-amd64-linux build-rust-amd64-windows
build-rust-all-targets: build-rust-amd64-darwin build-rust-arm64-darwin build-rust-amd64-linux build-rust-amd64-windows

build-rust-amd64-darwin:
rustup target add x86_64-apple-darwin
Expand All @@ -40,6 +41,14 @@ build-rust-amd64-darwin:
install_name_tool -id "@rpath/libwasmer_jni.dylib" ./artifacts/darwin-amd64/libwasmer_jni.dylib
test -h target/current || ln -s x86_64-apple-darwin/release target/current

build-rust-arm64-darwin:
rustup target add aarch64-apple-darwin
cargo build --release --target=aarch64-apple-darwin
mkdir -p artifacts/darwin-arm64
cp target/aarch64-apple-darwin/release/libwasmer_jni.dylib artifacts/darwin-arm64
install_name_tool -id "@rpath/libwasmer_jni.dylib" ./artifacts/darwin-arm64/libwasmer_jni.dylib
test -h target/current || ln -s aarch64-apple-darwin/release target/current

build-rust-amd64-linux:
rustup target add x86_64-unknown-linux-gnu
cargo build --release --target=x86_64-unknown-linux-gnu
Expand Down Expand Up @@ -72,6 +81,9 @@ test-rust: test-rust-$(build_arch)-$(build_os)
test-rust-amd64-darwin:
cargo test --lib --release --target=x86_64-apple-darwin

test-rust-arm64-darwin:
cargo test --lib --release --target=aarch64-apple-darwin

test-rust-amd64-linux:
cargo test --lib --release --target=x86_64-unknown-linux-gnu

Expand All @@ -85,7 +97,7 @@ test-java:
# Test the examples.
test-examples:
@for example in $(shell find examples -name "*Example.java") ; do \
example=$${example#examples/}; \
example=$${example%examples/}; \
example=$${example%Example.java}; \
echo "Testing $${example}"; \
make run-example EXAMPLE=$${example}; \
Expand Down
4 changes: 3 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,9 @@ String inferWasmerJarAppendix() {
case ["x86_64", "x64", "x86-64"]:
arch_name = "amd64"
break;

case ["arm64", "aarch64"]:
arch_name = "arm64"
break;
default:
throw new RuntimeException("Architecture " + arch.getName() + " is not supported.")
}
Expand Down
2 changes: 2 additions & 0 deletions examples/ImportExample.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import org.wasmer.Instance;
import org.wasmer.Module;
import org.wasmer.Type;
import org.wasmer.Memory;

import java.io.IOException;
import java.nio.file.Files;
Expand Down Expand Up @@ -33,6 +34,7 @@ public static void main(String[] args) throws IOException {
System.out.println("Calling exported function 'Core_initialize_block' as it calls both of the imported functions");
instance.exports.getFunction("Core_initialize_block").apply(1,2);

Memory memory = instance.exports.getMemory("memory");
instance.close();
}
}
Binary file not shown.
6 changes: 5 additions & 1 deletion src/imports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@ use jni::{
};
use std::{collections::HashMap, panic};
use std::convert::TryFrom;
use std::sync::Arc;
use wasmer::{ImportObject, NamedResolver, ChainableNamedResolver, Exports, Function, FunctionType, Type, Value, Memory, MemoryType};
use wasmer_wasi::WasiState;
use crate::memory::{IMPORTED_MEMORY, Memory as MemoryWrapper};

pub struct Imports {
pub(crate) import_object: Box<dyn NamedResolver>,
Expand Down Expand Up @@ -59,7 +61,9 @@ pub extern "system" fn Java_org_wasmer_Imports_nativeImportsInstantiate(
};
let shared = env.get_field(import, "shared", "Z")?.z()?;
let memory_type = MemoryType::new(u32::try_from(min_pages)?, max_pages, shared);
namespaces.entry(namespace).or_insert_with(|| Exports::new()).insert(name, Memory::new(&store, memory_type)?)
let memory = Memory::new(&store, memory_type)?;
IMPORTED_MEMORY.lock().unwrap().replace(MemoryWrapper::new(Arc::new(memory.clone())));
namespaces.entry(namespace).or_insert_with(|| Exports::new()).insert(name, memory)
} else {
let function = env.get_field(import, "function", "Ljava/util/function/Function;")?.l()?;
let params = env.get_field(import, "argTypesInt", "[I")?.l()?;
Expand Down
3 changes: 2 additions & 1 deletion src/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use jni::{
JNIEnv,
};
use std::{collections::HashMap, convert::TryFrom, panic, rc::Rc};
use std::sync::Arc;
use wasmer::{imports, Extern, Value as WasmValue, Function};
use wasmer as core;
use wasmer_compiler_cranelift::Cranelift;
Expand Down Expand Up @@ -43,7 +44,7 @@ impl Instance {
.exports
.iter()
.filter_map(|(export_name, export)| match export {
Extern::Memory(memory) => Some((export_name.to_string(), Memory::new(Rc::new(memory.clone())))),
Extern::Memory(memory) => Some((export_name.to_string(), Memory::new(Arc::new(memory.clone())))),
_ => None,
})
.collect();
Expand Down
2 changes: 1 addition & 1 deletion src/java/org/wasmer/Exports.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
* }</pre>
*/
public class Exports {
private Map<String, Export> inner;
private final Map<String, Export> inner;
private Instance instance;

/**
Expand Down
27 changes: 24 additions & 3 deletions src/java/org/wasmer/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,33 @@
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Collections;

public class Main {
public static void main(String[] args) throws IOException {
//Purely for demonstration purposes, delete all of it when writing actual code
byte[] bytes = Files.readAllBytes(Paths.get(System.getProperty("user.dir"), "../../examples/runtime.wasm"));
System.out.println("Reading wasm bytes");
byte[] bytes = Files.readAllBytes(Paths.get("../../examples/runtime.wasm"));
Module module = new Module(bytes);
System.out.println("Success");
System.out.println("Creating import object");
Imports imports = Imports.from(Arrays.asList(
new ImportObject.FuncImport("env", "ext_storage_set_version_1", argv -> {
System.out.println("Message printed in the body of 'ext_storage_set_version_1'");
return argv;
}, Arrays.asList(Type.I64, Type.I64), Collections.emptyList()),
new ImportObject.FuncImport("env", "ext_storage_get_version_1", argv -> {
System.out.println("Message printed in the body of 'ext_storage_get_version_1'");
return argv;
}, Collections.singletonList(Type.I64), Collections.singletonList(Type.I64)),
new ImportObject.MemoryImport("env", 20, false)), module);
System.out.println("Instantiating module");
Instance instance = module.instantiate(imports);

System.out.println("Calling exported function 'Core_initialize_block' as it calls both of the imported functions");
instance.exports.getFunction("Core_initialize_block").apply(1,2);

Memory memory = instance.exports.getMemory("memory");
System.out.println(memory.buffer());
instance.close();
}
}
3 changes: 3 additions & 0 deletions src/java/org/wasmer/Module.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package org.wasmer;

import org.wasmer.exports.Export;

import java.util.Collections;
import java.util.Map;

/**
* `Module` is a Java class that represents a WebAssembly module.
Expand Down
32 changes: 19 additions & 13 deletions src/java/org/wasmer/Native.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,13 @@

import java.io.*;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.nio.file.Files;
import java.util.logging.Level;
import java.util.logging.Logger;

public class Native {
public static final boolean LOADED_EMBEDDED_LIBRARY;
private static final Logger logger = Logger.getLogger(Native.class.getName());

static {
LOADED_EMBEDDED_LIBRARY = loadEmbeddedLibrary();
Expand All @@ -30,10 +28,19 @@ public static String getCurrentPlatformIdentifier() {
osName = "windows";
} else if (osName.contains("mac os x")) {
osName = "darwin";
String[] args = new String[] {"/bin/bash", "-c", "uname", "-p"};
try {
Process proc = new ProcessBuilder(args).start();
BufferedReader reader = new BufferedReader(new InputStreamReader(proc.getInputStream()));
if (reader.readLine().equals("Darwin")) {
return osName + "-arm64";
}
} catch (IOException e) {
throw new RuntimeException(e);
}
} else {
osName = osName.replaceAll("\\s+", "_");
}

return osName + "-" + System.getProperty("os.arch");
}

Expand All @@ -56,26 +63,25 @@ private static boolean loadEmbeddedLibrary() {
url.append(getCurrentPlatformIdentifier()).append("/");

URL nativeLibraryUrl = null;

// loop through extensions, stopping after finding first one
for (String lib: libs) {
nativeLibraryUrl = Module.class.getResource(url.toString() + lib);
nativeLibraryUrl = Module.class.getResource(url + lib);

if (nativeLibraryUrl != null) {
break;
}
}

if (nativeLibraryUrl != null) {
// native library found within JAR, extract and load
try {
final File libfile = File.createTempFile("wasmer_jni", ".lib");
libfile.deleteOnExit(); // just in case

final InputStream in = nativeLibraryUrl.openStream();
final OutputStream out = new BufferedOutputStream(new FileOutputStream(libfile));
final OutputStream out = new BufferedOutputStream(Files.newOutputStream(libfile.toPath()));

int len = 0;
int len;
byte[] buffer = new byte[8192];

while ((len = in.read(buffer)) > -1) {
Expand All @@ -88,7 +94,7 @@ private static boolean loadEmbeddedLibrary() {

usingEmbedded = true;
} catch (IOException x) {
// mission failed, do nothing
logger.log(Level.SEVERE, "Failed to load native library", x);
}

}
Expand Down
34 changes: 31 additions & 3 deletions src/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,24 @@ use jni::{
sys::jint,
JNIEnv,
};
use std::{cell::Cell, panic, rc::Rc, slice};
use std::{cell::Cell, panic, slice};
use std::sync::{Arc, Mutex};
use wasmer::MemoryView;
use wasmer::Pages;
use wasmer::Memory as WasmMemory;

/// A static variable holding the imported memory if there's such
///
/// Note that `Memory` here refers to the local struct and not `wasmer::Memory`
pub static IMPORTED_MEMORY: Mutex<Option<Memory>> = Mutex::new(None);

#[derive(Clone)]
pub struct Memory {
pub memory: Rc<WasmMemory>,
pub memory: Arc<WasmMemory>,
}

impl Memory {
pub fn new(memory: Rc<WasmMemory>) -> Self {
pub fn new(memory: Arc<WasmMemory>) -> Self {
Self { memory }
}

Expand Down Expand Up @@ -108,6 +114,7 @@ pub mod java {
types::{jptr, Pointer},
};
use jni::{objects::JObject, JNIEnv};
use crate::memory::IMPORTED_MEMORY;

pub fn initialize_memories(env: &JNIEnv, instance: &Instance) -> Result<(), Error> {
let exports_object: JObject = env
Expand All @@ -120,6 +127,27 @@ pub mod java {

// Get the `org.wasmer.Memory` class.
let memory_class = env.find_class("org/wasmer/Memory")?;
let memory_lock = IMPORTED_MEMORY.lock().unwrap();
if memory_lock.is_some() {
let memory_object = env.new_object(memory_class, "()V", &[])?;

// Try to set the memory pointer to the field `org.wasmer.Memory.memoryPointer`.
let memory_pointer: jptr = Pointer::new(memory_lock.clone().unwrap()).into();
env.set_field(memory_object, "memoryPointer", "J", memory_pointer.into())?;

// Add the newly created `org.wasmer.Memory` in the
// `org.wasmer.Exports` collection.
env.call_method(
exports_object,
"addMemory",
"(Ljava/lang/String;Lorg/wasmer/Memory;)V",
&[
JObject::from(env.new_string("memory")?).into(),
memory_object.into(),
],
)?;
}


for (memory_name, memory) in &instance.memories {
// Instantiate the `Memory` class.
Expand Down
4 changes: 2 additions & 2 deletions src/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use jni::{
JNIEnv,
};
use std::{collections::HashMap, panic, rc::Rc};
use std::sync::Arc;
use wasmer::{self as runtime, Extern, Engine as _};
use wasmer_compiler_cranelift::Cranelift;
use wasmer_engine_universal::Universal as UniversalEngine;
Expand Down Expand Up @@ -106,12 +107,11 @@ pub extern "system" fn Java_org_wasmer_Module_nativeInstantiate(
let instance = runtime::Instance::new(&module.module, &imports.import_object).map_err(|e| {
runtime_error(format!("Failed to instantiate a WebAssembly module: {}", e))
})?;

let memories: HashMap<String, Memory> = instance
.exports
.iter()
.filter_map(|(export_name, export)| match export {
Extern::Memory(memory) => Some((export_name.to_string(), Memory::new(Rc::new(memory.clone())))),
Extern::Memory(memory) => Some((export_name.to_string(), Memory::new(Arc::new(memory.clone())))),
_ => None,
})
.collect();
Expand Down

0 comments on commit c9df56d

Please sign in to comment.