Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (128789 => 128790)
--- trunk/Source/_javascript_Core/ChangeLog 2012-09-17 19:03:38 UTC (rev 128789)
+++ trunk/Source/_javascript_Core/ChangeLog 2012-09-17 19:07:32 UTC (rev 128790)
@@ -1,3 +1,52 @@
+2012-09-17 Filip Pizlo <[email protected]>
+
+ Array profiling has convergence issues
+ https://bugs.webkit.org/show_bug.cgi?id=96891
+
+ Reviewed by Gavin Barraclough.
+
+ Now each array profiling site merges in the indexing type it observed into
+ the m_observedArrayModes bitset. The ArrayProfile also uses this to detect
+ cases where the structure must have gone polymorphic (if the bitset is
+ polymorphic then the structure must be). This achieves something like the
+ best of both worlds: on the one hand, we get a probabilistic structure that
+ we can use to optimize the monomorphic structure case, but on the other hand,
+ we get an accurate view of the set of types that were encountered.
+
+ * assembler/MacroAssemblerARMv7.h:
+ (JSC::MacroAssemblerARMv7::or32):
+ (MacroAssemblerARMv7):
+ * assembler/MacroAssemblerX86.h:
+ (JSC::MacroAssemblerX86::or32):
+ (MacroAssemblerX86):
+ * assembler/MacroAssemblerX86_64.h:
+ (JSC::MacroAssemblerX86_64::or32):
+ (MacroAssemblerX86_64):
+ * assembler/X86Assembler.h:
+ (X86Assembler):
+ (JSC::X86Assembler::orl_rm):
+ * bytecode/ArrayProfile.cpp:
+ (JSC::ArrayProfile::computeUpdatedPrediction):
+ * bytecode/ArrayProfile.h:
+ (JSC::ArrayProfile::addressOfArrayModes):
+ (JSC::ArrayProfile::structureIsPolymorphic):
+ * jit/JIT.h:
+ (JIT):
+ * jit/JITInlineMethods.h:
+ (JSC):
+ (JSC::JIT::emitArrayProfilingSite):
+ * jit/JITPropertyAccess.cpp:
+ (JSC::JIT::emit_op_get_by_val):
+ (JSC::JIT::emit_op_put_by_val):
+ (JSC::JIT::privateCompilePatchGetArrayLength):
+ * jit/JITPropertyAccess32_64.cpp:
+ (JSC::JIT::emit_op_get_by_val):
+ (JSC::JIT::emit_op_put_by_val):
+ (JSC::JIT::privateCompilePatchGetArrayLength):
+ * llint/LowLevelInterpreter.asm:
+ * llint/LowLevelInterpreter32_64.asm:
+ * llint/LowLevelInterpreter64.asm:
+
2012-09-17 Mark Lam <[email protected]>
Not reviewed. Added svn:eol-style native to unbreak some build bots.
Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerARMv7.h (128789 => 128790)
--- trunk/Source/_javascript_Core/assembler/MacroAssemblerARMv7.h 2012-09-17 19:03:38 UTC (rev 128789)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerARMv7.h 2012-09-17 19:07:32 UTC (rev 128790)
@@ -313,6 +313,14 @@
{
m_assembler.orr(dest, dest, src);
}
+
+ void or32(RegisterID src, AbsoluteAddress dest)
+ {
+ move(TrustedImmPtr(dest.m_ptr), addressTempRegister);
+ load32(addressTempRegister, dataTempRegister);
+ or32(src, dataTempRegister);
+ store32(dataTempRegister, addressTempRegister);
+ }
void or32(TrustedImm32 imm, RegisterID dest)
{
Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerX86.h (128789 => 128790)
--- trunk/Source/_javascript_Core/assembler/MacroAssemblerX86.h 2012-09-17 19:03:38 UTC (rev 128789)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerX86.h 2012-09-17 19:07:32 UTC (rev 128790)
@@ -84,6 +84,11 @@
m_assembler.orl_im(imm.m_value, address.m_ptr);
}
+ void or32(RegisterID reg, AbsoluteAddress address)
+ {
+ m_assembler.orl_rm(reg, address.m_ptr);
+ }
+
void sub32(TrustedImm32 imm, AbsoluteAddress address)
{
m_assembler.subl_im(imm.m_value, address.m_ptr);
Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerX86_64.h (128789 => 128790)
--- trunk/Source/_javascript_Core/assembler/MacroAssemblerX86_64.h 2012-09-17 19:03:38 UTC (rev 128789)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerX86_64.h 2012-09-17 19:07:32 UTC (rev 128790)
@@ -75,6 +75,12 @@
or32(imm, Address(scratchRegister));
}
+ void or32(RegisterID reg, AbsoluteAddress address)
+ {
+ move(TrustedImmPtr(address.m_ptr), scratchRegister);
+ or32(reg, Address(scratchRegister));
+ }
+
void sub32(TrustedImm32 imm, AbsoluteAddress address)
{
move(TrustedImmPtr(address.m_ptr), scratchRegister);
Modified: trunk/Source/_javascript_Core/assembler/X86Assembler.h (128789 => 128790)
--- trunk/Source/_javascript_Core/assembler/X86Assembler.h 2012-09-17 19:03:38 UTC (rev 128789)
+++ trunk/Source/_javascript_Core/assembler/X86Assembler.h 2012-09-17 19:07:32 UTC (rev 128790)
@@ -541,6 +541,11 @@
m_formatter.immediate32(imm);
}
}
+
+ void orl_rm(RegisterID src, const void* addr)
+ {
+ m_formatter.oneByteOp(OP_OR_EvGv, src, addr);
+ }
#endif
void subl_rr(RegisterID src, RegisterID dst)
Modified: trunk/Source/_javascript_Core/bytecode/ArrayProfile.cpp (128789 => 128790)
--- trunk/Source/_javascript_Core/bytecode/ArrayProfile.cpp 2012-09-17 19:03:38 UTC (rev 128789)
+++ trunk/Source/_javascript_Core/bytecode/ArrayProfile.cpp 2012-09-17 19:07:32 UTC (rev 128790)
@@ -43,6 +43,11 @@
m_lastSeenStructure = 0;
}
+ if (hasTwoOrMoreBitsSet(m_observedArrayModes)) {
+ m_structureIsPolymorphic = true;
+ m_expectedStructure = 0;
+ }
+
if (operation == Collection
&& m_expectedStructure
&& !Heap::isMarked(m_expectedStructure)) {
Modified: trunk/Source/_javascript_Core/bytecode/ArrayProfile.h (128789 => 128790)
--- trunk/Source/_javascript_Core/bytecode/ArrayProfile.h 2012-09-17 19:03:38 UTC (rev 128789)
+++ trunk/Source/_javascript_Core/bytecode/ArrayProfile.h 2012-09-17 19:07:32 UTC (rev 128790)
@@ -70,6 +70,7 @@
unsigned bytecodeOffset() const { return m_bytecodeOffset; }
Structure** addressOfLastSeenStructure() { return &m_lastSeenStructure; }
+ ArrayModes* addressOfArrayModes() { return &m_observedArrayModes; }
void observeStructure(Structure* structure)
{
@@ -79,7 +80,10 @@
void computeUpdatedPrediction(OperationInProgress operation = NoOperation);
Structure* expectedStructure() const { return m_expectedStructure; }
- bool structureIsPolymorphic() const { return m_structureIsPolymorphic; }
+ bool structureIsPolymorphic() const
+ {
+ return m_structureIsPolymorphic;
+ }
bool hasDefiniteStructure() const
{
return !structureIsPolymorphic() && m_expectedStructure;
Modified: trunk/Source/_javascript_Core/jit/JIT.h (128789 => 128790)
--- trunk/Source/_javascript_Core/jit/JIT.h 2012-09-17 19:03:38 UTC (rev 128789)
+++ trunk/Source/_javascript_Core/jit/JIT.h 2012-09-17 19:07:32 UTC (rev 128790)
@@ -449,6 +449,8 @@
void emitValueProfilingSite(unsigned) { }
void emitValueProfilingSite() { }
#endif
+ void emitArrayProfilingSite(RegisterID structureAndIndexingType, RegisterID scratch, ArrayProfile*);
+ void emitArrayProfilingSiteForBytecodeIndex(RegisterID structureAndIndexingType, RegisterID scratch, unsigned bytecodeIndex);
enum FinalObjectMode { MayBeFinal, KnownNotFinal };
Modified: trunk/Source/_javascript_Core/jit/JITInlineMethods.h (128789 => 128790)
--- trunk/Source/_javascript_Core/jit/JITInlineMethods.h 2012-09-17 19:03:38 UTC (rev 128789)
+++ trunk/Source/_javascript_Core/jit/JITInlineMethods.h 2012-09-17 19:07:32 UTC (rev 128790)
@@ -529,7 +529,31 @@
{
emitValueProfilingSite(m_bytecodeOffset);
}
+#endif // ENABLE(VALUE_PROFILER)
+
+inline void JIT::emitArrayProfilingSite(RegisterID structureAndIndexingType, RegisterID scratch, ArrayProfile* arrayProfile)
+{
+ RegisterID structure = structureAndIndexingType;
+ RegisterID indexingType = structureAndIndexingType;
+
+ if (canBeOptimized()) {
+ storePtr(structure, arrayProfile->addressOfLastSeenStructure());
+ load8(Address(structure, Structure::indexingTypeOffset()), indexingType);
+ move(TrustedImm32(1), scratch);
+ lshift32(indexingType, scratch);
+ or32(scratch, AbsoluteAddress(arrayProfile->addressOfArrayModes()));
+ } else
+ load8(Address(structure, Structure::indexingTypeOffset()), indexingType);
+}
+
+inline void JIT::emitArrayProfilingSiteForBytecodeIndex(RegisterID structureAndIndexingType, RegisterID scratch, unsigned bytecodeIndex)
+{
+#if ENABLE(VALUE_PROFILER)
+ emitArrayProfilingSite(structureAndIndexingType, scratch, m_codeBlock->getOrAddArrayProfile(bytecodeIndex));
+#else
+ emitArrayProfilingSite(structureAndIndexingType, scratch, 0);
#endif
+}
#if USE(JSVALUE32_64)
Modified: trunk/Source/_javascript_Core/jit/JITPropertyAccess.cpp (128789 => 128790)
--- trunk/Source/_javascript_Core/jit/JITPropertyAccess.cpp 2012-09-17 19:03:38 UTC (rev 128789)
+++ trunk/Source/_javascript_Core/jit/JITPropertyAccess.cpp 2012-09-17 19:07:32 UTC (rev 128790)
@@ -111,10 +111,8 @@
emitJumpSlowCaseIfNotJSCell(regT0, base);
loadPtr(Address(regT0, JSCell::structureOffset()), regT2);
-#if ENABLE(VALUE_PROFILER)
- storePtr(regT2, currentInstruction[4].u.arrayProfile->addressOfLastSeenStructure());
-#endif
- addSlowCase(branchTest8(Zero, Address(regT2, Structure::indexingTypeOffset()), TrustedImm32(HasArrayStorage)));
+ emitArrayProfilingSite(regT2, regT3, currentInstruction[4].u.arrayProfile);
+ addSlowCase(branchTest32(Zero, regT2, TrustedImm32(HasArrayStorage)));
loadPtr(Address(regT0, JSObject::butterflyOffset()), regT2);
addSlowCase(branch32(AboveOrEqual, regT1, Address(regT2, ArrayStorage::vectorLengthOffset())));
@@ -236,10 +234,8 @@
zeroExtend32ToPtr(regT1, regT1);
emitJumpSlowCaseIfNotJSCell(regT0, base);
loadPtr(Address(regT0, JSCell::structureOffset()), regT2);
-#if ENABLE(VALUE_PROFILER)
- storePtr(regT2, currentInstruction[4].u.arrayProfile->addressOfLastSeenStructure());
-#endif
- addSlowCase(branchTest8(Zero, Address(regT2, Structure::indexingTypeOffset()), TrustedImm32(HasArrayStorage)));
+ emitArrayProfilingSite(regT2, regT3, currentInstruction[4].u.arrayProfile);
+ addSlowCase(branchTest32(Zero, regT2, TrustedImm32(HasArrayStorage)));
loadPtr(Address(regT0, JSObject::butterflyOffset()), regT2);
addSlowCase(branch32(AboveOrEqual, regT1, Address(regT2, ArrayStorage::vectorLengthOffset())));
@@ -656,13 +652,10 @@
StructureStubInfo* stubInfo = &m_codeBlock->getStubInfo(returnAddress);
// Check eax is an array
- loadPtr(Address(regT0, JSCell::structureOffset()), regT3);
-#if ENABLE(VALUE_PROFILER)
- storePtr(regT3, m_codeBlock->getOrAddArrayProfile(stubInfo->bytecodeIndex)->addressOfLastSeenStructure());
-#endif
- load8(Address(regT3, Structure::indexingTypeOffset()), regT3);
- Jump failureCases1 = branchTest32(Zero, regT3, TrustedImm32(IsArray));
- Jump failureCases2 = branchTest32(Zero, regT3, TrustedImm32(HasArrayStorage));
+ loadPtr(Address(regT0, JSCell::structureOffset()), regT2);
+ emitArrayProfilingSiteForBytecodeIndex(regT2, regT1, stubInfo->bytecodeIndex);
+ Jump failureCases1 = branchTest32(Zero, regT2, TrustedImm32(IsArray));
+ Jump failureCases2 = branchTest32(Zero, regT2, TrustedImm32(HasArrayStorage));
// Checks out okay! - get the length from the storage
loadPtr(Address(regT0, JSObject::butterflyOffset()), regT3);
Modified: trunk/Source/_javascript_Core/jit/JITPropertyAccess32_64.cpp (128789 => 128790)
--- trunk/Source/_javascript_Core/jit/JITPropertyAccess32_64.cpp 2012-09-17 19:03:38 UTC (rev 128789)
+++ trunk/Source/_javascript_Core/jit/JITPropertyAccess32_64.cpp 2012-09-17 19:07:32 UTC (rev 128790)
@@ -210,10 +210,8 @@
addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
emitJumpSlowCaseIfNotJSCell(base, regT1);
loadPtr(Address(regT0, JSCell::structureOffset()), regT1);
-#if ENABLE(VALUE_PROFILER)
- storePtr(regT1, currentInstruction[4].u.arrayProfile->addressOfLastSeenStructure());
-#endif
- addSlowCase(branchTest8(Zero, Address(regT1, Structure::indexingTypeOffset()), TrustedImm32(HasArrayStorage)));
+ emitArrayProfilingSite(regT1, regT3, currentInstruction[4].u.arrayProfile);
+ addSlowCase(branchTest32(Zero, regT1, TrustedImm32(HasArrayStorage)));
loadPtr(Address(regT0, JSObject::butterflyOffset()), regT3);
addSlowCase(branch32(AboveOrEqual, regT2, Address(regT3, ArrayStorage::vectorLengthOffset())));
@@ -269,10 +267,8 @@
addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
emitJumpSlowCaseIfNotJSCell(base, regT1);
loadPtr(Address(regT0, JSCell::structureOffset()), regT1);
-#if ENABLE(VALUE_PROFILER)
- storePtr(regT1, currentInstruction[4].u.arrayProfile->addressOfLastSeenStructure());
-#endif
- addSlowCase(branchTest8(Zero, Address(regT1, Structure::indexingTypeOffset()), TrustedImm32(HasArrayStorage)));
+ emitArrayProfilingSite(regT1, regT3, currentInstruction[4].u.arrayProfile);
+ addSlowCase(branchTest32(Zero, regT1, TrustedImm32(HasArrayStorage)));
loadPtr(Address(regT0, JSObject::butterflyOffset()), regT3);
addSlowCase(branch32(AboveOrEqual, regT2, Address(regT3, ArrayStorage::vectorLengthOffset())));
@@ -617,10 +613,7 @@
// Check for array
loadPtr(Address(regT0, JSCell::structureOffset()), regT2);
-#if ENABLE(VALUE_PROFILER)
- storePtr(regT2, m_codeBlock->getOrAddArrayProfile(stubInfo->bytecodeIndex)->addressOfLastSeenStructure());
-#endif
- load8(Address(regT2, Structure::indexingTypeOffset()), regT3);
+ emitArrayProfilingSiteForBytecodeIndex(regT2, regT3, stubInfo->bytecodeIndex);
Jump failureCases1 = branchTest32(Zero, regT2, TrustedImm32(IsArray));
Jump failureCases2 = branchTest32(Zero, regT2, TrustedImm32(HasArrayStorage));
Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm (128789 => 128790)
--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm 2012-09-17 19:03:38 UTC (rev 128789)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter.asm 2012-09-17 19:07:32 UTC (rev 128790)
@@ -187,6 +187,20 @@
end)
end
+macro arrayProfile(structureAndIndexingType, profile, scratch)
+ const structure = structureAndIndexingType
+ const indexingType = structureAndIndexingType
+ if VALUE_PROFILER
+ storep structure, ArrayProfile::m_lastSeenStructure[profile]
+ loadb Structure::m_indexingType[structure], indexingType
+ move 1, scratch
+ lshifti indexingType, scratch
+ ori scratch, ArrayProfile::m_observedArrayModes[profile]
+ else
+ loadb Structure::m_indexingType[structure], indexingType
+ end
+end
+
macro checkSwitchToJIT(increment, action)
if JIT_ENABLED
loadp CodeBlock[cfr], t0
Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm (128789 => 128790)
--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm 2012-09-17 19:03:38 UTC (rev 128789)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter32_64.asm 2012-09-17 19:07:32 UTC (rev 128790)
@@ -1176,12 +1176,9 @@
loadp 16[PC], t1
loadConstantOrVariablePayload(t0, CellTag, t3, .opGetArrayLengthSlow)
loadp JSCell::m_structure[t3], t2
- if VALUE_PROFILER
- storep t2, ArrayProfile::m_lastSeenStructure[t1]
- end
- loadb Structure::m_indexingType[t2], t1
- btiz t1, IsArray, .opGetArrayLengthSlow
- btiz t1, HasArrayStorage, .opGetArrayLengthSlow
+ arrayProfile(t2, t1, t0)
+ btiz t2, IsArray, .opGetArrayLengthSlow
+ btiz t2, HasArrayStorage, .opGetArrayLengthSlow
loadi 4[PC], t1
loadp 32[PC], t2
loadp JSObject::m_butterfly[t3], t0
@@ -1308,15 +1305,13 @@
_llint_op_get_by_val:
traceExecution()
loadi 8[PC], t2
- loadi 12[PC], t3
loadConstantOrVariablePayload(t2, CellTag, t0, .opGetByValSlow)
+ loadp JSCell::m_structure[t0], t2
+ loadp 16[PC], t3
+ arrayProfile(t2, t3, t1)
+ btiz t2, HasArrayStorage, .opGetByValSlow
+ loadi 12[PC], t3
loadConstantOrVariablePayload(t3, Int32Tag, t1, .opGetByValSlow)
- loadp JSCell::m_structure[t0], t3
- loadp 16[PC], t2
- if VALUE_PROFILER
- storep t3, ArrayProfile::m_lastSeenStructure[t2]
- end
- btpz Structure::m_indexingType[t3], HasArrayStorage, .opGetByValSlow
loadp JSObject::m_butterfly[t0], t3
biaeq t1, -sizeof IndexingHeader + IndexingHeader::m_vectorLength[t0], .opGetByValSlow
loadi 4[PC], t0
@@ -1392,14 +1387,12 @@
traceExecution()
loadi 4[PC], t0
loadConstantOrVariablePayload(t0, CellTag, t1, .opPutByValSlow)
+ loadp JSCell::m_structure[t1], t2
+ loadp 16[PC], t0
+ arrayProfile(t2, t0, t3)
+ btiz t2, HasArrayStorage, .opPutByValSlow
loadi 8[PC], t0
loadConstantOrVariablePayload(t0, Int32Tag, t2, .opPutByValSlow)
- loadp JSCell::m_structure[t1], t3
- loadp 16[PC], t0
- if VALUE_PROFILER
- storep t3, ArrayProfile::m_lastSeenStructure[t0]
- end
- btpz Structure::m_indexingType[t3], HasArrayStorage, .opPutByValSlow
loadp JSObject::m_butterfly[t1], t0
biaeq t2, -sizeof IndexingHeader + IndexingHeader::m_vectorLength[t0], .opPutByValSlow
bieq ArrayStorage::m_vector + TagOffset[t0, t2, 8], EmptyValueTag, .opPutByValEmpty
Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm (128789 => 128790)
--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm 2012-09-17 19:03:38 UTC (rev 128789)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm 2012-09-17 19:07:32 UTC (rev 128790)
@@ -1023,12 +1023,9 @@
loadp 32[PB, PC, 8], t1
loadConstantOrVariableCell(t0, t3, .opGetArrayLengthSlow)
loadp JSCell::m_structure[t3], t2
- if VALUE_PROFILER
- storep t2, ArrayProfile::m_lastSeenStructure[t1]
- end
- loadb Structure::m_indexingType[t2], t1
- btiz t1, IsArray, .opGetArrayLengthSlow
- btiz t1, HasArrayStorage, .opGetArrayLengthSlow
+ arrayProfile(t2, t1, t0)
+ btiz t2, IsArray, .opGetArrayLengthSlow
+ btiz t2, HasArrayStorage, .opGetArrayLengthSlow
loadis 8[PB, PC, 8], t1
loadp 64[PB, PC, 8], t2
loadp JSObject::m_butterfly[t3], t0
@@ -1152,16 +1149,14 @@
_llint_op_get_by_val:
traceExecution()
loadis 16[PB, PC, 8], t2
- loadis 24[PB, PC, 8], t3
loadConstantOrVariableCell(t2, t0, .opGetByValSlow)
+ loadp JSCell::m_structure[t0], t2
+ loadp 32[PB, PC, 8], t3
+ arrayProfile(t2, t3, t1)
+ loadis 24[PB, PC, 8], t3
+ btiz t2, HasArrayStorage, .opGetByValSlow
loadConstantOrVariableInt32(t3, t1, .opGetByValSlow)
sxi2p t1, t1
- loadp JSCell::m_structure[t0], t3
- loadp 32[PB, PC, 8], t2
- if VALUE_PROFILER
- storep t3, ArrayProfile::m_lastSeenStructure[t2]
- end
- btbz Structure::m_indexingType[t3], HasArrayStorage, .opGetByValSlow
loadp JSObject::m_butterfly[t0], t3
biaeq t1, -sizeof IndexingHeader + IndexingHeader::m_vectorLength[t3], .opGetByValSlow
loadis 8[PB, PC, 8], t0
@@ -1235,15 +1230,13 @@
traceExecution()
loadis 8[PB, PC, 8], t0
loadConstantOrVariableCell(t0, t1, .opPutByValSlow)
+ loadp JSCell::m_structure[t1], t2
+ loadp 32[PB, PC, 8], t0
+ arrayProfile(t2, t0, t3)
+ btiz t2, HasArrayStorage, .opPutByValSlow
loadis 16[PB, PC, 8], t0
loadConstantOrVariableInt32(t0, t2, .opPutByValSlow)
sxi2p t2, t2
- loadp JSCell::m_structure[t1], t3
- loadp 32[PB, PC, 8], t0
- if VALUE_PROFILER
- storep t3, ArrayProfile::m_lastSeenStructure[t0]
- end
- btbz Structure::m_indexingType[t3], HasArrayStorage, .opPutByValSlow
loadp JSObject::m_butterfly[t1], t0
biaeq t2, -sizeof IndexingHeader + IndexingHeader::m_vectorLength[t0], .opPutByValSlow
btpz ArrayStorage::m_vector[t0, t2, 8], .opPutByValEmpty
Modified: trunk/Source/WTF/ChangeLog (128789 => 128790)
--- trunk/Source/WTF/ChangeLog 2012-09-17 19:03:38 UTC (rev 128789)
+++ trunk/Source/WTF/ChangeLog 2012-09-17 19:07:32 UTC (rev 128790)
@@ -1,3 +1,16 @@
+2012-09-17 Filip Pizlo <[email protected]>
+
+ Array profiling has convergence issues
+ https://bugs.webkit.org/show_bug.cgi?id=96891
+
+ Reviewed by Gavin Barraclough.
+
+ Added functions for testing if something is a power of 2.
+
+ * wtf/MathExtras.h:
+ (hasZeroOrOneBitsSet):
+ (hasTwoOrMoreBitsSet):
+
2012-09-17 Ilya Tikhonovsky <[email protected]>
Web Inspector: NMI: now when we can detect instrumented classes we can
Modified: trunk/Source/WTF/wtf/MathExtras.h (128789 => 128790)
--- trunk/Source/WTF/wtf/MathExtras.h 2012-09-17 19:03:38 UTC (rev 128789)
+++ trunk/Source/WTF/wtf/MathExtras.h 2012-09-17 19:07:32 UTC (rev 128790)
@@ -294,6 +294,16 @@
return x > static_cast<float>(std::numeric_limits<int>::min()) && x < static_cast<float>(std::numeric_limits<int>::max());
}
+template<typename T> inline bool hasZeroOrOneBitsSet(T value)
+{
+ return !((value - 1) & value);
+}
+
+template<typename T> inline bool hasTwoOrMoreBitsSet(T value)
+{
+ return !hasZeroOrOneBitsSet(value);
+}
+
#if !COMPILER(MSVC) && !COMPILER(RVCT) && !OS(SOLARIS)
using std::isfinite;
#if !COMPILER_QUIRK(GCC11_GLOBAL_ISINF_ISNAN)