@@ -771,18 +771,23 @@ void SlowByteLengthUtf8(const FunctionCallbackInfo<Value>& args) {
771771 return ;
772772 }
773773
774+ size_t utf8_length;
775+
776+ // Fast path for external one-byte strings (common case for ASCII/Latin1)
777+ if (source->IsExternalOneByte ()) {
778+ auto ext = source->GetExternalOneByteStringResource ();
779+ utf8_length = simdutf::utf8_length_from_latin1 (ext->data (), ext->length ());
780+ args.GetReturnValue ().Set (static_cast <uint64_t >(utf8_length));
781+ return ;
782+ }
783+
784+ // For non-external strings, use ValueView
774785 String::ValueView view (isolate, source);
775786 size_t length = view.length ();
776- size_t utf8_length;
777787
778788 if (view.is_one_byte ()) {
779789 auto data = reinterpret_cast <const char *>(view.data8 ());
780- simdutf::result result = simdutf::validate_ascii_with_errors (data, length);
781- if (result.error == simdutf::SUCCESS) {
782- utf8_length = length; // Pure ASCII, length stays the same
783- } else {
784- utf8_length = simdutf::utf8_length_from_latin1 (data, length);
785- }
790+ utf8_length = simdutf::utf8_length_from_latin1 (data, length);
786791 } else {
787792 auto data = reinterpret_cast <const char16_t *>(view.data16 ());
788793 if (simdutf::validate_utf16 (data, length)) {
@@ -805,21 +810,32 @@ uint32_t FastByteLengthUtf8(
805810 CHECK (sourceValue->IsString ());
806811 Local<String> sourceStr = sourceValue.As <String>();
807812
813+ int length = sourceStr->Length ();
814+
808815 // For short inputs, use V8's path - function call overhead not worth it
809816 static constexpr int kSmallStringThreshold = 128 ;
810- if (sourceStr->Length () <= kSmallStringThreshold ) {
817+ if (length <= kSmallStringThreshold ) {
818+ return sourceStr->Utf8LengthV2 (isolate);
819+ }
820+
821+ // Fast path for external one-byte strings (common case for ASCII/Latin1)
822+ if (sourceStr->IsExternalOneByte ()) {
823+ auto ext = sourceStr->GetExternalOneByteStringResource ();
824+ return simdutf::utf8_length_from_latin1 (ext->data (), ext->length ());
825+ }
826+
827+ // For one-byte (Latin1/ASCII) strings, V8 is already fast and ValueView
828+ // creation has overhead. Use higher threshold before switching to simdutf.
829+ static constexpr int kOneByteLargeThreshold = 1024 ;
830+ if (sourceStr->IsOneByte () && length <= kOneByteLargeThreshold ) {
811831 return sourceStr->Utf8LengthV2 (isolate);
812832 }
813833
834+ // For larger strings or two-byte strings, use ValueView + simdutf
814835 String::ValueView view (isolate, sourceStr);
815- size_t length = view.length ();
816836
817837 if (view.is_one_byte ()) {
818838 auto data = reinterpret_cast <const char *>(view.data8 ());
819- simdutf::result result = simdutf::validate_ascii_with_errors (data, length);
820- if (result.error == simdutf::SUCCESS) {
821- return length; // Pure ASCII, length stays the same
822- }
823839 return simdutf::utf8_length_from_latin1 (data, length);
824840 }
825841
0 commit comments