• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef ECMASCRIPT_PLATFORM_JSON_HELPER_INTERNAL_ARM64_H
17 #define ECMASCRIPT_PLATFORM_JSON_HELPER_INTERNAL_ARM64_H
18 #include <arm_neon.h>
19 #include "ecmascript/base/config.h"
20 
21 namespace panda::ecmascript::base {
22 class JsonHelperInternal {
23 friend class JsonPlatformHelper;
24 private:
25     static constexpr uint8x16_t QUOTE_INDEX_MASK_DATA = {
26         0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71, 0x81, 0x91, 0xA1, 0xB1, 0xC1, 0xD1, 0xE1, 0xF1
27     };
28     static constexpr uint8x16_t BACKSLASH_INDEX_MASK_DATA = {
29         0x02, 0x12, 0x22, 0x32, 0x42, 0x52, 0x62, 0x72, 0x82, 0x92, 0xA2, 0xB2, 0xC2, 0xD2, 0xE2, 0xF2
30     };
31     static constexpr uint8x16_t CONTROL_INDEX_MASK_DATA = {
32         0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74, 0x84, 0x94, 0xA4, 0xB4, 0xC4, 0xD4, 0xE4, 0xF4
33     };
34     static constexpr uint8x16_t QUOTE_VECTOR = {
35         '"', '"', '"', '"', '"', '"', '"', '"', '"', '"', '"', '"', '"', '"', '"', '"'
36     };
37     static constexpr uint8x16_t BACKSLASH_VECTOR = {
38         '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\', '\\'
39     };
40     static constexpr uint8x16_t SPACE_VECTOR = {
41         ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '
42     };
43     static constexpr uint8x16_t ZERO_VECTOR = {
44         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
45     };
46     static constexpr uint8x16_t COMPARE_VECTOR = {
47         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
48     };
49     static constexpr uint8_t QUOTE_MASK = 0x01;
50     static constexpr uint8_t BACKSLASH_MASK = 0x02;
51     static constexpr uint8_t CONTROL_MASK = 0x04;
52     static constexpr uint8_t INDEX_MASK = 0xF0;
53     static constexpr uint8_t INDEX_SHIFT = 4;
54     static constexpr uint8_t QUOTE_CHAR = '"';
55     static constexpr uint8_t BACKSLASH_CHAR = '\\';
56     static constexpr uint8_t SPACE_CHAR = ' ';
57     static constexpr uint8_t COMPARE_MASK = 0xFF;
58     static constexpr size_t CHUNK_SIZE = 16;
59 
60     /**
61     * origin:          [   x,   x,'\\',   x, '"',   x,   x,'\t',   x,   x,'\\','\b',   x,   x, '"',   x]
62     * first step:
63     *      quote:      [   0,   0,   0,   0,0x41,   0,   0,   0,   0,   0,   0,   0,   0,   0,0xE1,   0]
64     *      backslash:  [   0,   0,0x22,   0,   0,   0,   0,   0,   0,   0,0xA2,   0,   0,   0,   0,   0]
65     *      control:    [   0,   0,   0,   0,   0,   0,   0,0x74,   0,   0,   0,0xB4,   0,   0,   0,   0]
66     * second step:
67     *      combine:    [   0,   0,0x22,   0,0x41,   0,   0,0x74,   0,   0,0xA2,0xB4,   0,   0,0xE1,   0]
68     *      final:      [0xFF,0xFF,0x22,0xFF,0x41,0xFF,0xFF,0x74,0xFF,0xFF,0xA2,0xB4,0xFF,0xFF,0xE1,0xFF]
69     * min_index: 0x22 =>  0x22 & 0x02 > 0  =>  backslash
70     */
ReadJsonStringRangeForUtf8(bool & isFastString,const uint8_t * current,const uint8_t * range,const uint8_t * & end)71     static bool ReadJsonStringRangeForUtf8(bool &isFastString, const uint8_t *current,
72                                        const uint8_t *range, const uint8_t *&end)
73     {
74         const uint8_t* cur = current;
75         for (; cur + CHUNK_SIZE <= range; cur += CHUNK_SIZE) {
76             uint8x16_t chunk = vld1q_u8(cur);
77             uint8x16_t quote_mask = vandq_u8(QUOTE_INDEX_MASK_DATA, vceqq_u8(chunk, QUOTE_VECTOR));
78             uint8x16_t backslash_mask = vandq_u8(BACKSLASH_INDEX_MASK_DATA, vceqq_u8(chunk, BACKSLASH_VECTOR));
79             uint8x16_t control_mask = vandq_u8(CONTROL_INDEX_MASK_DATA, vcltq_u8(chunk, SPACE_VECTOR));
80             uint8x16_t combined_mask = vorrq_u8(quote_mask, vorrq_u8(backslash_mask, control_mask));
81             uint8x16_t zero_mask = vceqq_u8(combined_mask, ZERO_VECTOR);
82             uint8x16_t indices = vbslq_u8(zero_mask, COMPARE_VECTOR, combined_mask);
83             uint8_t min_index = vminvq_u8(indices);
84             if (min_index != COMPARE_MASK) { // 0xFF means no special characters
85                 if ((min_index & QUOTE_MASK) > 0) {
86                     end = cur + ((min_index & INDEX_MASK) >> INDEX_SHIFT);
87                     return true;
88                 }
89                 if (UNLIKELY((min_index & BACKSLASH_MASK) > 0)) {
90                     isFastString = false;
91                     return true;
92                 }
93                 if (UNLIKELY((min_index & CONTROL_MASK) > 0)) {
94                     return false;
95                 }
96             }
97         }
98         for (; cur != range; ++cur) {
99             if (*cur == QUOTE_CHAR) {
100                 end = cur;
101                 return true;
102             }
103             if (UNLIKELY(*cur == BACKSLASH_CHAR)) {
104                 isFastString = false;
105                 return true;
106             }
107             if (UNLIKELY(*cur < SPACE_CHAR)) {
108                 return false;
109             }
110         }
111         return false;
112     }
113 };
114 }
115 #endif //ECMASCRIPT_PLATFORM_JSON_HELPER_INTERNAL_ARM64_H
116