From 15c6637c8691a189aaaf87a713a9acd3d1587c23 Mon Sep 17 00:00:00 2001 From: Vlad Brezae Date: Wed, 12 Aug 2020 13:53:09 +0300 Subject: [PATCH] [interp] Intrinsify IndexOfOrLessThan Speeds up json deserialization by 5-10% --- .../src/System/Text/Json/Reader/JsonReaderHelper.cs | 1 + src/mono/mono/mini/interp/interp-intrins.c | 12 ++++++++++++ src/mono/mono/mini/interp/interp-intrins.h | 3 +++ src/mono/mono/mini/interp/interp.c | 6 ++++++ src/mono/mono/mini/interp/mintops.def | 1 + src/mono/mono/mini/interp/transform.c | 5 +++++ 6 files changed, 28 insertions(+) diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Reader/JsonReaderHelper.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Reader/JsonReaderHelper.cs index dbea5c0fea0c10..94f1973d1f100c 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Reader/JsonReaderHelper.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Reader/JsonReaderHelper.cs @@ -75,6 +75,7 @@ ref MemoryMarshal.GetReference(span), span.Length); } + // Intrinsified in mono interpreter private static unsafe int IndexOfOrLessThan(ref byte searchSpace, byte value0, byte value1, byte lessThan, int length) { Debug.Assert(length >= 0); diff --git a/src/mono/mono/mini/interp/interp-intrins.c b/src/mono/mono/mini/interp/interp-intrins.c index b4093225dd288a..1cfb7e660a38d8 100644 --- a/src/mono/mono/mini/interp/interp-intrins.c +++ b/src/mono/mono/mini/interp/interp-intrins.c @@ -138,3 +138,15 @@ interp_intrins_widen_ascii_to_utf16 (guint8 *pAsciiBuffer, mono_unichar2 *pUtf16 } return currentOffset; } + +int +interp_intrins_json_index_of_lt (guint8 *searchSpace, guint8 value0, guint8 value1, guint8 lessThan, gint32 length) +{ + for (int i = 0; i < length; i++) { + guint8 value = searchSpace [i]; + if (value0 == value || value1 == value || lessThan > value) + return i; + } + + return -1; +} diff --git a/src/mono/mono/mini/interp/interp-intrins.h b/src/mono/mono/mini/interp/interp-intrins.h index 2be852f3315208..35e4dedb66ba59 100644 --- a/src/mono/mono/mini/interp/interp-intrins.h +++ b/src/mono/mono/mini/interp/interp-intrins.h @@ -24,4 +24,7 @@ interp_intrins_u32_to_decstr (guint32 value, MonoArray *cache, MonoVTable *vtabl mono_u interp_intrins_widen_ascii_to_utf16 (guint8 *pAsciiBuffer, mono_unichar2 *pUtf16Buffer, mono_u elementCount); +int +interp_intrins_json_index_of_lt (guint8 *searchSpace, guint8 value0, guint8 value1, guint8 lessThan, gint32 length); + #endif /* __MONO_MINI_INTERP_INTRINSICS_H__ */ diff --git a/src/mono/mono/mini/interp/interp.c b/src/mono/mono/mini/interp/interp.c index 53d20e1997c8d7..6ba5dff0dcfa4f 100644 --- a/src/mono/mono/mini/interp/interp.c +++ b/src/mono/mono/mini/interp/interp.c @@ -5355,6 +5355,12 @@ interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClauseArgs ip++; MINT_IN_BREAK; } + MINT_IN_CASE(MINT_INTRINS_JSON_INDEX_OF_LT) { + sp -= 4; + sp [-1].data.i = interp_intrins_json_index_of_lt ((guint8*)sp [-1].data.p, (guint8)sp [0].data.i, (guint8)sp [1].data.i, (guint8)sp [2].data.i, sp [3].data.i); + ip++; + MINT_IN_BREAK; + } MINT_IN_CASE(MINT_INTRINS_UNSAFE_BYTE_OFFSET) { sp -= 2; sp [0].data.nati = (guint8*)sp [1].data.p - (guint8*)sp [0].data.p; diff --git a/src/mono/mono/mini/interp/mintops.def b/src/mono/mono/mini/interp/mintops.def index 6e4d90fab787fa..d4731aedcda6ad 100644 --- a/src/mono/mono/mini/interp/mintops.def +++ b/src/mono/mono/mini/interp/mintops.def @@ -800,3 +800,4 @@ OPDEF(MINT_INTRINS_ORDINAL_IGNORE_CASE_ASCII, "intrins_ordinal_ignore_case_ascii OPDEF(MINT_INTRINS_64ORDINAL_IGNORE_CASE_ASCII, "intrins_64ordinal_ignore_case_ascii", 1, Pop2, Push1, MintOpNoArgs) OPDEF(MINT_INTRINS_U32_TO_DECSTR, "intrins_u32_to_decstr", 3, Pop1, Push1, MintOpNoArgs) OPDEF(MINT_INTRINS_WIDEN_ASCII_TO_UTF16, "intrins_widen_ascii_to_utf16", 1, Pop3, Push1, MintOpNoArgs) +OPDEF(MINT_INTRINS_JSON_INDEX_OF_LT, "intrins_json_index_of_lt", 1, Pop5, Push1, MintOpNoArgs) diff --git a/src/mono/mono/mini/interp/transform.c b/src/mono/mono/mini/interp/transform.c index a0fd6c0b068989..3e2564ee628f80 100644 --- a/src/mono/mono/mini/interp/transform.c +++ b/src/mono/mono/mini/interp/transform.c @@ -1895,6 +1895,11 @@ interp_handle_intrinsics (TransformData *td, MonoMethod *target_method, MonoClas !strncmp ("System.Runtime.Intrinsics", klass_name_space, 25) && !strcmp (tm, "get_IsSupported")) { *op = MINT_LDC_I4_0; + } else if (!strcmp (m_class_get_image (target_method->klass)->assembly_name, "System.Text.Json") && + !strcmp (klass_name_space, "System.Text.Json") && + !strcmp (klass_name, "JsonReaderHelper")) { + if (!strcmp (tm, "IndexOfOrLessThan")) + *op = MINT_INTRINS_JSON_INDEX_OF_LT; } #endif