Path: blob/master/runtime/compiler/aarch64/codegen/J9ARM64Snippet.cpp
6004 views
/*******************************************************************************1* Copyright (c) 2019, 2020 IBM Corp. and others2*3* This program and the accompanying materials are made available under4* the terms of the Eclipse Public License 2.0 which accompanies this5* distribution and is available at https://www.eclipse.org/legal/epl-2.0/6* or the Apache License, Version 2.0 which accompanies this distribution and7* is available at https://www.apache.org/licenses/LICENSE-2.0.8*9* This Source Code may also be made available under the following10* Secondary Licenses when the conditions for such availability set11* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU12* General Public License, version 2 with the GNU Classpath13* Exception [1] and GNU General Public License, version 2 with the14* OpenJDK Assembly Exception [2].15*16* [1] https://www.gnu.org/software/classpath/license.html17* [2] http://openjdk.java.net/legal/assembly-exception.html18*19* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception20*******************************************************************************/2122#include "j9.h"2324#include "codegen/ARM64Instruction.hpp"25#include "codegen/CodeGenerator.hpp"26#include "codegen/GCStackAtlas.hpp"27#include "codegen/J9ARM64Snippet.hpp"28#include "codegen/Relocation.hpp"29#include "codegen/SnippetGCMap.hpp"30#include "runtime/CodeCacheManager.hpp"3132TR::ARM64MonitorEnterSnippet::ARM64MonitorEnterSnippet(33TR::CodeGenerator *codeGen,34TR::Node *monitorNode,35TR::LabelSymbol *incLabel,36TR::LabelSymbol *callLabel,37TR::LabelSymbol *restartLabel)38: _incLabel(incLabel),39TR::ARM64HelperCallSnippet(codeGen, monitorNode, callLabel, monitorNode->getSymbolReference(), restartLabel)40{41// Helper call, preserves all registers42incLabel->setSnippet(this);43gcMap().setGCRegisterMask(0xFFFFFFFF);44}4546uint8_t *47TR::ARM64MonitorEnterSnippet::emitSnippetBody()48{49// The AArch64 code for the snippet looks like:50//51// incLabel:52// and tempReg, dataReg, ~(OBJECT_HEADER_LOCK_BITS_MASK - OBJECT_HEADER_LOCK_LAST_RECURSION_BIT)53// cmp metaReg, tempReg54// bne callLabel55// add dataReg, dataReg, LOCK_INC_DEC_VALUE56// str dataReg, [addrReg]57// b restartLabel58// callLabel:59// bl jitMonitorEntry60// b restartLabel6162TR::RegisterDependencyConditions *deps = getRestartLabel()->getInstruction()->getDependencyConditions();6364TR::RealRegister *metaReg = cg()->getMethodMetaDataRegister();65TR::RealRegister *dataReg = cg()->machine()->getRealRegister(deps->getPostConditions()->getRegisterDependency(1)->getRealRegister());66TR::RealRegister *addrReg = cg()->machine()->getRealRegister(deps->getPostConditions()->getRegisterDependency(2)->getRealRegister());67TR::RealRegister *tempReg = cg()->machine()->getRealRegister(deps->getPostConditions()->getRegisterDependency(3)->getRealRegister());68TR::RealRegister *zeroReg = cg()->machine()->getRealRegister(TR::RealRegister::xzr);6970TR_J9VMBase *fej9 = (TR_J9VMBase *)(cg()->fe());71TR::InstOpCode::Mnemonic op;7273uint8_t *buffer = cg()->getBinaryBufferCursor();7475_incLabel->setCodeLocation(buffer);7677*(int32_t *)buffer = TR::InstOpCode::getOpCodeBinaryEncoding(TR::InstOpCode::andimmx);78tempReg->setRegisterFieldRD((uint32_t *)buffer);79dataReg->setRegisterFieldRN((uint32_t *)buffer);80// OBJECT_HEADER_LOCK_BITS_MASK is 0xFF81// OBJECT_HEADER_LOCK_RECURSION_BIT is 0x8082// (OBJECT_HEADER_LOCK_BITS_MASK - OBJECT_HEADER_LOCK_LAST_RECURSION_BIT) is 0x7F83*(int32_t *)buffer |= 0x79E000; // immr=57, imms=56 for 0xFFFFFFFFFFFFFF8084buffer += ARM64_INSTRUCTION_LENGTH;8586*(int32_t *)buffer = TR::InstOpCode::getOpCodeBinaryEncoding(TR::InstOpCode::subsx); // for cmp87metaReg->setRegisterFieldRN((uint32_t *)buffer);88tempReg->setRegisterFieldRM((uint32_t *)buffer);89zeroReg->setRegisterFieldRD((uint32_t *)buffer);90buffer += ARM64_INSTRUCTION_LENGTH;9192*(int32_t *)buffer = TR::InstOpCode::getOpCodeBinaryEncoding(TR::InstOpCode::b_cond);93*(int32_t *)buffer |= ((4 << 5) | TR::CC_NE); // 4 instructions forward, bne94buffer += ARM64_INSTRUCTION_LENGTH;9596*(int32_t *)buffer = TR::InstOpCode::getOpCodeBinaryEncoding(TR::InstOpCode::addimmx);97dataReg->setRegisterFieldRD((uint32_t *)buffer);98dataReg->setRegisterFieldRN((uint32_t *)buffer);99*(int32_t *)buffer |= ((LOCK_INC_DEC_VALUE & 0xFFF) << 10); // imm12100buffer += ARM64_INSTRUCTION_LENGTH;101102op = fej9->generateCompressedLockWord() ? TR::InstOpCode::strimmw : TR::InstOpCode::strimmx;103*(int32_t *)buffer = TR::InstOpCode::getOpCodeBinaryEncoding(op);104dataReg->setRegisterFieldRT((uint32_t *)buffer);105addrReg->setRegisterFieldRN((uint32_t *)buffer);106// offset 0 -- no need to encode107buffer += ARM64_INSTRUCTION_LENGTH;108109*(int32_t *)buffer = TR::InstOpCode::getOpCodeBinaryEncoding(TR::InstOpCode::b);110intptr_t destination = (intptr_t)getRestartLabel()->getCodeLocation();111TR_ASSERT(!cg()->directCallRequiresTrampoline(destination, (intptr_t)buffer), "Jump target too far away.");112intptr_t distance = (intptr_t)destination - (intptr_t)buffer;113*(int32_t *)buffer |= ((distance >> 2) & 0x3FFFFFF); // imm26114buffer += ARM64_INSTRUCTION_LENGTH;115116cg()->setBinaryBufferCursor(buffer);117buffer = TR::ARM64HelperCallSnippet::emitSnippetBody(); // x0 holds the object118119return buffer;120}121122void123TR::ARM64MonitorEnterSnippet::print(TR::FILE *pOutFile, TR_Debug *debug)124{125uint8_t *cursor = getIncLabel()->getCodeLocation();126127debug->printSnippetLabel(pOutFile, getIncLabel(), cursor, "Inc Monitor Counter");128}129130uint32_t TR::ARM64MonitorEnterSnippet::getLength(int32_t estimatedSnippetStart)131{132int32_t len = 6 * ARM64_INSTRUCTION_LENGTH;133return len + TR::ARM64HelperCallSnippet::getLength(estimatedSnippetStart+len);134}135136int32_t TR::ARM64MonitorEnterSnippet::setEstimatedCodeLocation(int32_t estimatedSnippetStart)137{138_incLabel->setEstimatedCodeLocation(estimatedSnippetStart);139getSnippetLabel()->setEstimatedCodeLocation(estimatedSnippetStart + 6 * ARM64_INSTRUCTION_LENGTH);140return estimatedSnippetStart;141}142143144TR::ARM64MonitorExitSnippet::ARM64MonitorExitSnippet(145TR::CodeGenerator *codeGen,146TR::Node *monitorNode,147TR::LabelSymbol *decLabel,148TR::LabelSymbol *callLabel,149TR::LabelSymbol *restartLabel)150: _decLabel(decLabel),151TR::ARM64HelperCallSnippet(codeGen, monitorNode, callLabel, monitorNode->getSymbolReference(), restartLabel)152{153// Helper call, preserves all registers154decLabel->setSnippet(this);155gcMap().setGCRegisterMask(0xFFFFFFFF);156}157158uint8_t *159TR::ARM64MonitorExitSnippet::emitSnippetBody()160{161// The AArch64 code for the snippet looks like:162//163// decLabel:164// and tempReg, dataReg, ~OBJECT_HEADER_LOCK_RECURSION_MASK165// cmp metaReg, tempReg166// bne callLabel167// sub dataReg, dataReg, LOCK_INC_DEC_VALUE168// str dataReg, [addrReg]169// b restartLabel170// callLabel:171// bl jitMonitorExit172// b restartLabel173174TR::RegisterDependencyConditions *deps = getRestartLabel()->getInstruction()->getDependencyConditions();175176TR::RealRegister *metaReg = cg()->getMethodMetaDataRegister();177TR::RealRegister *dataReg = cg()->machine()->getRealRegister(deps->getPostConditions()->getRegisterDependency(1)->getRealRegister());178TR::RealRegister *addrReg = cg()->machine()->getRealRegister(deps->getPostConditions()->getRegisterDependency(2)->getRealRegister());179TR::RealRegister *tempReg = cg()->machine()->getRealRegister(deps->getPostConditions()->getRegisterDependency(3)->getRealRegister());180TR::RealRegister *zeroReg = cg()->machine()->getRealRegister(TR::RealRegister::xzr);181182TR_J9VMBase *fej9 = (TR_J9VMBase *)(cg()->fe());183TR::InstOpCode::Mnemonic op;184185uint8_t *buffer = cg()->getBinaryBufferCursor();186187_decLabel->setCodeLocation(buffer);188189*(int32_t *)buffer = TR::InstOpCode::getOpCodeBinaryEncoding(TR::InstOpCode::andimmx);190tempReg->setRegisterFieldRD((uint32_t *)buffer);191dataReg->setRegisterFieldRN((uint32_t *)buffer);192// OBJECT_HEADER_LOCK_RECURSION_MASK is 0xF8193*(int32_t *)buffer |= 0x78E800; // immr=56, imms=58 for 0xFFFFFFFFFFFFFF07194buffer += ARM64_INSTRUCTION_LENGTH;195196*(int32_t *)buffer = TR::InstOpCode::getOpCodeBinaryEncoding(TR::InstOpCode::subsx); // for cmp197metaReg->setRegisterFieldRN((uint32_t *)buffer);198tempReg->setRegisterFieldRM((uint32_t *)buffer);199zeroReg->setRegisterFieldRD((uint32_t *)buffer);200buffer += ARM64_INSTRUCTION_LENGTH;201202*(int32_t *)buffer = TR::InstOpCode::getOpCodeBinaryEncoding(TR::InstOpCode::b_cond);203*(int32_t *)buffer |= ((4 << 5) | TR::CC_NE); // 4 instructions forward, bne204buffer += ARM64_INSTRUCTION_LENGTH;205206*(int32_t *)buffer = TR::InstOpCode::getOpCodeBinaryEncoding(TR::InstOpCode::subimmx);207dataReg->setRegisterFieldRD((uint32_t *)buffer);208dataReg->setRegisterFieldRN((uint32_t *)buffer);209*(int32_t *)buffer |= ((LOCK_INC_DEC_VALUE & 0xFFF) << 10); // imm12210buffer += ARM64_INSTRUCTION_LENGTH;211212op = fej9->generateCompressedLockWord() ? TR::InstOpCode::strimmw : TR::InstOpCode::strimmx;213*(int32_t *)buffer = TR::InstOpCode::getOpCodeBinaryEncoding(op);214dataReg->setRegisterFieldRT((uint32_t *)buffer);215addrReg->setRegisterFieldRN((uint32_t *)buffer);216// offset 0 -- no need to encode217buffer += ARM64_INSTRUCTION_LENGTH;218219*(int32_t *)buffer = TR::InstOpCode::getOpCodeBinaryEncoding(TR::InstOpCode::b);220intptr_t destination = (intptr_t)getRestartLabel()->getCodeLocation();221TR_ASSERT(!cg()->directCallRequiresTrampoline(destination, (intptr_t)buffer), "Jump target too far away.");222intptr_t distance = (intptr_t)destination - (intptr_t)buffer;223*(int32_t *)buffer |= ((distance >> 2) & 0x3FFFFFF); // imm26224buffer += ARM64_INSTRUCTION_LENGTH;225226cg()->setBinaryBufferCursor(buffer);227buffer = TR::ARM64HelperCallSnippet::emitSnippetBody(); // x0 holds the object228229return buffer;230}231232void233TR::ARM64MonitorExitSnippet::print(TR::FILE *pOutFile, TR_Debug *debug)234{235uint8_t *cursor = getDecLabel()->getCodeLocation();236debug->printSnippetLabel(pOutFile, getDecLabel(), cursor, "Dec Monitor Counter");237}238239uint32_t240TR::ARM64MonitorExitSnippet::getLength(int32_t estimatedSnippetStart)241{242int32_t len = 6 * ARM64_INSTRUCTION_LENGTH;243return len + TR::ARM64HelperCallSnippet::getLength(estimatedSnippetStart+len);244}245246int32_t TR::ARM64MonitorExitSnippet::setEstimatedCodeLocation(int32_t estimatedSnippetStart)247{248_decLabel->setEstimatedCodeLocation(estimatedSnippetStart);249getSnippetLabel()->setEstimatedCodeLocation(estimatedSnippetStart + 6 * ARM64_INSTRUCTION_LENGTH);250return estimatedSnippetStart;251}252253254