Skip to content

Commit 3228603

Browse files
Avoid generating empty closures for fieldless enums
For many enums, this avoids generating lots of tiny stubs that need to be codegen'd and then inlined and removed by LLVM.
1 parent 65f3f8b commit 3228603

File tree

3 files changed

+46
-7
lines changed

3 files changed

+46
-7
lines changed

compiler/rustc_macros/src/serialize.rs

+18-7
Original file line numberDiff line numberDiff line change
@@ -247,13 +247,24 @@ fn encodable_body(
247247
})
248248
.collect();
249249

250-
let result = quote! { ::rustc_serialize::Encoder::emit_enum_variant(
251-
__encoder,
252-
#variant_name,
253-
#variant_idx,
254-
#field_idx,
255-
|__encoder| { ::std::result::Result::Ok({ #encode_fields }) }
256-
) };
250+
let result = if field_idx != 0 {
251+
quote! {
252+
::rustc_serialize::Encoder::emit_enum_variant(
253+
__encoder,
254+
#variant_name,
255+
#variant_idx,
256+
#field_idx,
257+
|__encoder| { ::std::result::Result::Ok({ #encode_fields }) }
258+
)
259+
}
260+
} else {
261+
quote! {
262+
::rustc_serialize::Encoder::emit_fieldless_enum_variant::<#variant_idx>(
263+
__encoder,
264+
#variant_name,
265+
)
266+
}
267+
};
257268
variant_idx += 1;
258269
result
259270
});

compiler/rustc_serialize/src/json.rs

+14
Original file line numberDiff line numberDiff line change
@@ -589,6 +589,13 @@ impl<'a> crate::Encoder for Encoder<'a> {
589589
}
590590
}
591591

592+
fn emit_fieldless_enum_variant<const ID: usize>(
593+
&mut self,
594+
name: &str,
595+
) -> Result<(), Self::Error> {
596+
escape_str(self.writer, name)
597+
}
598+
592599
fn emit_enum_variant_arg<F>(&mut self, first: bool, f: F) -> EncodeResult
593600
where
594601
F: FnOnce(&mut Encoder<'a>) -> EncodeResult,
@@ -885,6 +892,13 @@ impl<'a> crate::Encoder for PrettyEncoder<'a> {
885892
}
886893
}
887894

895+
fn emit_fieldless_enum_variant<const ID: usize>(
896+
&mut self,
897+
name: &str,
898+
) -> Result<(), Self::Error> {
899+
escape_str(self.writer, name)
900+
}
901+
888902
fn emit_enum_variant_arg<F>(&mut self, first: bool, f: F) -> EncodeResult
889903
where
890904
F: FnOnce(&mut PrettyEncoder<'a>) -> EncodeResult,

compiler/rustc_serialize/src/serialize.rs

+14
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,20 @@ pub trait Encoder {
5858
f(self)
5959
}
6060

61+
// We put the field index in a const generic to allow the emit_usize to be
62+
// compiled into a more efficient form. In practice, the variant index is
63+
// known at compile-time, and that knowledge allows much more efficient
64+
// codegen than we'd otherwise get. LLVM isn't always able to make the
65+
// optimization that would otherwise be necessary here, likely due to the
66+
// multiple levels of inlining and const-prop that are needed.
67+
#[inline]
68+
fn emit_fieldless_enum_variant<const ID: usize>(
69+
&mut self,
70+
_v_name: &str,
71+
) -> Result<(), Self::Error> {
72+
self.emit_usize(ID)
73+
}
74+
6175
#[inline]
6276
fn emit_enum_variant_arg<F>(&mut self, _first: bool, f: F) -> Result<(), Self::Error>
6377
where

0 commit comments

Comments
 (0)