blob: faf9df9738ace4c11bfff954fed2fe1fd6285e4c [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @author Mikhail Y. Fursov
*/
#ifndef _IA32_GC_SAFE_POINTS_H_
#define _IA32_GC_SAFE_POINTS_H_
#include "Ia32IRManager.h"
namespace Jitrino
{
namespace Ia32 {
class GCPointsBaseLiveRangeFixer: public SessionAction {
public:
void runImpl();
U_32 getSideEffects() const {return sideEffect;}
U_32 getNeedInfo()const{ return 0;}
private:
U_32 sideEffect;
};
class GCSafePointsInfo;
#define MPTR_OFFSET_UNKNOWN 2147483647 //((1<<31)-1) maxint -> illegal offset
class MPtrPair {
friend class GCSafePointsInfo;
Opnd* mptr;
Opnd* base;
int offset;
public:
MPtrPair(Opnd* _mptr, Opnd* _base, int _offset)
: mptr(_mptr), base(_base), offset (_offset)
{
assert(mptr != NULL);
}
MPtrPair(const MPtrPair& p) : mptr(p.mptr), base(p.base), offset(p.offset){}
//STL requirement : MPtrPair is stored by value in vector
MPtrPair() : mptr(NULL), base(NULL), offset(MPTR_OFFSET_UNKNOWN){}
inline MPtrPair& operator= (const MPtrPair& p) {
mptr = p.mptr;
base = p.base;
offset = p.offset;
return *this;
}
inline bool operator==(const MPtrPair& p) const {return (p.mptr == mptr && p.base == base && p.offset == offset);}
inline bool operator<(const MPtrPair& p) const {
if (mptr!=p.mptr) {
return mptr < p.mptr;
}
if (base!=p.base) {
return base < p.base;
}
if (offset!=p.offset) {
return offset < p.offset;
}
return false;
}
inline bool equalBaseAndMptr(const MPtrPair& p) const {return p.mptr == mptr && p.base == base;}
static bool equalMptrs(const MPtrPair& p1, const MPtrPair& p2) {return p1.mptr == p2.mptr;}
Opnd* getMptr() const { return mptr;}
Opnd* getBase() const {return base;}
int getOffset() const { return offset;}
};
typedef StlVector<MPtrPair> GCSafePointPairs;
typedef StlMap<U_32, GCSafePointPairs*> GCSafePointPairsMap;
class GCSafePointsInfo {
public:
/** FIX_BASES Mode -> works on 3-address IR, calculates pairs and resolves base-ambiguity
CALC_OFFSETS -> works on 2-address IR, calculates offsets only, does not resolves base-ambibuity */
enum Mode {MODE_1_FIX_BASES, MODE_2_CALC_OFFSETS};
GCSafePointsInfo(MemoryManager& mm, IRManager& irm, Mode mode);
bool hasPairs() const {return !pairsByGCSafePointInstId.empty();}
GCSafePointPairs& getGCSafePointPairs(const Inst* gcSafePointInst) const {
GCSafePointPairsMap::const_iterator it = pairsByGCSafePointInstId.find(gcSafePointInst->getId());
assert(it!=pairsByGCSafePointInstId.end());
return *(*it).second;
}
const StlSet<Opnd*>& getStaticFieldMptrs() const {return staticMptrs;}
bool isStaticFieldMptr(Opnd* opnd) const { return staticMptrs.find(opnd)!=staticMptrs.end();}
void dump(const char* stage) const;
static bool isGCSafePoint(const Inst* inst) {return IRManager::isGCSafePoint(inst);}
static bool graphHasSafePoints(const IRManager& irm);
static bool blockHasSafePoints(const Node* b);
/** if pairs!=NULL counts only gcpoints with non-empty pairs*/
static U_32 getNumSafePointsInBlock(const Node* b, const GCSafePointPairsMap* pairsMap = NULL);
static MPtrPair* findPairByMPtrOpnd(GCSafePointPairs& pairs, const Opnd* mptr);
static bool isManaged(Opnd* op) { return op->getType()->isObject() || op->getType()->isManagedPtr();}
private:
void _calculate();
void insertLivenessFilters();
void calculateMPtrs();
void filterLiveMPtrsOnGCSafePoints();
void filterStaticMptrs(Inst* inst);
void checkPairsOnNodeExits() const ;
void checkPairsOnGCSafePoints() const ;
/** fills res with pairs on 'node' entry, merges equal pairs and resolves ambiguous mptrs.
* side effect: while resolving ambiguous mptrs could modify pred blocks -> adds verdef
*/
void derivePairsOnEntry(const Node* node, GCSafePointPairs& res);
void updatePairsOnInst(Inst* inst, GCSafePointPairs& res) ;
void addAllLive(const BitSet* ls, GCSafePointPairs& res, const GCSafePointPairs& predBlockPairs) const ;
bool hasEqualElements(GCSafePointPairs& p1, GCSafePointPairs& p2) const {
if (p1.size()!=p2.size()) {
return FALSE;
}
std::sort(p1.begin(), p1.end());
std::sort(p2.begin(), p2.end());
return std::equal(p1.begin(), p1.end(), p2.begin());
};
void setLivenessFilter(const Inst* inst, const BitSet* ls);
const BitSet* findLivenessFilter(const Inst* inst) const;
void removePairByMPtrOpnd(GCSafePointPairs& pairs, const Opnd* mptr) const;
void runLivenessFilter(Inst* inst, GCSafePointPairs& res) const;
Opnd* getBaseAccordingMode(Opnd* opnd) const;
void updateMptrInfoInPairs(GCSafePointPairs& res, Opnd* newMptr, Opnd* fromOpnd, I_32 offset, bool fromOpndIsBase);
//returns offset if offsetOpnd is immediate ir MPTR_OFFSET_UNKNOWN if not */
I_32 getOffsetFromImmediate(Opnd* offsetOpnd) const;
MemoryManager& mm;
IRManager& irm;
StlVector<GCSafePointPairs*> pairsByNode;
GCSafePointPairsMap pairsByGCSafePointInstId;
StlMap<const Inst*, const BitSet*> livenessFilter;
StlMap<Inst*, Opnd*> ambiguityFilters;
StlSet<Opnd*> staticMptrs;
bool allowMerging;
/** stat fields */
U_32 opndsAdded;
U_32 instsAdded;
Mode mode;
};
}} //namespace
#endif