Path: blob/master/runtime/compiler/codegen/J9TreeEvaluator.cpp
6000 views
/*******************************************************************************1* Copyright (c) 2000, 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/TreeEvaluator.hpp"23#include "codegen/CodeGenerator.hpp"24#include "codegen/J9WatchedInstanceFieldSnippet.hpp"25#include "codegen/J9WatchedStaticFieldSnippet.hpp"26#include "env/CompilerEnv.hpp"27#include "env/IO.hpp"28#include "env/PersistentCHTable.hpp"29#include "env/VMJ9.h"30#include "il/Node.hpp"31#include "il/Node_inlines.hpp"32#include "il/StaticSymbol.hpp"33#include "runtime/RuntimeAssumptions.hpp"34#include "runtime/J9Profiler.hpp"35#include "runtime/J9ValueProfiler.hpp"36#include "util_api.h"3738TR::Register*39J9::TreeEvaluator::zdloadEvaluator(TR::Node *node, TR::CodeGenerator *cg)40{41return TR::TreeEvaluator::unImpOpEvaluator(node, cg);42}4344TR::Register*45J9::TreeEvaluator::zdloadiEvaluator(TR::Node *node, TR::CodeGenerator *cg)46{47return TR::TreeEvaluator::unImpOpEvaluator(node, cg);48}4950TR::Register*51J9::TreeEvaluator::zdstoreEvaluator(TR::Node *node, TR::CodeGenerator *cg)52{53return TR::TreeEvaluator::unImpOpEvaluator(node, cg);54}5556TR::Register*57J9::TreeEvaluator::zdstoreiEvaluator(TR::Node *node, TR::CodeGenerator *cg)58{59return TR::TreeEvaluator::unImpOpEvaluator(node, cg);60}6162TR::Register*63J9::TreeEvaluator::pd2zdEvaluator(TR::Node *node, TR::CodeGenerator *cg)64{65return TR::TreeEvaluator::unImpOpEvaluator(node, cg);66}6768TR::Register*69J9::TreeEvaluator::zd2pdEvaluator(TR::Node *node, TR::CodeGenerator *cg)70{71return TR::TreeEvaluator::unImpOpEvaluator(node, cg);72}7374TR::Register*75J9::TreeEvaluator::zdsleLoadEvaluator(TR::Node *node, TR::CodeGenerator *cg)76{77return TR::TreeEvaluator::unImpOpEvaluator(node, cg);78}7980TR::Register*81J9::TreeEvaluator::zdslsLoadEvaluator(TR::Node *node, TR::CodeGenerator *cg)82{83return TR::TreeEvaluator::unImpOpEvaluator(node, cg);84}8586TR::Register*87J9::TreeEvaluator::zdstsLoadEvaluator(TR::Node *node, TR::CodeGenerator *cg)88{89return TR::TreeEvaluator::unImpOpEvaluator(node, cg);90}9192TR::Register*93J9::TreeEvaluator::zdsleLoadiEvaluator(TR::Node *node, TR::CodeGenerator *cg)94{95return TR::TreeEvaluator::unImpOpEvaluator(node, cg);96}9798TR::Register*99J9::TreeEvaluator::zdslsLoadiEvaluator(TR::Node *node, TR::CodeGenerator *cg)100{101return TR::TreeEvaluator::unImpOpEvaluator(node, cg);102}103104TR::Register*105J9::TreeEvaluator::zdstsLoadiEvaluator(TR::Node *node, TR::CodeGenerator *cg)106{107return TR::TreeEvaluator::unImpOpEvaluator(node, cg);108}109110TR::Register*111J9::TreeEvaluator::zdsleStoreEvaluator(TR::Node *node, TR::CodeGenerator *cg)112{113return TR::TreeEvaluator::unImpOpEvaluator(node, cg);114}115116TR::Register*117J9::TreeEvaluator::zdslsStoreEvaluator(TR::Node *node, TR::CodeGenerator *cg)118{119return TR::TreeEvaluator::unImpOpEvaluator(node, cg);120}121122TR::Register*123J9::TreeEvaluator::zdstsStoreEvaluator(TR::Node *node, TR::CodeGenerator *cg)124{125return TR::TreeEvaluator::unImpOpEvaluator(node, cg);126}127128TR::Register*129J9::TreeEvaluator::zdsleStoreiEvaluator(TR::Node *node, TR::CodeGenerator *cg)130{131return TR::TreeEvaluator::unImpOpEvaluator(node, cg);132}133134TR::Register*135J9::TreeEvaluator::zdslsStoreiEvaluator(TR::Node *node, TR::CodeGenerator *cg)136{137return TR::TreeEvaluator::unImpOpEvaluator(node, cg);138}139140TR::Register*141J9::TreeEvaluator::zdstsStoreiEvaluator(TR::Node *node, TR::CodeGenerator *cg)142{143return TR::TreeEvaluator::unImpOpEvaluator(node, cg);144}145146TR::Register*147J9::TreeEvaluator::zd2zdsleEvaluator(TR::Node *node, TR::CodeGenerator *cg)148{149return TR::TreeEvaluator::unImpOpEvaluator(node, cg);150}151152TR::Register*153J9::TreeEvaluator::zd2zdslsEvaluator(TR::Node *node, TR::CodeGenerator *cg)154{155return TR::TreeEvaluator::unImpOpEvaluator(node, cg);156}157158TR::Register*159J9::TreeEvaluator::zd2zdstsEvaluator(TR::Node *node, TR::CodeGenerator *cg)160{161return TR::TreeEvaluator::unImpOpEvaluator(node, cg);162}163164TR::Register*165J9::TreeEvaluator::zdsle2pdEvaluator(TR::Node *node, TR::CodeGenerator *cg)166{167return TR::TreeEvaluator::unImpOpEvaluator(node, cg);168}169170TR::Register*171J9::TreeEvaluator::zdsls2pdEvaluator(TR::Node *node, TR::CodeGenerator *cg)172{173return TR::TreeEvaluator::unImpOpEvaluator(node, cg);174}175176TR::Register*177J9::TreeEvaluator::zdsts2pdEvaluator(TR::Node *node, TR::CodeGenerator *cg)178{179return TR::TreeEvaluator::unImpOpEvaluator(node, cg);180}181182TR::Register*183J9::TreeEvaluator::zdsle2zdEvaluator(TR::Node *node, TR::CodeGenerator *cg)184{185return TR::TreeEvaluator::unImpOpEvaluator(node, cg);186}187188TR::Register*189J9::TreeEvaluator::zdsls2zdEvaluator(TR::Node *node, TR::CodeGenerator *cg)190{191return TR::TreeEvaluator::unImpOpEvaluator(node, cg);192}193194TR::Register*195J9::TreeEvaluator::zdsts2zdEvaluator(TR::Node *node, TR::CodeGenerator *cg)196{197return TR::TreeEvaluator::unImpOpEvaluator(node, cg);198}199200TR::Register*201J9::TreeEvaluator::pd2zdslsEvaluator(TR::Node *node, TR::CodeGenerator *cg)202{203return TR::TreeEvaluator::unImpOpEvaluator(node, cg);204}205206TR::Register*207J9::TreeEvaluator::pd2zdslsSetSignEvaluator(TR::Node *node, TR::CodeGenerator *cg)208{209return TR::TreeEvaluator::unImpOpEvaluator(node, cg);210}211212TR::Register*213J9::TreeEvaluator::pd2zdstsEvaluator(TR::Node *node, TR::CodeGenerator *cg)214{215return TR::TreeEvaluator::unImpOpEvaluator(node, cg);216}217218TR::Register*219J9::TreeEvaluator::pd2zdstsSetSignEvaluator(TR::Node *node, TR::CodeGenerator *cg)220{221return TR::TreeEvaluator::unImpOpEvaluator(node, cg);222}223224TR::Register*225J9::TreeEvaluator::udLoadEvaluator(TR::Node *node, TR::CodeGenerator *cg)226{227return TR::TreeEvaluator::unImpOpEvaluator(node, cg);228}229230TR::Register*231J9::TreeEvaluator::udslLoadEvaluator(TR::Node *node, TR::CodeGenerator *cg)232{233return TR::TreeEvaluator::unImpOpEvaluator(node, cg);234}235236TR::Register*237J9::TreeEvaluator::udstLoadEvaluator(TR::Node *node, TR::CodeGenerator *cg)238{239return TR::TreeEvaluator::unImpOpEvaluator(node, cg);240}241242TR::Register*243J9::TreeEvaluator::udLoadiEvaluator(TR::Node *node, TR::CodeGenerator *cg)244{245return TR::TreeEvaluator::unImpOpEvaluator(node, cg);246}247248TR::Register*249J9::TreeEvaluator::udslLoadiEvaluator(TR::Node *node, TR::CodeGenerator *cg)250{251return TR::TreeEvaluator::unImpOpEvaluator(node, cg);252}253254TR::Register*255J9::TreeEvaluator::udstLoadiEvaluator(TR::Node *node, TR::CodeGenerator *cg)256{257return TR::TreeEvaluator::unImpOpEvaluator(node, cg);258}259260TR::Register*261J9::TreeEvaluator::udStoreEvaluator(TR::Node *node, TR::CodeGenerator *cg)262{263return TR::TreeEvaluator::unImpOpEvaluator(node, cg);264}265266TR::Register*267J9::TreeEvaluator::udslStoreEvaluator(TR::Node *node, TR::CodeGenerator *cg)268{269return TR::TreeEvaluator::unImpOpEvaluator(node, cg);270}271272TR::Register*273J9::TreeEvaluator::udstStoreEvaluator(TR::Node *node, TR::CodeGenerator *cg)274{275return TR::TreeEvaluator::unImpOpEvaluator(node, cg);276}277278TR::Register*279J9::TreeEvaluator::udStoreiEvaluator(TR::Node *node, TR::CodeGenerator *cg)280{281return TR::TreeEvaluator::unImpOpEvaluator(node, cg);282}283284TR::Register*285J9::TreeEvaluator::udslStoreiEvaluator(TR::Node *node, TR::CodeGenerator *cg)286{287return TR::TreeEvaluator::unImpOpEvaluator(node, cg);288}289290TR::Register*291J9::TreeEvaluator::udstStoreiEvaluator(TR::Node *node, TR::CodeGenerator *cg)292{293return TR::TreeEvaluator::unImpOpEvaluator(node, cg);294}295296TR::Register*297J9::TreeEvaluator::pd2udEvaluator(TR::Node *node, TR::CodeGenerator *cg)298{299return TR::TreeEvaluator::unImpOpEvaluator(node, cg);300}301302TR::Register*303J9::TreeEvaluator::pd2udslEvaluator(TR::Node *node, TR::CodeGenerator *cg)304{305return TR::TreeEvaluator::unImpOpEvaluator(node, cg);306}307308TR::Register*309J9::TreeEvaluator::pd2udstEvaluator(TR::Node *node, TR::CodeGenerator *cg)310{311return TR::TreeEvaluator::unImpOpEvaluator(node, cg);312}313314TR::Register*315J9::TreeEvaluator::udsl2udEvaluator(TR::Node *node, TR::CodeGenerator *cg)316{317return TR::TreeEvaluator::unImpOpEvaluator(node, cg);318}319320TR::Register*321J9::TreeEvaluator::udst2udEvaluator(TR::Node *node, TR::CodeGenerator *cg)322{323return TR::TreeEvaluator::unImpOpEvaluator(node, cg);324}325326TR::Register*327J9::TreeEvaluator::ud2pdEvaluator(TR::Node *node, TR::CodeGenerator *cg)328{329return TR::TreeEvaluator::unImpOpEvaluator(node, cg);330}331332TR::Register*333J9::TreeEvaluator::udsl2pdEvaluator(TR::Node *node, TR::CodeGenerator *cg)334{335return TR::TreeEvaluator::unImpOpEvaluator(node, cg);336}337338TR::Register*339J9::TreeEvaluator::udst2pdEvaluator(TR::Node *node, TR::CodeGenerator *cg)340{341return TR::TreeEvaluator::unImpOpEvaluator(node, cg);342}343344TR::Register*345J9::TreeEvaluator::pdloadEvaluator(TR::Node *node, TR::CodeGenerator *cg)346{347return TR::TreeEvaluator::unImpOpEvaluator(node, cg);348}349350TR::Register*351J9::TreeEvaluator::pdloadiEvaluator(TR::Node *node, TR::CodeGenerator *cg)352{353return TR::TreeEvaluator::unImpOpEvaluator(node, cg);354}355356TR::Register*357J9::TreeEvaluator::pdstoreEvaluator(TR::Node *node, TR::CodeGenerator *cg)358{359return TR::TreeEvaluator::unImpOpEvaluator(node, cg);360}361362TR::Register*363J9::TreeEvaluator::pdstoreiEvaluator(TR::Node *node, TR::CodeGenerator *cg)364{365return TR::TreeEvaluator::unImpOpEvaluator(node, cg);366}367368TR::Register*369J9::TreeEvaluator::pdaddEvaluator(TR::Node *node, TR::CodeGenerator *cg)370{371return TR::TreeEvaluator::unImpOpEvaluator(node, cg);372}373374TR::Register*375J9::TreeEvaluator::pdsubEvaluator(TR::Node *node, TR::CodeGenerator *cg)376{377return TR::TreeEvaluator::unImpOpEvaluator(node, cg);378}379380TR::Register*381J9::TreeEvaluator::pdmulEvaluator(TR::Node *node, TR::CodeGenerator *cg)382{383return TR::TreeEvaluator::unImpOpEvaluator(node, cg);384}385386TR::Register*387J9::TreeEvaluator::pddivEvaluator(TR::Node *node, TR::CodeGenerator *cg)388{389return TR::TreeEvaluator::unImpOpEvaluator(node, cg);390}391392TR::Register*393J9::TreeEvaluator::pdremEvaluator(TR::Node *node, TR::CodeGenerator *cg)394{395return TR::TreeEvaluator::unImpOpEvaluator(node, cg);396}397398TR::Register*399J9::TreeEvaluator::pdnegEvaluator(TR::Node *node, TR::CodeGenerator *cg)400{401return TR::TreeEvaluator::unImpOpEvaluator(node, cg);402}403404TR::Register*405J9::TreeEvaluator::pdabsEvaluator(TR::Node *node, TR::CodeGenerator *cg)406{407return TR::TreeEvaluator::unImpOpEvaluator(node, cg);408}409410TR::Register*411J9::TreeEvaluator::pdshrEvaluator(TR::Node *node, TR::CodeGenerator *cg)412{413return TR::TreeEvaluator::unImpOpEvaluator(node, cg);414}415416TR::Register*417J9::TreeEvaluator::pdshlEvaluator(TR::Node *node, TR::CodeGenerator *cg)418{419return TR::TreeEvaluator::unImpOpEvaluator(node, cg);420}421422TR::Register*423J9::TreeEvaluator::pdshrSetSignEvaluator(TR::Node *node, TR::CodeGenerator *cg)424{425return TR::TreeEvaluator::unImpOpEvaluator(node, cg);426}427428TR::Register*429J9::TreeEvaluator::pdshlSetSignEvaluator(TR::Node *node, TR::CodeGenerator *cg)430{431return TR::TreeEvaluator::unImpOpEvaluator(node, cg);432}433434TR::Register*435J9::TreeEvaluator::pdshlOverflowEvaluator(TR::Node *node, TR::CodeGenerator *cg)436{437return TR::TreeEvaluator::unImpOpEvaluator(node, cg);438}439440TR::Register*441J9::TreeEvaluator::pdchkEvaluator(TR::Node *node, TR::CodeGenerator *cg)442{443return TR::TreeEvaluator::unImpOpEvaluator(node, cg);444}445446TR::Register*447J9::TreeEvaluator::pd2iEvaluator(TR::Node *node, TR::CodeGenerator *cg)448{449return TR::TreeEvaluator::unImpOpEvaluator(node, cg);450}451452TR::Register*453J9::TreeEvaluator::pd2iuEvaluator(TR::Node *node, TR::CodeGenerator *cg)454{455return TR::TreeEvaluator::unImpOpEvaluator(node, cg);456}457458TR::Register*459J9::TreeEvaluator::pd2iOverflowEvaluator(TR::Node *node, TR::CodeGenerator *cg)460{461return TR::TreeEvaluator::unImpOpEvaluator(node, cg);462}463464TR::Register*465J9::TreeEvaluator::i2pdEvaluator(TR::Node *node, TR::CodeGenerator *cg)466{467return TR::TreeEvaluator::unImpOpEvaluator(node, cg);468}469470TR::Register*471J9::TreeEvaluator::iu2pdEvaluator(TR::Node *node, TR::CodeGenerator *cg)472{473return TR::TreeEvaluator::unImpOpEvaluator(node, cg);474}475476TR::Register*477J9::TreeEvaluator::pd2lEvaluator(TR::Node *node, TR::CodeGenerator *cg)478{479return TR::TreeEvaluator::unImpOpEvaluator(node, cg);480}481482TR::Register*483J9::TreeEvaluator::pd2luEvaluator(TR::Node *node, TR::CodeGenerator *cg)484{485return TR::TreeEvaluator::unImpOpEvaluator(node, cg);486}487488TR::Register*489J9::TreeEvaluator::pd2lOverflowEvaluator(TR::Node *node, TR::CodeGenerator *cg)490{491return TR::TreeEvaluator::unImpOpEvaluator(node, cg);492}493494TR::Register*495J9::TreeEvaluator::l2pdEvaluator(TR::Node *node, TR::CodeGenerator *cg)496{497return TR::TreeEvaluator::unImpOpEvaluator(node, cg);498}499500TR::Register*501J9::TreeEvaluator::lu2pdEvaluator(TR::Node *node, TR::CodeGenerator *cg)502{503return TR::TreeEvaluator::unImpOpEvaluator(node, cg);504}505506TR::Register*507J9::TreeEvaluator::pd2fEvaluator(TR::Node *node, TR::CodeGenerator *cg)508{509return TR::TreeEvaluator::unImpOpEvaluator(node, cg);510}511512TR::Register*513J9::TreeEvaluator::pd2dEvaluator(TR::Node *node, TR::CodeGenerator *cg)514{515return TR::TreeEvaluator::unImpOpEvaluator(node, cg);516}517518TR::Register*519J9::TreeEvaluator::f2pdEvaluator(TR::Node *node, TR::CodeGenerator *cg)520{521return TR::TreeEvaluator::unImpOpEvaluator(node, cg);522}523524TR::Register*525J9::TreeEvaluator::d2pdEvaluator(TR::Node *node, TR::CodeGenerator *cg)526{527return TR::TreeEvaluator::unImpOpEvaluator(node, cg);528}529530TR::Register*531J9::TreeEvaluator::pdcmpeqEvaluator(TR::Node *node, TR::CodeGenerator *cg)532{533return TR::TreeEvaluator::unImpOpEvaluator(node, cg);534}535536TR::Register*537J9::TreeEvaluator::pdcmpneEvaluator(TR::Node *node, TR::CodeGenerator *cg)538{539return TR::TreeEvaluator::unImpOpEvaluator(node, cg);540}541542TR::Register*543J9::TreeEvaluator::pdcmpltEvaluator(TR::Node *node, TR::CodeGenerator *cg)544{545return TR::TreeEvaluator::unImpOpEvaluator(node, cg);546}547548TR::Register*549J9::TreeEvaluator::pdcmpgeEvaluator(TR::Node *node, TR::CodeGenerator *cg)550{551return TR::TreeEvaluator::unImpOpEvaluator(node, cg);552}553554TR::Register*555J9::TreeEvaluator::pdcmpgtEvaluator(TR::Node *node, TR::CodeGenerator *cg)556{557return TR::TreeEvaluator::unImpOpEvaluator(node, cg);558}559560TR::Register*561J9::TreeEvaluator::pdcmpleEvaluator(TR::Node *node, TR::CodeGenerator *cg)562{563return TR::TreeEvaluator::unImpOpEvaluator(node, cg);564}565566TR::Register*567J9::TreeEvaluator::pdcleanEvaluator(TR::Node *node, TR::CodeGenerator *cg)568{569return TR::TreeEvaluator::unImpOpEvaluator(node, cg);570}571572TR::Register*573J9::TreeEvaluator::pdclearEvaluator(TR::Node *node, TR::CodeGenerator *cg)574{575return TR::TreeEvaluator::unImpOpEvaluator(node, cg);576}577578TR::Register*579J9::TreeEvaluator::pdclearSetSignEvaluator(TR::Node *node, TR::CodeGenerator *cg)580{581return TR::TreeEvaluator::unImpOpEvaluator(node, cg);582}583584TR::Register*585J9::TreeEvaluator::pdSetSignEvaluator(TR::Node *node, TR::CodeGenerator *cg)586{587return TR::TreeEvaluator::unImpOpEvaluator(node, cg);588}589590TR::Register*591J9::TreeEvaluator::pdModifyPrecisionEvaluator(TR::Node *node, TR::CodeGenerator *cg)592{593return TR::TreeEvaluator::unImpOpEvaluator(node, cg);594}595596TR::Register*597J9::TreeEvaluator::countDigitsEvaluator(TR::Node *node, TR::CodeGenerator *cg)598{599return TR::TreeEvaluator::unImpOpEvaluator(node, cg);600}601602TR::Register*603J9::TreeEvaluator::BCDCHKEvaluator(TR::Node *node, TR::CodeGenerator *cg)604{605return TR::TreeEvaluator::unImpOpEvaluator(node, cg);606}607608TR::Snippet *609J9::TreeEvaluator::getFieldWatchInstanceSnippet(TR::CodeGenerator *cg, TR::Node *node, J9Method *m, UDATA loc, UDATA os)610{611return new (cg->trHeapMemory()) TR::J9WatchedInstanceFieldSnippet(cg, node, m, loc, os);612}613614TR::Snippet *615J9::TreeEvaluator::getFieldWatchStaticSnippet(TR::CodeGenerator *cg, TR::Node *node, J9Method *m, UDATA loc, void *fieldAddress, J9Class *fieldClass)616{617return new (cg->trHeapMemory()) TR::J9WatchedStaticFieldSnippet(cg, node, m, loc, fieldAddress, fieldClass);618}619620void621J9::TreeEvaluator::rdWrtbarHelperForFieldWatch(TR::Node *node, TR::CodeGenerator *cg, TR::Register *sideEffectRegister, TR::Register *valueReg)622{623TR_ASSERT_FATAL(J9ClassHasWatchedFields >= std::numeric_limits<uint16_t>::min() && J9ClassHasWatchedFields <= std::numeric_limits<uint16_t>::max(), "Expecting value of J9ClassHasWatchedFields to be within 16 bits. Currently it's %d(%p).", J9ClassHasWatchedFields, J9ClassHasWatchedFields);624625// Populate a data snippet with the required information so we can call a VM helper to report the Field Watch event.626TR::SymbolReference *symRef = node->getSymbolReference();627J9Method *owningMethod = reinterpret_cast<J9Method *>(node->getOwningMethod());628TR::Register *dataSnippetRegister = cg->allocateRegister();629bool isWrite = node->getOpCode().isWrtBar();630bool isUnresolved = symRef->isUnresolved();631int32_t bcIndex = node->getByteCodeInfo().getByteCodeIndex();632633TR::Snippet *dataSnippet = NULL;634if (symRef->getSymbol()->isStatic())635{636void *fieldAddress = isUnresolved ? reinterpret_cast<void *>(-1) : symRef->getSymbol()->getStaticSymbol()->getStaticAddress();637J9Class *fieldClass = isUnresolved ? NULL : reinterpret_cast<J9Class *>(symRef->getOwningMethod(cg->comp())->getDeclaringClassFromFieldOrStatic(cg->comp(), symRef->getCPIndex()));638dataSnippet = TR::TreeEvaluator::getFieldWatchStaticSnippet(cg, node, owningMethod, bcIndex, fieldAddress, fieldClass);639}640else641{642dataSnippet = TR::TreeEvaluator::getFieldWatchInstanceSnippet(cg, node, owningMethod, bcIndex, isUnresolved ? -1 : symRef->getOffset() - TR::Compiler->om.objectHeaderSizeInBytes());643}644cg->addSnippet(dataSnippet);645646// If unresolved, then we generate instructions to populate the data snippet's fields correctly at runtime.647// Note: We also call the VM Helper routine to fill in the data snippet's fields if this is an AOT compilation.648// Once the infrastructure to support AOT during fieldwatch is enabled and functionally correct, we can remove is check.649if (isUnresolved || cg->needClassAndMethodPointerRelocations())650{651// Resolve and populate dataSnippet fields.652TR::TreeEvaluator::generateFillInDataBlockSequenceForUnresolvedField(cg, node, dataSnippet, isWrite, sideEffectRegister, dataSnippetRegister);653}654// Generate instructions to call the VM helper and report the fieldwatch event655TR::TreeEvaluator::generateTestAndReportFieldWatchInstructions(cg, node, dataSnippet, isWrite, sideEffectRegister, valueReg, dataSnippetRegister);656657cg->stopUsingRegister(dataSnippetRegister);658}659660TR::Register *661J9::TreeEvaluator::bwrtbarEvaluator(TR::Node *node, TR::CodeGenerator *cg)662{663// For rdbar and wrtbar nodes we first evaluate the children we need to664// handle the side effects. Then we delegate the evaluation of the remaining665// children and the load/store operation to the appropriate load/store evaluator.666TR::Register *valueReg = cg->evaluate(node->getFirstChild());667TR::Node *sideEffectNode = node->getSecondChild();668TR::Register *sideEffectRegister = cg->evaluate(sideEffectNode);669670if (cg->comp()->getOption(TR_EnableFieldWatch))671{672TR::TreeEvaluator::rdWrtbarHelperForFieldWatch(node, cg, sideEffectRegister, valueReg);673}674675// Note: The reference count for valueReg's node is not decremented here because the676// store evaluator also uses it and so it will evaluate+decrement it. Thus we must skip decrementing here677// to avoid double decrementing.678cg->decReferenceCount(sideEffectNode);679return TR::TreeEvaluator::bstoreEvaluator(node, cg);680}681682TR::Register *683J9::TreeEvaluator::bwrtbariEvaluator(TR::Node *node, TR::CodeGenerator *cg)684{685// For rdbar and wrtbar nodes we first evaluate the children we need to686// handle the side effects. Then we delegate the evaluation of the remaining687// children and the load/store operation to the appropriate load/store evaluator.688TR::Register *valueReg = cg->evaluate(node->getSecondChild());689TR::Node *sideEffectNode = node->getThirdChild();690TR::Register *sideEffectRegister = cg->evaluate(sideEffectNode);691692if (cg->comp()->getOption(TR_EnableFieldWatch))693{694TR::TreeEvaluator::rdWrtbarHelperForFieldWatch(node, cg, sideEffectRegister, valueReg);695}696697// Note: The reference count for valueReg's node is not decremented here because the698// store evaluator also uses it and so it will evaluate+decrement it. Thus we must skip decrementing here699// to avoid double decrementing.700cg->decReferenceCount(sideEffectNode);701return TR::TreeEvaluator::bstoreEvaluator(node, cg);702}703704TR::Register *705J9::TreeEvaluator::swrtbarEvaluator(TR::Node *node, TR::CodeGenerator *cg)706{707// For rdbar and wrtbar nodes we first evaluate the children we need to708// handle the side effects. Then we delegate the evaluation of the remaining709// children and the load/store operation to the appropriate load/store evaluator.710TR::Register *valueReg = cg->evaluate(node->getFirstChild());711TR::Node *sideEffectNode = node->getSecondChild();712TR::Register *sideEffectRegister = cg->evaluate(sideEffectNode);713714if (cg->comp()->getOption(TR_EnableFieldWatch))715{716TR::TreeEvaluator::rdWrtbarHelperForFieldWatch(node, cg, sideEffectRegister, valueReg);717}718719// Note: The reference count for valueReg's node is not decremented here because the720// store evaluator also uses it and so it will evaluate+decrement it. Thus we must skip decrementing here721// to avoid double decrementing.722cg->decReferenceCount(sideEffectNode);723return TR::TreeEvaluator::sstoreEvaluator(node, cg);724}725726TR::Register *727J9::TreeEvaluator::swrtbariEvaluator(TR::Node *node, TR::CodeGenerator *cg)728{729// For rdbar and wrtbar nodes we first evaluate the children we need to730// handle the side effects. Then we delegate the evaluation of the remaining731// children and the load/store operation to the appropriate load/store evaluator.732TR::Register *valueReg = cg->evaluate(node->getSecondChild());733TR::Node *sideEffectNode = node->getThirdChild();734TR::Register *sideEffectRegister = cg->evaluate(sideEffectNode);735736if (cg->comp()->getOption(TR_EnableFieldWatch))737{738TR::TreeEvaluator::rdWrtbarHelperForFieldWatch(node, cg, sideEffectRegister, valueReg);739}740741// Note: The reference count for valueReg's node is not decremented here because the742// store evaluator also uses it and so it will evaluate+decrement it. Thus we must skip decrementing here743// to avoid double decrementing.744cg->decReferenceCount(sideEffectNode);745return TR::TreeEvaluator::sstoreEvaluator(node, cg);746}747748TR::Register *749J9::TreeEvaluator::iwrtbarEvaluator(TR::Node *node, TR::CodeGenerator *cg)750{751// For rdbar and wrtbar nodes we first evaluate the children we need to752// handle the side effects. Then we delegate the evaluation of the remaining753// children and the load/store operation to the appropriate load/store evaluator.754TR::Register *valueReg = cg->evaluate(node->getFirstChild());755TR::Node *sideEffectNode = node->getSecondChild();756TR::Register *sideEffectRegister = cg->evaluate(sideEffectNode);757758if (cg->comp()->getOption(TR_EnableFieldWatch))759{760TR::TreeEvaluator::rdWrtbarHelperForFieldWatch(node, cg, sideEffectRegister, valueReg);761}762763// Note: The reference count for valueReg's node is not decremented here because the764// store evaluator also uses it and so it will evaluate+decrement it. Thus we must skip decrementing here765// to avoid double decrementing.766cg->decReferenceCount(sideEffectNode);767return TR::TreeEvaluator::istoreEvaluator(node, cg);768}769770TR::Register *771J9::TreeEvaluator::iwrtbariEvaluator(TR::Node *node, TR::CodeGenerator *cg)772{773// For rdbar and wrtbar nodes we first evaluate the children we need to774// handle the side effects. Then we delegate the evaluation of the remaining775// children and the load/store operation to the appropriate load/store evaluator.776TR::Register *valueReg = cg->evaluate(node->getSecondChild());777TR::Node *sideEffectNode = node->getThirdChild();778TR::Register *sideEffectRegister = cg->evaluate(sideEffectNode);779780if (cg->comp()->getOption(TR_EnableFieldWatch))781{782TR::TreeEvaluator::rdWrtbarHelperForFieldWatch(node, cg, sideEffectRegister, valueReg);783}784785// Note: The reference count for valueReg's node is not decremented here because the786// store evaluator also uses it and so it will evaluate+decrement it. Thus we must skip decrementing here787// to avoid double decrementing.788cg->decReferenceCount(sideEffectNode);789return TR::TreeEvaluator::istoreEvaluator(node, cg);790}791792TR::Register *793J9::TreeEvaluator::lwrtbarEvaluator(TR::Node *node, TR::CodeGenerator *cg)794{795// For rdbar and wrtbar nodes we first evaluate the children we need to796// handle the side effects. Then we delegate the evaluation of the remaining797// children and the load/store operation to the appropriate load/store evaluator.798TR::Register *valueReg = cg->evaluate(node->getFirstChild());799TR::Node *sideEffectNode = node->getSecondChild();800TR::Register *sideEffectRegister = cg->evaluate(sideEffectNode);801802if (cg->comp()->getOption(TR_EnableFieldWatch))803{804TR::TreeEvaluator::rdWrtbarHelperForFieldWatch(node, cg, sideEffectRegister, valueReg);805}806807// Note: The reference count for valueReg's node is not decremented here because the808// store evaluator also uses it and so it will evaluate+decrement it. Thus we must skip decrementing here809// to avoid double decrementing.810cg->decReferenceCount(sideEffectNode);811return TR::TreeEvaluator::lstoreEvaluator(node, cg);812}813814TR::Register *815J9::TreeEvaluator::lwrtbariEvaluator(TR::Node *node, TR::CodeGenerator *cg)816{817// For rdbar and wrtbar nodes we first evaluate the children we need to818// handle the side effects. Then we delegate the evaluation of the remaining819// children and the load/store operation to the appropriate load/store evaluator.820TR::Register *valueReg = cg->evaluate(node->getSecondChild());821TR::Node *sideEffectNode = node->getThirdChild();822TR::Register *sideEffectRegister = cg->evaluate(sideEffectNode);823824if (cg->comp()->getOption(TR_EnableFieldWatch))825{826TR::TreeEvaluator::rdWrtbarHelperForFieldWatch(node, cg, sideEffectRegister, valueReg);827}828829// Note: The reference count for valueReg's node is not decremented here because the830// store evaluator also uses it and so it will evaluate+decrement it. Thus we must skip decrementing here831// to avoid double decrementing.832cg->decReferenceCount(sideEffectNode);833return TR::TreeEvaluator::lstoreEvaluator(node, cg);834}835836TR::Register *837J9::TreeEvaluator::frdbarEvaluator(TR::Node *node, TR::CodeGenerator *cg)838{839// For rdbar and wrtbar nodes we first evaluate the children we need to840// handle the side effects. Then we delegate the evaluation of the remaining841// children and the load/store operation to the appropriate load/store evaluator.842TR::Node *sideEffectNode = node->getFirstChild();843TR::Register *sideEffectRegister = cg->evaluate(sideEffectNode);844845if (cg->comp()->getOption(TR_EnableFieldWatch))846{847TR::TreeEvaluator::rdWrtbarHelperForFieldWatch(node, cg, sideEffectRegister, NULL);848}849850cg->decReferenceCount(sideEffectNode);851return TR::TreeEvaluator::floadEvaluator(node, cg);852}853854TR::Register *855J9::TreeEvaluator::frdbariEvaluator(TR::Node *node, TR::CodeGenerator *cg)856{857// For rdbar and wrtbar nodes we first evaluate the children we need to858// handle the side effects. Then we delegate the evaluation of the remaining859// children and the load/store operation to the appropriate load/store evaluator.860TR::Register *sideEffectRegister = cg->evaluate(node->getFirstChild());861862if (cg->comp()->getOption(TR_EnableFieldWatch))863{864TR::TreeEvaluator::rdWrtbarHelperForFieldWatch(node, cg, sideEffectRegister, NULL);865}866// Note: For indirect rdbar nodes, the first child (sideEffectNode) is also used by the867// load evaluator. The load evaluator will also evaluate+decrement it. In order to avoid double868// decrementing the node we skip doing it here and let the load evaluator do it.869return TR::TreeEvaluator::floadEvaluator(node, cg);870}871872TR::Register *873J9::TreeEvaluator::drdbarEvaluator(TR::Node *node, TR::CodeGenerator *cg)874{875// For rdbar and wrtbar nodes we first evaluate the children we need to876// handle the side effects. Then we delegate the evaluation of the remaining877// children and the load/store operation to the appropriate load/store evaluator.878TR::Node *sideEffectNode = node->getFirstChild();879TR::Register *sideEffectRegister = cg->evaluate(sideEffectNode);880881if (cg->comp()->getOption(TR_EnableFieldWatch))882{883TR::TreeEvaluator::rdWrtbarHelperForFieldWatch(node, cg, sideEffectRegister, NULL);884}885886cg->decReferenceCount(sideEffectNode);887return TR::TreeEvaluator::dloadEvaluator(node, cg);888}889890TR::Register *891J9::TreeEvaluator::drdbariEvaluator(TR::Node *node, TR::CodeGenerator *cg)892{893// For rdbar and wrtbar nodes we first evaluate the children we need to894// handle the side effects. Then we delegate the evaluation of the remaining895// children and the load/store operation to the appropriate load/store evaluator.896TR::Register *sideEffectRegister = cg->evaluate(node->getFirstChild());897898if (cg->comp()->getOption(TR_EnableFieldWatch))899{900TR::TreeEvaluator::rdWrtbarHelperForFieldWatch(node, cg, sideEffectRegister, NULL);901}902903// Note: For indirect rdbar nodes, the first child (sideEffectNode) is also used by the904// load evaluator. The load evaluator will also evaluate+decrement it. In order to avoid double905// decrementing the node we skip doing it here and let the load evaluator do it.906return TR::TreeEvaluator::dloadEvaluator(node, cg);907}908909TR::Register *910J9::TreeEvaluator::brdbarEvaluator(TR::Node *node, TR::CodeGenerator *cg)911{912// For rdbar and wrtbar nodes we first evaluate the children we need to913// handle the side effects. Then we delegate the evaluation of the remaining914// children and the load/store operation to the appropriate load/store evaluator.915TR::Node *sideEffectNode = node->getFirstChild();916TR::Register *sideEffectRegister = cg->evaluate(sideEffectNode);917918if (cg->comp()->getOption(TR_EnableFieldWatch))919{920TR::TreeEvaluator::rdWrtbarHelperForFieldWatch(node, cg, sideEffectRegister, NULL);921}922923cg->decReferenceCount(sideEffectNode);924return TR::TreeEvaluator::bloadEvaluator(node, cg);925}926927TR::Register *928J9::TreeEvaluator::brdbariEvaluator(TR::Node *node, TR::CodeGenerator *cg)929{930// For rdbar and wrtbar nodes we first evaluate the children we need to931// handle the side effects. Then we delegate the evaluation of the remaining932// children and the load/store operation to the appropriate load/store evaluator.933TR::Register *sideEffectRegister = cg->evaluate(node->getFirstChild());934935if (cg->comp()->getOption(TR_EnableFieldWatch))936{937TR::TreeEvaluator::rdWrtbarHelperForFieldWatch(node, cg, sideEffectRegister, NULL);938}939940// Note: For indirect rdbar nodes, the first child (sideEffectNode) is also used by the941// load evaluator. The load evaluator will also evaluate+decrement it. In order to avoid double942// decrementing the node we skip doing it here and let the load evaluator do it.943return TR::TreeEvaluator::bloadEvaluator(node, cg);944}945946TR::Register *947J9::TreeEvaluator::srdbarEvaluator(TR::Node *node, TR::CodeGenerator *cg)948{949// For rdbar and wrtbar nodes we first evaluate the children we need to950// handle the side effects. Then we delegate the evaluation of the remaining951// children and the load/store operation to the appropriate load/store evaluator.952TR::Node *sideEffectNode = node->getFirstChild();953TR::Register *sideEffectRegister = cg->evaluate(sideEffectNode);954955if (cg->comp()->getOption(TR_EnableFieldWatch))956{957TR::TreeEvaluator::rdWrtbarHelperForFieldWatch(node, cg, sideEffectRegister, NULL);958}959960cg->decReferenceCount(sideEffectNode);961return TR::TreeEvaluator::sloadEvaluator(node, cg);962}963964TR::Register *965J9::TreeEvaluator::srdbariEvaluator(TR::Node *node, TR::CodeGenerator *cg)966{967// For rdbar and wrtbar nodes we first evaluate the children we need to968// handle the side effects. Then we delegate the evaluation of the remaining969// children and the load/store operation to the appropriate load/store evaluator.970TR::Register *sideEffectRegister = cg->evaluate(node->getFirstChild());971972if (cg->comp()->getOption(TR_EnableFieldWatch))973{974TR::TreeEvaluator::rdWrtbarHelperForFieldWatch(node, cg, sideEffectRegister, NULL);975}976977// Note: For indirect rdbar nodes, the first child (sideEffectNode) is also used by the978// load evaluator. The load evaluator will also evaluate+decrement it. In order to avoid double979// decrementing the node we skip doing it here and let the load evaluator do it.980return TR::TreeEvaluator::sloadEvaluator(node, cg);981}982983TR::Register *984J9::TreeEvaluator::lrdbarEvaluator(TR::Node *node, TR::CodeGenerator *cg)985{986// For rdbar and wrtbar nodes we first evaluate the children we need to987// handle the side effects. Then we delegate the evaluation of the remaining988// children and the load/store operation to the appropriate load/store evaluator.989TR::Node *sideEffectNode = node->getFirstChild();990TR::Register *sideEffectRegister = cg->evaluate(sideEffectNode);991992if (cg->comp()->getOption(TR_EnableFieldWatch))993{994TR::TreeEvaluator::rdWrtbarHelperForFieldWatch(node, cg, sideEffectRegister, NULL);995}996997cg->decReferenceCount(sideEffectNode);998return TR::TreeEvaluator::lloadEvaluator(node, cg);999}10001001TR::Register *1002J9::TreeEvaluator::lrdbariEvaluator(TR::Node *node, TR::CodeGenerator *cg)1003{1004// For rdbar and wrtbar nodes we first evaluate the children we need to1005// handle the side effects. Then we delegate the evaluation of the remaining1006// children and the load/store operation to the appropriate load/store evaluator.1007TR::Register *sideEffectRegister = cg->evaluate(node->getFirstChild());10081009if (cg->comp()->getOption(TR_EnableFieldWatch))1010{1011TR::TreeEvaluator::rdWrtbarHelperForFieldWatch(node, cg, sideEffectRegister, NULL);1012}10131014// Note: For indirect rdbar nodes, the first child (sideEffectNode) is also used by the1015// load evaluator. The load evaluator will also evaluate+decrement it. In order to avoid double1016// decrementing the node we skip doing it here and let the load evaluator do it.1017return TR::TreeEvaluator::lloadEvaluator(node, cg);1018}10191020///////////////////////////////////////////////////////////////////////////////////////1021// monexitfence -- do nothing, just a placeholder for live monitor meta data1022///////////////////////////////////////////////////////////////////////////////////////1023TR::Register *1024J9::TreeEvaluator::monexitfenceEvaluator(TR::Node *node, TR::CodeGenerator *cg)1025{1026return NULL;1027}10281029bool J9::TreeEvaluator::getIndirectWrtbarValueNode(TR::CodeGenerator *cg, TR::Node *node, TR::Node*& sourceChild, bool incSrcRefCount)1030{1031TR_ASSERT_FATAL(node->getOpCode().isIndirect() && node->getOpCode().isWrtBar(), "getIndirectWrtbarValueNode expects indirect wrtbar nodes only n%dn (%p)\n", node->getGlobalIndex(), node);1032bool usingCompressedPointers = false;1033sourceChild = node->getSecondChild();10341035if (cg->comp()->useCompressedPointers() && (node->getSymbolReference()->getSymbol()->getDataType() == TR::Address) &&1036(node->getSecondChild()->getDataType() != TR::Address))1037{1038// pattern match the sequence1039// awrtbari f awrtbari f <- node1040// aload O aload O1041// value l2i1042// lshr1043// lsub <- translatedNode1044// a2l1045// value <- sourceChild1046// lconst HB1047// iconst shftKonst1048//1049// -or- if the field is known to be null1050// awrtbari f1051// aload O1052// l2i1053// a2l1054// value <- sourceChild1055//1056TR::Node *translatedNode = sourceChild;1057if (translatedNode->getOpCodeValue() == TR::l2i)1058{1059translatedNode = translatedNode->getFirstChild();1060}1061if (translatedNode->getOpCode().isRightShift())1062{1063TR::Node *shiftAmountChild = translatedNode->getSecondChild();1064TR_ASSERT_FATAL(TR::Compiler->om.compressedReferenceShiftOffset() == shiftAmountChild->getConstValue(),1065"Expect shift amount in the compressedref conversion sequence to be %d but get %d for indirect wrtbar node n%dn (%p)\n",1066TR::Compiler->om.compressedReferenceShiftOffset(), shiftAmountChild->getConstValue(), node->getGlobalIndex(), node);10671068translatedNode = translatedNode->getFirstChild();1069}10701071usingCompressedPointers = true;10721073while ((sourceChild->getNumChildren() > 0) && (sourceChild->getOpCodeValue() != TR::a2l))1074{1075sourceChild = sourceChild->getFirstChild();1076}1077if (sourceChild->getOpCodeValue() == TR::a2l)1078{1079sourceChild = sourceChild->getFirstChild();1080}10811082// Artificially bump up the refCount on the value so1083// that different registers are allocated for the actual1084// and compressed values. This is done so that the VMwrtbarEvaluator1085// uses the uncompressed value. We only need to do this when the caller1086// is evaluating the actual write barrier.1087if (incSrcRefCount)1088{1089sourceChild->incReferenceCount();1090}1091}1092return usingCompressedPointers;1093}10941095static1096void traceInstanceOfOrCheckCastProfilingInfo(TR::CodeGenerator *cg, TR::Node *node, TR_OpaqueClassBlock *castClass)1097{1098TR::Compilation *comp = cg->comp();1099TR_J9VMBase *fej9 = (TR_J9VMBase *)(cg->fe());1100TR_ByteCodeInfo bcInfo = node->getByteCodeInfo();1101TR_ValueProfileInfoManager *valueProfileInfo = TR_ValueProfileInfoManager::get(comp);11021103if (!valueProfileInfo)1104{1105return;1106}11071108TR_AddressInfo * valueInfo = static_cast<TR_AddressInfo*>(valueProfileInfo->getValueInfo(bcInfo, comp, AddressInfo, TR_ValueProfileInfoManager::justInterpreterProfileInfo));1109if (!valueInfo || valueInfo->getNumProfiledValues() == 0)1110{1111return;1112}11131114traceMsg(comp, "%s:\n", __func__);11151116TR_ScratchList<TR_ExtraAddressInfo> valuesSortedByFrequency(comp->trMemory());11171118valueInfo->getSortedList(comp, &valuesSortedByFrequency);11191120ListIterator<TR_ExtraAddressInfo> sortedValuesIt(&valuesSortedByFrequency);1121for (TR_ExtraAddressInfo *profiledInfo = sortedValuesIt.getFirst(); profiledInfo != NULL; profiledInfo = sortedValuesIt.getNext())1122{1123TR_OpaqueClassBlock *profiledClass = fej9->getProfiledClassFromProfiledInfo(profiledInfo);11241125traceMsg(comp, "%s:\tProfiled class [" POINTER_PRINTF_FORMAT "] (%u/%u)\n",1126node->getOpCode().getName(), profiledClass, profiledInfo->_frequency, valueInfo->getTotalFrequency());11271128if (!profiledClass)1129continue;11301131if (comp->getPersistentInfo()->isObsoleteClass(profiledClass, fej9))1132{1133traceMsg(comp, "%s:\tProfiled class [" POINTER_PRINTF_FORMAT "] is obsolete\n",1134node->getOpCode().getName(), profiledClass);1135continue;1136}11371138bool isInstanceOf = fej9->instanceOfOrCheckCastNoCacheUpdate((J9Class *)profiledClass, (J9Class *)castClass);1139traceMsg(comp, "%s:\tProfiled class [" POINTER_PRINTF_FORMAT "] is %san instance of cast class\n",1140node->getOpCode().getName(), profiledClass, isInstanceOf ? "" : "not ");1141}1142}1143/** \brief Generates an array of profiled classes with the boolean representing if the profiled class is instanceOf cast class or not1144** \param profiledClassList1145** An array of InstanceOfOrCheckCasrProfiledClasses structure passed from the main evaluator to fill up with profiled classes info1146** \param topClassProbability1147** float pointer passed from main evaluator, we update the value with the probability for the top profiled class to be castClass1148** \param maxProfiledClass1149** An int denoting how many profiled classes we want1150**/1151static1152uint32_t getInstanceOfOrCheckCastTopProfiledClass(TR::CodeGenerator *cg, TR::Node *node, TR_OpaqueClassBlock *castClass, J9::TreeEvaluator::InstanceOfOrCheckCastProfiledClasses *profiledClassList, bool *topClassWasCastClass, uint32_t maxProfiledClass, float *topClassProbability)1153{1154TR::Compilation *comp = cg->comp();11551156if (comp->getOption(TR_TraceCG))1157{1158static bool traceProfilingInfo = feGetEnv("TR_traceInstanceOfOrCheckCastProfilingInfo") != NULL;1159if (traceProfilingInfo)1160traceInstanceOfOrCheckCastProfilingInfo(cg, node, castClass);1161}11621163TR_J9VMBase *fej9 = (TR_J9VMBase *)(cg->fe());1164TR_ByteCodeInfo bcInfo = node->getByteCodeInfo();1165TR_ValueProfileInfoManager *valueProfileInfo = TR_ValueProfileInfoManager::get(comp);11661167// We do not have validation record to verify that relocated profiled class1168// in the load run is instanceof castclass or not. So without that1169// verification, we could end up generating code where we have a defined1170// relationship between profiled class and cast class which could not be1171// true in load run and we could end up with incorrect execution in the1172// application.1173// TODO: Once we have validation record for instanceOfOrCheckCastNoCacheUpdate1174// enable profiled class test in AOT when SVM is enabled.1175if (!valueProfileInfo || comp->compileRelocatableCode())1176{1177return 0;1178}11791180TR_AddressInfo * valueInfo = static_cast<TR_AddressInfo*>(valueProfileInfo->getValueInfo(bcInfo, comp, AddressInfo, TR_ValueProfileInfoManager::justInterpreterProfileInfo));1181if (!valueInfo || valueInfo->getNumProfiledValues() == 0)1182{1183return 0;1184}11851186if (topClassWasCastClass)1187*topClassWasCastClass = false;11881189TR_ScratchList<TR_ExtraAddressInfo> valuesSortedByFrequency(comp->trMemory());11901191valueInfo->getSortedList(comp, &valuesSortedByFrequency);11921193float totalFrequency = valueInfo->getTotalFrequency();11941195ListIterator<TR_ExtraAddressInfo> sortedValuesIt(&valuesSortedByFrequency);1196uint32_t numProfiledClasses = 0;1197for (TR_ExtraAddressInfo *profiledInfo = sortedValuesIt.getFirst(); profiledInfo != NULL && numProfiledClasses < maxProfiledClass ; profiledInfo = sortedValuesIt.getNext())1198{1199TR_OpaqueClassBlock *tempProfiledClass = fej9->getProfiledClassFromProfiledInfo(profiledInfo);12001201if (!tempProfiledClass)1202continue;12031204// Skip unloaded classes.1205//1206if (comp->getPersistentInfo()->isObsoleteClass(tempProfiledClass, fej9))1207{1208if (comp->getOption(TR_TraceCG))1209{1210traceMsg(comp, "%s: Profiled class [" POINTER_PRINTF_FORMAT "] is obsolete, skipping\n",1211node->getOpCode().getName(), tempProfiledClass);1212}1213continue;1214}12151216// For checkcast, skip classes that will fail the cast, not much value in optimizing for those cases.1217// We also don't want to pollute the cast class cache with a failing class for the same reason.1218//1219bool isInstanceOf = fej9->instanceOfOrCheckCastNoCacheUpdate((J9Class *)tempProfiledClass, (J9Class *)castClass);1220if (node->getOpCode().isCheckCast() && !isInstanceOf)1221{1222if (comp->getOption(TR_TraceCG))1223{1224traceMsg(comp, "%s: Profiled class [" POINTER_PRINTF_FORMAT "] is not an instance of cast class, skipping\n",1225node->getOpCode().getName(), tempProfiledClass);1226}1227continue;1228}12291230// If the cast class is the top class skip it and return the next highest class if the caller requested it by providing an output param.1231//1232if (tempProfiledClass == castClass && topClassWasCastClass && numProfiledClasses == 0)1233{1234if (comp->getOption(TR_TraceCG))1235{1236traceMsg(comp, "%s: Profiled class [" POINTER_PRINTF_FORMAT "] is the cast class, informing caller and skipping\n",1237node->getOpCode().getName(), tempProfiledClass);1238}1239*topClassWasCastClass = true;1240*topClassProbability = profiledInfo->_frequency / totalFrequency;1241continue;1242}12431244// For AOT compiles with a SymbolValidationManager, skip any classes which cannot be verified.1245//1246if (comp->compileRelocatableCode() && comp->getOption(TR_UseSymbolValidationManager))1247if (!comp->getSymbolValidationManager()->addProfiledClassRecord(tempProfiledClass))1248continue;12491250float frequency = profiledInfo->_frequency / totalFrequency;1251if ( frequency >= TR::Options::getMinProfiledCheckcastFrequency() )1252{1253// We have a winner.1254//1255profiledClassList[numProfiledClasses].profiledClass = tempProfiledClass;1256profiledClassList[numProfiledClasses].isProfiledClassInstanceOfCastClass = isInstanceOf;1257profiledClassList[numProfiledClasses].frequency = frequency;1258numProfiledClasses++;1259}1260else1261{1262// Profiled Class is sorted by frequency so if the frequency is less than the Minimum don't bother with generating another profiled Class1263break;1264}1265}1266return numProfiledClasses;1267}12681269/** \brief Generates an array of profiled classes with the boolean representing if the profiled class is instanceOf cast class or not1270** \param profiledClassList1271** An array of InstanceOfOrCheckCasrProfiledClasses structure passed from the main evaluator to fill up with profiled classes info1272** \param numberOfProfiledClass1273** An int pointer passed from main evaluator, we update the value with the number of classes we get from profilef info1274** \param maxProfiledClass1275** An int denoting how many profiled classes we want1276** \param topClassProbability1277** Probability of having topClass to be castClass.1278** \param topClassWasCastClass1279** Boolean pointer which will be set to true or false depending on if top profiled class was cast class or not1280**/1281uint32_t J9::TreeEvaluator::calculateInstanceOfOrCheckCastSequences(TR::Node *instanceOfOrCheckCastNode, InstanceOfOrCheckCastSequences *sequences, TR_OpaqueClassBlock **compileTimeGuessClass, TR::CodeGenerator *cg, InstanceOfOrCheckCastProfiledClasses *profiledClassList, uint32_t *numberOfProfiledClass, uint32_t maxProfiledClass, float * topClassProbability, bool *topClassWasCastClass)1282{1283TR_J9VMBase *fej9 = (TR_J9VMBase *)(cg->fe());1284TR_ASSERT(instanceOfOrCheckCastNode->getOpCode().isCheckCast() || instanceOfOrCheckCastNode->getOpCodeValue() == TR::instanceof, "Unexpected node opcode");12851286TR::Node *objectNode = instanceOfOrCheckCastNode->getFirstChild();1287TR::Node *castClassNode = instanceOfOrCheckCastNode->getSecondChild();12881289bool isInstanceOf = instanceOfOrCheckCastNode->getOpCodeValue() == TR::instanceof;1290bool mayBeNull = !instanceOfOrCheckCastNode->isReferenceNonNull() && !objectNode->isNonNull();12911292// By default maxOnsiteCacheSlotForInstanceOf is set to 0 which means cache is disable.1293// To enable test pass JIT option maxOnsiteCacheSlotForInstanceOf=<number_of_slots>1294bool createDynamicCacheTests = cg->comp()->getOptions()->getMaxOnsiteCacheSlotForInstanceOf() > 0;129512961297uint32_t i = 0;1298uint32_t numProfiledClasses = 0;12991300if (castClassNode->getReferenceCount() > 1)1301{1302sequences[i++] = EvaluateCastClass;1303}13041305TR::SymbolReference *castClassSymRef = castClassNode->getSymbolReference();13061307if ((cg->comp()->getOption(TR_DisableInlineCheckCast) && (instanceOfOrCheckCastNode->getOpCodeValue() == TR::checkcast || instanceOfOrCheckCastNode->getOpCodeValue() == TR::checkcastAndNULLCHK)) || (cg->comp()->getOption(TR_DisableInlineInstanceOf) && instanceOfOrCheckCastNode->getOpCodeValue() == TR::instanceof))1308{1309if (instanceOfOrCheckCastNode->getOpCodeValue() == TR::checkcastAndNULLCHK)1310sequences[i++] = NullTest;1311sequences[i++] = HelperCall;1312}1313// Object is known to be null, usually removed by the optimizer, but in case they're not we know the result of the cast/instanceof.1314//1315else if (objectNode->isNull())1316{1317if (instanceOfOrCheckCastNode->getOpCodeValue() == TR::checkcastAndNULLCHK)1318sequences[i++] = NullTest;1319sequences[i++] = isInstanceOf ? GoToFalse : GoToTrue;1320}1321// Cast class is unresolved, not a lot of room to be fancy here.1322//1323else if (castClassSymRef->isUnresolved())1324{1325if (cg->comp()->getOption(TR_TraceCG))1326traceMsg(cg->comp(),"Cast Class unresolved\n");1327if (mayBeNull)1328sequences[i++] = NullTest;1329sequences[i++] = ClassEqualityTest;1330// There is a possibility of attempt to cast object to another class and having cache on that object updated by helper.1331// Before going to helper checking the cache.1332sequences[i++] = CastClassCacheTest;1333if (createDynamicCacheTests)1334sequences[i++] = DynamicCacheObjectClassTest;1335sequences[i++] = HelperCall;1336}1337// Cast class is a runtime variable, still not a lot of room to be fancy.1338//1339else if (!OMR::TreeEvaluator::isStaticClassSymRef(castClassSymRef))1340{1341traceMsg(cg->comp(),"Cast Class runtimeVariable\n");1342TR_ASSERT(isInstanceOf, "Expecting instanceof when cast class is a runtime variable");1343if (mayBeNull)1344sequences[i++] = NullTest;1345sequences[i++] = ClassEqualityTest;1346sequences[i++] = CastClassCacheTest;1347// On Z, We were having support for Super Class Test for dynamic Cast Class so adding it here. It can be guarded if Power/X do not need it.1348if (cg->supportsInliningOfIsInstance() &&1349instanceOfOrCheckCastNode->getOpCodeValue() == TR::instanceof &&1350instanceOfOrCheckCastNode->getSecondChild()->getOpCodeValue() != TR::loadaddr)1351sequences[i++] = SuperClassTest;1352if (createDynamicCacheTests)1353sequences[i++] = DynamicCacheDynamicCastClassTest;1354sequences[i++] = HelperCall;1355}13561357// Cast class is a compile-time constant, we can generate better code in this case.1358//1359else1360{13611362TR::StaticSymbol *castClassSym = castClassSymRef->getSymbol()->getStaticSymbol();1363TR_OpaqueClassBlock *castClass = (TR_OpaqueClassBlock *)castClassSym->getStaticAddress();1364J9UTF8 *castClassName = J9ROMCLASS_CLASSNAME(TR::Compiler->cls.romClassOf((TR_OpaqueClassBlock *) castClass));1365// Cast class is a primitive (implies this is an instanceof, since you can't cast an object to a primitive).1366// Usually removed by the optimizer, but in case they're not we know they'll always fail, no object can be of a primitive type.1367// We don't even need to do a null test unless it's a checkcastAndNULLCHK node.1368//1369if (TR::Compiler->cls.isPrimitiveClass(cg->comp(), castClass))1370{1371TR_ASSERT(isInstanceOf, "Expecting instanceof when cast class is a primitive");1372if (instanceOfOrCheckCastNode->getOpCodeValue() == TR::checkcastAndNULLCHK)1373sequences[i++] = NullTest;1374sequences[i++] = GoToFalse;1375}1376// Cast class is java/lang/Object.1377// Usually removed by the optimizer, if not we know everything is an Object, instanceof on null is the only thing that needs to be checked.1378//1379else if (cg->comp()->getObjectClassPointer() == castClass)1380{1381if (isInstanceOf)1382{1383if (mayBeNull)1384sequences[i++] = NullTest;1385sequences[i++] = GoToTrue;1386}1387else1388{1389if (instanceOfOrCheckCastNode->getOpCodeValue() == TR::checkcastAndNULLCHK)1390sequences[i++] = NullTest;1391sequences[i++] = GoToTrue;1392}1393}1394else1395{1396if (mayBeNull)1397{1398sequences[i++] = NullTest;1399}14001401TR_OpaqueClassBlock *topProfiledClass = NULL;14021403// If the caller doesn't provide the output param don't bother with profiling.1404//1405if (profiledClassList)1406{1407*numberOfProfiledClass = getInstanceOfOrCheckCastTopProfiledClass(cg, instanceOfOrCheckCastNode, castClass, profiledClassList, topClassWasCastClass, maxProfiledClass, topClassProbability);1408numProfiledClasses = *numberOfProfiledClass;1409if (cg->comp()->getOption(TR_TraceCG))1410{1411for (int i=0; i<numProfiledClasses; i++)1412{1413J9UTF8 *profiledClassName = J9ROMCLASS_CLASSNAME(TR::Compiler->cls.romClassOf((TR_OpaqueClassBlock *) profiledClassList[i].profiledClass));1414traceMsg(cg->comp(), "%s:Interpreter profiling instance class: [" POINTER_PRINTF_FORMAT "] %.*s, probability=%.1f\n",1415instanceOfOrCheckCastNode->getOpCode().getName(), profiledClassList[i].profiledClass, J9UTF8_LENGTH(profiledClassName), J9UTF8_DATA(profiledClassName), profiledClassList[i].frequency);1416}1417}1418}14191420TR_OpaqueClassBlock *singleImplementerClass = NULL;14211422// If the caller doesn't provide the output param don't bother with guessing.1423//1424if ((!cg->comp()->compileRelocatableCode() || cg->comp()->getOption(TR_UseSymbolValidationManager))1425&& compileTimeGuessClass1426&& !TR::Compiler->cls.isConcreteClass(cg->comp(), castClass))1427{1428// Figuring out that an interface/abstract class has a single concrete implementation is not as useful for instanceof as it is for checkcast.1429// For checkcast we expect the cast to succeed and the single concrete implementation is the logical class to do a quick up front test against.1430// For instanceof false can be a common result and the single concrete implementation doesn't tell us anything special.1431//1432if (!isInstanceOf)1433{1434singleImplementerClass = cg->comp()->getPersistentInfo()->getPersistentCHTable()->findSingleConcreteSubClass(castClass, cg->comp());1435if (cg->comp()->getOption(TR_TraceCG))1436{1437if (singleImplementerClass)1438{1439J9UTF8 *singleImplementerClassName = J9ROMCLASS_CLASSNAME(TR::Compiler->cls.romClassOf((TR_OpaqueClassBlock *) singleImplementerClass));1440traceMsg(cg->comp(), "%s: Single implementer for interface/abstract class: [" POINTER_PRINTF_FORMAT "] %.*s\n",1441instanceOfOrCheckCastNode->getOpCode().getName(), singleImplementerClass, J9UTF8_LENGTH(singleImplementerClassName), J9UTF8_DATA(singleImplementerClassName));1442}1443}1444}1445*compileTimeGuessClass = singleImplementerClass;1446}14471448if (TR::Compiler->cls.isClassArray(cg->comp(), castClass))1449{1450if (TR::Compiler->cls.isReferenceArray(cg->comp(), castClass))1451{1452TR_OpaqueClassBlock *componentClass = fej9->getComponentClassFromArrayClass(castClass);1453TR_OpaqueClassBlock *leafClass = fej9->getLeafComponentClassFromArrayClass(castClass);14541455// Cast class is a single dim array of java/lang/Object, all we need to do is check if the object is an array of non-primitives.1456//1457if (cg->comp()->getObjectClassPointer() == componentClass && componentClass == leafClass)1458{1459sequences[i++] = ArrayOfJavaLangObjectTest;1460sequences[i++] = GoToFalse;1461}1462// Cast class is a single dim array of a final class, all we need to do is check if the object is of this type, anything else is false.1463//1464else if (fej9->isClassFinal(componentClass) && componentClass == leafClass)1465{1466sequences[i++] = ClassEqualityTest;1467sequences[i++] = GoToFalse;1468}1469// Cast class is an array of some non-final class or multiple dimensions.1470//1471else1472{1473if (numProfiledClasses > 0)1474{1475if (!*topClassWasCastClass)1476{1477sequences[i++] = ProfiledClassTest;1478sequences[i++] = CastClassCacheTest;1479}1480else1481{1482sequences[i++] = ClassEqualityTest;1483sequences[i++] = ProfiledClassTest;1484sequences[i++] = CastClassCacheTest;1485}1486}1487else1488{1489sequences[i++] = ClassEqualityTest;1490sequences[i++] = CastClassCacheTest;1491}14921493sequences[i++] = HelperCall;1494}1495}1496// Cast class is an array of some primitive, all we need to do is check if the object is of this type, anything else is false.1497//1498else1499{1500sequences[i++] = ClassEqualityTest;1501sequences[i++] = GoToFalse;1502}1503}1504// Cast class is an interface, we can skip the class equality test.1505//1506else if (TR::Compiler->cls.isInterfaceClass(cg->comp(), castClass))1507{1508if (singleImplementerClass)1509{1510sequences[i++] = CompileTimeGuessClassTest;1511}1512else if (numProfiledClasses > 0)1513{1514sequences[i++] = ProfiledClassTest;1515sequences[i++] = CastClassCacheTest;1516}1517else1518{1519sequences[i++] = CastClassCacheTest;1520}1521if (createDynamicCacheTests)1522sequences[i++] = DynamicCacheObjectClassTest;1523sequences[i++] = HelperCall;1524}1525// Cast class is an abstract class, we can skip the class equality test, a superclass test is enough.1526//1527else if (fej9->isAbstractClass(castClass))1528{1529// Don't bother with the cast class cache, it's not updated by the VM when the cast can be determined via a superclass test.1530//1531if (singleImplementerClass)1532sequences[i++] = CompileTimeGuessClassTest;1533else if (numProfiledClasses > 0)1534sequences[i++] = ProfiledClassTest;15351536sequences[i++] = SuperClassTest;1537sequences[i++] = GoToFalse;1538}1539// Cast class is a final class, all we need to do is check if the object is of this type, anything else is false.1540//1541else if (fej9->isClassFinal(castClass))1542{1543sequences[i++] = ClassEqualityTest;1544sequences[i++] = GoToFalse;1545}1546// Arbitrary concrete class.1547//1548else1549{1550// Don't bother with the cast class cache, it's not updated by the VM when the cast can be determined via a superclass test.1551//1552if (numProfiledClasses > 0)1553{1554if (!*topClassWasCastClass)1555{1556sequences[i++] = ProfiledClassTest;1557sequences[i++] = ClassEqualityTest;1558}1559else1560{1561sequences[i++] = ClassEqualityTest;1562sequences[i++] = ProfiledClassTest;1563}1564}1565else1566{1567sequences[i++] = ClassEqualityTest;1568}15691570sequences[i++] = SuperClassTest;1571sequences[i++] = GoToFalse;1572}1573}1574}15751576// Insert LoadObjectClass and/or EvaluateCastClass where required.1577//1578bool objectClassLoaded = false;1579bool castClassEvaluated = false;15801581for (uint32_t j = 0; j < i; ++j)1582{1583InstanceOfOrCheckCastSequences s = sequences[j];1584if (s == EvaluateCastClass)1585{1586castClassEvaluated = true;1587}1588else if (s == LoadObjectClass)1589{1590objectClassLoaded = true;1591}1592else1593{1594if (s == ProfiledClassTest ||1595s == CompileTimeGuessClassTest ||1596s == ArrayOfJavaLangObjectTest ||1597s == ClassEqualityTest ||1598s == SuperClassTest ||1599s == CastClassCacheTest)1600{1601if (!objectClassLoaded)1602{1603memmove(&sequences[j + 1], &sequences[j], (i - j) * sizeof(InstanceOfOrCheckCastSequences));1604sequences[j] = LoadObjectClass;1605i += 1;1606objectClassLoaded = true;1607}1608}1609// Even though the helper call also needs the cast class, we expect to generate the helper call out of line1610// and can load it there. Here we just want to know whether the cast class is needed in the main line sequence.1611//1612if (s == ClassEqualityTest ||1613s == SuperClassTest ||1614s == CastClassCacheTest)1615{1616if (!castClassEvaluated)1617{1618// Ideally we would insert EvaluateCastClass at sequences[j], however1619// if the cast class needs to be evaluated it needs to be done before carrying out any tests1620// in order to prevent evaluation inside internal control flow. Therefore,1621// we insert it at the front of the list rather than at 'j'.1622const uint32_t insertAt = 0;1623memmove(&sequences[insertAt + 1], &sequences[insertAt], (i - insertAt) * sizeof(InstanceOfOrCheckCastSequences));1624sequences[insertAt] = EvaluateCastClass;1625i += 1;1626castClassEvaluated = true;1627}1628}1629}1630}16311632TR_ASSERT(sequences[i - 1] == HelperCall ||1633sequences[i - 1] == GoToTrue ||1634sequences[i - 1] == GoToFalse,1635"Expecting last sequence to be a terminal sequence (that provides a definitive answer)");16361637return i;1638}16391640/*1641* if recordAll is true, record all result in classArray, skip MinProfiledCheckcastFrequency check1642* if probability is not null, record class' corresponding probability in this array. Used for cost/benefit analysis for profiled check.1643*/1644uint8_t1645J9::TreeEvaluator::interpreterProfilingInstanceOfOrCheckCastInfo(1646TR::CodeGenerator * cg,1647TR::Node * node,1648TR_OpaqueClassBlock **classArray,1649float* probability,1650bool recordAll)1651{1652TR_ByteCodeInfo bcInfo = node->getByteCodeInfo();1653TR::Compilation *comp = cg->comp();1654TR_ValueProfileInfoManager * valueProfileInfo = TR_ValueProfileInfoManager::get(comp);1655static const char *p = feGetEnv("TR_TracePIC");1656bool p1 = p && comp->getOption(TR_TraceCG); // allow per method tracing16571658if (!valueProfileInfo)1659return 0;16601661TR_AddressInfo * valueInfo = static_cast<TR_AddressInfo*>(valueProfileInfo->getValueInfo(bcInfo, comp, AddressInfo, TR_ValueProfileInfoManager::justInterpreterProfileInfo));1662if (!valueInfo || valueInfo->getNumProfiledValues()==0)1663{1664if (p1) traceMsg(comp, "==TPIC==No IProfiler info on node %p in %s\n", node, comp->signature());1665return 0;1666}16671668TR_OpaqueClassBlock *topValue = (TR_OpaqueClassBlock *) valueInfo->getTopValue();1669if (!topValue)1670{1671if (p1) traceMsg(comp, "==TPIC==No topvalue on node %p in %s\n", node, comp->signature());1672return 0;1673}16741675if ((recordAll == false) && valueInfo->getTopProbability() < TR::Options::getMinProfiledCheckcastFrequency())1676{1677if (p1) traceMsg(comp, "==TPIC==low top probability on node %p in %s\n", node, comp->signature());1678return 0;1679}16801681if (comp->getPersistentInfo()->isObsoleteClass(topValue, cg->fe()))1682{1683if (p1) traceMsg(comp, "==TPIC==%p unloaded on node %p in %s\n", topValue, node, comp->signature());1684return 0;1685}16861687uintptr_t totalFrequency = valueInfo->getTotalFrequency();1688TR_ScratchList<TR_ExtraAddressInfo> valuesSortedByFrequency(comp->trMemory());1689valueInfo->getSortedList(comp, &valuesSortedByFrequency);16901691ListIterator<TR_ExtraAddressInfo> sortedValuesIt(&valuesSortedByFrequency);1692TR_ExtraAddressInfo *profiledInfo;1693uint8_t number = 0;1694for (profiledInfo = sortedValuesIt.getFirst(); profiledInfo != NULL; profiledInfo = sortedValuesIt.getNext())1695{1696TR_OpaqueClassBlock * classPointer = (TR_OpaqueClassBlock *)(profiledInfo->_value);1697if (!classPointer)1698continue;16991700if (comp->getPersistentInfo()->isObsoleteClass((void *)classPointer, cg->fe()))1701{1702return 0;1703}17041705TR_OpaqueClassBlock *thisType = cg->fej9()->getProfiledClassFromProfiledInfo(profiledInfo);1706if (!thisType)1707continue;1708if (p1)1709{1710char *name;1711int32_t len;1712name = comp->fej9()->getClassNameChars(thisType, len);1713traceMsg(comp, "==TPIC==Freq %d (%.2f%%) %.*s @ %p\n", profiledInfo->_frequency, (float) profiledInfo->_frequency/totalFrequency, len, name, thisType); fflush(stdout);1714}1715if ((recordAll == false) && ((float) profiledInfo->_frequency/totalFrequency) < TR::Options::getMinProfiledCheckcastFrequency())1716continue;17171718classArray[number] = thisType;1719if (probability)1720{1721probability[number] = ((float)profiledInfo->_frequency)/totalFrequency;1722}1723number++;1724}1725return number;1726}172717281729TR_OpaqueClassBlock *1730J9::TreeEvaluator::interpreterProfilingInstanceOfOrCheckCastInfo(TR::CodeGenerator * cg, TR::Node * node)1731{1732TR::Compilation *comp= cg->comp();1733TR_ByteCodeInfo bcInfo = node->getByteCodeInfo();1734TR_ValueProfileInfoManager * valueProfileInfo = TR_ValueProfileInfoManager::get(comp);17351736if (!valueProfileInfo)1737return NULL;17381739TR_AddressInfo * valueInfo = static_cast<TR_AddressInfo*>(valueProfileInfo->getValueInfo(bcInfo, comp, AddressInfo, TR_ValueProfileInfoManager::justInterpreterProfileInfo));1740if (!valueInfo || valueInfo->getNumProfiledValues()==0)1741{1742return NULL;1743}17441745TR_OpaqueClassBlock *topValue = (TR_OpaqueClassBlock *) valueInfo->getTopValue();1746if (!topValue)1747{1748return NULL;1749}17501751if (valueInfo->getTopProbability() < TR::Options::getMinProfiledCheckcastFrequency())1752return NULL;17531754if (comp->getPersistentInfo()->isObsoleteClass(topValue, cg->fe()))1755{1756return NULL;1757}17581759return topValue;1760}176117621763bool1764J9::TreeEvaluator::checkcastShouldOutlineSuperClassTest(TR::Node *node, TR::CodeGenerator *cg)1765{1766// caller should always first call instanceOfOrCheckCastNeedSuperTest1767TR::Node *castClassNode = node->getSecondChild();1768TR::MethodSymbol *helperSym = node->getSymbol()->castToMethodSymbol();1769TR::SymbolReference *castClassSymRef = castClassNode->getSymbolReference();1770TR_ByteCodeInfo bcInfo = node->getByteCodeInfo();1771TR::Compilation *comp= cg->comp();17721773TR_ValueProfileInfoManager * valueProfileInfo = TR_ValueProfileInfoManager::get(comp);17741775if (castClassSymRef->isUnresolved())1776{1777return false;1778}17791780if (!TR::TreeEvaluator::isStaticClassSymRef(castClassSymRef))1781{1782// We could theoretically do a super test on something with no sym, but it would require significant1783// changes to platform code. The benefit is little at this point (shows up from reference arraycopy reductions)1784return false;1785}17861787TR::StaticSymbol *castClassSym = castClassSymRef->getSymbol()->getStaticSymbol();17881789if (!valueProfileInfo)1790return false;17911792TR_AddressInfo * valueInfo = static_cast<TR_AddressInfo*>(valueProfileInfo->getValueInfo(bcInfo, comp, AddressInfo, TR_ValueProfileInfoManager::justInterpreterProfileInfo));17931794if (!valueInfo || valueInfo->getNumProfiledValues()==0)1795{1796return false;1797}17981799TR_OpaqueClassBlock *topValue = (TR_OpaqueClassBlock *) valueInfo->getTopValue();18001801if (!topValue)1802{1803return false;1804}18051806if (valueInfo->getTopProbability() < TR::Options::getMinProfiledCheckcastFrequency())1807return false;18081809if (comp->getPersistentInfo()->isObsoleteClass(topValue, cg->fe()))1810{1811return false;1812}18131814if (topValue == (TR_OpaqueClassBlock *) castClassSym->getStaticAddress())1815{1816return true;1817}18181819return false;1820}182118221823bool1824J9::TreeEvaluator::loadLookaheadAfterHeaderAccess(TR::Node *node, int32_t &fieldOffset, TR::CodeGenerator *cg)1825{1826TR::Node *object = node->getFirstChild();18271828TR::TreeTop *currTree = cg->getCurrentEvaluationTreeTop()->getNextTreeTop();1829while (currTree)1830{1831TR::Node *currNode = currTree->getNode();1832if (currNode->getOpCodeValue() == TR::aloadi || currNode->getOpCodeValue() == TR::iloadi)1833{1834if (currNode->getFirstChild() == object)1835{1836int displacement = 0;1837TR::Symbol *sym = currNode->getSymbolReference()->getSymbol();1838if (sym)1839{1840if (sym->isRegisterMappedSymbol() &&1841sym->getRegisterMappedSymbol()->getOffset() != 0)1842{1843displacement = sym->getRegisterMappedSymbol()->getOffset();1844}1845}184618471848fieldOffset = displacement + currNode->getSymbolReference()->getOffset();1849return true;1850}1851}1852else if (currNode->getNumChildren() > 0 &&1853currNode->getFirstChild()->getNumChildren() > 0 &&1854(currNode->getFirstChild()->getOpCodeValue() == TR::aloadi || currNode->getFirstChild()->getOpCodeValue() == TR::iloadi))1855{1856if (currNode->getFirstChild()->getFirstChild() == object)1857{1858int displacement = 0;1859TR::Symbol *sym = currNode->getFirstChild()->getSymbolReference()->getSymbol();1860if (sym)1861{1862if (sym->isRegisterMappedSymbol() &&1863sym->getRegisterMappedSymbol()->getOffset() != 0)1864{1865displacement = sym->getRegisterMappedSymbol()->getOffset();1866}1867}18681869fieldOffset = displacement + currNode->getFirstChild()->getSymbolReference()->getOffset();1870return true;1871}1872}1873currTree = currTree->getNextTreeTop();1874}18751876return false;1877}187818791880// only need a helper call if the class is not super and not final, otherwise1881// it can be determined without a call-out1882bool J9::TreeEvaluator::instanceOfNeedHelperCall(bool testCastClassIsSuper, bool isFinalClass)1883{1884return !testCastClassIsSuper && !isFinalClass;1885}188618871888bool J9::TreeEvaluator::instanceOfOrCheckCastIsJavaLangObjectArray(TR::Node * node, TR::CodeGenerator *cg)1889{1890TR::Node *castClassNode = node->getSecondChild();1891TR::SymbolReference *castClassSymRef = castClassNode->getSymbolReference();18921893if (!TR::TreeEvaluator::isStaticClassSymRef(castClassSymRef))1894{1895return false;1896}18971898TR::StaticSymbol *castClassSym = castClassSymRef->getSymbol()->getStaticSymbol();18991900if (castClassSymRef->isUnresolved())1901{1902return false;1903}1904else1905{1906TR_OpaqueClassBlock * clazz;1907if (castClassSym &&1908(clazz = (TR_OpaqueClassBlock *) castClassSym->getStaticAddress()) &&1909TR::Compiler->cls.isClassArray(cg->comp(), clazz))1910{1911TR_OpaqueClassBlock *objectClass = cg->fej9()->getSystemClassFromClassName("java/lang/Object", 16);1912clazz = cg->fej9()->getComponentClassFromArrayClass(clazz);1913return (objectClass) && objectClass == clazz;1914}1915}1916return false;1917}191819191920TR_OpaqueClassBlock *1921J9::TreeEvaluator::getCastClassAddress(TR::Node * castClassNode)1922{1923TR::SymbolReference * symRef = castClassNode->getSymbolReference();1924if (!TR::TreeEvaluator::isStaticClassSymRef(symRef))1925{1926return NULL;1927}19281929TR::Symbol * symbol = symRef->getSymbol();19301931if (symRef->isUnresolved())1932{1933return NULL; // node is unresolved - class address not known yet1934}1935TR_OpaqueClassBlock * staticAddressValue = (TR_OpaqueClassBlock*) symbol->castToStaticSymbol()->getStaticAddress();1936return staticAddressValue;1937}193819391940/*1941* return true if instanceof/checkcast's checking class is final array1942*/1943bool1944J9::TreeEvaluator::instanceOfOrCheckCastIsFinalArray(TR::Node * node, TR::CodeGenerator *cg)1945{1946TR::Node *castClassNode = node->getSecondChild();1947TR::SymbolReference *castClassSymRef = castClassNode->getSymbolReference();19481949if (!TR::TreeEvaluator::isStaticClassSymRef(castClassSymRef))1950{1951return false;1952}19531954TR::StaticSymbol *castClassSym = castClassSymRef->getSymbol()->getStaticSymbol();19551956if (castClassSymRef->isUnresolved())1957{1958return false;1959}1960else1961{1962TR_OpaqueClassBlock * clazz;1963// If the class is a regular class (i.e., not an interface nor an array) and1964// not known to be a final class, an inline superclass test can be generated.1965// If the helper does not preserve all the registers there will not be1966// enough registers to do the superclass test inline.1967// Also, don't generate the superclass test if optimizing for space.1968//1969if (castClassSym &&1970(clazz = (TR_OpaqueClassBlock *) castClassSym->getStaticAddress()) &&1971TR::Compiler->cls.isClassArray(cg->comp(), clazz) &&1972(clazz = cg->fej9()->getLeafComponentClassFromArrayClass(clazz)) &&1973(cg->fej9()->isClassFinal(clazz) || TR::Compiler->cls.isPrimitiveClass(cg->comp(), clazz))1974)1975return true;1976}1977return false;1978}197919801981void1982J9::TreeEvaluator::evaluateLockForReservation(TR::Node *node, bool *reservingLock, bool *normalLockPreservingReservation, TR::CodeGenerator *cg)1983{1984static const char *allPreserving = feGetEnv("TR_AllLocksPreserving");1985TR::Compilation *comp= cg->comp();19861987if (!node->isSyncMethodMonitor())1988{1989*reservingLock = false;1990*normalLockPreservingReservation = false;1991return;1992}19931994if (comp->getOption(TR_ReserveAllLocks))1995{1996*reservingLock = true;1997*normalLockPreservingReservation = false;1998return;1999}20002001if (allPreserving)2002{2003*reservingLock = false;2004*normalLockPreservingReservation = true;2005return;2006}20072008TR_OpaqueMethodBlock *owningMethod = node->getOwningMethod();2009TR_OpaqueClassBlock *classPointer = cg->fej9()->getClassOfMethod(owningMethod);2010TR_PersistentClassInfo * persistentClassInfo =2011comp->getPersistentInfo()->getPersistentCHTable()->findClassInfoAfterLocking(classPointer, comp);20122013if (persistentClassInfo && persistentClassInfo->isReservable())2014{2015if (comp->getMethodHotness() >= warm)2016*reservingLock = true;2017else2018*normalLockPreservingReservation = true;2019}2020}2021202220232024static TR::Node *scanForMonitorExitNode(TR::TreeTop *firstTree)2025{2026TR::TreeTop *currTree = firstTree;2027while (currTree)2028{2029TR::Node *currNode = currTree->getNode();2030if (currNode->getOpCodeValue() == TR::monexit)2031{2032if (currNode->isSyncMethodMonitor())2033return currNode;2034else2035return NULL;2036}2037else if (currNode->getNumChildren() > 0 &&2038currNode->getFirstChild()->getNumChildren() > 0 &&2039currNode->getFirstChild()->getOpCodeValue() == TR::monexit)2040{2041if (currNode->getFirstChild()->isSyncMethodMonitor())2042return currNode->getFirstChild();2043else2044return NULL;2045}20462047if ((currNode->getOpCodeValue() == TR::monent ||2048currNode->exceptionsRaised() != 0 ||2049currNode->canCauseGC() ||2050currNode->getOpCode().isBranch()))2051{2052return NULL;2053}20542055currTree = currTree->getNextTreeTop();2056}20572058return NULL;2059}206020612062bool2063J9::TreeEvaluator::isPrimitiveMonitor(TR::Node *monNode, TR::CodeGenerator *cg)2064{2065// TODO: enable primitive monitors once we have the standard ones working2066// The primitive monitors will need separate monexit helper where the2067// recursive count is incremented in case FLC is set. The state of RES and FLC set2068// while the count is 0 is illegal.2069static const char *allReservingPrimitive = feGetEnv("TR_AllLocksReservingPrimitive");2070static const char *noReservingPrimitiveLocks = feGetEnv("TR_NoReservingPrimitiveLocks");20712072if (allReservingPrimitive)2073return true;20742075if (noReservingPrimitiveLocks)2076return false;20772078TR::Node *object = monNode->getFirstChild();20792080TR_ASSERT(monNode->getOpCodeValue() == TR::monent, "Primitive monitor region check should only be done on monitor enter node");20812082TR::Node *guardExit = NULL;20832084TR::TreeTop *currTree = cg->getCurrentEvaluationTreeTop()->getNextTreeTop();2085while (currTree)2086{2087TR::Node *currNode = currTree->getNode();2088if (currNode->getOpCodeValue() == TR::monexit)2089{2090if (currNode->getFirstChild() == object)2091{2092monNode->setPrimitiveLockedRegion();2093currNode->setPrimitiveLockedRegion();20942095if (guardExit != NULL)2096{2097guardExit->setPrimitiveLockedRegion();2098}2099return true;2100}2101else2102return false;2103}2104else if (currNode->getNumChildren() > 0 &&2105currNode->getFirstChild()->getNumChildren() > 0 &&2106currNode->getFirstChild()->getOpCodeValue() == TR::monexit)2107{2108if (currNode->getFirstChild()->getFirstChild() == object)2109{2110monNode->setPrimitiveLockedRegion();2111currNode->getFirstChild()->setPrimitiveLockedRegion();21122113if (guardExit != NULL)2114{2115guardExit->setPrimitiveLockedRegion();2116}2117return true;2118}2119else2120return false;2121}21222123if ((currNode->getOpCodeValue() == TR::monent ||2124currNode->exceptionsRaised() != 0 ||2125currNode->canCauseGC() ||2126currNode->getOpCode().isBranch() ||2127(currNode->getOpCodeValue() == TR::BBStart && !currNode->getBlock()->isExtensionOfPreviousBlock())2128))2129{2130if ((currNode->getOpCode().isIf() && currNode->isNonoverriddenGuard()))2131{2132guardExit = scanForMonitorExitNode( currNode->getBranchDestination());21332134if (!guardExit && monNode->isSyncMethodMonitor())2135return false;2136}2137else2138return false;2139}21402141currTree = currTree->getNextTreeTop();2142}21432144return false;2145}21462147bool2148J9::TreeEvaluator::isDummyMonitorEnter(TR::Node *monNode, TR::CodeGenerator *cg)2149{2150TR::Node *object = monNode->getFirstChild();21512152TR_ASSERT(monNode->getOpCodeValue() == TR::monent, "Primitive monitor region check should only be done on monitor enter node");21532154TR::Node *guardExit = NULL;21552156TR::TreeTop *currTree = cg->getCurrentEvaluationTreeTop()->getNextTreeTop();2157TR::Node *currNode = currTree->getNode();215821592160if (currNode->getOpCode().isIf() && currNode->isNonoverriddenGuard() && monNode->isSyncMethodMonitor())2161{2162guardExit = scanForMonitorExitNode(currNode->getBranchDestination());21632164if (!guardExit)2165return false;21662167currTree = currTree->getNextTreeTop();2168}21692170if (currTree)2171{2172currNode = currTree->getNode();2173if (currNode->getOpCodeValue() == TR::monexit)2174{2175if (currNode->getFirstChild() == object)2176{2177return true;2178}2179else2180return false;2181}2182else if (currNode->getNumChildren() > 0 &&2183currNode->getFirstChild()->getNumChildren() > 0 &&2184currNode->getFirstChild()->getOpCodeValue() == TR::monexit)2185{2186if (currNode->getFirstChild()->getFirstChild() == object)2187{2188return true;2189}2190else2191return false;2192}2193}21942195return false;2196}21972198bool2199J9::TreeEvaluator::isDummyMonitorExit(TR::Node *monNode, TR::CodeGenerator *cg)2200{2201TR::Node *object = monNode->getFirstChild();22022203TR_ASSERT(monNode->getOpCodeValue() == TR::monexit, "Primitive monitor region check should only be done on monitor exit node");22042205TR::TreeTop *currTree = cg->getCurrentEvaluationTreeTop()->getPrevTreeTop();2206TR::Node *currNode = currTree->getNode();22072208if (currNode->getOpCode().isIf() && currNode->isNonoverriddenGuard() && monNode->isSyncMethodMonitor())2209{2210currTree = currTree->getPrevTreeTop();2211}22122213if (currTree)2214{2215currNode = currTree->getNode();2216if (currNode->getOpCodeValue() == TR::monent)2217{2218if (currNode->getFirstChild() == object)2219{2220return true;2221}2222else2223return false;2224}2225else if (currNode->getNumChildren() > 0 &&2226currNode->getFirstChild()->getNumChildren() > 0 &&2227currNode->getFirstChild()->getOpCodeValue() == TR::monent)2228{2229if (currNode->getFirstChild()->getFirstChild() == object)2230{2231return true;2232}2233else2234return false;2235}2236}22372238return false;2239}224022412242// Helper Functions for BNDCHKwithSpineCHK22432244// Evaluate all subtrees whose first reference is under the root node and whose2245// last reference is not.2246//2247// Evaluate every subtree S of a node N that meets the following criteria:2248//2249// (1) the first reference to S is in a subtree of N, and2250// (2) not all references to S appear under N2251//2252// All subtrees will be evaluated as soon as they are discovered.2253//2254//2255// TODO: do not pre-evaluate nodes under a spinechk if all other references are also under2256// a spinechk (there could be some complications here though).2257//2258void J9::TreeEvaluator::preEvaluateEscapingNodesForSpineCheck(TR::Node *root, TR::CodeGenerator *cg)2259{2260TR::TreeEvaluator::initializeStrictlyFutureUseCounts(root, cg->comp()->incVisitCount(), cg);2261TR::TreeEvaluator::evaluateNodesWithFutureUses(root, cg);2262}226322642265///////////////////////////////////////////////////////////////////////////////////////2266// resolveCHKEvaluator - Resolve check a static, field or method. child 1 is reference2267// to be resolved. Symbolref indicates failure action/destination2268///////////////////////////////////////////////////////////////////////////////////////2269TR::Register *J9::TreeEvaluator::resolveCHKEvaluator(TR::Node *node, TR::CodeGenerator *cg)2270{2271// No code is generated for the resolve check. The child will reference an2272// unresolved symbol and all check handling is done via the corresponding2273// snippet.2274//2275TR::Node *firstChild = node->getFirstChild();2276cg->evaluate(firstChild);2277cg->decReferenceCount(firstChild);2278return NULL;2279}228022812282bool2283J9::TreeEvaluator::requireHelperCallValueTypeAllocation(TR::Node *node, TR::CodeGenerator *cg)2284{2285if (TR::Compiler->om.areValueTypesEnabled() && node->getOpCodeValue() == TR::New)2286{2287TR::Compilation *comp = cg->comp();2288TR::SymbolReference *newValueSymRef = comp->getSymRefTab()->findOrCreateNewValueSymbolRef(comp->getMethodSymbol());2289TR::SymbolReference *nodeSymRef = node->getSymbolReference();2290TR::SymbolReference *classSymRef = node->getFirstChild()->getSymbolReference();22912292TR_OpaqueClassBlock *clazz = NULL;2293if (!classSymRef->isUnresolved())2294clazz = (TR_OpaqueClassBlock *)classSymRef->getSymbol()->getStaticSymbol()->getStaticAddress();22952296bool isValueTypeClass = clazz ? TR::Compiler->cls.isValueTypeClass(clazz) : false;22972298// If "new jitNewValue" is used to create a non value type, or if "new jitNewObject" is used to2299// create a value type, InstantiationError exception needs to be thrown. Use helper call in these cases.2300if (((nodeSymRef == newValueSymRef) && !isValueTypeClass)2301|| ((nodeSymRef != newValueSymRef) && isValueTypeClass))2302{2303return true;2304}2305}2306return false;2307}230823092310