Backed out changeset 4ca9a6bd8f64 (bug 865059) for jsreftest crashes.

This commit is contained in:
Ryan VanderMeulen 2013-05-06 22:20:26 -04:00
parent 0dbb3c55f6
commit c7f7e6de00
22 changed files with 100 additions and 262 deletions

View File

@ -4367,9 +4367,6 @@ EmitNormalFor(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
if (EmitJump(cx, bce, op, top - bce->offset()) < 0)
return false;
if (!bce->tryNoteList.append(JSTRY_LOOP, bce->stackDepth, top, bce->offset()))
return false;
/* Now fixup all breaks and continues. */
return PopStatementBCE(cx, bce);
}
@ -4556,9 +4553,6 @@ EmitDo(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
if (beq < 0)
return false;
if (!bce->tryNoteList.append(JSTRY_LOOP, bce->stackDepth, top, bce->offset()))
return false;
/*
* Be careful: We must set noteIndex2 before noteIndex in case the noteIndex
* note gets bigger.
@ -4615,9 +4609,6 @@ EmitWhile(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, ptrdiff_t top)
if (beq < 0)
return false;
if (!bce->tryNoteList.append(JSTRY_LOOP, bce->stackDepth, top, bce->offset()))
return false;
if (!SetSrcNoteOffset(cx, bce, noteIndex, 0, beq - jmp))
return false;

View File

@ -10,20 +10,6 @@
using namespace js;
using namespace js::ion;
bool
SetElemICInspector::sawOOBDenseWrite() const
{
if (!icEntry_)
return false;
// Check for a SetElem_DenseAdd stub.
for (ICStub *stub = icEntry_->firstStub(); stub; stub = stub->next()) {
if (stub->isSetElem_DenseAdd())
return true;
}
return false;
}
bool
SetElemICInspector::sawOOBTypedArrayWrite() const
{

View File

@ -39,7 +39,6 @@ class SetElemICInspector : public ICInspector
: ICInspector(inspector, pc, icEntry)
{ }
bool sawOOBDenseWrite() const;
bool sawOOBTypedArrayWrite() const;
};

View File

@ -197,7 +197,7 @@ IonBuilder::canEnterInlinedFunction(JSFunction *target)
{
RootedScript targetScript(cx, target->nonLazyScript());
if (!targetScript->ensureRanAnalysis(cx))
if (!targetScript->hasAnalysis())
return false;
if (!targetScript->analysis()->ionInlineable())
@ -313,7 +313,7 @@ IonBuilder::analyzeNewLoopTypes(MBasicBlock *entry, jsbytecode *start, jsbytecod
MPhi *phi = entry->getSlot(slot)->toPhi();
if (js_CodeSpec[*last].format & JOF_TYPESET) {
types::StackTypeSet *typeSet = types::TypeScript::BytecodeTypes(script(), last);
types::StackTypeSet *typeSet = script()->analysis()->bytecodeTypes(last);
if (!typeSet->empty()) {
MIRType type = MIRTypeFromValueType(typeSet->getKnownTypeTag());
phi->addBackedgeType(type, typeSet);
@ -427,9 +427,6 @@ IonBuilder::pushLoop(CFGState::State initial, jsbytecode *stopAt, MBasicBlock *e
bool
IonBuilder::build()
{
if (!script()->ensureHasBytecodeTypeMap(cx))
return false;
setCurrentAndSpecializePhis(newBlock(pc));
if (!current)
return false;
@ -4554,7 +4551,7 @@ IonBuilder::jsop_funapplyarguments(uint32_t argc)
if (!resumeAfter(apply))
return false;
types::StackTypeSet *types = types::TypeScript::BytecodeTypes(script(), pc);
types::StackTypeSet *types = script()->analysis()->bytecodeTypes(pc);
return pushTypeBarrier(apply, types, true);
}
@ -4875,7 +4872,7 @@ IonBuilder::makeCall(HandleFunction target, CallInfo &callInfo, bool cloneAtCall
if (!resumeAfter(call))
return false;
types::StackTypeSet *types = types::TypeScript::BytecodeTypes(script(), pc);
types::StackTypeSet *types = script()->analysis()->bytecodeTypes(pc);
bool barrier = true;
if (call->isDOMFunction()) {
@ -4968,7 +4965,7 @@ IonBuilder::jsop_eval(uint32_t argc)
current->add(ins);
current->push(ins);
types::StackTypeSet *types = types::TypeScript::BytecodeTypes(script(), pc);
types::StackTypeSet *types = script()->analysis()->bytecodeTypes(pc);
return resumeAfter(ins) && pushTypeBarrier(ins, types, true);
}
@ -5021,7 +5018,7 @@ IonBuilder::jsop_newarray(uint32_t count)
return false;
types::StackTypeSet::DoubleConversion conversion =
types::TypeScript::BytecodeTypes(script(), pc)->convertDoubleElements(cx);
script()->analysis()->bytecodeTypes(pc)->convertDoubleElements(cx);
if (conversion == types::StackTypeSet::AlwaysConvertToDoubles)
templateObject->setShouldConvertDoubleElements();
@ -5422,10 +5419,7 @@ IonBuilder::newPendingLoopHeader(MBasicBlock *predecessor, jsbytecode *pc, bool
bool haveValue = false;
Value existingValue;
if (info().fun() && i == info().thisSlot()) {
haveValue = true;
existingValue = fp.thisValue();
} else {
{
uint32_t arg = i - info().firstArgSlot();
uint32_t var = i - info().firstLocalSlot();
if (arg < info().nargs()) {
@ -5826,7 +5820,7 @@ IonBuilder::jsop_getgname(HandlePropertyName name)
return jsop_getname(name);
}
types::StackTypeSet *types = types::TypeScript::BytecodeTypes(script(), pc);
types::StackTypeSet *types = script()->analysis()->bytecodeTypes(pc);
bool barrier = PropertyReadNeedsTypeBarrier(cx, globalType, name, types);
// If the property is permanent, a shape guard isn't necessary.
@ -6001,14 +5995,14 @@ IonBuilder::jsop_getname(HandlePropertyName name)
if (!resumeAfter(ins))
return false;
types::StackTypeSet *types = types::TypeScript::BytecodeTypes(script(), pc);
types::StackTypeSet *types = script()->analysis()->bytecodeTypes(pc);
return pushTypeBarrier(ins, types, true);
}
bool
IonBuilder::jsop_intrinsic(HandlePropertyName name)
{
types::StackTypeSet *types = types::TypeScript::BytecodeTypes(script(), pc);
types::StackTypeSet *types = script()->analysis()->bytecodeTypes(pc);
JSValueType type = types->getKnownTypeTag();
// If we haven't executed this opcode yet, we need to get the intrinsic
@ -6104,7 +6098,7 @@ IonBuilder::jsop_getelem()
MInstruction *ins;
bool cacheable = obj->mightBeType(MIRType_Object) && !obj->mightBeType(MIRType_String) &&
bool cacheable = obj->type() == MIRType_Object &&
(index->mightBeType(MIRType_Int32) || index->mightBeType(MIRType_String));
// Turn off cacheing if the element is int32 and we've seen non-native objects as the target
@ -6112,7 +6106,7 @@ IonBuilder::jsop_getelem()
if (index->mightBeType(MIRType_Int32) && script()->analysis()->getCode(pc).nonNativeGetElement)
cacheable = false;
types::StackTypeSet *types = types::TypeScript::BytecodeTypes(script(), pc);
types::StackTypeSet *types = script()->analysis()->bytecodeTypes(pc);
bool barrier = PropertyReadNeedsTypeBarrier(cx, obj, NULL, types);
// Always add a barrier if the index might be a string, so that the cache
@ -6150,7 +6144,7 @@ IonBuilder::jsop_getelem_dense()
MDefinition *id = current->pop();
MDefinition *obj = current->pop();
types::StackTypeSet *types = types::TypeScript::BytecodeTypes(script(), pc);
types::StackTypeSet *types = script()->analysis()->bytecodeTypes(pc);
bool barrier = PropertyReadNeedsTypeBarrier(cx, obj, NULL, types);
bool needsHoleCheck = !ElementAccessIsPacked(cx, obj);
@ -6338,7 +6332,7 @@ IonBuilder::jsop_getelem_typed(int arrayType)
if (staticAccess)
return true;
types::StackTypeSet *types = types::TypeScript::BytecodeTypes(script(), pc);
types::StackTypeSet *types = script()->analysis()->bytecodeTypes(pc);
MDefinition *id = current->pop();
MDefinition *obj = current->pop();
@ -6505,15 +6499,11 @@ IonBuilder::jsop_setelem_dense(types::StackTypeSet::DoubleConversion conversion,
MElements *elements = MElements::New(obj);
current->add(elements);
bool writeHole = script()->analysis()->getCode(pc).arrayWriteHole;
SetElemICInspector icInspect(inspector->setElemICInspector(pc));
writeHole |= icInspect.sawOOBDenseWrite();
// Use MStoreElementHole if this SETELEM has written to out-of-bounds
// indexes in the past. Otherwise, use MStoreElement so that we can hoist
// the initialized length and bounds check.
MStoreElementCommon *store;
if (writeHole && writeOutOfBounds) {
if (script()->analysis()->getCode(pc).arrayWriteHole && writeOutOfBounds) {
MStoreElementHole *ins = MStoreElementHole::New(obj, elements, id, newValue);
store = ins;
@ -6654,7 +6644,7 @@ IonBuilder::jsop_length()
bool
IonBuilder::jsop_length_fastPath()
{
types::StackTypeSet *types = types::TypeScript::BytecodeTypes(script(), pc);
types::StackTypeSet *types = script()->analysis()->bytecodeTypes(pc);
if (types->getKnownTypeTag() != JSVAL_TYPE_INT32)
return false;
@ -6758,7 +6748,7 @@ IonBuilder::jsop_arguments_getelem()
current->add(load);
current->push(load);
types::StackTypeSet *types = types::TypeScript::BytecodeTypes(script(), pc);
types::StackTypeSet *types = script()->analysis()->bytecodeTypes(pc);
return pushTypeBarrier(load, types, true);
}
@ -7172,7 +7162,7 @@ IonBuilder::jsop_getprop(HandlePropertyName name)
bool emitted = false;
types::StackTypeSet *types = types::TypeScript::BytecodeTypes(script(), pc);
types::StackTypeSet *types = script()->analysis()->bytecodeTypes(pc);
// Try to optimize arguments.length.
if (!getPropTryArgumentsLength(&emitted) || emitted)
@ -7756,9 +7746,7 @@ IonBuilder::jsop_this()
}
types::StackTypeSet *types = types::TypeScript::ThisTypes(script());
if (types && (types->getKnownTypeTag() == JSVAL_TYPE_OBJECT ||
(types->empty() && fp && fp.thisValue().isObject())))
{
if (types && types->getKnownTypeTag() == JSVAL_TYPE_OBJECT) {
// This is safe, because if the entry type of |this| is an object, it
// will necessarily be an object throughout the entire function. OSR
// can introduce a phi, but this phi will be specialized.
@ -7895,7 +7883,7 @@ IonBuilder::jsop_getaliasedvar(ScopeCoordinate sc)
current->add(load);
current->push(load);
types::StackTypeSet *types = types::TypeScript::BytecodeTypes(script(), pc);
types::StackTypeSet *types = script()->analysis()->bytecodeTypes(pc);
return pushTypeBarrier(load, types, true);
}

View File

@ -435,9 +435,6 @@ HandleException(JSContext *cx, const IonFrameIterator &frame, ResumeFromExceptio
break;
}
case JSTRY_LOOP:
break;
default:
JS_NOT_REACHED("Invalid try note");
}

View File

@ -119,7 +119,7 @@ IonBuilder::inlineNativeCall(CallInfo &callInfo, JSNative native)
types::StackTypeSet *
IonBuilder::getInlineReturnTypeSet()
{
return types::TypeScript::BytecodeTypes(script(), pc);
return script()->analysis()->bytecodeTypes(pc);
}
MIRType

View File

@ -2737,7 +2737,7 @@ class MBitXor : public MBinaryBitwiseInstruction
return this;
}
MDefinition *foldIfEqual() {
return this;
return MConstant::New(Int32Value(0));
}
};

View File

@ -191,6 +191,10 @@ ScriptAnalysis::analyzeBytecode(JSContext *cx)
startcode->stackDepth = 0;
codeArray[0] = startcode;
/* Number of JOF_TYPESET opcodes we have encountered. */
unsigned nTypeSets = 0;
types::TypeSet *typeArray = script_->types->typeArray();
unsigned offset, nextOffset = 0;
while (nextOffset < length) {
offset = nextOffset;
@ -267,6 +271,22 @@ ScriptAnalysis::analyzeBytecode(JSContext *cx)
stackDepth += ndefs;
}
/*
* Assign an observed type set to each reachable JOF_TYPESET opcode.
* This may be less than the number of type sets in the script if some
* are unreachable, and may be greater in case the number of type sets
* overflows a uint16_t. In the latter case a single type set will be
* used for the observed types of all ops after the overflow.
*/
if ((js_CodeSpec[op].format & JOF_TYPESET) && cx->typeInferenceEnabled()) {
if (nTypeSets < script_->nTypeSets) {
code->observedTypes = typeArray[nTypeSets++].toStackTypeSet();
} else {
JS_ASSERT(nTypeSets == UINT16_MAX);
code->observedTypes = typeArray[nTypeSets - 1].toStackTypeSet();
}
}
switch (op) {
case JSOP_RETURN:
@ -373,7 +393,7 @@ ScriptAnalysis::analyzeBytecode(JSContext *cx)
if (catchOffset > forwardCatch)
forwardCatch = catchOffset;
if (tn->kind != JSTRY_ITER && tn->kind != JSTRY_LOOP) {
if (tn->kind != JSTRY_ITER) {
if (!addJump(cx, catchOffset, &nextOffset, &forwardJump, &forwardLoop, stackDepth))
return;
getCode(catchOffset).exceptionEntry = true;
@ -1475,7 +1495,7 @@ ScriptAnalysis::analyzeSSA(JSContext *cx)
if (startOffset == offset + 1) {
unsigned catchOffset = startOffset + tn->length;
if (tn->kind != JSTRY_ITER && tn->kind != JSTRY_LOOP) {
if (tn->kind != JSTRY_ITER) {
checkBranchTarget(cx, catchOffset, branchTargets, values, stackDepth);
checkExceptionTarget(cx, catchOffset, exceptionTargets);
}

View File

@ -122,8 +122,13 @@ class Bytecode
private:
union {
/* If this is a JOF_TYPESET opcode, index into the observed types for the op. */
types::StackTypeSet *observedTypes;
/* If this is a JSOP_LOOPHEAD or JSOP_LOOPENTRY, information about the loop. */
LoopAnalysis *loop;
};
/* --------- Lifetime analysis --------- */
@ -881,6 +886,11 @@ class ScriptAnalysis
return (cs->format & JOF_POST) && !popGuaranteed(pc);
}
types::StackTypeSet *bytecodeTypes(const jsbytecode *pc) {
JS_ASSERT(js_CodeSpec[*pc].format & JOF_TYPESET);
return getCode(pc).observedTypes;
}
const SSAValue &poppedValue(uint32_t offset, uint32_t which) {
JS_ASSERT(offset < script_->length);
JS_ASSERT(which < GetUseCount(script_, offset) +

View File

@ -1752,7 +1752,6 @@ struct JSContext : js::ContextFriendFields,
#endif
inline bool typeInferenceEnabled() const;
inline bool jaegerCompilationAllowed() const;
void updateJITEnabled();

View File

@ -411,12 +411,6 @@ JSContext::typeInferenceEnabled() const
return compartment->zone()->types.inferenceEnabled;
}
inline bool
JSContext::jaegerCompilationAllowed() const
{
return compartment->zone()->types.jaegerCompilationAllowed;
}
inline js::Handle<js::GlobalObject*>
JSContext::global() const
{

View File

@ -1274,7 +1274,7 @@ PropertyAccess(JSContext *cx, JSScript *script, jsbytecode *pc, TypeObject *obje
target->addSubset(cx, types);
} else {
JS_ASSERT_IF(script->hasAnalysis(),
target == TypeScript::BytecodeTypes(script, pc));
target == script->analysis()->bytecodeTypes(pc));
if (!types->hasPropagatedProperty())
object->getFromPrototypes(cx, id, types);
if (UsePropertyTypeBarrier(pc)) {
@ -1421,7 +1421,7 @@ TypeConstraintCall::newType(JSContext *cx, TypeSet *source, Type type)
jsbytecode *pc = callsite->pc;
JS_ASSERT_IF(script->hasAnalysis(),
callsite->returnTypes == TypeScript::BytecodeTypes(script, pc));
callsite->returnTypes == script->analysis()->bytecodeTypes(pc));
if (type.isUnknown() || type.isAnyObject()) {
/* Monitor calls on unknown functions. */
@ -2467,12 +2467,10 @@ TypeZone::init(JSContext *cx)
!cx->hasOption(JSOPTION_TYPE_INFERENCE) ||
!cx->runtime->jitSupportsFloatingPoint)
{
jaegerCompilationAllowed = true;
return;
}
inferenceEnabled = true;
jaegerCompilationAllowed = cx->hasOption(JSOPTION_METHODJIT);
}
TypeObject *
@ -2694,28 +2692,13 @@ types::UseNewTypeForInitializer(JSContext *cx, JSScript *script, jsbytecode *pc,
if (key != JSProto_Object && !(key >= JSProto_Int8Array && key <= JSProto_Uint8ClampedArray))
return GenericObject;
/*
* All loops in the script will have a JSTRY_ITER or JSTRY_LOOP try note
* indicating their boundary.
*/
AutoEnterAnalysis enter(cx);
if (!script->hasTrynotes())
return SingletonObject;
unsigned offset = pc - script->code;
JSTryNote *tn = script->trynotes()->vector;
JSTryNote *tnlimit = tn + script->trynotes()->length;
for (; tn < tnlimit; tn++) {
if (tn->kind != JSTRY_ITER && tn->kind != JSTRY_LOOP)
continue;
unsigned startOffset = script->mainOffset + tn->start;
unsigned endOffset = startOffset + tn->length;
if (offset >= startOffset && offset < endOffset)
if (!script->ensureRanAnalysis(cx))
return GenericObject;
if (script->analysis()->getCode(pc).inLoop)
return GenericObject;
}
return SingletonObject;
}
@ -4314,7 +4297,7 @@ ScriptAnalysis::analyzeTypesBytecode(JSContext *cx, unsigned offset, TypeInferen
case JSOP_CALLGNAME: {
jsid id = GetAtomId(cx, script, pc, 0);
StackTypeSet *seen = TypeScript::BytecodeTypes(script, pc);
StackTypeSet *seen = bytecodeTypes(pc);
seen->addSubset(cx, &pushed[0]);
/*
@ -4346,7 +4329,7 @@ ScriptAnalysis::analyzeTypesBytecode(JSContext *cx, unsigned offset, TypeInferen
case JSOP_GETINTRINSIC:
case JSOP_CALLNAME:
case JSOP_CALLINTRINSIC: {
StackTypeSet *seen = TypeScript::BytecodeTypes(script, pc);
StackTypeSet *seen = bytecodeTypes(pc);
addTypeBarrier(cx, pc, seen, Type::UnknownType());
seen->addSubset(cx, &pushed[0]);
break;
@ -4375,7 +4358,7 @@ ScriptAnalysis::analyzeTypesBytecode(JSContext *cx, unsigned offset, TypeInferen
break;
case JSOP_GETXPROP: {
StackTypeSet *seen = TypeScript::BytecodeTypes(script, pc);
StackTypeSet *seen = bytecodeTypes(pc);
addTypeBarrier(cx, pc, seen, Type::UnknownType());
seen->addSubset(cx, &pushed[0]);
break;
@ -4429,7 +4412,7 @@ ScriptAnalysis::analyzeTypesBytecode(JSContext *cx, unsigned offset, TypeInferen
* there is little benefit to maintaining a TypeSet for the aliased
* variable. Instead, we monitor/barrier all reads unconditionally.
*/
TypeScript::BytecodeTypes(script, pc)->addSubset(cx, &pushed[0]);
bytecodeTypes(pc)->addSubset(cx, &pushed[0]);
break;
case JSOP_SETALIASEDVAR:
@ -4445,7 +4428,7 @@ ScriptAnalysis::analyzeTypesBytecode(JSContext *cx, unsigned offset, TypeInferen
break;
case JSOP_REST: {
StackTypeSet *types = TypeScript::BytecodeTypes(script, pc);
StackTypeSet *types = script->analysis()->bytecodeTypes(pc);
if (script->compileAndGo) {
TypeObject *rest = TypeScript::InitObject(cx, script, pc, JSProto_Array);
if (!rest)
@ -4479,7 +4462,7 @@ ScriptAnalysis::analyzeTypesBytecode(JSContext *cx, unsigned offset, TypeInferen
case JSOP_GETPROP:
case JSOP_CALLPROP: {
jsid id = GetAtomId(cx, script, pc, 0);
StackTypeSet *seen = TypeScript::BytecodeTypes(script, pc);
StackTypeSet *seen = script->analysis()->bytecodeTypes(pc);
HeapTypeSet *input = &script->types->propertyReadTypes[state.propertyReadIndex++];
poppedTypes(pc, 0)->addSubset(cx, input);
@ -4508,7 +4491,7 @@ ScriptAnalysis::analyzeTypesBytecode(JSContext *cx, unsigned offset, TypeInferen
case JSOP_GETELEM:
case JSOP_CALLELEM: {
StackTypeSet *seen = TypeScript::BytecodeTypes(script, pc);
StackTypeSet *seen = script->analysis()->bytecodeTypes(pc);
/* Don't try to compute a precise callee for CALLELEM. */
if (op == JSOP_CALLELEM)
@ -4596,7 +4579,7 @@ ScriptAnalysis::analyzeTypesBytecode(JSContext *cx, unsigned offset, TypeInferen
case JSOP_FUNCALL:
case JSOP_FUNAPPLY:
case JSOP_NEW: {
StackTypeSet *seen = TypeScript::BytecodeTypes(script, pc);
StackTypeSet *seen = script->analysis()->bytecodeTypes(pc);
seen->addSubset(cx, &pushed[0]);
/* Construct the base call information about this site. */
@ -4644,7 +4627,7 @@ ScriptAnalysis::analyzeTypesBytecode(JSContext *cx, unsigned offset, TypeInferen
case JSOP_NEWINIT:
case JSOP_NEWARRAY:
case JSOP_NEWOBJECT: {
StackTypeSet *types = TypeScript::BytecodeTypes(script, pc);
StackTypeSet *types = script->analysis()->bytecodeTypes(pc);
types->addSubset(cx, &pushed[0]);
bool isArray = (op == JSOP_NEWARRAY || (op == JSOP_NEWINIT && GET_UINT8(pc) == JSProto_Array));
@ -4877,9 +4860,6 @@ ScriptAnalysis::analyzeTypes(JSContext *cx)
return;
}
if (!script_->ensureHasBytecodeTypeMap(cx))
return;
/*
* Set this early to avoid reentrance. Any failures are OOMs, and will nuke
* all types in the compartment.
@ -5289,7 +5269,7 @@ AnalyzePoppedThis(JSContext *cx, SSAUseChain *use,
Shape *shape = type->proto ? type->proto->nativeLookup(cx, id) : NULL;
if (shape && shape->hasSlot()) {
Value protov = type->proto->getSlot(shape->slot());
TypeSet *types = TypeScript::BytecodeTypes(script, pc);
TypeSet *types = script->analysis()->bytecodeTypes(pc);
types->addType(cx, GetValueType(cx, protov));
}
@ -5581,7 +5561,7 @@ ScriptAnalysis::printTypes(JSContext *cx)
continue;
if (js_CodeSpec[*pc].format & JOF_TYPESET) {
TypeSet *types = TypeScript::BytecodeTypes(script_, pc);
TypeSet *types = script_->analysis()->bytecodeTypes(pc);
printf(" typeset %d:", (int) (types - script_->types->typeArray()));
types->print();
printf("\n");
@ -5633,11 +5613,6 @@ types::MarkIteratorUnknownSlow(JSContext *cx)
AutoEnterAnalysis enter(cx);
if (!script->ensureHasTypes(cx)) {
cx->compartment->types.setPendingNukeTypes(cx);
return;
}
/*
* This script is iterating over an actual Iterator or Generator object, or
* an object with a custom __iterator__ hook. In such cases 'for in' loops
@ -5721,16 +5696,15 @@ void
types::TypeDynamicResult(JSContext *cx, JSScript *script, jsbytecode *pc, Type type)
{
JS_ASSERT(cx->typeInferenceEnabled());
AutoEnterAnalysis enter(cx);
/* Directly update associated type sets for applicable bytecodes. */
if (js_CodeSpec[*pc].format & JOF_TYPESET) {
if (!script->ensureHasBytecodeTypeMap(cx)) {
if (!script->ensureRanAnalysis(cx)) {
cx->compartment->types.setPendingNukeTypes(cx);
return;
}
TypeSet *types = TypeScript::BytecodeTypes(script, pc);
TypeSet *types = script->analysis()->bytecodeTypes(pc);
if (!types->hasType(type)) {
InferSpew(ISpewOps, "externalType: monitorResult #%u:%05u: %s",
script->id(), pc - script->code, TypeString(type));
@ -5829,13 +5803,13 @@ types::TypeMonitorResult(JSContext *cx, JSScript *script, jsbytecode *pc, const
AutoEnterAnalysis enter(cx);
if (!script->ensureHasBytecodeTypeMap(cx)) {
if (!script->ensureRanAnalysis(cx)) {
cx->compartment->types.setPendingNukeTypes(cx);
return;
}
Type type = GetValueType(cx, rval);
TypeSet *types = TypeScript::BytecodeTypes(script, pc);
TypeSet *types = script->analysis()->bytecodeTypes(pc);
if (types->hasType(type))
return;
@ -5932,7 +5906,7 @@ JSScript::makeTypes(JSContext *cx)
return false;
}
new(types) TypeScript();
return analyzedArgsUsage() || ensureRanAnalysis(cx);
return true;
}
AutoEnterAnalysis enter(cx);
@ -6002,36 +5976,6 @@ JSScript::makeTypes(JSContext *cx)
}
#endif
return analyzedArgsUsage() || ensureRanAnalysis(cx);
}
bool
JSScript::makeBytecodeTypeMap(JSContext *cx)
{
JS_ASSERT(cx->typeInferenceEnabled());
JS_ASSERT(types && !types->bytecodeMap);
types->bytecodeMap = cx->analysisLifoAlloc().newArrayUninitialized<uint32_t>(nTypeSets + 1);
if (!types->bytecodeMap)
return false;
uint32_t added = 0;
for (jsbytecode *pc = code; pc < code + length; pc += GetBytecodeLength(pc)) {
JSOp op = JSOp(*pc);
if (js_CodeSpec[op].format & JOF_TYPESET) {
types->bytecodeMap[added++] = pc - code;
if (added == nTypeSets)
break;
}
}
JS_ASSERT(added == nTypeSets);
// The last entry in the last index found, and is used to avoid binary
// searches for the sought entry when queries are in linear order.
types->bytecodeMap[nTypeSets] = 0;
return true;
}

View File

@ -1177,12 +1177,6 @@ class TypeScript
/* Analysis information for the script, cleared on each GC. */
analyze::ScriptAnalysis *analysis;
/*
* List mapping indexes of bytecode type sets to the offset of the opcode
* they correspond to. Cleared on each GC.
*/
uint32_t *bytecodeMap;
public:
/* Dynamic types generated at points within this script. */
TypeResult *dynamicList;
@ -1207,9 +1201,6 @@ class TypeScript
/* Follows slot layout in jsanalyze.h, can get this/arg/local type sets. */
static inline StackTypeSet *SlotTypes(JSScript *script, unsigned slot);
/* Get the type set for values observed at an opcode. */
static inline StackTypeSet *BytecodeTypes(JSScript *script, jsbytecode *pc);
/* Get the default 'new' object for a given standard class, per the script's global. */
static inline TypeObject *StandardType(JSContext *cx, JSProtoKey kind);
@ -1475,13 +1466,6 @@ struct TypeZone
/* Whether type inference is enabled in this compartment. */
bool inferenceEnabled;
/*
* JM compilation is allowed only if script analysis has been used to
* monitor the behavior of all scripts in this zone since its creation.
* OSR in JM requires this property.
*/
bool jaegerCompilationAllowed;
TypeZone(JS::Zone *zone);
~TypeZone();
void init(JSContext *cx);

View File

@ -586,7 +586,7 @@ TypeMonitorCall(JSContext *cx, const js::CallArgs &args, bool constructing)
if (args.callee().isFunction()) {
JSFunction *fun = args.callee().toFunction();
if (fun->isInterpreted()) {
if (!fun->nonLazyScript()->ensureHasTypes(cx))
if (!fun->nonLazyScript()->ensureRanAnalysis(cx))
return false;
if (cx->typeInferenceEnabled())
TypeMonitorCallSlow(cx, &args.callee(), args, constructing);
@ -858,49 +858,6 @@ TypeScript::SlotTypes(JSScript *script, unsigned slot)
return types->toStackTypeSet();
}
/* static */ inline StackTypeSet *
TypeScript::BytecodeTypes(JSScript *script, jsbytecode *pc)
{
JS_ASSERT(js_CodeSpec[*pc].format & JOF_TYPESET);
JS_ASSERT(script->types && script->types->bytecodeMap);
uint32_t *bytecodeMap = script->types->bytecodeMap;
uint32_t *hint = bytecodeMap + script->nTypeSets;
uint32_t offset = pc - script->code;
JS_ASSERT(offset < script->length);
// See if this pc is the next typeset opcode after the last one looked up.
if (bytecodeMap[*hint + 1] == offset && (*hint + 1) < script->nTypeSets) {
(*hint)++;
return script->types->typeArray()->toStackTypeSet() + *hint;
}
// See if this pc is the same as the last one looked up.
if (bytecodeMap[*hint] == offset)
return script->types->typeArray()->toStackTypeSet() + *hint;
// Fall back to a binary search.
size_t bottom = 0;
size_t top = script->nTypeSets - 1;
size_t mid = (bottom + top) / 2;
while (mid < top) {
if (bytecodeMap[mid] < offset)
bottom = mid + 1;
else if (bytecodeMap[mid] > offset)
top = mid;
else
break;
mid = (bottom + top) / 2;
}
// We should have have zeroed in on either the exact offset, unless there
// are more JOF_TYPESET opcodes than nTypeSets in the script (as can happen
// if the script is very long).
JS_ASSERT(bytecodeMap[mid] == offset || mid == top);
*hint = mid;
return script->types->typeArray()->toStackTypeSet() + *hint;
}
/* static */ inline TypeObject *
TypeScript::StandardType(JSContext *cx, JSProtoKey key)
{
@ -1825,12 +1782,6 @@ JSScript::ensureHasTypes(JSContext *cx)
return types || makeTypes(cx);
}
inline bool
JSScript::ensureHasBytecodeTypeMap(JSContext *cx)
{
return ensureHasTypes(cx) && (types->bytecodeMap || makeBytecodeTypeMap(cx));
}
inline bool
JSScript::ensureRanAnalysis(JSContext *cx)
{
@ -1872,10 +1823,8 @@ JSScript::analysis()
inline void
JSScript::clearAnalysis()
{
if (types) {
if (types)
types->analysis = NULL;
types->bytecodeMap = NULL;
}
}
inline void

View File

@ -565,7 +565,7 @@ js::ExecuteKernel(JSContext *cx, HandleScript script, JSObject &scopeChainArg, c
if (!cx->stack.pushExecuteFrame(cx, script, thisv, scopeChain, type, evalInFrame, &efg))
return false;
if (!script->ensureHasTypes(cx))
if (!script->ensureRanAnalysis(cx))
return false;
TypeScript::SetThis(cx, script, efg.fp()->thisValue());
@ -3366,11 +3366,7 @@ END_CASE(JSOP_ARRAYPUSH)
regs.sp -= 1;
if (!ok)
goto error;
break;
}
case JSTRY_LOOP:
break;
}
}

View File

@ -1520,9 +1520,7 @@ js::CreateThisForFunctionWithProto(JSContext *cx, HandleObject callee, JSObject
}
if (res && cx->typeInferenceEnabled()) {
JSScript *script = callee->toFunction()->nonLazyScript();
if (!script->ensureHasTypes(cx))
return NULL;
RootedScript script(cx, callee->toFunction()->nonLazyScript());
TypeScript::SetThis(cx, script, types::Type::ObjectType(res));
}
@ -1549,9 +1547,7 @@ js::CreateThisForFunction(JSContext *cx, HandleObject callee, bool newType)
/* Reshape the singleton before passing it as the 'this' value. */
JSObject::clear(cx, nobj);
JSScript *calleeScript = callee->toFunction()->nonLazyScript();
if (!calleeScript->ensureHasTypes(cx))
return NULL;
RootedScript calleeScript(cx, callee->toFunction()->nonLazyScript());
TypeScript::SetThis(cx, calleeScript, types::Type::ObjectType(nobj));
return nobj;

View File

@ -49,15 +49,12 @@ namespace analyze {
/*
* Type of try note associated with each catch or finally block, and also with
* for-in and other kinds of loops. Non-for-in loops do not need these notes
* for exception unwinding, but storing their boundaries here is helpful for
* heuristics that need to know whether a given op is inside a loop.
* for-in loops.
*/
typedef enum JSTryNoteKind {
JSTRY_CATCH,
JSTRY_FINALLY,
JSTRY_ITER,
JSTRY_LOOP
JSTRY_ITER
} JSTryNoteKind;
/*
@ -67,9 +64,9 @@ struct JSTryNote {
uint8_t kind; /* one of JSTryNoteKind */
uint8_t padding; /* explicit padding on uint16_t boundary */
uint16_t stackDepth; /* stack depth upon exception handler entry */
uint32_t start; /* start of the try statement or loop
uint32_t start; /* start of the try statement or for-in loop
relative to script->main */
uint32_t length; /* length of the try statement or loop */
uint32_t length; /* length of the try statement or for-in loop */
};
namespace js {
@ -720,9 +717,6 @@ class JSScript : public js::gc::Cell
/* Ensure the script has a TypeScript. */
inline bool ensureHasTypes(JSContext *cx);
/* Ensure the script has a TypeScript and map for computing BytecodeTypes. */
inline bool ensureHasBytecodeTypeMap(JSContext *cx);
/*
* Ensure the script has bytecode analysis information. Performed when the
* script first runs, or first runs after a TypeScript GC purge.
@ -764,7 +758,6 @@ class JSScript : public js::gc::Cell
private:
bool makeTypes(JSContext *cx);
bool makeBytecodeTypeMap(JSContext *cx);
bool makeAnalysis(JSContext *cx);
#ifdef JS_METHODJIT

View File

@ -121,8 +121,6 @@ mjit::Compiler::Compiler(JSContext *cx, JSScript *outerScript,
gcNumber(cx->runtime->gcNumber),
pcLengths(NULL)
{
JS_ASSERT(cx->jaegerCompilationAllowed());
if (!IsIonEnabled(cx)) {
/* Once a script starts getting really hot we will inline calls in it. */
if (!debugMode() && cx->typeInferenceEnabled() && globalObj &&
@ -996,9 +994,6 @@ mjit::CanMethodJIT(JSContext *cx, JSScript *script, jsbytecode *pc,
if (!cx->methodJitEnabled)
return Compile_Abort;
if (!cx->jaegerCompilationAllowed())
return Compile_Abort;
#ifdef JS_ION
if (ion::IsBaselineEnabled(cx) || ion::IsEnabled(cx))
return Compile_Abort;
@ -8128,7 +8123,7 @@ mjit::Compiler::testBarrier(RegisterID typeReg, RegisterID dataReg,
if (!cx->typeInferenceEnabled() || !(js_CodeSpec[*PC].format & JOF_TYPESET))
return state;
types::StackTypeSet *types = types::TypeScript::BytecodeTypes(script_, PC);
types::StackTypeSet *types = analysis->bytecodeTypes(PC);
if (types->unknown()) {
/*
* If the result of this opcode is already unknown, there is no way for
@ -8193,7 +8188,7 @@ mjit::Compiler::testPushedType(RejoinState rejoin, int which, bool ool)
if (!cx->typeInferenceEnabled() || !(js_CodeSpec[*PC].format & JOF_TYPESET))
return;
types::TypeSet *types = types::TypeScript::BytecodeTypes(script_, PC);
types::TypeSet *types = analysis->bytecodeTypes(PC);
if (types->unknown())
return;

View File

@ -115,11 +115,7 @@ FindExceptionHandler(JSContext *cx)
cx->regs().sp -= 1;
if (!ok)
goto error;
break;
}
case JSTRY_LOOP:
break;
}
}
} else {

View File

@ -437,7 +437,7 @@ mjit::NativeStubEpilogue(VMFrame &f, Assembler &masm, NativeStubLinker::FinalJum
* the call. We don't assume knowledge about the types that natives can
* return, except when generating specialized paths in FastBuiltins.
*/
types::TypeSet *types = types::TypeScript::BytecodeTypes(f.script(), f.pc());
types::TypeSet *types = f.script()->analysis()->bytecodeTypes(f.pc());
if (!masm.generateTypeCheck(f.cx, resultAddress, types, &mismatches))
THROWV(false);
}

View File

@ -1809,7 +1809,7 @@ JS_STATIC_ASSERT(JSTRY_CATCH == 0);
JS_STATIC_ASSERT(JSTRY_FINALLY == 1);
JS_STATIC_ASSERT(JSTRY_ITER == 2);
static const char* const TryNoteNames[] = { "catch", "finally", "iter", "loop" };
static const char* const TryNoteNames[] = { "catch", "finally", "iter" };
static JSBool
TryNotes(JSContext *cx, HandleScript script, Sprinter *sp)
@ -4927,6 +4927,11 @@ ProcessArgs(JSContext *cx, JSObject *obj_, OptionParser *op)
if (op->getBoolOption('s'))
JS_ToggleOptions(cx, JSOPTION_STRICT);
if (op->getBoolOption("no-jm")) {
enableMethodJit = false;
JS_ToggleOptions(cx, JSOPTION_METHODJIT);
}
if (op->getBoolOption('d')) {
JS_SetRuntimeDebugMode(JS_GetRuntime(cx), true);
JS_SetDebugMode(cx, true);
@ -5116,17 +5121,13 @@ Shell(JSContext *cx, OptionParser *op, char **envp)
JSAutoRequest ar(cx);
/*
* First check to see if type inference and JM are enabled. These flags
* must be set on the compartment when it is constructed.
* First check to see if type inference is enabled. This flag must be set
* on the compartment when it is constructed.
*/
if (op->getBoolOption("no-ti")) {
enableTypeInference = false;
JS_ToggleOptions(cx, JSOPTION_TYPE_INFERENCE);
}
if (op->getBoolOption("no-jm")) {
enableMethodJit = false;
JS_ToggleOptions(cx, JSOPTION_METHODJIT);
}
RootedObject glob(cx);
glob = NewGlobalObject(cx, NULL);

View File

@ -26,7 +26,7 @@ namespace js {
* and saved versions. If deserialization fails, the data should be
* invalidated if possible.
*/
static const uint32_t XDR_BYTECODE_VERSION = uint32_t(0xb973c0de - 142);
static const uint32_t XDR_BYTECODE_VERSION = uint32_t(0xb973c0de - 141);
class XDRBuffer {
public: