Optimize JsValue::{from_bool, undefined, null} constructors (#220)

This commit optimizes constructing an instance of `JsValue` which is one of
`null`, `undefined`, `true`, or `false`. These are commonly created on the Rust
side of things and since there's only a limited set of values we can easily
prepopulate the global slab with a few entries and use hardcoded indices to
refer to these constants. This should avoid the need to travel into JS to insert
a `null` or and `undefined` into the global slab.
This commit is contained in:
Alex Crichton
2018-06-01 16:46:42 -05:00
committed by GitHub
parent 346d2fda22
commit cb1e5cf136
3 changed files with 41 additions and 48 deletions

View File

@ -690,17 +690,23 @@ impl<'a> Context<'a> {
if !self.exposed_globals.insert("slab") { if !self.exposed_globals.insert("slab") {
return; return;
} }
self.global(&format!("let slab = [];")); let initial_values = [
"{ obj: null }",
"{ obj: undefined }",
"{ obj: true }",
"{ obj: false }",
];
self.global(&format!("let slab = [{}];", initial_values.join(", ")));
if self.config.debug { if self.config.debug {
self.export("assertSlabEmpty", " self.export("assertSlabEmpty", &format!("
function() { function() {{
for (let i = 0; i < slab.length; i++) { for (let i = {}; i < slab.length; i++) {{
if (typeof(slab[i]) === 'number') if (typeof(slab[i]) === 'number')
continue; continue;
throw new Error('slab is not currently empty'); throw new Error('slab is not currently empty');
} }}
} }}
"); ", initial_values.len()));
} }
} }
@ -708,8 +714,9 @@ impl<'a> Context<'a> {
if !self.exposed_globals.insert("slab_next") { if !self.exposed_globals.insert("slab_next") {
return; return;
} }
self.expose_global_slab();
self.global(&format!(" self.global(&format!("
let slab_next = 0; let slab_next = slab.length;
")); "));
} }

41
package-lock.json generated
View File

@ -2717,8 +2717,7 @@
"ansi-regex": { "ansi-regex": {
"version": "2.1.1", "version": "2.1.1",
"bundled": true, "bundled": true,
"dev": true, "dev": true
"optional": true
}, },
"aproba": { "aproba": {
"version": "1.2.0", "version": "1.2.0",
@ -2739,14 +2738,12 @@
"balanced-match": { "balanced-match": {
"version": "1.0.0", "version": "1.0.0",
"bundled": true, "bundled": true,
"dev": true, "dev": true
"optional": true
}, },
"brace-expansion": { "brace-expansion": {
"version": "1.1.11", "version": "1.1.11",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"balanced-match": "^1.0.0", "balanced-match": "^1.0.0",
"concat-map": "0.0.1" "concat-map": "0.0.1"
@ -2761,20 +2758,17 @@
"code-point-at": { "code-point-at": {
"version": "1.1.0", "version": "1.1.0",
"bundled": true, "bundled": true,
"dev": true, "dev": true
"optional": true
}, },
"concat-map": { "concat-map": {
"version": "0.0.1", "version": "0.0.1",
"bundled": true, "bundled": true,
"dev": true, "dev": true
"optional": true
}, },
"console-control-strings": { "console-control-strings": {
"version": "1.1.0", "version": "1.1.0",
"bundled": true, "bundled": true,
"dev": true, "dev": true
"optional": true
}, },
"core-util-is": { "core-util-is": {
"version": "1.0.2", "version": "1.0.2",
@ -2891,8 +2885,7 @@
"inherits": { "inherits": {
"version": "2.0.3", "version": "2.0.3",
"bundled": true, "bundled": true,
"dev": true, "dev": true
"optional": true
}, },
"ini": { "ini": {
"version": "1.3.5", "version": "1.3.5",
@ -2904,7 +2897,6 @@
"version": "1.0.0", "version": "1.0.0",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"number-is-nan": "^1.0.0" "number-is-nan": "^1.0.0"
} }
@ -2919,7 +2911,6 @@
"version": "3.0.4", "version": "3.0.4",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"brace-expansion": "^1.1.7" "brace-expansion": "^1.1.7"
} }
@ -2927,14 +2918,12 @@
"minimist": { "minimist": {
"version": "0.0.8", "version": "0.0.8",
"bundled": true, "bundled": true,
"dev": true, "dev": true
"optional": true
}, },
"minipass": { "minipass": {
"version": "2.2.4", "version": "2.2.4",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"safe-buffer": "^5.1.1", "safe-buffer": "^5.1.1",
"yallist": "^3.0.0" "yallist": "^3.0.0"
@ -2953,7 +2942,6 @@
"version": "0.5.1", "version": "0.5.1",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"minimist": "0.0.8" "minimist": "0.0.8"
} }
@ -3034,8 +3022,7 @@
"number-is-nan": { "number-is-nan": {
"version": "1.0.1", "version": "1.0.1",
"bundled": true, "bundled": true,
"dev": true, "dev": true
"optional": true
}, },
"object-assign": { "object-assign": {
"version": "4.1.1", "version": "4.1.1",
@ -3047,7 +3034,6 @@
"version": "1.4.0", "version": "1.4.0",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"wrappy": "1" "wrappy": "1"
} }
@ -3133,8 +3119,7 @@
"safe-buffer": { "safe-buffer": {
"version": "5.1.1", "version": "5.1.1",
"bundled": true, "bundled": true,
"dev": true, "dev": true
"optional": true
}, },
"safer-buffer": { "safer-buffer": {
"version": "2.1.2", "version": "2.1.2",
@ -3170,7 +3155,6 @@
"version": "1.0.2", "version": "1.0.2",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"code-point-at": "^1.0.0", "code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0", "is-fullwidth-code-point": "^1.0.0",
@ -3190,7 +3174,6 @@
"version": "3.0.1", "version": "3.0.1",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"ansi-regex": "^2.0.0" "ansi-regex": "^2.0.0"
} }
@ -3234,14 +3217,12 @@
"wrappy": { "wrappy": {
"version": "1.0.2", "version": "1.0.2",
"bundled": true, "bundled": true,
"dev": true, "dev": true
"optional": true
}, },
"yallist": { "yallist": {
"version": "3.0.2", "version": "3.0.2",
"bundled": true, "bundled": true,
"dev": true, "dev": true
"optional": true
} }
} }
}, },

View File

@ -60,6 +60,12 @@ pub struct JsValue {
idx: u32, idx: u32,
} }
const JSIDX_NULL: u32 = 0;
const JSIDX_UNDEFINED: u32 = 2;
const JSIDX_TRUE: u32 = 4;
const JSIDX_FALSE: u32 = 6;
const JSIDX_RESERVED: u32 = 8;
impl JsValue { impl JsValue {
/// Creates a new JS value which is a string. /// Creates a new JS value which is a string.
/// ///
@ -86,23 +92,17 @@ impl JsValue {
/// This function creates a JS object representing a boolean (a heap /// This function creates a JS object representing a boolean (a heap
/// allocated boolean) and returns a handle to the JS version of it. /// allocated boolean) and returns a handle to the JS version of it.
pub fn from_bool(b: bool) -> JsValue { pub fn from_bool(b: bool) -> JsValue {
unsafe { JsValue { idx: if b { JSIDX_TRUE } else { JSIDX_FALSE } }
JsValue { idx: __wbindgen_boolean_new(b as u32) }
}
} }
/// Creates a new JS value representing `undefined`. /// Creates a new JS value representing `undefined`.
pub fn undefined() -> JsValue { pub fn undefined() -> JsValue {
unsafe { JsValue { idx: JSIDX_UNDEFINED }
JsValue { idx: __wbindgen_undefined_new() }
}
} }
/// Creates a new JS value representing `null`. /// Creates a new JS value representing `null`.
pub fn null() -> JsValue { pub fn null() -> JsValue {
unsafe { JsValue { idx: JSIDX_NULL }
JsValue { idx: __wbindgen_null_new() }
}
} }
/// Creates a new JS symbol with the optional description specified. /// Creates a new JS symbol with the optional description specified.
@ -331,7 +331,12 @@ impl Clone for JsValue {
impl Drop for JsValue { impl Drop for JsValue {
fn drop(&mut self) { fn drop(&mut self) {
unsafe { unsafe {
__wbindgen_object_drop_ref(self.idx); // if the first bit is set then this is a stack value, so we for
// sure need to drop it. Otherwise if this is one of the special
// reserved values there's no need to drop it.
if (self.idx & 1) == 1 || self.idx >= JSIDX_RESERVED {
__wbindgen_object_drop_ref(self.idx);
}
} }
} }
} }