Changeset 207239 in webkit


Ignore:
Timestamp:
Oct 12, 2016 1:47:51 PM (8 years ago)
Author:
Yusuke Suzuki
Message:

[DOMJIT][JSC] Explore the way to embed nodeType into JSC::JSType in WebCore
https://bugs.webkit.org/show_bug.cgi?id=163245

Reviewed by Filip Pizlo.

Source/JavaScriptCore:

We reserve the highest bit of JSC::JSType for extensions outside JSC.
JSC does not use JSType bits so many: only 52 types are defined.

And we extend CallDOM patchpoint to claim that it does not require a global object.
This global object is used to generate a DOM wrapper. However, nodeType does not require
it since it just returns integer. In the future, we will extend CallDOM to claim
its result type. And we can decide this requireGlobalObject condition automatically
according to the result type.

(JSC::DFG::ByteCodeParser::handleDOMJITGetter):

  • dfg/DFGFixupPhase.cpp:

(JSC::DFG::FixupPhase::fixupNode):

  • dfg/DFGGraph.h:
  • dfg/DFGNode.h:

(JSC::DFG::Node::hasCheckDOMPatchpoint):
(JSC::DFG::Node::checkDOMPatchpoint):
(JSC::DFG::Node::hasCallDOMPatchpoint):
(JSC::DFG::Node::callDOMPatchpoint):
(JSC::DFG::Node::hasDOMJIT): Deleted.
(JSC::DFG::Node::domJIT): Deleted.

  • dfg/DFGSpeculativeJIT.cpp:

(JSC::DFG::SpeculativeJIT::compileCallDOM):
(JSC::DFG::SpeculativeJIT::compileCheckDOM):

  • domjit/DOMJITCallDOMPatchpoint.h: Copied from Source/JavaScriptCore/domjit/DOMJITGetterSetter.h.

(JSC::DOMJIT::CallDOMPatchpoint::create):

  • domjit/DOMJITGetterSetter.h:
  • domjit/DOMJITPatchpoint.h:
  • ftl/FTLLowerDFGToB3.cpp:

(JSC::FTL::DFG::LowerDFGToB3::compileCheckDOM):
(JSC::FTL::DFG::LowerDFGToB3::compileCallDOM):

  • jsc.cpp:
  • llint/LLIntData.cpp:

(JSC::LLInt::Data::performAssertions):

  • llint/LowLevelInterpreter.asm:
  • runtime/JSType.h:

Source/WebCore:

Node.nodeType accessor is so frequently called. For example, jQuery's $ function uses
this to distinguish DOM objects from the other JS objects. So every time you call $(dom),
nodeType accessor is called. In addition to that, jQuery's prev, next, parent etc. also uses
this nodeType. And Ember.js also uses it. And ... So this function is super critical for DOM
performance.

The challenge is that there is no room for putting NodeType into C++ Node class. Node class
has a 32bit field to store some data. However, these bits are already exhausted. Extending
Node class is unacceptable since it significantly enlarges memory consumption of WebKit (Node
is everywhere!). Unfortunately, current Node::nodeType is implemented as a virtual function
even though this function is frequently called from JS world.

Interestingly, we already store some duplicate data in JSObject, JSC::JSType. WebCore already
extends it with JSElementType, JSNodeType, and JSDocumentWrapperType. And these types are
corresponding to specific NodeTypes. For example, JSElementType should have ELEMENT_NODE type.

This patch further extends this JSC::JSType in WebCore side safely. We embed NodeType bits into
JSC::JSType. This design offers significantly faster nodeType implementation. Furthermore, it
makes DOMJIT easy for nodeType accessor.

Even without the IC change[1], Dromaeo dom-query shows 8 - 10% improvement,
1452.96 runs/s vs 1578.56 runs/s. We can expect that this improvement will be applied to the
other benchmarks / real applications when the IC change is landed.

[1]: https://bugs.webkit.org/show_bug.cgi?id=163226

  • WebCore.xcodeproj/project.pbxproj:
  • bindings/js/JSDOMWrapper.h:
  • bindings/js/JSNodeCustom.h:

(WebCore::JSNode::nodeType):

  • bindings/scripts/CodeGeneratorJS.pm:

(GetJSTypeForNode):
(GenerateHeader):

  • dom/Node.idl:
  • dom/NodeConstants.h: Copied from Source/JavaScriptCore/domjit/DOMJITGetterSetter.h.
  • domjit/JSNodeDOMJIT.cpp:

(WebCore::createCallDOMForOffsetAccess):
(WebCore::NodeFirstChildDOMJIT::callDOM):
(WebCore::NodeLastChildDOMJIT::callDOM):
(WebCore::NodeNextSiblingDOMJIT::callDOM):
(WebCore::NodePreviousSiblingDOMJIT::callDOM):
(WebCore::NodeParentNodeDOMJIT::callDOM):
(WebCore::NodeNodeTypeDOMJIT::checkDOM):
(WebCore::NodeNodeTypeDOMJIT::callDOM):

LayoutTests:

  • js/dom/domjit-accessor-node-type.html: Added.
Location:
trunk
Files:
1 added
22 edited
2 copied

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r207238 r207239  
     12016-10-12  Yusuke Suzuki  <utatane.tea@gmail.com>
     2
     3        [DOMJIT][JSC] Explore the way to embed nodeType into JSC::JSType in WebCore
     4        https://bugs.webkit.org/show_bug.cgi?id=163245
     5
     6        Reviewed by Filip Pizlo.
     7
     8        * js/dom/domjit-accessor-node-type.html: Added.
     9
    1102016-10-12  Chris Dumez  <cdumez@apple.com>
    211
  • trunk/Source/JavaScriptCore/ChangeLog

    r207235 r207239  
     12016-10-12  Yusuke Suzuki  <utatane.tea@gmail.com>
     2
     3        [DOMJIT][JSC] Explore the way to embed nodeType into JSC::JSType in WebCore
     4        https://bugs.webkit.org/show_bug.cgi?id=163245
     5
     6        Reviewed by Filip Pizlo.
     7
     8        We reserve the highest bit of JSC::JSType for extensions outside JSC.
     9        JSC does not use JSType bits so many: only 52 types are defined.
     10
     11        And we extend CallDOM patchpoint to claim that it does not require a global object.
     12        This global object is used to generate a DOM wrapper. However, nodeType does not require
     13        it since it just returns integer. In the future, we will extend CallDOM to claim
     14        its result type. And we can decide this `requireGlobalObject` condition automatically
     15        according to the result type.
     16
     17        * JavaScriptCore.xcodeproj/project.pbxproj:
     18        * dfg/DFGByteCodeParser.cpp:
     19        (JSC::DFG::ByteCodeParser::handleDOMJITGetter):
     20        * dfg/DFGFixupPhase.cpp:
     21        (JSC::DFG::FixupPhase::fixupNode):
     22        * dfg/DFGGraph.h:
     23        * dfg/DFGNode.h:
     24        (JSC::DFG::Node::hasCheckDOMPatchpoint):
     25        (JSC::DFG::Node::checkDOMPatchpoint):
     26        (JSC::DFG::Node::hasCallDOMPatchpoint):
     27        (JSC::DFG::Node::callDOMPatchpoint):
     28        (JSC::DFG::Node::hasDOMJIT): Deleted.
     29        (JSC::DFG::Node::domJIT): Deleted.
     30        * dfg/DFGSpeculativeJIT.cpp:
     31        (JSC::DFG::SpeculativeJIT::compileCallDOM):
     32        (JSC::DFG::SpeculativeJIT::compileCheckDOM):
     33        * domjit/DOMJITCallDOMPatchpoint.h: Copied from Source/JavaScriptCore/domjit/DOMJITGetterSetter.h.
     34        (JSC::DOMJIT::CallDOMPatchpoint::create):
     35        * domjit/DOMJITGetterSetter.h:
     36        * domjit/DOMJITPatchpoint.h:
     37        * ftl/FTLLowerDFGToB3.cpp:
     38        (JSC::FTL::DFG::LowerDFGToB3::compileCheckDOM):
     39        (JSC::FTL::DFG::LowerDFGToB3::compileCallDOM):
     40        * jsc.cpp:
     41        * llint/LLIntData.cpp:
     42        (JSC::LLInt::Data::performAssertions):
     43        * llint/LowLevelInterpreter.asm:
     44        * runtime/JSType.h:
     45
    1462016-10-12  Keith Miller  <keith_miller@apple.com>
    247
  • trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r207222 r207239  
    20972097                E33F50871B8449EF00413856 /* JSInternalPromiseConstructor.lut.h in Headers */ = {isa = PBXBuildFile; fileRef = E33F50861B8449EF00413856 /* JSInternalPromiseConstructor.lut.h */; };
    20982098                E354622B1B6065D100545386 /* ConstructAbility.h in Headers */ = {isa = PBXBuildFile; fileRef = E354622A1B6065D100545386 /* ConstructAbility.h */; settings = {ATTRIBUTES = (Private, ); }; };
     2099                E3555B8A1DAE03A500F36921 /* DOMJITCallDOMPatchpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = E3555B891DAE03A200F36921 /* DOMJITCallDOMPatchpoint.h */; settings = {ATTRIBUTES = (Private, ); }; };
    20992100                E355F3521B7DC85300C50DC5 /* ModuleLoaderPrototype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E355F3501B7DC85300C50DC5 /* ModuleLoaderPrototype.cpp */; };
    21002101                E355F3531B7DC85300C50DC5 /* ModuleLoaderPrototype.h in Headers */ = {isa = PBXBuildFile; fileRef = E355F3511B7DC85300C50DC5 /* ModuleLoaderPrototype.h */; };
     
    44004401                E33F50881B844A1A00413856 /* InternalPromiseConstructor.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = InternalPromiseConstructor.js; sourceTree = "<group>"; };
    44014402                E354622A1B6065D100545386 /* ConstructAbility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConstructAbility.h; sourceTree = "<group>"; };
     4403                E3555B891DAE03A200F36921 /* DOMJITCallDOMPatchpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMJITCallDOMPatchpoint.h; sourceTree = "<group>"; };
    44024404                E355F3501B7DC85300C50DC5 /* ModuleLoaderPrototype.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ModuleLoaderPrototype.cpp; sourceTree = "<group>"; };
    44034405                E355F3511B7DC85300C50DC5 /* ModuleLoaderPrototype.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ModuleLoaderPrototype.h; sourceTree = "<group>"; };
     
    71967198                        isa = PBXGroup;
    71977199                        children = (
     7200                                E3555B891DAE03A200F36921 /* DOMJITCallDOMPatchpoint.h */,
    71987201                                E3FF752F1D9CEA1200C7E16D /* DOMJITGetterSetter.h */,
    71997202                                E3C08E3B1DA41B7B0039478F /* DOMJITPatchpoint.h */,
     
    80738076                                BC18C4270E16F5CD00B34460 /* JSString.h in Headers */,
    80748077                                86E85539111B9968001AF51E /* JSStringBuilder.h in Headers */,
     8078                                E3555B8A1DAE03A500F36921 /* DOMJITCallDOMPatchpoint.h in Headers */,
    80758079                                70EC0EC31AA0D7DA00B6AAFA /* JSStringIterator.h in Headers */,
    80768080                                0F070A471D543A8B006E7232 /* CellContainer.h in Headers */,
  • trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

    r207060 r207239  
    26882688    addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(variant.structureSet())), thisNode);
    26892689
     2690    Ref<DOMJIT::Patchpoint> checkDOMPatchpoint = domJIT->checkDOM();
     2691    m_graph.m_domJITPatchpoints.append(checkDOMPatchpoint.ptr());
    26902692    // We do not need to emit CheckCell thingy here. When the custom accessor is replaced to different one, Structure transition occurs.
    2691     addToGraph(CheckDOM, OpInfo(domJIT), OpInfo(domJIT->thisClassInfo()), thisNode);
    2692     Node* globalObject = addToGraph(GetGlobalObject, thisNode);
    2693     addVarArgChild(globalObject); // GlobalObject of thisNode is always used to create a DOMWrapper.
     2693    addToGraph(CheckDOM, OpInfo(checkDOMPatchpoint.ptr()), OpInfo(domJIT->thisClassInfo()), thisNode);
     2694
     2695    Ref<DOMJIT::CallDOMPatchpoint> callDOMPatchpoint = domJIT->callDOM();
     2696    m_graph.m_domJITPatchpoints.append(callDOMPatchpoint.ptr());
     2697    if (callDOMPatchpoint->requireGlobalObject) {
     2698        Node* globalObject = addToGraph(GetGlobalObject, thisNode);
     2699        addVarArgChild(globalObject); // GlobalObject of thisNode is always used to create a DOMWrapper.
     2700    }
    26942701    addVarArgChild(thisNode);
    2695     set(VirtualRegister(resultOperand), addToGraph(Node::VarArg, CallDOM, OpInfo(domJIT), OpInfo(prediction)));
     2702    set(VirtualRegister(resultOperand), addToGraph(Node::VarArg, CallDOM, OpInfo(callDOMPatchpoint.ptr()), OpInfo(prediction)));
    26962703    return true;
    26972704}
  • trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp

    r206853 r207239  
    17041704            break;
    17051705
    1706         case CallDOM:
    1707             fixEdge<KnownCellUse>(m_graph.varArgChild(node, 0)); // GlobalObject.
    1708             fixEdge<CellUse>(m_graph.varArgChild(node, 1)); // DOM.
    1709             break;
     1706        case CallDOM: {
     1707            int childIndex = 0;
     1708            DOMJIT::CallDOMPatchpoint* patchpoint = node->callDOMPatchpoint();
     1709            if (patchpoint->requireGlobalObject)
     1710                fixEdge<KnownCellUse>(m_graph.varArgChild(node, childIndex++)); // GlobalObject.
     1711            fixEdge<CellUse>(m_graph.varArgChild(node, childIndex++)); // DOM.
     1712            break;
     1713        }
    17101714
    17111715#if !ASSERT_DISABLED
  • trunk/Source/JavaScriptCore/dfg/DFGGraph.h

    r206525 r207239  
    905905    HashSet<std::pair<JSObject*, PropertyOffset>> m_safeToLoad;
    906906    HashMap<PropertyTypeKey, InferredType::Descriptor> m_inferredTypes;
     907    Vector<RefPtr<DOMJIT::Patchpoint>> m_domJITPatchpoints;
    907908    std::unique_ptr<Dominators> m_dominators;
    908909    std::unique_ptr<PrePostNumbering> m_prePostNumbering;
  • trunk/Source/JavaScriptCore/dfg/DFGNode.h

    r206846 r207239  
    6060
    6161namespace DOMJIT {
    62 class GetterSetter;
     62class Patchpoint;
     63class CallDOMPatchpoint;
    6364}
    6465
     
    23152316    }
    23162317
    2317     bool hasDOMJIT() const
    2318     {
    2319         return op() == CheckDOM || op() == CallDOM;
    2320     }
    2321 
    2322     DOMJIT::GetterSetter* domJIT()
    2323     {
    2324         ASSERT(hasDOMJIT());
    2325         return m_opInfo.as<DOMJIT::GetterSetter*>();
     2318    bool hasCheckDOMPatchpoint() const
     2319    {
     2320        return op() == CheckDOM;
     2321    }
     2322
     2323    DOMJIT::Patchpoint* checkDOMPatchpoint()
     2324    {
     2325        ASSERT(hasCheckDOMPatchpoint());
     2326        return m_opInfo.as<DOMJIT::Patchpoint*>();
     2327    }
     2328
     2329    bool hasCallDOMPatchpoint() const
     2330    {
     2331        return op() == CallDOM;
     2332    }
     2333
     2334    DOMJIT::CallDOMPatchpoint* callDOMPatchpoint()
     2335    {
     2336        ASSERT(hasCallDOMPatchpoint());
     2337        return m_opInfo.as<DOMJIT::CallDOMPatchpoint*>();
    23262338    }
    23272339
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

    r207166 r207239  
    71317131void SpeculativeJIT::compileCallDOM(Node* node)
    71327132{
    7133     Ref<DOMJIT::Patchpoint> patchpoint = node->domJIT()->callDOM();
     7133    DOMJIT::CallDOMPatchpoint* patchpoint = node->callDOMPatchpoint();
    71347134
    71357135    Vector<GPRReg> gpScratch;
     
    71377137    Vector<DOMJIT::Value> regs;
    71387138
    7139     // FIXME: patchpoint should have a way to tell this can reuse "base" register.
    7140     // Teaching DFG about DOMJIT::Patchpoint clobber information is nice.
    7141     SpeculateCellOperand globalObject(this, m_jit.graph().varArgChild(node, 0));
    7142     SpeculateCellOperand base(this, m_jit.graph().varArgChild(node, 1));
    71437139    JSValueRegsTemporary result(this);
    7144 
    71457140    regs.append(result.regs());
    7146     regs.append(DOMJIT::Value(globalObject.gpr(), m_state.forNode(m_jit.graph().varArgChild(node, 0)).value()));
    7147     regs.append(DOMJIT::Value(base.gpr(), m_state.forNode(m_jit.graph().varArgChild(node, 1)).value()));
    7148 #if USE(JSVALUE64)
    7149     regs.append(static_cast<GPRReg>(GPRInfo::tagMaskRegister));
    7150     regs.append(static_cast<GPRReg>(GPRInfo::tagTypeNumberRegister));
    7151 #endif
     7141
     7142    int childIndex = 0;
     7143
     7144    Optional<SpeculateCellOperand> globalObject;
     7145    if (patchpoint->requireGlobalObject) {
     7146        Edge& globalObjectEdge = m_jit.graph().varArgChild(node, childIndex++);
     7147        globalObject = SpeculateCellOperand(this, globalObjectEdge);
     7148        regs.append(DOMJIT::Value(globalObject->gpr(), m_state.forNode(globalObjectEdge).value()));
     7149    }
     7150
     7151    Edge& baseEdge = m_jit.graph().varArgChild(node, childIndex++);
     7152    SpeculateCellOperand base(this, baseEdge);
     7153    regs.append(DOMJIT::Value(base.gpr(), m_state.forNode(baseEdge).value()));
    71527154
    71537155    Vector<GPRTemporary> gpTempraries;
    71547156    Vector<FPRTemporary> fpTempraries;
    7155     allocateTemporaryRegistersForPatchpoint(this, gpTempraries, fpTempraries, gpScratch, fpScratch, patchpoint.get());
     7157    allocateTemporaryRegistersForPatchpoint(this, gpTempraries, fpTempraries, gpScratch, fpScratch, *patchpoint);
    71567158    DOMJITPatchpointParams params(this, WTFMove(regs), WTFMove(gpScratch), WTFMove(fpScratch));
    71577159    patchpoint->generator()->run(m_jit, params);
     
    71627164{
    71637165    // FIXME: We can add the fallback implementation that inlines jsDynamicCast things here.
    7164     Ref<DOMJIT::Patchpoint> patchpoint = node->domJIT()->checkDOM();
     7166    DOMJIT::Patchpoint* patchpoint = node->checkDOMPatchpoint();
    71657167
    71667168    Vector<GPRReg> gpScratch;
     
    71747176    Vector<GPRTemporary> gpTempraries;
    71757177    Vector<FPRTemporary> fpTempraries;
    7176     allocateTemporaryRegistersForPatchpoint(this, gpTempraries, fpTempraries, gpScratch, fpScratch, patchpoint.get());
     7178    allocateTemporaryRegistersForPatchpoint(this, gpTempraries, fpTempraries, gpScratch, fpScratch, *patchpoint);
    71777179
    71787180    DOMJITPatchpointParams params(this, WTFMove(regs), WTFMove(gpScratch), WTFMove(fpScratch));
  • trunk/Source/JavaScriptCore/domjit/DOMJITCallDOMPatchpoint.h

    r207238 r207239  
    2626#pragma once
    2727
     28#if ENABLE(JIT)
     29
    2830#include "DOMJITPatchpoint.h"
    29 #include "PropertySlot.h"
    30 #include "PutPropertySlot.h"
    31 #include "SpeculatedType.h"
     31#include "RegisterSet.h"
    3232
    3333namespace JSC { namespace DOMJIT {
    3434
    35 class GetterSetter {
     35class CallDOMPatchpoint : public Patchpoint {
    3636public:
    37     typedef PropertySlot::GetValueFunc CustomGetter;
    38     typedef PutPropertySlot::PutValueFunc CustomSetter;
    39 
    40     GetterSetter(CustomGetter getter, CustomSetter setter, const ClassInfo* classInfo)
    41         : m_getter(getter)
    42         , m_setter(setter)
    43         , m_thisClassInfo(classInfo)
     37    static Ref<CallDOMPatchpoint> create()
    4438    {
     39        return adoptRef(*new CallDOMPatchpoint());
    4540    }
    4641
    47     virtual ~GetterSetter() { }
    48 
    49     CustomGetter getter() const { return m_getter; }
    50     CustomSetter setter() const { return m_setter; }
    51     const ClassInfo* thisClassInfo() const { return m_thisClassInfo; }
    52 
    53 #if ENABLE(JIT)
    54     virtual Ref<DOMJIT::Patchpoint> callDOM() = 0;
    55     virtual Ref<DOMJIT::Patchpoint> checkDOM() = 0;
    56 #endif
     42    // To look up DOMWrapper cache, GlobalObject is required.
     43    // FIXME: Later, we will extend this patchpoint to represent the result type by DOMJIT::Signature.
     44    // And after that, we will automatically pass a global object when the result type includes a DOM wrapper thing.
     45    // https://bugs.webkit.org/show_bug.cgi?id=162980
     46    bool requireGlobalObject { true };
    5747
    5848private:
    59     CustomGetter m_getter;
    60     CustomSetter m_setter;
    61     const ClassInfo* m_thisClassInfo;
     49    CallDOMPatchpoint() = default;
    6250};
    6351
    6452} }
     53
     54#endif
  • trunk/Source/JavaScriptCore/domjit/DOMJITGetterSetter.h

    r206779 r207239  
    2626#pragma once
    2727
    28 #include "DOMJITPatchpoint.h"
     28#include "DOMJITCallDOMPatchpoint.h"
    2929#include "PropertySlot.h"
    3030#include "PutPropertySlot.h"
     
    5252
    5353#if ENABLE(JIT)
    54     virtual Ref<DOMJIT::Patchpoint> callDOM() = 0;
     54    virtual Ref<DOMJIT::CallDOMPatchpoint> callDOM() = 0;
    5555    virtual Ref<DOMJIT::Patchpoint> checkDOM() = 0;
    5656#endif
  • trunk/Source/JavaScriptCore/domjit/DOMJITPatchpoint.h

    r206779 r207239  
    6363    uint8_t numFPScratchRegisters { 0 };
    6464
    65 private:
     65protected:
    6666    Patchpoint() = default;
    6767
     68private:
    6869    RefPtr<PatchpointGenerator> m_generator;
    6970};
  • trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp

    r207166 r207239  
    87258725        LValue cell = lowCell(m_node->child1());
    87268726
    8727         RefPtr<DOMJIT::Patchpoint> domJIT = m_node->domJIT()->checkDOM();
     8727        DOMJIT::Patchpoint* domJIT = m_node->checkDOMPatchpoint();
    87288728
    87298729        PatchpointValue* patchpoint = m_out.patchpoint(Void);
     
    87708770    void compileCallDOM()
    87718771    {
    8772         LValue globalObject = lowCell(m_graph.varArgChild(m_node, 0));
    8773         LValue cell = lowCell(m_graph.varArgChild(m_node, 1));
    8774 
    8775         RefPtr<DOMJIT::Patchpoint> domJIT = m_node->domJIT()->callDOM();
     8772        DOMJIT::CallDOMPatchpoint* domJIT = m_node->callDOMPatchpoint();
     8773        int childIndex = 0;
     8774
     8775        LValue globalObject;
     8776        JSValue globalObjectConstant;
     8777        if (domJIT->requireGlobalObject) {
     8778            Edge& globalObjectEdge = m_graph.varArgChild(m_node, childIndex++);
     8779            globalObject = lowCell(globalObjectEdge);
     8780            globalObjectConstant = m_state.forNode(globalObjectEdge).value();
     8781        }
     8782
     8783        Edge& baseEdge = m_graph.varArgChild(m_node, childIndex++);
     8784        LValue base = lowCell(baseEdge);
     8785        JSValue baseConstant = m_state.forNode(baseEdge).value();
     8786
    87768787        PatchpointValue* patchpoint = m_out.patchpoint(Int64);
    8777         patchpoint->appendSomeRegister(globalObject);
    8778         patchpoint->appendSomeRegister(cell);
     8788        if (domJIT->requireGlobalObject)
     8789            patchpoint->appendSomeRegister(globalObject);
     8790        patchpoint->appendSomeRegister(base);
    87798791        patchpoint->append(m_tagMask, ValueRep::reg(GPRInfo::tagMaskRegister));
    87808792        patchpoint->append(m_tagTypeNumber, ValueRep::reg(GPRInfo::tagTypeNumberRegister));
     
    87878799        State* state = &m_ftlState;
    87888800        Node* node = m_node;
    8789         JSValue child1Constant = m_state.forNode(m_graph.varArgChild(m_node, 0)).value();
    8790         JSValue child2Constant = m_state.forNode(m_graph.varArgChild(m_node, 1)).value();
    87918801        patchpoint->setGenerator(
    87928802            [=] (CCallHelpers& jit, const StackmapGenerationParams& params) {
     
    87978807                Vector<DOMJIT::Value> regs;
    87988808
    8799                 // FIXME: patchpoint should have a way to tell this can reuse "base" register.
    8800                 // Teaching DFG about DOMJIT::Patchpoint clobber information is nice.
     8809                int childIndex = 1;
    88018810                regs.append(JSValueRegs(params[0].gpr()));
    8802                 regs.append(DOMJIT::Value(params[1].gpr(), child1Constant));
    8803                 regs.append(DOMJIT::Value(params[2].gpr(), child2Constant));
     8811                if (domJIT->requireGlobalObject)
     8812                    regs.append(DOMJIT::Value(params[childIndex++].gpr(), globalObjectConstant));
     8813                regs.append(DOMJIT::Value(params[childIndex++].gpr(), baseConstant));
    88048814
    88058815                for (unsigned i = 0; i < domJIT->numGPScratchRegisters; ++i)
  • trunk/Source/JavaScriptCore/jsc.cpp

    r206899 r207239  
    621621        }
    622622
    623         Ref<DOMJIT::Patchpoint> callDOM() override
     623        Ref<DOMJIT::CallDOMPatchpoint> callDOM() override
    624624        {
    625             Ref<DOMJIT::Patchpoint> patchpoint = DOMJIT::Patchpoint::create();
     625            Ref<DOMJIT::CallDOMPatchpoint> patchpoint = DOMJIT::CallDOMPatchpoint::create();
     626            patchpoint->requireGlobalObject = false;
    626627            patchpoint->setGenerator([=](CCallHelpers& jit, const DOMJIT::PatchpointParams& params) {
    627628                JSValueRegs results = params[0].jsValueRegs();
    628                 GPRReg dom = params[2].gpr();
     629                GPRReg dom = params[1].gpr();
    629630
    630631                params.addSlowPathCall(jit.jump(), jit, static_cast<EncodedJSValue(*)(ExecState*, void*)>([](ExecState*, void* pointer) {
  • trunk/Source/JavaScriptCore/llint/LLIntData.cpp

    r206344 r207239  
    162162    STATIC_ASSERT(ArrayType == 31);
    163163    STATIC_ASSERT(DerivedArrayType == 32);
    164     STATIC_ASSERT(ProxyObjectType == 116);
    165     STATIC_ASSERT(Int8ArrayType == 100);
    166     STATIC_ASSERT(Int16ArrayType == 101);
    167     STATIC_ASSERT(Int32ArrayType == 102);
    168     STATIC_ASSERT(Uint8ArrayType == 103);
    169     STATIC_ASSERT(Uint8ClampedArrayType == 104);
    170     STATIC_ASSERT(Uint16ArrayType == 105);
    171     STATIC_ASSERT(Uint32ArrayType == 106);
    172     STATIC_ASSERT(Float32ArrayType == 107);
    173     STATIC_ASSERT(Float64ArrayType == 108);
     164    STATIC_ASSERT(ProxyObjectType == 49);
     165    STATIC_ASSERT(Int8ArrayType == 33);
     166    STATIC_ASSERT(Int16ArrayType == 34);
     167    STATIC_ASSERT(Int32ArrayType == 35);
     168    STATIC_ASSERT(Uint8ArrayType == 36);
     169    STATIC_ASSERT(Uint8ClampedArrayType == 37);
     170    STATIC_ASSERT(Uint16ArrayType == 38);
     171    STATIC_ASSERT(Uint32ArrayType == 39);
     172    STATIC_ASSERT(Float32ArrayType == 40);
     173    STATIC_ASSERT(Float64ArrayType == 41);
    174174    STATIC_ASSERT(MasqueradesAsUndefined == 1);
    175175    STATIC_ASSERT(ImplementsDefaultHasInstance == 2);
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm

    r206853 r207239  
    351351const ArrayType = 31
    352352const DerivedArrayType = 32
    353 const ProxyObjectType = 116
     353const ProxyObjectType = 49
    354354
    355355# The typed array types need to be numbered in a particular order because of the manually written
    356356# switch statement in get_by_val and put_by_val.
    357 const Int8ArrayType = 100
    358 const Int16ArrayType = 101
    359 const Int32ArrayType = 102
    360 const Uint8ArrayType = 103
    361 const Uint8ClampedArrayType = 104
    362 const Uint16ArrayType = 105
    363 const Uint32ArrayType = 106
    364 const Float32ArrayType = 107
    365 const Float64ArrayType = 108
     357const Int8ArrayType = 33
     358const Int16ArrayType = 34
     359const Int32ArrayType = 35
     360const Uint8ArrayType = 36
     361const Uint8ClampedArrayType = 37
     362const Uint16ArrayType = 38
     363const Uint32ArrayType = 39
     364const Float32ArrayType = 40
     365const Float64ArrayType = 41
    366366
    367367const FirstArrayType = Int8ArrayType
  • trunk/Source/JavaScriptCore/runtime/JSType.h

    r206525 r207239  
    6666    DerivedArrayType,
    6767
    68     Int8ArrayType = 100,
     68    Int8ArrayType,
    6969    Int16ArrayType,
    7070    Int32ArrayType,
     
    8888
    8989    LastJSCObjectType = JSSetType,
     90    MaxJSType = 0b11111111,
    9091};
    9192
    92 COMPILE_ASSERT(sizeof(JSType) == sizeof(uint8_t), sizeof_jstype_is_one_byte);
     93static_assert(sizeof(JSType) == sizeof(uint8_t), "sizeof(JSType) is one byte.");
     94static_assert(LastJSCObjectType < 128, "The highest bit is reserved for embedder's extension.");
    9395
    9496} // namespace JSC
  • trunk/Source/WebCore/ChangeLog

    r207238 r207239  
     12016-10-12  Yusuke Suzuki  <utatane.tea@gmail.com>
     2
     3        [DOMJIT][JSC] Explore the way to embed nodeType into JSC::JSType in WebCore
     4        https://bugs.webkit.org/show_bug.cgi?id=163245
     5
     6        Reviewed by Filip Pizlo.
     7
     8        Node.nodeType accessor is so frequently called. For example, jQuery's $ function uses
     9        this to distinguish DOM objects from the other JS objects. So every time you call `$(dom)`,
     10        nodeType accessor is called. In addition to that, jQuery's prev, next, parent etc. also uses
     11        this `nodeType`. And Ember.js also uses it. And ... So this function is super critical for DOM
     12        performance.
     13
     14        The challenge is that there is no room for putting NodeType into C++ Node class. Node class
     15        has a 32bit field to store some data. However, these bits are already exhausted. Extending
     16        Node class is unacceptable since it significantly enlarges memory consumption of WebKit (Node
     17        is everywhere!). Unfortunately, current Node::nodeType is implemented as a virtual function
     18        even though this function is frequently called from JS world.
     19
     20        Interestingly, we already store some duplicate data in JSObject, JSC::JSType. WebCore already
     21        extends it with JSElementType, JSNodeType, and JSDocumentWrapperType. And these types are
     22        corresponding to specific NodeTypes. For example, JSElementType should have ELEMENT_NODE type.
     23
     24        This patch further extends this JSC::JSType in WebCore side safely. We embed NodeType bits into
     25        JSC::JSType. This design offers significantly faster nodeType implementation. Furthermore, it
     26        makes DOMJIT easy for nodeType accessor.
     27
     28        Even without the IC change[1], Dromaeo dom-query shows 8 - 10% improvement,
     29        1452.96 runs/s vs 1578.56 runs/s. We can expect that this improvement will be applied to the
     30        other benchmarks / real applications when the IC change is landed.
     31
     32        [1]: https://bugs.webkit.org/show_bug.cgi?id=163226
     33
     34        * WebCore.xcodeproj/project.pbxproj:
     35        * bindings/js/JSDOMWrapper.h:
     36        * bindings/js/JSNodeCustom.h:
     37        (WebCore::JSNode::nodeType):
     38        * bindings/scripts/CodeGeneratorJS.pm:
     39        (GetJSTypeForNode):
     40        (GenerateHeader):
     41        * dom/Node.idl:
     42        * dom/NodeConstants.h: Copied from Source/JavaScriptCore/domjit/DOMJITGetterSetter.h.
     43        * domjit/JSNodeDOMJIT.cpp:
     44        (WebCore::createCallDOMForOffsetAccess):
     45        (WebCore::NodeFirstChildDOMJIT::callDOM):
     46        (WebCore::NodeLastChildDOMJIT::callDOM):
     47        (WebCore::NodeNextSiblingDOMJIT::callDOM):
     48        (WebCore::NodePreviousSiblingDOMJIT::callDOM):
     49        (WebCore::NodeParentNodeDOMJIT::callDOM):
     50        (WebCore::NodeNodeTypeDOMJIT::checkDOM):
     51        (WebCore::NodeNodeTypeDOMJIT::callDOM):
     52
    1532016-10-12  Chris Dumez  <cdumez@apple.com>
    254
  • trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj

    r207151 r207239  
    61446144                E3150EA61DA7219000194012 /* JSNodeDOMJIT.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E3AFA9641DA6E908002861BD /* JSNodeDOMJIT.cpp */; };
    61456145                E3150EA71DA7219300194012 /* DOMJITHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = E3150EA51DA7218D00194012 /* DOMJITHelpers.h */; };
     6146                E377FE4D1DADE16500CDD025 /* NodeConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = E3D049931DADC04500718F3C /* NodeConstants.h */; settings = {ATTRIBUTES = (Private, ); }; };
    61466147                E38838981BAD145F00D62EE3 /* ScriptModuleLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E38838941BAD145F00D62EE3 /* ScriptModuleLoader.cpp */; };
    61476148                E38838991BAD145F00D62EE3 /* ScriptModuleLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = E38838951BAD145F00D62EE3 /* ScriptModuleLoader.h */; };
     
    1378513786                E3B2F0E81D7F35EC00B0C9D1 /* LoadableScriptClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LoadableScriptClient.h; sourceTree = "<group>"; };
    1378613787                E3B2F0E91D7F3D3C00B0C9D1 /* LoadableScript.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LoadableScript.cpp; sourceTree = "<group>"; };
     13788                E3D049931DADC04500718F3C /* NodeConstants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NodeConstants.h; sourceTree = "<group>"; };
    1378713789                E3FA38611D716E7600AA5950 /* PendingScriptClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PendingScriptClient.h; sourceTree = "<group>"; };
    1378813790                E401C27417CE53EC00C41A35 /* ElementIteratorAssertions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ElementIteratorAssertions.h; sourceTree = "<group>"; };
     
    2327623278                                E43105B716750F0C00DB2FB8 /* NodeTraversal.cpp */,
    2327723279                                E43105BA16750F1600DB2FB8 /* NodeTraversal.h */,
     23280                                E3D049931DADC04500718F3C /* NodeConstants.h */,
    2327823281                                9382AAB10D8C386100F357A6 /* NodeWithIndex.h */,
    2327923282                                E46B41F81CB24E70008F11DE /* NoEventDispatchAssertion.h */,
     
    2584825851                                5EA3D6DF1C859D7F00300BBB /* MockMediaEndpoint.h in Headers */,
    2584925852                                CDF2B0131820540600F2B424 /* MockMediaPlayerMediaSource.h in Headers */,
     25853                                E377FE4D1DADE16500CDD025 /* NodeConstants.h in Headers */,
    2585025854                                CDF2B0151820540600F2B424 /* MockMediaSourcePrivate.h in Headers */,
    2585125855                                07D6A4F41BED5F8800174146 /* MockRealtimeAudioSource.h in Headers */,
  • trunk/Source/WebCore/bindings/js/JSDOMWrapper.h

    r207013 r207239  
    2323
    2424#include "JSDOMGlobalObject.h"
     25#include "NodeConstants.h"
    2526#include <runtime/JSDestructibleObject.h>
    2627
     
    3031class ScriptExecutionContext;
    3132
    32 static const uint8_t JSDOMWrapperType = JSC::LastJSCObjectType + 1;
    33 static const uint8_t JSNodeType = JSC::LastJSCObjectType + 2;
    34 static const uint8_t JSDocumentWrapperType = JSC::LastJSCObjectType + 3;
    35 static const uint8_t JSElementType = JSC::LastJSCObjectType + 4;
     33// We encode Node type into JSType. The format is the following.
     34// offset | 7 | 6 5 4 | 3 2 1 0  |
     35// value  | 1 | Kind  | NodeType |
     36static const uint8_t JSNodeTypeMask                  = 0b00001111;
     37
     38static const uint8_t JSDOMWrapperType                = 0b10000000;
     39static const uint8_t JSNodeType                      = 0b10010000;
     40static const uint8_t JSTextNodeType                  = JSNodeType | NodeConstants::TEXT_NODE;
     41static const uint8_t JSProcessingInstructionNodeType = JSNodeType | NodeConstants::PROCESSING_INSTRUCTION_NODE;
     42static const uint8_t JSDocumentTypeNodeType          = JSNodeType | NodeConstants::DOCUMENT_TYPE_NODE;
     43static const uint8_t JSDocumentFragmentNodeType      = JSNodeType | NodeConstants::DOCUMENT_FRAGMENT_NODE;
     44static const uint8_t JSDocumentWrapperType           = JSNodeType | NodeConstants::DOCUMENT_NODE;
     45static const uint8_t JSCommentNodeType               = JSNodeType | NodeConstants::COMMENT_NODE;
     46static const uint8_t JSCDATASectionNodeType          = JSNodeType | NodeConstants::CDATA_SECTION_NODE;
     47static const uint8_t JSAttrNodeType                  = JSNodeType | NodeConstants::ATTRIBUTE_NODE;
     48static const uint8_t JSElementType                   = 0b10100000 | NodeConstants::ELEMENT_NODE;
     49
     50static_assert(JSDOMWrapperType > JSC::LastJSCObjectType, "JSC::JSType offers the highest bit.");
     51static_assert(NodeConstants::LastNodeType <= JSNodeTypeMask, "NodeType should be represented in 4bit.");
    3652
    3753class JSDOMObject : public JSC::JSDestructibleObject {
  • trunk/Source/WebCore/bindings/js/JSNodeCustom.h

    r200934 r207239  
    8686}
    8787
     88ALWAYS_INLINE JSC::JSValue JSNode::nodeType(JSC::ExecState&) const
     89{
     90    return JSC::jsNumber(static_cast<uint8_t>(type()) & JSNodeTypeMask);
     91}
     92
    8893} // namespace WebCore
  • trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm

    r207193 r207239  
    11691169    }
    11701170    return $result;
     1171}
     1172
     1173sub GetJSTypeForNode
     1174{
     1175    my ($codeGenerator, $interface) = @_;
     1176
     1177    if ($codeGenerator->InheritsInterface($interface, "Document")) {
     1178        return "JSDocumentWrapperType";
     1179    }
     1180    if ($codeGenerator->InheritsInterface($interface, "DocumentFragment")) {
     1181        return "JSDocumentFragmentNodeType";
     1182    }
     1183    if ($codeGenerator->InheritsInterface($interface, "DocumentType")) {
     1184        return "JSDocumentTypeNodeType";
     1185    }
     1186    if ($codeGenerator->InheritsInterface($interface, "ProcessingInstruction")) {
     1187        return "JSProcessingInstructionNodeType";
     1188    }
     1189    if ($codeGenerator->InheritsInterface($interface, "CDATASection")) {
     1190        return "JSCDATASectionNodeType";
     1191    }
     1192    if ($codeGenerator->InheritsInterface($interface, "Attr")) {
     1193        return "JSAttrNodeType";
     1194    }
     1195    if ($codeGenerator->InheritsInterface($interface, "Comment")) {
     1196        return "JSCommentNodeType";
     1197    }
     1198    if ($codeGenerator->InheritsInterface($interface, "Text")) {
     1199        return "JSTextNodeType";
     1200    }
     1201    if ($codeGenerator->InheritsInterface($interface, "Element")) {
     1202        return "JSElementType";
     1203    }
     1204    return "JSNodeType";
    11711205}
    11721206
     
    13691403    if (IsDOMGlobalObject($interface)) {
    13701404        push(@headerContent, "        return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::GlobalObjectType, StructureFlags), info());\n");
    1371     } elsif ($codeGenerator->InheritsInterface($interface, "Document")) {
    1372         push(@headerContent, "        return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::JSType(JSDocumentWrapperType), StructureFlags), info());\n");
    1373     } elsif ($codeGenerator->InheritsInterface($interface, "Element")) {
    1374         push(@headerContent, "        return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::JSType(JSElementType), StructureFlags), info());\n");
    13751405    } elsif ($codeGenerator->InheritsInterface($interface, "Node")) {
    1376         push(@headerContent, "        return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::JSType(JSNodeType), StructureFlags), info());\n");
     1406        my $type = GetJSTypeForNode($codeGenerator, $interface);
     1407        push(@headerContent, "        return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::JSType($type), StructureFlags), info());\n");
    13771408    } else {
    13781409        push(@headerContent, "        return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info());\n");
     
    16701701            push(@headerContent, "#if ENABLE(JIT)\n");
    16711702            push(@headerContent, "    Ref<JSC::DOMJIT::Patchpoint> checkDOM() override;\n");
    1672             push(@headerContent, "    Ref<JSC::DOMJIT::Patchpoint> callDOM() override;\n");
     1703            push(@headerContent, "    Ref<JSC::DOMJIT::CallDOMPatchpoint> callDOM() override;\n");
    16731704            push(@headerContent, "#endif\n");
    16741705            push(@headerContent, "};\n\n");
  • trunk/Source/WebCore/dom/Node.idl

    r207170 r207239  
    4747    [CEReactions, SetterMayThrowLegacyException] attribute DOMString? nodeValue;
    4848
    49     readonly attribute unsigned short nodeType;
     49    [DOMJIT, CustomGetter] readonly attribute unsigned short nodeType;
    5050    [DOMJIT] readonly attribute Node? parentNode;
    5151    readonly attribute NodeList childNodes;
  • trunk/Source/WebCore/dom/NodeConstants.h

    r207238 r207239  
    2626#pragma once
    2727
    28 #include "DOMJITPatchpoint.h"
    29 #include "PropertySlot.h"
    30 #include "PutPropertySlot.h"
    31 #include "SpeculatedType.h"
     28namespace WebCore {
    3229
    33 namespace JSC { namespace DOMJIT {
     30struct NodeConstants {
     31    enum NodeType {
     32        ELEMENT_NODE = 1,
     33        ATTRIBUTE_NODE = 2,
     34        TEXT_NODE = 3,
     35        CDATA_SECTION_NODE = 4,
     36        PROCESSING_INSTRUCTION_NODE = 7,
     37        COMMENT_NODE = 8,
     38        DOCUMENT_NODE = 9,
     39        DOCUMENT_TYPE_NODE = 10,
     40        DOCUMENT_FRAGMENT_NODE = 11,
     41    };
    3442
    35 class GetterSetter {
    36 public:
    37     typedef PropertySlot::GetValueFunc CustomGetter;
    38     typedef PutPropertySlot::PutValueFunc CustomSetter;
     43    enum DeprecatedNodeType {
     44        ENTITY_REFERENCE_NODE = 5,
     45        ENTITY_NODE = 6,
     46        NOTATION_NODE = 12,
     47    };
    3948
    40     GetterSetter(CustomGetter getter, CustomSetter setter, const ClassInfo* classInfo)
    41         : m_getter(getter)
    42         , m_setter(setter)
    43         , m_thisClassInfo(classInfo)
    44     {
    45     }
    46 
    47     virtual ~GetterSetter() { }
    48 
    49     CustomGetter getter() const { return m_getter; }
    50     CustomSetter setter() const { return m_setter; }
    51     const ClassInfo* thisClassInfo() const { return m_thisClassInfo; }
    52 
    53 #if ENABLE(JIT)
    54     virtual Ref<DOMJIT::Patchpoint> callDOM() = 0;
    55     virtual Ref<DOMJIT::Patchpoint> checkDOM() = 0;
    56 #endif
    57 
    58 private:
    59     CustomGetter m_getter;
    60     CustomSetter m_setter;
    61     const ClassInfo* m_thisClassInfo;
     49    static const uint8_t LastNodeType = NOTATION_NODE;
    6250};
    6351
    64 } }
     52} // namespace WebCore::NodeType
  • trunk/Source/WebCore/domjit/JSNodeDOMJIT.cpp

    r207166 r207239  
    5151
    5252template<typename WrappedNode>
    53 static Ref<DOMJIT::Patchpoint> createCallDOMForOffsetAccess(ptrdiff_t offset, IsContainerGuardRequirement isContainerGuardRequirement)
     53static Ref<DOMJIT::CallDOMPatchpoint> createCallDOMForOffsetAccess(ptrdiff_t offset, IsContainerGuardRequirement isContainerGuardRequirement)
    5454{
    55     Ref<DOMJIT::Patchpoint> patchpoint = DOMJIT::Patchpoint::create();
     55    Ref<DOMJIT::CallDOMPatchpoint> patchpoint = DOMJIT::CallDOMPatchpoint::create();
    5656    patchpoint->numGPScratchRegisters = 1;
    5757    patchpoint->setGenerator([=](CCallHelpers& jit, const DOMJIT::PatchpointParams& params) {
     
    9999}
    100100
    101 Ref<DOMJIT::Patchpoint> NodeFirstChildDOMJIT::callDOM()
     101Ref<DOMJIT::CallDOMPatchpoint> NodeFirstChildDOMJIT::callDOM()
    102102{
    103103    return createCallDOMForOffsetAccess<Node>(CAST_OFFSET(Node*, ContainerNode*) + ContainerNode::firstChildMemoryOffset(), IsContainerGuardRequirement::Required);
     
    110110}
    111111
    112 Ref<DOMJIT::Patchpoint> NodeLastChildDOMJIT::callDOM()
     112Ref<DOMJIT::CallDOMPatchpoint> NodeLastChildDOMJIT::callDOM()
    113113{
    114114    return createCallDOMForOffsetAccess<Node>(CAST_OFFSET(Node*, ContainerNode*) + ContainerNode::lastChildMemoryOffset(), IsContainerGuardRequirement::Required);
     
    121121}
    122122
    123 Ref<DOMJIT::Patchpoint> NodeNextSiblingDOMJIT::callDOM()
     123Ref<DOMJIT::CallDOMPatchpoint> NodeNextSiblingDOMJIT::callDOM()
    124124{
    125125    return createCallDOMForOffsetAccess<Node>(Node::nextSiblingMemoryOffset(), IsContainerGuardRequirement::NotRequired);
     
    132132}
    133133
    134 Ref<DOMJIT::Patchpoint> NodePreviousSiblingDOMJIT::callDOM()
     134Ref<DOMJIT::CallDOMPatchpoint> NodePreviousSiblingDOMJIT::callDOM()
    135135{
    136136    return createCallDOMForOffsetAccess<Node>(Node::previousSiblingMemoryOffset(), IsContainerGuardRequirement::NotRequired);
     
    143143}
    144144
    145 Ref<DOMJIT::Patchpoint> NodeParentNodeDOMJIT::callDOM()
     145Ref<DOMJIT::CallDOMPatchpoint> NodeParentNodeDOMJIT::callDOM()
    146146{
    147147    return createCallDOMForOffsetAccess<ContainerNode>(Node::parentNodeMemoryOffset(), IsContainerGuardRequirement::NotRequired);
     148}
     149
     150// Node#nodeType.
     151Ref<DOMJIT::Patchpoint> NodeNodeTypeDOMJIT::checkDOM()
     152{
     153    return checkNode();
     154}
     155
     156Ref<DOMJIT::CallDOMPatchpoint> NodeNodeTypeDOMJIT::callDOM()
     157{
     158    Ref<DOMJIT::CallDOMPatchpoint> patchpoint = DOMJIT::CallDOMPatchpoint::create();
     159    patchpoint->requireGlobalObject = false;
     160    patchpoint->setGenerator([=](CCallHelpers& jit, const DOMJIT::PatchpointParams& params) {
     161        JSValueRegs result = params[0].jsValueRegs();
     162        GPRReg node = params[1].gpr();
     163        jit.load8(CCallHelpers::Address(node, JSC::JSCell::typeInfoTypeOffset()), result.payloadGPR());
     164        jit.and32(CCallHelpers::TrustedImm32(JSNodeTypeMask), result.payloadGPR());
     165        jit.boxInt32(result.payloadGPR(), result);
     166        return CCallHelpers::JumpList();
     167    });
     168    return patchpoint;
    148169}
    149170
Note: See TracChangeset for help on using the changeset viewer.