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 20AllocateObjectTlabValidation = { 21 spills_count_max: 2, # TODO(msherstennikov): set to 0 once regalloc supports smart temps 22 code_size_max: { arm64: 108, x86_64: 460, arm32: 9999 } 23 # TODO(msherstennikov): revert back code size values, once regalloc supports smart temps 24 # code_size_max: { arm64: 100, x86_64: 125, arm32: 9999 } 25} 26 27AllocateArrayTlabValidation = { 28 spills_count_max: 2, # TODO(msherstennikov): set to 0 once regalloc supports smart temps 29 code_size_max: { arm64: 136, x86_64: 476, arm32: 9999 } 30 # TODO(msherstennikov): revert back code size values, once regalloc supports smart temps 31 # code_size_max: { arm64: 128, x86_64: 145, arm32: 9999 } 32} 33 34function(:AllocateObjectTlab, 35 params: {klass: 'ref', size: 'word'}, 36 regmap: $full_regmap, 37 mode: [:FastPath], 38 regalloc_set: $available_regs, 39 validate: AllocateObjectTlabValidation) { 40 41 if Options.arch == :arm32 42 Intrinsic(:UNREACHABLE).void 43 ReturnVoid() 44 next 45 end 46 47 # Load pointer to the TLAB from TLS 48 tlab_ptr := LoadI(%tr).Imm(Constants::TLAB_OFFSET).ptr 49 50 # Load pointer to the start address of free memory in the TLAB 51 start := LoadI(tlab_ptr).Imm(Constants::TLAB_CUR_FREE_POSITION_OFFSET).ptr 52 53 # Load pointer to the end address of free memory in the TLAB 54 tls_end := LoadI(tlab_ptr).Imm(Constants::TLAB_MEMORY_END_ADDR_OFFSET).ptr 55 56 tls_size := Sub(tls_end, start).word 57 58 If(tls_size, size).CC(:CC_LT).b { 59 Intrinsic(:SLOW_PATH_ENTRY, klass, size).AddImm(Constants::CREATE_OBJECT_BY_CLASS).ptr 60 Intrinsic(:UNREACHABLE).void if defines.DEBUG 61 } Else { 62 call_runtime_save_all(Constants::WRITE_TLAB_STATS_NO_BRIDGE, size).void if defines.DEBUG 63 if defines.__SANITIZE_ADDRESS__ || defines.__SANITIZE_THREAD__ 64 call_runtime_save_all(Constants::ANNOTATE_SANITIZERS_NO_BRIDGE, start, size).void 65 end 66 new_start := Add(start, size).ptr 67 StoreI(start, klass).Imm(Constants::OBJECT_CLASS_OFFSET).ref 68 addr := Add(tlab_ptr, Constants::TLAB_CUR_FREE_POSITION_OFFSET).ptr 69 StoreI(addr, new_start).Imm(0).Volatile.ptr 70 Return(start).ptr 71 } 72} 73 74# Allow three temps, two arguments registers and one callee saved register 75$available_regs = $available_regs + :callee0 76 77def AllocateArrayTlab(element_size) 78 function("AllocateArrayTlab#{element_size}".to_sym, 79 params: {klass: 'ref', elements_num: 'word'}, 80 regmap: $full_regmap, 81 mode: [:FastPath], 82 regalloc_set: $available_regs, 83 validate: AllocateArrayTlabValidation) { 84 if Options.arch == :arm32 85 ReturnVoid() 86 next 87 end 88 89 if element_size == 8 90 size := elements_num 91 elsif element_size == 16 92 size := Shl(elements_num, 1).word 93 elsif element_size == 32 94 size := Shl(elements_num, 2).word 95 elsif element_size == 64 96 size := Shl(elements_num, 3).word 97 else 98 raise "Wrong element size #{element_size}" 99 end 100 # Add sizeof(Array) and do align 101 size := Add(size, "DEFAULT_ALIGNMENT_IN_BYTES - 1 + CORETYPES_ARRAY_CLASS_SIZE").word 102 size := And(size, "~(DEFAULT_ALIGNMENT_IN_BYTES - 1)").word 103 104 # Load pointer to the TLAB from TLS 105 tlab_ptr := LoadI(%tr).Imm(Constants::TLAB_OFFSET).ptr 106 107 # Load pointer to the start address of free memory in the TLAB 108 start := LoadI(tlab_ptr).Imm(Constants::TLAB_CUR_FREE_POSITION_OFFSET).ptr 109 110 # Load pointer to the end address of free memory in the TLAB 111 tls_end := LoadI(tlab_ptr).Imm(Constants::TLAB_MEMORY_END_ADDR_OFFSET).ptr 112 113 tls_size := Sub(tls_end, start).word 114 115 If(tls_size, size).CC(:CC_LT).b { 116 Intrinsic(:SLOW_PATH_ENTRY, klass, elements_num).AddImm(Constants::CREATE_ARRAY_SLOW_PATH).ptr 117 Intrinsic(:UNREACHABLE).void if defines.DEBUG 118 } Else { 119 call_runtime_save_all(Constants::WRITE_TLAB_STATS_NO_BRIDGE, size).void if defines.DEBUG 120 if defines.__SANITIZE_ADDRESS__ || defines.__SANITIZE_THREAD__ 121 call_runtime_save_all(Constants::ANNOTATE_SANITIZERS_NO_BRIDGE, start, size).void 122 end 123 new_start := Add(start, size).ptr 124 StoreI(start, klass).Imm(Constants::OBJECT_CLASS_OFFSET).ref 125 StoreI(start, elements_num).Imm(Constants::ARRAY_LENGTH_OFFSET).ref 126 addr := Add(tlab_ptr, Constants::TLAB_CUR_FREE_POSITION_OFFSET).ptr 127 StoreI(addr, new_start).Imm(0).Volatile.ptr 128 Return(start).ptr 129 } 130 } 131end 132 133AllocateArrayTlab(8) 134AllocateArrayTlab(16) 135AllocateArrayTlab(32) 136AllocateArrayTlab(64) 137