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/20 16:36:29 UTC
svn commit: r558008 - in /harmony/enhanced/drlvm/trunk/vm:
jitrino/src/optimizer/helper_inliner.cpp jitrino/src/optimizer/inliner.cpp
jitrino/src/optimizer/inliner.h vmcore/src/jit/jit_runtime_support.cpp
Author: mfursov
Date: Fri Jul 20 07:36:28 2007
New Revision: 558008
URL: http://svn.apache.org/viewvc?view=rev&rev=558008
Log:
Fix for regression introduced by HARMONY-4475
Fix for HARMONY-4507
Modified:
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
harmony/enhanced/drlvm/trunk/vm/vmcore/src/jit/jit_runtime_support.cpp
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=558008&r1=558007&r2=558008
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/helper_inliner.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/helper_inliner.cpp Fri Jul 20 07:36:28 2007
@@ -287,7 +287,7 @@
}
Inliner inliner(session, localMM, *irm, false, false, flags.inlinerPipelineName);
- inliner.doInline(localMM, call);
+ inliner.runInliner(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=558008&r1=558007&r2=558008
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/inliner.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/inliner.cpp Fri Jul 20 07:36:28 2007
@@ -65,6 +65,7 @@
#define INLINE_EXACT_ALL_BONUS 0
#define INLINE_SKIP_EXCEPTION_PATH true
+#define PRAGMA_INLINE_BENEFIT (2*1000*1000*1000)
DEFINE_SESSION_ACTION(InlinePass, inline, "Method Inlining");
@@ -810,35 +811,24 @@
MethodDesc &methodDesc = inlinedIRM.getMethodDesc();
if (Log::isEnabled()) {
- Log::out() << "inlineAndProcessRegion "
- << methodDesc.getParentType()->getName() << "."
- << methodDesc.getName() << ::std::endl;
+ Log::out()<<"inlineAndProcessRegion "<< methodDesc.getParentType()->getName() << "."<< methodDesc.getName()<<std::endl;
}
- //
// Scale block counts in the inlined region for this particular call site
- //
- if (callNode != NULL)
+ if (callNode != NULL) {
scaleBlockCounts(callNode, inlinedIRM);
-
- //
- // Update priority queue with calls in this region
- //
- if (usePriorityQueue) {
- processRegion(inlineNode, dtree, ltree);
}
- //
+ // Update priority queue with calls in this region and check @Inline pragmas
+ processRegion(inlineNode, dtree, ltree);
+
// If top level flowgraph
- //
if (inlineNode == _inlineTree.getRoot()) {
Log::out() << "inlineNode is root" << ::std::endl;
return;
}
- //
// Splice region into top level flowgraph at call site
- //
assert(callInst->getOpcode() == Op_DirectCall);
Log::out() << "Inlining " << methodDesc.getParentType()->getName()
<< "." << methodDesc.getName() << ::std::endl;
@@ -874,8 +864,8 @@
inlineCC.setCurrentSessionAction(NULL);
}
-MethodCallInst*
-Inliner::getNextRegionToInline() {
+InlineNode*
+Inliner::getNextRegionToInline(CompilationContext& inlineCC) {
// If in DPGO profiling mode, don't inline if profile information is not available.
if(_doProfileOnlyInlining && !_toplevelIRM.getFlowGraph().hasEdgeProfile()) {
return NULL;
@@ -895,20 +885,21 @@
// Find new candidate.
callNode = _inlineCandidates.top().callNode;
inlineParentNode = _inlineCandidates.top().inlineNode;
+ int benefit = _inlineCandidates.top().benefit;
_inlineCandidates.pop();
-
+
call = ((Inst*)callNode->getLastInst())->asMethodCallInst();
assert(call != NULL);
methodDesc = call->getMethodDesc();
-
+ bool isPragmaInline = benefit == PRAGMA_INLINE_BENEFIT;
+
// If candidate would cause top level method to exceed size threshold, throw away.
uint32 methodByteSize = methodDesc->getByteCodeSize();
methodByteSize = (methodByteSize <= CALL_COST) ? 1 : methodByteSize-CALL_COST;
newByteSize = _currentByteSize + methodByteSize;
double factor = ((double) newByteSize) / ((double) _initByteSize);
- if(newByteSize < _minInlineStop || factor <= _maxInlineGrowthFactor
- || (methodByteSize < _inlineSmallMaxByteSize)) {
+ if(isPragmaInline || newByteSize < _minInlineStop || factor <= _maxInlineGrowthFactor || (methodByteSize < _inlineSmallMaxByteSize)) {
found = true;
} else {
Log::out() << "Skip inlining " << methodDesc->getParentType()->getName() << "." << methodDesc->getName() << ::std::endl;
@@ -916,25 +907,28 @@
<< (int)methodByteSize
<< ", newByteSize = " << (int)newByteSize
<< ", factor=" << factor
- << ::std::endl;
+ << std::endl;
}
}
if(!found) {
// No more candidates. Done with inlining.
assert(_inlineCandidates.empty());
- Log::out() << "Done inlining " << ::std::endl;
+ Log::out() << "Done inlining " << std::endl;
return NULL;
}
- //
// Set candidate as current inlined region
- //
Log::out() << "Opt: Inline " << methodDesc->getParentType()->getName() << "." << methodDesc->getName() <<
- methodDesc->getSignatureString() << ::std::endl;
-
+ methodDesc->getSignatureString() << std::endl;
+
+ // Generate flowgraph for new region
+ InlineNode* inlineNode = createInlineNode(inlineCC, call);
+ assert(inlineNode!=NULL);
+ inlineParentNode->addChild(inlineNode);
+
_currentByteSize = newByteSize;
- return call;
+ return inlineNode;
}
InlineNode* Inliner::createInlineNode(CompilationContext& inlineCC, MethodCallInst* call) {
@@ -977,19 +971,24 @@
assert(call != NULL);
MethodDesc* methodDesc = call->getMethodDesc();
- Log::out() << "Considering inlining instruction I"
- << (int)call->getId() << ::std::endl;
- if(canInlineInto(*methodDesc)) {
+ Log::out() << "Considering inlining instruction I" << (int)call->getId() << ::std::endl;
+ if (methodDesc->hasAnnotation(inlinePragma)) {
+ assert(!methodDesc->isSynchronized()); //not tested!
+ if (Log::isEnabled()) {
+ Log::out()<<"Found Inline pragma, adding to the queue:";call->print(Log::out());Log::out()<<std::endl;
+ }
+ _inlineCandidates.push(CallSite(PRAGMA_INLINE_BENEFIT, node, inlineNode));
+ } else if (usePriorityQueue && canInlineInto(*methodDesc)) {
uint32 size = methodDesc->getByteCodeSize();
int32 benefit = computeInlineBenefit(node, *methodDesc, inlineNode, ltree->getLoopDepth(node));
assert(size > 0);
Log::out() << "Inline benefit " << methodDesc->getParentType()->getName() << "." << methodDesc->getName() << " == " << (int) benefit << ::std::endl;
if(0 < size && benefit > _minBenefitThreshold) {
// Inline candidate
- Log::out() << "Add to queue" << ::std::endl;
+ Log::out() << "Add to queue" << std::endl;
_inlineCandidates.push(CallSite(benefit, node, inlineNode));
} else {
- Log::out() << "Will not inline" << ::std::endl;
+ Log::out() << "Will not inline" << std::endl;
}
}
}
@@ -1118,73 +1117,61 @@
typedef StlVector<MethodCallInst*> InlineVector;
-void Inliner::doInline(MemoryManager& tmpMM, MethodCallInst* origCall) {
+void Inliner::runInliner(MethodCallInst* call) {
CompilationContext* topCC = _toplevelIRM.getCompilationContext();
CompilationInterface* ci = topCC->getVMCompilationInterface();
-
- InlineVector pragmaInlineCalls(tmpMM);
- bool firstIteration = true;
+ InlineNode* rootRegionNode = (InlineNode*) getInlineTree().getRoot();
+ bool first = 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);
+ InlineNode* regionNode = 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);
+ if (first) {
+ if (call == NULL) { //if method is null -> check all calls in top level method
+ regionNode = rootRegionNode;
+ } else {
+ regionNode = createInlineNode(inlineCC, call); //if method is not null -> inline it first
+ rootRegionNode->addChild(regionNode);
+ }
+ first = false;
+ } else {
+ regionNode = getNextRegionToInline(inlineCC);
}
- // 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);
+ if (regionNode == NULL) {
+ break;
}
- OptPass::computeDominatorsAndLoops(regionManager);
- } else {// processing whole method
- ir = (InlineNode*)getInlineTree().getRoot();
+ compileAndConnectRegion(regionNode, inlineCC);
}
+ //inline current region
+ inlineRegion(regionNode);
+ } while (true);
+}
- //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;
- }
- }
- }
- }
+void Inliner::compileAndConnectRegion(InlineNode* inlineNode, CompilationContext& inlineCC) {
+ MethodCallInst* call = inlineNode->getCallInst()!=NULL ? inlineNode->getCallInst()->asMethodCallInst() : NULL;
+ if (call!=NULL) { // processing custom call in a method
+ IRManager ®ionManager = inlineNode->getIRManager();
+ assert(inlineCC.getHIRManager() == ®ionManager);
+
+ // Connect region arguments to top-level flowgraph
+ if(connectEarly) {
+ connectRegion(inlineNode);
}
- //inline current region
- inlineRegion(ir);
- } while (!pragmaInlineCalls.empty());
+
+ // Optimize inlined region before splicing
+ CompilationContext* topCC = regionManager.getCompilationContext();
+ inlineCC.stageId = topCC->stageId;
+ Inliner::runInlinerPipeline(inlineCC, inlinerPipelineName);
+ topCC->stageId = inlineCC.stageId;
+
+ // Splice into flow graph and find next region.
+ if(!connectEarly) {
+ connectRegion(inlineNode);
+ }
+ OptPass::computeDominatorsAndLoops(regionManager);
+ }
}
void InlinePass::_run(IRManager& irm) {
@@ -1198,23 +1185,16 @@
MemoryManager tmpMM("Inliner::tmp_mm");
Inliner inliner(this, tmpMM, irm, irm.getFlowGraph().hasEdgeProfile(), true, pipeName);
inliner.setConnectEarly(connectEarly);
- inliner.doInline(tmpMM, NULL);
-
- // Inline calls
- do {
- MethodCallInst* call = inliner.getNextRegionToInline();
- if (call == NULL) {
- break;
- }
- inliner.doInline(tmpMM, call);
- } while (true);
+ inliner.runInliner(NULL); //call is unspecified -> check all calls using priority queue
+
const OptimizerFlags& optimizerFlags = irm.getOptimizerFlags();
// Print the results to logging / dot file
if(optimizerFlags.dumpdot) {
inliner.getInlineTree().printDotFile(irm.getMethodDesc(), "inlinetree");
}
if(Log::isEnabled()) {
- Log::out() << indent(irm) << "Opt: Inline Tree" << ::std::endl;
+ Log::out()<<std::endl;
+ Log::out() << indent(irm) << "Opt: Inline Tree" << std::endl;
inliner.getInlineTree().printIndentedTree(Log::out(), " ");
}
Log::out() << "Inline Checksum == " << (int) inliner.getInlineTree().computeCheckSum() << ::std::endl;
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=558008&r1=558007&r2=558008
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/inliner.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/inliner.h Fri Jul 20 07:36:28 2007
@@ -102,8 +102,10 @@
// Connect input and return operands of the region to the top-level method. Do not yet splice.
void connectRegion(InlineNode* inlineNode);
+ void compileAndConnectRegion(InlineNode* inlineNode, CompilationContext& inlineCC);
+
// Searches the flowgraph for the next inline candidate method.
- MethodCallInst* getNextRegionToInline();
+ InlineNode* getNextRegionToInline(CompilationContext& inlineCC);
InlineTree& getInlineTree() { return _inlineTree; }
@@ -115,11 +117,15 @@
static void runInlinerPipeline(CompilationContext& inlineCC, const char* pipeName);
- void doInline(MemoryManager& tmpMM, MethodCallInst* call);
+ /**runs inliner for a specified top level call.
+ * If call==NULL runs inliner for all calls in a method: priority queue is used to find methods to inline
+ */
+ void runInliner(MethodCallInst* call);
void setConnectEarly(bool early) {connectEarly = early;}
private:
+
class CallSite {
public:
CallSite(int32 benefit, Node* callNode, InlineNode* inlineNode) : benefit(benefit), callNode(callNode), inlineNode(inlineNode) {}
Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/jit/jit_runtime_support.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/jit/jit_runtime_support.cpp?view=diff&rev=558008&r1=558007&r2=558008
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/jit/jit_runtime_support.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/jit/jit_runtime_support.cpp Fri Jul 20 07:36:28 2007
@@ -2166,7 +2166,6 @@
END_RAISE_AREA;
assert(m!=NULL);
-
assert(obj!=NULL);
assert(obj->vt()!=NULL);
Class* objClass = obj->vt()->clss;
@@ -2174,7 +2173,10 @@
assert(objClass->is_initialized() || objClass->is_initializing());
char* infc_vtable = (char*)Class::helper_get_interface_vtable(obj, m->get_class());
- assert(infc_vtable);
+ if(infc_vtable == NULL) {
+ exn_throw_by_name("java/lang/IncompatibleClassChangeError", objClass->get_name()->bytes);
+ return NULL;
+ }
unsigned base_index = (unsigned)(infc_vtable - (char*)objClass->get_vtable()->methods)/sizeof(char*);
Method* infc_method = objClass->get_method_from_vtable(base_index + m->get_index());
assert(infc_method);