You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by mf...@apache.org on 2007/07/18 16:45:44 UTC
svn commit: r557277 - in /harmony/enhanced/drlvm/trunk/vm/jitrino/src:
codegenerator/ia32/ main/ optimizer/
Author: mfursov
Date: Wed Jul 18 07:45:43 2007
New Revision: 557277
URL: http://svn.apache.org/viewvc?view=rev&rev=557277
Log:
Fix for HARMONY-3817
New feature: pragma @Inline support in Jitrino.OPT: HARMONY-4475
Modified:
harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32CodeEmitter.cpp
harmony/enhanced/drlvm/trunk/vm/jitrino/src/main/CompilationContext.cpp
harmony/enhanced/drlvm/trunk/vm/jitrino/src/main/CompilationContext.h
harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/escanalyzer.cpp
harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/helper_inliner.cpp
harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/inliner.cpp
harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/inliner.h
Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32CodeEmitter.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32CodeEmitter.cpp?view=diff&rev=557277&r1=557276&r2=557277
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32CodeEmitter.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32CodeEmitter.cpp Wed Jul 18 07:45:43 2007
@@ -474,6 +474,7 @@
// if the inst is the only in the bb)
Inst* nopInst = irManager->newInst(Mnemonic_NOP);
bb->prependInst(nopInst,inst);
+ nopInst->setCodeOffset( (uint32)(ip-blockStartIp) );
ip = nopInst->emit(ip);
// the last two
ip = (uint8*)EncoderBase::nops((char*)ip,2);
@@ -919,7 +920,19 @@
if (methMarkerInst != NULL) { // inlined locations for methMarkerInst
assert(methInfo == methodLocationMap[methMarkerInst]);
if( ! inst->hasKind(Inst::Kind_PseudoInst)) {
- instSizeMap[(POINTER_SIZE_INT) inst->getCodeStartAddr()] = inst->getCodeSize();
+ POINTER_SIZE_INT instAddr = (POINTER_SIZE_INT)inst->getCodeStartAddr();
+ POINTER_SIZE_INT nextAddr = (POINTER_SIZE_INT)inst->getNext()->getCodeStartAddr();
+ uint32 instSize = inst->getCodeSize();
+ if (inst->getMnemonic() == Mnemonic_NOP && instAddr+instSize < nextAddr) {
+ // there is a special case when code patching support generates 3 (ia32) or 13 (em64t) nops
+ // before calls for future runtime patching. First nop is generated as a common CFG inst.
+ // The rest ones are generated directly to the memory using encoder.
+ // Taking this into account:
+ assert(nextAddr > instAddr);
+ instSizeMap[instAddr] = nextAddr-instAddr;
+ } else {
+ instSizeMap[instAddr] = instSize;
+ }
}
uint16 bcOffset = inst->getBCOffset();
methInfo->includeInst(inst,bcOffset);
Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/src/main/CompilationContext.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/src/main/CompilationContext.cpp?view=diff&rev=557277&r1=557276&r2=557277
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/src/main/CompilationContext.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/main/CompilationContext.cpp Wed Jul 18 07:45:43 2007
@@ -38,13 +38,6 @@
init();
}
-CompilationContext::CompilationContext(MemoryManager& _mm, CompilationInterface* ci, const CompilationContext* cc)
-: mm(_mm), compilationInterface(ci), jitContext(cc->getCurrentJITContext())
-{
- init();
- pipeline = cc->pipeline;
-}
-
void CompilationContext::init()
{
compilationFailed = compilationFinished = false;
Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/src/main/CompilationContext.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/src/main/CompilationContext.h?view=diff&rev=557277&r1=557276&r2=557277
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/src/main/CompilationContext.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/main/CompilationContext.h Wed Jul 18 07:45:43 2007
@@ -47,7 +47,6 @@
// Exists only during a compilation of method
// This class uses destructor and must not be created on MemoryManager
CompilationContext(MemoryManager& mm, CompilationInterface* ci, JITInstanceContext* jit);
- CompilationContext(MemoryManager& mm, CompilationInterface* ci, const CompilationContext* cc);
~CompilationContext();
CompilationInterface* getVMCompilationInterface() const {return compilationInterface;}
Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/escanalyzer.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/escanalyzer.cpp?view=diff&rev=557277&r1=557276&r2=557277
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/escanalyzer.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/escanalyzer.cpp Wed Jul 18 07:45:43 2007
@@ -2347,7 +2347,8 @@
}
{
- CompilationContext inlineCC(irManager.getMemoryManager(), &ci, ci.getCompilationContext());
+ CompilationContext inlineCC(irManager.getMemoryManager(), &ci, irManager.getCurrentJITContext());
+ inlineCC.setPipeline(irManager.getCompilationContext()->getPipeline());
inlineCC.setHIRManager(inlinedIRM);
runTranslatorSession(inlineCC);
}
Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/helper_inliner.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/helper_inliner.cpp?view=diff&rev=557277&r1=557276&r2=557277
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/helper_inliner.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/helper_inliner.cpp Wed Jul 18 07:45:43 2007
@@ -27,8 +27,6 @@
namespace Jitrino {
-#define PRAGMA_INLINE "org/vmmagic/pragma/Inline"
-
struct HelperInlinerFlags {
const char* inlinerPipelineName;
@@ -118,7 +116,7 @@
public:
HelperInliner(HelperInlinerSession* _sessionAction, MemoryManager& tmpMM, CompilationContext* _cc, Inst* _inst)
: flags(((HelperInlinerAction*)_sessionAction->getAction())->getFlags()), localMM(tmpMM),
- cc(_cc), inst(_inst), session(_sessionAction), method(NULL), inlinePragma(NULL)
+ cc(_cc), inst(_inst), session(_sessionAction), method(NULL)
{
irm = cc->getHIRManager();
instFactory = &irm->getInstFactory();
@@ -142,8 +140,7 @@
Inst* inst;
HelperInlinerSession* session;
MethodDesc* method;
- NamedType* inlinePragma;
-
+
//these fields used by almost every subclass -> cache them
IRManager* irm;
InstFactory* instFactory;
@@ -164,11 +161,6 @@
}\
method = ensureClassIsResolvedAndInitialized(flags.flagPrefix##_className, flags.flagPrefix##_methodName, flags.flagPrefix##_signature);\
if (!method) return;\
- if (!inlinePragma) { \
- inlinePragma = cc->getVMCompilationInterface()->resolveClassUsingBootstrapClassloader(PRAGMA_INLINE);\
- } \
- if (!inlinePragma) return;\
- \
doInline();\
}\
virtual void doInline();\
@@ -189,6 +181,10 @@
HelperInlinerAction* action = (HelperInlinerAction*)getAction();
HelperInlinerFlags& flags = action->getFlags();
+ if (cc->getVMCompilationInterface()->resolveClassUsingBootstrapClassloader(PRAGMA_INLINE) == NULL) {
+ Log::out()<<"Helpers inline pass failed! class not found: "<<PRAGMA_INLINE<<std::endl;
+ return;
+ }
//finding all helper calls
ControlFlowGraph& fg = irm.getFlowGraph();
double entryExecCount = fg.hasEdgeProfile() ? fg.getEntryNode()->getExecCount(): 1;
@@ -285,55 +281,13 @@
typedef StlVector<MethodCallInst*> InlineVector;
-void HelperInliner::inlineVMHelper(MethodCallInst* origCall) {
- assert(inlinePragma!=0);
-
- InlineVector methodsToInline(localMM);
- methodsToInline.push_back(origCall);
- while (!methodsToInline.empty()) {
- MethodCallInst* call = *methodsToInline.rbegin();
- methodsToInline.pop_back();
- if (Log::isEnabled()) {
- Log::out()<<"Inlining VMHelper:";call->print(Log::out());Log::out()<<std::endl;
- }
-
- CompilationInterface* ci = cc->getVMCompilationInterface();
-
- //now inline the call
- CompilationContext inlineCC(cc->getCompilationLevelMemoryManager(), ci, cc->getCurrentJITContext());
- inlineCC.setPipeline(cc->getPipeline());
-
- Inliner inliner(session, localMM, *irm, false);
- InlineNode* regionToInline = inliner.createInlineNode(inlineCC, call);
-
- inliner.connectRegion(regionToInline);
-
- // Optimize inlined region before splicing
- inlineCC.stageId = cc->stageId;
- Inliner::runInlinerPipeline(inlineCC, flags.inlinerPipelineName);
- cc->stageId = inlineCC.stageId;
-
- //add all methods with pragma inline into the list.
- const Nodes& nodesInRegion = regionToInline->getIRManager().getFlowGraph().getNodes();
- for (Nodes::const_iterator it = nodesInRegion.begin(), end = nodesInRegion.end(); it!=end; ++it) {
- Node* node = *it;
- for (Inst* inst = (Inst*)node->getFirstInst(); inst!=NULL; inst = inst->getNextInst()) {
- if (inst->isMethodCall()) {
- MethodCallInst* methodCall = inst->asMethodCallInst();
- MethodDesc* md = methodCall->getMethodDesc();
- if (md->hasAnnotation(inlinePragma)) {
- methodsToInline.push_back(methodCall);
- if (Log::isEnabled()) {
- Log::out()<<"Found Inline pragma, adding to the queue:";methodCall->print(Log::out());Log::out()<<std::endl;
- }
- }
- }
- }
- }
-
- //inline the region
- inliner.inlineRegion(regionToInline, false);
+void HelperInliner::inlineVMHelper(MethodCallInst* call) {
+ if (Log::isEnabled()) {
+ Log::out()<<"Inlining VMHelper:";call->print(Log::out());Log::out()<<std::endl;
}
+
+ Inliner inliner(session, localMM, *irm, false, false, flags.inlinerPipelineName);
+ inliner.doInline(localMM, call);
}
void HelperInliner::finalizeCall(MethodCallInst* callInst) {
Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/inliner.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/inliner.cpp?view=diff&rev=557277&r1=557276&r2=557277
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/inliner.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/inliner.cpp Wed Jul 18 07:45:43 2007
@@ -68,7 +68,8 @@
DEFINE_SESSION_ACTION(InlinePass, inline, "Method Inlining");
-Inliner::Inliner(SessionAction* argSource, MemoryManager& mm, IRManager& irm, bool doProfileOnly)
+Inliner::Inliner(SessionAction* argSource, MemoryManager& mm, IRManager& irm,
+ bool doProfileOnly, bool _usePriorityQueue, const char* inlinePipeline)
: _tmpMM(mm), _toplevelIRM(irm),
_typeManager(irm.getTypeManager()), _instFactory(irm.getInstFactory()),
_opndManager(irm.getOpndManager()),
@@ -76,7 +77,8 @@
_inlineCandidates(mm), _initByteSize(irm.getMethodDesc().getByteCodeSize()),
_currentByteSize(irm.getMethodDesc().getByteCodeSize()),
_inlineTree(new (mm) InlineNode(irm, 0, 0)),
- translatorAction(NULL)
+ translatorAction(NULL), inlinePragma(NULL),
+ usePriorityQueue(_usePriorityQueue), inlinerPipelineName(inlinePipeline), connectEarly(true)
{
const char* translatorName = argSource->getStringArg("translatorActionName", "translator");
@@ -138,6 +140,8 @@
}
_usesOptimisticBalancedSync = argSource->getBoolArg("sync_optimistic", false) ? argSource->getBoolArg("sync_optcatch", true) : false;
+
+ inlinePragma = irm.getCompilationInterface().resolveClassUsingBootstrapClassloader(PRAGMA_INLINE);
}
int32
@@ -150,6 +154,11 @@
<< methodDesc.getParentType()->getName()
<< "." << methodDesc.getName() << ::std::endl;
}
+ if (inlinePragma!=NULL && methodDesc.hasAnnotation(inlinePragma)) {
+ //methods marked with inline pragma processed separately and are always inlined
+ //regardless of it benefits and size limitations.
+ return -1;
+ }
if (_inlineBonusMethodTable!=NULL && _inlineBonusMethodTable->accept_this_method(methodDesc)) {
benefit+=1000;
if (Log::isEnabled()) {
@@ -791,7 +800,7 @@
}
void
-Inliner::inlineRegion(InlineNode* inlineNode, bool updatePriorityQueue) {
+Inliner::inlineRegion(InlineNode* inlineNode) {
IRManager &inlinedIRM = inlineNode->getIRManager();
DominatorTree* dtree = inlinedIRM.getDominatorTree();
LoopTree* ltree = inlinedIRM.getLoopTree();
@@ -815,7 +824,7 @@
//
// Update priority queue with calls in this region
//
- if (updatePriorityQueue) {
+ if (usePriorityQueue) {
processRegion(inlineNode, dtree, ltree);
}
@@ -865,8 +874,8 @@
inlineCC.setCurrentSessionAction(NULL);
}
-InlineNode*
-Inliner::getNextRegionToInline(CompilationContext& inlineCC) {
+MethodCallInst*
+Inliner::getNextRegionToInline() {
// If in DPGO profiling mode, don't inline if profile information is not available.
if(_doProfileOnlyInlining && !_toplevelIRM.getFlowGraph().hasEdgeProfile()) {
return NULL;
@@ -924,15 +933,8 @@
Log::out() << "Opt: Inline " << methodDesc->getParentType()->getName() << "." << methodDesc->getName() <<
methodDesc->getSignatureString() << ::std::endl;
- // Generate flowgraph for new region
-
- InlineNode* inlineNode = createInlineNode(inlineCC, call);
- assert(inlineNode!=NULL);
-
- inlineParentNode->addChild(inlineNode);
-
_currentByteSize = newByteSize;
- return inlineNode;
+ return call;
}
InlineNode* Inliner::createInlineNode(CompilationContext& inlineCC, MethodCallInst* call) {
@@ -1114,51 +1116,97 @@
}
}
+typedef StlVector<MethodCallInst*> InlineVector;
+
+void Inliner::doInline(MemoryManager& tmpMM, MethodCallInst* origCall) {
+ CompilationContext* topCC = _toplevelIRM.getCompilationContext();
+ CompilationInterface* ci = topCC->getVMCompilationInterface();
+
+ InlineVector pragmaInlineCalls(tmpMM);
+ bool firstIteration = true;
+ do {
+ MethodCallInst* call = NULL;
+ bool rootMethodAnalysis = firstIteration && origCall == NULL;
+ if (firstIteration) {
+ call = origCall;
+ firstIteration = false;
+ } else {
+ call = *pragmaInlineCalls.rbegin();
+ pragmaInlineCalls.pop_back();
+ assert(call!=NULL);
+ }
+
+ InlineNode* ir = NULL;
+ if (!rootMethodAnalysis) { // processing custom call in a method
+ assert(call!=NULL);
+ CompilationContext inlineCC(topCC->getCompilationLevelMemoryManager(), ci, topCC->getCurrentJITContext());
+ inlineCC.setPipeline(topCC->getPipeline());//workaround for logging issue. Pipeline must not be NULL
+ ir = createInlineNode(inlineCC, call);
+ IRManager ®ionManager = ir->getIRManager();
+ assert(inlineCC.getHIRManager() == ®ionManager);
+
+ // Connect region arguments to top-level flowgraph
+ if(connectEarly) {
+ connectRegion(ir);
+ }
+
+ // Optimize inlined region before splicing
+ inlineCC.stageId = topCC->stageId;
+ Inliner::runInlinerPipeline(inlineCC, inlinerPipelineName);
+ topCC->stageId = inlineCC.stageId;
+
+ // Splice into flow graph and find next region.
+ if(!connectEarly) {
+ connectRegion(ir);
+ }
+ OptPass::computeDominatorsAndLoops(regionManager);
+ } else {// processing whole method
+ ir = (InlineNode*)getInlineTree().getRoot();
+ }
+
+ //check all methods with @Inline pragmas
+ const Nodes& nodesInRegion = ir->getIRManager().getFlowGraph().getNodes();
+ for (Nodes::const_iterator it = nodesInRegion.begin(), end = nodesInRegion.end(); it!=end; ++it) {
+ Node* node = *it;
+ for (Inst* inst = (Inst*)node->getFirstInst(); inst!=NULL; inst = inst->getNextInst()) {
+ if (inst->isMethodCall()) {
+ MethodCallInst* methodCall = inst->asMethodCallInst();
+ MethodDesc* md = methodCall->getMethodDesc();
+ if (md->hasAnnotation(inlinePragma)) {
+ assert(!md->isSynchronized()); //not tested!
+ pragmaInlineCalls.push_back(methodCall);
+ if (Log::isEnabled()) {
+ Log::out()<<"Found Inline pragma, adding to the queue:";methodCall->print(Log::out());Log::out()<<std::endl;
+ }
+ }
+ }
+ }
+ }
+ //inline current region
+ inlineRegion(ir);
+ } while (!pragmaInlineCalls.empty());
+}
+
void InlinePass::_run(IRManager& irm) {
computeDominatorsAndLoops(irm);
-
- CompilationContext* cc = getCompilationContext();
- MemoryManager& mm = cc->getCompilationLevelMemoryManager() ;
- CompilationInterface* ci = cc->getVMCompilationInterface();
-
// Set up Inliner
bool connectEarly = getBoolArg("connect_early", true);
const char* pipeName = getStringArg("pipeline", "inliner_pipeline");
MemoryManager tmpMM("Inliner::tmp_mm");
- Inliner inliner(this, tmpMM, irm, irm.getFlowGraph().hasEdgeProfile());
- InlineNode* rootRegionNode = (InlineNode*) inliner.getInlineTree().getRoot();
- inliner.inlineRegion(rootRegionNode);
+ Inliner inliner(this, tmpMM, irm, irm.getFlowGraph().hasEdgeProfile(), true, pipeName);
+ inliner.setConnectEarly(connectEarly);
+ inliner.doInline(tmpMM, NULL);
// Inline calls
do {
- CompilationContext inlineCC(mm, ci, cc);
- InlineNode* regionNode = inliner.getNextRegionToInline(inlineCC);
- if (regionNode == NULL) {
+ MethodCallInst* call = inliner.getNextRegionToInline();
+ if (call == NULL) {
break;
}
- assert(regionNode != rootRegionNode);
- IRManager ®ionManager = regionNode->getIRManager();
- assert(inlineCC.getHIRManager() == ®ionManager);
-
- // Connect region arguments to top-level flowgraph
- if(connectEarly) {
- inliner.connectRegion(regionNode);
- }
-
- // Optimize inlined region before splicing
- inlineCC.stageId = cc->stageId;
- Inliner::runInlinerPipeline(inlineCC, pipeName);
- cc->stageId = inlineCC.stageId;
-
- // Splice into flow graph and find next region.
- if(!connectEarly) {
- inliner.connectRegion(regionNode);
- }
- OptPass::computeDominatorsAndLoops(regionManager);
- inliner.inlineRegion(regionNode);
+ inliner.doInline(tmpMM, call);
} while (true);
const OptimizerFlags& optimizerFlags = irm.getOptimizerFlags();
// Print the results to logging / dot file
Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/inliner.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/inliner.h?view=diff&rev=557277&r1=557276&r2=557277
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/inliner.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/inliner.h Wed Jul 18 07:45:43 2007
@@ -28,6 +28,8 @@
#include "Tree.h"
#include "irmanager.h"
+#define PRAGMA_INLINE "org/vmmagic/pragma/Inline"
+
namespace Jitrino {
class MemoryManager;
@@ -89,19 +91,19 @@
class Inliner
{
public:
- Inliner(SessionAction* argSource, MemoryManager& mm, IRManager& irm, bool doProfileOnly=false);
+ Inliner(SessionAction* argSource, MemoryManager& mm, IRManager& irm,
+ bool doProfileOnly, bool usePriorityQueue, const char* inlinerPipelineName);
// Inline this method into the current CFG and process it for further
// inline candidates. If the argument is the top level CFG, only processing
// occurs.
- void inlineRegion(InlineNode* inlineNode, bool updatePriorityQueue = true);
+ void inlineRegion(InlineNode* inlineNode);
// Connect input and return operands of the region to the top-level method. Do not yet splice.
void connectRegion(InlineNode* inlineNode);
- // Build the flowgraph for the next inline candidate method. Note, this flowgraph
- // is not yet connected to the top level CFG.
- InlineNode* getNextRegionToInline(CompilationContext& inlineCC);
+ // Searches the flowgraph for the next inline candidate method.
+ MethodCallInst* getNextRegionToInline();
InlineTree& getInlineTree() { return _inlineTree; }
@@ -113,6 +115,10 @@
static void runInlinerPipeline(CompilationContext& inlineCC, const char* pipeName);
+ void doInline(MemoryManager& tmpMM, MethodCallInst* call);
+
+ void setConnectEarly(bool early) {connectEarly = early;}
+
private:
class CallSite {
public:
@@ -191,6 +197,10 @@
bool isBCmapRequired;
void* bc2HIRMapHandler;
TranslatorAction* translatorAction;
+ NamedType* inlinePragma;
+ bool usePriorityQueue;
+ const char* inlinerPipelineName;
+ bool connectEarly;
};