Skip to content

Commit 06f7f1f

Browse files
committed
Optimize some span operations
Decode span data only once
1 parent 2e6a1a9 commit 06f7f1f

File tree

2 files changed

+58
-30
lines changed

2 files changed

+58
-30
lines changed

Diff for: src/librustc/ich/hcx.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -370,17 +370,18 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for Span {
370370
// If this is not an empty or invalid span, we want to hash the last
371371
// position that belongs to it, as opposed to hashing the first
372372
// position past it.
373-
let span_hi = if self.hi() > self.lo() {
373+
let span = self.data();
374+
let span_hi = if span.hi > span.lo {
374375
// We might end up in the middle of a multibyte character here,
375376
// but that's OK, since we are not trying to decode anything at
376377
// this position.
377-
self.hi() - ::syntax_pos::BytePos(1)
378+
span.hi - ::syntax_pos::BytePos(1)
378379
} else {
379-
self.hi()
380+
span.hi
380381
};
381382

382383
{
383-
let loc1 = hcx.codemap().byte_pos_to_line_and_col(self.lo());
384+
let loc1 = hcx.codemap().byte_pos_to_line_and_col(span.lo);
384385
let loc1 = loc1.as_ref()
385386
.map(|&(ref fm, line, col)| (&fm.name[..], line, col.to_usize()))
386387
.unwrap_or(("???", 0, 0));
@@ -413,7 +414,7 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for Span {
413414
}
414415
}
415416

416-
if self.ctxt() == SyntaxContext::empty() {
417+
if span.ctxt == SyntaxContext::empty() {
417418
0u8.hash_stable(hcx, hasher);
418419
} else {
419420
1u8.hash_stable(hcx, hasher);

Diff for: src/libsyntax_pos/lib.rs

+52-25
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,21 @@ pub struct SpanData {
7575
pub ctxt: SyntaxContext,
7676
}
7777

78+
impl SpanData {
79+
#[inline]
80+
pub fn with_lo(&self, lo: BytePos) -> Span {
81+
Span::new(lo, self.hi, self.ctxt)
82+
}
83+
#[inline]
84+
pub fn with_hi(&self, hi: BytePos) -> Span {
85+
Span::new(self.lo, hi, self.ctxt)
86+
}
87+
#[inline]
88+
pub fn with_ctxt(&self, ctxt: SyntaxContext) -> Span {
89+
Span::new(self.lo, self.hi, ctxt)
90+
}
91+
}
92+
7893
// The interner in thread-local, so `Span` shouldn't move between threads.
7994
impl !Send for Span {}
8095
impl !Sync for Span {}
@@ -109,38 +124,37 @@ impl Span {
109124
}
110125
#[inline]
111126
pub fn with_lo(self, lo: BytePos) -> Span {
112-
let base = self.data();
113-
Span::new(lo, base.hi, base.ctxt)
127+
self.data().with_lo(lo)
114128
}
115129
#[inline]
116130
pub fn hi(self) -> BytePos {
117131
self.data().hi
118132
}
119133
#[inline]
120134
pub fn with_hi(self, hi: BytePos) -> Span {
121-
let base = self.data();
122-
Span::new(base.lo, hi, base.ctxt)
135+
self.data().with_hi(hi)
123136
}
124137
#[inline]
125138
pub fn ctxt(self) -> SyntaxContext {
126139
self.data().ctxt
127140
}
128141
#[inline]
129142
pub fn with_ctxt(self, ctxt: SyntaxContext) -> Span {
130-
let base = self.data();
131-
Span::new(base.lo, base.hi, ctxt)
143+
self.data().with_ctxt(ctxt)
132144
}
133145

134146
/// Returns a new span representing just the end-point of this span
135147
pub fn end_point(self) -> Span {
136-
let lo = cmp::max(self.hi().0 - 1, self.lo().0);
137-
self.with_lo(BytePos(lo))
148+
let span = self.data();
149+
let lo = cmp::max(span.hi.0 - 1, span.lo.0);
150+
span.with_lo(BytePos(lo))
138151
}
139152

140153
/// Returns a new span representing the next character after the end-point of this span
141154
pub fn next_point(self) -> Span {
142-
let lo = cmp::max(self.hi().0, self.lo().0 + 1);
143-
Span::new(BytePos(lo), BytePos(lo), self.ctxt())
155+
let span = self.data();
156+
let lo = cmp::max(span.hi.0, span.lo.0 + 1);
157+
Span::new(BytePos(lo), BytePos(lo), span.ctxt)
144158
}
145159

146160
/// Returns `self` if `self` is not the dummy span, and `other` otherwise.
@@ -150,21 +164,27 @@ impl Span {
150164

151165
/// Return true if `self` fully encloses `other`.
152166
pub fn contains(self, other: Span) -> bool {
153-
self.lo() <= other.lo() && other.hi() <= self.hi()
167+
let span = self.data();
168+
let other = other.data();
169+
span.lo <= other.lo && other.hi <= span.hi
154170
}
155171

156172
/// Return true if the spans are equal with regards to the source text.
157173
///
158174
/// Use this instead of `==` when either span could be generated code,
159175
/// and you only care that they point to the same bytes of source text.
160176
pub fn source_equal(&self, other: &Span) -> bool {
161-
self.lo() == other.lo() && self.hi() == other.hi()
177+
let span = self.data();
178+
let other = other.data();
179+
span.lo == other.lo && span.hi == other.hi
162180
}
163181

164182
/// Returns `Some(span)`, where the start is trimmed by the end of `other`
165183
pub fn trim_start(self, other: Span) -> Option<Span> {
166-
if self.hi() > other.hi() {
167-
Some(self.with_lo(cmp::max(self.lo(), other.hi())))
184+
let span = self.data();
185+
let other = other.data();
186+
if span.hi > other.hi {
187+
Some(span.with_lo(cmp::max(span.lo, other.hi)))
168188
} else {
169189
None
170190
}
@@ -268,29 +288,35 @@ impl Span {
268288

269289
/// Return a `Span` that would enclose both `self` and `end`.
270290
pub fn to(self, end: Span) -> Span {
291+
let span = self.data();
292+
let end = end.data();
271293
Span::new(
272-
cmp::min(self.lo(), end.lo()),
273-
cmp::max(self.hi(), end.hi()),
294+
cmp::min(span.lo, end.lo),
295+
cmp::max(span.hi, end.hi),
274296
// FIXME(jseyfried): self.ctxt should always equal end.ctxt here (c.f. issue #23480)
275-
if self.ctxt() == SyntaxContext::empty() { end.ctxt() } else { self.ctxt() },
297+
if span.ctxt == SyntaxContext::empty() { end.ctxt } else { span.ctxt },
276298
)
277299
}
278300

279301
/// Return a `Span` between the end of `self` to the beginning of `end`.
280302
pub fn between(self, end: Span) -> Span {
303+
let span = self.data();
304+
let end = end.data();
281305
Span::new(
282-
self.hi(),
283-
end.lo(),
284-
if end.ctxt() == SyntaxContext::empty() { end.ctxt() } else { self.ctxt() },
306+
span.hi,
307+
end.lo,
308+
if end.ctxt == SyntaxContext::empty() { end.ctxt } else { span.ctxt },
285309
)
286310
}
287311

288312
/// Return a `Span` between the beginning of `self` to the beginning of `end`.
289313
pub fn until(self, end: Span) -> Span {
314+
let span = self.data();
315+
let end = end.data();
290316
Span::new(
291-
self.lo(),
292-
end.lo(),
293-
if end.ctxt() == SyntaxContext::empty() { end.ctxt() } else { self.ctxt() },
317+
span.lo,
318+
end.lo,
319+
if end.ctxt == SyntaxContext::empty() { end.ctxt } else { span.ctxt },
294320
)
295321
}
296322
}
@@ -316,13 +342,14 @@ impl Default for Span {
316342

317343
impl serialize::UseSpecializedEncodable for Span {
318344
fn default_encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
345+
let span = self.data();
319346
s.emit_struct("Span", 2, |s| {
320347
s.emit_struct_field("lo", 0, |s| {
321-
self.lo().encode(s)
348+
span.lo.encode(s)
322349
})?;
323350

324351
s.emit_struct_field("hi", 1, |s| {
325-
self.hi().encode(s)
352+
span.hi.encode(s)
326353
})
327354
})
328355
}

0 commit comments

Comments
 (0)