bool VariableAccessData::shouldUseDoubleFormatAccordingToVote() { // We don't support this facility for arguments, yet. // FIXME: make this work for arguments. if (local().isArgument()) return false; // If the variable is not a number prediction, then this doesn't // make any sense. if (!isFullNumberSpeculation(prediction())) { // FIXME: we may end up forcing a local in inlined argument position to be a double even // if it is sometimes not even numeric, since this never signals the fact that it doesn't // want doubles. https://bugs.webkit.org/show_bug.cgi?id=109511 return false; } // If the variable is predicted to hold only doubles, then it's a // no-brainer: it should be formatted as a double. if (isDoubleSpeculation(prediction())) return true; // If the variable is known to be used as an integer, then be safe - // don't force it to be a double. if (flags() & NodeBytecodeUsesAsInt) return false; // If the variable has been voted to become a double, then make it a // double. if (voteRatio() >= Options::doubleVoteRatioForDoubleFormat()) return true; return false; }
// We don't expose this because we don't want anyone relying on the fact that this method currently // just returns string constants. static const char* speculationToAbbreviatedString(SpeculatedType prediction) { if (isFinalObjectSpeculation(prediction)) return "<Final>"; if (isArraySpeculation(prediction)) return "<Array>"; if (isStringIdentSpeculation(prediction)) return "<StringIdent>"; if (isStringSpeculation(prediction)) return "<String>"; if (isFunctionSpeculation(prediction)) return "<Function>"; if (isInt8ArraySpeculation(prediction)) return "<Int8array>"; if (isInt16ArraySpeculation(prediction)) return "<Int16array>"; if (isInt32ArraySpeculation(prediction)) return "<Int32array>"; if (isUint8ArraySpeculation(prediction)) return "<Uint8array>"; if (isUint16ArraySpeculation(prediction)) return "<Uint16array>"; if (isUint32ArraySpeculation(prediction)) return "<Uint32array>"; if (isFloat32ArraySpeculation(prediction)) return "<Float32array>"; if (isFloat64ArraySpeculation(prediction)) return "<Float64array>"; if (isDirectArgumentsSpeculation(prediction)) return "<DirectArguments>"; if (isScopedArgumentsSpeculation(prediction)) return "<ScopedArguments>"; if (isStringObjectSpeculation(prediction)) return "<StringObject>"; if (isStringOrStringObjectSpeculation(prediction)) return "<StringOrStringObject>"; if (isObjectSpeculation(prediction)) return "<Object>"; if (isCellSpeculation(prediction)) return "<Cell>"; if (isInt32Speculation(prediction)) return "<Int32>"; if (isInt52AsDoubleSpeculation(prediction)) return "<Int52AsDouble>"; if (isInt52Speculation(prediction)) return "<Int52>"; if (isMachineIntSpeculation(prediction)) return "<MachineInt>"; if (isDoubleSpeculation(prediction)) return "<Double>"; if (isFullNumberSpeculation(prediction)) return "<Number>"; if (isBooleanSpeculation(prediction)) return "<Boolean>"; if (isOtherSpeculation(prediction)) return "<Other>"; if (isMiscSpeculation(prediction)) return "<Misc>"; return ""; }
void doRoundOfDoubleVoting() { #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) dataLog("Voting on double uses of locals [%u]\n", m_count); #endif for (unsigned i = 0; i < m_graph.m_variableAccessData.size(); ++i) m_graph.m_variableAccessData[i].find()->clearVotes(); for (m_compileIndex = 0; m_compileIndex < m_graph.size(); ++m_compileIndex) { Node& node = m_graph[m_compileIndex]; switch (node.op()) { case ValueAdd: case ArithAdd: case ArithSub: { SpeculatedType left = m_graph[node.child1()].prediction(); SpeculatedType right = m_graph[node.child2()].prediction(); DoubleBallot ballot; if (isNumberSpeculation(left) && isNumberSpeculation(right) && !m_graph.addShouldSpeculateInteger(node)) ballot = VoteDouble; else ballot = VoteValue; m_graph.vote(node.child1(), ballot); m_graph.vote(node.child2(), ballot); break; } case ArithMul: { SpeculatedType left = m_graph[node.child1()].prediction(); SpeculatedType right = m_graph[node.child2()].prediction(); DoubleBallot ballot; if (isNumberSpeculation(left) && isNumberSpeculation(right) && !m_graph.mulShouldSpeculateInteger(node)) ballot = VoteDouble; else ballot = VoteValue; m_graph.vote(node.child1(), ballot); m_graph.vote(node.child2(), ballot); break; } case ArithMin: case ArithMax: case ArithMod: case ArithDiv: { SpeculatedType left = m_graph[node.child1()].prediction(); SpeculatedType right = m_graph[node.child2()].prediction(); DoubleBallot ballot; if (isNumberSpeculation(left) && isNumberSpeculation(right) && !(Node::shouldSpeculateInteger(m_graph[node.child1()], m_graph[node.child1()]) && node.canSpeculateInteger())) ballot = VoteDouble; else ballot = VoteValue; m_graph.vote(node.child1(), ballot); m_graph.vote(node.child2(), ballot); break; } case ArithAbs: DoubleBallot ballot; if (!(m_graph[node.child1()].shouldSpeculateInteger() && node.canSpeculateInteger())) ballot = VoteDouble; else ballot = VoteValue; m_graph.vote(node.child1(), ballot); break; case ArithSqrt: m_graph.vote(node.child1(), VoteDouble); break; case SetLocal: { SpeculatedType prediction = m_graph[node.child1()].prediction(); if (isDoubleSpeculation(prediction)) node.variableAccessData()->vote(VoteDouble); else if (!isNumberSpeculation(prediction) || isInt32Speculation(prediction)) node.variableAccessData()->vote(VoteValue); break; } default: m_graph.vote(node, VoteValue); break; } } for (unsigned i = 0; i < m_graph.m_variableAccessData.size(); ++i) { VariableAccessData* variableAccessData = &m_graph.m_variableAccessData[i]; if (!variableAccessData->isRoot()) continue; if (operandIsArgument(variableAccessData->local()) || variableAccessData->isCaptured()) continue; m_changed |= variableAccessData->tallyVotesForShouldUseDoubleFormat(); } for (unsigned i = 0; i < m_graph.m_argumentPositions.size(); ++i) m_changed |= m_graph.m_argumentPositions[i].mergeArgumentAwareness(); for (unsigned i = 0; i < m_graph.m_variableAccessData.size(); ++i) { VariableAccessData* variableAccessData = &m_graph.m_variableAccessData[i]; if (!variableAccessData->isRoot()) continue; if (operandIsArgument(variableAccessData->local()) || variableAccessData->isCaptured()) continue; m_changed |= variableAccessData->makePredictionForDoubleFormat(); } }