Skip to content

Fix broken offthread compilation on Windows #341

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Feb 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ jobs:
PYTHON3: "C:\\mozilla-build\\python3\\python3.exe"
LIBCLANG_PATH: "C:\\ProgramData\\scoop\\apps\\llvm\\current\\lib"
run: |
cargo test --verbose ${{ matrix.features }} --lib
cargo test --verbose ${{ matrix.features }}
Integrity:
runs-on: ubuntu-latest
steps:
Expand Down
1 change: 1 addition & 0 deletions mozjs/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,7 @@ const BLACKLIST_FUNCTIONS: &'static [&'static str] = &[
"JS_GetPropertyDescriptor",
"JS_GetUCPropertyDescriptor",
"js::SetPropertyIgnoringNamedGetter",
"JS::FinishOffThreadStencil",
];

/// Types that should be treated as an opaque blob of bytes whenever they show
Expand Down
2 changes: 2 additions & 0 deletions rust-mozjs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ name = "enumerate"
[[test]]
name = "evaluate"
[[test]]
name = "offthread"
[[test]]
name = "panic"
[[test]]
name = "property_descriptor"
Expand Down
7 changes: 7 additions & 0 deletions rust-mozjs/src/glue.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use jsapi::*;
use jsapi::js::frontend::CompilationStencil;
use std::os::raw::{c_char, c_void};
use std::{mem, ptr};

Expand Down Expand Up @@ -609,4 +610,10 @@ extern "C" {
value: HandleValue,
attrs: u32,
);
pub fn FinishOffThreadStencil(
cx: *mut JSContext,
token: *mut OffThreadToken,
storage: *mut InstantiationStorage,
out: *mut already_AddRefed<CompilationStencil>,
);
}
3 changes: 2 additions & 1 deletion rust-mozjs/src/glue_wrappers.in
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@ wrap!(glue: pub fn JS_GetPromiseResult(promise: HandleObject, dest: MutableHandl
wrap!(glue: pub fn JS_GetScriptPrivate(script: *mut JSScript, dest: MutableHandleValue));
wrap!(glue: pub fn JS_GetModulePrivate(module: *mut JSObject, dest: MutableHandleValue));
wrap!(glue: pub fn EncodeStringToUTF8(cx: *mut JSContext, str: HandleString, cb: fn(*const c_char)));
wrap!(glue: pub fn SetDataPropertyDescriptor(desc: MutableHandle<PropertyDescriptor>, value: HandleValue, attrs: u32));
wrap!(glue: pub fn SetDataPropertyDescriptor(desc: MutableHandle<PropertyDescriptor>, value: HandleValue, attrs: u32));
wrap!(glue: pub fn FinishOffThreadStencil(cx: *mut JSContext, token: *mut OffThreadToken, storage: *mut InstantiationStorage, out: *mut already_AddRefed<CompilationStencil>));
11 changes: 11 additions & 0 deletions rust-mozjs/src/jsglue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "js/StructuredClone.h"
#include "js/Wrapper.h"
#include "js/experimental/JitInfo.h"
#include "js/experimental/JSStencil.h"
#include "js/experimental/TypedData.h"
#include "js/friend/ErrorMessages.h"
#include "jsapi.h"
Expand Down Expand Up @@ -1080,4 +1081,14 @@ void SetDataPropertyDescriptor(
desc.set(JS::PropertyDescriptor::Data(value, attrs));
}

void FinishOffThreadStencil(
JSContext* cx,
JS::OffThreadToken* token,
JS::InstantiationStorage* storage,
already_AddRefed<JS::Stencil>* stencil
) {
already_AddRefed<JS::Stencil> retval = JS::FinishOffThreadStencil(cx, token, storage);
*stencil = std::move(retval);
}

} // extern "C"
6 changes: 5 additions & 1 deletion rust-mozjs/src/rust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -976,7 +976,11 @@ pub unsafe fn FinishOffThreadStencil(
token: *mut OffThreadToken,
storage: *mut InstantiationStorage,
) -> Stencil {
let stencil = jsapi::FinishOffThreadStencil(cx, token, storage);
let mut stencil = already_AddRefed {
mRawPtr: std::ptr::null_mut(),
_phantom_0: PhantomData,
};
crate::glue::FinishOffThreadStencil(cx, token, storage, &mut stencil);
return Stencil { inner: stencil };
}

Expand Down
101 changes: 101 additions & 0 deletions rust-mozjs/tests/offthread.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#[macro_use]
extern crate mozjs;

use std::os::raw::c_void;
use std::ptr;
use std::sync::mpsc::{channel, Sender};

use mozjs::jsapi::{
JS_NewGlobalObject, OnNewGlobalHookOption, OffThreadToken, CanCompileOffThread,
CompileToStencilOffThread1, InstantiateOptions, InstantiateGlobalStencil, JSAutoRealm,
};
use mozjs::jsval::UndefinedValue;
use mozjs::rust::{
JSEngine, RealmOptions, Runtime, SIMPLE_GLOBAL_CLASS, CompileOptionsWrapper,
transform_str_to_source_text, FinishOffThreadStencil, wrappers::JS_ExecuteScript
};

struct Token(*mut OffThreadToken);

unsafe impl Send for Token {}

struct Context {
text: String,
sender: Sender<Token>,
}

unsafe extern "C" fn callback(
token: *mut OffThreadToken,
callback_data: *mut c_void,
) {
let context = Box::from_raw(callback_data as *mut Context);
let token = Token(token);
context.sender.send(token).unwrap();
}

#[test]
fn evaluate() {
let engine = JSEngine::init().unwrap();
let runtime = Runtime::new(engine.handle());
let context = runtime.cx();
let h_option = OnNewGlobalHookOption::FireOnNewGlobalHook;
let c_option = RealmOptions::default();

unsafe {
rooted!(in(context) let global = JS_NewGlobalObject(
context,
&SIMPLE_GLOBAL_CLASS,
ptr::null_mut(),
h_option,
&*c_option,
));

let _ac = JSAutoRealm::new(context, global.get());

let src = "1 + 1".to_string();
let mut options = CompileOptionsWrapper::new(context, "", 1);
(*options.ptr)._base.forceAsync = true;
let options_ptr = options.ptr as *const _;
assert!(CanCompileOffThread(context, options_ptr, src.len()));
let (sender, receiver) = channel();
let script_context = Box::new(Context {
text: src,
sender,
});
assert!(!CompileToStencilOffThread1(
context,
options_ptr,
&mut transform_str_to_source_text(&script_context.text) as *mut _,
Some(callback),
Box::into_raw(script_context) as *mut c_void,
).is_null());

let token = receiver.recv().unwrap();
let compiled_script = FinishOffThreadStencil(context, token.0, ptr::null_mut());
assert!(!compiled_script.is_null());

let options = InstantiateOptions {
skipFilenameValidation: false,
hideScriptFromDebugger: false,
deferDebugMetadata: false,
};
rooted!(in(context) let script = InstantiateGlobalStencil(
context,
&options,
*compiled_script,
ptr::null_mut(),
));

rooted!(in(context) let mut rval = UndefinedValue());
let result = JS_ExecuteScript(context, script.handle(), rval.handle_mut());
assert!(result);
/*assert!(runtime
.evaluate_script(global.handle(), "1 + 1", "test", 1, rval.handle_mut())
.is_ok());*/
assert_eq!(rval.get().to_int32(), 2);
}
}