Changeset 252021 in webkit for trunk/Source/JavaScriptCore/bytecode/ArithProfile.h
- Timestamp:
- Nov 4, 2019, 3:47:07 PM (6 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/bytecode/ArithProfile.h
r252015 r252021 67 67 }; 68 68 69 template <typename BitfieldType> 70 class ArithProfile { 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 71 86 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 72 165 enum ObservedResults { 73 166 NonNegZeroDouble = 1 << 0, … … 78 171 BigInt = 1 << 5, 79 172 }; 80 static constexpr uint32_t observedResultsNumBitsNeeded = 6; 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; } 81 198 82 199 bool didObserveNonInt32() const { return hasBits(NonNegZeroDouble | NegZeroDouble | NonNumeric | BigInt); } … … 95 212 void setObservedInt32Overflow() { setBit(Int32Overflow); } 96 213 void setObservedInt52Overflow() { setBit(Int52Overflow); } 214 215 const void* addressOfBits() const { return &m_bits; } 97 216 98 217 void observeResult(JSValue value) … … 111 230 } 112 231 113 const void* addressOfBits() const { return &m_bits; }114 115 #if ENABLE(JIT)116 // Sets (Int32Overflow | Int52Overflow | NonNegZeroDouble | NegZeroDouble) if it sees a117 // 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 BigInt129 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 * - ObservedResults148 * - ObservedType for the argument149 */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 else202 newProfile.argSawNumber();203 } else204 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 * - ObservedResults219 * - ObservedType for right-hand-side220 * - ObservedType for left-hand-side221 * - a bit used by division to indicate whether a special fast path was taken222 */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 297 232 void lhsSawInt32() { setLhsObservedType(lhsObservedType().withInt32()); } 298 233 void lhsSawNumber() { setLhsObservedType(lhsObservedType().withNumber()); } … … 304 239 void observeLHS(JSValue lhs) 305 240 { 306 BinaryArithProfile newProfile = *this;241 ArithProfile newProfile = *this; 307 242 if (lhs.isNumber()) { 308 243 if (lhs.isInt32()) … … 320 255 observeLHS(lhs); 321 256 322 BinaryArithProfile newProfile = *this;257 ArithProfile newProfile = *this; 323 258 if (rhs.isNumber()) { 324 259 if (rhs.isInt32()) … … 332 267 } 333 268 334 bool isObservedTypeEmpty() 335 { 336 return lhsObservedType().isEmpty() && rhsObservedType().isEmpty(); 337 } 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. 338 309 339 310 friend class JSC::LLIntOffsetsExtractor; … … 344 315 namespace WTF { 345 316 346 void printInternal(PrintStream&, const JSC::UnaryArithProfile&); 347 void printInternal(PrintStream&, const JSC::BinaryArithProfile&); 317 void printInternal(PrintStream&, const JSC::ArithProfile&); 348 318 void printInternal(PrintStream&, const JSC::ObservedType&); 349 319
Note:
See TracChangeset
for help on using the changeset viewer.