servo: Merge #15659 - Eliminate a mem::transmute in CodeGen (from gregkatz:eliminate_transmute_find_enum); r=Ms2ger

<!-- Please describe your changes on the following line: -->
Eliminate a mem::transmute in CodeGen by changing the find_enum_string_index function to take a slice of pairs and return an enum value.

---
<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: -->
- [X] `./mach build -d` does not report any errors
- [X] `./mach test-tidy` does not report any errors
- [X] These changes fix #15587 (github issue number if applicable).

<!-- Either: -->
- [ ] There are tests for these changes OR
- [X] These changes do not require tests because _____

<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->

Source-Repo: https://github.com/servo/servo
Source-Revision: af6353df87770c6d616facdc07f9f929e99b9eda

--HG--
extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear
extra : subtree_revision : 42992b500828053caff27a6ee20ca35f0f42f2d5
This commit is contained in:
Gregory Katz 2017-02-21 04:28:32 -08:00
Родитель 163a482778
Коммит d9d32c4c2a
2 изменённых файлов: 18 добавлений и 19 удалений

Просмотреть файл

@ -967,14 +967,11 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
handleInvalidEnumValueCode = "return true;" handleInvalidEnumValueCode = "return true;"
template = ( template = (
"match find_enum_string_index(cx, ${val}, %(values)s) {\n" "match find_enum_value(cx, ${val}, %(pairs)s) {\n"
" Err(_) => { %(exceptionCode)s },\n" " Err(_) => { %(exceptionCode)s },\n"
" Ok((None, search)) => { %(handleInvalidEnumValueCode)s },\n" " Ok((None, search)) => { %(handleInvalidEnumValueCode)s },\n"
" Ok((Some(index), _)) => {\n" " Ok((Some(&value), _)) => value,\n"
" //XXXjdm need some range checks up in here.\n" "}" % {"pairs": enum + "Values::pairs",
" mem::transmute(index)\n"
" },\n"
"}" % {"values": enum + "Values::strings",
"exceptionCode": exceptionCode, "exceptionCode": exceptionCode,
"handleInvalidEnumValueCode": handleInvalidEnumValueCode}) "handleInvalidEnumValueCode": handleInvalidEnumValueCode})
@ -3978,39 +3975,41 @@ class CGEnum(CGThing):
def __init__(self, enum): def __init__(self, enum):
CGThing.__init__(self) CGThing.__init__(self)
ident = enum.identifier.name
decl = """\ decl = """\
#[repr(usize)] #[repr(usize)]
#[derive(JSTraceable, PartialEq, Copy, Clone, HeapSizeOf, Debug)] #[derive(JSTraceable, PartialEq, Copy, Clone, HeapSizeOf, Debug)]
pub enum %s { pub enum %s {
%s %s
} }
""" % (enum.identifier.name, ",\n ".join(map(getEnumValueName, enum.values()))) """ % (ident, ",\n ".join(map(getEnumValueName, enum.values())))
pairs = ",\n ".join(['("%s", super::%s::%s)' % (val, ident, getEnumValueName(val)) for val in enum.values()])
inner = """\ inner = """\
use dom::bindings::conversions::ToJSValConvertible; use dom::bindings::conversions::ToJSValConvertible;
use js::jsapi::{JSContext, MutableHandleValue}; use js::jsapi::{JSContext, MutableHandleValue};
use js::jsval::JSVal; use js::jsval::JSVal;
pub const strings: &'static [&'static str] = &[ pub const pairs: &'static [(&'static str, super::%s)] = &[
%s, %s,
]; ];
impl super::%s { impl super::%s {
pub fn as_str(&self) -> &'static str { pub fn as_str(&self) -> &'static str {
strings[*self as usize] pairs[*self as usize].0
} }
} }
impl ToJSValConvertible for super::%s { impl ToJSValConvertible for super::%s {
unsafe fn to_jsval(&self, cx: *mut JSContext, rval: MutableHandleValue) { unsafe fn to_jsval(&self, cx: *mut JSContext, rval: MutableHandleValue) {
strings[*self as usize].to_jsval(cx, rval); pairs[*self as usize].0.to_jsval(cx, rval);
} }
} }
""" % (",\n ".join(['"%s"' % val for val in enum.values()]), enum.identifier.name, enum.identifier.name) """ % (ident, pairs, ident, ident)
self.cgRoot = CGList([ self.cgRoot = CGList([
CGGeneric(decl), CGGeneric(decl),
CGNamespace.build([enum.identifier.name + "Values"], CGNamespace.build([ident + "Values"],
CGIndenter(CGGeneric(inner)), public=True), CGIndenter(CGGeneric(inner)), public=True),
]) ])
@ -5573,7 +5572,7 @@ def generate_imports(config, cgthings, descriptors, callbacks=None, dictionaries
'dom::bindings::utils::ProtoOrIfaceArray', 'dom::bindings::utils::ProtoOrIfaceArray',
'dom::bindings::utils::enumerate_global', 'dom::bindings::utils::enumerate_global',
'dom::bindings::utils::finalize_global', 'dom::bindings::utils::finalize_global',
'dom::bindings::utils::find_enum_string_index', 'dom::bindings::utils::find_enum_value',
'dom::bindings::utils::generic_getter', 'dom::bindings::utils::generic_getter',
'dom::bindings::utils::generic_lenient_getter', 'dom::bindings::utils::generic_lenient_getter',
'dom::bindings::utils::generic_lenient_setter', 'dom::bindings::utils::generic_lenient_setter',

Просмотреть файл

@ -177,20 +177,20 @@ pub fn get_array_index_from_id(_cx: *mut JSContext, id: HandleId) -> Option<u32>
}*/ }*/
} }
/// Find the index of a string given by `v` in `values`. /// Find the enum equivelent of a string given by `v` in `pairs`.
/// Returns `Err(())` on JSAPI failure (there is a pending exception), and /// Returns `Err(())` on JSAPI failure (there is a pending exception), and
/// `Ok((None, value))` if there was no matching string. /// `Ok((None, value))` if there was no matching string.
pub unsafe fn find_enum_string_index(cx: *mut JSContext, pub unsafe fn find_enum_value<'a, T>(cx: *mut JSContext,
v: HandleValue, v: HandleValue,
values: &[&'static str]) pairs: &'a [(&'static str, T)])
-> Result<(Option<usize>, DOMString), ()> { -> Result<(Option<&'a T>, DOMString), ()> {
let jsstr = ToString(cx, v); let jsstr = ToString(cx, v);
if jsstr.is_null() { if jsstr.is_null() {
return Err(()); return Err(());
} }
let search = jsstring_to_str(cx, jsstr); let search = jsstring_to_str(cx, jsstr);
Ok((values.iter().position(|value| search == *value), search)) Ok((pairs.iter().find(|&&(key, _)| search == *key).map(|&(_, ref ev)| ev), search))
} }
/// Returns wether `obj` is a platform object /// Returns wether `obj` is a platform object