Changeset 207239 in webkit
- Timestamp:
- Oct 12, 2016 1:47:51 PM (8 years ago)
- Location:
- trunk
- Files:
-
- 1 added
- 22 edited
- 2 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r207238 r207239 1 2016-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 1 10 2016-10-12 Chris Dumez <cdumez@apple.com> 2 11 -
trunk/Source/JavaScriptCore/ChangeLog
r207235 r207239 1 2016-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 1 46 2016-10-12 Keith Miller <keith_miller@apple.com> 2 47 -
trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
r207222 r207239 2097 2097 E33F50871B8449EF00413856 /* JSInternalPromiseConstructor.lut.h in Headers */ = {isa = PBXBuildFile; fileRef = E33F50861B8449EF00413856 /* JSInternalPromiseConstructor.lut.h */; }; 2098 2098 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, ); }; }; 2099 2100 E355F3521B7DC85300C50DC5 /* ModuleLoaderPrototype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E355F3501B7DC85300C50DC5 /* ModuleLoaderPrototype.cpp */; }; 2100 2101 E355F3531B7DC85300C50DC5 /* ModuleLoaderPrototype.h in Headers */ = {isa = PBXBuildFile; fileRef = E355F3511B7DC85300C50DC5 /* ModuleLoaderPrototype.h */; }; … … 4400 4401 E33F50881B844A1A00413856 /* InternalPromiseConstructor.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = InternalPromiseConstructor.js; sourceTree = "<group>"; }; 4401 4402 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>"; }; 4402 4404 E355F3501B7DC85300C50DC5 /* ModuleLoaderPrototype.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ModuleLoaderPrototype.cpp; sourceTree = "<group>"; }; 4403 4405 E355F3511B7DC85300C50DC5 /* ModuleLoaderPrototype.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ModuleLoaderPrototype.h; sourceTree = "<group>"; }; … … 7196 7198 isa = PBXGroup; 7197 7199 children = ( 7200 E3555B891DAE03A200F36921 /* DOMJITCallDOMPatchpoint.h */, 7198 7201 E3FF752F1D9CEA1200C7E16D /* DOMJITGetterSetter.h */, 7199 7202 E3C08E3B1DA41B7B0039478F /* DOMJITPatchpoint.h */, … … 8073 8076 BC18C4270E16F5CD00B34460 /* JSString.h in Headers */, 8074 8077 86E85539111B9968001AF51E /* JSStringBuilder.h in Headers */, 8078 E3555B8A1DAE03A500F36921 /* DOMJITCallDOMPatchpoint.h in Headers */, 8075 8079 70EC0EC31AA0D7DA00B6AAFA /* JSStringIterator.h in Headers */, 8076 8080 0F070A471D543A8B006E7232 /* CellContainer.h in Headers */, -
trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r207060 r207239 2688 2688 addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(variant.structureSet())), thisNode); 2689 2689 2690 Ref<DOMJIT::Patchpoint> checkDOMPatchpoint = domJIT->checkDOM(); 2691 m_graph.m_domJITPatchpoints.append(checkDOMPatchpoint.ptr()); 2690 2692 // 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 } 2694 2701 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))); 2696 2703 return true; 2697 2704 } -
trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
r206853 r207239 1704 1704 break; 1705 1705 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 } 1710 1714 1711 1715 #if !ASSERT_DISABLED -
trunk/Source/JavaScriptCore/dfg/DFGGraph.h
r206525 r207239 905 905 HashSet<std::pair<JSObject*, PropertyOffset>> m_safeToLoad; 906 906 HashMap<PropertyTypeKey, InferredType::Descriptor> m_inferredTypes; 907 Vector<RefPtr<DOMJIT::Patchpoint>> m_domJITPatchpoints; 907 908 std::unique_ptr<Dominators> m_dominators; 908 909 std::unique_ptr<PrePostNumbering> m_prePostNumbering; -
trunk/Source/JavaScriptCore/dfg/DFGNode.h
r206846 r207239 60 60 61 61 namespace DOMJIT { 62 class GetterSetter; 62 class Patchpoint; 63 class CallDOMPatchpoint; 63 64 } 64 65 … … 2315 2316 } 2316 2317 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*>(); 2326 2338 } 2327 2339 -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
r207166 r207239 7131 7131 void SpeculativeJIT::compileCallDOM(Node* node) 7132 7132 { 7133 Ref<DOMJIT::Patchpoint> patchpoint = node->domJIT()->callDOM();7133 DOMJIT::CallDOMPatchpoint* patchpoint = node->callDOMPatchpoint(); 7134 7134 7135 7135 Vector<GPRReg> gpScratch; … … 7137 7137 Vector<DOMJIT::Value> regs; 7138 7138 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));7143 7139 JSValueRegsTemporary result(this); 7144 7145 7140 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())); 7152 7154 7153 7155 Vector<GPRTemporary> gpTempraries; 7154 7156 Vector<FPRTemporary> fpTempraries; 7155 allocateTemporaryRegistersForPatchpoint(this, gpTempraries, fpTempraries, gpScratch, fpScratch, patchpoint.get());7157 allocateTemporaryRegistersForPatchpoint(this, gpTempraries, fpTempraries, gpScratch, fpScratch, *patchpoint); 7156 7158 DOMJITPatchpointParams params(this, WTFMove(regs), WTFMove(gpScratch), WTFMove(fpScratch)); 7157 7159 patchpoint->generator()->run(m_jit, params); … … 7162 7164 { 7163 7165 // 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(); 7165 7167 7166 7168 Vector<GPRReg> gpScratch; … … 7174 7176 Vector<GPRTemporary> gpTempraries; 7175 7177 Vector<FPRTemporary> fpTempraries; 7176 allocateTemporaryRegistersForPatchpoint(this, gpTempraries, fpTempraries, gpScratch, fpScratch, patchpoint.get());7178 allocateTemporaryRegistersForPatchpoint(this, gpTempraries, fpTempraries, gpScratch, fpScratch, *patchpoint); 7177 7179 7178 7180 DOMJITPatchpointParams params(this, WTFMove(regs), WTFMove(gpScratch), WTFMove(fpScratch)); -
trunk/Source/JavaScriptCore/domjit/DOMJITCallDOMPatchpoint.h
r207238 r207239 26 26 #pragma once 27 27 28 #if ENABLE(JIT) 29 28 30 #include "DOMJITPatchpoint.h" 29 #include "PropertySlot.h" 30 #include "PutPropertySlot.h" 31 #include "SpeculatedType.h" 31 #include "RegisterSet.h" 32 32 33 33 namespace JSC { namespace DOMJIT { 34 34 35 class GetterSetter{35 class CallDOMPatchpoint : public Patchpoint { 36 36 public: 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() 44 38 { 39 return adoptRef(*new CallDOMPatchpoint()); 45 40 } 46 41 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 }; 57 47 58 48 private: 59 CustomGetter m_getter; 60 CustomSetter m_setter; 61 const ClassInfo* m_thisClassInfo; 49 CallDOMPatchpoint() = default; 62 50 }; 63 51 64 52 } } 53 54 #endif -
trunk/Source/JavaScriptCore/domjit/DOMJITGetterSetter.h
r206779 r207239 26 26 #pragma once 27 27 28 #include "DOMJIT Patchpoint.h"28 #include "DOMJITCallDOMPatchpoint.h" 29 29 #include "PropertySlot.h" 30 30 #include "PutPropertySlot.h" … … 52 52 53 53 #if ENABLE(JIT) 54 virtual Ref<DOMJIT:: Patchpoint> callDOM() = 0;54 virtual Ref<DOMJIT::CallDOMPatchpoint> callDOM() = 0; 55 55 virtual Ref<DOMJIT::Patchpoint> checkDOM() = 0; 56 56 #endif -
trunk/Source/JavaScriptCore/domjit/DOMJITPatchpoint.h
r206779 r207239 63 63 uint8_t numFPScratchRegisters { 0 }; 64 64 65 pr ivate:65 protected: 66 66 Patchpoint() = default; 67 67 68 private: 68 69 RefPtr<PatchpointGenerator> m_generator; 69 70 }; -
trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp
r207166 r207239 8725 8725 LValue cell = lowCell(m_node->child1()); 8726 8726 8727 RefPtr<DOMJIT::Patchpoint> domJIT = m_node->domJIT()->checkDOM();8727 DOMJIT::Patchpoint* domJIT = m_node->checkDOMPatchpoint(); 8728 8728 8729 8729 PatchpointValue* patchpoint = m_out.patchpoint(Void); … … 8770 8770 void compileCallDOM() 8771 8771 { 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 8776 8787 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); 8779 8791 patchpoint->append(m_tagMask, ValueRep::reg(GPRInfo::tagMaskRegister)); 8780 8792 patchpoint->append(m_tagTypeNumber, ValueRep::reg(GPRInfo::tagTypeNumberRegister)); … … 8787 8799 State* state = &m_ftlState; 8788 8800 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();8791 8801 patchpoint->setGenerator( 8792 8802 [=] (CCallHelpers& jit, const StackmapGenerationParams& params) { … … 8797 8807 Vector<DOMJIT::Value> regs; 8798 8808 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; 8801 8810 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)); 8804 8814 8805 8815 for (unsigned i = 0; i < domJIT->numGPScratchRegisters; ++i) -
trunk/Source/JavaScriptCore/jsc.cpp
r206899 r207239 621 621 } 622 622 623 Ref<DOMJIT:: Patchpoint> callDOM() override623 Ref<DOMJIT::CallDOMPatchpoint> callDOM() override 624 624 { 625 Ref<DOMJIT::Patchpoint> patchpoint = DOMJIT::Patchpoint::create(); 625 Ref<DOMJIT::CallDOMPatchpoint> patchpoint = DOMJIT::CallDOMPatchpoint::create(); 626 patchpoint->requireGlobalObject = false; 626 627 patchpoint->setGenerator([=](CCallHelpers& jit, const DOMJIT::PatchpointParams& params) { 627 628 JSValueRegs results = params[0].jsValueRegs(); 628 GPRReg dom = params[ 2].gpr();629 GPRReg dom = params[1].gpr(); 629 630 630 631 params.addSlowPathCall(jit.jump(), jit, static_cast<EncodedJSValue(*)(ExecState*, void*)>([](ExecState*, void* pointer) { -
trunk/Source/JavaScriptCore/llint/LLIntData.cpp
r206344 r207239 162 162 STATIC_ASSERT(ArrayType == 31); 163 163 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); 174 174 STATIC_ASSERT(MasqueradesAsUndefined == 1); 175 175 STATIC_ASSERT(ImplementsDefaultHasInstance == 2); -
trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm
r206853 r207239 351 351 const ArrayType = 31 352 352 const DerivedArrayType = 32 353 const ProxyObjectType = 116353 const ProxyObjectType = 49 354 354 355 355 # The typed array types need to be numbered in a particular order because of the manually written 356 356 # switch statement in get_by_val and put_by_val. 357 const Int8ArrayType = 100358 const Int16ArrayType = 101359 const Int32ArrayType = 102360 const Uint8ArrayType = 103361 const Uint8ClampedArrayType = 104362 const Uint16ArrayType = 105363 const Uint32ArrayType = 106364 const Float32ArrayType = 107365 const Float64ArrayType = 108357 const Int8ArrayType = 33 358 const Int16ArrayType = 34 359 const Int32ArrayType = 35 360 const Uint8ArrayType = 36 361 const Uint8ClampedArrayType = 37 362 const Uint16ArrayType = 38 363 const Uint32ArrayType = 39 364 const Float32ArrayType = 40 365 const Float64ArrayType = 41 366 366 367 367 const FirstArrayType = Int8ArrayType -
trunk/Source/JavaScriptCore/runtime/JSType.h
r206525 r207239 66 66 DerivedArrayType, 67 67 68 Int8ArrayType = 100,68 Int8ArrayType, 69 69 Int16ArrayType, 70 70 Int32ArrayType, … … 88 88 89 89 LastJSCObjectType = JSSetType, 90 MaxJSType = 0b11111111, 90 91 }; 91 92 92 COMPILE_ASSERT(sizeof(JSType) == sizeof(uint8_t), sizeof_jstype_is_one_byte); 93 static_assert(sizeof(JSType) == sizeof(uint8_t), "sizeof(JSType) is one byte."); 94 static_assert(LastJSCObjectType < 128, "The highest bit is reserved for embedder's extension."); 93 95 94 96 } // namespace JSC -
trunk/Source/WebCore/ChangeLog
r207238 r207239 1 2016-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 1 53 2016-10-12 Chris Dumez <cdumez@apple.com> 2 54 -
trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj
r207151 r207239 6144 6144 E3150EA61DA7219000194012 /* JSNodeDOMJIT.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E3AFA9641DA6E908002861BD /* JSNodeDOMJIT.cpp */; }; 6145 6145 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, ); }; }; 6146 6147 E38838981BAD145F00D62EE3 /* ScriptModuleLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E38838941BAD145F00D62EE3 /* ScriptModuleLoader.cpp */; }; 6147 6148 E38838991BAD145F00D62EE3 /* ScriptModuleLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = E38838951BAD145F00D62EE3 /* ScriptModuleLoader.h */; }; … … 13785 13786 E3B2F0E81D7F35EC00B0C9D1 /* LoadableScriptClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LoadableScriptClient.h; sourceTree = "<group>"; }; 13786 13787 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>"; }; 13787 13789 E3FA38611D716E7600AA5950 /* PendingScriptClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PendingScriptClient.h; sourceTree = "<group>"; }; 13788 13790 E401C27417CE53EC00C41A35 /* ElementIteratorAssertions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ElementIteratorAssertions.h; sourceTree = "<group>"; }; … … 23276 23278 E43105B716750F0C00DB2FB8 /* NodeTraversal.cpp */, 23277 23279 E43105BA16750F1600DB2FB8 /* NodeTraversal.h */, 23280 E3D049931DADC04500718F3C /* NodeConstants.h */, 23278 23281 9382AAB10D8C386100F357A6 /* NodeWithIndex.h */, 23279 23282 E46B41F81CB24E70008F11DE /* NoEventDispatchAssertion.h */, … … 25848 25851 5EA3D6DF1C859D7F00300BBB /* MockMediaEndpoint.h in Headers */, 25849 25852 CDF2B0131820540600F2B424 /* MockMediaPlayerMediaSource.h in Headers */, 25853 E377FE4D1DADE16500CDD025 /* NodeConstants.h in Headers */, 25850 25854 CDF2B0151820540600F2B424 /* MockMediaSourcePrivate.h in Headers */, 25851 25855 07D6A4F41BED5F8800174146 /* MockRealtimeAudioSource.h in Headers */, -
trunk/Source/WebCore/bindings/js/JSDOMWrapper.h
r207013 r207239 23 23 24 24 #include "JSDOMGlobalObject.h" 25 #include "NodeConstants.h" 25 26 #include <runtime/JSDestructibleObject.h> 26 27 … … 30 31 class ScriptExecutionContext; 31 32 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 | 36 static const uint8_t JSNodeTypeMask = 0b00001111; 37 38 static const uint8_t JSDOMWrapperType = 0b10000000; 39 static const uint8_t JSNodeType = 0b10010000; 40 static const uint8_t JSTextNodeType = JSNodeType | NodeConstants::TEXT_NODE; 41 static const uint8_t JSProcessingInstructionNodeType = JSNodeType | NodeConstants::PROCESSING_INSTRUCTION_NODE; 42 static const uint8_t JSDocumentTypeNodeType = JSNodeType | NodeConstants::DOCUMENT_TYPE_NODE; 43 static const uint8_t JSDocumentFragmentNodeType = JSNodeType | NodeConstants::DOCUMENT_FRAGMENT_NODE; 44 static const uint8_t JSDocumentWrapperType = JSNodeType | NodeConstants::DOCUMENT_NODE; 45 static const uint8_t JSCommentNodeType = JSNodeType | NodeConstants::COMMENT_NODE; 46 static const uint8_t JSCDATASectionNodeType = JSNodeType | NodeConstants::CDATA_SECTION_NODE; 47 static const uint8_t JSAttrNodeType = JSNodeType | NodeConstants::ATTRIBUTE_NODE; 48 static const uint8_t JSElementType = 0b10100000 | NodeConstants::ELEMENT_NODE; 49 50 static_assert(JSDOMWrapperType > JSC::LastJSCObjectType, "JSC::JSType offers the highest bit."); 51 static_assert(NodeConstants::LastNodeType <= JSNodeTypeMask, "NodeType should be represented in 4bit."); 36 52 37 53 class JSDOMObject : public JSC::JSDestructibleObject { -
trunk/Source/WebCore/bindings/js/JSNodeCustom.h
r200934 r207239 86 86 } 87 87 88 ALWAYS_INLINE JSC::JSValue JSNode::nodeType(JSC::ExecState&) const 89 { 90 return JSC::jsNumber(static_cast<uint8_t>(type()) & JSNodeTypeMask); 91 } 92 88 93 } // namespace WebCore -
trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm
r207193 r207239 1169 1169 } 1170 1170 return $result; 1171 } 1172 1173 sub 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"; 1171 1205 } 1172 1206 … … 1369 1403 if (IsDOMGlobalObject($interface)) { 1370 1404 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");1375 1405 } 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"); 1377 1408 } else { 1378 1409 push(@headerContent, " return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info());\n"); … … 1670 1701 push(@headerContent, "#if ENABLE(JIT)\n"); 1671 1702 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"); 1673 1704 push(@headerContent, "#endif\n"); 1674 1705 push(@headerContent, "};\n\n"); -
trunk/Source/WebCore/dom/Node.idl
r207170 r207239 47 47 [CEReactions, SetterMayThrowLegacyException] attribute DOMString? nodeValue; 48 48 49 readonly attribute unsigned short nodeType;49 [DOMJIT, CustomGetter] readonly attribute unsigned short nodeType; 50 50 [DOMJIT] readonly attribute Node? parentNode; 51 51 readonly attribute NodeList childNodes; -
trunk/Source/WebCore/dom/NodeConstants.h
r207238 r207239 26 26 #pragma once 27 27 28 #include "DOMJITPatchpoint.h" 29 #include "PropertySlot.h" 30 #include "PutPropertySlot.h" 31 #include "SpeculatedType.h" 28 namespace WebCore { 32 29 33 namespace JSC { namespace DOMJIT { 30 struct 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 }; 34 42 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 }; 39 48 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; 62 50 }; 63 51 64 } }52 } // namespace WebCore::NodeType -
trunk/Source/WebCore/domjit/JSNodeDOMJIT.cpp
r207166 r207239 51 51 52 52 template<typename WrappedNode> 53 static Ref<DOMJIT:: Patchpoint> createCallDOMForOffsetAccess(ptrdiff_t offset, IsContainerGuardRequirement isContainerGuardRequirement)53 static Ref<DOMJIT::CallDOMPatchpoint> createCallDOMForOffsetAccess(ptrdiff_t offset, IsContainerGuardRequirement isContainerGuardRequirement) 54 54 { 55 Ref<DOMJIT:: Patchpoint> patchpoint = DOMJIT::Patchpoint::create();55 Ref<DOMJIT::CallDOMPatchpoint> patchpoint = DOMJIT::CallDOMPatchpoint::create(); 56 56 patchpoint->numGPScratchRegisters = 1; 57 57 patchpoint->setGenerator([=](CCallHelpers& jit, const DOMJIT::PatchpointParams& params) { … … 99 99 } 100 100 101 Ref<DOMJIT:: Patchpoint> NodeFirstChildDOMJIT::callDOM()101 Ref<DOMJIT::CallDOMPatchpoint> NodeFirstChildDOMJIT::callDOM() 102 102 { 103 103 return createCallDOMForOffsetAccess<Node>(CAST_OFFSET(Node*, ContainerNode*) + ContainerNode::firstChildMemoryOffset(), IsContainerGuardRequirement::Required); … … 110 110 } 111 111 112 Ref<DOMJIT:: Patchpoint> NodeLastChildDOMJIT::callDOM()112 Ref<DOMJIT::CallDOMPatchpoint> NodeLastChildDOMJIT::callDOM() 113 113 { 114 114 return createCallDOMForOffsetAccess<Node>(CAST_OFFSET(Node*, ContainerNode*) + ContainerNode::lastChildMemoryOffset(), IsContainerGuardRequirement::Required); … … 121 121 } 122 122 123 Ref<DOMJIT:: Patchpoint> NodeNextSiblingDOMJIT::callDOM()123 Ref<DOMJIT::CallDOMPatchpoint> NodeNextSiblingDOMJIT::callDOM() 124 124 { 125 125 return createCallDOMForOffsetAccess<Node>(Node::nextSiblingMemoryOffset(), IsContainerGuardRequirement::NotRequired); … … 132 132 } 133 133 134 Ref<DOMJIT:: Patchpoint> NodePreviousSiblingDOMJIT::callDOM()134 Ref<DOMJIT::CallDOMPatchpoint> NodePreviousSiblingDOMJIT::callDOM() 135 135 { 136 136 return createCallDOMForOffsetAccess<Node>(Node::previousSiblingMemoryOffset(), IsContainerGuardRequirement::NotRequired); … … 143 143 } 144 144 145 Ref<DOMJIT:: Patchpoint> NodeParentNodeDOMJIT::callDOM()145 Ref<DOMJIT::CallDOMPatchpoint> NodeParentNodeDOMJIT::callDOM() 146 146 { 147 147 return createCallDOMForOffsetAccess<ContainerNode>(Node::parentNodeMemoryOffset(), IsContainerGuardRequirement::NotRequired); 148 } 149 150 // Node#nodeType. 151 Ref<DOMJIT::Patchpoint> NodeNodeTypeDOMJIT::checkDOM() 152 { 153 return checkNode(); 154 } 155 156 Ref<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; 148 169 } 149 170
Note: See TracChangeset
for help on using the changeset viewer.