Fix value profiling in 32_64 JIT
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 9 Oct 2011 10:19:23 +0000 (10:19 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 9 Oct 2011 10:19:23 +0000 (10:19 +0000)
https://bugs.webkit.org/show_bug.cgi?id=69717

Patch by Yuqiang Xian <yuqiang.xian@intel.com> on 2011-10-09
Reviewed by Filip Pizlo.

Current value profiling for 32_64 JIT is broken and cannot record
correct predicated types, which results in many speculation failures
in the 32_64 DFG JIT, fallbacks to baseline JIT, and re-optimizations
again and again.
With this fix 32_64 DFG JIT can demonstrate real performance gains.

* bytecode/ValueProfile.cpp:
(JSC::ValueProfile::computeStatistics):
* bytecode/ValueProfile.h:
(JSC::ValueProfile::classInfo):
(JSC::ValueProfile::numberOfSamples):
(JSC::ValueProfile::isLive):
(JSC::ValueProfile::numberOfInt32s):
(JSC::ValueProfile::numberOfDoubles):
(JSC::ValueProfile::numberOfBooleans):
(JSC::ValueProfile::dump):
    Empty value check should be performed on decoded JSValue,
    as for 32_64 empty value is not identical to encoded 0.
* jit/JIT.cpp:
(JSC::JIT::privateCompile):
* jit/JITInlineMethods.h:
(JSC::JIT::emitValueProfilingSite):
* jit/JITStubCall.h:
(JSC::JITStubCall::callWithValueProfiling):
    Record the right profiling result for 32_64.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@97025 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/bytecode/ValueProfile.cpp
Source/JavaScriptCore/bytecode/ValueProfile.h
Source/JavaScriptCore/jit/JIT.cpp
Source/JavaScriptCore/jit/JITInlineMethods.h
Source/JavaScriptCore/jit/JITStubCall.h

index 8dff99e..5ae6c6a 100644 (file)
@@ -1,5 +1,38 @@
 2011-10-09  Yuqiang Xian  <yuqiang.xian@intel.com>
 
+        Fix value profiling in 32_64 JIT
+        https://bugs.webkit.org/show_bug.cgi?id=69717
+
+        Reviewed by Filip Pizlo.
+
+        Current value profiling for 32_64 JIT is broken and cannot record
+        correct predicated types, which results in many speculation failures
+        in the 32_64 DFG JIT, fallbacks to baseline JIT, and re-optimizations
+        again and again. 
+        With this fix 32_64 DFG JIT can demonstrate real performance gains.
+
+        * bytecode/ValueProfile.cpp:
+        (JSC::ValueProfile::computeStatistics):
+        * bytecode/ValueProfile.h:
+        (JSC::ValueProfile::classInfo):
+        (JSC::ValueProfile::numberOfSamples):
+        (JSC::ValueProfile::isLive):
+        (JSC::ValueProfile::numberOfInt32s):
+        (JSC::ValueProfile::numberOfDoubles):
+        (JSC::ValueProfile::numberOfBooleans):
+        (JSC::ValueProfile::dump):
+            Empty value check should be performed on decoded JSValue,
+            as for 32_64 empty value is not identical to encoded 0.
+        * jit/JIT.cpp:
+        (JSC::JIT::privateCompile):
+        * jit/JITInlineMethods.h:
+        (JSC::JIT::emitValueProfilingSite):
+        * jit/JITStubCall.h:
+        (JSC::JITStubCall::callWithValueProfiling):
+            Record the right profiling result for 32_64.
+
+2011-10-09  Yuqiang Xian  <yuqiang.xian@intel.com>
+
         Remove 32 bit restrictions in DFG JIT
         https://bugs.webkit.org/show_bug.cgi?id=69711
 
index 6dad6ef..3bd7b83 100644 (file)
@@ -60,7 +60,8 @@ void ValueProfile::computeStatistics(const ClassInfo* classInfo, Statistics& sta
 void ValueProfile::computeStatistics(Statistics& statistics) const
 {
     for (unsigned i = 0; i < numberOfBuckets; ++i) {
-        if (!m_buckets[i]) {
+        JSValue value = JSValue::decode(m_buckets[i]);
+        if (!value) {
             WeakBucket weakBucket = m_weakBuckets[i];
             if (!!weakBucket) {
                 statistics.samples++;
@@ -72,7 +73,6 @@ void ValueProfile::computeStatistics(Statistics& statistics) const
         
         statistics.samples++;
         
-        JSValue value = JSValue::decode(m_buckets[i]);
         if (value.isInt32())
             statistics.int32s++;
         else if (value.isDouble())
index 201f00a..a1e85ee 100644 (file)
@@ -55,8 +55,8 @@ struct ValueProfile {
     
     const ClassInfo* classInfo(unsigned bucket) const
     {
-        if (!!m_buckets[bucket]) {
-            JSValue value = JSValue::decode(m_buckets[bucket]);
+        JSValue value = JSValue::decode(m_buckets[bucket]);
+        if (!!value) {
             if (!value.isCell())
                 return 0;
             return value.asCell()->structure()->classInfo();
@@ -68,7 +68,7 @@ struct ValueProfile {
     {
         unsigned result = 0;
         for (unsigned i = 0; i < numberOfBuckets; ++i) {
-            if (!!m_buckets[i] || !!m_weakBuckets[i])
+            if (!!JSValue::decode(m_buckets[i]) || !!m_weakBuckets[i])
                 result++;
         }
         return result;
@@ -82,7 +82,7 @@ struct ValueProfile {
     bool isLive() const
     {
         for (unsigned i = 0; i < numberOfBuckets; ++i) {
-            if (!!m_buckets[i] || !!m_weakBuckets[i])
+            if (!!JSValue::decode(m_buckets[i]) || !!m_weakBuckets[i])
                 return true;
         }
         return false;
@@ -99,7 +99,7 @@ struct ValueProfile {
     {
         unsigned result = 0;
         for (unsigned i = 0; i < numberOfBuckets; ++i) {
-            if (!!m_buckets[i] && JSValue::decode(m_buckets[i]).isInt32())
+            if (JSValue::decode(m_buckets[i]).isInt32())
                 result++;
         }
         return result;
@@ -109,7 +109,7 @@ struct ValueProfile {
     {
         unsigned result = 0;
         for (unsigned i = 0; i < numberOfBuckets; ++i) {
-            if (!!m_buckets[i] && JSValue::decode(m_buckets[i]).isDouble())
+            if (JSValue::decode(m_buckets[i]).isDouble())
                 result++;
         }
         return result;
@@ -170,7 +170,7 @@ struct ValueProfile {
     {
         unsigned result = 0;
         for (unsigned i = 0; i < numberOfBuckets; ++i) {
-            if (!!m_buckets[i] && JSValue::decode(m_buckets[i]).isBoolean())
+            if (JSValue::decode(m_buckets[i]).isBoolean())
                 result++;
         }
         return result;
@@ -238,7 +238,8 @@ struct ValueProfile {
                 predictionToString(m_prediction), m_numberOfSamplesInPrediction);
         bool first = true;
         for (unsigned i = 0; i < numberOfBuckets; ++i) {
-            if (!!m_buckets[i] || !!m_weakBuckets[i]) {
+            JSValue value = JSValue::decode(m_buckets[i]);
+            if (!!value || !!m_weakBuckets[i]) {
                 if (first) {
                     fprintf(out, ": ");
                     first = false;
@@ -246,8 +247,8 @@ struct ValueProfile {
                     fprintf(out, ", ");
             }
             
-            if (!!m_buckets[i])
-                fprintf(out, "%s", JSValue::decode(m_buckets[i]).description());
+            if (!!value)
+                fprintf(out, "%s", value.description());
             
             if (!!m_weakBuckets[i])
                 fprintf(out, "DeadCell");
index 1086273..0f09a39 100644 (file)
@@ -573,7 +573,12 @@ JITCode JIT::privateCompile(CodePtr* functionEntryArityCheck)
                     && argumentRegister == -RegisterFile::CallFrameHeaderSize - m_codeBlock->m_numParameters)
                     m_codeBlock->addValueProfile(-1);
                 else {
+#if USE(JSVALUE64)
                     loadPtr(Address(callFrameRegister, argumentRegister * sizeof(Register)), regT0);
+#elif USE(JSVALUE32_64)
+                    load32(Address(callFrameRegister, argumentRegister * sizeof(Register) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT0);
+                    load32(Address(callFrameRegister, argumentRegister * sizeof(Register) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), regT1);
+#endif
                     emitValueProfilingSite(FirstProfilingSite);
                 }
             }
index bee36c4..c8a9c16 100644 (file)
@@ -471,7 +471,13 @@ inline void JIT::emitValueProfilingSite(ValueProfilingSiteKind siteKind)
         add32(Imm32(3), bucketCounterRegister);
     and32(Imm32(ValueProfile::bucketIndexMask), bucketCounterRegister);
     move(ImmPtr(valueProfile->m_buckets), scratch);
+#if USE(JSVALUE64)
     storePtr(value, BaseIndex(scratch, bucketCounterRegister, TimesEight));
+#elif USE(JSVALUE32_64)
+    const RegisterID valueTag = regT1;
+    store32(value, BaseIndex(scratch, bucketCounterRegister, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
+    store32(valueTag, BaseIndex(scratch, bucketCounterRegister, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
+#endif
 }
 #endif
 
index 71fbfe6..18441c3 100644 (file)
@@ -205,6 +205,9 @@ namespace JSC {
         {
             ASSERT(m_returnType == Value || m_returnType == Cell);
             JIT::Call call = this->call();
+            ASSERT(JIT::returnValueRegister == JIT::regT0);
+            if (m_returnType == Cell)
+                m_jit->move(JIT::TrustedImm32(JSValue::CellTag), JIT::regT1);
             m_jit->emitValueProfilingSite(kind);
             if (m_returnType == Value)
                 m_jit->emitStore(dst, JIT::regT1, JIT::regT0);