Changeset 251106 in webkit for trunk/Source/JavaScriptCore/bytecode/ArithProfile.h
- Timestamp:
- Oct 14, 2019, 3:52:11 PM (6 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/bytecode/ArithProfile.h
r251090 r251106 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(BitfieldType bits)137 : m_bits(bits)138 {139 }140 141 bool hasBits(int mask) const { return m_bits & mask; }142 void setBit(int mask) { m_bits |= mask; }143 144 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.145 };146 147 /* This class stores the following components in 16 bits:148 * - ObservedResults149 * - ResultType for the argument150 * - ObservedType for the argument151 */152 class UnaryArithProfile : public ArithProfile<uint16_t> {153 static constexpr unsigned argResultTypeShift = observedResultsNumBitsNeeded;154 static constexpr unsigned argObservedTypeShift = argResultTypeShift + ResultType::numBitsNeeded;155 156 static_assert(argObservedTypeShift + ObservedType::numBitsNeeded <= sizeof(uint16_t) * 8, "Should fit in a uint16_t");157 158 static constexpr uint16_t clearArgObservedTypeBitMask = static_cast<uint16_t>(~(0b111 << argObservedTypeShift));159 160 static constexpr uint16_t resultTypeMask = (1 << ResultType::numBitsNeeded) - 1;161 static constexpr uint16_t observedTypeMask = (1 << ObservedType::numBitsNeeded) - 1;162 163 public:164 UnaryArithProfile(ResultType arg)165 : ArithProfile<uint16_t>(arg.bits() << argResultTypeShift)166 {167 ASSERT(argResultType().bits() == arg.bits());168 ASSERT(argObservedType().isEmpty());169 ASSERT(argObservedType().isEmpty());170 }171 172 UnaryArithProfile()173 : UnaryArithProfile(ResultType::unknownType())174 {175 }176 177 static constexpr uint16_t observedIntBits()178 {179 constexpr ObservedType observedInt32 { ObservedType().withInt32() };180 constexpr uint16_t bits = observedInt32.bits() << argObservedTypeShift;181 static_assert(bits == 0x2000, "");182 return bits;183 }184 static constexpr uint16_t observedNumberBits()185 {186 constexpr ObservedType observedNumber { ObservedType().withNumber() };187 constexpr uint16_t bits = observedNumber.bits() << argObservedTypeShift;188 static_assert(bits == 0x4000, "");189 return bits;190 }191 192 ResultType argResultType() const { return ResultType((m_bits >> argResultTypeShift) & resultTypeMask); }193 194 constexpr ObservedType argObservedType() const { return ObservedType((m_bits >> argObservedTypeShift) & observedTypeMask); }195 void setArgObservedType(ObservedType type)196 {197 uint16_t bits = m_bits;198 bits &= clearArgObservedTypeBitMask;199 bits |= type.bits() << argObservedTypeShift;200 m_bits = bits;201 ASSERT(argObservedType() == type);202 }203 204 void argSawInt32() { setArgObservedType(argObservedType().withInt32()); }205 void argSawNumber() { setArgObservedType(argObservedType().withNumber()); }206 void argSawNonNumber() { setArgObservedType(argObservedType().withNonNumber()); }207 208 void observeArg(JSValue arg)209 {210 UnaryArithProfile newProfile = *this;211 if (arg.isNumber()) {212 if (arg.isInt32())213 newProfile.argSawInt32();214 else215 newProfile.argSawNumber();216 } else217 newProfile.argSawNonNumber();218 219 m_bits = newProfile.bits();220 }221 222 bool isObservedTypeEmpty()223 {224 return argObservedType().isEmpty();225 }226 227 friend class JSC::LLIntOffsetsExtractor;228 };229 230 /* This class stores the following components in 32 bits:231 * - ObservedResults232 * - ResultType for right-hand-side233 * - ResultType for left-hand-side234 * - ObservedType for right-hand-side235 * - ObservedType for left-hand-side236 * - a bit used by division to indicate whether a special fast path was taken237 */238 class BinaryArithProfile : public ArithProfile<uint32_t> {239 static constexpr uint32_t rhsResultTypeShift = observedResultsNumBitsNeeded;240 static constexpr uint32_t lhsResultTypeShift = rhsResultTypeShift + ResultType::numBitsNeeded;241 static constexpr uint32_t rhsObservedTypeShift = lhsResultTypeShift + ResultType::numBitsNeeded;242 static constexpr uint32_t lhsObservedTypeShift = rhsObservedTypeShift + ObservedType::numBitsNeeded;243 244 static_assert(ObservedType::numBitsNeeded == 3, "We make a hard assumption about that here.");245 static constexpr uint32_t clearRhsObservedTypeBitMask = static_cast<uint32_t>(~(0b111 << rhsObservedTypeShift));246 static constexpr uint32_t clearLhsObservedTypeBitMask = static_cast<uint32_t>(~(0b111 << lhsObservedTypeShift));247 248 static constexpr uint32_t resultTypeMask = (1 << ResultType::numBitsNeeded) - 1;249 static constexpr uint32_t observedTypeMask = (1 << ObservedType::numBitsNeeded) - 1;250 251 public:252 static constexpr uint32_t specialFastPathBit = 1 << (lhsObservedTypeShift + ObservedType::numBitsNeeded);253 static_assert((lhsObservedTypeShift + ObservedType::numBitsNeeded + 1) <= sizeof(uint32_t) * 8, "Should fit in a uint32_t.");254 static_assert(!(specialFastPathBit & ~clearLhsObservedTypeBitMask), "These bits should not intersect.");255 static_assert(specialFastPathBit & clearLhsObservedTypeBitMask, "These bits should intersect.");256 static_assert(specialFastPathBit > ~clearLhsObservedTypeBitMask, "These bits should not intersect and specialFastPathBit should be a higher bit.");257 258 BinaryArithProfile(ResultType lhs, ResultType rhs)259 : ArithProfile<uint32_t>((lhs.bits() << lhsResultTypeShift) | (rhs.bits() << rhsResultTypeShift))260 {261 ASSERT(lhsResultType().bits() == lhs.bits() && rhsResultType().bits() == rhs.bits());262 ASSERT(lhsObservedType().isEmpty());263 ASSERT(rhsObservedType().isEmpty());264 }265 266 BinaryArithProfile(OperandTypes types)267 : BinaryArithProfile(types.first(), types.second())268 { }269 270 BinaryArithProfile()271 : BinaryArithProfile(ResultType::unknownType(), ResultType::unknownType())272 {273 }274 275 static constexpr uint32_t observedIntIntBits()276 {277 constexpr ObservedType observedInt32 { ObservedType().withInt32() };278 constexpr uint32_t bits = (observedInt32.bits() << lhsObservedTypeShift) | (observedInt32.bits() << rhsObservedTypeShift);279 static_assert(bits == 0x900000, "");280 return bits;281 }282 static constexpr uint32_t observedNumberIntBits()283 {284 constexpr ObservedType observedNumber { ObservedType().withNumber() };285 constexpr ObservedType observedInt32 { ObservedType().withInt32() };286 constexpr uint32_t bits = (observedNumber.bits() << lhsObservedTypeShift) | (observedInt32.bits() << rhsObservedTypeShift);287 static_assert(bits == 0x1100000, "");288 return bits;289 }290 static constexpr uint32_t observedIntNumberBits()291 {292 constexpr ObservedType observedNumber { ObservedType().withNumber() };293 constexpr ObservedType observedInt32 { ObservedType().withInt32() };294 constexpr uint32_t bits = (observedInt32.bits() << lhsObservedTypeShift) | (observedNumber.bits() << rhsObservedTypeShift);295 static_assert(bits == 0xa00000, "");296 return bits;297 }298 static constexpr uint32_t observedNumberNumberBits()299 {300 constexpr ObservedType observedNumber { ObservedType().withNumber() };301 constexpr uint32_t bits = (observedNumber.bits() << lhsObservedTypeShift) | (observedNumber.bits() << rhsObservedTypeShift);302 static_assert(bits == 0x1200000, "");303 return bits;304 }305 306 ResultType lhsResultType() const { return ResultType((m_bits >> lhsResultTypeShift) & resultTypeMask); }307 ResultType rhsResultType() const { return ResultType((m_bits >> rhsResultTypeShift) & resultTypeMask); }308 309 constexpr ObservedType lhsObservedType() const { return ObservedType((m_bits >> lhsObservedTypeShift) & observedTypeMask); }310 constexpr ObservedType rhsObservedType() const { return ObservedType((m_bits >> rhsObservedTypeShift) & observedTypeMask); }311 void setLhsObservedType(ObservedType type)312 {313 uint32_t bits = m_bits;314 bits &= clearLhsObservedTypeBitMask;315 bits |= type.bits() << lhsObservedTypeShift;316 m_bits = bits;317 ASSERT(lhsObservedType() == type);318 }319 320 void setRhsObservedType(ObservedType type)321 {322 uint32_t bits = m_bits;323 bits &= clearRhsObservedTypeBitMask;324 bits |= type.bits() << rhsObservedTypeShift;325 m_bits = bits;326 ASSERT(rhsObservedType() == type);327 }328 329 bool tookSpecialFastPath() const { return m_bits & specialFastPathBit; }330 331 232 void lhsSawInt32() { setLhsObservedType(lhsObservedType().withInt32()); } 332 233 void lhsSawNumber() { setLhsObservedType(lhsObservedType().withNumber()); } … … 338 239 void observeLHS(JSValue lhs) 339 240 { 340 BinaryArithProfile newProfile = *this;241 ArithProfile newProfile = *this; 341 242 if (lhs.isNumber()) { 342 243 if (lhs.isInt32()) … … 354 255 observeLHS(lhs); 355 256 356 BinaryArithProfile newProfile = *this;257 ArithProfile newProfile = *this; 357 258 if (rhs.isNumber()) { 358 259 if (rhs.isInt32()) … … 366 267 } 367 268 368 bool isObservedTypeEmpty() 369 { 370 return lhsObservedType().isEmpty() && rhsObservedType().isEmpty(); 371 } 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. 372 309 373 310 friend class JSC::LLIntOffsetsExtractor; … … 378 315 namespace WTF { 379 316 380 void printInternal(PrintStream&, const JSC::UnaryArithProfile&); 381 void printInternal(PrintStream&, const JSC::BinaryArithProfile&); 317 void printInternal(PrintStream&, const JSC::ArithProfile&); 382 318 void printInternal(PrintStream&, const JSC::ObservedType&); 383 319
Note:
See TracChangeset
for help on using the changeset viewer.