Skip to content

Commit

Permalink
Add an ASCII fast-pass to ROW
Browse files Browse the repository at this point in the history
  • Loading branch information
lhecker committed Jun 30, 2023
1 parent d628c46 commit aaba650
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 26 deletions.
71 changes: 64 additions & 7 deletions src/buffer/out/Row.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -538,28 +538,85 @@ catch (...)

[[msvc::forceinline]] void ROW::WriteHelper::ReplaceText() noexcept
{
auto it = chars.begin();
const auto end = chars.end();
size_t ch = chBeg;

for (const auto& s : til::utf16_iterator{ chars })
// First a fast-pass for ASCII. ASCII is still predominant in technical areas.
while (it != end)
{
const auto wide = til::at(s, 0) < 0x80 ? false : IsGlyphFullWidth(s);
const auto colEndNew = gsl::narrow_cast<uint16_t>(colEnd + 1u + wide);
// MSVC is hoists the inlined call outside of the loop and puts it at the end of ROW::ReplaceText(), past WriteHelper::Finish().
// Inlining the call manually technically improves performance slightly, but is less maintainable.
if (*it >= 0x80)
{
_replaceTextUnicode(ch, it, end);
return;
}

if (colEnd >= colLimit)
{
colEndDirty = colLimit;
charsConsumed = ch - chBeg;
return;
}

til::at(row._charOffsets, colEnd) = gsl::narrow_cast<uint16_t>(ch);
++colEnd;
++ch;
++it;
}

colEndDirty = colEnd;
charsConsumed = ch - chBeg;
}

[[msvc::forceinline]] void ROW::WriteHelper::_replaceTextUnicode(size_t ch, std::wstring_view::const_iterator it, const std::wstring_view::const_iterator end)
{
while (it != end)
{
unsigned int width = 1;
auto ptr = &*it;
const auto wch = *ptr;
size_t advance = 1;

++it;

if (wch >= 0x80)
{
if (til::is_surrogate(wch))
{
if (it != end && til::is_leading_surrogate(wch) && til::is_trailing_surrogate(*it))
{
advance = 2;
++it;
}
else
{
ptr = &UNICODE_REPLACEMENT;
}
}

width = IsGlyphFullWidth({ ptr, advance }) + 1u;
}

const auto colEndNew = gsl::narrow_cast<uint16_t>(colEnd + width);
if (colEndNew > colLimit)
{
colEndDirty = colLimit;
break;
charsConsumed = ch - chBeg;
return;
}

til::at(row._charOffsets, colEnd++) = gsl::narrow_cast<uint16_t>(ch);
if (wide)
if (colEnd < colEndNew)
{
til::at(row._charOffsets, colEnd++) = gsl::narrow_cast<uint16_t>(ch | CharOffsetsTrailer);
}

colEndDirty = colEnd;
ch += s.size();
ch += advance;
}

colEndDirty = colEnd;
charsConsumed = ch - chBeg;
}

Expand Down
22 changes: 3 additions & 19 deletions src/buffer/out/Row.hpp
Original file line number Diff line number Diff line change
@@ -1,22 +1,5 @@
/*++
Copyright (c) Microsoft Corporation
Licensed under the MIT license.
Module Name:
- Row.hpp
Abstract:
- data structure for information associated with one row of screen buffer
Author(s):
- Michael Niksa (miniksa) 10-Apr-2014
- Paul Campbell (paulcam) 10-Apr-2014
Revision History:
- From components of output.h/.c
by Therese Stowell (ThereseS) 1990-1991
- Pulled into its own file from textBuffer.hpp/cpp (AustDi, 2017)
--*/
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

#pragma once

Expand Down Expand Up @@ -170,6 +153,7 @@ class ROW final
bool IsValid() const noexcept;
void ReplaceCharacters(til::CoordType width) noexcept;
void ReplaceText() noexcept;
void _replaceTextUnicode(size_t ch, std::wstring_view::const_iterator it, const std::wstring_view::const_iterator end);
void CopyTextFrom(const std::span<const uint16_t>& charOffsets) noexcept;
static void _copyOffsets(uint16_t* dst, const uint16_t* src, uint16_t size, uint16_t offset) noexcept;
void Finish();
Expand Down

0 comments on commit aaba650

Please sign in to comment.