mirror of
https://github.com/alacritty/alacritty.git
synced 2024-11-18 13:55:23 -05:00
Specialize Storage::swap for Row<T>
Removes 4 movaps instructions from generated assembly.
This commit is contained in:
parent
182524b884
commit
6eead1f95c
4 changed files with 59 additions and 15 deletions
|
@ -27,7 +27,7 @@ pub use self::row::Row;
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
mod storage;
|
mod storage;
|
||||||
use self::storage::Storage;
|
use self::storage::{Storage, Swap};
|
||||||
|
|
||||||
/// Bidirection iterator
|
/// Bidirection iterator
|
||||||
pub trait BidirectionalIterator: Iterator {
|
pub trait BidirectionalIterator: Iterator {
|
||||||
|
|
|
@ -58,7 +58,6 @@ impl<T: Copy + Clone> Row<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Resets contents to the contents of `other`
|
/// Resets contents to the contents of `other`
|
||||||
#[inline(never)]
|
|
||||||
pub fn reset(&mut self, other: &T) {
|
pub fn reset(&mut self, other: &T) {
|
||||||
let occ = self.occ;
|
let occ = self.occ;
|
||||||
for item in &mut self.inner[..occ] {
|
for item in &mut self.inner[..occ] {
|
||||||
|
|
|
@ -15,10 +15,67 @@ use std::ops::{Index, IndexMut};
|
||||||
use std::slice;
|
use std::slice;
|
||||||
|
|
||||||
use index::Line;
|
use index::Line;
|
||||||
|
use grid::Row;
|
||||||
|
|
||||||
/// Maximum number of invisible lines before buffer is resized
|
/// Maximum number of invisible lines before buffer is resized
|
||||||
const TRUNCATE_STEP: usize = 100;
|
const TRUNCATE_STEP: usize = 100;
|
||||||
|
|
||||||
|
pub trait Swap {
|
||||||
|
fn swap(&mut self, _: usize, _: usize);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Swap for Storage<T> {
|
||||||
|
/// Swap two lines in raw buffer
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// `swap` will panic if either `a` or `b` are out-of-bounds of the
|
||||||
|
/// underlying storage.
|
||||||
|
default fn swap(&mut self, a: usize, b: usize) {
|
||||||
|
let a = self.compute_index(a);
|
||||||
|
let b = self.compute_index(b);
|
||||||
|
|
||||||
|
self.inner.swap(a, b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Swap for Storage<Row<T>> {
|
||||||
|
/// Custom swap implementation for Row<T>.
|
||||||
|
///
|
||||||
|
/// Exploits the known size of Row<T> to produce a slightly more efficient
|
||||||
|
/// swap than going through slice::swap.
|
||||||
|
///
|
||||||
|
/// The default implementation from swap generates 8 movups and 4 movaps
|
||||||
|
/// instructions. This implementation only uses 8 movups instructions.
|
||||||
|
fn swap(&mut self, a: usize, b: usize) {
|
||||||
|
use std::mem::{size_of, uninitialized};
|
||||||
|
use ::libc::memcpy;
|
||||||
|
|
||||||
|
debug_assert!(size_of::<Row<T>>() == 32);
|
||||||
|
|
||||||
|
let a = self.compute_index(a);
|
||||||
|
let b = self.compute_index(b);
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
// Cast to a u64 array of size 4 to pretend that the data is copy
|
||||||
|
let a_ptr = self.inner.as_mut_ptr().offset(a as isize) as *mut u64;
|
||||||
|
let b_ptr = self.inner.as_mut_ptr().offset(b as isize) as *mut u64;
|
||||||
|
|
||||||
|
// Swap space
|
||||||
|
let mut tmp: u64;
|
||||||
|
|
||||||
|
// Copy 1 qword at a time
|
||||||
|
//
|
||||||
|
// The optimizer unrolls this loop and vectorizes it.
|
||||||
|
for i in 0..4 {
|
||||||
|
tmp = *a_ptr.offset(i);
|
||||||
|
*a_ptr.offset(i) = *b_ptr.offset(i);
|
||||||
|
*b_ptr.offset(i) = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||||
pub struct Storage<T> {
|
pub struct Storage<T> {
|
||||||
inner: Vec<T>,
|
inner: Vec<T>,
|
||||||
|
@ -205,19 +262,6 @@ impl<T> Storage<T> {
|
||||||
self.inner.swap(a, b);
|
self.inner.swap(a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Swap two lines in raw buffer
|
|
||||||
///
|
|
||||||
/// # Panics
|
|
||||||
///
|
|
||||||
/// `swap` will panic if either `a` or `b` are out-of-bounds of the
|
|
||||||
/// underlying storage.
|
|
||||||
pub fn swap(&mut self, a: usize, b: usize) {
|
|
||||||
let a = self.compute_index(a);
|
|
||||||
let b = self.compute_index(b);
|
|
||||||
|
|
||||||
self.inner.swap(a, b);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Iterator over *logical* entries in the storage
|
/// Iterator over *logical* entries in the storage
|
||||||
///
|
///
|
||||||
/// This *does not* iterate over hidden entries.
|
/// This *does not* iterate over hidden entries.
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
//! Alacritty - The GPU Enhanced Terminal
|
//! Alacritty - The GPU Enhanced Terminal
|
||||||
|
#![feature(specialization)]
|
||||||
#![cfg_attr(feature = "clippy", feature(plugin))]
|
#![cfg_attr(feature = "clippy", feature(plugin))]
|
||||||
#![cfg_attr(feature = "clippy", plugin(clippy))]
|
#![cfg_attr(feature = "clippy", plugin(clippy))]
|
||||||
#![cfg_attr(feature = "clippy", deny(clippy))]
|
#![cfg_attr(feature = "clippy", deny(clippy))]
|
||||||
|
|
Loading…
Reference in a new issue