[JSC] More aggressively use `constexpr` in LowLevelInterpreter.asm for constant values
https://bugs.webkit.org/show_bug.cgi?id=190659
Reviewed by Keith Miller.
Asking the actual constant value to the JSC binary is always the best way to get the correct value.
The value is correctly updated once the original value is changed. We would like to encourage this
approach more in LowLevelInterpreter.asm.
This patch expands the coverage of this approach. We make ObservedType, ResultType, and ArithProfile
constexpr-friendly to produce the magic value used in LowLevelInterpreter.asm at compiling time.
This change allows us to easily extend ArithProfile in the future to adopt BigInt efficiently.
We additionally use `constexpr` for several constant values in LowLevelInterpreter.asm.
* assembler/MaxFrameExtentForSlowPathCall.h:
Use this value in LowLevelInterpreter.asm directly. We also make them constexpr. And we add CPU(ARM64E).
* bytecode/ArithProfile.h:
(JSC::ObservedType::ObservedType):
(JSC::ObservedType::sawInt32 const):
(JSC::ObservedType::isOnlyInt32 const):
(JSC::ObservedType::sawNumber const):
(JSC::ObservedType::isOnlyNumber const):
(JSC::ObservedType::sawNonNumber const):
(JSC::ObservedType::isOnlyNonNumber const):
(JSC::ObservedType::isEmpty const):
(JSC::ObservedType::bits const):
(JSC::ObservedType::withInt32 const):
(JSC::ObservedType::withNumber const):
(JSC::ObservedType::withNonNumber const):
(JSC::ObservedType::withoutNonNumber const):
(JSC::ObservedType::operator== const):
(JSC::ArithProfile::ArithProfile):
(JSC::ArithProfile::fromInt):
(JSC::ArithProfile::observedUnaryInt):
(JSC::ArithProfile::observedUnaryNumber):
(JSC::ArithProfile::observedBinaryIntInt):
(JSC::ArithProfile::observedBinaryNumberInt):
(JSC::ArithProfile::observedBinaryIntNumber):
(JSC::ArithProfile::observedBinaryNumberNumber):
(JSC::ArithProfile::lhsObservedType const):
(JSC::ArithProfile::rhsObservedType const):
(JSC::ArithProfile::bits const):
Make ObservedType and ArithProfile constexpr-friendly.
* llint/LLIntData.cpp:
(JSC::LLInt::Data::performAssertions):
Make several ASSERTs to STATIC_ASSERTs. Remove some unnecessary checks.
* llint/LLIntOffsetsExtractor.cpp:
* llint/LowLevelInterpreter.asm:
Remove unused constant values. Use constexpr more and more aggressively.
* parser/ResultType.h:
(JSC::ResultType::ResultType):
(JSC::ResultType::isInt32 const):
(JSC::ResultType::definitelyIsNumber const):
(JSC::ResultType::definitelyIsString const):
(JSC::ResultType::definitelyIsBoolean const):
(JSC::ResultType::definitelyIsBigInt const):
(JSC::ResultType::mightBeNumber const):
(JSC::ResultType::isNotNumber const):
(JSC::ResultType::mightBeBigInt const):
(JSC::ResultType::isNotBigInt const):
(JSC::ResultType::nullType):
(JSC::ResultType::booleanType):
(JSC::ResultType::numberType):
(JSC::ResultType::numberTypeIsInt32):
(JSC::ResultType::stringOrNumberType):
(JSC::ResultType::addResultType):
(JSC::ResultType::stringType):
(JSC::ResultType::bigIntType):
(JSC::ResultType::unknownType):
(JSC::ResultType::forAdd):
(JSC::ResultType::forLogicalOp):
(JSC::ResultType::forBitOp):
(JSC::ResultType::bits const):
Make ResultType constexpr-friendly.
* runtime/JSCJSValue.h:
Use offsetof instead of OBJECT_OFFSETOF. It is OK since EncodedValueDescriptor is POD.
This change makes TagOffset and PayloadOffset macros constexpr-friendly while OBJECT_OFFSETOF
cannot be used in constexpr since it uses reinterpret_cast.
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@237220 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog
index fe82449..86b4e66 100644
--- a/Source/JavaScriptCore/ChangeLog
+++ b/Source/JavaScriptCore/ChangeLog
@@ -1,3 +1,89 @@
+2018-10-17 Yusuke Suzuki <yusukesuzuki@slowstart.org>
+
+ [JSC] More aggressively use `constexpr` in LowLevelInterpreter.asm for constant values
+ https://bugs.webkit.org/show_bug.cgi?id=190659
+
+ Reviewed by Keith Miller.
+
+ Asking the actual constant value to the JSC binary is always the best way to get the correct value.
+ The value is correctly updated once the original value is changed. We would like to encourage this
+ approach more in LowLevelInterpreter.asm.
+
+ This patch expands the coverage of this approach. We make ObservedType, ResultType, and ArithProfile
+ constexpr-friendly to produce the magic value used in LowLevelInterpreter.asm at compiling time.
+ This change allows us to easily extend ArithProfile in the future to adopt BigInt efficiently.
+
+ We additionally use `constexpr` for several constant values in LowLevelInterpreter.asm.
+
+ * assembler/MaxFrameExtentForSlowPathCall.h:
+ Use this value in LowLevelInterpreter.asm directly. We also make them constexpr. And we add CPU(ARM64E).
+
+ * bytecode/ArithProfile.h:
+ (JSC::ObservedType::ObservedType):
+ (JSC::ObservedType::sawInt32 const):
+ (JSC::ObservedType::isOnlyInt32 const):
+ (JSC::ObservedType::sawNumber const):
+ (JSC::ObservedType::isOnlyNumber const):
+ (JSC::ObservedType::sawNonNumber const):
+ (JSC::ObservedType::isOnlyNonNumber const):
+ (JSC::ObservedType::isEmpty const):
+ (JSC::ObservedType::bits const):
+ (JSC::ObservedType::withInt32 const):
+ (JSC::ObservedType::withNumber const):
+ (JSC::ObservedType::withNonNumber const):
+ (JSC::ObservedType::withoutNonNumber const):
+ (JSC::ObservedType::operator== const):
+ (JSC::ArithProfile::ArithProfile):
+ (JSC::ArithProfile::fromInt):
+ (JSC::ArithProfile::observedUnaryInt):
+ (JSC::ArithProfile::observedUnaryNumber):
+ (JSC::ArithProfile::observedBinaryIntInt):
+ (JSC::ArithProfile::observedBinaryNumberInt):
+ (JSC::ArithProfile::observedBinaryIntNumber):
+ (JSC::ArithProfile::observedBinaryNumberNumber):
+ (JSC::ArithProfile::lhsObservedType const):
+ (JSC::ArithProfile::rhsObservedType const):
+ (JSC::ArithProfile::bits const):
+ Make ObservedType and ArithProfile constexpr-friendly.
+
+ * llint/LLIntData.cpp:
+ (JSC::LLInt::Data::performAssertions):
+ Make several ASSERTs to STATIC_ASSERTs. Remove some unnecessary checks.
+ * llint/LLIntOffsetsExtractor.cpp:
+ * llint/LowLevelInterpreter.asm:
+ Remove unused constant values. Use constexpr more and more aggressively.
+
+ * parser/ResultType.h:
+ (JSC::ResultType::ResultType):
+ (JSC::ResultType::isInt32 const):
+ (JSC::ResultType::definitelyIsNumber const):
+ (JSC::ResultType::definitelyIsString const):
+ (JSC::ResultType::definitelyIsBoolean const):
+ (JSC::ResultType::definitelyIsBigInt const):
+ (JSC::ResultType::mightBeNumber const):
+ (JSC::ResultType::isNotNumber const):
+ (JSC::ResultType::mightBeBigInt const):
+ (JSC::ResultType::isNotBigInt const):
+ (JSC::ResultType::nullType):
+ (JSC::ResultType::booleanType):
+ (JSC::ResultType::numberType):
+ (JSC::ResultType::numberTypeIsInt32):
+ (JSC::ResultType::stringOrNumberType):
+ (JSC::ResultType::addResultType):
+ (JSC::ResultType::stringType):
+ (JSC::ResultType::bigIntType):
+ (JSC::ResultType::unknownType):
+ (JSC::ResultType::forAdd):
+ (JSC::ResultType::forLogicalOp):
+ (JSC::ResultType::forBitOp):
+ (JSC::ResultType::bits const):
+ Make ResultType constexpr-friendly.
+
+ * runtime/JSCJSValue.h:
+ Use offsetof instead of OBJECT_OFFSETOF. It is OK since EncodedValueDescriptor is POD.
+ This change makes TagOffset and PayloadOffset macros constexpr-friendly while OBJECT_OFFSETOF
+ cannot be used in constexpr since it uses reinterpret_cast.
+
2018-10-17 Keith Miller <keith_miller@apple.com>
Unreviewed revert Fujii's revert in r237214 with new WinCairo build fix.
diff --git a/Source/JavaScriptCore/assembler/MaxFrameExtentForSlowPathCall.h b/Source/JavaScriptCore/assembler/MaxFrameExtentForSlowPathCall.h
index 4321305..6dac09c 100644
--- a/Source/JavaScriptCore/assembler/MaxFrameExtentForSlowPathCall.h
+++ b/Source/JavaScriptCore/assembler/MaxFrameExtentForSlowPathCall.h
@@ -36,44 +36,44 @@
// from JS code.
#if !ENABLE(ASSEMBLER)
-static const size_t maxFrameExtentForSlowPathCall = 0;
+static constexpr size_t maxFrameExtentForSlowPathCall = 0;
#elif CPU(X86_64) && OS(WINDOWS)
// 4 args in registers, but stack space needs to be allocated for all args.
-static const size_t maxFrameExtentForSlowPathCall = 64;
+static constexpr size_t maxFrameExtentForSlowPathCall = 64;
#elif CPU(X86_64)
// All args in registers.
-static const size_t maxFrameExtentForSlowPathCall = 0;
+static constexpr size_t maxFrameExtentForSlowPathCall = 0;
#elif CPU(X86)
// 7 args on stack (28 bytes).
-static const size_t maxFrameExtentForSlowPathCall = 40;
+static constexpr size_t maxFrameExtentForSlowPathCall = 40;
-#elif CPU(ARM64)
+#elif CPU(ARM64) || CPU(ARM64E)
// All args in registers.
-static const size_t maxFrameExtentForSlowPathCall = 0;
+static constexpr size_t maxFrameExtentForSlowPathCall = 0;
#elif CPU(ARM)
// First four args in registers, remaining 4 args on stack.
-static const size_t maxFrameExtentForSlowPathCall = 24;
+static constexpr size_t maxFrameExtentForSlowPathCall = 24;
#elif CPU(MIPS)
// Though args are in registers, there need to be space on the stack for all args.
-static const size_t maxFrameExtentForSlowPathCall = 40;
+static constexpr size_t maxFrameExtentForSlowPathCall = 40;
#else
#error "Unsupported CPU: need value for maxFrameExtentForSlowPathCall"
#endif
-COMPILE_ASSERT(!(maxFrameExtentForSlowPathCall % sizeof(Register)), extent_must_be_in_multiples_of_registers);
+static_assert(!(maxFrameExtentForSlowPathCall % sizeof(Register)), "Extent must be in multiples of registers");
#if ENABLE(ASSEMBLER)
// Make sure that cfr - maxFrameExtentForSlowPathCall bytes will make the stack pointer aligned
-COMPILE_ASSERT((maxFrameExtentForSlowPathCall % 16) == 16 - sizeof(CallerFrameAndPC), extent_must_align_stack_from_callframe_pointer);
+static_assert((maxFrameExtentForSlowPathCall % 16) == 16 - sizeof(CallerFrameAndPC), "Extent must align stack from callframe pointer");
#endif
-static const size_t maxFrameExtentForSlowPathCallInRegisters = maxFrameExtentForSlowPathCall / sizeof(Register);
+static constexpr size_t maxFrameExtentForSlowPathCallInRegisters = maxFrameExtentForSlowPathCall / sizeof(Register);
} // namespace JSC
diff --git a/Source/JavaScriptCore/bytecode/ArithProfile.h b/Source/JavaScriptCore/bytecode/ArithProfile.h
index 40fad1b..52eef82 100644
--- a/Source/JavaScriptCore/bytecode/ArithProfile.h
+++ b/Source/JavaScriptCore/bytecode/ArithProfile.h
@@ -35,80 +35,126 @@
class CCallHelpers;
struct ObservedType {
- ObservedType(uint8_t bits = TypeEmpty)
+ constexpr ObservedType(uint8_t bits = TypeEmpty)
: m_bits(bits)
{ }
- bool sawInt32() const { return m_bits & TypeInt32; }
- bool isOnlyInt32() const { return m_bits == TypeInt32; }
- bool sawNumber() const { return m_bits & TypeNumber; }
- bool isOnlyNumber() const { return m_bits == TypeNumber; }
- bool sawNonNumber() const { return m_bits & TypeNonNumber; }
- bool isOnlyNonNumber() const { return m_bits == TypeNonNumber; }
- bool isEmpty() const { return !m_bits; }
- uint8_t bits() const { return m_bits; }
+ constexpr bool sawInt32() const { return m_bits & TypeInt32; }
+ constexpr bool isOnlyInt32() const { return m_bits == TypeInt32; }
+ constexpr bool sawNumber() const { return m_bits & TypeNumber; }
+ constexpr bool isOnlyNumber() const { return m_bits == TypeNumber; }
+ constexpr bool sawNonNumber() const { return m_bits & TypeNonNumber; }
+ constexpr bool isOnlyNonNumber() const { return m_bits == TypeNonNumber; }
+ constexpr bool isEmpty() const { return !m_bits; }
+ constexpr uint8_t bits() const { return m_bits; }
- ObservedType withInt32() const { return ObservedType(m_bits | TypeInt32); }
- ObservedType withNumber() const { return ObservedType(m_bits | TypeNumber); }
- ObservedType withNonNumber() const { return ObservedType(m_bits | TypeNonNumber); }
- ObservedType withoutNonNumber() const { return ObservedType(m_bits & ~TypeNonNumber); }
+ constexpr ObservedType withInt32() const { return ObservedType(m_bits | TypeInt32); }
+ constexpr ObservedType withNumber() const { return ObservedType(m_bits | TypeNumber); }
+ constexpr ObservedType withNonNumber() const { return ObservedType(m_bits | TypeNonNumber); }
+ constexpr ObservedType withoutNonNumber() const { return ObservedType(m_bits & ~TypeNonNumber); }
- bool operator==(const ObservedType& other) const { return m_bits == other.m_bits; }
+ constexpr bool operator==(const ObservedType& other) const { return m_bits == other.m_bits; }
- static const uint8_t TypeEmpty = 0x0;
- static const uint8_t TypeInt32 = 0x1;
- static const uint8_t TypeNumber = 0x02;
- static const uint8_t TypeNonNumber = 0x04;
+ static constexpr uint8_t TypeEmpty = 0x0;
+ static constexpr uint8_t TypeInt32 = 0x1;
+ static constexpr uint8_t TypeNumber = 0x02;
+ static constexpr uint8_t TypeNonNumber = 0x04;
- static const uint32_t numBitsNeeded = 3;
+ static constexpr uint32_t numBitsNeeded = 3;
private:
- uint8_t m_bits;
+ uint8_t m_bits { 0 };
};
struct ArithProfile {
private:
- static const uint32_t numberOfFlagBits = 5;
- static const uint32_t rhsResultTypeShift = numberOfFlagBits;
- static const uint32_t lhsResultTypeShift = rhsResultTypeShift + ResultType::numBitsNeeded;
- static const uint32_t rhsObservedTypeShift = lhsResultTypeShift + ResultType::numBitsNeeded;
- static const uint32_t lhsObservedTypeShift = rhsObservedTypeShift + ObservedType::numBitsNeeded;
+ static constexpr uint32_t numberOfFlagBits = 5;
+ static constexpr uint32_t rhsResultTypeShift = numberOfFlagBits;
+ static constexpr uint32_t lhsResultTypeShift = rhsResultTypeShift + ResultType::numBitsNeeded;
+ static constexpr uint32_t rhsObservedTypeShift = lhsResultTypeShift + ResultType::numBitsNeeded;
+ static constexpr uint32_t lhsObservedTypeShift = rhsObservedTypeShift + ObservedType::numBitsNeeded;
static_assert(ObservedType::numBitsNeeded == 3, "We make a hard assumption about that here.");
- static const uint32_t clearRhsObservedTypeBitMask = static_cast<uint32_t>(~((1 << rhsObservedTypeShift) | (1 << (rhsObservedTypeShift + 1)) | (1 << (rhsObservedTypeShift + 2))));
- static const uint32_t clearLhsObservedTypeBitMask = static_cast<uint32_t>(~((1 << lhsObservedTypeShift) | (1 << (lhsObservedTypeShift + 1)) | (1 << (lhsObservedTypeShift + 2))));
+ static constexpr uint32_t clearRhsObservedTypeBitMask = static_cast<uint32_t>(~((1 << rhsObservedTypeShift) | (1 << (rhsObservedTypeShift + 1)) | (1 << (rhsObservedTypeShift + 2))));
+ static constexpr uint32_t clearLhsObservedTypeBitMask = static_cast<uint32_t>(~((1 << lhsObservedTypeShift) | (1 << (lhsObservedTypeShift + 1)) | (1 << (lhsObservedTypeShift + 2))));
- static const uint32_t resultTypeMask = (1 << ResultType::numBitsNeeded) - 1;
- static const uint32_t observedTypeMask = (1 << ObservedType::numBitsNeeded) - 1;
+ static constexpr uint32_t resultTypeMask = (1 << ResultType::numBitsNeeded) - 1;
+ static constexpr uint32_t observedTypeMask = (1 << ObservedType::numBitsNeeded) - 1;
+
+ enum class ConstantTag { Constant };
+
public:
- static const uint32_t specialFastPathBit = 1 << (lhsObservedTypeShift + ObservedType::numBitsNeeded);
+ static constexpr uint32_t specialFastPathBit = 1 << (lhsObservedTypeShift + ObservedType::numBitsNeeded);
static_assert((lhsObservedTypeShift + ObservedType::numBitsNeeded) <= (sizeof(uint32_t) * 8) - 1, "Should fit in a uint32_t.");
static_assert(!(specialFastPathBit & ~clearLhsObservedTypeBitMask), "These bits should not intersect.");
static_assert(specialFastPathBit & clearLhsObservedTypeBitMask, "These bits should intersect.");
static_assert(specialFastPathBit > ~clearLhsObservedTypeBitMask, "These bits should not intersect and specialFastPathBit should be a higher bit.");
ArithProfile(ResultType arg)
+ : ArithProfile(ConstantTag::Constant, arg)
{
- m_bits = (arg.bits() << lhsResultTypeShift);
ASSERT(lhsResultType().bits() == arg.bits());
ASSERT(lhsObservedType().isEmpty());
ASSERT(rhsObservedType().isEmpty());
}
ArithProfile(ResultType lhs, ResultType rhs)
+ : ArithProfile(ConstantTag::Constant, lhs, rhs)
{
- m_bits = (lhs.bits() << lhsResultTypeShift) | (rhs.bits() << rhsResultTypeShift);
ASSERT(lhsResultType().bits() == lhs.bits() && rhsResultType().bits() == rhs.bits());
ASSERT(lhsObservedType().isEmpty());
ASSERT(rhsObservedType().isEmpty());
}
ArithProfile() = default;
- static ArithProfile fromInt(uint32_t bits)
+ static constexpr ArithProfile fromInt(uint32_t bits)
{
- ArithProfile result;
- result.m_bits = bits;
- return result;
+ return ArithProfile { ConstantTag::Constant, bits };
+ }
+
+ static constexpr ArithProfile observedUnaryInt()
+ {
+ constexpr ObservedType observedInt32 { ObservedType().withInt32() };
+ constexpr uint32_t bits = observedInt32.bits() << lhsObservedTypeShift;
+ static_assert(bits == 0x400000, "");
+ return fromInt(bits);
+ }
+ static constexpr ArithProfile observedUnaryNumber()
+ {
+ constexpr ObservedType observedNumber { ObservedType().withNumber() };
+ constexpr uint32_t bits = observedNumber.bits() << lhsObservedTypeShift;
+ static_assert(bits == 0x800000, "");
+ return fromInt(bits);
+ }
+ static constexpr ArithProfile observedBinaryIntInt()
+ {
+ constexpr ObservedType observedInt32 { ObservedType().withInt32() };
+ constexpr uint32_t bits = (observedInt32.bits() << lhsObservedTypeShift) | (observedInt32.bits() << rhsObservedTypeShift);
+ static_assert(bits == 0x480000, "");
+ return fromInt(bits);
+ }
+ static constexpr ArithProfile observedBinaryNumberInt()
+ {
+ constexpr ObservedType observedNumber { ObservedType().withNumber() };
+ constexpr ObservedType observedInt32 { ObservedType().withInt32() };
+ constexpr uint32_t bits = (observedNumber.bits() << lhsObservedTypeShift) | (observedInt32.bits() << rhsObservedTypeShift);
+ static_assert(bits == 0x880000, "");
+ return fromInt(bits);
+ }
+ static constexpr ArithProfile observedBinaryIntNumber()
+ {
+ constexpr ObservedType observedNumber { ObservedType().withNumber() };
+ constexpr ObservedType observedInt32 { ObservedType().withInt32() };
+ constexpr uint32_t bits = (observedInt32.bits() << lhsObservedTypeShift) | (observedNumber.bits() << rhsObservedTypeShift);
+ static_assert(bits == 0x500000, "");
+ return fromInt(bits);
+ }
+ static constexpr ArithProfile observedBinaryNumberNumber()
+ {
+ constexpr ObservedType observedNumber { ObservedType().withNumber() };
+ constexpr uint32_t bits = (observedNumber.bits() << lhsObservedTypeShift) | (observedNumber.bits() << rhsObservedTypeShift);
+ static_assert(bits == 0x900000, "");
+ return fromInt(bits);
}
enum ObservedResults {
@@ -122,8 +168,8 @@
ResultType lhsResultType() const { return ResultType((m_bits >> lhsResultTypeShift) & resultTypeMask); }
ResultType rhsResultType() const { return ResultType((m_bits >> rhsResultTypeShift) & resultTypeMask); }
- ObservedType lhsObservedType() const { return ObservedType((m_bits >> lhsObservedTypeShift) & observedTypeMask); }
- ObservedType rhsObservedType() const { return ObservedType((m_bits >> rhsObservedTypeShift) & observedTypeMask); }
+ constexpr ObservedType lhsObservedType() const { return ObservedType((m_bits >> lhsObservedTypeShift) & observedTypeMask); }
+ constexpr ObservedType rhsObservedType() const { return ObservedType((m_bits >> rhsObservedTypeShift) & observedTypeMask); }
void setLhsObservedType(ObservedType type)
{
uint32_t bits = m_bits;
@@ -222,9 +268,24 @@
bool shouldEmitSetNonNumber() const;
#endif // ENABLE(JIT)
- uint32_t bits() const { return m_bits; }
+ constexpr uint32_t bits() const { return m_bits; }
private:
+ constexpr explicit ArithProfile(ConstantTag, uint32_t bits)
+ : m_bits(bits)
+ {
+ }
+
+ constexpr ArithProfile(ConstantTag, ResultType arg)
+ : m_bits(arg.bits() << lhsResultTypeShift)
+ {
+ }
+
+ constexpr ArithProfile(ConstantTag, ResultType lhs, ResultType rhs)
+ : m_bits((lhs.bits() << lhsResultTypeShift) | (rhs.bits() << rhsResultTypeShift))
+ {
+ }
+
bool hasBits(int mask) const { return m_bits & mask; }
void setBit(int mask) { m_bits |= mask; }
diff --git a/Source/JavaScriptCore/llint/LLIntData.cpp b/Source/JavaScriptCore/llint/LLIntData.cpp
index d061b63..a981f4a 100644
--- a/Source/JavaScriptCore/llint/LLIntData.cpp
+++ b/Source/JavaScriptCore/llint/LLIntData.cpp
@@ -98,11 +98,11 @@
ASSERT(CallFrame::argumentOffsetIncludingThis(0) == CallFrameSlot::thisArgument);
#if CPU(BIG_ENDIAN)
- ASSERT(OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag) == 0);
- ASSERT(OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload) == 4);
+ STATIC_ASSERT(TagOffset == 0);
+ STATIC_ASSERT(PayloadOffset == 4);
#else
- ASSERT(OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag) == 4);
- ASSERT(OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload) == 0);
+ STATIC_ASSERT(TagOffset == 4);
+ STATIC_ASSERT(PayloadOffset == 0);
#endif
#if USE(JSVALUE32_64)
STATIC_ASSERT(JSValue::Int32Tag == static_cast<unsigned>(-1));
@@ -123,15 +123,6 @@
STATIC_ASSERT(ValueUndefined == (TagBitTypeOther | TagBitUndefined));
STATIC_ASSERT(ValueNull == TagBitTypeOther);
#endif
-#if (CPU(X86_64) && !OS(WINDOWS)) || CPU(ARM64) || !ENABLE(ASSEMBLER)
- STATIC_ASSERT(!maxFrameExtentForSlowPathCall);
-#elif CPU(ARM)
- STATIC_ASSERT(maxFrameExtentForSlowPathCall == 24);
-#elif CPU(X86) || CPU(MIPS)
- STATIC_ASSERT(maxFrameExtentForSlowPathCall == 40);
-#elif CPU(X86_64) && OS(WINDOWS)
- STATIC_ASSERT(maxFrameExtentForSlowPathCall == 64);
-#endif
#if ENABLE(C_LOOP) || USE(JSVALUE32_64)
ASSERT(!CodeBlock::llintBaselineCalleeSaveSpaceAsVirtualRegisters());
@@ -151,47 +142,37 @@
ASSERT(bitwise_cast<int**>(&testVector)[0] == testVector.begin());
#endif
- ASSERT(StringImpl::s_hashFlag8BitBuffer == 8);
-
{
- uint32_t bits = 0x480000;
- UNUSED_PARAM(bits);
ArithProfile arithProfile;
arithProfile.lhsSawInt32();
arithProfile.rhsSawInt32();
- ASSERT(arithProfile.bits() == bits);
- ASSERT(ArithProfile::fromInt(bits).lhsObservedType().isOnlyInt32());
- ASSERT(ArithProfile::fromInt(bits).rhsObservedType().isOnlyInt32());
+ ASSERT(arithProfile.bits() == ArithProfile::observedBinaryIntInt().bits());
+ STATIC_ASSERT(ArithProfile::observedBinaryIntInt().lhsObservedType().isOnlyInt32());
+ STATIC_ASSERT(ArithProfile::observedBinaryIntInt().rhsObservedType().isOnlyInt32());
}
{
- uint32_t bits = 0x880000;
- UNUSED_PARAM(bits);
ArithProfile arithProfile;
arithProfile.lhsSawNumber();
arithProfile.rhsSawInt32();
- ASSERT(arithProfile.bits() == bits);
- ASSERT(ArithProfile::fromInt(bits).lhsObservedType().isOnlyNumber());
- ASSERT(ArithProfile::fromInt(bits).rhsObservedType().isOnlyInt32());
+ ASSERT(arithProfile.bits() == ArithProfile::observedBinaryNumberInt().bits());
+ STATIC_ASSERT(ArithProfile::observedBinaryNumberInt().lhsObservedType().isOnlyNumber());
+ STATIC_ASSERT(ArithProfile::observedBinaryNumberInt().rhsObservedType().isOnlyInt32());
}
{
- uint32_t bits = 0x900000;
- UNUSED_PARAM(bits);
ArithProfile arithProfile;
arithProfile.lhsSawNumber();
arithProfile.rhsSawNumber();
- ASSERT(arithProfile.bits() == bits);
- ASSERT(ArithProfile::fromInt(bits).lhsObservedType().isOnlyNumber());
- ASSERT(ArithProfile::fromInt(bits).rhsObservedType().isOnlyNumber());
+ ASSERT(arithProfile.bits() == ArithProfile::observedBinaryNumberNumber().bits());
+ STATIC_ASSERT(ArithProfile::observedBinaryNumberNumber().lhsObservedType().isOnlyNumber());
+ STATIC_ASSERT(ArithProfile::observedBinaryNumberNumber().rhsObservedType().isOnlyNumber());
}
{
- uint32_t bits = 0x500000;
- UNUSED_PARAM(bits);
ArithProfile arithProfile;
arithProfile.lhsSawInt32();
arithProfile.rhsSawNumber();
- ASSERT(arithProfile.bits() == bits);
- ASSERT(ArithProfile::fromInt(bits).lhsObservedType().isOnlyInt32());
- ASSERT(ArithProfile::fromInt(bits).rhsObservedType().isOnlyNumber());
+ ASSERT(arithProfile.bits() == ArithProfile::observedBinaryIntNumber().bits());
+ STATIC_ASSERT(ArithProfile::observedBinaryIntNumber().lhsObservedType().isOnlyInt32());
+ STATIC_ASSERT(ArithProfile::observedBinaryIntNumber().rhsObservedType().isOnlyNumber());
}
}
IGNORE_CLANG_WARNINGS_END
diff --git a/Source/JavaScriptCore/llint/LLIntOffsetsExtractor.cpp b/Source/JavaScriptCore/llint/LLIntOffsetsExtractor.cpp
index 6174b94..4fd9050 100644
--- a/Source/JavaScriptCore/llint/LLIntOffsetsExtractor.cpp
+++ b/Source/JavaScriptCore/llint/LLIntOffsetsExtractor.cpp
@@ -25,6 +25,7 @@
#include "config.h"
+#include "ArithProfile.h"
#include "ArrayProfile.h"
#include "BytecodeStructs.h"
#include "CodeBlock.h"
@@ -50,6 +51,7 @@
#include "JumpTable.h"
#include "LLIntOfflineAsmConfig.h"
#include "MarkedSpace.h"
+#include "MaxFrameExtentForSlowPathCall.h"
#include "NativeExecutable.h"
#include "ProtoCallFrame.h"
#include "ShadowChicken.h"
diff --git a/Source/JavaScriptCore/llint/LowLevelInterpreter.asm b/Source/JavaScriptCore/llint/LowLevelInterpreter.asm
index e8aa300..6507eb8 100644
--- a/Source/JavaScriptCore/llint/LowLevelInterpreter.asm
+++ b/Source/JavaScriptCore/llint/LowLevelInterpreter.asm
@@ -154,22 +154,21 @@
# These declarations must match interpreter/JSStack.h.
const PtrSize = constexpr (sizeof(void*))
+const MachineRegisterSize = constexpr (sizeof(CPURegister))
+const SlotSize = constexpr (sizeof(Register))
if JSVALUE64
const CallFrameHeaderSlots = 5
- const MachineRegisterSize = 8
else
const CallFrameHeaderSlots = 4
const CallFrameAlignSlots = 1
- const MachineRegisterSize = 4
end
-const SlotSize = 8
const JSLexicalEnvironment_variables = (sizeof JSLexicalEnvironment + SlotSize - 1) & ~(SlotSize - 1)
const DirectArguments_storage = (sizeof DirectArguments + SlotSize - 1) & ~(SlotSize - 1)
-const StackAlignment = 16
-const StackAlignmentSlots = 2
+const StackAlignment = constexpr (stackAlignmentBytes())
+const StackAlignmentSlots = constexpr (stackAlignmentRegisters())
const StackAlignmentMask = StackAlignment - 1
const CallerFrameAndPCSize = constexpr (sizeof(CallerFrameAndPC))
@@ -185,25 +184,25 @@
# Some value representation constants.
if JSVALUE64
- const TagBitTypeOther = 0x2
- const TagBitBool = 0x4
- const TagBitUndefined = 0x8
- const ValueEmpty = 0x0
- const ValueFalse = TagBitTypeOther | TagBitBool
- const ValueTrue = TagBitTypeOther | TagBitBool | 1
- const ValueUndefined = TagBitTypeOther | TagBitUndefined
- const ValueNull = TagBitTypeOther
- const TagTypeNumber = 0xffff000000000000
- const TagMask = TagTypeNumber | TagBitTypeOther
+ const TagBitTypeOther = constexpr TagBitTypeOther
+ const TagBitBool = constexpr TagBitBool
+ const TagBitUndefined = constexpr TagBitUndefined
+ const ValueEmpty = constexpr ValueEmpty
+ const ValueFalse = constexpr ValueFalse
+ const ValueTrue = constexpr ValueTrue
+ const ValueUndefined = constexpr ValueUndefined
+ const ValueNull = constexpr ValueNull
+ const TagTypeNumber = constexpr TagTypeNumber
+ const TagMask = constexpr TagMask
else
- const Int32Tag = -1
- const BooleanTag = -2
- const NullTag = -3
- const UndefinedTag = -4
- const CellTag = -5
- const EmptyValueTag = -6
- const DeletedValueTag = -7
- const LowestTag = DeletedValueTag
+ const Int32Tag = constexpr JSValue::Int32Tag
+ const BooleanTag = constexpr JSValue::BooleanTag
+ const NullTag = constexpr JSValue::NullTag
+ const UndefinedTag = constexpr JSValue::UndefinedTag
+ const CellTag = constexpr JSValue::CellTag
+ const EmptyValueTag = constexpr JSValue::EmptyValueTag
+ const DeletedValueTag = constexpr JSValue::DeletedValueTag
+ const LowestTag = constexpr JSValue::LowestTag
end
# PutByIdFlags data
@@ -223,19 +222,9 @@
const PutByIdSecondaryTypeObjectOrOther = constexpr PutByIdSecondaryTypeObjectOrOther
const PutByIdSecondaryTypeTop = constexpr PutByIdSecondaryTypeTop
-const CallOpCodeSize = 9
+const CallOpCodeSize = constexpr op_call_length
-if X86_64 or ARM64 or ARM64E or C_LOOP
- const maxFrameExtentForSlowPathCall = 0
-elsif ARM or ARMv7_TRADITIONAL or ARMv7
- const maxFrameExtentForSlowPathCall = 24
-elsif X86 or X86_WIN
- const maxFrameExtentForSlowPathCall = 40
-elsif MIPS
- const maxFrameExtentForSlowPathCall = 40
-elsif X86_64_WIN
- const maxFrameExtentForSlowPathCall = 64
-end
+const maxFrameExtentForSlowPathCall = constexpr maxFrameExtentForSlowPathCall
if X86_64 or X86_64_WIN or ARM64 or ARM64E
const CalleeSaveSpaceAsVirtualRegisters = 3
@@ -255,12 +244,12 @@
const ShadowChickenTailMarker = constexpr ShadowChicken::Packet::tailMarkerValue
# ArithProfile data
-const ArithProfileInt = 0x400000
-const ArithProfileIntInt = 0x480000
-const ArithProfileNumber = 0x800000
-const ArithProfileNumberInt = 0x880000
-const ArithProfileNumberNumber = 0x900000
-const ArithProfileIntNumber = 0x500000
+const ArithProfileInt = constexpr (ArithProfile::observedUnaryInt().bits())
+const ArithProfileNumber = constexpr (ArithProfile::observedUnaryNumber().bits())
+const ArithProfileIntInt = constexpr (ArithProfile::observedBinaryIntInt().bits())
+const ArithProfileNumberInt = constexpr (ArithProfile::observedBinaryNumberInt().bits())
+const ArithProfileIntNumber = constexpr (ArithProfile::observedBinaryIntNumber().bits())
+const ArithProfileNumberNumber = constexpr (ArithProfile::observedBinaryNumberNumber().bits())
# Pointer Tags
const BytecodePtrTag = constexpr BytecodePtrTag
@@ -361,13 +350,8 @@
end
# Constants for reasoning about value representation.
-if BIG_ENDIAN
- const TagOffset = 0
- const PayloadOffset = 4
-else
- const TagOffset = 4
- const PayloadOffset = 0
-end
+const TagOffset = constexpr TagOffset
+const PayloadOffset = constexpr PayloadOffset
# Constant for reasoning about butterflies.
const IsArray = constexpr IsArray
@@ -422,10 +406,10 @@
const LLIntReturnPC = ArgumentCount + TagOffset
# String flags.
-const HashFlags8BitBuffer = 8
+const HashFlags8BitBuffer = constexpr StringImpl::s_hashFlag8BitBuffer
# Copied from PropertyOffset.h
-const firstOutOfLineOffset = 100
+const firstOutOfLineOffset = constexpr firstOutOfLineOffset
# ResolveType
const GlobalProperty = constexpr GlobalProperty
@@ -450,13 +434,6 @@
const BlackThreshold = constexpr blackThreshold
-# Allocation constants
-if JSVALUE64
- const JSFinalObjectSizeClassIndex = 1
-else
- const JSFinalObjectSizeClassIndex = 3
-end
-
# This must match wtf/Vector.h
const VectorBufferOffset = 0
if JSVALUE64
diff --git a/Source/JavaScriptCore/parser/ResultType.h b/Source/JavaScriptCore/parser/ResultType.h
index 03cae2a4..7d46929 100644
--- a/Source/JavaScriptCore/parser/ResultType.h
+++ b/Source/JavaScriptCore/parser/ResultType.h
@@ -32,116 +32,116 @@
friend struct OperandTypes;
using Type = uint8_t;
- static const Type TypeInt32 = 1;
- static const Type TypeMaybeNumber = 0x02;
- static const Type TypeMaybeString = 0x04;
- static const Type TypeMaybeNull = 0x08;
- static const Type TypeMaybeBool = 0x10;
- static const Type TypeMaybeBigInt = 0x20;
- static const Type TypeMaybeOther = 0x40;
+ static constexpr Type TypeInt32 = 1;
+ static constexpr Type TypeMaybeNumber = 0x02;
+ static constexpr Type TypeMaybeString = 0x04;
+ static constexpr Type TypeMaybeNull = 0x08;
+ static constexpr Type TypeMaybeBool = 0x10;
+ static constexpr Type TypeMaybeBigInt = 0x20;
+ static constexpr Type TypeMaybeOther = 0x40;
- static const Type TypeBits = TypeMaybeNumber | TypeMaybeString | TypeMaybeNull | TypeMaybeBool | TypeMaybeBigInt | TypeMaybeOther;
+ static constexpr Type TypeBits = TypeMaybeNumber | TypeMaybeString | TypeMaybeNull | TypeMaybeBool | TypeMaybeBigInt | TypeMaybeOther;
public:
- static const int numBitsNeeded = 7;
+ static constexpr int numBitsNeeded = 7;
static_assert((TypeBits & ((1 << numBitsNeeded) - 1)) == TypeBits, "This is necessary for correctness.");
- explicit ResultType(Type type)
+ constexpr explicit ResultType(Type type)
: m_bits(type)
{
}
- bool isInt32() const
+ constexpr bool isInt32() const
{
return m_bits & TypeInt32;
}
- bool definitelyIsNumber() const
+ constexpr bool definitelyIsNumber() const
{
return (m_bits & TypeBits) == TypeMaybeNumber;
}
- bool definitelyIsString() const
+ constexpr bool definitelyIsString() const
{
return (m_bits & TypeBits) == TypeMaybeString;
}
- bool definitelyIsBoolean() const
+ constexpr bool definitelyIsBoolean() const
{
return (m_bits & TypeBits) == TypeMaybeBool;
}
- bool definitelyIsBigInt() const
+ constexpr bool definitelyIsBigInt() const
{
return (m_bits & TypeBits) == TypeMaybeBigInt;
}
- bool mightBeNumber() const
+ constexpr bool mightBeNumber() const
{
return m_bits & TypeMaybeNumber;
}
- bool isNotNumber() const
+ constexpr bool isNotNumber() const
{
return !mightBeNumber();
}
- bool mightBeBigInt() const
+ constexpr bool mightBeBigInt() const
{
return m_bits & TypeMaybeBigInt;
}
- bool isNotBigInt() const
+ constexpr bool isNotBigInt() const
{
return !mightBeBigInt();
}
- static ResultType nullType()
+ static constexpr ResultType nullType()
{
return ResultType(TypeMaybeNull);
}
- static ResultType booleanType()
+ static constexpr ResultType booleanType()
{
return ResultType(TypeMaybeBool);
}
- static ResultType numberType()
+ static constexpr ResultType numberType()
{
return ResultType(TypeMaybeNumber);
}
- static ResultType numberTypeIsInt32()
+ static constexpr ResultType numberTypeIsInt32()
{
return ResultType(TypeInt32 | TypeMaybeNumber);
}
- static ResultType stringOrNumberType()
+ static constexpr ResultType stringOrNumberType()
{
return ResultType(TypeMaybeNumber | TypeMaybeString);
}
- static ResultType addResultType()
+ static constexpr ResultType addResultType()
{
return ResultType(TypeMaybeNumber | TypeMaybeString | TypeMaybeBigInt);
}
- static ResultType stringType()
+ static constexpr ResultType stringType()
{
return ResultType(TypeMaybeString);
}
- static ResultType bigIntType()
+ static constexpr ResultType bigIntType()
{
return ResultType(TypeMaybeBigInt);
}
- static ResultType unknownType()
+ static constexpr ResultType unknownType()
{
return ResultType(TypeBits);
}
- static ResultType forAdd(ResultType op1, ResultType op2)
+ static constexpr ResultType forAdd(ResultType op1, ResultType op2)
{
if (op1.definitelyIsNumber() && op2.definitelyIsNumber())
return numberType();
@@ -154,7 +154,7 @@
// Unlike in C, a logical op produces the value of the
// last expression evaluated (and not true or false).
- static ResultType forLogicalOp(ResultType op1, ResultType op2)
+ static constexpr ResultType forLogicalOp(ResultType op1, ResultType op2)
{
if (op1.definitelyIsBoolean() && op2.definitelyIsBoolean())
return booleanType();
@@ -167,12 +167,12 @@
return unknownType();
}
- static ResultType forBitOp()
+ static constexpr ResultType forBitOp()
{
return numberTypeIsInt32();
}
- Type bits() const { return m_bits; }
+ constexpr Type bits() const { return m_bits; }
private:
Type m_bits;
diff --git a/Source/JavaScriptCore/runtime/JSCJSValue.h b/Source/JavaScriptCore/runtime/JSCJSValue.h
index 7c7e8c3..90d8f9f 100644
--- a/Source/JavaScriptCore/runtime/JSCJSValue.h
+++ b/Source/JavaScriptCore/runtime/JSCJSValue.h
@@ -108,8 +108,8 @@
#endif
};
-#define TagOffset (OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag))
-#define PayloadOffset (OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload))
+#define TagOffset (offsetof(EncodedValueDescriptor, asBits.tag))
+#define PayloadOffset (offsetof(EncodedValueDescriptor, asBits.payload))
#if USE(JSVALUE64)
#define CellPayloadOffset 0