• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env ruby
2
3# Copyright (c) 2021-2022 Huawei Device Co., Ltd.
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16include_relative 'common.irt'
17
18$available_regs = $temps_mask + :arg0 + :arg1
19# there are 2 temp registers are using in case of arm64 (instead of 3 for x86_64 and arm32)
20# that's why one callee-saved register is added to the mask
21if Options.arch == :arm64
22  $available_regs = $available_regs + :callee1
23end
24
25AllocateObjectTlabValidation = {
26  spills_count_max: { default: 2, arm32: 9999 },  # TODO(msherstennikov): set to 0 once regalloc supports smart temps
27  code_size_max: { arm64: 116, x86_64: 477, arm32: 9999 }
28  # TODO(msherstennikov): revert back code size values, once regalloc supports smart temps
29  # code_size_max: { arm64: 100, x86_64: 125, arm32: 9999 }
30}
31
32AllocateArrayTlabValidation = {
33  spills_count_max: { default: 2, arm32: 9999 },  # TODO(msherstennikov): set to 0 once regalloc supports smart temps
34  code_size_max: { arm64: 136, x86_64: 476, arm32: 9999 }
35  # TODO(msherstennikov): revert back code size values, once regalloc supports smart temps
36  # code_size_max: { arm64: 128, x86_64: 145, arm32: 9999 }
37}
38
39function(:AllocateObjectTlab,
40         params: {klass: 'ref', size: 'word'},
41         regmap: $full_regmap,
42         mode: [:FastPath],
43         regalloc_set: $available_regs,
44         validate: AllocateObjectTlabValidation) {
45
46  if Options.arch == :arm32
47    Intrinsic(:UNREACHABLE).Terminator.void
48    ReturnVoid().void
49    next
50  end
51
52  # Load pointer to the TLAB from TLS
53  tlab_ptr := LoadI(%tr).Imm(Constants::TLAB_OFFSET).ptr
54
55  # Load pointer to the start address of free memory in the TLAB
56  start := LoadI(tlab_ptr).Imm(Constants::TLAB_CUR_FREE_POSITION_OFFSET).ptr
57
58  # Load pointer to the end address of free memory in the TLAB
59  tls_end := LoadI(tlab_ptr).Imm(Constants::TLAB_MEMORY_END_ADDR_OFFSET).ptr
60
61  tls_size := Sub(tls_end, start).word
62
63  If(tls_size, size).LT.Unlikely.b {
64    Intrinsic(:SLOW_PATH_ENTRY, klass, size).AddImm(Constants::CREATE_OBJECT_BY_CLASS_SLOW_PATH).AddImm(Constants::CREATE_OBJECT_BY_CLASS_USUAL_BRIDGE).Terminator.ptr
65    Intrinsic(:UNREACHABLE).Terminator.void if defines.DEBUG
66  } Else {
67    call_runtime_save_all(Constants::WRITE_TLAB_STATS_NO_BRIDGE, start, size).void if defines.DEBUG
68    if defines.__SANITIZE_ADDRESS__ || defines.__SANITIZE_THREAD__
69      call_runtime_save_all(Constants::ANNOTATE_SANITIZERS_NO_BRIDGE, start, size).void
70    end
71    new_start := Add(start, size).ptr
72    StoreI(start, klass).Imm(Constants::OBJECT_CLASS_OFFSET).ref
73    addr := Add(tlab_ptr, Constants::TLAB_CUR_FREE_POSITION_OFFSET).ptr
74    StoreI(addr, new_start).Imm(0).Volatile.ptr
75    Return(start).ptr
76  }
77}
78
79# Allow three temps, two arguments registers and one callee saved register
80$available_regs = $available_regs + :callee0
81
82def AllocateArrayTlab(element_size)
83  function("AllocateArrayTlab#{element_size}".to_sym,
84           params: {klass: 'ref', elements_num: 'word'},
85           regmap: $full_regmap,
86           mode: [:FastPath],
87           regalloc_set: $available_regs,
88           validate: AllocateArrayTlabValidation) {
89    if Options.arch == :arm32
90      ReturnVoid().void
91      next
92    end
93    elements_num := And(elements_num, "0x00000000ffffffff").word
94    if element_size == 8
95      size := elements_num
96    elsif element_size == 16
97      size := Shl(elements_num, 1).word
98    elsif element_size == 32
99      size := Shl(elements_num, 2).word
100    elsif element_size == 64
101      size := Shl(elements_num, 3).word
102    else
103      raise "Wrong element size #{element_size}"
104    end
105    # Add sizeof(Array) and do align
106    size := Add(size, "DEFAULT_ALIGNMENT_IN_BYTES - 1 + CORETYPES_ARRAY_CLASS_SIZE").word
107    size := And(size, "(~(DEFAULT_ALIGNMENT_IN_BYTES - 1))").word
108
109    # Load pointer to the TLAB from TLS
110    tlab_ptr := LoadI(%tr).Imm(Constants::TLAB_OFFSET).ptr
111
112    # Load pointer to the start address of free memory in the TLAB
113    start := LoadI(tlab_ptr).Imm(Constants::TLAB_CUR_FREE_POSITION_OFFSET).ptr
114
115    # Load pointer to the end address of free memory in the TLAB
116    tls_end := LoadI(tlab_ptr).Imm(Constants::TLAB_MEMORY_END_ADDR_OFFSET).ptr
117
118    tls_size := Sub(tls_end, start).word
119
120    If(tls_size, size).LT.Unlikely.b {
121      Intrinsic(:SLOW_PATH_ENTRY, klass, elements_num).AddImm(Constants::CREATE_ARRAY_SLOW_PATH).AddImm(Constants::CREATE_ARRAY_USUAL_BRIDGE).Terminator.ptr
122      Intrinsic(:UNREACHABLE).Terminator.void if defines.DEBUG
123    } Else {
124      call_runtime_save_all(Constants::WRITE_TLAB_STATS_NO_BRIDGE, start, size).void if defines.DEBUG
125      if defines.__SANITIZE_ADDRESS__ || defines.__SANITIZE_THREAD__
126        call_runtime_save_all(Constants::ANNOTATE_SANITIZERS_NO_BRIDGE, start, size).void
127      end
128      new_start := Add(start, size).ptr
129      StoreI(start, klass).Imm(Constants::OBJECT_CLASS_OFFSET).ref
130      StoreI(start, elements_num).Imm(Constants::ARRAY_LENGTH_OFFSET).word
131      addr := Add(tlab_ptr, Constants::TLAB_CUR_FREE_POSITION_OFFSET).ptr
132      StoreI(addr, new_start).Imm(0).Volatile.ptr
133      Return(start).ptr
134    }
135  }
136end
137
138AllocateArrayTlab(8)
139AllocateArrayTlab(16)
140AllocateArrayTlab(32)
141AllocateArrayTlab(64)
142