Changeset 252015 in webkit for trunk/Source/JavaScriptCore/bytecode/ArithProfile.h
- Timestamp:
- Nov 4, 2019, 2:20:37 PM (6 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/bytecode/ArithProfile.h
r251106 r252015 67 67 }; 68 68 69 struct ArithProfile { 70 private: 71 static constexpr uint32_t numberOfFlagBits = 6; 72 static constexpr uint32_t rhsResultTypeShift = numberOfFlagBits; 73 static constexpr uint32_t lhsResultTypeShift = rhsResultTypeShift + ResultType::numBitsNeeded; 74 static constexpr uint32_t rhsObservedTypeShift = lhsResultTypeShift + ResultType::numBitsNeeded; 75 static constexpr uint32_t lhsObservedTypeShift = rhsObservedTypeShift + ObservedType::numBitsNeeded; 76 77 static_assert(ObservedType::numBitsNeeded == 3, "We make a hard assumption about that here."); 78 static constexpr uint32_t clearRhsObservedTypeBitMask = static_cast<uint32_t>(~((1 << rhsObservedTypeShift) | (1 << (rhsObservedTypeShift + 1)) | (1 << (rhsObservedTypeShift + 2)))); 79 static constexpr uint32_t clearLhsObservedTypeBitMask = static_cast<uint32_t>(~((1 << lhsObservedTypeShift) | (1 << (lhsObservedTypeShift + 1)) | (1 << (lhsObservedTypeShift + 2)))); 80 81 static constexpr uint32_t resultTypeMask = (1 << ResultType::numBitsNeeded) - 1; 82 static constexpr uint32_t observedTypeMask = (1 << ObservedType::numBitsNeeded) - 1; 83 84 enum class ConstantTag { Constant }; 85 69 template <typename BitfieldType> 70 class ArithProfile { 86 71 public: 87 static constexpr uint32_t specialFastPathBit = 1 << (lhsObservedTypeShift + ObservedType::numBitsNeeded);88 static_assert((lhsObservedTypeShift + ObservedType::numBitsNeeded) <= (sizeof(uint32_t) * 8) - 1, "Should fit in a uint32_t.");89 static_assert(!(specialFastPathBit & ~clearLhsObservedTypeBitMask), "These bits should not intersect.");90 static_assert(specialFastPathBit & clearLhsObservedTypeBitMask, "These bits should intersect.");91 static_assert(specialFastPathBit > ~clearLhsObservedTypeBitMask, "These bits should not intersect and specialFastPathBit should be a higher bit.");92 93 ArithProfile(ResultType arg)94 : ArithProfile(ConstantTag::Constant, arg)95 {96 ASSERT(lhsResultType().bits() == arg.bits());97 ASSERT(lhsObservedType().isEmpty());98 ASSERT(rhsObservedType().isEmpty());99 }100 101 ArithProfile(ResultType lhs, ResultType rhs)102 : ArithProfile(ConstantTag::Constant, lhs, rhs)103 {104 ASSERT(lhsResultType().bits() == lhs.bits() && rhsResultType().bits() == rhs.bits());105 ASSERT(lhsObservedType().isEmpty());106 ASSERT(rhsObservedType().isEmpty());107 }108 109 ArithProfile(OperandTypes types)110 : ArithProfile(types.first(), types.second())111 { }112 113 ArithProfile() = default;114 115 static constexpr ArithProfile fromInt(uint32_t bits)116 {117 return ArithProfile { ConstantTag::Constant, bits };118 }119 120 static constexpr ArithProfile observedUnaryInt()121 {122 constexpr ObservedType observedInt32 { ObservedType().withInt32() };123 constexpr uint32_t bits = observedInt32.bits() << lhsObservedTypeShift;124 static_assert(bits == 0x800000, "");125 return fromInt(bits);126 }127 static constexpr ArithProfile observedUnaryNumber()128 {129 constexpr ObservedType observedNumber { ObservedType().withNumber() };130 constexpr uint32_t bits = observedNumber.bits() << lhsObservedTypeShift;131 static_assert(bits == 0x1000000, "");132 return fromInt(bits);133 }134 static constexpr ArithProfile observedBinaryIntInt()135 {136 constexpr ObservedType observedInt32 { ObservedType().withInt32() };137 constexpr uint32_t bits = (observedInt32.bits() << lhsObservedTypeShift) | (observedInt32.bits() << rhsObservedTypeShift);138 static_assert(bits == 0x900000, "");139 return fromInt(bits);140 }141 static constexpr ArithProfile observedBinaryNumberInt()142 {143 constexpr ObservedType observedNumber { ObservedType().withNumber() };144 constexpr ObservedType observedInt32 { ObservedType().withInt32() };145 constexpr uint32_t bits = (observedNumber.bits() << lhsObservedTypeShift) | (observedInt32.bits() << rhsObservedTypeShift);146 static_assert(bits == 0x1100000, "");147 return fromInt(bits);148 }149 static constexpr ArithProfile observedBinaryIntNumber()150 {151 constexpr ObservedType observedNumber { ObservedType().withNumber() };152 constexpr ObservedType observedInt32 { ObservedType().withInt32() };153 constexpr uint32_t bits = (observedInt32.bits() << lhsObservedTypeShift) | (observedNumber.bits() << rhsObservedTypeShift);154 static_assert(bits == 0xa00000, "");155 return fromInt(bits);156 }157 static constexpr ArithProfile observedBinaryNumberNumber()158 {159 constexpr ObservedType observedNumber { ObservedType().withNumber() };160 constexpr uint32_t bits = (observedNumber.bits() << lhsObservedTypeShift) | (observedNumber.bits() << rhsObservedTypeShift);161 static_assert(bits == 0x1200000, "");162 return fromInt(bits);163 }164 165 72 enum ObservedResults { 166 73 NonNegZeroDouble = 1 << 0, … … 171 78 BigInt = 1 << 5, 172 79 }; 173 174 ResultType lhsResultType() const { return ResultType((m_bits >> lhsResultTypeShift) & resultTypeMask); } 175 ResultType rhsResultType() const { return ResultType((m_bits >> rhsResultTypeShift) & resultTypeMask); } 176 177 constexpr ObservedType lhsObservedType() const { return ObservedType((m_bits >> lhsObservedTypeShift) & observedTypeMask); } 178 constexpr ObservedType rhsObservedType() const { return ObservedType((m_bits >> rhsObservedTypeShift) & observedTypeMask); } 179 void setLhsObservedType(ObservedType type) 180 { 181 uint32_t bits = m_bits; 182 bits &= clearLhsObservedTypeBitMask; 183 bits |= type.bits() << lhsObservedTypeShift; 184 m_bits = bits; 185 ASSERT(lhsObservedType() == type); 186 } 187 188 void setRhsObservedType(ObservedType type) 189 { 190 uint32_t bits = m_bits; 191 bits &= clearRhsObservedTypeBitMask; 192 bits |= type.bits() << rhsObservedTypeShift; 193 m_bits = bits; 194 ASSERT(rhsObservedType() == type); 195 } 196 197 bool tookSpecialFastPath() const { return m_bits & specialFastPathBit; } 80 static constexpr uint32_t observedResultsNumBitsNeeded = 6; 198 81 199 82 bool didObserveNonInt32() const { return hasBits(NonNegZeroDouble | NegZeroDouble | NonNumeric | BigInt); } … … 212 95 void setObservedInt32Overflow() { setBit(Int32Overflow); } 213 96 void setObservedInt52Overflow() { setBit(Int52Overflow); } 214 215 const void* addressOfBits() const { return &m_bits; }216 97 217 98 void observeResult(JSValue value) … … 230 111 } 231 112 113 const void* addressOfBits() const { return &m_bits; } 114 115 #if ENABLE(JIT) 116 // Sets (Int32Overflow | Int52Overflow | NonNegZeroDouble | NegZeroDouble) if it sees a 117 // double. Sets NonNumeric if it sees a non-numeric. 118 void emitObserveResult(CCallHelpers&, JSValueRegs, TagRegistersMode = HaveTagRegisters); 119 120 // Sets (Int32Overflow | Int52Overflow | NonNegZeroDouble | NegZeroDouble). 121 bool shouldEmitSetDouble() const; 122 void emitSetDouble(CCallHelpers&) const; 123 124 // Sets NonNumber. 125 void emitSetNonNumeric(CCallHelpers&) const; 126 bool shouldEmitSetNonNumeric() const; 127 128 // Sets BigInt 129 void emitSetBigInt(CCallHelpers&) const; 130 bool shouldEmitSetBigInt() const; 131 #endif // ENABLE(JIT) 132 133 constexpr uint32_t bits() const { return m_bits; } 134 135 protected: 136 ArithProfile() 137 { 138 } 139 140 bool hasBits(int mask) const { return m_bits & mask; } 141 void setBit(int mask) { m_bits |= mask; } 142 143 BitfieldType m_bits { 0 }; // We take care to update m_bits only in a single operation. We don't ever store an inconsistent bit representation to it. 144 }; 145 146 /* This class stores the following components in 16 bits: 147 * - ObservedResults 148 * - ObservedType for the argument 149 */ 150 using UnaryArithProfileBase = uint16_t; 151 class UnaryArithProfile : public ArithProfile<UnaryArithProfileBase> { 152 static constexpr unsigned argObservedTypeShift = observedResultsNumBitsNeeded; 153 154 static_assert(argObservedTypeShift + ObservedType::numBitsNeeded <= sizeof(UnaryArithProfileBase) * 8, "Should fit in a the type of the underlying bitfield."); 155 156 static constexpr UnaryArithProfileBase clearArgObservedTypeBitMask = static_cast<UnaryArithProfileBase>(~(0b111 << argObservedTypeShift)); 157 158 static constexpr UnaryArithProfileBase observedTypeMask = (1 << ObservedType::numBitsNeeded) - 1; 159 160 public: 161 UnaryArithProfile() 162 : ArithProfile<UnaryArithProfileBase>() 163 { 164 ASSERT(argObservedType().isEmpty()); 165 ASSERT(argObservedType().isEmpty()); 166 } 167 168 static constexpr UnaryArithProfileBase observedIntBits() 169 { 170 constexpr ObservedType observedInt32 { ObservedType().withInt32() }; 171 constexpr UnaryArithProfileBase bits = observedInt32.bits() << argObservedTypeShift; 172 return bits; 173 } 174 static constexpr UnaryArithProfileBase observedNumberBits() 175 { 176 constexpr ObservedType observedNumber { ObservedType().withNumber() }; 177 constexpr UnaryArithProfileBase bits = observedNumber.bits() << argObservedTypeShift; 178 return bits; 179 } 180 181 constexpr ObservedType argObservedType() const { return ObservedType((m_bits >> argObservedTypeShift) & observedTypeMask); } 182 void setArgObservedType(ObservedType type) 183 { 184 UnaryArithProfileBase bits = m_bits; 185 bits &= clearArgObservedTypeBitMask; 186 bits |= type.bits() << argObservedTypeShift; 187 m_bits = bits; 188 ASSERT(argObservedType() == type); 189 } 190 191 void argSawInt32() { setArgObservedType(argObservedType().withInt32()); } 192 void argSawNumber() { setArgObservedType(argObservedType().withNumber()); } 193 void argSawNonNumber() { setArgObservedType(argObservedType().withNonNumber()); } 194 195 void observeArg(JSValue arg) 196 { 197 UnaryArithProfile newProfile = *this; 198 if (arg.isNumber()) { 199 if (arg.isInt32()) 200 newProfile.argSawInt32(); 201 else 202 newProfile.argSawNumber(); 203 } else 204 newProfile.argSawNonNumber(); 205 206 m_bits = newProfile.bits(); 207 } 208 209 bool isObservedTypeEmpty() 210 { 211 return argObservedType().isEmpty(); 212 } 213 214 friend class JSC::LLIntOffsetsExtractor; 215 }; 216 217 /* This class stores the following components in 16 bits: 218 * - ObservedResults 219 * - ObservedType for right-hand-side 220 * - ObservedType for left-hand-side 221 * - a bit used by division to indicate whether a special fast path was taken 222 */ 223 using BinaryArithProfileBase = uint16_t; 224 class BinaryArithProfile : public ArithProfile<BinaryArithProfileBase> { 225 static constexpr uint32_t rhsObservedTypeShift = observedResultsNumBitsNeeded; 226 static constexpr uint32_t lhsObservedTypeShift = rhsObservedTypeShift + ObservedType::numBitsNeeded; 227 228 static_assert(ObservedType::numBitsNeeded == 3, "We make a hard assumption about that here."); 229 static constexpr BinaryArithProfileBase clearRhsObservedTypeBitMask = static_cast<BinaryArithProfileBase>(~(0b111 << rhsObservedTypeShift)); 230 static constexpr BinaryArithProfileBase clearLhsObservedTypeBitMask = static_cast<BinaryArithProfileBase>(~(0b111 << lhsObservedTypeShift)); 231 232 static constexpr BinaryArithProfileBase observedTypeMask = (1 << ObservedType::numBitsNeeded) - 1; 233 234 public: 235 static constexpr BinaryArithProfileBase specialFastPathBit = 1 << (lhsObservedTypeShift + ObservedType::numBitsNeeded); 236 static_assert((lhsObservedTypeShift + ObservedType::numBitsNeeded + 1) <= sizeof(BinaryArithProfileBase) * 8, "Should fit in a uint32_t."); 237 static_assert(!(specialFastPathBit & ~clearLhsObservedTypeBitMask), "These bits should not intersect."); 238 static_assert(specialFastPathBit & clearLhsObservedTypeBitMask, "These bits should intersect."); 239 static_assert(specialFastPathBit > ~clearLhsObservedTypeBitMask, "These bits should not intersect and specialFastPathBit should be a higher bit."); 240 241 BinaryArithProfile() 242 : ArithProfile<BinaryArithProfileBase> () 243 { 244 ASSERT(lhsObservedType().isEmpty()); 245 ASSERT(rhsObservedType().isEmpty()); 246 } 247 248 static constexpr BinaryArithProfileBase observedIntIntBits() 249 { 250 constexpr ObservedType observedInt32 { ObservedType().withInt32() }; 251 constexpr BinaryArithProfileBase bits = (observedInt32.bits() << lhsObservedTypeShift) | (observedInt32.bits() << rhsObservedTypeShift); 252 return bits; 253 } 254 static constexpr BinaryArithProfileBase observedNumberIntBits() 255 { 256 constexpr ObservedType observedNumber { ObservedType().withNumber() }; 257 constexpr ObservedType observedInt32 { ObservedType().withInt32() }; 258 constexpr BinaryArithProfileBase bits = (observedNumber.bits() << lhsObservedTypeShift) | (observedInt32.bits() << rhsObservedTypeShift); 259 return bits; 260 } 261 static constexpr BinaryArithProfileBase observedIntNumberBits() 262 { 263 constexpr ObservedType observedNumber { ObservedType().withNumber() }; 264 constexpr ObservedType observedInt32 { ObservedType().withInt32() }; 265 constexpr BinaryArithProfileBase bits = (observedInt32.bits() << lhsObservedTypeShift) | (observedNumber.bits() << rhsObservedTypeShift); 266 return bits; 267 } 268 static constexpr BinaryArithProfileBase observedNumberNumberBits() 269 { 270 constexpr ObservedType observedNumber { ObservedType().withNumber() }; 271 constexpr BinaryArithProfileBase bits = (observedNumber.bits() << lhsObservedTypeShift) | (observedNumber.bits() << rhsObservedTypeShift); 272 return bits; 273 } 274 275 constexpr ObservedType lhsObservedType() const { return ObservedType((m_bits >> lhsObservedTypeShift) & observedTypeMask); } 276 constexpr ObservedType rhsObservedType() const { return ObservedType((m_bits >> rhsObservedTypeShift) & observedTypeMask); } 277 void setLhsObservedType(ObservedType type) 278 { 279 BinaryArithProfileBase bits = m_bits; 280 bits &= clearLhsObservedTypeBitMask; 281 bits |= type.bits() << lhsObservedTypeShift; 282 m_bits = bits; 283 ASSERT(lhsObservedType() == type); 284 } 285 286 void setRhsObservedType(ObservedType type) 287 { 288 BinaryArithProfileBase bits = m_bits; 289 bits &= clearRhsObservedTypeBitMask; 290 bits |= type.bits() << rhsObservedTypeShift; 291 m_bits = bits; 292 ASSERT(rhsObservedType() == type); 293 } 294 295 bool tookSpecialFastPath() const { return m_bits & specialFastPathBit; } 296 232 297 void lhsSawInt32() { setLhsObservedType(lhsObservedType().withInt32()); } 233 298 void lhsSawNumber() { setLhsObservedType(lhsObservedType().withNumber()); } … … 239 304 void observeLHS(JSValue lhs) 240 305 { 241 ArithProfile newProfile = *this;306 BinaryArithProfile newProfile = *this; 242 307 if (lhs.isNumber()) { 243 308 if (lhs.isInt32()) … … 255 320 observeLHS(lhs); 256 321 257 ArithProfile newProfile = *this;322 BinaryArithProfile newProfile = *this; 258 323 if (rhs.isNumber()) { 259 324 if (rhs.isInt32()) … … 267 332 } 268 333 269 #if ENABLE(JIT) 270 // Sets (Int32Overflow | Int52Overflow | NonNegZeroDouble | NegZeroDouble) if it sees a 271 // double. Sets NonNumeric if it sees a non-numeric. 272 void emitObserveResult(CCallHelpers&, JSValueRegs, TagRegistersMode = HaveTagRegisters); 273 274 // Sets (Int32Overflow | Int52Overflow | NonNegZeroDouble | NegZeroDouble). 275 bool shouldEmitSetDouble() const; 276 void emitSetDouble(CCallHelpers&) const; 277 278 // Sets NonNumber. 279 void emitSetNonNumeric(CCallHelpers&) const; 280 bool shouldEmitSetNonNumeric() const; 281 282 // Sets BigInt 283 void emitSetBigInt(CCallHelpers&) const; 284 bool shouldEmitSetBigInt() const; 285 #endif // ENABLE(JIT) 286 287 constexpr uint32_t bits() const { return m_bits; } 288 289 private: 290 constexpr explicit ArithProfile(ConstantTag, uint32_t bits) 291 : m_bits(bits) 292 { 293 } 294 295 constexpr ArithProfile(ConstantTag, ResultType arg) 296 : m_bits(arg.bits() << lhsResultTypeShift) 297 { 298 } 299 300 constexpr ArithProfile(ConstantTag, ResultType lhs, ResultType rhs) 301 : m_bits((lhs.bits() << lhsResultTypeShift) | (rhs.bits() << rhsResultTypeShift)) 302 { 303 } 304 305 bool hasBits(int mask) const { return m_bits & mask; } 306 void setBit(int mask) { m_bits |= mask; } 307 308 uint32_t m_bits { 0 }; // We take care to update m_bits only in a single operation. We don't ever store an inconsistent bit representation to it. 334 bool isObservedTypeEmpty() 335 { 336 return lhsObservedType().isEmpty() && rhsObservedType().isEmpty(); 337 } 309 338 310 339 friend class JSC::LLIntOffsetsExtractor; … … 315 344 namespace WTF { 316 345 317 void printInternal(PrintStream&, const JSC::ArithProfile&); 346 void printInternal(PrintStream&, const JSC::UnaryArithProfile&); 347 void printInternal(PrintStream&, const JSC::BinaryArithProfile&); 318 348 void printInternal(PrintStream&, const JSC::ObservedType&); 319 349
Note:
See TracChangeset
for help on using the changeset viewer.