Path: blob/master/runtime/compiler/codegen/J9WatchedStaticFieldSnippet.cpp
6000 views
/*******************************************************************************1* Copyright (c) 2019, 2021 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 "codegen/J9WatchedStaticFieldSnippet.hpp"23#include "codegen/Relocation.hpp"24#include "il/SymbolReference.hpp"2526TR::J9WatchedStaticFieldSnippet::J9WatchedStaticFieldSnippet(TR::CodeGenerator *cg, TR::Node *node, J9Method *m, UDATA loc, void *fieldAddress, J9Class *fieldClass)27: TR::Snippet(cg, node, generateLabelSymbol(cg), false)28{29staticFieldData.method = m;30staticFieldData.location = loc;31staticFieldData.fieldAddress = fieldAddress;32staticFieldData.fieldClass = fieldClass;33}3435uint8_t *TR::J9WatchedStaticFieldSnippet::emitSnippetBody()36{37uint8_t *cursor = cg()->getBinaryBufferCursor();38getSnippetLabel()->setCodeLocation(cursor);39TR::Node *node = getNode();4041// We emit the dataSnippet based on the assumption that the J9JITWatchedStaticFieldData structure is laid out as below:42/*43typedef struct J9JITWatchedStaticFieldData {44J9Method *method; // Currently executing method45UDATA location; // Bytecode PC index46void *fieldAddress; // Address of static field storage47J9Class *fieldClass; // Declaring class of static field48} J9JITWatchedStaticFieldData;49*/5051// Emit each field and add a relocation record (for AOT compiles) for any field if needed.52J9JITWatchedStaticFieldData *str = reinterpret_cast<J9JITWatchedStaticFieldData *>(cursor);53str->method = staticFieldData.method;54str->location = staticFieldData.location;55str->fieldAddress = staticFieldData.fieldAddress;56str->fieldClass = staticFieldData.fieldClass;5758if (cg()->comp()->getOption(TR_UseSymbolValidationManager))59{60cg()->addExternalRelocation(61new (cg()->trHeapMemory()) TR::ExternalRelocation(cursor + offsetof(J9JITWatchedStaticFieldData, method), reinterpret_cast<uint8_t *>(staticFieldData.method), reinterpret_cast<uint8_t *>(TR::SymbolType::typeMethod), TR_SymbolFromManager, cg()),62__FILE__,63__LINE__,64node);65}66else if (cg()->needClassAndMethodPointerRelocations())67{68cg()->addExternalRelocation(new (cg()->trHeapMemory()) TR::ExternalRelocation(cursor + offsetof(J9JITWatchedStaticFieldData, method), NULL, TR_RamMethod, cg()), __FILE__, __LINE__, node);69}7071bool isResolved = !node->getSymbolReference()->isUnresolved();72// If the field is unresolved then we populate these snippet fields with the correct value at runtime (via the instructions generated by generateFillInDataBlockSequenceForUnresolvedField)73// and hence don't need to add relocation records here.74if (isResolved)75{76if (cg()->needRelocationsForStatics())77{78cg()->addExternalRelocation(79new (cg()->trHeapMemory()) TR::ExternalRelocation(cursor + offsetof(J9JITWatchedStaticFieldData, fieldAddress), reinterpret_cast<uint8_t *>(node->getSymbolReference()), reinterpret_cast<uint8_t *>(node->getInlinedSiteIndex()), TR_DataAddress, cg()),80__FILE__,81__LINE__,82node);83}8485if (cg()->comp()->getOption(TR_UseSymbolValidationManager))86{87cg()->addExternalRelocation(88new (cg()->trHeapMemory()) TR::ExternalRelocation(cursor + offsetof(J9JITWatchedStaticFieldData, fieldClass), reinterpret_cast<uint8_t *>(staticFieldData.fieldClass), reinterpret_cast<uint8_t *>(TR::SymbolType::typeClass), TR_SymbolFromManager, cg()),89__FILE__,90__LINE__,91node);92}93// relocations for TR_ClassAddress are needed for AOT/AOTaaS compiles and not needed for regular JIT and JITServer compiles.94// cg->needClassAndMethodPointerRelocations() tells us whether a relocation is needed depending on the type of compile being performed.95else if (cg()->needClassAndMethodPointerRelocations())96{97// As things currently stand, this will not work on Power because TR_ClassAddress is used to a generate a 5 instruction sequence that materializes the address into a register. Meanwhile we are using TR_ClassAddress here to represent a contiguous word.98// A short-term solution would be to use TR_ClassPointer. However this is hacky because TR_ClassPointer expects an aconst node (so we would have to create a dummy node). The proper solution would be to implement the functionality in the power99// codegenerator to be able to patch TR_ClassAddress contiguous word.100cg()->addExternalRelocation(101new (cg()->trHeapMemory()) TR::ExternalRelocation(cursor + offsetof(J9JITWatchedStaticFieldData, fieldClass), reinterpret_cast<uint8_t *>(node->getSymbolReference()), reinterpret_cast<uint8_t *>(node->getInlinedSiteIndex()), TR_ClassAddress, cg()),102__FILE__,103__LINE__,104node);105}106}107108cursor += sizeof(J9JITWatchedStaticFieldData);109110return cursor;111}112113void TR::J9WatchedStaticFieldSnippet::print(TR::FILE *pOutFile, TR_Debug *debug)114{115uint8_t *bufferPos = getSnippetLabel()->getCodeLocation();116117debug->printSnippetLabel(pOutFile, getSnippetLabel(), bufferPos, "J9WatchedStaticFieldSnippet");118119debug->printPrefix(pOutFile, NULL, bufferPos, sizeof(J9Method *));120trfprintf(pOutFile, "DC \t%p \t\t# J9Method", *(reinterpret_cast<J9Method **>(bufferPos)));121bufferPos += sizeof(J9Method *);122123debug->printPrefix(pOutFile, NULL, bufferPos, sizeof(UDATA));124trfprintf(pOutFile, "DC \t%lu \t\t# location", *(reinterpret_cast<UDATA *>(bufferPos)));125bufferPos += sizeof(UDATA);126127debug->printPrefix(pOutFile, NULL, bufferPos, sizeof(void *));128trfprintf(pOutFile, "DC \t%p \t\t# fieldAddress", *(reinterpret_cast<void **>(bufferPos)));129bufferPos += sizeof(void *);130131debug->printPrefix(pOutFile, NULL, bufferPos, sizeof(J9Class *));132trfprintf(pOutFile, "DC \t%p \t\t# fieldClass", *(reinterpret_cast<J9Class **>(bufferPos)));133bufferPos += sizeof(J9Class *);134}135136137138