Title: [128790] trunk/Source
Revision
128790
Author
[email protected]
Date
2012-09-17 12:07:32 -0700 (Mon, 17 Sep 2012)

Log Message

Array profiling has convergence issues
https://bugs.webkit.org/show_bug.cgi?id=96891

Reviewed by Gavin Barraclough.

Source/_javascript_Core: 

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:

Source/WTF: 

Added functions for testing if something is a power of 2.

* wtf/MathExtras.h:
(hasZeroOrOneBitsSet):
(hasTwoOrMoreBitsSet):

Modified Paths

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)
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to