• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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