1# plugin string_builder 2# Copyright (c) 2024 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 15include_relative 'common.irt' 16include_relative '../../../irtoc/scripts/common.irt' 17 18module Constants 19 MUL_32 = "0x5bd1e995U" 20 MUL_64 = "0xc6a4a7935bd1e995ULL" 21 #TO_STRING_CACHE_OFFSET = "cross_values::GetEtsVmDoubleToStringCacheOffset(GetArch())" 22 ELEM_DATA_OFFSET = "8" 23 ELEM_STRING_OFFSET = ELEM_DATA_OFFSET 24 ELEM_FLAG_OFFSET = "12" 25 ELEM_NUMBER_OFFSET = "16" 26end 27 28function(:DoubleToStringDecimal, 29 params: {cache: 'ref', numInt: 'u64', unused: 'u64'}, 30 regmap: $full_regmap, 31 regalloc_set: $panda_mask, 32 mode: [:FastPath]) { 33 34 # Arm32 is not supported 35 if Options.arch == :arm32 36 Intrinsic(:UNREACHABLE).void.Terminator 37 next 38 end 39 40 num := Bitcast(numInt).f64 41 mul := Cast(Constants::MUL_64).u64 42 hash := Mul(numInt, mul).u64 43 hash := ShrI(hash).Imm(56).u64 44 45 elem_offset := AddI(ShlI(hash).Imm(2).u64).Imm(Constants::ARRAY_DATA_OFFSET).u64 46 elem := Load(cache, elem_offset).Volatile.ref 47 IfImm(Compare(elem, 0).EQ.b).Imm(0).NE.Unlikely { 48 Goto(:SlowPath) 49 } 50 # Volatile because need acquire ordering 51 cachedData := LoadI(elem).Imm(Constants::ELEM_DATA_OFFSET).Volatile.u64 52 cachedNumber := LoadI(elem).Imm(Constants::ELEM_NUMBER_OFFSET).Volatile.f64 53 54 flag := Cast(ShrI(cachedData).Imm(32).u64).u32 55 If(And(flag, 1).u32, 0).NE.Unlikely { 56 # elem is already being updated 57 Goto(:SlowPathNoCache) 58 } 59 IfImm(Compare(num, cachedNumber).NE.b).Imm(0).NE.Unlikely { 60 Goto(:SlowPathStore) 61 } 62 63 cachedStr := Bitcast(Cast(Cast(cachedData).u32).u64).ptr 64 # Relaxed load because we have acquire above 65 newFlag := LoadI(elem).Imm(Constants::ELEM_FLAG_OFFSET).u32 66 If(flag, newFlag).NE.Unlikely { 67 Goto(:SlowPathNoCache) 68 } 69 Return(cachedStr).ptr 70 71Label(:SlowPathStore) 72 ep_offset = get_entrypoint_offset("DOUBLE_TO_STRING_DECIMAL_STORE_SLOW_PATH") 73 Intrinsic(:SLOW_PATH_ENTRY, elem, numInt, cachedData).AddImm(ep_offset).MethodAsImm("DoubleToStringDecimalStoreOddSavedBridge").Terminator.ptr 74Label(:SlowPath) 75 ep_offset = get_entrypoint_offset("DOUBLE_TO_STRING_DECIMAL_SLOW_PATH") 76 Intrinsic(:SLOW_PATH_ENTRY, cache, numInt).AddImm(ep_offset).MethodAsImm("DoubleToStringDecimal3ArgBridge").Terminator.ptr 77Label(:SlowPathNoCache) 78 ep_offset = get_entrypoint_offset("DOUBLE_TO_STRING_DECIMAL_NO_CACHE_SLOW_PATH") 79 Intrinsic(:SLOW_PATH_ENTRY, numInt).AddImm(ep_offset).MethodAsImm("DoubleToStringDecimalNoCache3ArgBridge").Terminator.ptr 80} 81