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