зеркало из https://github.com/mozilla/gecko-dev.git
Implemented multiple type specialized trees per entry point (bug 450833, r=gal)
This commit is contained in:
Родитель
b1d2219a45
Коммит
610531b27c
|
@ -49,3 +49,4 @@ JITSTAT(unstableLoopVariable)
|
|||
JITSTAT(breakLoopExits)
|
||||
JITSTAT(returnLoopExits)
|
||||
JITSTAT(mergedLoopExits)
|
||||
JITSTAT(noCompatInnerTrees)
|
||||
|
|
|
@ -108,18 +108,6 @@ class TypeMap;
|
|||
# define CLS(T) void*
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Fragment quick cache entry.
|
||||
*/
|
||||
typedef struct JSFragmentCacheEntry {
|
||||
jsbytecode* pc;
|
||||
CLS(nanojit::Fragment) fragment;
|
||||
} JSFragmentCacheEntry;
|
||||
|
||||
#define JS_FRAGMENT_CACHE_LOG2 2
|
||||
#define JS_FRAGMENT_CACHE_SIZE JS_BIT(JS_FRAGMENT_CACHE_LOG2)
|
||||
#define JS_FRAGMENT_CACHE_MASK JS_BITMASK(JS_FRAGMENT_CACHE_LOG2)
|
||||
|
||||
/*
|
||||
* Trace monitor. Every JSThread (if JS_THREADSAFE) or JSRuntime (if not
|
||||
* JS_THREADSAFE) has an associated trace monitor that keeps track of loop
|
||||
|
@ -138,7 +126,6 @@ typedef struct JSTraceMonitor {
|
|||
uint32 globalShape;
|
||||
CLS(SlotList) globalSlots;
|
||||
CLS(TypeMap) globalTypeMap;
|
||||
JSFragmentCacheEntry fcache[JS_FRAGMENT_CACHE_SIZE];
|
||||
jsval *recoveryDoublePool;
|
||||
jsval *recoveryDoublePoolPtr;
|
||||
uint32 jitCacheGen;
|
||||
|
|
1127
js/src/jstracer.cpp
1127
js/src/jstracer.cpp
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -168,6 +168,13 @@ public:
|
|||
bool matches(TypeMap& other) const;
|
||||
};
|
||||
|
||||
struct UnstableExit
|
||||
{
|
||||
nanojit::Fragment* fragment;
|
||||
nanojit::SideExit* exit;
|
||||
UnstableExit* next;
|
||||
};
|
||||
|
||||
class TreeInfo MMGC_SUBCLASS_DECL {
|
||||
nanojit::Fragment* fragment;
|
||||
public:
|
||||
|
@ -176,14 +183,15 @@ public:
|
|||
ptrdiff_t nativeStackBase;
|
||||
unsigned maxCallDepth;
|
||||
TypeMap stackTypeMap;
|
||||
unsigned mismatchCount;
|
||||
Queue<nanojit::Fragment*> dependentTrees;
|
||||
unsigned branchCount;
|
||||
Queue<nanojit::SideExit*> sideExits;
|
||||
UnstableExit* unstableExits;
|
||||
|
||||
TreeInfo(nanojit::Fragment* _fragment) {
|
||||
TreeInfo(nanojit::Fragment* _fragment) : unstableExits(NULL) {
|
||||
fragment = _fragment;
|
||||
}
|
||||
~TreeInfo();
|
||||
};
|
||||
|
||||
struct FrameInfo {
|
||||
|
@ -235,6 +243,9 @@ class TraceRecorder : public GCObject {
|
|||
jsval* global_dslots;
|
||||
JSTraceableNative* pendingTraceableNative;
|
||||
bool terminate;
|
||||
intptr_t terminate_ip_adj;
|
||||
nanojit::Fragment* outerToBlacklist;
|
||||
nanojit::Fragment* promotedPeer;
|
||||
bool isRootFragment;
|
||||
|
||||
bool isGlobal(jsval* p) const;
|
||||
|
@ -255,8 +266,10 @@ class TraceRecorder : public GCObject {
|
|||
nanojit::LIns* writeBack(nanojit::LIns* i, nanojit::LIns* base, ptrdiff_t offset);
|
||||
void set(jsval* p, nanojit::LIns* l, bool initializing = false);
|
||||
|
||||
bool checkType(jsval& v, uint8 type, bool& recompile);
|
||||
bool verifyTypeStability();
|
||||
bool checkType(jsval& v, uint8 t, jsval*& stage_val, nanojit::LIns*& stage_ins,
|
||||
unsigned& stage_count);
|
||||
bool deduceTypeStability(nanojit::Fragment* root_peer, nanojit::Fragment** stable_peer,
|
||||
unsigned* demotes);
|
||||
|
||||
jsval& argval(unsigned n) const;
|
||||
jsval& varval(unsigned n) const;
|
||||
|
@ -340,7 +353,7 @@ public:
|
|||
|
||||
TraceRecorder(JSContext* cx, nanojit::SideExit*, nanojit::Fragment*, TreeInfo*,
|
||||
unsigned ngslots, uint8* globalTypeMap, uint8* stackTypeMap,
|
||||
nanojit::SideExit* expectedInnerExit);
|
||||
nanojit::SideExit* expectedInnerExit, nanojit::Fragment* outerToBlacklist);
|
||||
~TraceRecorder();
|
||||
|
||||
uint8 determineSlotType(jsval* vp) const;
|
||||
|
@ -348,11 +361,12 @@ public:
|
|||
nanojit::Fragment* getFragment() const { return fragment; }
|
||||
bool isLoopHeader(JSContext* cx) const;
|
||||
void compile(nanojit::Fragmento* fragmento);
|
||||
void closeLoop(nanojit::Fragmento* fragmento);
|
||||
bool closeLoop(nanojit::Fragmento* fragmento, bool& demote, unsigned *demotes);
|
||||
void endLoop(nanojit::Fragmento* fragmento);
|
||||
void joinEdgesToEntry(nanojit::Fragmento* fragmento, nanojit::Fragment* peer_root);
|
||||
void blacklist() { fragment->blacklist(); }
|
||||
bool adjustCallerTypes(nanojit::Fragment* f);
|
||||
bool selectCallablePeerFragment(nanojit::Fragment** first);
|
||||
bool adjustCallerTypes(nanojit::Fragment* f, unsigned* demote_slots, bool& trash);
|
||||
nanojit::Fragment* findNestedCompatiblePeer(nanojit::Fragment* f, nanojit::Fragment** empty);
|
||||
void prepareTreeCall(nanojit::Fragment* inner);
|
||||
void emitTreeCall(nanojit::Fragment* inner, nanojit::SideExit* exit);
|
||||
unsigned getCallDepth() const;
|
||||
|
@ -365,9 +379,12 @@ public:
|
|||
bool record_DefLocalFunSetSlot(uint32 slot, JSObject* obj);
|
||||
bool record_FastNativeCallComplete();
|
||||
|
||||
nanojit::Fragment* getOuterToBlacklist() { return outerToBlacklist; }
|
||||
void deepAbort() { deepAborted = true; }
|
||||
bool wasDeepAborted() { return deepAborted; }
|
||||
bool walkedOutOfLoop() { return terminate; }
|
||||
void setPromotedPeer(nanojit::Fragment* peer) { promotedPeer = peer; }
|
||||
TreeInfo* getTreeInfo() { return treeInfo; }
|
||||
|
||||
#define OPDEF(op,val,name,token,length,nuses,ndefs,prec,format) \
|
||||
bool record_##op();
|
||||
|
|
|
@ -511,6 +511,12 @@ namespace nanojit
|
|||
NanoAssert(_pages == 0);
|
||||
}
|
||||
|
||||
void Fragment::resetHits()
|
||||
{
|
||||
blacklistLevel >>= 1;
|
||||
_hits = 0;
|
||||
}
|
||||
|
||||
void Fragment::blacklist()
|
||||
{
|
||||
blacklistLevel++;
|
||||
|
@ -522,6 +528,7 @@ namespace nanojit
|
|||
GC *gc = _core->gc;
|
||||
Fragment *f = new (gc) Fragment(ip);
|
||||
f->blacklistLevel = 5;
|
||||
f->recordAttempts = 0;
|
||||
return f;
|
||||
}
|
||||
|
||||
|
|
|
@ -176,6 +176,7 @@ namespace nanojit
|
|||
void setCode(NIns* codee, Page* pages) { _code = codee; _pages = pages; }
|
||||
GuardRecord* links() { return _links; }
|
||||
int32_t& hits() { return _hits; }
|
||||
void resetHits();
|
||||
void blacklist();
|
||||
bool isBlacklisted() { return _hits < 0; }
|
||||
debug_only( bool hasOnlyTreeLinks(); )
|
||||
|
@ -215,6 +216,7 @@ namespace nanojit
|
|||
const void* ip;
|
||||
uint32_t guardCount;
|
||||
uint32_t xjumpCount;
|
||||
uint32_t recordAttempts;
|
||||
int32_t blacklistLevel;
|
||||
NIns* fragEntry;
|
||||
int32_t calldepth;
|
||||
|
|
|
@ -172,9 +172,12 @@ namespace nanojit
|
|||
NESTED_EXIT,
|
||||
MISMATCH_EXIT,
|
||||
OOM_EXIT,
|
||||
OVERFLOW_EXIT
|
||||
OVERFLOW_EXIT,
|
||||
UNSTABLE_LOOP_EXIT
|
||||
};
|
||||
|
||||
struct GuardRecord;
|
||||
|
||||
class LIns;
|
||||
|
||||
struct SideExit;
|
||||
|
|
|
@ -1548,9 +1548,9 @@ function testNestedExitStackOuter() {
|
|||
}
|
||||
testNestedExitStackOuter.expected = 81;
|
||||
testNestedExitStackOuter.jitstats = {
|
||||
recorderStarted: 3,
|
||||
recorderAborted: 0,
|
||||
traceTriggered: 7
|
||||
recorderStarted: 5,
|
||||
recorderAborted: 2,
|
||||
traceTriggered: 9
|
||||
};
|
||||
test(testNestedExitStackOuter);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче