Title: [224938] trunk/Source/_javascript_Core
Revision
224938
Author
sbar...@apple.com
Date
2017-11-16 15:44:12 -0800 (Thu, 16 Nov 2017)

Log Message

Add some X86 intrinsics to $vm to help with some perf testing
https://bugs.webkit.org/show_bug.cgi?id=179693

Reviewed by Mark Lam.

I've been doing some local perf testing of various ideas and have
had these come in handy. I'm going to land them to dollarVM to prevent
having to add them to my local build every time I do perf testing.

* assembler/MacroAssemblerX86Common.h:
(JSC::MacroAssemblerX86Common::mfence):
(JSC::MacroAssemblerX86Common::rdtsc):
(JSC::MacroAssemblerX86Common::pause):
(JSC::MacroAssemblerX86Common::cpuid):
* assembler/X86Assembler.h:
(JSC::X86Assembler::rdtsc):
(JSC::X86Assembler::pause):
(JSC::X86Assembler::cpuid):
* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::handleIntrinsicCall):
* dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
* dfg/DFGDoesGC.cpp:
(JSC::DFG::doesGC):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* dfg/DFGGraph.cpp:
(JSC::DFG::Graph::dump):
* dfg/DFGNode.h:
(JSC::DFG::Node::intrinsic):
* dfg/DFGNodeType.h:
* dfg/DFGPredictionPropagationPhase.cpp:
* dfg/DFGSafeToExecute.h:
(JSC::DFG::safeToExecute):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGValidate.cpp:
* ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileNode):
(JSC::FTL::DFG::LowerDFGToB3::compileCPUIntrinsic):
* runtime/Intrinsic.cpp:
(JSC::intrinsicName):
* runtime/Intrinsic.h:
* tools/JSDollarVM.cpp:
(JSC::functionCpuMfence):
(JSC::functionCpuRdtsc):
(JSC::functionCpuCpuid):
(JSC::functionCpuPause):
(JSC::functionCpuClflush):
(JSC::JSDollarVM::finishCreation):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (224937 => 224938)


--- trunk/Source/_javascript_Core/ChangeLog	2017-11-16 23:27:59 UTC (rev 224937)
+++ trunk/Source/_javascript_Core/ChangeLog	2017-11-16 23:44:12 UTC (rev 224938)
@@ -1,3 +1,62 @@
+2017-11-16  Saam Barati  <sbar...@apple.com>
+
+        Add some X86 intrinsics to $vm to help with some perf testing
+        https://bugs.webkit.org/show_bug.cgi?id=179693
+
+        Reviewed by Mark Lam.
+
+        I've been doing some local perf testing of various ideas and have
+        had these come in handy. I'm going to land them to dollarVM to prevent
+        having to add them to my local build every time I do perf testing.
+
+        * assembler/MacroAssemblerX86Common.h:
+        (JSC::MacroAssemblerX86Common::mfence):
+        (JSC::MacroAssemblerX86Common::rdtsc):
+        (JSC::MacroAssemblerX86Common::pause):
+        (JSC::MacroAssemblerX86Common::cpuid):
+        * assembler/X86Assembler.h:
+        (JSC::X86Assembler::rdtsc):
+        (JSC::X86Assembler::pause):
+        (JSC::X86Assembler::cpuid):
+        * dfg/DFGAbstractInterpreterInlines.h:
+        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::handleIntrinsicCall):
+        * dfg/DFGClobberize.h:
+        (JSC::DFG::clobberize):
+        * dfg/DFGDoesGC.cpp:
+        (JSC::DFG::doesGC):
+        * dfg/DFGFixupPhase.cpp:
+        (JSC::DFG::FixupPhase::fixupNode):
+        * dfg/DFGGraph.cpp:
+        (JSC::DFG::Graph::dump):
+        * dfg/DFGNode.h:
+        (JSC::DFG::Node::intrinsic):
+        * dfg/DFGNodeType.h:
+        * dfg/DFGPredictionPropagationPhase.cpp:
+        * dfg/DFGSafeToExecute.h:
+        (JSC::DFG::safeToExecute):
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGValidate.cpp:
+        * ftl/FTLCapabilities.cpp:
+        (JSC::FTL::canCompile):
+        * ftl/FTLLowerDFGToB3.cpp:
+        (JSC::FTL::DFG::LowerDFGToB3::compileNode):
+        (JSC::FTL::DFG::LowerDFGToB3::compileCPUIntrinsic):
+        * runtime/Intrinsic.cpp:
+        (JSC::intrinsicName):
+        * runtime/Intrinsic.h:
+        * tools/JSDollarVM.cpp:
+        (JSC::functionCpuMfence):
+        (JSC::functionCpuRdtsc):
+        (JSC::functionCpuCpuid):
+        (JSC::functionCpuPause):
+        (JSC::functionCpuClflush):
+        (JSC::JSDollarVM::finishCreation):
+
 2017-11-16  JF Bastien  <jfbast...@apple.com>
 
         It should be easier to reify lazy property names

Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerX86Common.h (224937 => 224938)


--- trunk/Source/_javascript_Core/assembler/MacroAssemblerX86Common.h	2017-11-16 23:27:59 UTC (rev 224937)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerX86Common.h	2017-11-16 23:44:12 UTC (rev 224938)
@@ -3880,6 +3880,26 @@
         s_avxCheckState = (flags & (1 << 28)) ? CPUIDCheckState::Set : CPUIDCheckState::Clear;
     }
 
+    void mfence()
+    {
+        m_assembler.mfence();
+    }
+
+    void rdtsc()
+    {
+        m_assembler.rdtsc();
+    }
+
+    void pause()
+    {
+        m_assembler.pause();
+    }
+
+    void cpuid()
+    {
+        m_assembler.cpuid();
+    }
+
 protected:
     X86Assembler::Condition x86Condition(RelationalCondition cond)
     {

Modified: trunk/Source/_javascript_Core/assembler/X86Assembler.h (224937 => 224938)


--- trunk/Source/_javascript_Core/assembler/X86Assembler.h	2017-11-16 23:27:59 UTC (rev 224937)
+++ trunk/Source/_javascript_Core/assembler/X86Assembler.h	2017-11-16 23:44:12 UTC (rev 224938)
@@ -260,6 +260,7 @@
         OP_GROUP1A_Ev                   = 0x8F,
         OP_NOP                          = 0x90,
         OP_XCHG_EAX                     = 0x90,
+        OP_PAUSE                        = 0x90,
         OP_CDQ                          = 0x99,
         OP_MOV_EAXOv                    = 0xA1,
         OP_MOV_OvEAX                    = 0xA3,
@@ -300,6 +301,7 @@
         OP2_CVTTSD2SI_GdWsd = 0x2C,
         OP2_CVTTSS2SI_GdWsd = 0x2C,
         OP2_UCOMISD_VsdWsd  = 0x2E,
+        OP2_RDTSC           = 0x31,
         OP2_3BYTE_ESCAPE_3A = 0x3A,
         OP2_CMOVCC          = 0x40,
         OP2_ADDSD_VsdWsd    = 0x58,
@@ -318,6 +320,7 @@
         OP2_MOVD_EdVd       = 0x7E,
         OP2_JCC_rel32       = 0x80,
         OP_SETCC            = 0x90,
+        OP2_CPUID           = 0xA2,
         OP2_3BYTE_ESCAPE_AE = 0xAE,
         OP2_IMUL_GvEv       = 0xAF,
         OP2_CMPXCHGb        = 0xB0,
@@ -3544,6 +3547,22 @@
         m_formatter.threeByteOp(OP2_3BYTE_ESCAPE_AE, OP3_MFENCE);
     }
 
+    void rdtsc()
+    {
+        m_formatter.twoByteOp(OP2_RDTSC);
+    }
+
+    void pause()
+    {
+        m_formatter.prefix(PRE_SSE_F3);
+        m_formatter.oneByteOp(OP_PAUSE);
+    }
+
+    void cpuid()
+    {
+        m_formatter.twoByteOp(OP2_CPUID);
+    }
+
     // Assembler admin methods:
 
     size_t codeSize() const

Modified: trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h (224937 => 224938)


--- trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h	2017-11-16 23:27:59 UTC (rev 224937)
+++ trunk/Source/_javascript_Core/dfg/DFGAbstractInterpreterInlines.h	2017-11-16 23:44:12 UTC (rev 224938)
@@ -3233,6 +3233,13 @@
         m_state.setStructureClobberState(StructuresAreWatched);
         break;
 
+    case CPUIntrinsic: 
+        if (node->intrinsic() == CPURdtscIntrinsic)
+            forNode(node).setType(SpecInt32Only);
+        else
+            forNode(node).setType(SpecOther);
+        break;
+
     case CheckTraps:
     case LogShadowChickenPrologue:
     case LogShadowChickenTail:

Modified: trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp (224937 => 224938)


--- trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2017-11-16 23:27:59 UTC (rev 224937)
+++ trunk/Source/_javascript_Core/dfg/DFGByteCodeParser.cpp	2017-11-16 23:44:12 UTC (rev 224938)
@@ -3037,6 +3037,23 @@
         return true;
     }
 
+    case CPUMfenceIntrinsic:
+    case CPURdtscIntrinsic:
+    case CPUCpuidIntrinsic:
+    case CPUPauseIntrinsic: {
+#if CPU(X86_64)
+        if (!isFTL(m_graph.m_plan.mode))
+            return false;
+        insertChecks();
+        set(VirtualRegister(resultOperand),
+            addToGraph(CPUIntrinsic, OpInfo(intrinsic), OpInfo()));
+        return true;
+#else
+        return false;
+#endif
+    }
+
+
     default:
         return false;
     }

Modified: trunk/Source/_javascript_Core/dfg/DFGClobberize.h (224937 => 224938)


--- trunk/Source/_javascript_Core/dfg/DFGClobberize.h	2017-11-16 23:27:59 UTC (rev 224937)
+++ trunk/Source/_javascript_Core/dfg/DFGClobberize.h	2017-11-16 23:44:12 UTC (rev 224938)
@@ -437,6 +437,7 @@
     case Switch:
     case EntrySwitch:
     case ForceOSRExit:
+    case CPUIntrinsic:
     case CheckBadCell:
     case Return:
     case Unreachable:

Modified: trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp (224937 => 224938)


--- trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp	2017-11-16 23:27:59 UTC (rev 224937)
+++ trunk/Source/_javascript_Core/dfg/DFGDoesGC.cpp	2017-11-16 23:44:12 UTC (rev 224938)
@@ -200,6 +200,7 @@
     case SuperSamplerBegin:
     case SuperSamplerEnd:
     case ForceOSRExit:
+    case CPUIntrinsic:
     case CheckTraps:
     case StringFromCharCode:
     case MapHash:

Modified: trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp (224937 => 224938)


--- trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp	2017-11-16 23:27:59 UTC (rev 224937)
+++ trunk/Source/_javascript_Core/dfg/DFGFixupPhase.cpp	2017-11-16 23:44:12 UTC (rev 224938)
@@ -2133,6 +2133,7 @@
         case CompareEqPtr:
         case NumberToStringWithValidRadixConstant:
         case GetGlobalThis:
+        case CPUIntrinsic:
             break;
 #else
         default:

Modified: trunk/Source/_javascript_Core/dfg/DFGGraph.cpp (224937 => 224938)


--- trunk/Source/_javascript_Core/dfg/DFGGraph.cpp	2017-11-16 23:27:59 UTC (rev 224937)
+++ trunk/Source/_javascript_Core/dfg/DFGGraph.cpp	2017-11-16 23:44:12 UTC (rev 224938)
@@ -243,6 +243,8 @@
         out.print(comma, inContext(node->structureSet().toStructureSet(), context));
     if (node->hasStructure())
         out.print(comma, inContext(*node->structure().get(), context));
+    if (node->op() == CPUIntrinsic)
+        out.print(comma, intrinsicName(node->intrinsic()));
     if (node->hasTransition()) {
         out.print(comma, pointerDumpInContext(node->transition(), context));
 #if USE(JSVALUE64)

Modified: trunk/Source/_javascript_Core/dfg/DFGNode.h (224937 => 224938)


--- trunk/Source/_javascript_Core/dfg/DFGNode.h	2017-11-16 23:27:59 UTC (rev 224937)
+++ trunk/Source/_javascript_Core/dfg/DFGNode.h	2017-11-16 23:44:12 UTC (rev 224938)
@@ -1442,6 +1442,12 @@
         ASSERT(isEntrySwitch());
         return m_opInfo.as<EntrySwitchData*>();
     }
+
+    Intrinsic intrinsic()
+    {
+        RELEASE_ASSERT(op() == CPUIntrinsic);
+        return m_opInfo.as<Intrinsic>();
+    }
     
     unsigned numSuccessors()
     {

Modified: trunk/Source/_javascript_Core/dfg/DFGNodeType.h (224937 => 224938)


--- trunk/Source/_javascript_Core/dfg/DFGNodeType.h	2017-11-16 23:27:59 UTC (rev 224937)
+++ trunk/Source/_javascript_Core/dfg/DFGNodeType.h	2017-11-16 23:44:12 UTC (rev 224938)
@@ -456,8 +456,12 @@
     /* Metadata node that initializes the state for flushed argument types at an entrypoint in the program. */ \
     /* Currently, we only use this for the blocks an EntrySwitch branches to at the root of the program. */ \
     /* This is only used in SSA. */ \
-    macro(InitializeEntrypointArguments, NodeMustGenerate)
+    macro(InitializeEntrypointArguments, NodeMustGenerate) \
+    \
+    /* Used for $vm performance debugging */ \
+    macro(CPUIntrinsic, NodeResultJS | NodeMustGenerate) \
 
+
 // This enum generates a monotonically increasing id for all Node types,
 // and is used by the subsequent enum to fill out the id (as accessed via the NodeIdMask).
 enum NodeType {

Modified: trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp (224937 => 224938)


--- trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp	2017-11-16 23:27:59 UTC (rev 224937)
+++ trunk/Source/_javascript_Core/dfg/DFGPredictionPropagationPhase.cpp	2017-11-16 23:44:12 UTC (rev 224938)
@@ -1042,6 +1042,14 @@
             break;
         }
 
+        case CPUIntrinsic: {
+            if (m_currentNode->intrinsic() == CPURdtscIntrinsic)
+                setPrediction(SpecInt32Only);
+            else
+                setPrediction(SpecOther);
+            break;
+        }
+
         case PutByValAlias:
         case DoubleAsInt32:
         case GetLocalUnlinked:

Modified: trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h (224937 => 224938)


--- trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h	2017-11-16 23:27:59 UTC (rev 224937)
+++ trunk/Source/_javascript_Core/dfg/DFGSafeToExecute.h	2017-11-16 23:44:12 UTC (rev 224938)
@@ -352,6 +352,7 @@
     case SuperSamplerBegin:
     case SuperSamplerEnd:
     case ForceOSRExit:
+    case CPUIntrinsic:
     case CheckTraps:
     case LogShadowChickenPrologue:
     case LogShadowChickenTail:

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp (224937 => 224938)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp	2017-11-16 23:27:59 UTC (rev 224937)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp	2017-11-16 23:44:12 UTC (rev 224938)
@@ -5665,6 +5665,7 @@
     case IdentityWithProfile:
     case InitializeEntrypointArguments:
     case EntrySwitch:
+    case CPUIntrinsic:
         DFG_CRASH(m_jit.graph(), node, "unexpected node in DFG backend");
         break;
     }

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (224937 => 224938)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2017-11-16 23:27:59 UTC (rev 224937)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2017-11-16 23:44:12 UTC (rev 224938)
@@ -6135,6 +6135,7 @@
     case PhantomSpread:
     case PhantomNewArrayWithSpread:
     case IdentityWithProfile:
+    case CPUIntrinsic:
         DFG_CRASH(m_jit.graph(), node, "Unexpected node");
         break;
     }

Modified: trunk/Source/_javascript_Core/dfg/DFGValidate.cpp (224937 => 224938)


--- trunk/Source/_javascript_Core/dfg/DFGValidate.cpp	2017-11-16 23:27:59 UTC (rev 224937)
+++ trunk/Source/_javascript_Core/dfg/DFGValidate.cpp	2017-11-16 23:44:12 UTC (rev 224938)
@@ -333,6 +333,19 @@
                     VALIDATE((node), type == Array::ArrayStorage || type == Array::SlowPutArrayStorage);
                     break;
                 }
+                case CPUIntrinsic: {
+                    switch (node->intrinsic()) {
+                    case CPUMfenceIntrinsic:
+                    case CPURdtscIntrinsic:
+                    case CPUCpuidIntrinsic:
+                    case CPUPauseIntrinsic:
+                        break;
+                    default:
+                        VALIDATE((node), false);
+                        break;
+                    }
+                    break;
+                }
                 default:
                     break;
                 }

Modified: trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp (224937 => 224938)


--- trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp	2017-11-16 23:27:59 UTC (rev 224937)
+++ trunk/Source/_javascript_Core/ftl/FTLCapabilities.cpp	2017-11-16 23:44:12 UTC (rev 224938)
@@ -315,6 +315,7 @@
     case AtomicsXor:
     case AtomicsIsLockFree:
     case InitializeEntrypointArguments:
+    case CPUIntrinsic:
         // These are OK.
         break;
 

Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp (224937 => 224938)


--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp	2017-11-16 23:27:59 UTC (rev 224937)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp	2017-11-16 23:44:12 UTC (rev 224938)
@@ -1003,6 +1003,13 @@
         case ForceOSRExit:
             compileForceOSRExit();
             break;
+        case CPUIntrinsic:
+#if CPU(X86_64)
+            compileCPUIntrinsic();
+#else
+            RELEASE_ASSERT_NOT_REACHED();
+#endif
+            break;
         case Throw:
             compileThrow();
             break;
@@ -8190,6 +8197,53 @@
     {
         terminate(InadequateCoverage);
     }
+
+    void compileCPUIntrinsic()
+    {
+#if CPU(X86_64)
+        Intrinsic intrinsic = m_node->intrinsic();
+        switch (intrinsic) {
+        case CPUMfenceIntrinsic:
+        case CPUCpuidIntrinsic:
+        case CPUPauseIntrinsic: {
+            PatchpointValue* patchpoint = m_out.patchpoint(Void);
+            patchpoint->effects = Effects::forCall();
+            patchpoint->setGenerator([=] (CCallHelpers& jit, const B3::StackmapGenerationParams&) {
+                switch (intrinsic) {
+                case CPUMfenceIntrinsic:
+                    jit.mfence();
+                    break;
+                case CPUCpuidIntrinsic:
+                    jit.cpuid();
+                    break;
+                case CPUPauseIntrinsic:
+                    jit.pause();
+                    break;
+                default:
+                    RELEASE_ASSERT_NOT_REACHED();
+                }
+            });
+            setJSValue(m_out.constInt64(JSValue::encode(jsUndefined())));
+            break;
+        }
+        case CPURdtscIntrinsic: {
+            PatchpointValue* patchpoint = m_out.patchpoint(Int32);
+            patchpoint->effects = Effects::forCall();
+            patchpoint->clobber(RegisterSet { X86Registers::eax, X86Registers::edx });
+            // The low 32-bits of rdtsc go into rax.
+            patchpoint->resultConstraint = ValueRep::reg(X86Registers::eax);
+            patchpoint->setGenerator( [=] (CCallHelpers& jit, const B3::StackmapGenerationParams&) {
+                jit.rdtsc();
+            });
+            setJSValue(boxInt32(patchpoint));
+            break;
+        }
+        default:
+            RELEASE_ASSERT_NOT_REACHED();
+
+        }
+#endif
+    }
     
     void compileThrow()
     {

Modified: trunk/Source/_javascript_Core/runtime/Intrinsic.cpp (224937 => 224938)


--- trunk/Source/_javascript_Core/runtime/Intrinsic.cpp	2017-11-16 23:27:59 UTC (rev 224937)
+++ trunk/Source/_javascript_Core/runtime/Intrinsic.cpp	2017-11-16 23:44:12 UTC (rev 224938)
@@ -209,6 +209,14 @@
         return "CheckInt32Intrinsic";
     case FiatInt52Intrinsic:
         return "FiatInt52Intrinsic";
+    case CPUMfenceIntrinsic:
+        return "CPUMfenceIntrinsic";
+    case CPURdtscIntrinsic:
+        return "CPURdtscIntrinsic";
+    case CPUCpuidIntrinsic:
+        return "CPUCpuidIntrinsic";
+    case CPUPauseIntrinsic:
+        return "CPUPauseIntrinsic";
     }
     RELEASE_ASSERT_NOT_REACHED();
     return nullptr;

Modified: trunk/Source/_javascript_Core/runtime/Intrinsic.h (224937 => 224938)


--- trunk/Source/_javascript_Core/runtime/Intrinsic.h	2017-11-16 23:27:59 UTC (rev 224937)
+++ trunk/Source/_javascript_Core/runtime/Intrinsic.h	2017-11-16 23:44:12 UTC (rev 224938)
@@ -122,6 +122,12 @@
     SetInt32HeapPredictionIntrinsic,
     CheckInt32Intrinsic,
     FiatInt52Intrinsic,
+
+    // These are used for $vm performance debugging features.
+    CPUMfenceIntrinsic,
+    CPURdtscIntrinsic,
+    CPUCpuidIntrinsic,
+    CPUPauseIntrinsic,
 };
 
 const char* intrinsicName(Intrinsic);

Modified: trunk/Source/_javascript_Core/tools/JSDollarVM.cpp (224937 => 224938)


--- trunk/Source/_javascript_Core/tools/JSDollarVM.cpp	2017-11-16 23:27:59 UTC (rev 224937)
+++ trunk/Source/_javascript_Core/tools/JSDollarVM.cpp	2017-11-16 23:44:12 UTC (rev 224938)
@@ -28,8 +28,10 @@
 
 #include "CodeBlock.h"
 #include "FunctionCodeBlock.h"
+#include "JSArrayBuffer.h"
 #include "JSCInlines.h"
 #include "VMInspector.h"
+#include <wtf/Atomics.h>
 #include <wtf/DataLog.h>
 #include <wtf/ProcessID.h>
 #include <wtf/StringPrintStream.h>
@@ -59,6 +61,97 @@
     return JSValue::encode(jsBoolean(false));
 }
 
+static EncodedJSValue JSC_HOST_CALL functionCpuMfence(ExecState*)
+{
+#if CPU(X86_64) && !OS(WINDOWS)
+    asm volatile("mfence" ::: "memory");
+#endif
+    return JSValue::encode(jsUndefined());
+}
+
+static EncodedJSValue JSC_HOST_CALL functionCpuRdtsc(ExecState*)
+{
+#if CPU(X86_64) && !OS(WINDOWS)
+    unsigned high;
+    unsigned low;
+    asm volatile ("rdtsc" : "=a"(low), "=d"(high));
+    return JSValue::encode(jsNumber(low));
+#else
+    return JSValue::encode(jsNumber(0));
+#endif
+}
+
+static EncodedJSValue JSC_HOST_CALL functionCpuCpuid(ExecState*)
+{
+#if CPU(X86_64) && !OS(WINDOWS)
+    WTF::x86_cpuid();
+#endif
+    return JSValue::encode(jsUndefined());
+}
+
+static EncodedJSValue JSC_HOST_CALL functionCpuPause(ExecState*)
+{
+#if CPU(X86_64) && !OS(WINDOWS)
+    asm volatile ("pause" ::: "memory");
+#endif
+    return JSValue::encode(jsUndefined());
+}
+
+// This takes either a JSArrayBuffer, JSArrayBufferView*, or any other object as its first
+// argument. The second argument is expected to be an integer.
+//
+// If the first argument is a JSArrayBuffer, it'll clflush on that buffer
+// plus the second argument as a byte offset. It'll also flush on the object
+// itself so its length, etc, aren't in the cache.
+//
+// If the first argument is not a JSArrayBuffer, we load the butterfly
+// and clflush at the address of the butterfly.
+static EncodedJSValue JSC_HOST_CALL functionCpuClflush(ExecState* exec)
+{
+#if CPU(X86_64) && !OS(WINDOWS)
+    VM& vm = exec->vm();
+
+    if (!exec->argument(1).isInt32())
+        return JSValue::encode(jsBoolean(false));
+
+    auto clflush = [] (void* ptr) {
+        char* ptrToFlush = static_cast<char*>(ptr);
+        asm volatile ("clflush %0" :: "m"(*ptrToFlush) : "memory");
+    };
+
+    uint32_t offset = exec->argument(1).asUInt32();
+
+    char* ptr = nullptr;
+    if (JSArrayBuffer* buffer = jsDynamicCast<JSArrayBuffer*>(vm, exec->argument(0))) {
+        if (ArrayBuffer* impl = buffer->impl()) {
+            if (offset < impl->byteLength()) {
+                clflush(impl);
+                ptr = bitwise_cast<char*>(impl) + offset;
+            }
+        }
+    } else if (JSArrayBufferView* view = jsDynamicCast<JSArrayBufferView*>(vm, exec->argument(0)))
+        ptr = bitwise_cast<char*>(view);
+    else if (JSObject* object = jsDynamicCast<JSObject*>(vm, exec->argument(0))) {
+        switch (object->indexingType()) {
+        case ALL_INT32_INDEXING_TYPES:
+        case ALL_CONTIGUOUS_INDEXING_TYPES:
+        case ALL_DOUBLE_INDEXING_TYPES:
+            clflush(object);
+            ptr = bitwise_cast<char*>(object->butterfly()) + offset;
+        }
+    }
+
+    if (!ptr)
+        return JSValue::encode(jsBoolean(false));
+
+    clflush(ptr);
+    return JSValue::encode(jsBoolean(true));
+#else
+    UNUSED_PARAM(exec);
+    return JSValue::encode(jsBoolean(false));
+#endif
+}
+
 class CallerFrameJITTypeFunctor {
 public:
     CallerFrameJITTypeFunctor()
@@ -270,6 +363,12 @@
     addFunction(vm, globalObject, "crash", functionCrash, 0);
     
     putDirectNativeFunction(vm, globalObject, Identifier::fromString(&vm, "dfgTrue"), 0, functionDFGTrue, DFGTrueIntrinsic, static_cast<unsigned>(PropertyAttribute::DontEnum));
+
+    putDirectNativeFunction(vm, globalObject, Identifier::fromString(&vm, "cpuMfence"), 0, functionCpuMfence, CPUMfenceIntrinsic, 0);
+    putDirectNativeFunction(vm, globalObject, Identifier::fromString(&vm, "cpuRdtsc"), 0, functionCpuRdtsc, CPURdtscIntrinsic, 0);
+    putDirectNativeFunction(vm, globalObject, Identifier::fromString(&vm, "cpuCpuid"), 0, functionCpuCpuid, CPUCpuidIntrinsic, 0);
+    putDirectNativeFunction(vm, globalObject, Identifier::fromString(&vm, "cpuPause"), 0, functionCpuPause, CPUPauseIntrinsic, 0);
+    addFunction(vm, globalObject, "cpuClflush", functionCpuClflush, 2);
     
     addFunction(vm, globalObject, "llintTrue", functionLLintTrue, 0);
     addFunction(vm, globalObject, "jitTrue", functionJITTrue, 0);
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to