void IRTranslator::passPredictedAndInferredTypes(const NormalizedInstruction& i) { if (!i.outStack || i.breaksTracelet) return; auto const jitType = Type(i.outStack->rtt); m_hhbcTrans.setBcOff(i.next->offset(), false); if (RuntimeOption::EvalHHIRRelaxGuards) { if (i.outputPredicted) { if (i.outputPredictionStatic && jitType.notCounted()) { // If the prediction is from static analysis it really means jitType | // InitNull. When jitType is an uncounted type, we know that the value // will always be an uncounted type, so we assert that fact before // doing the real check. This allows us to relax the CheckType away // while still eliminating some refcounting operations. m_hhbcTrans.assertTypeStack(0, Type::Uncounted); } m_hhbcTrans.checkTypeTopOfStack(jitType, i.next->offset()); } return; } NormalizedInstruction::OutputUse u = i.getOutputUsage(i.outStack); if (u == NormalizedInstruction::OutputUse::Inferred) { TRACE(1, "irPassPredictedAndInferredTypes: output inferred as %s\n", jitType.toString().c_str()); m_hhbcTrans.assertTypeStack(0, jitType); } else if (u == NormalizedInstruction::OutputUse::Used && i.outputPredicted) { // If the value was predicted statically by the front-end, it // means that it's either the predicted type or null. In this // case, if the predicted value is not ref-counted and it's simply // going to be popped, then pass the information as an assertion // that the type is not ref-counted. This avoid both generating a // type check and dec-refing the value. if (i.outputPredictionStatic && isPop(i.next->op()) && !jitType.maybeCounted()) { TRACE(1, "irPassPredictedAndInferredTypes: output inferred as %s\n", jitType.toString().c_str()); m_hhbcTrans.assertTypeStack(0, JIT::Type::Uncounted); } else { TRACE(1, "irPassPredictedAndInferredTypes: output predicted as %s\n", jitType.toString().c_str()); m_hhbcTrans.checkTypeTopOfStack(jitType, i.next->offset()); } } }
void Token::print() const { if( eol() ) std::cout << "NEWLINE" ; else if( eof() ) std::cout << "ENDMARKER" ; else if( indent() ) std::cout << "INDENT"; else if( dedent() ) std::cout << "DEDENT"; else if( isOpenBrace() ) std::cout << " { "; else if( isCloseBrace() ) std::cout << " } "; else if( isComma() ) std::cout << " , "; else if( isPeriod()) std::cout<< "."; else if( isEqual() ) std::cout << " == "; else if( isNotEqual() ) std::cout << " != "; else if( isLessThan() ) std::cout << " < "; else if( isGreaterThan() ) std::cout << " > "; else if( isLessThanEqual() ) std::cout << " <= "; else if( isGreaterThanEqual() ) std::cout << " >= "; else if( isOpenParen() ) std::cout << " ( " ; else if( isCloseParen() ) std::cout << " ) " ; else if( isAssignmentOperator() ) std::cout << " = "; else if( isColon() ) std::cout << " : " ; else if( isMultiplicationOperator() ) std::cout << " * " ; else if( isAdditionOperator() ) std::cout << " + "; else if( isSubtractionOperator() ) std::cout << " - "; else if( isModuloOperator() ) std::cout << " % "; else if( isDivisionOperator() ) std::cout << " / "; else if( isFloorDivision() ) std::cout << " // "; else if( isOpenBrack() ) std::cout<< "["; else if( isCloseBrack() ) std::cout<< "]"; else if( isName() ) std::cout << getName(); else if( isKeyword() ) std::cout << getKeyword(); else if( isWholeNumber() ) std::cout << getWholeNumber(); else if( isFloat() ) std::cout << getFloat(); else if( isString() ) std::cout << getString(); else if( isCall() ) std::cout << "CALL " << getName(); else if( isSub() ) std::cout << "ARRAY SUB " << getName(); else if( isAppend() ) std::cout << "ARRAY APPEND " << getName(); else if( isPop() ) std::cout << "ARRAY POP " << getName(); else std::cout << "Uninitialized token.\n"; }