bool TypeInferenceOracle::getOsrTypes(jsbytecode *osrPc, Vector<MIRType> &slotTypes) { JS_ASSERT(JSOp(*osrPc) == JSOP_LOOPENTRY); JS_ASSERT(script()->code < osrPc); JS_ASSERT(osrPc < script()->code + script()->length); Vector<types::StackTypeSet *> slotTypeSets(cx); if (!slotTypeSets.resize(TotalSlots(script()))) return false; for (uint32_t slot = ThisSlot(); slot < TotalSlots(script()); slot++) slotTypeSets[slot] = TypeScript::SlotTypes(script(), slot); jsbytecode *pc = script()->code; ScriptAnalysis *analysis = script()->analysis(); // To determine the slot types at the OSR pc, we have to do a forward walk // over the bytecode to reconstruct the types. for (;;) { Bytecode *opinfo = analysis->maybeCode(pc); if (opinfo) { if (opinfo->jumpTarget) { // Update variable types for all new values at this bytecode. if (const SlotValue *newv = analysis->newValues(pc)) { while (newv->slot) { if (newv->slot < TotalSlots(script())) slotTypeSets[newv->slot] = analysis->getValueTypes(newv->value); newv++; } } } if (BytecodeUpdatesSlot(JSOp(*pc))) { uint32_t slot = GetBytecodeSlot(script(), pc); if (analysis->trackSlot(slot)) slotTypeSets[slot] = analysis->pushedTypes(pc, 0); } } if (pc == osrPc) break; pc += GetBytecodeLength(pc); } JS_ASSERT(pc == osrPc); // TI always includes the |this| slot, but Ion only does so for function // scripts. This means we have to subtract 1 for global/eval scripts. JS_ASSERT(ThisSlot() == 1); JS_ASSERT(ArgSlot(0) == 2); #ifdef DEBUG uint32_t stackDepth = analysis->getCode(osrPc).stackDepth; #endif if (script()->function()) { JS_ASSERT(slotTypes.length() == TotalSlots(script()) + stackDepth); for (size_t i = ThisSlot(); i < TotalSlots(script()); i++) slotTypes[i] = getMIRType(slotTypeSets[i]); } else { JS_ASSERT(slotTypes.length() == TotalSlots(script()) + stackDepth - 1); for (size_t i = ArgSlot(0); i < TotalSlots(script()); i++) slotTypes[i - 1] = getMIRType(slotTypeSets[i]); } return true; }