Bug 864928 - Remove ScriptAnalysis::analyzeTypes, r=jandem.

This commit is contained in:
Brian Hackett 2013-09-02 15:39:31 -07:00
Родитель a8d96b359f
Коммит 3a92a6a72f
7 изменённых файлов: 21 добавлений и 2442 удалений

Просмотреть файл

@ -1787,88 +1787,6 @@ ScriptAnalysis::needsArgsObj(JSContext *cx)
return needsArgsObj(cx, seen, SSAValue::PushedValue(pcOff, 0));
}
CrossSSAValue
CrossScriptSSA::foldValue(const CrossSSAValue &cv)
{
const Frame &frame = getFrame(cv.frame);
const SSAValue &v = cv.v;
JSScript *parentScript = NULL;
ScriptAnalysis *parentAnalysis = NULL;
if (frame.parent != INVALID_FRAME) {
parentScript = getFrame(frame.parent).script;
parentAnalysis = parentScript->analysis();
}
if (v.kind() == SSAValue::VAR && v.varInitial() && parentScript) {
uint32_t slot = v.varSlot();
if (slot >= ArgSlot(0) && slot < LocalSlot(frame.script, 0)) {
uint32_t argc = GET_ARGC(frame.parentpc);
SSAValue argv = parentAnalysis->poppedValue(frame.parentpc, argc - 1 - (slot - ArgSlot(0)));
return foldValue(CrossSSAValue(frame.parent, argv));
}
}
if (v.kind() == SSAValue::PUSHED) {
jsbytecode *pc = frame.script->code + v.pushedOffset();
switch (JSOp(*pc)) {
case JSOP_THIS:
if (parentScript) {
uint32_t argc = GET_ARGC(frame.parentpc);
SSAValue thisv = parentAnalysis->poppedValue(frame.parentpc, argc);
return foldValue(CrossSSAValue(frame.parent, thisv));
}
break;
case JSOP_CALL: {
/*
* If there is a single inline callee with a single return site,
* propagate back to that.
*/
JSScript *callee = NULL;
uint32_t calleeFrame = INVALID_FRAME;
for (unsigned i = 0; i < numFrames(); i++) {
if (iterFrame(i).parent == cv.frame && iterFrame(i).parentpc == pc) {
if (callee)
return cv; /* Multiple callees */
callee = iterFrame(i).script;
calleeFrame = iterFrame(i).index;
}
}
if (callee && callee->analysis()->numReturnSites() == 1) {
ScriptAnalysis *analysis = callee->analysis();
uint32_t offset = 0;
while (offset < callee->length) {
jsbytecode *pc = callee->code + offset;
if (analysis->maybeCode(pc) && JSOp(*pc) == JSOP_RETURN)
return foldValue(CrossSSAValue(calleeFrame, analysis->poppedValue(pc, 0)));
offset += GetBytecodeLength(pc);
}
}
break;
}
case JSOP_TOID: {
/*
* TOID acts as identity for integers, so to get better precision
* we should propagate its popped values forward if it acted as
* identity.
*/
ScriptAnalysis *analysis = frame.script->analysis();
SSAValue toidv = analysis->poppedValue(pc, 0);
if (analysis->getValueTypes(toidv)->getKnownTypeTag() == JSVAL_TYPE_INT32)
return foldValue(CrossSSAValue(cv.frame, toidv));
break;
}
default:;
}
}
return cv;
}
#ifdef DEBUG
void

Просмотреть файл

@ -78,15 +78,6 @@ class Bytecode
/* Whether this is a catch/finally entry point. */
bool exceptionEntry : 1;
/*
* Side effects of this bytecode were not determined by type inference.
* Either a property set with unknown lvalue, or call with unknown callee.
*/
bool monitoredTypes : 1;
/* Call whose result should be monitored. */
bool monitoredTypesReturn : 1;
/*
* Dynamically observed state about the execution of this opcode. These are
* hints about the script for use during compilation.
@ -129,14 +120,6 @@ class Bytecode
*/
Vector<SlotValue> *pendingValues;
};
/* --------- Type inference --------- */
/* Types for all values pushed by this bytecode. */
types::StackTypeSet *pushedTypes;
/* Any type barriers in place at this bytecode. */
types::TypeBarrier *typeBarriers;
};
/*
@ -471,7 +454,6 @@ class SSAValue
uint32_t phiSlot() const;
uint32_t phiLength() const;
const SSAValue &phiValue(uint32_t i) const;
types::TypeSet *phiTypes() const;
/* Offset at which this phi node was created. */
uint32_t phiOffset() const {
@ -571,7 +553,6 @@ class SSAValue
*/
struct SSAPhiNode
{
types::StackTypeSet types;
uint32_t slot;
uint32_t length;
SSAValue *options;
@ -599,13 +580,6 @@ SSAValue::phiValue(uint32_t i) const
return u.phi.node->options[i];
}
inline types::TypeSet *
SSAValue::phiTypes() const
{
JS_ASSERT(kind() == PHI);
return &u.phi.node->types;
}
class SSAUseChain
{
public:
@ -654,7 +628,6 @@ class ScriptAnalysis
bool ranBytecode_;
bool ranSSA_;
bool ranLifetimes_;
bool ranInference_;
#ifdef DEBUG
/* Whether the compartment was in debug mode when we performed the analysis. */
@ -689,15 +662,10 @@ class ScriptAnalysis
bool ranBytecode() { return ranBytecode_; }
bool ranSSA() { return ranSSA_; }
bool ranLifetimes() { return ranLifetimes_; }
bool ranInference() { return ranInference_; }
void analyzeBytecode(JSContext *cx);
void analyzeSSA(JSContext *cx);
void analyzeLifetimes(JSContext *cx);
void analyzeTypes(JSContext *cx);
/* Analyze the effect of invoking 'new' on script. */
void analyzeTypesNew(JSContext *cx);
bool OOM() const { return outOfMemory; }
bool failed() const { return hadFailure; }
@ -760,45 +728,6 @@ class ScriptAnalysis
}
const SlotValue *newValues(const jsbytecode *pc) { return newValues(pc - script_->code); }
inline types::StackTypeSet *pushedTypes(uint32_t offset, uint32_t which = 0);
inline types::StackTypeSet *pushedTypes(const jsbytecode *pc, uint32_t which);
bool hasPushedTypes(const jsbytecode *pc) { return getCode(pc).pushedTypes != NULL; }
types::TypeBarrier *typeBarriers(JSContext *cx, uint32_t offset) {
if (getCode(offset).typeBarriers)
pruneTypeBarriers(cx, offset);
return getCode(offset).typeBarriers;
}
types::TypeBarrier *typeBarriers(JSContext *cx, const jsbytecode *pc) {
return typeBarriers(cx, pc - script_->code);
}
void addTypeBarrier(JSContext *cx, const jsbytecode *pc,
types::TypeSet *target, types::Type type);
void addSingletonTypeBarrier(JSContext *cx, const jsbytecode *pc,
types::TypeSet *target,
HandleObject singleton, HandleId singletonId);
/* Remove obsolete type barriers at the given offset. */
void pruneTypeBarriers(JSContext *cx, uint32_t offset);
/*
* Remove still-active type barriers at the given offset. If 'all' is set,
* then all barriers are removed, otherwise only those deemed excessive
* are removed.
*/
void breakTypeBarriers(JSContext *cx, uint32_t offset, bool all);
/* Break all type barriers used in computing v. */
void breakTypeBarriersSSA(JSContext *cx, const SSAValue &v);
inline void addPushedType(JSContext *cx, uint32_t offset, uint32_t which, types::Type type);
inline types::StackTypeSet *getValueTypes(const SSAValue &v);
inline types::StackTypeSet *poppedTypes(uint32_t offset, uint32_t which);
inline types::StackTypeSet *poppedTypes(const jsbytecode *pc, uint32_t which);
bool trackUseChain(const SSAValue &v) {
JS_ASSERT_IF(v.kind() == SSAValue::VAR, trackSlot(v.varSlot()));
return v.kind() != SSAValue::EMPTY &&
@ -912,9 +841,6 @@ class ScriptAnalysis
{}
};
/* Type inference helpers */
bool analyzeTypesBytecode(JSContext *cx, unsigned offset, TypeInferenceState &state);
typedef Vector<SSAValue, 16> SeenVector;
bool needsArgsObj(JSContext *cx, SeenVector &seen, const SSAValue &v);
bool needsArgsObj(JSContext *cx, SeenVector &seen, SSAUseChain *use);
@ -928,84 +854,6 @@ class ScriptAnalysis
#endif
};
/* SSA value as used by CrossScriptSSA, identifies the frame it came from. */
struct CrossSSAValue
{
unsigned frame;
SSAValue v;
CrossSSAValue(unsigned frame, const SSAValue &v) : frame(frame), v(v) {}
};
/*
* Analysis for managing SSA values from multiple call stack frames. These are
* created by the backend compiler when inlining functions, and allow for
* values to be tracked as they flow into or out of the inlined frames.
*/
class CrossScriptSSA
{
public:
static const uint32_t OUTER_FRAME = UINT32_MAX;
static const unsigned INVALID_FRAME = uint32_t(-2);
struct Frame {
uint32_t index;
JSScript *script;
uint32_t depth; /* Distance from outer frame to this frame, in sizeof(Value) */
uint32_t parent;
jsbytecode *parentpc;
Frame(uint32_t index, JSScript *script, uint32_t depth, uint32_t parent,
jsbytecode *parentpc)
: index(index), script(script), depth(depth), parent(parent), parentpc(parentpc)
{}
};
const Frame &getFrame(uint32_t index) {
if (index == OUTER_FRAME)
return outerFrame;
return inlineFrames[index];
}
unsigned numFrames() { return 1 + inlineFrames.length(); }
const Frame &iterFrame(unsigned i) {
if (i == 0)
return outerFrame;
return inlineFrames[i - 1];
}
JSScript *outerScript() { return outerFrame.script; }
/* Total length of scripts preceding a frame. */
size_t frameLength(uint32_t index) {
if (index == OUTER_FRAME)
return 0;
size_t res = outerFrame.script->length;
for (unsigned i = 0; i < index; i++)
res += inlineFrames[i].script->length;
return res;
}
inline types::StackTypeSet *getValueTypes(const CrossSSAValue &cv);
bool addInlineFrame(JSScript *script, uint32_t depth, uint32_t parent,
jsbytecode *parentpc)
{
uint32_t index = inlineFrames.length();
return inlineFrames.append(Frame(index, script, depth, parent, parentpc));
}
CrossScriptSSA(JSContext *cx, JSScript *outer)
: outerFrame(OUTER_FRAME, outer, 0, INVALID_FRAME, NULL), inlineFrames(cx)
{}
CrossSSAValue foldValue(const CrossSSAValue &cv);
private:
Frame outerFrame;
Vector<Frame> inlineFrames;
};
#ifdef DEBUG
void PrintBytecode(JSContext *cx, HandleScript script, jsbytecode *pc);
#endif

Просмотреть файл

@ -29,64 +29,6 @@ ScriptAnalysis::poppedValue(const jsbytecode *pc, uint32_t which)
return poppedValue(pc - script_->code, which);
}
inline types::StackTypeSet *
ScriptAnalysis::pushedTypes(uint32_t offset, uint32_t which)
{
JS_ASSERT(offset < script_->length);
JS_ASSERT(which < GetDefCount(script_, offset) +
(ExtendedDef(script_->code + offset) ? 1 : 0));
types::StackTypeSet *array = getCode(offset).pushedTypes;
JS_ASSERT(array);
return array + which;
}
inline types::StackTypeSet *
ScriptAnalysis::pushedTypes(const jsbytecode *pc, uint32_t which)
{
return pushedTypes(pc - script_->code, which);
}
inline types::StackTypeSet *
ScriptAnalysis::getValueTypes(const SSAValue &v)
{
switch (v.kind()) {
case SSAValue::PUSHED:
return pushedTypes(v.pushedOffset(), v.pushedIndex());
case SSAValue::VAR:
JS_ASSERT(!slotEscapes(v.varSlot()));
if (v.varInitial()) {
if (v.varSlot() < LocalSlot(script_, 0))
return types::TypeScript::SlotTypes(script_, v.varSlot());
return undefinedTypeSet;
} else {
/*
* Results of intermediate assignments have the same type as
* the first type pushed by the assignment op. Note that this
* may not be the exact same value as was pushed, due to
* post-inc/dec ops.
*/
return pushedTypes(v.varOffset(), 0);
}
case SSAValue::PHI:
return &v.phiNode()->types;
default:
/* Cannot compute types for empty SSA values. */
MOZ_ASSUME_UNREACHABLE("Bad SSA value");
}
}
inline types::StackTypeSet *
ScriptAnalysis::poppedTypes(uint32_t offset, uint32_t which)
{
return getValueTypes(poppedValue(offset, which));
}
inline types::StackTypeSet *
ScriptAnalysis::poppedTypes(const jsbytecode *pc, uint32_t which)
{
return getValueTypes(poppedValue(pc, which));
}
inline SSAUseChain *&
ScriptAnalysis::useChain(const SSAValue &v)
{
@ -107,12 +49,6 @@ ScriptAnalysis::getCallPC(jsbytecode *pc)
return script_->code + uses->offset;
}
inline types::StackTypeSet *
CrossScriptSSA::getValueTypes(const CrossSSAValue &cv)
{
return getFrame(cv.frame).script->analysis()->getValueTypes(cv.v);
}
} /* namespace analyze */
} /* namespace js */

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -571,22 +571,8 @@ class StackTypeSet : public TypeSet
*/
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);
void addSetProperty(JSContext *cx, JSScript *script, jsbytecode *pc,
StackTypeSet *target, jsid id);
void addSetElement(JSContext *cx, JSScript *script, jsbytecode *pc,
StackTypeSet *objectTypes, StackTypeSet *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);
void addSubsetBarrier(JSContext *cx, JSScript *script, jsbytecode *pc, TypeSet *target);
/* Propagate any types from this set into target. */
void addSubset(JSContext *cx, StackTypeSet *target);
/*
* Constraints for JIT compilation.
@ -679,16 +665,8 @@ 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. */
/* Propagate any types from this set into target. */
void addSubset(JSContext *cx, HeapTypeSet *target);
/* Completely freeze the contents of this type set. */
void addFreeze(JSContext *cx);
@ -1152,7 +1130,7 @@ struct TypeObject : gc::Cell
void clearAddendum(ExclusiveContext *cx);
void clearNewScriptAddendum(ExclusiveContext *cx);
void clearBinaryDataAddendum(ExclusiveContext *cx);
void getFromPrototypes(JSContext *cx, jsid id, TypeSet *types, bool force = false);
void getFromPrototypes(JSContext *cx, jsid id, HeapTypeSet *types, bool force = false);
void print();
@ -1500,10 +1478,6 @@ struct TypeCompartment
void addPendingRecompile(JSContext *cx, const RecompileInfo &info);
void addPendingRecompile(JSContext *cx, JSScript *script);
/* Monitor future effects on a bytecode. */
void monitorBytecode(JSContext *cx, JSScript *script, uint32_t offset,
bool returnOnly = false);
/* Mark any type set containing obj as having a generic object type. */
void markSetsUnknown(JSContext *cx, TypeObject *obj);

Просмотреть файл

@ -1682,18 +1682,6 @@ JSScript::ensureRanAnalysis(JSContext *cx)
return true;
}
inline bool
JSScript::ensureRanInference(JSContext *cx)
{
if (!ensureRanAnalysis(cx))
return false;
if (!analysis()->ranInference()) {
js::types::AutoEnterAnalysis enter(cx);
analysis()->analyzeTypes(cx);
}
return !analysis()->OOM() && !cx->zone()->types.pendingNukeTypes;
}
inline bool
JSScript::hasAnalysis()
{
@ -1723,14 +1711,6 @@ JSScript::clearPropertyReadTypes()
types->propertyReadTypes = NULL;
}
inline void
js::analyze::ScriptAnalysis::addPushedType(JSContext *cx, uint32_t offset, uint32_t which,
js::types::Type type)
{
js::types::TypeSet *pushed = pushedTypes(offset, which);
pushed->addType(cx, type);
}
namespace js {
template <>

Просмотреть файл

@ -2834,11 +2834,6 @@ JSScript::argumentsOptimizationFailed(JSContext *cx, HandleScript script)
}
}
if (script->hasAnalysis() && script->analysis()->ranInference()) {
types::AutoEnterAnalysis enter(cx);
types::TypeScript::MonitorUnknown(cx, script, script->argumentsBytecode());
}
return true;
}