Path: blob/master/runtime/compiler/p/codegen/J9UnresolvedDataSnippet.cpp
6004 views
/*******************************************************************************1* Copyright (c) 2000, 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 "codegen/UnresolvedDataSnippet.hpp"23#include "codegen/UnresolvedDataSnippet_inlines.hpp"2425#include <stddef.h>26#include <stdint.h>27#include "codegen/CodeGenerator.hpp"28#include "env/FrontEnd.hpp"29#include "codegen/Instruction.hpp"30#include "codegen/Machine.hpp"31#include "codegen/MemoryReference.hpp"32#include "codegen/RealRegister.hpp"33#include "codegen/Relocation.hpp"34#include "compile/Compilation.hpp"35#include "compile/ResolvedMethod.hpp"36#include "compile/SymbolReferenceTable.hpp"37#include "control/Options.hpp"38#include "control/Options_inlines.hpp"39#include "env/IO.hpp"40#include "env/ObjectModel.hpp"41#include "env/TRMemory.hpp"42#include "env/jittypes.h"43#include "env/VMJ9.h"44#include "il/DataTypes.hpp"45#include "il/LabelSymbol.hpp"46#include "il/Node.hpp"47#include "il/StaticSymbol.hpp"48#include "il/StaticSymbol_inlines.hpp"49#include "il/Symbol.hpp"50#include "il/SymbolReference.hpp"51#include "infra/Assert.hpp"52#include "p/codegen/PPCTableOfConstants.hpp"53#include "ras/Debug.hpp"54#include "runtime/CodeCacheManager.hpp"55#include "runtime/J9Runtime.hpp"56#include "env/CompilerEnv.hpp"5758J9::Power::UnresolvedDataSnippet::UnresolvedDataSnippet(59TR::CodeGenerator *cg,60TR::Node *node,61TR::SymbolReference *symRef,62bool isStore,63bool canCauseGC) :64J9::UnresolvedDataSnippet(cg, node, symRef, isStore, canCauseGC),65_memoryReference(NULL), _dataRegister(NULL)66{67}6869uint8_t *J9::Power::UnresolvedDataSnippet::getAddressOfDataReference()70{71if (self()->getDataReferenceInstruction())72return self()->getDataReferenceInstruction()->getBinaryEncoding();73else74return self()->OMR::UnresolvedDataSnippet::getAddressOfDataReference();75}7677uint8_t *J9::Power::UnresolvedDataSnippet::emitSnippetBody()78{79uint8_t *cursor = cg()->getBinaryBufferCursor();80TR::Compilation *comp = cg()->comp();81TR_J9VMBase *fej9 = (TR_J9VMBase *)(comp->fe());82TR::SymbolReference *glueRef;83TR_RuntimeHelper refNum;8485if (getDataSymbol()->getShadowSymbol() != NULL) // instance data86{87if (isUnresolvedStore())88refNum = TR_PPCinterpreterUnresolvedInstanceDataStoreGlue;89else90refNum = TR_PPCinterpreterUnresolvedInstanceDataGlue;91}92else if (getDataSymbol()->isClassObject())93{94if (getDataSymbol()->addressIsCPIndexOfStatic())95refNum = TR_PPCinterpreterUnresolvedClassGlue2;96else97refNum = TR_PPCinterpreterUnresolvedClassGlue;98}99else if (getDataSymbol()->isConstString())100{101refNum = TR_PPCinterpreterUnresolvedStringGlue;102}103else if (getDataSymbol()->isConstMethodType())104{105refNum = TR_interpreterUnresolvedMethodTypeGlue;106}107else if (getDataSymbol()->isConstMethodHandle())108{109refNum = TR_interpreterUnresolvedMethodHandleGlue;110}111else if (getDataSymbol()->isCallSiteTableEntry())112{113refNum = TR_interpreterUnresolvedCallSiteTableEntryGlue;114}115else if (getDataSymbol()->isMethodTypeTableEntry())116{117refNum = TR_interpreterUnresolvedMethodTypeTableEntryGlue;118}119else if (getDataSymbol()->isConstantDynamic())120{121refNum = TR_PPCinterpreterUnresolvedConstantDynamicGlue;122}123else // must be static data124{125if (isUnresolvedStore())126refNum = TR_PPCinterpreterUnresolvedStaticDataStoreGlue;127else128refNum = TR_PPCinterpreterUnresolvedStaticDataGlue;129}130131glueRef = cg()->symRefTab()->findOrCreateRuntimeHelper(refNum);132getSnippetLabel()->setCodeLocation(cursor);133134intptr_t helperAddress = (intptr_t)glueRef->getMethodAddress();135if (cg()->directCallRequiresTrampoline(helperAddress, (intptr_t)cursor))136{137helperAddress = TR::CodeCacheManager::instance()->findHelperTrampoline(glueRef->getReferenceNumber(), (void *)cursor);138TR_ASSERT_FATAL(comp->target().cpu.isTargetWithinIFormBranchRange(helperAddress, (intptr_t)cursor), "Helper address is out of range");139}140141// bl distance142*(int32_t *)cursor = 0x48000001 | ((helperAddress - (intptr_t)cursor) & 0x03fffffc);143cg()->addProjectSpecializedRelocation(cursor,(uint8_t *)glueRef, NULL, TR_HelperAddress,144__FILE__,145__LINE__,146getNode());147if (getDataSymbol()->isClassObject() && cg()->wantToPatchClassPointer(NULL, getAddressOfDataReference()))148{149uintptr_t dis = cursor - getAddressOfDataReference();150cg()->jitAddUnresolvedAddressMaterializationToPatchOnClassRedefinition((void *) getAddressOfDataReference());151}152cursor += 4;153154*(intptr_t *)cursor = (intptr_t)getAddressOfDataReference(); // Code Cache RA155cg()->addProjectSpecializedRelocation(cursor, NULL, NULL, TR_AbsoluteMethodAddress,156__FILE__, __LINE__, getNode());157cursor += TR::Compiler->om.sizeofReferenceAddress();158159if (getDataSymbolReference()->getSymbol()->isCallSiteTableEntry())160{161*(int32_t *)cursor = getDataSymbolReference()->getSymbol()->castToCallSiteTableEntrySymbol()->getCallSiteIndex();162}163else if (getDataSymbol()->isMethodTypeTableEntry())164{165*(int32_t *)cursor = getDataSymbolReference()->getSymbol()->castToMethodTypeTableEntrySymbol()->getMethodTypeIndex();166}167else // constant pool index168{169*(int32_t *)cursor = getDataSymbolReference()->getCPIndex();170}171172if (getMemoryReference()->isTOCAccess())173*(int32_t *)cursor |= 1<<31; // Set Pseudo TOC bit174if (isSpecialDouble())175*(int32_t *)cursor |= 1<<30; // Set Special Double bit176if (inSyncSequence())177*(int32_t *)cursor |= 1<<29; // Set Sync Pattern bit178if (getMemoryReference()->useIndexedForm())179*(int32_t *)cursor |= 1<<28; // Set the index bit180if (is32BitLong())181*(int32_t *)cursor |= 1<<27; // Set the double word load/store bit182cursor += 4;183184*(intptr_t *)cursor = (intptr_t)getDataSymbolReference()->getOwningMethod(comp)->constantPool();185cg()->addExternalRelocation(new (cg()->trHeapMemory()) TR::ExternalRelocation(cursor,*(uint8_t **)cursor,186getNode() ? (uint8_t *)getNode()->getInlinedSiteIndex() : (uint8_t *)-1,187TR_ConstantPool,188cg()),189__FILE__,190__LINE__,191getNode());192cursor += TR::Compiler->om.sizeofReferenceAddress();193194if (getMemoryReference()->isTOCAccess())195{196*(int32_t *)cursor = getMemoryReference()->getTOCOffset();197}198else199{200*(int32_t *)cursor = getMemoryReference()->getOffset(*(comp)); // offset201if (getDataSymbol()->isConstObjectRef() || getDataSymbol()->isConstantDynamic())202{203cg()->addProjectSpecializedRelocation(cursor, *(uint8_t **)(cursor-4),204getNode() ? (uint8_t *)getNode()->getInlinedSiteIndex() : (uint8_t *)-1, TR_ConstantPool,205__FILE__,206__LINE__,207getNode());208}209}210cursor += 4;211212if (getMemoryReference()->isTOCAccess())213{214if (getMemoryReference()->getTOCOffset() != PTOC_FULL_INDEX)215{216if (getMemoryReference()->getTOCOffset()<LOWER_IMMED ||217getMemoryReference()->getTOCOffset()>UPPER_IMMED)218{219*(int32_t *)cursor = 0x3c000000;220toRealRegister(getMemoryReference()->getModBase())->setRegisterFieldRT((uint32_t *)cursor);221}222else223{224*(int32_t *)cursor = comp->target().is64Bit()?0xe8000000:0x80000000;225getDataRegister()->setRegisterFieldRT((uint32_t *)cursor);226}227cg()->getTOCBaseRegister()->setRegisterFieldRA((uint32_t *)cursor);228}229else230{231*(int32_t *)cursor = 0x3c000000;232getDataRegister()->setRegisterFieldRT((uint32_t *)cursor);233}234}235else236{237*(int32_t *)cursor = 0x3c000000; // Template238toRealRegister(getMemoryReference()->getModBase())->setRegisterFieldRT((uint32_t *)cursor);239if (getMemoryReference()->getBaseRegister() == NULL)240{241cg()->machine()->getRealRegister(TR::RealRegister::gr0)->setRegisterFieldRA((uint32_t *)cursor);242}243else244{245toRealRegister(getMemoryReference()->getBaseRegister())->setRegisterFieldRA((uint32_t *)cursor);246}247}248cursor += 4;249250*(int32_t *)cursor = 0; // Lock word251252// CLInit case253cursor += 4;254*(int32_t *)cursor = 0xdeadbeef; // Patched with lis via runtime code255cursor += 4;256intptr_t targetAddress = (intptr_t)getAddressOfDataReference()+4;257TR_ASSERT_FATAL(comp->target().cpu.isTargetWithinIFormBranchRange(targetAddress, (intptr_t)cursor),258"Return address is out of range");259*(int32_t *)cursor = 0x48000000 | ((targetAddress - (intptr_t)cursor) & 0x03fffffc);260261return cursor+4;262}263264265void266TR_Debug::print(TR::FILE *pOutFile, TR::UnresolvedDataSnippet * snippet)267{268uint8_t *cursor = snippet->getSnippetLabel()->getCodeLocation();269270printSnippetLabel(pOutFile, snippet->getSnippetLabel(), cursor, "Unresolved Data Snippet");271272TR::SymbolReference *glueRef;273274if (snippet->getDataSymbol()->getShadowSymbol() != NULL) // instance data275{276if (snippet->isUnresolvedStore())277glueRef = _cg->getSymRef(TR_PPCinterpreterUnresolvedInstanceDataStoreGlue);278else279glueRef = _cg->getSymRef(TR_PPCinterpreterUnresolvedInstanceDataGlue);280}281else if (snippet->getDataSymbol()->isClassObject())282{283if (snippet->getDataSymbol()->addressIsCPIndexOfStatic())284glueRef = _cg->getSymRef(TR_PPCinterpreterUnresolvedClassGlue2);285else286glueRef = _cg->getSymRef(TR_PPCinterpreterUnresolvedClassGlue);287}288else if (snippet->getDataSymbol()->isConstString())289{290glueRef = _cg->getSymRef(TR_PPCinterpreterUnresolvedStringGlue);291}292else if (snippet->getDataSymbol()->isConstMethodType())293{294glueRef = _cg->getSymRef(TR_interpreterUnresolvedMethodTypeGlue);295}296else if (snippet->getDataSymbol()->isConstMethodHandle())297{298glueRef = _cg->getSymRef(TR_interpreterUnresolvedMethodHandleGlue);299}300else if (snippet->getDataSymbol()->isCallSiteTableEntry())301{302glueRef = _cg->getSymRef(TR_interpreterUnresolvedCallSiteTableEntryGlue);303}304else if (snippet->getDataSymbol()->isMethodTypeTableEntry())305{306glueRef = _cg->getSymRef(TR_interpreterUnresolvedMethodTypeTableEntryGlue);307}308else if (snippet->getDataSymbol()->isConstantDynamic())309{310glueRef = _cg->getSymRef(TR_PPCinterpreterUnresolvedConstantDynamicGlue);311}312else // must be static data313{314if (snippet->isUnresolvedStore())315glueRef = _cg->getSymRef(TR_PPCinterpreterUnresolvedStaticDataStoreGlue);316else317glueRef = _cg->getSymRef(TR_PPCinterpreterUnresolvedStaticDataGlue);318}319320char *info = "";321int32_t distance;322if (isBranchToTrampoline(glueRef, cursor, distance))323info = " Through Trampoline";324325printPrefix(pOutFile, NULL, cursor, 4);326distance = *((int32_t *) cursor) & 0x03fffffc;327distance = (distance << 6) >> 6; // sign extend328trfprintf(pOutFile, "bl \t" POINTER_PRINTF_FORMAT "\t\t;%s", (intptr_t)cursor + distance, info);329cursor += 4;330331printPrefix(pOutFile, NULL, cursor, sizeof(intptr_t));332trfprintf(pOutFile, ".long \t" POINTER_PRINTF_FORMAT "\t\t; Code cache return address", *(intptr_t *)cursor);333cursor += sizeof(intptr_t);334335printPrefix(pOutFile, NULL, cursor, 4);336trfprintf(pOutFile, ".long \t0x%08x\t\t; pTOC|VD|SY|IX|cpIndex of the data reference", *(int32_t *)cursor);337cursor += 4;338339printPrefix(pOutFile, NULL, cursor, sizeof(intptr_t));340trfprintf(pOutFile, ".long \t" POINTER_PRINTF_FORMAT "\t\t; Constant pool address", *(intptr_t *)cursor);341cursor += sizeof(intptr_t);342343printPrefix(pOutFile, NULL, cursor, 4);344trfprintf(pOutFile, ".long \t0x%08x\t\t; Offset to be merged", *(int32_t *)cursor);345cursor += 4;346347printPrefix(pOutFile, NULL, cursor, 4);348trfprintf(pOutFile, ".long \t0x%08x\t\t; Instruction template", *(int32_t *)cursor);349cursor += 4;350351printPrefix(pOutFile, NULL, cursor, 4);352trfprintf(pOutFile, ".long \t0x%08x\t\t; Lock word initialized to 0", *(int32_t *)cursor);353cursor += 4;354355printPrefix(pOutFile, NULL, cursor, 4);356trfprintf(pOutFile, ".long \t0x%08x\t\t; <clinit> case - 1st instruction (0xdeadbeef)", *(int32_t *)cursor);357cursor += 4;358359printPrefix(pOutFile, NULL, cursor, 4);360distance = *((int32_t *) cursor) & 0x03fffffc;361distance = (distance << 6) >> 6; // sign extend362trfprintf(pOutFile, "b \t" POINTER_PRINTF_FORMAT "\t\t; <clinit> case - Branch back to main line code", (intptr_t)cursor + distance);363}364365uint32_t J9::Power::UnresolvedDataSnippet::getLength(int32_t estimatedSnippetStart)366{367return 28+2*TR::Compiler->om.sizeofReferenceAddress();368}369370371