Merge pull request #958 from alexcrichton/no-global-cache

js_sys: Use a thread local to cache `global()`
This commit is contained in:
Alex Crichton 2018-10-10 17:41:41 -07:00 committed by GitHub
commit 41d3a08028
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -23,7 +23,6 @@ extern crate wasm_bindgen;
use std::fmt;
use std::mem;
use std::sync::atomic::{AtomicUsize, Ordering::SeqCst, ATOMIC_USIZE_INIT};
use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;
@ -4407,19 +4406,7 @@ extern "C" {
/// This allows access to the global properties and global names by accessing
/// the `Object` returned.
pub fn global() -> Object {
// Cached `Box<JsValue>`, if we've already executed this.
//
// 0 = not calculated
// n = Some(n) == Some(Box<JsValue>)
static GLOBAL: AtomicUsize = ATOMIC_USIZE_INIT;
match GLOBAL.load(SeqCst) {
0 => {}
n => return unsafe { (*(n as *const JsValue)).clone().unchecked_into() },
}
// Ok we don't have a cached value, let's load one!
//
thread_local!(static GLOBAL: Object = {
// According to StackOverflow you can access the global object via:
//
// const global = Function('return this')();
@ -4438,17 +4425,11 @@ pub fn global() -> Object {
// Note that we avoid `unwrap()` on `call0` to avoid code size bloat, we
// just handle the `Err` case as returning a different object.
debug_assert!(this.is_some());
let this = match this {
Some(this) => this,
None => return JsValue::undefined().unchecked_into(),
};
match this {
Some(this) => this.unchecked_into(),
None => JsValue::undefined().unchecked_into(),
}
});
let ptr: *mut JsValue = Box::into_raw(Box::new(this.clone()));
match GLOBAL.compare_exchange(0, ptr as usize, SeqCst, SeqCst) {
// We stored out value, relinquishing ownership of `ptr`
Ok(_) => {}
// Another thread one, drop our value
Err(_) => unsafe { drop(Box::from_raw(ptr)) },
}
this.unchecked_into()
GLOBAL.with(|g| g.clone())
}