Backout d62929fa4325 for talos crashes

This commit is contained in:
Ed Morley 2012-08-22 14:53:11 +01:00
parent 1ad046b572
commit 9476c8d8ec
34 changed files with 711 additions and 1442 deletions

View File

@ -147,7 +147,6 @@ static bool sCCLockedOut;
static PRTime sCCLockedOutTime;
static js::GCSliceCallback sPrevGCSliceCallback;
static js::AnalysisPurgeCallback sPrevAnalysisPurgeCallback;
// The number of currently pending document loads. This count isn't
// guaranteed to always reflect reality and can't easily as we don't
@ -200,17 +199,6 @@ static nsIScriptSecurityManager *sSecurityManager;
static bool sGCOnMemoryPressure;
static PRTime
GetCollectionTimeDelta()
{
PRTime now = PR_Now();
if (sFirstCollectionTime) {
return now - sFirstCollectionTime;
}
sFirstCollectionTime = now;
return 0;
}
class nsMemoryPressureObserver MOZ_FINAL : public nsIObserver
{
public:
@ -3129,7 +3117,12 @@ nsJSContext::CycleCollectNow(nsICycleCollectorListener *aListener,
Telemetry::Accumulate(Telemetry::FORGET_SKIPPABLE_MAX,
sMaxForgetSkippableTime / PR_USEC_PER_MSEC);
PRTime delta = GetCollectionTimeDelta();
PRTime delta = 0;
if (sFirstCollectionTime) {
delta = now - sFirstCollectionTime;
} else {
sFirstCollectionTime = now;
}
PRUint32 cleanups = sForgetSkippableBeforeCC ? sForgetSkippableBeforeCC : 1;
PRUint32 minForgetSkippableTime = (sMinForgetSkippableTime == PR_UINT32_MAX)
@ -3515,7 +3508,13 @@ DOMGCSliceCallback(JSRuntime *aRt, js::GCProgress aProgress, const js::GCDescrip
NS_ASSERTION(NS_IsMainThread(), "GCs must run on the main thread");
if (aProgress == js::GC_CYCLE_END) {
PRTime delta = GetCollectionTimeDelta();
PRTime now = PR_Now();
PRTime delta = 0;
if (sFirstCollectionTime) {
delta = now - sFirstCollectionTime;
} else {
sFirstCollectionTime = now;
}
if (sPostGCEventsToConsole) {
NS_NAMED_LITERAL_STRING(kFmt, "GC(T+%.1f) ");
@ -3532,7 +3531,7 @@ DOMGCSliceCallback(JSRuntime *aRt, js::GCProgress aProgress, const js::GCDescrip
if (sPostGCEventsToConsole || sPostGCEventsToObserver) {
nsString json;
json.Adopt(aDesc.formatJSON(aRt, PR_Now()));
json.Adopt(aDesc.formatJSON(aRt, now));
nsRefPtr<NotifyGCEndRunnable> notify = new NotifyGCEndRunnable(json);
NS_DispatchToMainThread(notify);
}
@ -3589,32 +3588,6 @@ DOMGCSliceCallback(JSRuntime *aRt, js::GCProgress aProgress, const js::GCDescrip
(*sPrevGCSliceCallback)(aRt, aProgress, aDesc);
}
static void
DOMAnalysisPurgeCallback(JSRuntime *aRt, JSFlatString *aDesc)
{
NS_ASSERTION(NS_IsMainThread(), "GCs must run on the main thread");
PRTime delta = GetCollectionTimeDelta();
if (sPostGCEventsToConsole) {
NS_NAMED_LITERAL_STRING(kFmt, "Analysis Purge (T+%.1f) ");
nsString prefix;
prefix.Adopt(nsTextFormatter::smprintf(kFmt.get(),
double(delta) / PR_USEC_PER_SEC));
nsDependentJSString stats(aDesc);
nsString msg = prefix + stats;
nsCOMPtr<nsIConsoleService> cs = do_GetService(NS_CONSOLESERVICE_CONTRACTID);
if (cs) {
cs->LogStringMessage(msg.get());
}
}
if (sPrevAnalysisPurgeCallback)
(*sPrevAnalysisPurgeCallback)(aRt, aDesc);
}
// Script object mananagement - note duplicate implementation
// in nsJSRuntime below...
nsresult
@ -4031,7 +4004,6 @@ nsJSRuntime::Init()
NS_ASSERTION(NS_IsMainThread(), "bad");
sPrevGCSliceCallback = js::SetGCSliceCallback(sRuntime, DOMGCSliceCallback);
sPrevAnalysisPurgeCallback = js::SetAnalysisPurgeCallback(sRuntime, DOMAnalysisPurgeCallback);
// Set up the structured clone callbacks.
static JSStructuredCloneCallbacks cloneCallbacks = {
@ -4126,12 +4098,6 @@ nsJSRuntime::Init()
SetMemoryGCPrefChangedCallback("javascript.options.mem.gc_high_frequency_high_limit_mb",
(void *)JSGC_HIGH_FREQUENCY_HIGH_LIMIT);
Preferences::RegisterCallback(SetMemoryGCPrefChangedCallback,
"javascript.options.mem.analysis_purge_mb",
(void *)JSGC_ANALYSIS_PURGE_TRIGGER);
SetMemoryGCPrefChangedCallback("javascript.options.mem.analysis_purge_mb",
(void *)JSGC_ANALYSIS_PURGE_TRIGGER);
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
if (!obs)
return NS_ERROR_FAILURE;

View File

@ -963,8 +963,8 @@ ParallelArrayObject::create(JSContext *cx, HandleObject buffer, uint32_t offset,
TypeObject *bufferType = buffer->getType(cx);
TypeObject *resultType = result->getType(cx);
if (!bufferType->unknownProperties() && !resultType->unknownProperties()) {
HeapTypeSet *bufferIndexTypes = bufferType->getProperty(cx, JSID_VOID, false);
HeapTypeSet *resultIndexTypes = resultType->getProperty(cx, JSID_VOID, true);
TypeSet *bufferIndexTypes = bufferType->getProperty(cx, JSID_VOID, false);
TypeSet *resultIndexTypes = resultType->getProperty(cx, JSID_VOID, true);
bufferIndexTypes->addSubset(cx, resultIndexTypes);
}
}

View File

@ -806,7 +806,6 @@ static JSFunctionSpecWithHelp TestingFunctions[] = {
" 10: Incremental GC in multiple slices\n"
" 11: Verify post write barriers between instructions\n"
" 12: Verify post write barriers between paints\n"
" 13: Purge analysis state when memory is allocated\n"
" Period specifies that collection happens every n allocations.\n"),
JS_FN_HELP("schedulegc", ScheduleGC, 1, 0,

View File

@ -263,21 +263,12 @@ class LifoAlloc
latest->release(mark);
}
void releaseAll() {
JS_ASSERT(!markCount);
latest = first;
if (latest)
latest->resetBump();
}
/* Get the total "used" (occupied bytes) count for the arena chunks. */
size_t used() const {
size_t accum = 0;
BumpChunk *it = first;
while (it) {
accum += it->used();
if (it == latest)
break;
it = it->next();
}
return accum;

View File

@ -2642,11 +2642,7 @@ frontend::EmitFunctionScript(JSContext *cx, BytecodeEmitter *bce, ParseNode *bod
if (!EmitTree(cx, bce, body))
return false;
/*
* Always end the script with a JSOP_STOP. Some other parts of the codebase
* depend on this opcode, e.g. js_InternalInterpret.
*/
if (Emit1(cx, bce, JSOP_STOP) < 0)
return false;

View File

@ -47,7 +47,7 @@ ScriptAnalysis::addJump(JSContext *cx, unsigned offset,
Bytecode *&code = codeArray[offset];
if (!code) {
code = cx->analysisLifoAlloc().new_<Bytecode>();
code = cx->typeLifoAlloc().new_<Bytecode>();
if (!code) {
setOOM(cx);
return false;
@ -96,13 +96,13 @@ ScriptAnalysis::analyzeBytecode(JSContext *cx)
{
JS_ASSERT(cx->compartment->activeAnalysis);
JS_ASSERT(!ranBytecode());
LifoAlloc &alloc = cx->analysisLifoAlloc();
LifoAlloc &tla = cx->typeLifoAlloc();
numSlots = TotalSlots(script);
unsigned length = script->length;
codeArray = alloc.newArray<Bytecode*>(length);
escapedSlots = alloc.newArray<bool>(numSlots);
codeArray = tla.newArray<Bytecode*>(length);
escapedSlots = tla.newArray<bool>(numSlots);
if (!codeArray || !escapedSlots) {
setOOM(cx);
@ -173,7 +173,7 @@ ScriptAnalysis::analyzeBytecode(JSContext *cx)
unsigned forwardCatch = 0;
/* Fill in stack depth and definitions at initial bytecode. */
Bytecode *startcode = alloc.new_<Bytecode>();
Bytecode *startcode = tla.new_<Bytecode>();
if (!startcode) {
setOOM(cx);
return;
@ -270,10 +270,10 @@ ScriptAnalysis::analyzeBytecode(JSContext *cx)
*/
if ((js_CodeSpec[op].format & JOF_TYPESET) && cx->typeInferenceEnabled()) {
if (nTypeSets < script->nTypeSets) {
code->observedTypes = typeArray[nTypeSets++].toStackTypeSet();
code->observedTypes = &typeArray[nTypeSets++];
} else {
JS_ASSERT(nTypeSets == UINT16_MAX);
code->observedTypes = typeArray[nTypeSets - 1].toStackTypeSet();
code->observedTypes = &typeArray[nTypeSets - 1];
}
}
@ -460,14 +460,6 @@ ScriptAnalysis::analyzeBytecode(JSContext *cx)
isInlineable = false;
break;
case JSOP_GETPROP:
case JSOP_CALLPROP:
case JSOP_LENGTH:
case JSOP_GETELEM:
case JSOP_CALLELEM:
numPropertyReads_++;
break;
/* Additional opcodes which can be compiled but which can't be inlined. */
case JSOP_ARGUMENTS:
case JSOP_THROW:
@ -517,6 +509,11 @@ ScriptAnalysis::analyzeBytecode(JSContext *cx)
case JSOP_TYPEOF:
case JSOP_TYPEOFEXPR:
case JSOP_VOID:
case JSOP_GETPROP:
case JSOP_CALLPROP:
case JSOP_LENGTH:
case JSOP_GETELEM:
case JSOP_CALLELEM:
case JSOP_TOID:
case JSOP_SETELEM:
case JSOP_IMPLICITTHIS:
@ -605,7 +602,7 @@ ScriptAnalysis::analyzeBytecode(JSContext *cx)
Bytecode *&nextcode = codeArray[successorOffset];
if (!nextcode) {
nextcode = alloc.new_<Bytecode>();
nextcode = tla.new_<Bytecode>();
if (!nextcode) {
setOOM(cx);
return;
@ -637,25 +634,6 @@ ScriptAnalysis::analyzeBytecode(JSContext *cx)
*/
if (!script->analyzedArgsUsage())
analyzeSSA(cx);
/*
* If the script has JIT information (we are reanalyzing the script after
* a purge), add safepoints for the targets of any cross chunk edges in
* the script. These safepoints are normally added when the JITScript is
* constructed, but will have been lost during the purge.
*/
#ifdef JS_METHODJIT
mjit::JITScript *jit = NULL;
for (int constructing = 0; constructing <= 1 && !jit; constructing++) {
for (int barriers = 0; barriers <= 1 && !jit; barriers++)
jit = script->getJIT((bool) constructing, (bool) barriers);
}
if (jit) {
mjit::CrossChunkEdge *edges = jit->edges();
for (size_t i = 0; i < jit->nedges; i++)
getCode(edges[i].target).safePoint = true;
}
#endif
}
/////////////////////////////////////////////////////////////////////
@ -673,9 +651,9 @@ ScriptAnalysis::analyzeLifetimes(JSContext *cx)
return;
}
LifoAlloc &alloc = cx->analysisLifoAlloc();
LifoAlloc &tla = cx->typeLifoAlloc();
lifetimes = alloc.newArray<LifetimeVariable>(numSlots);
lifetimes = tla.newArray<LifetimeVariable>(numSlots);
if (!lifetimes) {
setOOM(cx);
return;
@ -797,7 +775,7 @@ ScriptAnalysis::analyzeLifetimes(JSContext *cx)
/* Restore all saved variables. :FIXME: maybe do this precisely. */
for (unsigned i = 0; i < savedCount; i++) {
LifetimeVariable &var = *saved[i];
var.lifetime = alloc.new_<Lifetime>(offset, var.savedEnd, var.saved);
var.lifetime = tla.new_<Lifetime>(offset, var.savedEnd, var.saved);
if (!var.lifetime) {
cx->free_(saved);
setOOM(cx);
@ -864,7 +842,7 @@ ScriptAnalysis::analyzeLifetimes(JSContext *cx)
if (loop && loop->entry > loop->lastBlock)
loop->lastBlock = loop->entry;
LoopAnalysis *nloop = alloc.new_<LoopAnalysis>();
LoopAnalysis *nloop = tla.new_<LoopAnalysis>();
if (!nloop) {
cx->free_(saved);
setOOM(cx);
@ -914,7 +892,7 @@ ScriptAnalysis::analyzeLifetimes(JSContext *cx)
* Jumping to a place where this variable is live. Make a new
* lifetime segment for the variable.
*/
var.lifetime = alloc.new_<Lifetime>(offset, var.savedEnd, var.saved);
var.lifetime = tla.new_<Lifetime>(offset, var.savedEnd, var.saved);
if (!var.lifetime) {
cx->free_(saved);
setOOM(cx);
@ -978,7 +956,7 @@ ScriptAnalysis::addVariable(JSContext *cx, LifetimeVariable &var, unsigned offse
}
}
}
var.lifetime = cx->analysisLifoAlloc().new_<Lifetime>(offset, var.savedEnd, var.saved);
var.lifetime = cx->typeLifoAlloc().new_<Lifetime>(offset, var.savedEnd, var.saved);
if (!var.lifetime) {
setOOM(cx);
return;
@ -993,7 +971,7 @@ ScriptAnalysis::killVariable(JSContext *cx, LifetimeVariable &var, unsigned offs
{
if (!var.lifetime) {
/* Make a point lifetime indicating the write. */
Lifetime *lifetime = cx->analysisLifoAlloc().new_<Lifetime>(offset, var.savedEnd, var.saved);
Lifetime *lifetime = cx->typeLifoAlloc().new_<Lifetime>(offset, var.savedEnd, var.saved);
if (!lifetime) {
setOOM(cx);
return;
@ -1024,7 +1002,7 @@ ScriptAnalysis::killVariable(JSContext *cx, LifetimeVariable &var, unsigned offs
* We set the new interval's savedEnd to 0, since it will always be
* adjacent to the old interval, so it never needs to be extended.
*/
var.lifetime = cx->analysisLifoAlloc().new_<Lifetime>(start, 0, var.lifetime);
var.lifetime = cx->typeLifoAlloc().new_<Lifetime>(start, 0, var.lifetime);
if (!var.lifetime) {
setOOM(cx);
return;
@ -1113,7 +1091,7 @@ ScriptAnalysis::extendVariable(JSContext *cx, LifetimeVariable &var,
}
JS_ASSERT(savedEnd <= end);
if (savedEnd > segment->end) {
Lifetime *tail = cx->analysisLifoAlloc().new_<Lifetime>(savedEnd, 0, segment->next);
Lifetime *tail = cx->typeLifoAlloc().new_<Lifetime>(savedEnd, 0, segment->next);
if (!tail) {
setOOM(cx);
return;
@ -1190,7 +1168,7 @@ ScriptAnalysis::analyzeSSA(JSContext *cx)
return;
}
LifoAlloc &alloc = cx->analysisLifoAlloc();
LifoAlloc &tla = cx->typeLifoAlloc();
unsigned maxDepth = script->nslots - script->nfixed;
/*
@ -1374,7 +1352,7 @@ ScriptAnalysis::analyzeSSA(JSContext *cx)
unsigned xuses = ExtendedUse(pc) ? nuses + 1 : nuses;
if (xuses) {
code->poppedValues = alloc.newArray<SSAValue>(xuses);
code->poppedValues = tla.newArray<SSAValue>(xuses);
if (!code->poppedValues) {
setOOM(cx);
return;
@ -1397,7 +1375,7 @@ ScriptAnalysis::analyzeSSA(JSContext *cx)
}
if (xuses) {
SSAUseChain *useChains = alloc.newArray<SSAUseChain>(xuses);
SSAUseChain *useChains = tla.newArray<SSAUseChain>(xuses);
if (!useChains) {
setOOM(cx);
return;
@ -1424,7 +1402,7 @@ ScriptAnalysis::analyzeSSA(JSContext *cx)
unsigned xdefs = ExtendedDef(pc) ? ndefs + 1 : ndefs;
if (xdefs) {
code->pushedUses = alloc.newArray<SSAUseChain *>(xdefs);
code->pushedUses = tla.newArray<SSAUseChain *>(xdefs);
if (!code->pushedUses) {
setOOM(cx);
return;
@ -1605,8 +1583,8 @@ PhiNodeCapacity(unsigned length)
bool
ScriptAnalysis::makePhi(JSContext *cx, uint32_t slot, uint32_t offset, SSAValue *pv)
{
SSAPhiNode *node = cx->analysisLifoAlloc().new_<SSAPhiNode>();
SSAValue *options = cx->analysisLifoAlloc().newArray<SSAValue>(PhiNodeCapacity(0));
SSAPhiNode *node = cx->typeLifoAlloc().new_<SSAPhiNode>();
SSAValue *options = cx->typeLifoAlloc().newArray<SSAValue>(PhiNodeCapacity(0));
if (!node || !options) {
setOOM(cx);
return false;
@ -1638,7 +1616,7 @@ ScriptAnalysis::insertPhi(JSContext *cx, SSAValue &phi, const SSAValue &v)
if (trackUseChain(v)) {
SSAUseChain *&uses = useChain(v);
SSAUseChain *use = cx->analysisLifoAlloc().new_<SSAUseChain>();
SSAUseChain *use = cx->typeLifoAlloc().new_<SSAUseChain>();
if (!use) {
setOOM(cx);
return;
@ -1657,7 +1635,7 @@ ScriptAnalysis::insertPhi(JSContext *cx, SSAValue &phi, const SSAValue &v)
}
SSAValue *newOptions =
cx->analysisLifoAlloc().newArray<SSAValue>(PhiNodeCapacity(node->length + 1));
cx->typeLifoAlloc().newArray<SSAValue>(PhiNodeCapacity(node->length + 1));
if (!newOptions) {
setOOM(cx);
return;
@ -1857,7 +1835,7 @@ ScriptAnalysis::freezeNewValues(JSContext *cx, uint32_t offset)
return;
}
code.newValues = cx->analysisLifoAlloc().newArray<SlotValue>(count + 1);
code.newValues = cx->typeLifoAlloc().newArray<SlotValue>(count + 1);
if (!code.newValues) {
setOOM(cx);
return;
@ -2036,7 +2014,7 @@ CrossScriptSSA::foldValue(const CrossSSAValue &cv)
*/
ScriptAnalysis *analysis = frame.script->analysis();
SSAValue toidv = analysis->poppedValue(pc, 0);
if (analysis->getValueTypes(toidv)->getKnownTypeTag() == JSVAL_TYPE_INT32)
if (analysis->getValueTypes(toidv)->getKnownTypeTag(cx) == JSVAL_TYPE_INT32)
return foldValue(CrossSSAValue(cv.frame, toidv));
break;
}

View File

@ -122,7 +122,7 @@ class Bytecode
union {
/* If this is a JOF_TYPESET opcode, index into the observed types for the op. */
types::StackTypeSet *observedTypes;
types::TypeSet *observedTypes;
/* If this is a loop head (TRACE or NOTRACE), information about the loop. */
LoopAnalysis *loop;
@ -164,7 +164,7 @@ class Bytecode
/* --------- Type inference --------- */
/* Types for all values pushed by this bytecode. */
types::StackTypeSet *pushedTypes;
types::TypeSet *pushedTypes;
/* Any type barriers in place at this bytecode. */
types::TypeBarrier *typeBarriers;
@ -739,7 +739,7 @@ class SSAValue
*/
struct SSAPhiNode
{
types::StackTypeSet types;
types::TypeSet types;
uint32_t slot;
uint32_t length;
SSAValue *options;
@ -809,7 +809,6 @@ class ScriptAnalysis
Bytecode **codeArray;
uint32_t numSlots;
uint32_t numPropertyReads_;
bool outOfMemory;
bool hadFailure;
@ -873,9 +872,6 @@ class ScriptAnalysis
bool inlineable(uint32_t argc) { return isInlineable && argc == script->function()->nargs; }
bool jaegerCompileable() { return isJaegerCompileable; }
/* Number of property read opcodes in the script. */
uint32_t numPropertyReads() const { return numPropertyReads_; }
/* Whether there are POPV/SETRVAL bytecodes which can write to the frame's rval. */
bool usesReturnValue() const { return usesReturnValue_; }
@ -929,7 +925,7 @@ class ScriptAnalysis
return (cs->format & JOF_POST) && !popGuaranteed(pc);
}
types::StackTypeSet *bytecodeTypes(const jsbytecode *pc) {
types::TypeSet *bytecodeTypes(const jsbytecode *pc) {
JS_ASSERT(js_CodeSpec[*pc].format & JOF_TYPESET);
return getCode(pc).observedTypes;
}
@ -950,15 +946,15 @@ class ScriptAnalysis
}
const SlotValue *newValues(const jsbytecode *pc) { return newValues(pc - script->code); }
types::StackTypeSet *pushedTypes(uint32_t offset, uint32_t which = 0) {
types::TypeSet *pushedTypes(uint32_t offset, uint32_t which = 0) {
JS_ASSERT(offset < script->length);
JS_ASSERT(which < GetDefCount(script, offset) +
(ExtendedDef(script->code + offset) ? 1 : 0));
types::StackTypeSet *array = getCode(offset).pushedTypes;
types::TypeSet *array = getCode(offset).pushedTypes;
JS_ASSERT(array);
return array + which;
}
types::StackTypeSet *pushedTypes(const jsbytecode *pc, uint32_t which) {
types::TypeSet *pushedTypes(const jsbytecode *pc, uint32_t which) {
return pushedTypes(pc - script->code, which);
}
@ -992,7 +988,7 @@ class ScriptAnalysis
inline void addPushedType(JSContext *cx, uint32_t offset, uint32_t which, types::Type type);
types::StackTypeSet *getValueTypes(const SSAValue &v) {
types::TypeSet *getValueTypes(const SSAValue &v) {
switch (v.kind()) {
case SSAValue::PUSHED:
return pushedTypes(v.pushedOffset(), v.pushedIndex());
@ -1018,10 +1014,10 @@ class ScriptAnalysis
}
}
types::StackTypeSet *poppedTypes(uint32_t offset, uint32_t which) {
types::TypeSet *poppedTypes(uint32_t offset, uint32_t which) {
return getValueTypes(poppedValue(offset, which));
}
types::StackTypeSet *poppedTypes(const jsbytecode *pc, uint32_t which) {
types::TypeSet *poppedTypes(const jsbytecode *pc, uint32_t which) {
return getValueTypes(poppedValue(pc, which));
}
@ -1161,12 +1157,9 @@ class ScriptAnalysis
Vector<SSAPhiNode *> phiNodes;
bool hasGetSet;
bool hasHole;
types::StackTypeSet *forTypes;
bool hasPropertyReadTypes;
uint32_t propertyReadIndex;
types::TypeSet *forTypes;
TypeInferenceState(JSContext *cx)
: phiNodes(cx), hasGetSet(false), hasHole(false), forTypes(NULL),
hasPropertyReadTypes(false), propertyReadIndex(0)
: phiNodes(cx), hasGetSet(false), hasHole(false), forTypes(NULL)
{}
};
@ -1276,7 +1269,7 @@ class CrossScriptSSA
return res;
}
types::StackTypeSet *getValueTypes(const CrossSSAValue &cv) {
types::TypeSet *getValueTypes(const CrossSSAValue &cv) {
return getFrame(cv.frame).script->analysis()->getValueTypes(cv.v);
}

View File

@ -807,8 +807,6 @@ JSRuntime::JSRuntime()
gcCallback(NULL),
gcSliceCallback(NULL),
gcFinalizeCallback(NULL),
analysisPurgeCallback(NULL),
analysisPurgeTriggerBytes(0),
gcMallocBytes(0),
gcBlackRootsTraceOp(NULL),
gcBlackRootsData(NULL),
@ -3064,9 +3062,6 @@ JS_SetGCParameter(JSRuntime *rt, JSGCParamKey key, uint32_t value)
case JSGC_DYNAMIC_MARK_SLICE:
rt->gcDynamicMarkSlice = value;
break;
case JSGC_ANALYSIS_PURGE_TRIGGER:
rt->analysisPurgeTriggerBytes = value * 1024 * 1024;
break;
default:
JS_ASSERT(key == JSGC_MODE);
rt->gcMode = JSGCMode(value);
@ -3113,8 +3108,6 @@ JS_GetGCParameter(JSRuntime *rt, JSGCParamKey key)
return rt->gcDynamicHeapGrowth;
case JSGC_DYNAMIC_MARK_SLICE:
return rt->gcDynamicMarkSlice;
case JSGC_ANALYSIS_PURGE_TRIGGER:
return rt->analysisPurgeTriggerBytes / 1024 / 1024;
default:
JS_ASSERT(key == JSGC_NUMBER);
return uint32_t(rt->gcNumber);
@ -7108,8 +7101,7 @@ JS_SetGCZeal(JSContext *cx, uint8_t zeal, uint32_t frequency)
" 9: Incremental GC in two slices: 1) mark all 2) new marking and finish\n"
" 10: Incremental GC in multiple slices\n"
" 11: Verify post write barriers between instructions\n"
" 12: Verify post write barriers between paints\n"
" 13: Purge analysis state every F allocations (default: 100)\n");
" 12: Verify post write barriers between paints\n");
}
const char *p = strchr(env, ',');
zeal = atoi(env);

View File

@ -4096,10 +4096,7 @@ typedef enum JSGCParamKey {
JSGC_DYNAMIC_HEAP_GROWTH = 17,
/* If true, high-frequency GCs will use a longer mark slice. */
JSGC_DYNAMIC_MARK_SLICE = 18,
/* Number of megabytes of analysis data to allocate before purging. */
JSGC_ANALYSIS_PURGE_TRIGGER = 19
JSGC_DYNAMIC_MARK_SLICE = 18
} JSGCParamKey;
typedef enum JSGCMode {

View File

@ -687,7 +687,6 @@ struct JSRuntime : js::RuntimeFriendFields
bool needZealousGC() {
if (gcNextScheduled > 0 && --gcNextScheduled == 0) {
if (gcZeal() == js::gc::ZealAllocValue ||
gcZeal() == js::gc::ZealPurgeAnalysisValue ||
(gcZeal() >= js::gc::ZealIncrementalRootsThenFinish &&
gcZeal() <= js::gc::ZealIncrementalMultipleSlices))
{
@ -708,9 +707,6 @@ struct JSRuntime : js::RuntimeFriendFields
js::GCSliceCallback gcSliceCallback;
JSFinalizeCallback gcFinalizeCallback;
js::AnalysisPurgeCallback analysisPurgeCallback;
uint64_t analysisPurgeTriggerBytes;
private:
/*
* Malloc counter to measure memory pressure for GC scheduling. It runs
@ -1296,7 +1292,6 @@ struct JSContext : js::ContextFriendFields
bool hasAtLineOption() const { return hasRunOption(JSOPTION_ATLINE); }
js::LifoAlloc &tempLifoAlloc() { return runtime->tempLifoAlloc; }
inline js::LifoAlloc &analysisLifoAlloc();
inline js::LifoAlloc &typeLifoAlloc();
inline js::PropertyTree &propertyTree();

View File

@ -549,11 +549,6 @@ JSContext::setCompileOptions(unsigned newcopts)
maybeOverrideVersion(newVersion);
}
inline js::LifoAlloc &
JSContext::analysisLifoAlloc()
{
return compartment->analysisLifoAlloc;
}
inline js::LifoAlloc &
JSContext::typeLifoAlloc()

View File

@ -55,8 +55,7 @@ JSCompartment::JSCompartment(JSRuntime *rt)
hold(false),
isSystemCompartment(false),
lastCodeRelease(0),
analysisLifoAlloc(LIFO_ALLOC_PRIMARY_CHUNK_SIZE),
typeLifoAlloc(LIFO_ALLOC_PRIMARY_CHUNK_SIZE),
typeLifoAlloc(TYPE_LIFO_ALLOC_PRIMARY_CHUNK_SIZE),
data(NULL),
active(false),
lastAnimationTime(0),
@ -580,13 +579,11 @@ JSCompartment::sweep(FreeOp *fop, bool releaseTypes)
for (CellIterUnderGC i(this, FINALIZE_SCRIPT); !i.done(); i.next()) {
JSScript *script = i.get<JSScript>();
script->clearAnalysis();
script->clearPropertyReadTypes();
}
}
{
gcstats::AutoPhase ap2(rt->gcStats, gcstats::PHASE_FREE_TI_ARENA);
rt->freeLifoAlloc.transferFrom(&analysisLifoAlloc);
rt->freeLifoAlloc.transferFrom(&oldAlloc);
}
}

View File

@ -248,11 +248,13 @@ struct JSCompartment
int64_t lastCodeRelease;
/* Pools for analysis and type information in this compartment. */
static const size_t LIFO_ALLOC_PRIMARY_CHUNK_SIZE = 128 * 1024;
js::LifoAlloc analysisLifoAlloc;
/*
* Pool for analysis and intermediate type information in this compartment.
* Cleared on every GC, unless the GC happens during analysis (indicated
* by activeAnalysis, which is implied by activeInference).
*/
static const size_t TYPE_LIFO_ALLOC_PRIMARY_CHUNK_SIZE = 128 * 1024;
js::LifoAlloc typeLifoAlloc;
bool activeAnalysis;
bool activeInference;

View File

@ -798,14 +798,6 @@ GCDescription::formatJSON(JSRuntime *rt, uint64_t timestamp) const
return rt->gcStats.formatJSON(timestamp);
}
JS_FRIEND_API(AnalysisPurgeCallback)
SetAnalysisPurgeCallback(JSRuntime *rt, AnalysisPurgeCallback callback)
{
AnalysisPurgeCallback old = rt->analysisPurgeCallback;
rt->analysisPurgeCallback = callback;
return old;
}
JS_FRIEND_API(void)
NotifyDidPaint(JSRuntime *rt)
{

View File

@ -799,12 +799,6 @@ typedef void
extern JS_FRIEND_API(GCSliceCallback)
SetGCSliceCallback(JSRuntime *rt, GCSliceCallback callback);
typedef void
(* AnalysisPurgeCallback)(JSRuntime *rt, JSFlatString *desc);
extern JS_FRIEND_API(AnalysisPurgeCallback)
SetAnalysisPurgeCallback(JSRuntime *rt, AnalysisPurgeCallback callback);
/* Was the most recent GC run incrementally? */
extern JS_FRIEND_API(bool)
WasIncrementalGC(JSRuntime *rt);
@ -812,6 +806,7 @@ WasIncrementalGC(JSRuntime *rt);
typedef JSBool
(* DOMInstanceClassMatchesProto)(JSHandleObject protoObject, uint32_t protoID,
uint32_t depth);
struct JSDOMCallbacks {
DOMInstanceClassMatchesProto instanceClassMatchesProto;
};

View File

@ -4793,9 +4793,6 @@ RunDebugGC(JSContext *cx)
{
rt->gcIncrementalLimit = rt->gcZealFrequency / 2;
}
} else if (type == ZealPurgeAnalysisValue) {
if (!cx->compartment->activeAnalysis)
cx->compartment->types.maybePurgeAnalysis(cx, /* force = */ true);
} else {
Collect(rt, false, SliceBudget::Unlimited, GC_NORMAL, gcreason::DEBUG_GC);
}

View File

@ -1165,7 +1165,6 @@ const int ZealIncrementalMarkAllThenFinish = 9;
const int ZealIncrementalMultipleSlices = 10;
const int ZealVerifierPostValue = 11;
const int ZealFrameVerifierPostValue = 12;
const int ZealPurgeAnalysisValue = 13;
enum VerifierType {
PreBarrierVerifier,

File diff suppressed because it is too large Load Diff

View File

@ -135,35 +135,17 @@ inline Type GetValueType(JSContext *cx, const Value &val);
* Inference constructs a global web of constraints relating the contents of
* type sets particular to various scripts and type objects within a
* compartment. This data can consume a significant amount of memory, and to
* avoid this building up we try to clear it with some regularity.
* avoid this building up we try to clear it with some regularity. On each GC
* which occurs while we are not actively working with inference or other
* analysis information, we clear out all generated constraints, all type sets
* describing stack types within scripts, and (normally) all data describing
* type objects for particular JS objects (see the lazy type objects overview
* below). JIT code depends on this data and is cleared as well.
*
* There are two operations which can clear inference and analysis data.
*
* - Analysis purges clear analysis information while retaining jitcode.
*
* - GCs may clear both analysis information and jitcode. Sometimes GCs will
* preserve all information and code, and will not collect any scripts,
* type objects or singleton JS objects.
*
* There are several categories of data affected differently by the above
* operations.
*
* - Data cleared by every analysis purge and non-preserving GC. This includes
* the ScriptAnalysis for each analyzed script and data from each analysis
* pass performed, type sets for stack values, and all type constraints for
* such type sets and for observed/argument/local type sets on scripts
* (TypeSet::constraintsPurged, aka StackTypeSet). This is exactly the data
* allocated using compartment->analysisLifoAlloc.
*
* - Data cleared by non-preserving GCs. This includes property type sets for
* singleton JS objects, property read input type sets, type constraints on
* all type sets, and dead references in all type sets. This data is all
* allocated using compartment->typeLifoAlloc; the GC copies live data into a
* new allocator and clears the old one.
*
* - Data cleared occasionally by non-preserving GCs. TypeScripts and the data
* in their sets are occasionally destroyed during GC. When a JSScript or
* TypeObject is swept, type information for its contents is destroyed.
* All this data is allocated into compartment->pool. Some type inference data
* lives across GCs: type sets for scripts and non-singleton type objects, and
* propeties for such type objects. This data is also allocated into
* compartment->pool, but everything still live is copied to a new arena on GC.
*/
/*
@ -173,15 +155,23 @@ inline Type GetValueType(JSContext *cx, const Value &val);
class TypeConstraint
{
public:
#ifdef DEBUG
const char *kind_;
const char *kind() const { return kind_; }
#else
const char *kind() const { return NULL; }
#endif
/* Next constraint listening to the same type set. */
TypeConstraint *next;
TypeConstraint()
TypeConstraint(const char *kind)
: next(NULL)
{}
/* Debugging name for this kind of constraint. */
virtual const char *kind() = 0;
{
#ifdef DEBUG
this->kind_ = kind;
#endif
}
/* Register a new type for the set this constraint is listening to. */
virtual void newType(JSContext *cx, TypeSet *source, Type type) = 0;
@ -223,45 +213,30 @@ enum {
/* Mask of normal type flags on a type set. */
TYPE_FLAG_BASE_MASK = 0x000100ff,
/* Flags describing the kind of type set this is. */
/*
* Flag for type sets which describe stack values and are cleared on
* analysis purges.
*/
TYPE_FLAG_PURGED = 0x00020000,
/*
* Flag for type sets whose constraints are cleared on analysis purges.
* This includes all temporary type sets, as well as sets in TypeScript
* which propagate into temporary type sets.
*/
TYPE_FLAG_CONSTRAINTS_PURGED = 0x00040000,
/* Flags for type sets which are on object properties. */
/*
* Whether there are subset constraints propagating the possible types
* for this property inherited from the object's prototypes. Reset on GC.
*/
TYPE_FLAG_PROPAGATED_PROPERTY = 0x00080000,
TYPE_FLAG_PROPAGATED_PROPERTY = 0x00020000,
/* Whether this property has ever been directly written. */
TYPE_FLAG_OWN_PROPERTY = 0x00100000,
TYPE_FLAG_OWN_PROPERTY = 0x00040000,
/*
* Whether the property has ever been deleted or reconfigured to behave
* differently from a normal native property (e.g. made non-writable or
* given a scripted getter or setter).
*/
TYPE_FLAG_CONFIGURED_PROPERTY = 0x00200000,
TYPE_FLAG_CONFIGURED_PROPERTY = 0x00080000,
/*
* Whether the property is definitely in a particular inline slot on all
* objects from which it has not been deleted or reconfigured. Implies
* OWN_PROPERTY and unlike OWN/CONFIGURED property, this cannot change.
*/
TYPE_FLAG_DEFINITE_PROPERTY = 0x00400000,
TYPE_FLAG_DEFINITE_PROPERTY = 0x00100000,
/* If the property is definite, mask and shift storing the slot. */
TYPE_FLAG_DEFINITE_MASK = 0x0f000000,
@ -340,9 +315,6 @@ enum {
};
typedef uint32_t TypeObjectFlags;
class StackTypeSet;
class HeapTypeSet;
/* Information about the set of types associated with an lvalue. */
class TypeSet
{
@ -380,12 +352,12 @@ class TypeSet
return !!(baseFlags() & flags);
}
bool ownProperty(bool configurable) const {
bool isOwnProperty(bool configurable) const {
return flags & (configurable ? TYPE_FLAG_CONFIGURED_PROPERTY : TYPE_FLAG_OWN_PROPERTY);
}
bool definiteProperty() const { return flags & TYPE_FLAG_DEFINITE_PROPERTY; }
bool isDefiniteProperty() const { return flags & TYPE_FLAG_DEFINITE_PROPERTY; }
unsigned definiteSlot() const {
JS_ASSERT(definiteProperty());
JS_ASSERT(isDefiniteProperty());
return flags >> TYPE_FLAG_DEFINITE_SHIFT;
}
@ -421,115 +393,55 @@ class TypeSet
bool hasPropagatedProperty() { return !!(flags & TYPE_FLAG_PROPAGATED_PROPERTY); }
void setPropagatedProperty() { flags |= TYPE_FLAG_PROPAGATED_PROPERTY; }
bool constraintsPurged() { return !!(flags & TYPE_FLAG_CONSTRAINTS_PURGED); }
void setConstraintsPurged() { flags |= TYPE_FLAG_CONSTRAINTS_PURGED; }
enum FilterKind {
FILTER_ALL_PRIMITIVES,
FILTER_NULL_VOID,
FILTER_VOID
};
bool purged() { return !!(flags & TYPE_FLAG_PURGED); }
void setPurged() { flags |= TYPE_FLAG_PURGED | TYPE_FLAG_CONSTRAINTS_PURGED; }
inline StackTypeSet *toStackTypeSet();
inline HeapTypeSet *toHeapTypeSet();
inline void addTypesToConstraint(JSContext *cx, TypeConstraint *constraint);
/* Add specific kinds of constraints to this set. */
inline void add(JSContext *cx, TypeConstraint *constraint, bool callExisting = true);
protected:
uint32_t baseObjectCount() const {
return (flags & TYPE_FLAG_OBJECT_COUNT_MASK) >> TYPE_FLAG_OBJECT_COUNT_SHIFT;
}
inline void setBaseObjectCount(uint32_t count);
inline void clearObjects();
};
/*
* Type set for a stack value manipulated in a script, or the argument or
* local types of said script. Constraints on these type sets are cleared
* during analysis purges; the contents of the sets are implicitly frozen
* during compilation to ensure that changes to the sets trigger recompilation
* of the associated script.
*/
class StackTypeSet : public TypeSet
{
public:
/*
* Make a type set with the specified debugging name, not embedded in
* another structure.
*/
static StackTypeSet *make(JSContext *cx, const char *name);
/* Constraints for type inference. */
void addSubset(JSContext *cx, TypeSet *target);
void addGetProperty(JSContext *cx, JSScript *script, jsbytecode *pc,
StackTypeSet *target, jsid id);
TypeSet *target, jsid id);
void addSetProperty(JSContext *cx, JSScript *script, jsbytecode *pc,
StackTypeSet *target, jsid id);
TypeSet *target, jsid id);
void addCallProperty(JSContext *cx, JSScript *script, jsbytecode *pc, jsid id);
void addSetElement(JSContext *cx, JSScript *script, jsbytecode *pc,
StackTypeSet *objectTypes, StackTypeSet *valueTypes);
TypeSet *objectTypes, TypeSet *valueTypes);
void addCall(JSContext *cx, TypeCallsite *site);
void addArith(JSContext *cx, JSScript *script, jsbytecode *pc,
TypeSet *target, TypeSet *other = NULL);
void addTransformThis(JSContext *cx, JSScript *script, TypeSet *target);
void addPropagateThis(JSContext *cx, JSScript *script, jsbytecode *pc,
Type type, StackTypeSet *types = NULL);
Type type, TypeSet *types = NULL);
void addFilterPrimitives(JSContext *cx, TypeSet *target, FilterKind filter);
void addSubsetBarrier(JSContext *cx, JSScript *script, jsbytecode *pc, TypeSet *target);
/*
* Constraints for JIT compilation.
*
* Methods for JIT compilation. These must be used when a script is
* currently being compiled (see AutoEnterCompilation) and will add
* constraints ensuring that if the return value change in the future due
* to new type information, the script's jitcode will be discarded.
* Make an type set with the specified debugging name, not embedded in
* another structure.
*/
/* Get any type tag which all values in this set must have. */
JSValueType getKnownTypeTag();
bool isMagicArguments() { return getKnownTypeTag() == JSVAL_TYPE_MAGIC; }
/* Whether the type set contains objects with any of a set of flags. */
bool hasObjectFlags(JSContext *cx, TypeObjectFlags flags);
static TypeSet *make(JSContext *cx, const char *name);
/*
* Get the typed array type of all objects in this set. Returns
* TypedArray::TYPE_MAX if the set contains different array types.
* Methods for JIT compilation. If a script is currently being compiled
* (see AutoEnterCompilation) these will add constraints ensuring that if
* the return value change in the future due to new type information, the
* currently compiled script will be marked for recompilation.
*/
int getTypedArrayType();
/* Get the single value which can appear in this type set, otherwise NULL. */
JSObject *getSingleton();
/* Whether any objects in the type set needs a barrier on id. */
bool propertyNeedsBarrier(JSContext *cx, jsid id);
};
/*
* Type set for a property of a TypeObject, or for the return value or property
* read inputs of a script. In contrast with stack type sets, constraints on
* these sets are not cleared during analysis purges, and are not implicitly
* frozen during compilation.
*/
class HeapTypeSet : public TypeSet
{
public:
/* Constraints for type inference. */
void addSubset(JSContext *cx, TypeSet *target);
void addGetProperty(JSContext *cx, JSScript *script, jsbytecode *pc,
StackTypeSet *target, jsid id);
void addCallProperty(JSContext *cx, JSScript *script, jsbytecode *pc, jsid id);
void addFilterPrimitives(JSContext *cx, TypeSet *target);
void addSubsetBarrier(JSContext *cx, JSScript *script, jsbytecode *pc, TypeSet *target);
/* Constraints for JIT compilation. */
/* Completely freeze the contents of this type set. */
void addFreeze(JSContext *cx);
/* Get any type tag which all values in this set must have. */
JSValueType getKnownTypeTag(JSContext *cx);
bool isMagicArguments(JSContext *cx) { return getKnownTypeTag(cx) == JSVAL_TYPE_MAGIC; }
/* Whether the type set or a particular object has any of a set of flags. */
bool hasObjectFlags(JSContext *cx, TypeObjectFlags flags);
static bool HasObjectFlags(JSContext *cx, TypeObject *object, TypeObjectFlags flags);
/*
* Watch for a generic object state change on a type object. This currently
@ -538,9 +450,6 @@ class HeapTypeSet : public TypeSet
*/
static void WatchObjectStateChange(JSContext *cx, TypeObject *object);
/* Whether an object has any of a set of flags. */
static bool HasObjectFlags(JSContext *cx, TypeObject *object, TypeObjectFlags flags);
/*
* For type sets on a property, return true if the property has any 'own'
* values assigned. If configurable is set, return 'true' if the property
@ -556,30 +465,33 @@ class HeapTypeSet : public TypeSet
/* Get whether this type set is known to be a subset of other. */
bool knownSubset(JSContext *cx, TypeSet *other);
/*
* Get the typed array type of all objects in this set. Returns
* TypedArray::TYPE_MAX if the set contains different array types.
*/
int getTypedArrayType(JSContext *cx);
/* Get the single value which can appear in this type set, otherwise NULL. */
JSObject *getSingleton(JSContext *cx);
JSObject *getSingleton(JSContext *cx, bool freeze = true);
inline void clearObjects();
/*
* Whether a location with this TypeSet needs a write barrier (i.e., whether
* it can hold GC things). The type set is frozen if no barrier is needed.
*/
bool needsBarrier(JSContext *cx);
/* The type set is frozen if no barrier is needed. */
bool propertyNeedsBarrier(JSContext *cx, jsid id);
private:
uint32_t baseObjectCount() const {
return (flags & TYPE_FLAG_OBJECT_COUNT_MASK) >> TYPE_FLAG_OBJECT_COUNT_SHIFT;
}
inline void setBaseObjectCount(uint32_t count);
};
inline StackTypeSet *
TypeSet::toStackTypeSet()
{
JS_ASSERT(constraintsPurged());
return (StackTypeSet *) this;
}
inline HeapTypeSet *
TypeSet::toHeapTypeSet()
{
JS_ASSERT(!constraintsPurged());
return (HeapTypeSet *) this;
}
/*
* Handler which persists information about dynamic types pushed within a
* script which can affect its behavior and are not covered by JOF_TYPESET ops,
@ -689,7 +601,7 @@ struct Property
HeapId id;
/* Possible types for this property, including types inherited from prototypes. */
HeapTypeSet types;
TypeSet types;
inline Property(jsid id);
inline Property(const Property &o);
@ -881,10 +793,10 @@ struct TypeObject : gc::Cell
* assignment, and the own types of the property will be used instead of
* aggregate types.
*/
inline HeapTypeSet *getProperty(JSContext *cx, jsid id, bool assign);
inline TypeSet *getProperty(JSContext *cx, jsid id, bool assign);
/* Get a property only if it already exists. */
inline HeapTypeSet *maybeGetProperty(JSContext *cx, jsid id);
inline TypeSet *maybeGetProperty(JSContext *cx, jsid id);
inline unsigned getPropertyCount();
inline Property *getProperty(unsigned i);
@ -989,13 +901,13 @@ struct TypeCallsite
/* Types of each argument to the call. */
unsigned argumentCount;
StackTypeSet **argumentTypes;
TypeSet **argumentTypes;
/* Types of the this variable. */
StackTypeSet *thisTypes;
TypeSet *thisTypes;
/* Type set receiving the return value of this call. */
StackTypeSet *returnTypes;
TypeSet *returnTypes;
inline TypeCallsite(JSContext *cx, JSScript *script, jsbytecode *pc,
bool isNew, unsigned argumentCount);
@ -1013,25 +925,18 @@ class TypeScript
/* Dynamic types generated at points within this script. */
TypeResult *dynamicList;
/*
* Array of type sets storing the possible inputs to property reads.
* Generated the first time the script is analyzed by inference and kept
* after analysis purges.
*/
HeapTypeSet *propertyReadTypes;
/* Array of type type sets for variables and JOF_TYPESET ops. */
TypeSet *typeArray() { return (TypeSet *) (uintptr_t(this) + sizeof(TypeScript)); }
static inline unsigned NumTypeSets(JSScript *script);
static inline HeapTypeSet *ReturnTypes(JSScript *script);
static inline StackTypeSet *ThisTypes(JSScript *script);
static inline StackTypeSet *ArgTypes(JSScript *script, unsigned i);
static inline StackTypeSet *LocalTypes(JSScript *script, unsigned i);
static inline TypeSet *ReturnTypes(JSScript *script);
static inline TypeSet *ThisTypes(JSScript *script);
static inline TypeSet *ArgTypes(JSScript *script, unsigned i);
static inline TypeSet *LocalTypes(JSScript *script, unsigned i);
/* Follows slot layout in jsanalyze.h, can get this/arg/local type sets. */
static inline StackTypeSet *SlotTypes(JSScript *script, unsigned slot);
static inline TypeSet *SlotTypes(JSScript *script, unsigned slot);
#ifdef DEBUG
/* Check that correct types were inferred for the values pushed by this bytecode. */
@ -1079,9 +984,6 @@ class TypeScript
static inline void SetArgument(JSContext *cx, JSScript *script, unsigned arg, Type type);
static inline void SetArgument(JSContext *cx, JSScript *script, unsigned arg, const js::Value &value);
static void AddFreezeConstraints(JSContext *cx, JSScript *script);
static void Purge(JSContext *cx, JSScript *script);
static void Sweep(FreeOp *fop, JSScript *script);
void destroy();
};
@ -1264,9 +1166,6 @@ struct TypeCompartment
void sweep(FreeOp *fop);
void sweepCompilerOutputs(FreeOp *fop);
void maybePurgeAnalysis(JSContext *cx, bool force = false);
void finalizeObjects();
};

View File

@ -602,18 +602,16 @@ TypeScript::NumTypeSets(JSScript *script)
return script->nTypeSets + analyze::TotalSlots(script);
}
/* static */ inline HeapTypeSet *
/* static */ inline TypeSet *
TypeScript::ReturnTypes(JSScript *script)
{
TypeSet *types = script->types->typeArray() + script->nTypeSets + js::analyze::CalleeSlot();
return types->toHeapTypeSet();
return script->types->typeArray() + script->nTypeSets + js::analyze::CalleeSlot();
}
/* static */ inline StackTypeSet *
/* static */ inline TypeSet *
TypeScript::ThisTypes(JSScript *script)
{
TypeSet *types = script->types->typeArray() + script->nTypeSets + js::analyze::ThisSlot();
return types->toStackTypeSet();
return script->types->typeArray() + script->nTypeSets + js::analyze::ThisSlot();
}
/*
@ -622,28 +620,25 @@ TypeScript::ThisTypes(JSScript *script)
* or undefined for localTypes) and not types from subsequent assignments.
*/
/* static */ inline StackTypeSet *
/* static */ inline TypeSet *
TypeScript::ArgTypes(JSScript *script, unsigned i)
{
JS_ASSERT(i < script->function()->nargs);
TypeSet *types = script->types->typeArray() + script->nTypeSets + js::analyze::ArgSlot(i);
return types->toStackTypeSet();
return script->types->typeArray() + script->nTypeSets + js::analyze::ArgSlot(i);
}
/* static */ inline StackTypeSet *
/* static */ inline TypeSet *
TypeScript::LocalTypes(JSScript *script, unsigned i)
{
JS_ASSERT(i < script->nfixed);
TypeSet *types = script->types->typeArray() + script->nTypeSets + js::analyze::LocalSlot(script, i);
return types->toStackTypeSet();
return script->types->typeArray() + script->nTypeSets + js::analyze::LocalSlot(script, i);
}
/* static */ inline StackTypeSet *
/* static */ inline TypeSet *
TypeScript::SlotTypes(JSScript *script, unsigned slot)
{
JS_ASSERT(slot < js::analyze::TotalSlots(script));
TypeSet *types = script->types->typeArray() + script->nTypeSets + slot;
return types->toStackTypeSet();
return script->types->typeArray() + script->nTypeSets + slot;
}
/* static */ inline TypeObject *
@ -1002,7 +997,7 @@ HashKey(T v)
*/
template <class T, class U, class KEY>
static U **
HashSetInsertTry(LifoAlloc &alloc, U **&values, unsigned &count, T key)
HashSetInsertTry(JSCompartment *compartment, U **&values, unsigned &count, T key)
{
unsigned capacity = HashSetCapacity(count);
unsigned insertpos = HashKey<T,KEY>(key) & (capacity - 1);
@ -1026,7 +1021,7 @@ HashSetInsertTry(LifoAlloc &alloc, U **&values, unsigned &count, T key)
return &values[insertpos];
}
U **newValues = alloc.newArray<U*>(newCapacity);
U **newValues = compartment->typeLifoAlloc.newArray<U*>(newCapacity);
if (!newValues)
return NULL;
PodZero(newValues, newCapacity);
@ -1054,7 +1049,7 @@ HashSetInsertTry(LifoAlloc &alloc, U **&values, unsigned &count, T key)
*/
template <class T, class U, class KEY>
static inline U **
HashSetInsert(LifoAlloc &alloc, U **&values, unsigned &count, T key)
HashSetInsert(JSCompartment *compartment, U **&values, unsigned &count, T key)
{
if (count == 0) {
JS_ASSERT(values == NULL);
@ -1067,7 +1062,7 @@ HashSetInsert(LifoAlloc &alloc, U **&values, unsigned &count, T key)
if (KEY::getKey(oldData) == key)
return (U **) &values;
values = alloc.newArray<U*>(SET_ARRAY_SIZE);
values = compartment->typeLifoAlloc.newArray<U*>(SET_ARRAY_SIZE);
if (!values) {
values = (U **) oldData;
return NULL;
@ -1091,7 +1086,7 @@ HashSetInsert(LifoAlloc &alloc, U **&values, unsigned &count, T key)
}
}
return HashSetInsertTry<T,U,KEY>(alloc, values, count, key);
return HashSetInsertTry<T,U,KEY>(compartment, values, count, key);
}
/* Lookup an entry in a hash set, return NULL if it does not exist. */
@ -1213,14 +1208,10 @@ TypeSet::addType(JSContext *cx, Type type)
return;
if (type.isAnyObject())
goto unknownObject;
LifoAlloc &alloc =
purged() ? cx->compartment->analysisLifoAlloc : cx->compartment->typeLifoAlloc;
uint32_t objectCount = baseObjectCount();
TypeObjectKey *object = type.objectKey();
TypeObjectKey **pentry = HashSetInsert<TypeObjectKey *,TypeObjectKey,TypeObjectKey>
(alloc, objectSet, objectCount, object);
(cx->compartment, objectSet, objectCount, object);
if (!pentry) {
cx->compartment->types.setPendingNukeTypes(cx);
return;
@ -1335,7 +1326,7 @@ TypeCallsite::TypeCallsite(JSContext *cx, JSScript *script, jsbytecode *pc,
thisTypes(NULL), returnTypes(NULL)
{
/* Caller must check for failure. */
argumentTypes = cx->analysisLifoAlloc().newArray<StackTypeSet*>(argumentCount);
argumentTypes = cx->typeLifoAlloc().newArray<TypeSet*>(argumentCount);
}
/////////////////////////////////////////////////////////////////////
@ -1373,7 +1364,7 @@ TypeObject::setBasePropertyCount(uint32_t count)
| (count << OBJECT_FLAG_PROPERTY_COUNT_SHIFT);
}
inline HeapTypeSet *
inline TypeSet *
TypeObject::getProperty(JSContext *cx, jsid id, bool assign)
{
JS_ASSERT(cx->compartment->activeInference);
@ -1383,7 +1374,7 @@ TypeObject::getProperty(JSContext *cx, jsid id, bool assign)
uint32_t propertyCount = basePropertyCount();
Property **pprop = HashSetInsert<jsid,Property,Property>
(cx->compartment->typeLifoAlloc, propertySet, propertyCount, id);
(cx->compartment, propertySet, propertyCount, id);
if (!pprop) {
cx->compartment->types.setPendingNukeTypes(cx);
return NULL;
@ -1398,25 +1389,15 @@ TypeObject::getProperty(JSContext *cx, jsid id, bool assign)
}
if (propertyCount == OBJECT_FLAG_PROPERTY_COUNT_LIMIT) {
markUnknown(cx);
/*
* Return an arbitrary property in the object, as all have unknown
* type and are treated as configured.
*/
unsigned count = getPropertyCount();
for (unsigned i = 0; i < count; i++) {
if (Property *prop = getProperty(i))
return &prop->types;
}
JS_NOT_REACHED("Missing property");
return NULL;
TypeSet *types = TypeSet::make(cx, "propertyOverflow");
types->addType(cx, Type::UnknownType());
return types;
}
}
HeapTypeSet *types = &(*pprop)->types;
TypeSet *types = &(*pprop)->types;
if (assign && !types->ownProperty(false)) {
if (assign && !types->isOwnProperty(false)) {
/*
* Normally, we just want to set the property as being an own property
* when we got a set to it. The exception is when the set is actually
@ -1450,7 +1431,7 @@ TypeObject::getProperty(JSContext *cx, jsid id, bool assign)
return types;
}
inline HeapTypeSet *
inline TypeSet *
TypeObject::maybeGetProperty(JSContext *cx, jsid id)
{
JS_ASSERT(JSID_IS_VOID(id) || JSID_IS_EMPTY(id) || JSID_IS_STRING(id));
@ -1643,13 +1624,6 @@ JSScript::clearAnalysis()
types->analysis = NULL;
}
inline void
JSScript::clearPropertyReadTypes()
{
if (types && types->propertyReadTypes)
types->propertyReadTypes = NULL;
}
inline void
js::analyze::ScriptAnalysis::addPushedType(JSContext *cx, uint32_t offset, uint32_t which,
js::types::Type type)

View File

@ -469,9 +469,6 @@ struct JSScript : public js::gc::Cell
JSCompartment::scriptCountsMap */
bool hasDebugScript:1; /* script has an entry in
JSCompartment::debugScriptMap */
bool hasFreezeConstraints:1; /* freeze constraints for stack
* type sets have been generated */
private:
/* See comments below. */
bool argsHasVarBinding_:1;
@ -578,8 +575,6 @@ struct JSScript : public js::gc::Cell
inline void clearAnalysis();
inline js::analyze::ScriptAnalysis *analysis();
inline void clearPropertyReadTypes();
inline bool hasGlobal() const;
inline bool hasClearedGlobal() const;

View File

@ -83,8 +83,6 @@ mjit::Compiler::Compiler(JSContext *cx, JSScript *outerScript,
doubleList(CompilerAllocPolicy(cx, *thisFromCtor())),
rootedTemplates(CompilerAllocPolicy(cx, *thisFromCtor())),
rootedRegExps(CompilerAllocPolicy(cx, *thisFromCtor())),
monitoredBytecodes(CompilerAllocPolicy(cx, *thisFromCtor())),
typeBarrierBytecodes(CompilerAllocPolicy(cx, *thisFromCtor())),
fixedIntToDoubleEntries(CompilerAllocPolicy(cx, *thisFromCtor())),
fixedDoubleToAnyEntries(CompilerAllocPolicy(cx, *thisFromCtor())),
jumpTables(CompilerAllocPolicy(cx, *thisFromCtor())),
@ -227,9 +225,9 @@ mjit::Compiler::scanInlineCalls(uint32_t index, uint32_t depth)
continue;
uint32_t argc = GET_ARGC(pc);
types::StackTypeSet *calleeTypes = analysis->poppedTypes(pc, argc + 1);
types::TypeSet *calleeTypes = analysis->poppedTypes(pc, argc + 1);
if (calleeTypes->getKnownTypeTag() != JSVAL_TYPE_OBJECT)
if (calleeTypes->getKnownTypeTag(cx) != JSVAL_TYPE_OBJECT)
continue;
if (calleeTypes->getObjectCount() >= INLINE_SITE_LIMIT)
@ -334,19 +332,12 @@ mjit::Compiler::scanInlineCalls(uint32_t index, uint32_t depth)
break;
}
if (types::HeapTypeSet::HasObjectFlags(cx, fun->getType(cx),
types::OBJECT_FLAG_UNINLINEABLE)) {
if (types::TypeSet::HasObjectFlags(cx, fun->getType(cx),
types::OBJECT_FLAG_UNINLINEABLE)) {
okay = false;
break;
}
/*
* Watch for a generic state change in the callee's type, so that
* the outer script will be recompiled if any type information
* changes in stack values within the callee.
*/
types::HeapTypeSet::WatchObjectStateChange(cx, fun->getType(cx));
/*
* Don't inline scripts which use 'this' if it is possible they
* could be called with a 'this' value requiring wrapping. During
@ -354,7 +345,7 @@ mjit::Compiler::scanInlineCalls(uint32_t index, uint32_t depth)
* caller.
*/
if (script->analysis()->usesThisValue() &&
types::TypeScript::ThisTypes(script)->getKnownTypeTag() != JSVAL_TYPE_OBJECT) {
types::TypeScript::ThisTypes(script)->getKnownTypeTag(cx) != JSVAL_TYPE_OBJECT) {
okay = false;
break;
}
@ -362,6 +353,8 @@ mjit::Compiler::scanInlineCalls(uint32_t index, uint32_t depth)
if (!okay)
continue;
calleeTypes->addFreeze(cx);
/*
* Add the inline frames to the cross script SSA. We will pick these
* back up when compiling the call site.
@ -1015,13 +1008,6 @@ mjit::CanMethodJIT(JSContext *cx, JSScript *script, jsbytecode *pc,
status = cc.compile();
}
/*
* Check if we have hit the threshold for purging analysis data. This is
* done after compilation, rather than after another analysis stage, to
* ensure we don't throw away the work just performed.
*/
cx->compartment->types.maybePurgeAnalysis(cx);
if (status == Compile_Okay) {
/*
* Compiling a script can occasionally trigger its own recompilation,
@ -1197,7 +1183,7 @@ mjit::Compiler::ensureDoubleArguments()
/* Convert integer arguments which were inferred as (int|double) to doubles. */
for (uint32_t i = 0; script->function() && i < script->function()->nargs; i++) {
uint32_t slot = ArgSlot(i);
if (a->varTypes[slot].getTypeTag() == JSVAL_TYPE_DOUBLE && analysis->trackSlot(slot))
if (a->varTypes[slot].getTypeTag(cx) == JSVAL_TYPE_DOUBLE && analysis->trackSlot(slot))
frame.ensureDouble(frame.getArg(i));
}
}
@ -1345,8 +1331,6 @@ mjit::Compiler::finishThisUp()
sizeof(CallSite) * callSites.length() +
sizeof(JSObject*) * rootedTemplates.length() +
sizeof(RegExpShared*) * rootedRegExps.length() +
sizeof(uint32_t) * monitoredBytecodes.length() +
sizeof(uint32_t) * typeBarrierBytecodes.length() +
#if defined JS_MONOIC
sizeof(ic::GetGlobalNameIC) * getGlobalNames.length() +
sizeof(ic::SetGlobalNameIC) * setGlobalNames.length() +
@ -1490,18 +1474,6 @@ mjit::Compiler::finishThisUp()
jitRootedRegExps[i]->incRef();
}
uint32_t *jitMonitoredBytecodes = (uint32_t *)cursor;
chunk->nMonitoredBytecodes = monitoredBytecodes.length();
cursor += sizeof(uint32_t) * chunk->nMonitoredBytecodes;
for (size_t i = 0; i < chunk->nMonitoredBytecodes; i++)
jitMonitoredBytecodes[i] = monitoredBytecodes[i];
uint32_t *jitTypeBarrierBytecodes = (uint32_t *)cursor;
chunk->nTypeBarrierBytecodes = typeBarrierBytecodes.length();
cursor += sizeof(uint32_t) * chunk->nTypeBarrierBytecodes;
for (size_t i = 0; i < chunk->nTypeBarrierBytecodes; i++)
jitTypeBarrierBytecodes[i] = typeBarrierBytecodes[i];
#if defined JS_MONOIC
if (chunkIndex == 0 && script->function()) {
JS_ASSERT(jit->argsCheckPool == NULL);
@ -2119,7 +2091,7 @@ mjit::Compiler::generateMethod()
if (newv->value.kind() == SSAValue::PHI &&
newv->value.phiOffset() == uint32_t(PC - script->code) &&
analysis->trackSlot(newv->slot) &&
a->varTypes[newv->slot].getTypeTag() == JSVAL_TYPE_DOUBLE) {
a->varTypes[newv->slot].getTypeTag(cx) == JSVAL_TYPE_DOUBLE) {
FrameEntry *fe = frame.getSlotEntry(newv->slot);
masm.ensureInMemoryDouble(frame.addressOf(fe));
}
@ -2141,7 +2113,7 @@ mjit::Compiler::generateMethod()
jsbytecode *backedge = script->code + analysis->getLoop(PC)->backedge;
if (!bytecodeInChunk(backedge)){
for (uint32_t slot = ArgSlot(0); slot < TotalSlots(script); slot++) {
if (a->varTypes[slot].getTypeTag() == JSVAL_TYPE_DOUBLE) {
if (a->varTypes[slot].getTypeTag(cx) == JSVAL_TYPE_DOUBLE) {
FrameEntry *fe = frame.getSlotEntry(slot);
masm.ensureInMemoryDouble(frame.addressOf(fe));
}
@ -3534,9 +3506,9 @@ mjit::Compiler::updateElemCounts(jsbytecode *pc, FrameEntry *obj, FrameEntry *id
masm.bumpCount(&counts.get(count), reg);
if (obj->mightBeType(JSVAL_TYPE_OBJECT)) {
types::StackTypeSet *types = frame.extra(obj).types;
types::TypeSet *types = frame.extra(obj).types;
if (types && !types->hasObjectFlags(cx, types::OBJECT_FLAG_NON_TYPED_ARRAY) &&
types->getTypedArrayType() != TypedArray::TYPE_MAX) {
types->getTypedArrayType(cx) != TypedArray::TYPE_MAX) {
count = PCCounts::ELEM_OBJECT_TYPED;
} else if (types && !types->hasObjectFlags(cx, types::OBJECT_FLAG_NON_DENSE_ARRAY)) {
if (!types->hasObjectFlags(cx, types::OBJECT_FLAG_NON_PACKED_ARRAY))
@ -4258,13 +4230,6 @@ mjit::Compiler::inlineCallHelper(uint32_t argc, bool callingNew, FrameSize &call
callIC.typeMonitored = monitored(PC) || hasTypeBarriers(PC);
if (script == outerScript) {
if (monitored(PC))
monitoredBytecodes.append(PC - script->code);
if (hasTypeBarriers(PC))
typeBarrierBytecodes.append(PC - script->code);
}
/* Test the type if necessary. Failing this always takes a really slow path. */
MaybeJump notObjectJump;
if (icCalleeType.isSet())
@ -4879,7 +4844,7 @@ mjit::Compiler::jsop_getprop(PropertyName *name, JSValueType knownType,
/* Handle lenth accesses of optimize 'arguments'. */
if (name == cx->runtime->atomState.lengthAtom &&
cx->typeInferenceEnabled() &&
analysis->poppedTypes(PC, 0)->isMagicArguments() &&
analysis->poppedTypes(PC, 0)->isMagicArguments(cx) &&
knownPushedType(0) == JSVAL_TYPE_INT32)
{
frame.pop();
@ -4908,7 +4873,7 @@ mjit::Compiler::jsop_getprop(PropertyName *name, JSValueType knownType,
}
}
types::StackTypeSet *types = analysis->poppedTypes(PC, 0);
types::TypeSet *types = analysis->poppedTypes(PC, 0);
/*
* Check if we are accessing the 'length' property of a known dense array.
@ -5038,11 +5003,12 @@ mjit::Compiler::jsop_getprop(PropertyName *name, JSValueType knownType,
id == types::MakeTypeId(cx, id)) {
JS_ASSERT(!forPrototype);
types::TypeObject *object = types->getTypeObject(0);
types::HeapTypeSet *propertyTypes = object->getProperty(cx, id, false);
types::TypeSet *propertyTypes = object->getProperty(cx, id, false);
if (!propertyTypes)
return false;
if (propertyTypes->definiteProperty() &&
if (propertyTypes->isDefiniteProperty() &&
!propertyTypes->isOwnProperty(cx, object, true)) {
types->addFreeze(cx);
uint32_t slot = propertyTypes->definiteSlot();
bool isObject = top->isTypeKnown();
if (!isObject) {
@ -5241,11 +5207,11 @@ mjit::Compiler::testSingletonPropertyTypes(FrameEntry *top, HandleId id, bool *t
{
*testObject = false;
types::StackTypeSet *types = frame.extra(top).types;
types::TypeSet *types = frame.extra(top).types;
if (!types || types->unknownObject())
return false;
RootedObject singleton(cx, types->getSingleton());
RootedObject singleton(cx, types->getSingleton(cx));
if (singleton)
return testSingletonProperty(singleton, id);
@ -5253,7 +5219,7 @@ mjit::Compiler::testSingletonPropertyTypes(FrameEntry *top, HandleId id, bool *t
return false;
JSProtoKey key;
JSValueType type = types->getKnownTypeTag();
JSValueType type = types->getKnownTypeTag(cx);
switch (type) {
case JSVAL_TYPE_STRING:
key = JSProto_String;
@ -5277,6 +5243,7 @@ mjit::Compiler::testSingletonPropertyTypes(FrameEntry *top, HandleId id, bool *t
Rooted<JSObject*> proto(cx, object->proto);
if (!testSingletonProperty(proto, id))
return false;
types->addFreeze(cx);
/* If we don't know this is an object, we will need a test. */
*testObject = (type != JSVAL_TYPE_OBJECT) && !top->isTypeKnown();
@ -5327,6 +5294,8 @@ mjit::Compiler::jsop_getprop_dispatch(PropertyName *name)
if (objTypes->unknownObject() || objTypes->getObjectCount() == 0)
return false;
pushedTypes->addFreeze(cx);
/* Map each type in the object to the resulting pushed value. */
Vector<JSObject *> results(CompilerAllocPolicy(cx, *this));
@ -5345,7 +5314,7 @@ mjit::Compiler::jsop_getprop_dispatch(PropertyName *name)
}
if (object->unknownProperties() || !object->proto)
return false;
types::HeapTypeSet *ownTypes = object->getProperty(cx, id, false);
types::TypeSet *ownTypes = object->getProperty(cx, id, false);
if (ownTypes->isOwnProperty(cx, object, false))
return false;
@ -5355,7 +5324,7 @@ mjit::Compiler::jsop_getprop_dispatch(PropertyName *name)
if (proto->getType(cx)->unknownProperties())
return false;
types::HeapTypeSet *protoTypes = proto->type()->getProperty(cx, id, false);
types::TypeSet *protoTypes = proto->type()->getProperty(cx, id, false);
if (!protoTypes)
return false;
JSObject *singleton = protoTypes->getSingleton(cx);
@ -5369,6 +5338,8 @@ mjit::Compiler::jsop_getprop_dispatch(PropertyName *name)
if (oomInVector)
return false;
objTypes->addFreeze(cx);
/* Done filtering, now generate code which dispatches on the type. */
frame.forgetMismatchedObject(top);
@ -5459,7 +5430,7 @@ mjit::Compiler::jsop_setprop(PropertyName *name, bool popGuaranteed)
* always has the property in a particular inline slot.
*/
jsid id = NameToId(name);
types::StackTypeSet *types = frame.extra(lhs).types;
types::TypeSet *types = frame.extra(lhs).types;
if (JSOp(*PC) == JSOP_SETPROP && id == types::MakeTypeId(cx, id) &&
types && !types->unknownObject() &&
types->getObjectCount() == 1 &&
@ -5467,11 +5438,12 @@ mjit::Compiler::jsop_setprop(PropertyName *name, bool popGuaranteed)
!types->getTypeObject(0)->unknownProperties())
{
types::TypeObject *object = types->getTypeObject(0);
types::HeapTypeSet *propertyTypes = object->getProperty(cx, id, false);
types::TypeSet *propertyTypes = object->getProperty(cx, id, false);
if (!propertyTypes)
return false;
if (propertyTypes->definiteProperty() &&
if (propertyTypes->isDefiniteProperty() &&
!propertyTypes->isOwnProperty(cx, object, true)) {
types->addFreeze(cx);
uint32_t slot = propertyTypes->definiteSlot();
RegisterID reg = frame.tempRegForData(lhs);
frame.pinReg(reg);
@ -5525,11 +5497,19 @@ mjit::Compiler::jsop_setprop(PropertyName *name, bool popGuaranteed)
pic.name = name;
if (monitored(PC)) {
if (script == outerScript)
monitoredBytecodes.append(PC - script->code);
pic.typeMonitored = true;
types::TypeSet *types = frame.extra(rhs).types;
if (!types) {
/* Handle FORNAME and other compound opcodes. Yuck. */
types = types::TypeSet::make(cx, "unknownRHS");
if (!types)
return false;
types->addType(cx, types::Type::UnknownType());
}
pic.rhsTypes = types;
} else {
pic.typeMonitored = false;
pic.rhsTypes = NULL;
}
RESERVE_IC_SPACE(masm);
@ -5965,7 +5945,7 @@ mjit::Compiler::jsop_this()
}
JSValueType type = cx->typeInferenceEnabled()
? types::TypeScript::ThisTypes(script)->getKnownTypeTag()
? types::TypeScript::ThisTypes(script)->getKnownTypeTag(cx)
: JSVAL_TYPE_UNKNOWN;
if (type != JSVAL_TYPE_OBJECT) {
Jump notObj = frame.testObject(Assembler::NotEqual, thisFe);
@ -6312,7 +6292,7 @@ mjit::Compiler::jsop_getgname(uint32_t index)
JSValueType type = knownPushedType(0);
if (cx->typeInferenceEnabled() && globalObj->isGlobal() && id == types::MakeTypeId(cx, id) &&
!globalObj->getType(cx)->unknownProperties()) {
types::HeapTypeSet *propertyTypes = globalObj->getType(cx)->getProperty(cx, id, false);
types::TypeSet *propertyTypes = globalObj->getType(cx)->getProperty(cx, id, false);
if (!propertyTypes)
return false;
@ -6427,9 +6407,6 @@ bool
mjit::Compiler::jsop_setgname(PropertyName *name, bool popGuaranteed)
{
if (monitored(PC)) {
if (script == outerScript)
monitoredBytecodes.append(PC - script->code);
/* Global accesses are monitored only for a few names like __proto__. */
jsop_setgname_slow(name);
return true;
@ -6444,7 +6421,7 @@ mjit::Compiler::jsop_setgname(PropertyName *name, bool popGuaranteed)
* can't get a function later and cause the global object to become
* branded, requiring a shape change if it changes again.
*/
types::HeapTypeSet *types = globalObj->getType(cx)->getProperty(cx, id, false);
types::TypeSet *types = globalObj->getType(cx)->getProperty(cx, id, false);
if (!types)
return false;
js::Shape *shape = globalObj->nativeLookup(cx, NameToId(name));
@ -6800,8 +6777,8 @@ mjit::Compiler::jsop_regexp()
&obj->global() != globalObj ||
!cx->typeInferenceEnabled() ||
analysis->localsAliasStack() ||
types::HeapTypeSet::HasObjectFlags(cx, globalObj->getType(cx),
types::OBJECT_FLAG_REGEXP_FLAGS_SET))
types::TypeSet::HasObjectFlags(cx, globalObj->getType(cx),
types::OBJECT_FLAG_REGEXP_FLAGS_SET))
{
prepareStubCall(Uses(0));
masm.move(ImmPtr(obj), Registers::ArgReg1);
@ -6831,7 +6808,7 @@ mjit::Compiler::jsop_regexp()
jsbytecode *use = script->code + uses->offset;
uint32_t which = uses->u.which;
if (JSOp(*use) == JSOP_CALLPROP) {
JSObject *callee = analysis->pushedTypes(use, 0)->getSingleton();
JSObject *callee = analysis->pushedTypes(use, 0)->getSingleton(cx);
if (callee && callee->isFunction()) {
Native native = callee->toFunction()->maybeNative();
if (native == js::regexp_exec || native == js::regexp_test) {
@ -6841,7 +6818,7 @@ mjit::Compiler::jsop_regexp()
}
} else if (JSOp(*use) == JSOP_CALL && which == 0) {
uint32_t argc = GET_ARGC(use);
JSObject *callee = analysis->poppedTypes(use, argc + 1)->getSingleton();
JSObject *callee = analysis->poppedTypes(use, argc + 1)->getSingleton(cx);
if (callee && callee->isFunction() && argc >= 1 && which == argc - 1) {
Native native = callee->toFunction()->maybeNative();
if (native == js::str_match ||
@ -6996,7 +6973,7 @@ mjit::Compiler::finishLoop(jsbytecode *head)
* variables are coherent in such cases.
*/
for (uint32_t slot = ArgSlot(0); slot < TotalSlots(script); slot++) {
if (a->varTypes[slot].getTypeTag() == JSVAL_TYPE_DOUBLE) {
if (a->varTypes[slot].getTypeTag(cx) == JSVAL_TYPE_DOUBLE) {
FrameEntry *fe = frame.getSlotEntry(slot);
stubcc.masm.ensureInMemoryDouble(frame.addressOf(fe));
}
@ -7014,8 +6991,8 @@ mjit::Compiler::finishLoop(jsbytecode *head)
analysis->trackSlot(newv->slot))
{
JS_ASSERT(newv->slot < TotalSlots(script));
types::StackTypeSet *targetTypes = analysis->getValueTypes(newv->value);
if (targetTypes->getKnownTypeTag() == JSVAL_TYPE_DOUBLE) {
types::TypeSet *targetTypes = analysis->getValueTypes(newv->value);
if (targetTypes->getKnownTypeTag(cx) == JSVAL_TYPE_DOUBLE) {
FrameEntry *fe = frame.getSlotEntry(newv->slot);
stubcc.masm.ensureInMemoryDouble(frame.addressOf(fe));
}
@ -7100,7 +7077,7 @@ mjit::Compiler::jumpAndRun(Jump j, jsbytecode *target, Jump *slow, bool *trampol
if (cx->typeInferenceEnabled()) {
RegisterAllocation *&alloc = analysis->getAllocation(target);
if (!alloc) {
alloc = cx->analysisLifoAlloc().new_<RegisterAllocation>(false);
alloc = cx->typeLifoAlloc().new_<RegisterAllocation>(false);
if (!alloc) {
js_ReportOutOfMemory(cx);
return false;
@ -7204,9 +7181,9 @@ mjit::Compiler::constructThis()
}
jsid id = NameToId(cx->runtime->atomState.classPrototypeAtom);
types::HeapTypeSet *protoTypes = fun->getType(cx)->getProperty(cx, id, false);
types::TypeSet *protoTypes = fun->getType(cx)->getProperty(cx, id, false);
JSObject *proto = protoTypes->getSingleton(cx);
JSObject *proto = protoTypes->getSingleton(cx, true);
if (!proto)
break;
@ -7231,7 +7208,7 @@ mjit::Compiler::constructThis()
* should this information change later.
*/
if (templateObject->type()->newScript)
types::HeapTypeSet::WatchObjectStateChange(cx, templateObject->type());
types::TypeSet::WatchObjectStateChange(cx, templateObject->type());
RegisterID result = frame.allocReg();
Jump emptyFreeList = getNewObject(cx, result, templateObject);
@ -7240,7 +7217,7 @@ mjit::Compiler::constructThis()
stubcc.leave();
stubcc.masm.move(ImmPtr(proto), Registers::ArgReg1);
OOL_STUBCALL(stubs::CreateThis, REJOIN_THIS_CREATED);
OOL_STUBCALL(stubs::CreateThis, REJOIN_RESUME);
frame.setThis(result);
@ -7274,7 +7251,7 @@ mjit::Compiler::constructThis()
prepareStubCall(Uses(0));
if (protoReg != Registers::ArgReg1)
masm.move(protoReg, Registers::ArgReg1);
INLINE_STUBCALL(stubs::CreateThis, REJOIN_THIS_CREATED);
INLINE_STUBCALL(stubs::CreateThis, REJOIN_RESUME);
frame.freeReg(protoReg);
return true;
}
@ -7399,7 +7376,7 @@ mjit::Compiler::jsop_in()
FrameEntry *id = frame.peek(-2);
if (cx->typeInferenceEnabled() && id->isType(JSVAL_TYPE_INT32)) {
types::StackTypeSet *types = analysis->poppedTypes(PC, 0);
types::TypeSet *types = analysis->poppedTypes(PC, 0);
if (obj->mightBeType(JSVAL_TYPE_OBJECT) &&
!types->hasObjectFlags(cx, types::OBJECT_FLAG_NON_DENSE_ARRAY) &&
@ -7501,11 +7478,11 @@ mjit::Compiler::fixDoubleTypes(jsbytecode *target)
continue;
}
JS_ASSERT(newv->slot < TotalSlots(script));
types::StackTypeSet *targetTypes = analysis->getValueTypes(newv->value);
types::TypeSet *targetTypes = analysis->getValueTypes(newv->value);
FrameEntry *fe = frame.getSlotEntry(newv->slot);
VarType &vt = a->varTypes[newv->slot];
JSValueType type = vt.getTypeTag();
if (targetTypes->getKnownTypeTag() == JSVAL_TYPE_DOUBLE) {
JSValueType type = vt.getTypeTag(cx);
if (targetTypes->getKnownTypeTag(cx) == JSVAL_TYPE_DOUBLE) {
if (type == JSVAL_TYPE_INT32) {
fixedIntToDoubleEntries.append(newv->slot);
frame.ensureDouble(fe);
@ -7537,7 +7514,7 @@ mjit::Compiler::watchGlobalReallocation()
JS_ASSERT(cx->typeInferenceEnabled());
if (hasGlobalReallocation)
return;
types::HeapTypeSet::WatchObjectStateChange(cx, globalObj->getType(cx));
types::TypeSet::WatchObjectStateChange(cx, globalObj->getType(cx));
hasGlobalReallocation = true;
}
@ -7554,7 +7531,7 @@ mjit::Compiler::updateVarType()
* (see prepareInferenceTypes).
*/
types::StackTypeSet *types = pushedTypeSet(0);
types::TypeSet *types = pushedTypeSet(0);
uint32_t slot = GetBytecodeSlot(script, PC);
if (analysis->trackSlot(slot)) {
@ -7566,7 +7543,7 @@ mjit::Compiler::updateVarType()
* maintained by the frame as a double. We might forget the exact
* representation used by the next call to fixDoubleTypes, fix it now.
*/
if (vt.getTypeTag() == JSVAL_TYPE_DOUBLE)
if (vt.getTypeTag(cx) == JSVAL_TYPE_DOUBLE)
frame.ensureDouble(frame.getSlotEntry(slot));
}
}
@ -7583,9 +7560,9 @@ mjit::Compiler::updateJoinVarTypes()
while (newv->slot) {
if (newv->slot < TotalSlots(script)) {
VarType &vt = a->varTypes[newv->slot];
JSValueType type = vt.getTypeTag();
JSValueType type = vt.getTypeTag(cx);
vt.setTypes(analysis->getValueTypes(newv->value));
if (vt.getTypeTag() != type) {
if (vt.getTypeTag(cx) != type) {
/*
* If the known type of a variable changes (even if the
* variable itself has not been reassigned) then we can't
@ -7616,7 +7593,7 @@ mjit::Compiler::restoreVarType()
* of tracked variables match their inferred type (as tracked in varTypes),
* but may have forgotten it due to a branch or syncAndForgetEverything.
*/
JSValueType type = a->varTypes[slot].getTypeTag();
JSValueType type = a->varTypes[slot].getTypeTag(cx);
if (type != JSVAL_TYPE_UNKNOWN &&
(type != JSVAL_TYPE_DOUBLE || analysis->trackSlot(slot))) {
FrameEntry *fe = frame.getSlotEntry(slot);
@ -7631,8 +7608,8 @@ mjit::Compiler::knownPushedType(uint32_t pushed)
{
if (!cx->typeInferenceEnabled())
return JSVAL_TYPE_UNKNOWN;
types::StackTypeSet *types = analysis->pushedTypes(PC, pushed);
return types->getKnownTypeTag();
types::TypeSet *types = analysis->pushedTypes(PC, pushed);
return types->getKnownTypeTag(cx);
}
bool
@ -7650,7 +7627,7 @@ mjit::Compiler::mayPushUndefined(uint32_t pushed)
return types->hasType(types::Type::UndefinedType());
}
types::StackTypeSet *
types::TypeSet *
mjit::Compiler::pushedTypeSet(uint32_t pushed)
{
if (!cx->typeInferenceEnabled())
@ -7687,8 +7664,8 @@ mjit::Compiler::pushedSingleton(unsigned pushed)
if (!cx->typeInferenceEnabled())
return NULL;
types::StackTypeSet *types = analysis->pushedTypes(PC, pushed);
return types->getSingleton();
types::TypeSet *types = analysis->pushedTypes(PC, pushed);
return types->getSingleton(cx);
}
/*
@ -7742,7 +7719,7 @@ mjit::Compiler::pushAddressMaybeBarrier(Address address, JSValueType type, bool
}
MaybeJump
mjit::Compiler::trySingleTypeTest(types::StackTypeSet *types, RegisterID typeReg)
mjit::Compiler::trySingleTypeTest(types::TypeSet *types, RegisterID typeReg)
{
/*
* If a type set we have a barrier on is monomorphic, generate a single
@ -7752,7 +7729,7 @@ mjit::Compiler::trySingleTypeTest(types::StackTypeSet *types, RegisterID typeReg
*/
MaybeJump res;
switch (types->getKnownTypeTag()) {
switch (types->getKnownTypeTag(cx)) {
case JSVAL_TYPE_INT32:
res.setJump(masm.testInt32(Assembler::NotEqual, typeReg));
return res;
@ -7775,7 +7752,7 @@ mjit::Compiler::trySingleTypeTest(types::StackTypeSet *types, RegisterID typeReg
}
JSC::MacroAssembler::Jump
mjit::Compiler::addTypeTest(types::StackTypeSet *types, RegisterID typeReg, RegisterID dataReg)
mjit::Compiler::addTypeTest(types::TypeSet *types, RegisterID typeReg, RegisterID dataReg)
{
/*
* :TODO: It would be good to merge this with GenerateTypeCheck, but the
@ -7845,7 +7822,7 @@ mjit::Compiler::testBarrier(RegisterID typeReg, RegisterID dataReg,
if (!cx->typeInferenceEnabled() || !(js_CodeSpec[*PC].format & JOF_TYPESET))
return state;
types::StackTypeSet *types = analysis->bytecodeTypes(PC);
types::TypeSet *types = analysis->bytecodeTypes(PC);
if (types->unknown()) {
/*
* If the result of this opcode is already unknown, there is no way for
@ -7864,8 +7841,7 @@ mjit::Compiler::testBarrier(RegisterID typeReg, RegisterID dataReg,
return state;
}
if (hasTypeBarriers(PC))
typeBarrierBytecodes.append(PC - script->code);
types->addFreeze(cx);
/* Cannot have type barriers when the result of the operation is already unknown. */
JS_ASSERT(!types->unknown());

View File

@ -209,6 +209,7 @@ class Compiler : public BaseCompiler
bool hasTypeCheck;
bool typeMonitored;
bool cached;
types::TypeSet *rhsTypes;
ValueRemat vr;
union {
ic::GetPropLabels getPropLabels_;
@ -248,6 +249,7 @@ class Compiler : public BaseCompiler
}
ic.typeMonitored = typeMonitored;
ic.cached = cached;
ic.rhsTypes = rhsTypes;
if (ic.isGet())
ic.setLabels(getPropLabels());
else if (ic.isSet())
@ -319,19 +321,19 @@ class Compiler : public BaseCompiler
*/
class VarType {
JSValueType type;
types::StackTypeSet *types;
types::TypeSet *types;
public:
void setTypes(types::StackTypeSet *types) {
void setTypes(types::TypeSet *types) {
this->types = types;
this->type = JSVAL_TYPE_MISSING;
}
types::TypeSet *getTypes() { return types; }
JSValueType getTypeTag() {
JSValueType getTypeTag(JSContext *cx) {
if (type == JSVAL_TYPE_MISSING)
type = types ? types->getKnownTypeTag() : JSVAL_TYPE_UNKNOWN;
type = types ? types->getKnownTypeTag(cx) : JSVAL_TYPE_UNKNOWN;
return type;
}
};
@ -431,8 +433,6 @@ private:
js::Vector<DoublePatch, 16, CompilerAllocPolicy> doubleList;
js::Vector<JSObject*, 0, CompilerAllocPolicy> rootedTemplates;
js::Vector<RegExpShared*, 0, CompilerAllocPolicy> rootedRegExps;
js::Vector<uint32_t> monitoredBytecodes;
js::Vector<uint32_t> typeBarrierBytecodes;
js::Vector<uint32_t> fixedIntToDoubleEntries;
js::Vector<uint32_t> fixedDoubleToAnyEntries;
js::Vector<JumpTable, 16> jumpTables;
@ -547,7 +547,7 @@ private:
void restoreVarType();
JSValueType knownPushedType(uint32_t pushed);
bool mayPushUndefined(uint32_t pushed);
types::StackTypeSet *pushedTypeSet(uint32_t which);
types::TypeSet *pushedTypeSet(uint32_t which);
bool monitored(jsbytecode *pc);
bool hasTypeBarriers(jsbytecode *pc);
bool testSingletonProperty(HandleObject obj, HandleId id);
@ -562,8 +562,8 @@ private:
RegisterID dataReg;
};
MaybeJump trySingleTypeTest(types::StackTypeSet *types, RegisterID typeReg);
Jump addTypeTest(types::StackTypeSet *types, RegisterID typeReg, RegisterID dataReg);
MaybeJump trySingleTypeTest(types::TypeSet *types, RegisterID typeReg);
Jump addTypeTest(types::TypeSet *types, RegisterID typeReg, RegisterID dataReg);
BarrierState pushAddressMaybeBarrier(Address address, JSValueType type, bool reuseBase,
bool testUndefined = false);
BarrierState testBarrier(RegisterID typeReg, RegisterID dataReg,

View File

@ -615,7 +615,9 @@ mjit::Compiler::compileArrayConcat(types::TypeSet *thisTypes, types::TypeSet *ar
* so check that type information already reflects possible side effects of
* this call.
*/
types::HeapTypeSet *thisElemTypes = thisType->getProperty(cx, JSID_VOID, false);
thisTypes->addFreeze(cx);
argTypes->addFreeze(cx);
types::TypeSet *thisElemTypes = thisType->getProperty(cx, JSID_VOID, false);
if (!thisElemTypes)
return Compile_Error;
if (!pushedTypeSet(0)->hasType(types::Type::ObjectType(thisType)))
@ -626,7 +628,7 @@ mjit::Compiler::compileArrayConcat(types::TypeSet *thisTypes, types::TypeSet *ar
types::TypeObject *argType = argTypes->getTypeObject(i);
if (!argType)
continue;
types::HeapTypeSet *elemTypes = argType->getProperty(cx, JSID_VOID, false);
types::TypeSet *elemTypes = argType->getProperty(cx, JSID_VOID, false);
if (!elemTypes)
return Compile_Error;
if (!elemTypes->knownSubset(cx, thisElemTypes))
@ -873,7 +875,7 @@ mjit::Compiler::inlineNativeFunction(uint32_t argc, bool callingNew)
FrameEntry *origCallee = frame.peek(-((int)argc + 2));
FrameEntry *thisValue = frame.peek(-((int)argc + 1));
types::StackTypeSet *thisTypes = analysis->poppedTypes(PC, argc);
types::TypeSet *thisTypes = analysis->poppedTypes(PC, argc);
if (!origCallee->isConstant() || !origCallee->isType(JSVAL_TYPE_OBJECT))
return Compile_InlineAbort;
@ -945,7 +947,7 @@ mjit::Compiler::inlineNativeFunction(uint32_t argc, bool callingNew)
}
} else if (argc == 1) {
FrameEntry *arg = frame.peek(-1);
types::StackTypeSet *argTypes = frame.extra(arg).types;
types::TypeSet *argTypes = frame.extra(arg).types;
if (!argTypes)
return Compile_InlineAbort;
JSValueType argType = arg->isTypeKnown() ? arg->getKnownType() : JSVAL_TYPE_UNKNOWN;

View File

@ -387,8 +387,8 @@ mjit::Compiler::jsop_equality_obj_obj(JSOp op, jsbytecode *target, JSOp fused)
* special equality operator on either object, if that passes then
* this is a pointer comparison.
*/
types::StackTypeSet *lhsTypes = analysis->poppedTypes(PC, 1);
types::StackTypeSet *rhsTypes = analysis->poppedTypes(PC, 0);
types::TypeSet *lhsTypes = analysis->poppedTypes(PC, 1);
types::TypeSet *rhsTypes = analysis->poppedTypes(PC, 0);
if (!lhsTypes->hasObjectFlags(cx, types::OBJECT_FLAG_SPECIAL_EQUALITY) &&
!rhsTypes->hasObjectFlags(cx, types::OBJECT_FLAG_SPECIAL_EQUALITY)) {
/* :TODO: Merge with jsop_relational_int? */
@ -896,8 +896,8 @@ mjit::Compiler::jsop_localinc(JSOp op, uint32_t slot)
{
restoreVarType();
types::StackTypeSet *types = pushedTypeSet(0);
JSValueType type = types ? types->getKnownTypeTag() : JSVAL_TYPE_UNKNOWN;
types::TypeSet *types = pushedTypeSet(0);
JSValueType type = types ? types->getKnownTypeTag(cx) : JSVAL_TYPE_UNKNOWN;
int amt = (op == JSOP_LOCALINC || op == JSOP_INCLOCAL) ? 1 : -1;
@ -959,8 +959,8 @@ mjit::Compiler::jsop_arginc(JSOp op, uint32_t slot)
{
restoreVarType();
types::StackTypeSet *types = pushedTypeSet(0);
JSValueType type = types ? types->getKnownTypeTag() : JSVAL_TYPE_UNKNOWN;
types::TypeSet *types = pushedTypeSet(0);
JSValueType type = types ? types->getKnownTypeTag(cx) : JSVAL_TYPE_UNKNOWN;
int amt = (op == JSOP_ARGINC || op == JSOP_INCARG) ? 1 : -1;
@ -1169,7 +1169,7 @@ mjit::Compiler::jsop_setelem_dense()
* because in that case the slot we're overwriting was previously
* undefined.
*/
types::StackTypeSet *types = frame.extra(obj).types;
types::TypeSet *types = frame.extra(obj).types;
if (cx->compartment->compileBarriers() && (!types || types->propertyNeedsBarrier(cx, JSID_VOID))) {
Label barrierStart = stubcc.masm.label();
stubcc.linkExitDirect(masm.jump(), barrierStart);
@ -1538,9 +1538,6 @@ mjit::Compiler::jsop_setelem(bool popGuaranteed)
FrameEntry *value = frame.peek(-1);
if (!IsCacheableSetElem(obj, id, value) || monitored(PC)) {
if (monitored(PC) && script == outerScript)
monitoredBytecodes.append(PC - script->code);
jsop_setelem_slow();
return true;
}
@ -1548,7 +1545,7 @@ mjit::Compiler::jsop_setelem(bool popGuaranteed)
// If the object is definitely a dense array or a typed array we can generate
// code directly without using an inline cache.
if (cx->typeInferenceEnabled()) {
types::StackTypeSet *types = analysis->poppedTypes(PC, 2);
types::TypeSet *types = analysis->poppedTypes(PC, 2);
if (!types->hasObjectFlags(cx, types::OBJECT_FLAG_NON_DENSE_ARRAY) &&
!types::ArrayPrototypeHasIndexedProperty(cx, outerScript)) {
@ -1561,7 +1558,7 @@ mjit::Compiler::jsop_setelem(bool popGuaranteed)
if ((value->mightBeType(JSVAL_TYPE_INT32) || value->mightBeType(JSVAL_TYPE_DOUBLE)) &&
!types->hasObjectFlags(cx, types::OBJECT_FLAG_NON_TYPED_ARRAY)) {
// Inline typed array path.
int atype = types->getTypedArrayType();
int atype = types->getTypedArrayType(cx);
if (atype != TypedArray::TYPE_MAX) {
jsop_setelem_typed(atype);
return true;
@ -2148,8 +2145,8 @@ mjit::Compiler::jsop_getelem()
// If the object is definitely an arguments object, a dense array or a typed array
// we can generate code directly without using an inline cache.
if (cx->typeInferenceEnabled() && !id->isType(JSVAL_TYPE_STRING)) {
types::StackTypeSet *types = analysis->poppedTypes(PC, 1);
if (types->isMagicArguments() && !outerScript->analysis()->modifiesArguments()) {
types::TypeSet *types = analysis->poppedTypes(PC, 1);
if (types->isMagicArguments(cx) && !outerScript->analysis()->modifiesArguments()) {
// Inline arguments path.
jsop_getelem_args();
return true;
@ -2168,7 +2165,7 @@ mjit::Compiler::jsop_getelem()
if (obj->mightBeType(JSVAL_TYPE_OBJECT) &&
!types->hasObjectFlags(cx, types::OBJECT_FLAG_NON_TYPED_ARRAY)) {
// Inline typed array path.
int atype = types->getTypedArrayType();
int atype = types->getTypedArrayType(cx);
if (atype != TypedArray::TYPE_MAX) {
if (jsop_getelem_typed(atype))
return true;
@ -2689,9 +2686,6 @@ mjit::Compiler::jsop_initprop()
RootedObject baseobj(cx, frame.extra(obj).initObject);
if (!baseobj || monitored(PC) || cx->compartment->compileBarriers()) {
if (monitored(PC) && script == outerScript)
monitoredBytecodes.append(PC - script->code);
prepareStubCall(Uses(2));
masm.move(ImmPtr(name), Registers::ArgReg1);
INLINE_STUBCALL(stubs::InitProp, REJOIN_FALLTHROUGH);

View File

@ -29,8 +29,7 @@ FrameState::~FrameState()
{
while (a) {
ActiveFrame *parent = a->parent;
if (a->script->hasAnalysis())
a->script->analysis()->clearAllocations();
a->script->analysis()->clearAllocations();
cx->free_(a);
a = parent;
}
@ -543,7 +542,7 @@ RegisterAllocation *
FrameState::computeAllocation(jsbytecode *target)
{
JS_ASSERT(cx->typeInferenceEnabled());
RegisterAllocation *alloc = cx->analysisLifoAlloc().new_<RegisterAllocation>(false);
RegisterAllocation *alloc = cx->typeLifoAlloc().new_<RegisterAllocation>(false);
if (!alloc) {
js_ReportOutOfMemory(cx);
return NULL;
@ -593,8 +592,8 @@ FrameState::computeAllocation(jsbytecode *target)
if (newv->value.kind() == SSAValue::PHI &&
newv->value.phiOffset() == uint32_t(target - a->script->code) &&
newv->slot == entrySlot(fe)) {
types::StackTypeSet *types = a->analysis->getValueTypes(newv->value);
if (types->getKnownTypeTag() != JSVAL_TYPE_DOUBLE)
types::TypeSet *types = a->analysis->getValueTypes(newv->value);
if (types->getKnownTypeTag(cx) != JSVAL_TYPE_DOUBLE)
nonDoubleTarget = true;
}
newv++;
@ -826,7 +825,7 @@ FrameState::discardForJoin(RegisterAllocation *&alloc, uint32_t stackDepth)
* This shows up for loop entries which are not reachable from the
* loop head, and for exception, switch target and trap safe points.
*/
alloc = cx->analysisLifoAlloc().new_<RegisterAllocation>(false);
alloc = cx->typeLifoAlloc().new_<RegisterAllocation>(false);
if (!alloc) {
js_ReportOutOfMemory(cx);
return false;

View File

@ -698,7 +698,7 @@ class FrameState
struct StackEntryExtra {
bool initArray;
JSObject *initObject;
types::StackTypeSet *types;
types::TypeSet *types;
JSAtom *name;
void reset() { PodZero(this); }
};

View File

@ -867,10 +867,7 @@ js_InternalInterpret(void *returnData, void *returnType, void *returnReg, js::VM
if (!obj)
return js_InternalThrow(f);
fp->thisValue() = ObjectValue(*obj);
/* FALLTHROUGH */
}
case REJOIN_THIS_CREATED: {
Probes::enterScript(f.cx, f.script(), f.script()->function(), fp);
if (script->debugMode) {
@ -878,13 +875,9 @@ js_InternalInterpret(void *returnData, void *returnType, void *returnReg, js::VM
switch (status) {
case JSTRAP_CONTINUE:
break;
case JSTRAP_RETURN: {
/* Advance to the JSOP_STOP at the end of the script. */
f.regs.pc = script->code + script->length - 1;
nextDepth = 0;
JS_ASSERT(*f.regs.pc == JSOP_STOP);
break;
}
case JSTRAP_RETURN:
*f.returnAddressLocation() = f.cx->jaegerRuntime().forceReturnFromExternC();
return NULL;
case JSTRAP_THROW:
case JSTRAP_ERROR:
return js_InternalThrow(f);

View File

@ -126,7 +126,7 @@ LoopState::init(jsbytecode *head, Jump entry, jsbytecode *entryTarget)
RegisterAllocation *&alloc = outerAnalysis->getAllocation(head);
JS_ASSERT(!alloc);
alloc = cx->analysisLifoAlloc().new_<RegisterAllocation>(true);
alloc = cx->typeLifoAlloc().new_<RegisterAllocation>(true);
if (!alloc) {
js_ReportOutOfMemory(cx);
return false;
@ -140,7 +140,7 @@ LoopState::init(jsbytecode *head, Jump entry, jsbytecode *entryTarget)
* had indirect modification of their arguments.
*/
if (outerScript->function()) {
if (HeapTypeSet::HasObjectFlags(cx, outerScript->function()->getType(cx), OBJECT_FLAG_UNINLINEABLE))
if (TypeSet::HasObjectFlags(cx, outerScript->function()->getType(cx), OBJECT_FLAG_UNINLINEABLE))
this->skipAnalysis = true;
}
@ -778,10 +778,10 @@ LoopState::invariantLength(const CrossSSAValue &obj)
int32_t objConstant;
if (!getEntryValue(obj, &objSlot, &objConstant) || objSlot == UNASSIGNED || objConstant != 0)
return NULL;
StackTypeSet *objTypes = ssa->getValueTypes(obj);
TypeSet *objTypes = ssa->getValueTypes(obj);
/* Check for 'length' on the lazy arguments for the current frame. */
if (objTypes->isMagicArguments()) {
if (objTypes->isMagicArguments(cx)) {
JS_ASSERT(obj.frame == CrossScriptSSA::OUTER_FRAME);
for (unsigned i = 0; i < invariantEntries.length(); i++) {
@ -824,6 +824,9 @@ LoopState::invariantLength(const CrossSSAValue &obj)
/* Hoist 'length' access on typed arrays. */
if (!objTypes->hasObjectFlags(cx, OBJECT_FLAG_NON_TYPED_ARRAY)) {
/* Recompile if object type changes. */
objTypes->addFreeze(cx);
uint32_t which = frame.allocTemporary();
if (which == UINT32_MAX)
return NULL;
@ -858,6 +861,7 @@ LoopState::invariantLength(const CrossSSAValue &obj)
if (object && hasModifiedProperty(object, JSID_VOID))
return NULL;
}
objTypes->addFreeze(cx);
uint32_t which = frame.allocTemporary();
if (which == UINT32_MAX)
@ -909,11 +913,12 @@ LoopState::invariantProperty(const CrossSSAValue &obj, jsid id)
TypeObject *object = objTypes->getTypeObject(0);
if (!object || object->unknownProperties() || hasModifiedProperty(object, id) || id != MakeTypeId(cx, id))
return NULL;
HeapTypeSet *propertyTypes = object->getProperty(cx, id, false);
TypeSet *propertyTypes = object->getProperty(cx, id, false);
if (!propertyTypes)
return NULL;
if (!propertyTypes->definiteProperty() || propertyTypes->isOwnProperty(cx, object, true))
if (!propertyTypes->isDefiniteProperty() || propertyTypes->isOwnProperty(cx, object, true))
return NULL;
objTypes->addFreeze(cx);
uint32_t which = frame.allocTemporary();
if (which == UINT32_MAX)
@ -1173,8 +1178,8 @@ LoopState::ignoreIntegerOverflow(const CrossSSAValue &pushed)
return false;
}
StackTypeSet *lhsTypes = outerAnalysis->poppedTypes(use->offset, 1);
if (lhsTypes->getKnownTypeTag() != JSVAL_TYPE_INT32)
TypeSet *lhsTypes = outerAnalysis->poppedTypes(use->offset, 1);
if (lhsTypes->getKnownTypeTag(cx) != JSVAL_TYPE_INT32)
return false;
JaegerSpew(JSpew_Analysis, "Integer result is RHS in integer addition\n");
@ -1566,8 +1571,8 @@ LoopState::analyzeLoopTest()
SSAValue two = outerAnalysis->poppedValue(test.pushedOffset(), 0);
/* The test must be comparing known integers. */
if (outerAnalysis->getValueTypes(one)->getKnownTypeTag() != JSVAL_TYPE_INT32 ||
outerAnalysis->getValueTypes(two)->getKnownTypeTag() != JSVAL_TYPE_INT32) {
if (outerAnalysis->getValueTypes(one)->getKnownTypeTag(cx) != JSVAL_TYPE_INT32 ||
outerAnalysis->getValueTypes(two)->getKnownTypeTag(cx) != JSVAL_TYPE_INT32) {
return;
}
@ -1670,11 +1675,11 @@ LoopState::definiteArrayAccess(const SSAValue &obj, const SSAValue &index)
* other value by which the overflow could be observed.
*/
StackTypeSet *objTypes = outerAnalysis->getValueTypes(obj);
StackTypeSet *elemTypes = outerAnalysis->getValueTypes(index);
TypeSet *objTypes = outerAnalysis->getValueTypes(obj);
TypeSet *elemTypes = outerAnalysis->getValueTypes(index);
if (objTypes->getKnownTypeTag() != JSVAL_TYPE_OBJECT ||
elemTypes->getKnownTypeTag() != JSVAL_TYPE_INT32) {
if (objTypes->getKnownTypeTag(cx) != JSVAL_TYPE_OBJECT ||
elemTypes->getKnownTypeTag(cx) != JSVAL_TYPE_INT32) {
return false;
}
@ -1796,18 +1801,19 @@ LoopState::analyzeLoopBody(unsigned frame)
SSAValue objValue = analysis->poppedValue(pc, 2);
SSAValue elemValue = analysis->poppedValue(pc, 1);
StackTypeSet *objTypes = analysis->getValueTypes(objValue);
StackTypeSet *elemTypes = analysis->getValueTypes(elemValue);
TypeSet *objTypes = analysis->getValueTypes(objValue);
TypeSet *elemTypes = analysis->getValueTypes(elemValue);
/*
* Mark the modset as unknown if the index might be non-integer,
* we don't want to consider the SETELEM PIC here.
*/
if (objTypes->unknownObject() || elemTypes->getKnownTypeTag() != JSVAL_TYPE_INT32) {
if (objTypes->unknownObject() || elemTypes->getKnownTypeTag(cx) != JSVAL_TYPE_INT32) {
unknownModset = true;
break;
}
objTypes->addFreeze(cx);
for (unsigned i = 0; i < objTypes->getObjectCount(); i++) {
TypeObject *object = objTypes->getTypeObject(i);
if (!object)
@ -1842,6 +1848,7 @@ LoopState::analyzeLoopBody(unsigned frame)
break;
}
objTypes->addFreeze(cx);
for (unsigned i = 0; i < objTypes->getObjectCount(); i++) {
TypeObject *object = objTypes->getTypeObject(i);
if (!object)
@ -1909,7 +1916,7 @@ LoopState::analyzeLoopBody(unsigned frame)
case JSOP_GE:
case JSOP_STRICTEQ:
case JSOP_STRICTNE: {
JSValueType type = analysis->poppedTypes(pc, 1)->getKnownTypeTag();
JSValueType type = analysis->poppedTypes(pc, 1)->getKnownTypeTag(cx);
if (type != JSVAL_TYPE_INT32 && type != JSVAL_TYPE_DOUBLE)
constrainedLoop = false;
}
@ -1918,7 +1925,7 @@ LoopState::analyzeLoopBody(unsigned frame)
case JSOP_POS:
case JSOP_NEG:
case JSOP_BITNOT: {
JSValueType type = analysis->poppedTypes(pc, 0)->getKnownTypeTag();
JSValueType type = analysis->poppedTypes(pc, 0)->getKnownTypeTag(cx);
if (type != JSVAL_TYPE_INT32 && type != JSVAL_TYPE_DOUBLE)
constrainedLoop = false;
break;

View File

@ -1122,22 +1122,10 @@ JITChunk::rootedRegExps() const
return (RegExpShared **)&rootedTemplates()[nRootedTemplates];
}
uint32_t *
JITChunk::monitoredBytecodes() const
{
return (uint32_t *)&rootedRegExps()[nRootedRegExps];
}
uint32_t *
JITChunk::typeBarrierBytecodes() const
{
return (uint32_t *)&monitoredBytecodes()[nMonitoredBytecodes];
}
char *
JITChunk::commonSectionLimit() const
{
return (char *)&typeBarrierBytecodes()[nTypeBarrierBytecodes];
return (char *)&rootedRegExps()[nRootedRegExps];
}
#ifdef JS_MONOIC
@ -1269,9 +1257,6 @@ JITScript::destroy(FreeOp *fop)
for (unsigned i = 0; i < nchunks; i++)
destroyChunk(fop, i);
if (liveness)
fop->free_(liveness);
if (shimPool)
shimPool->release();
}
@ -1399,8 +1384,6 @@ size_t
mjit::JITScript::sizeOfIncludingThis(JSMallocSizeOfFun mallocSizeOf)
{
size_t n = mallocSizeOf(this);
if (liveness)
n += mallocSizeOf(liveness);
for (unsigned i = 0; i < nchunks; i++) {
const ChunkDescriptor &desc = chunkDescriptor(i);
if (desc.chunk)
@ -1419,8 +1402,6 @@ mjit::JITChunk::computedSizeOfIncludingThis()
sizeof(CallSite) * nCallSites +
sizeof(JSObject*) * nRootedTemplates +
sizeof(RegExpShared*) * nRootedRegExps +
sizeof(uint32_t) * nMonitoredBytecodes +
sizeof(uint32_t) * nTypeBarrierBytecodes +
#if defined JS_MONOIC
sizeof(ic::GetGlobalNameIC) * nGetGlobalNames +
sizeof(ic::SetGlobalNameIC) * nSetGlobalNames +

View File

@ -37,10 +37,6 @@ namespace mjit {
struct JITScript;
}
namespace analyze {
struct ScriptLiveness;
}
struct VMFrame
{
#if defined(JS_CPU_SPARC)
@ -304,9 +300,6 @@ enum RejoinState {
*/
REJOIN_THIS_PROTOTYPE,
/* As above, after the 'this' object has been created. */
REJOIN_THIS_CREATED,
/*
* Type check on arguments failed during prologue, need stack check and
* the rest of the JIT prologue before the script can execute.
@ -656,8 +649,6 @@ struct JITChunk
uint32_t nCallSites;
uint32_t nRootedTemplates;
uint32_t nRootedRegExps;
uint32_t nMonitoredBytecodes;
uint32_t nTypeBarrierBytecodes;
#ifdef JS_MONOIC
uint32_t nGetGlobalNames;
uint32_t nSetGlobalNames;
@ -686,15 +677,6 @@ struct JITChunk
js::mjit::CallSite *callSites() const;
JSObject **rootedTemplates() const;
RegExpShared **rootedRegExps() const;
/*
* Offsets of bytecodes which were monitored or had type barriers at the
* point of compilation. Used to avoid unnecessary recompilation after
* analysis purges.
*/
uint32_t *monitoredBytecodes() const;
uint32_t *typeBarrierBytecodes() const;
#ifdef JS_MONOIC
ic::GetGlobalNameIC *getGlobalNames() const;
ic::SetGlobalNameIC *setGlobalNames() const;
@ -804,12 +786,6 @@ struct JITScript
*/
JSC::ExecutablePool *shimPool;
/*
* Optional liveness information attached to the JITScript if the analysis
* information is purged while retaining JIT info.
*/
analyze::ScriptLiveness *liveness;
#ifdef JS_MONOIC
/* Inline cache at function entry for checking this/argument types. */
JSC::CodeLocationLabel argsCheckStub;

View File

@ -410,17 +410,7 @@ class SetPropCompiler : public PICStubCompiler
types::TypeSet *types = type->getProperty(cx, types::MakeTypeId(cx, id), true);
if (!types)
return false;
jsbytecode *pc;
JSScript *script = cx->stack.currentScript(&pc);
if (!script->ensureRanInference(cx) || monitor.recompiled())
return false;
JS_ASSERT(*pc == JSOP_SETPROP || *pc == JSOP_SETNAME);
types::StackTypeSet *rhsTypes = script->analysis()->poppedTypes(pc, 0);
rhsTypes->addSubset(cx, types);
pic.rhsTypes->addSubset(cx, types);
}
return !monitor.recompiled();

View File

@ -409,6 +409,9 @@ struct PICInfo : public BasePolyIC {
// Offset from start of fast path to initial shape guard.
uint32_t shapeGuard;
// Possible types of the RHS, for monitored SETPROP PICs.
types::TypeSet *rhsTypes;
inline bool isSet() const {
return kind == SET;
}

View File

@ -725,8 +725,6 @@ pref("javascript.options.mem.gc_low_frequency_heap_growth", 150);
pref("javascript.options.mem.gc_dynamic_heap_growth", true);
pref("javascript.options.mem.gc_dynamic_mark_slice", true);
pref("javascript.options.mem.analysis_purge_mb", 100);
// advanced prefs
pref("advanced.mailftp", false);
pref("image.animation_mode", "normal");