Changeset 206846 in webkit
- Timestamp:
- Oct 5, 2016 10:20:10 PM (8 years ago)
- Location:
- trunk
- Files:
-
- 5 added
- 34 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/JSTests/ChangeLog
r206804 r206846 1 2016-10-05 Yusuke Suzuki <utatane.tea@gmail.com> 2 3 [DOMJIT] Add initial CheckDOM and CallDOM implementations 4 https://bugs.webkit.org/show_bug.cgi?id=162941 5 6 Reviewed by Filip Pizlo. 7 8 * stress/domjit-getter-poly.js: Added. 9 (shouldBe): 10 (access): 11 * stress/domjit-getter-proto.js: Added. 12 (shouldBe): 13 (access): 14 * stress/domjit-getter-super-poly.js: Added. 15 (shouldBe): 16 (access): 17 * stress/domjit-getter.js: Added. 18 (shouldBe): 19 (access): 20 1 21 2016-10-04 Saam Barati <sbarati@apple.com> 2 22 -
trunk/Source/JavaScriptCore/ChangeLog
r206844 r206846 1 2016-10-05 Yusuke Suzuki <utatane.tea@gmail.com> 2 3 [DOMJIT] Add initial CheckDOM and CallDOM implementations 4 https://bugs.webkit.org/show_bug.cgi?id=162941 5 6 Reviewed by Filip Pizlo. 7 8 This patch implements a prototype of DOMJIT accelerated getter. 9 We add two new DFG nodes, CheckDOM and CallDOM. 10 11 CheckDOM is used to filter inappropriate |this| object for DOM getter. Its functionality 12 is equivalent to jsDynamicCast's Check. You can use like "CheckDOM, @1, JSNode::info()", 13 and this CheckDOM incurs a BadType exit if the class of the given @1 is not a subclass of 14 JSNode::info(). 15 16 CallDOM is used to emit actual DOM operations. It takes GlobalObject and checked DOM 17 object. And it returns JSValue as its result. 18 19 Both CheckDOM and CallDOM can take a DOMJIT::Patchpoint. This is somewhat code snippet 20 generator, and is injectable to DFG and FTL. DFG and FTL set up registers correctly 21 according to DOMJIT::Patchpoint's requirement and invoke this patchpoint generator to emit code. 22 While CallDOM always requires a patchpoint, ideally CheckDOM does not require it since 23 isSubclassOf check can be implemented in DFG / FTL side. However, some classes have a 24 faster way to query isSubclassOf. For example, JSNode in WebCore introduces a special 25 JSType to optimize this query. CheckDOM's patchpoint gives us a chance to emit special 26 faster code for such a case. 27 28 By leveraging above nodes, we can construct DOMJIT accelerated getter. When DFG recognizes the 29 given getter call is CustomGetter and it has DOMJIT::GetterSetter information, DFG emits the above nodes. 30 We implemented a prototype in jsc.cpp shell as DOMJITGetter to test the functionality. 31 32 Notes about the future extensions. 33 34 1. Currently, we do not allow CallDOM to emit any function calls. This will be extended by 35 adding `addSlowPathCall` functionality to DOMJIT::Patchpoint later. Interesting thing is that 36 we need to create an abstraction over DFG slow path call and FTL slow path call! 37 38 2. CheckDOM is not handled in DFGTypeCheckHoistingPhase yet. And we have a chance to merge several CheckDOM into one. 39 For example, given CheckDOM A and CheckDOM B to the same target. If A is subclass of B, we can merge them to CheckDOM A. 40 41 * JavaScriptCore.xcodeproj/project.pbxproj: 42 * b3/B3Effects.h: 43 (JSC::B3::Effects::forCheck): 44 * b3/B3Value.cpp: 45 (JSC::B3::Value::effects): 46 * bytecode/GetByIdStatus.cpp: 47 (JSC::GetByIdStatus::computeForStubInfoWithoutExitSiteFeedback): 48 (JSC::GetByIdStatus::makesCalls): 49 (JSC::GetByIdStatus::dump): 50 * bytecode/GetByIdStatus.h: 51 (JSC::GetByIdStatus::GetByIdStatus): 52 (JSC::GetByIdStatus::isCustom): 53 (JSC::GetByIdStatus::takesSlowPath): 54 (JSC::GetByIdStatus::isSimple): Deleted. 55 * bytecode/SpeculatedType.cpp: 56 (JSC::speculationFromClassInfo): 57 * dfg/DFGAbstractInterpreter.h: 58 (JSC::DFG::AbstractInterpreter::filterClassInfo): 59 * dfg/DFGAbstractInterpreterInlines.h: 60 (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects): 61 (JSC::DFG::AbstractInterpreter<AbstractStateType>::filterClassInfo): 62 * dfg/DFGAbstractValue.cpp: 63 (JSC::DFG::AbstractValue::filterClassInfo): 64 * dfg/DFGAbstractValue.h: 65 * dfg/DFGByteCodeParser.cpp: 66 (JSC::DFG::ByteCodeParser::handleDOMJITGetter): 67 (JSC::DFG::ByteCodeParser::handleGetById): 68 * dfg/DFGClobberize.h: 69 (JSC::DFG::clobberize): 70 * dfg/DFGConstantFoldingPhase.cpp: 71 (JSC::DFG::ConstantFoldingPhase::foldConstants): 72 * dfg/DFGDoesGC.cpp: 73 (JSC::DFG::doesGC): 74 * dfg/DFGFixupPhase.cpp: 75 (JSC::DFG::FixupPhase::fixupNode): 76 * dfg/DFGNode.h: 77 (JSC::DFG::Node::hasHeapPrediction): 78 (JSC::DFG::Node::hasDOMJIT): 79 (JSC::DFG::Node::domJIT): 80 (JSC::DFG::Node::hasClassInfo): 81 (JSC::DFG::Node::classInfo): 82 (JSC::DFG::Node::OpInfoWrapper::OpInfoWrapper): 83 (JSC::DFG::Node::OpInfoWrapper::operator=): 84 * dfg/DFGNodeType.h: 85 * dfg/DFGOpInfo.h: 86 (JSC::DFG::OpInfo::OpInfo): 87 * dfg/DFGPredictionPropagationPhase.cpp: 88 * dfg/DFGSafeToExecute.h: 89 (JSC::DFG::safeToExecute): 90 * dfg/DFGSpeculativeJIT.cpp: 91 (JSC::DFG::allocateTemporaryRegistersForPatchpoint): 92 (JSC::DFG::SpeculativeJIT::compileCallDOM): 93 (JSC::DFG::SpeculativeJIT::compileCheckDOM): 94 * dfg/DFGSpeculativeJIT.h: 95 * dfg/DFGSpeculativeJIT32_64.cpp: 96 (JSC::DFG::SpeculativeJIT::compile): 97 * dfg/DFGSpeculativeJIT64.cpp: 98 (JSC::DFG::SpeculativeJIT::compile): 99 * dfg/DFGStructureAbstractValue.cpp: 100 (JSC::DFG::StructureAbstractValue::filterClassInfoSlow): 101 (JSC::DFG::StructureAbstractValue::isSubClassOf): 102 * dfg/DFGStructureAbstractValue.h: 103 (JSC::DFG::StructureAbstractValue::filterClassInfo): 104 (JSC::DFG::StructureAbstractValue::filter): Deleted. 105 * domjit/DOMJITPatchpointParams.h: Copied from Source/JavaScriptCore/dfg/DFGOpInfo.h. 106 (JSC::DOMJIT::PatchpointParams::~PatchpointParams): 107 (JSC::DOMJIT::PatchpointParams::size): 108 (JSC::DOMJIT::PatchpointParams::at): 109 (JSC::DOMJIT::PatchpointParams::operator[]): 110 (JSC::DOMJIT::PatchpointParams::gpScratch): 111 (JSC::DOMJIT::PatchpointParams::fpScratch): 112 (JSC::DOMJIT::PatchpointParams::PatchpointParams): 113 * domjit/DOMJITReg.h: Added. 114 (JSC::DOMJIT::Reg::Reg): 115 (JSC::DOMJIT::Reg::isGPR): 116 (JSC::DOMJIT::Reg::isFPR): 117 (JSC::DOMJIT::Reg::isJSValueRegs): 118 (JSC::DOMJIT::Reg::gpr): 119 (JSC::DOMJIT::Reg::fpr): 120 (JSC::DOMJIT::Reg::jsValueRegs): 121 * ftl/FTLCapabilities.cpp: 122 (JSC::FTL::canCompile): 123 * ftl/FTLLowerDFGToB3.cpp: 124 (JSC::FTL::DFG::LowerDFGToB3::compileNode): 125 (JSC::FTL::DFG::LowerDFGToB3::compileCheckDOM): 126 (JSC::FTL::DFG::LowerDFGToB3::compileCallDOM): 127 (JSC::FTL::DFG::LowerDFGToB3::compileUnreachable): Deleted. 128 * jit/AssemblyHelpers.h: 129 * jsc.cpp: 130 (WTF::DOMJITNode::DOMJITNode): 131 (WTF::DOMJITNode::createStructure): 132 (WTF::DOMJITNode::create): 133 (WTF::DOMJITNode::value): 134 (WTF::DOMJITNode::offsetOfValue): 135 (WTF::DOMJITGetter::DOMJITGetter): 136 (WTF::DOMJITGetter::createStructure): 137 (WTF::DOMJITGetter::create): 138 (WTF::DOMJITGetter::DOMJITNodeDOMJIT::DOMJITNodeDOMJIT): 139 (WTF::DOMJITGetter::domJITNodeGetterSetter): 140 (WTF::DOMJITGetter::finishCreation): 141 (WTF::DOMJITGetter::customGetter): 142 (GlobalObject::finishCreation): 143 (functionCreateDOMJITNodeObject): 144 (functionCreateDOMJITGetterObject): 145 1 146 2016-10-05 Yusuke Suzuki <utatane.tea@gmail.com> 2 147 -
trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
r206779 r206846 2099 2099 E3794E751B77EB97005543AE /* ModuleAnalyzer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E3794E731B77EB97005543AE /* ModuleAnalyzer.cpp */; }; 2100 2100 E3794E761B77EB97005543AE /* ModuleAnalyzer.h in Headers */ = {isa = PBXBuildFile; fileRef = E3794E741B77EB97005543AE /* ModuleAnalyzer.h */; settings = {ATTRIBUTES = (Private, ); }; }; 2101 E37AD83C1DA4928600F3D412 /* DOMJITPatchpointParams.h in Headers */ = {isa = PBXBuildFile; fileRef = E37AD83A1DA4928000F3D412 /* DOMJITPatchpointParams.h */; settings = {ATTRIBUTES = (Private, ); }; }; 2102 E37AD83D1DA4928600F3D412 /* DOMJITReg.h in Headers */ = {isa = PBXBuildFile; fileRef = E37AD83B1DA4928000F3D412 /* DOMJITReg.h */; settings = {ATTRIBUTES = (Private, ); }; }; 2101 2103 E3963CEE1B73F75000EB4CE5 /* NodesAnalyzeModule.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E3963CEC1B73F75000EB4CE5 /* NodesAnalyzeModule.cpp */; }; 2102 2104 E39D45F51D39005600B3B377 /* InterpreterInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = E39D9D841D39000600667282 /* InterpreterInlines.h */; settings = {ATTRIBUTES = (Private, ); }; }; … … 4398 4400 E3794E731B77EB97005543AE /* ModuleAnalyzer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ModuleAnalyzer.cpp; sourceTree = "<group>"; }; 4399 4401 E3794E741B77EB97005543AE /* ModuleAnalyzer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ModuleAnalyzer.h; sourceTree = "<group>"; }; 4402 E37AD83A1DA4928000F3D412 /* DOMJITPatchpointParams.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMJITPatchpointParams.h; sourceTree = "<group>"; }; 4403 E37AD83B1DA4928000F3D412 /* DOMJITReg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMJITReg.h; sourceTree = "<group>"; }; 4400 4404 E3963CEC1B73F75000EB4CE5 /* NodesAnalyzeModule.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NodesAnalyzeModule.cpp; sourceTree = "<group>"; }; 4401 4405 E39D9D841D39000600667282 /* InterpreterInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InterpreterInlines.h; sourceTree = "<group>"; }; … … 7184 7188 E3FF752F1D9CEA1200C7E16D /* DOMJITGetterSetter.h */, 7185 7189 E3C08E3B1DA41B7B0039478F /* DOMJITPatchpoint.h */, 7190 E37AD83A1DA4928000F3D412 /* DOMJITPatchpointParams.h */, 7191 E37AD83B1DA4928000F3D412 /* DOMJITReg.h */, 7186 7192 ); 7187 7193 path = domjit; … … 7601 7607 0FFB921C16D02F110055A5DB /* DFGOSRExitCompilationInfo.h in Headers */, 7602 7608 0FC0977114693AF500CF2442 /* DFGOSRExitCompiler.h in Headers */, 7609 E37AD83D1DA4928600F3D412 /* DOMJITReg.h in Headers */, 7603 7610 0F7025AA1714B0FC00382C0E /* DFGOSRExitCompilerCommon.h in Headers */, 7604 7611 0F392C8A1B46188400844728 /* DFGOSRExitFuzz.h in Headers */, … … 8429 8436 79B1788E1D399B8000B1A567 /* JITMathICForwards.h in Headers */, 8430 8437 451539B912DC994500EF7AC4 /* Yarr.h in Headers */, 8438 E37AD83C1DA4928600F3D412 /* DOMJITPatchpointParams.h in Headers */, 8431 8439 86704B8512DBA33700A9FE7B /* YarrInterpreter.h in Headers */, 8432 8440 86704B8712DBA33700A9FE7B /* YarrJIT.h in Headers */, -
trunk/Source/JavaScriptCore/b3/B3Effects.h
r206739 r206846 79 79 } 80 80 81 static Effects forCheck() 82 { 83 Effects result; 84 result.exitsSideways = true; 85 // The program could read anything after exiting, and it's on us to declare this. 86 result.reads = HeapRange::top(); 87 return result; 88 } 89 81 90 bool mustExecute() const 82 91 { -
trunk/Source/JavaScriptCore/b3/B3Value.cpp
r206739 r206846 615 615 case CheckMul: 616 616 case Check: 617 result.exitsSideways = true; 618 // The program could read anything after exiting, and it's on us to declare this. 619 result.reads = HeapRange::top(); 617 result = Effects::forCheck(); 620 618 break; 621 619 case Upsilon: -
trunk/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp
r206844 r206846 247 247 if (!domJIT) 248 248 return GetByIdStatus(slowPathState, true); 249 result.m_state = Custom; 249 250 break; 250 251 } … … 264 265 if (!result.appendVariant(variant)) 265 266 return GetByIdStatus(slowPathState, true); 267 268 if (domJIT) { 269 // Give up when cutom accesses are not merged into one. 270 if (result.numVariants() != 1) 271 return GetByIdStatus(slowPathState, true); 272 } else { 273 // Give up when custom access and simple access are mixed. 274 if (result.m_state == Custom) 275 return GetByIdStatus(slowPathState, true); 276 } 266 277 break; 267 278 } } … … 363 374 case NoInformation: 364 375 case TakesSlowPath: 376 case Custom: 365 377 return false; 366 378 case Simple: … … 404 416 out.print("Simple"); 405 417 break; 418 case Custom: 419 out.print("Custom"); 420 break; 406 421 case TakesSlowPath: 407 422 out.print("TakesSlowPath"); -
trunk/Source/JavaScriptCore/bytecode/GetByIdStatus.h
r206525 r206846 45 45 Simple, // It's cached for a simple access to a known object property with 46 46 // a possible structure chain and a possible specific value. 47 Custom, // It's cached for a custom accessor with a possible structure chain. 47 48 TakesSlowPath, // It's known to often take slow path. 48 49 MakesCalls // It's known to take paths that make calls. … … 65 66 , m_wasSeenInJIT(wasSeenInJIT) 66 67 { 67 ASSERT((state == Simple ) == variant.isSet());68 ASSERT((state == Simple || state == Custom) == variant.isSet()); 68 69 m_variants.append(variant); 69 70 } … … 83 84 bool operator!() const { return !isSet(); } 84 85 bool isSimple() const { return m_state == Simple; } 86 bool isCustom() const { return m_state == Custom; } 85 87 86 88 size_t numVariants() const { return m_variants.size(); } … … 89 91 const GetByIdVariant& operator[](size_t index) const { return at(index); } 90 92 91 bool takesSlowPath() const { return m_state == TakesSlowPath || m_state == MakesCalls ; }93 bool takesSlowPath() const { return m_state == TakesSlowPath || m_state == MakesCalls || m_state == Custom; } 92 94 bool makesCalls() const; 93 95 -
trunk/Source/JavaScriptCore/bytecode/SpeculatedType.cpp
r206267 r206846 354 354 SpeculatedType speculationFromClassInfo(const ClassInfo* classInfo) 355 355 { 356 if (classInfo == JSString::info()) 357 return SpecString; 358 359 if (classInfo == Symbol::info()) 360 return SpecSymbol; 361 356 362 if (classInfo == JSFinalObject::info()) 357 363 return SpecFinalObject; … … 386 392 if (isTypedView(classInfo->typedArrayStorageType)) 387 393 return speculationFromTypedArrayType(classInfo->typedArrayStorageType); 394 395 if (classInfo->isSubClassOf(JSArray::info())) 396 return SpecDerivedArray; 388 397 389 398 if (classInfo->isSubClassOf(JSObject::info())) -
trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreter.h
r206525 r206846 135 135 } 136 136 137 template<typename T> 138 FiltrationResult filterClassInfo(T node, const ClassInfo* classInfo) 139 { 140 return filterClassInfo(forNode(node), classInfo); 141 } 142 137 143 FiltrationResult filter(AbstractValue&, const StructureSet&, SpeculatedType admittedTypes = SpecNone); 138 144 FiltrationResult filterArrayModes(AbstractValue&, ArrayModes); 139 145 FiltrationResult filter(AbstractValue&, SpeculatedType); 140 146 FiltrationResult filterByValue(AbstractValue&, FrozenValue); 147 FiltrationResult filterClassInfo(AbstractValue&, const ClassInfo*); 141 148 142 149 PhiChildren* phiChildren() { return m_phiChildren.get(); } -
trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
r206804 r206846 30 30 #include "ArrayConstructor.h" 31 31 #include "DFGAbstractInterpreter.h" 32 #include "DOMJITGetterSetter.h" 32 33 #include "GetByIdStatus.h" 33 34 #include "GetterSetter.h" … … 2268 2269 case ReallocatePropertyStorage: 2269 2270 forNode(node).clear(); // The result is not a JS value. 2271 break; 2272 case CheckDOM: { 2273 JSValue constant = forNode(node->child1()).value(); 2274 if (constant) { 2275 if (constant.isCell() && constant.asCell()->inherits(node->classInfo())) { 2276 m_state.setFoundConstants(true); 2277 ASSERT(constant); 2278 break; 2279 } 2280 } 2281 2282 AbstractValue& value = forNode(node->child1()); 2283 2284 if (value.m_structure.isSubClassOf(node->classInfo())) 2285 m_state.setFoundConstants(true); 2286 2287 filterClassInfo(value, node->classInfo()); 2288 break; 2289 } 2290 case CallDOM: 2291 clobberWorld(node->origin.semantic, clobberLimit); 2292 forNode(node).makeBytecodeTop(); 2270 2293 break; 2271 2294 case CheckArray: { … … 3057 3080 3058 3081 template<typename AbstractStateType> 3082 FiltrationResult AbstractInterpreter<AbstractStateType>::filterClassInfo( 3083 AbstractValue& value, const ClassInfo* classInfo) 3084 { 3085 if (value.filterClassInfo(m_graph, classInfo) == FiltrationOK) 3086 return FiltrationOK; 3087 m_state.setIsValid(false); 3088 return Contradiction; 3089 } 3090 3091 template<typename AbstractStateType> 3059 3092 void AbstractInterpreter<AbstractStateType>::executeDoubleUnaryOpEffects(Node* node, double(*equivalentFunction)(double)) 3060 3093 { -
trunk/Source/JavaScriptCore/dfg/DFGAbstractValue.cpp
r205254 r206846 307 307 } 308 308 309 FiltrationResult AbstractValue::filterClassInfo(Graph& graph, const ClassInfo* classInfo) 310 { 311 // FIXME: AI should track ClassInfo to leverage hierarchical class information. 312 // https://bugs.webkit.org/show_bug.cgi?id=162989 313 if (isClear()) 314 return FiltrationOK; 315 316 m_type &= speculationFromClassInfo(classInfo); 317 m_structure.filterClassInfo(classInfo); 318 319 m_structure.filter(m_type); 320 321 filterArrayModesByType(); 322 filterValueByType(); 323 return normalizeClarity(graph); 324 } 325 309 326 FiltrationResult AbstractValue::filter(SpeculatedType type) 310 327 { -
trunk/Source/JavaScriptCore/dfg/DFGAbstractValue.h
r206525 r206846 308 308 FiltrationResult filterByValue(const FrozenValue& value); 309 309 FiltrationResult filter(const AbstractValue&); 310 FiltrationResult filterClassInfo(Graph&, const ClassInfo*); 310 311 311 312 FiltrationResult filter(Graph&, const InferredType::Descriptor&); -
trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
r206804 r206846 220 220 Node* handlePutByOffset(Node* base, unsigned identifier, PropertyOffset, const InferredType::Descriptor&, Node* value); 221 221 Node* handleGetByOffset(SpeculatedType, Node* base, unsigned identifierNumber, PropertyOffset, const InferredType::Descriptor&, NodeType = GetByOffset); 222 bool handleDOMJITGetter(int resultOperand, const GetByIdVariant&, Node* thisNode, SpeculatedType prediction); 222 223 223 224 // Create a presence ObjectPropertyCondition based on some known offset and structure set. Does not … … 2674 2675 } 2675 2676 2677 bool ByteCodeParser::handleDOMJITGetter(int resultOperand, const GetByIdVariant& variant, Node* thisNode, SpeculatedType prediction) 2678 { 2679 if (!variant.domJIT()) 2680 return false; 2681 2682 DOMJIT::GetterSetter* domJIT = variant.domJIT(); 2683 2684 // We do not need to actually look up CustomGetterSetter here. Checking Structures or registering watchpoints are enough, 2685 // since replacement of CustomGetterSetter always incurs Structure transition. 2686 if (!check(variant.conditionSet())) 2687 return false; 2688 addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(variant.structureSet())), thisNode); 2689 2690 // 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. 2694 addVarArgChild(thisNode); 2695 set(VirtualRegister(resultOperand), addToGraph(Node::VarArg, CallDOM, OpInfo(domJIT), OpInfo(prediction))); 2696 return true; 2697 } 2698 2676 2699 template<typename ChecksFunctor> 2677 2700 bool ByteCodeParser::handleTypedArrayConstructor( … … 3267 3290 else 3268 3291 getById = TryGetById; 3292 3293 // Special path for custom accessors since custom's offset does not have any meanings. 3294 // So, this is completely different from Simple one. But we have a chance to optimize it when we use DOMJIT. 3295 if (getByIdStatus.isCustom()) { 3296 ASSERT(getByIdStatus.numVariants() == 1); 3297 ASSERT(!getByIdStatus.makesCalls()); 3298 GetByIdVariant variant = getByIdStatus[0]; 3299 ASSERT(variant.domJIT()); 3300 if (handleDOMJITGetter(destinationOperand, variant, base, prediction)) { 3301 if (m_graph.compilation()) 3302 m_graph.compilation()->noticeInlinedGetById(); 3303 return; 3304 } 3305 } 3269 3306 3270 3307 ASSERT(type == AccessType::Get || !getByIdStatus.makesCalls()); -
trunk/Source/JavaScriptCore/dfg/DFGClobberize.h
r206804 r206846 886 886 return; 887 887 888 case CheckDOM: 889 def(PureValue(node, node->classInfo())); 890 return; 891 892 case CallDOM: 893 read(World); 894 write(Heap); 895 return; 896 888 897 case Arrayify: 889 898 case ArrayifyToStructure: -
trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp
r203895 r206846 159 159 break; 160 160 } 161 162 case CheckDOM: { 163 JSValue constant = m_state.forNode(node->child1()).value(); 164 if (constant) { 165 if (constant.isCell() && constant.asCell()->inherits(node->classInfo())) { 166 m_interpreter.execute(indexInBlock); 167 node->remove(); 168 eliminated = true; 169 break; 170 } 171 } 172 173 AbstractValue& value = m_state.forNode(node->child1()); 174 175 if (value.m_structure.isSubClassOf(node->classInfo())) { 176 m_interpreter.execute(indexInBlock); 177 node->remove(); 178 eliminated = true; 179 break; 180 } 181 break; 182 } 161 183 162 184 case GetIndexedPropertyStorage: { -
trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp
r206804 r206846 119 119 case GetExecutable: 120 120 case GetButterfly: 121 case CallDOM: 122 case CheckDOM: 121 123 case CheckArray: 122 124 case GetScope: -
trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
r206804 r206846 1699 1699 break; 1700 1700 } 1701 1702 case CheckDOM: 1703 fixEdge<CellUse>(node->child1()); 1704 break; 1705 1706 case CallDOM: 1707 fixEdge<KnownCellUse>(m_graph.varArgChild(node, 0)); // GlobalObject. 1708 fixEdge<CellUse>(m_graph.varArgChild(node, 1)); // DOM. 1709 break; 1701 1710 1702 1711 #if !ASSERT_DISABLED -
trunk/Source/JavaScriptCore/dfg/DFGNode.h
r206779 r206846 1447 1447 case ToNumber: 1448 1448 case LoadFromJSMapBucket: 1449 case CallDOM: 1449 1450 return true; 1450 1451 default: … … 2313 2314 return m_opInfo.as<BasicBlockLocation*>(); 2314 2315 } 2315 2316 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*>(); 2326 } 2327 2328 bool hasClassInfo() const 2329 { 2330 return op() == CheckDOM; 2331 } 2332 2333 const ClassInfo* classInfo() 2334 { 2335 return m_opInfo2.as<const ClassInfo*>(); 2336 } 2337 2316 2338 Node* replacement() const 2317 2339 { … … 2393 2415 u.pointer = pointer; 2394 2416 } 2417 OpInfoWrapper(const void* constPointer) 2418 { 2419 u.int64 = 0; 2420 u.constPointer = constPointer; 2421 } 2395 2422 OpInfoWrapper& operator=(uint32_t int32) 2396 2423 { … … 2416 2443 return *this; 2417 2444 } 2445 OpInfoWrapper& operator=(const void* constPointer) 2446 { 2447 u.int64 = 0; 2448 u.constPointer = constPointer; 2449 return *this; 2450 } 2418 2451 template <typename T> 2419 ALWAYS_INLINE auto as() const -> typename std::enable_if<std::is_pointer<T>::value , T>::type2452 ALWAYS_INLINE auto as() const -> typename std::enable_if<std::is_pointer<T>::value && !std::is_const<typename std::remove_pointer<T>::type>::value, T>::type 2420 2453 { 2421 2454 return static_cast<T>(u.pointer); 2455 } 2456 template <typename T> 2457 ALWAYS_INLINE auto as() const -> typename std::enable_if<std::is_pointer<T>::value && std::is_const<typename std::remove_pointer<T>::type>::value, T>::type 2458 { 2459 return static_cast<T>(u.constPointer); 2422 2460 } 2423 2461 template <typename T> … … 2435 2473 uint64_t int64; 2436 2474 void* pointer; 2475 const void* constPointer; 2437 2476 } u; 2438 2477 }; -
trunk/Source/JavaScriptCore/dfg/DFGNodeType.h
r206804 r206846 399 399 \ 400 400 macro(ToLowerCase, NodeResultJS) \ 401 /* Nodes for DOM JIT */\ 402 macro(CheckDOM, NodeMustGenerate) \ 403 macro(CallDOM, NodeResultJS | NodeMustGenerate | NodeHasVarArgs) \ 401 404 402 405 // This enum generates a monotonically increasing id for all Node types, -
trunk/Source/JavaScriptCore/dfg/DFGOpInfo.h
r206525 r206846 44 44 #endif 45 45 explicit OpInfo(void* value) : m_value(static_cast<uint64_t>(reinterpret_cast<uintptr_t>(value))) { } 46 explicit OpInfo(const void* value) : m_value(static_cast<uint64_t>(reinterpret_cast<uintptr_t>(value))) { } 46 47 uint64_t m_value; 47 48 }; -
trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
r206804 r206846 700 700 case GetFromArguments: 701 701 case LoadFromJSMapBucket: 702 case ToNumber: { 702 case ToNumber: 703 case CallDOM: { 703 704 setPrediction(m_currentNode->getHeapPrediction()); 704 705 break; … … 824 825 break; 825 826 } 827 828 case CheckDOM: 829 break; 826 830 827 831 case CallObjectConstructor: { -
trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h
r206804 r206846 219 219 case GetExecutable: 220 220 case GetButterfly: 221 case CallDOM: 222 case CheckDOM: 221 223 case CheckArray: 222 224 case Arrayify: -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
r206841 r206846 39 39 #include "DFGSaneStringGetByValSlowPathGenerator.h" 40 40 #include "DFGSlowPathGenerator.h" 41 #include "DOMJITPatchpoint.h" 42 #include "DOMJITPatchpointParams.h" 41 43 #include "DirectArguments.h" 42 44 #include "JITAddGenerator.h" … … 7112 7114 } 7113 7115 7116 static void allocateTemporaryRegistersForPatchpoint(SpeculativeJIT* jit, Vector<GPRTemporary>& gpHolders, Vector<FPRTemporary>& fpHolders, Vector<GPRReg>& gpScratch, Vector<FPRReg>& fpScratch, DOMJIT::Patchpoint& patchpoint) 7117 { 7118 for (unsigned i = 0; i < patchpoint.numGPScratchRegisters; ++i) { 7119 GPRTemporary temporary(jit); 7120 gpScratch.append(temporary.gpr()); 7121 gpHolders.append(WTFMove(temporary)); 7122 } 7123 7124 for (unsigned i = 0; i < patchpoint.numFPScratchRegisters; ++i) { 7125 FPRTemporary temporary(jit); 7126 fpScratch.append(temporary.fpr()); 7127 fpHolders.append(WTFMove(temporary)); 7128 } 7129 } 7130 7131 void SpeculativeJIT::compileCallDOM(Node* node) 7132 { 7133 Ref<DOMJIT::Patchpoint> patchpoint = node->domJIT()->callDOM(); 7134 7135 Vector<GPRReg> gpScratch; 7136 Vector<FPRReg> fpScratch; 7137 Vector<DOMJIT::Reg> regs; 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 JSValueRegsTemporary result(this); 7144 7145 regs.append(result.regs()); 7146 regs.append(globalObject.gpr()); 7147 regs.append(base.gpr()); 7148 #if USE(JSVALUE64) 7149 regs.append(static_cast<GPRReg>(GPRInfo::tagMaskRegister)); 7150 regs.append(static_cast<GPRReg>(GPRInfo::tagTypeNumberRegister)); 7151 #endif 7152 7153 Vector<GPRTemporary> gpTempraries; 7154 Vector<FPRTemporary> fpTempraries; 7155 allocateTemporaryRegistersForPatchpoint(this, gpTempraries, fpTempraries, gpScratch, fpScratch, patchpoint.get()); 7156 DOMJIT::PatchpointParams params(WTFMove(regs), WTFMove(gpScratch), WTFMove(fpScratch)); 7157 patchpoint->generator()->run(m_jit, params); 7158 jsValueResult(result.regs(), node); 7159 } 7160 7161 void SpeculativeJIT::compileCheckDOM(Node* node) 7162 { 7163 // FIXME: We can add the fallback implementation that inlines jsDynamicCast things here. 7164 Ref<DOMJIT::Patchpoint> patchpoint = node->domJIT()->checkDOM(); 7165 7166 Vector<GPRReg> gpScratch; 7167 Vector<FPRReg> fpScratch; 7168 Vector<DOMJIT::Reg> regs; 7169 7170 SpeculateCellOperand base(this, node->child1()); 7171 GPRReg baseGPR = base.gpr(); 7172 regs.append(baseGPR); 7173 7174 Vector<GPRTemporary> gpTempraries; 7175 Vector<FPRTemporary> fpTempraries; 7176 allocateTemporaryRegistersForPatchpoint(this, gpTempraries, fpTempraries, gpScratch, fpScratch, patchpoint.get()); 7177 7178 DOMJIT::PatchpointParams params(WTFMove(regs), WTFMove(gpScratch), WTFMove(fpScratch)); 7179 CCallHelpers::JumpList failureCases = patchpoint->generator()->run(m_jit, params); 7180 speculationCheck(BadType, JSValueSource::unboxedCell(baseGPR), node->child1(), failureCases); 7181 noResult(node); 7182 } 7183 7114 7184 GPRReg SpeculativeJIT::temporaryRegisterForPutByVal(GPRTemporary& temporary, ArrayMode arrayMode) 7115 7185 { -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
r206804 r206846 2544 2544 void compileReallocatePropertyStorage(Node*); 2545 2545 void compileGetButterfly(Node*); 2546 void compileCallDOM(Node*); 2547 void compileCheckDOM(Node*); 2546 2548 2547 2549 #if USE(JSVALUE32_64) -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
r206804 r206846 5436 5436 } 5437 5437 5438 case CallDOM: 5439 compileCallDOM(node); 5440 break; 5441 5442 case CheckDOM: 5443 compileCheckDOM(node); 5444 break; 5445 5438 5446 case Unreachable: 5439 5447 unreachable(node); -
trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
r206804 r206846 5567 5567 break; 5568 5568 5569 case CallDOM: 5570 compileCallDOM(node); 5571 break; 5572 5573 case CheckDOM: 5574 compileCheckDOM(node); 5575 break; 5576 5569 5577 #if ENABLE(FTL_JIT) 5570 5578 case CheckTierUpInLoop: { -
trunk/Source/JavaScriptCore/dfg/DFGStructureAbstractValue.cpp
r198364 r206846 259 259 } 260 260 261 void StructureAbstractValue::filterClassInfoSlow(const ClassInfo* classInfo) 262 { 263 ASSERT(!isTop()); 264 m_set.genericFilter( 265 [&] (Structure* structure) { 266 return structure->classInfo()->isSubClassOf(classInfo); 267 }); 268 } 269 261 270 bool StructureAbstractValue::contains(Structure* structure) const 262 271 { … … 320 329 } 321 330 331 bool StructureAbstractValue::isSubClassOf(const ClassInfo* classInfo) const 332 { 333 if (isInfinite()) 334 return false; 335 336 // Note taht this function returns true if the structure set is empty. 337 for (const Structure* structure : m_set) { 338 if (!structure->classInfo()->isSubClassOf(classInfo)) 339 return false; 340 } 341 return true; 342 } 343 322 344 bool StructureAbstractValue::equalsSlow(const StructureAbstractValue& other) const 323 345 { -
trunk/Source/JavaScriptCore/dfg/DFGStructureAbstractValue.h
r206525 r206846 164 164 filterSlow(type); 165 165 } 166 167 ALWAYS_INLINE void filterClassInfo(const ClassInfo* classInfo) 168 { 169 if (isNeitherClearNorTop()) 170 filterClassInfoSlow(classInfo); 171 } 166 172 167 173 ALWAYS_INLINE bool operator==(const StructureAbstractValue& other) const … … 232 238 bool overlaps(const StructureSet& other) const; 233 239 bool overlaps(const StructureAbstractValue& other) const; 240 241 bool isSubClassOf(const ClassInfo*) const; 234 242 235 243 void validateReferences(const TrackedReferences&) const; … … 242 250 243 251 void filterSlow(SpeculatedType type); 252 void filterClassInfoSlow(const ClassInfo*); 244 253 bool mergeSlow(const StructureAbstractValue& other); 245 254 -
trunk/Source/JavaScriptCore/domjit/DOMJITPatchpointParams.h
r206844 r206846 21 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 24 */ 25 25 26 26 #pragma once 27 27 28 #i nclude <wtf/StdLibExtras.h>28 #if ENABLE(JIT) 29 29 30 #if ENABLE(DFG_JIT) 30 #include "CCallHelpers.h" 31 #include "DOMJITReg.h" 32 #include "RegisterSet.h" 31 33 32 namespace JSC { namespace D FG{34 namespace JSC { namespace DOMJIT { 33 35 34 // This type used in passing an immediate argument to Node constructor; 35 // distinguishes an immediate value (typically an index into a CodeBlock data structure - 36 // a constant index, argument, or identifier) from a Node*. 37 struct OpInfo { 38 OpInfo() : m_value(0) { } 39 explicit OpInfo(int32_t value) : m_value(static_cast<uint64_t>(value)) { } 40 explicit OpInfo(uint32_t value) : m_value(static_cast<uint64_t>(value)) { } 41 explicit OpInfo(uint64_t value) : m_value(static_cast<uint64_t>(value)) { } 42 #if OS(DARWIN) 43 explicit OpInfo(uintptr_t value) : m_value(static_cast<uint64_t>(value)) { } 44 #endif 45 explicit OpInfo(void* value) : m_value(static_cast<uint64_t>(reinterpret_cast<uintptr_t>(value))) { } 46 uint64_t m_value; 36 class PatchpointParams { 37 WTF_MAKE_NONCOPYABLE(PatchpointParams); 38 public: 39 virtual ~PatchpointParams() { } 40 41 unsigned size() const { return m_regs.size(); } 42 const Reg& at(unsigned index) const { return m_regs[index]; } 43 const Reg& operator[](unsigned index) const { return at(index); } 44 45 GPRReg gpScratch(unsigned index) const { return m_gpScratch[index]; } 46 FPRReg fpScratch(unsigned index) const { return m_fpScratch[index]; } 47 48 PatchpointParams(Vector<Reg>&& regs, Vector<GPRReg>&& gpScratch, Vector<FPRReg>&& fpScratch) 49 : m_regs(WTFMove(regs)) 50 , m_gpScratch(WTFMove(gpScratch)) 51 , m_fpScratch(WTFMove(fpScratch)) 52 { 53 } 54 55 private: 56 57 Vector<Reg> m_regs; 58 Vector<GPRReg> m_gpScratch; 59 Vector<FPRReg> m_fpScratch; 47 60 }; 48 61 49 } } // namespace JSC::DFG62 } } 50 63 51 #endif // ENABLE(DFG_JIT)64 #endif -
trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp
r206804 r206846 267 267 case DefineAccessorProperty: 268 268 case ToLowerCase: 269 case CheckDOM: 270 case CallDOM: 269 271 // These are OK. 270 272 break; -
trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp
r206804 r206846 45 45 #include "DFGOSRAvailabilityAnalysisPhase.h" 46 46 #include "DFGOSRExitFuzz.h" 47 #include "DOMJITPatchpoint.h" 48 #include "DOMJITPatchpointParams.h" 47 49 #include "DirectArguments.h" 48 50 #include "FTLAbstractHeapRepository.h" … … 1046 1048 case ToLowerCase: 1047 1049 compileToLowerCase(); 1050 break; 1051 case CheckDOM: 1052 compileCheckDOM(); 1053 break; 1054 case CallDOM: 1055 compileCallDOM(); 1048 1056 break; 1049 1057 … … 8712 8720 8713 8721 crash(); 8722 } 8723 8724 void compileCheckDOM() 8725 { 8726 LValue cell = lowCell(m_node->child1()); 8727 8728 RefPtr<DOMJIT::Patchpoint> domJIT = m_node->domJIT()->checkDOM(); 8729 8730 PatchpointValue* patchpoint = m_out.patchpoint(Void); 8731 patchpoint->appendSomeRegister(cell); 8732 patchpoint->numGPScratchRegisters = domJIT->numGPScratchRegisters; 8733 patchpoint->numFPScratchRegisters = domJIT->numFPScratchRegisters; 8734 8735 State* state = &m_ftlState; 8736 NodeOrigin origin = m_origin; 8737 unsigned osrExitArgumentOffset = patchpoint->numChildren(); 8738 OSRExitDescriptor* exitDescriptor = appendOSRExitDescriptor(jsValueValue(cell), m_node->child1().node()); 8739 patchpoint->appendColdAnys(buildExitArguments(exitDescriptor, origin.forExit, jsValueValue(cell))); 8740 8741 patchpoint->setGenerator( 8742 [=] (CCallHelpers& jit, const StackmapGenerationParams& params) { 8743 Vector<GPRReg> gpScratch; 8744 Vector<FPRReg> fpScratch; 8745 Vector<DOMJIT::Reg> regs; 8746 8747 regs.append(params[0].gpr()); 8748 8749 for (unsigned i = 0; i < domJIT->numGPScratchRegisters; ++i) 8750 gpScratch.append(params.gpScratch(i)); 8751 8752 for (unsigned i = 0; i < domJIT->numFPScratchRegisters; ++i) 8753 fpScratch.append(params.fpScratch(i)); 8754 8755 RefPtr<OSRExitHandle> handle = exitDescriptor->emitOSRExitLater(*state, BadType, origin, params, osrExitArgumentOffset); 8756 8757 DOMJIT::PatchpointParams domJITParams(WTFMove(regs), WTFMove(gpScratch), WTFMove(fpScratch)); 8758 CCallHelpers::JumpList failureCases = domJIT->generator()->run(jit, domJITParams); 8759 8760 jit.addLinkTask([=] (LinkBuffer& linkBuffer) { 8761 linkBuffer.link(failureCases, linkBuffer.locationOf(handle->label)); 8762 }); 8763 }); 8764 patchpoint->effects = Effects::forCheck(); 8765 } 8766 8767 void compileCallDOM() 8768 { 8769 LValue globalObject = lowCell(m_graph.varArgChild(m_node, 0)); 8770 LValue cell = lowCell(m_graph.varArgChild(m_node, 1)); 8771 8772 RefPtr<DOMJIT::Patchpoint> domJIT = m_node->domJIT()->callDOM(); 8773 PatchpointValue* patchpoint = m_out.patchpoint(Int64); 8774 patchpoint->appendSomeRegister(globalObject); 8775 patchpoint->appendSomeRegister(cell); 8776 patchpoint->append(m_tagMask, ValueRep::lateReg(GPRInfo::tagMaskRegister)); 8777 patchpoint->append(m_tagTypeNumber, ValueRep::lateReg(GPRInfo::tagTypeNumberRegister)); 8778 RefPtr<PatchpointExceptionHandle> exceptionHandle = preparePatchpointForExceptions(patchpoint); 8779 patchpoint->clobber(RegisterSet::macroScratchRegisters()); 8780 patchpoint->numGPScratchRegisters = domJIT->numGPScratchRegisters; 8781 patchpoint->numFPScratchRegisters = domJIT->numFPScratchRegisters; 8782 8783 patchpoint->setGenerator( 8784 [=] (CCallHelpers& jit, const StackmapGenerationParams& params) { 8785 Vector<GPRReg> gpScratch; 8786 Vector<FPRReg> fpScratch; 8787 Vector<DOMJIT::Reg> regs; 8788 8789 // FIXME: patchpoint should have a way to tell this can reuse "base" register. 8790 // Teaching DFG about DOMJIT::Patchpoint clobber information is nice. 8791 regs.append(JSValueRegs(params[0].gpr())); 8792 regs.append(params[1].gpr()); 8793 regs.append(params[2].gpr()); 8794 regs.append(params[3].gpr()); 8795 regs.append(params[4].gpr()); 8796 8797 for (unsigned i = 0; i < domJIT->numGPScratchRegisters; ++i) 8798 gpScratch.append(params.gpScratch(i)); 8799 8800 for (unsigned i = 0; i < domJIT->numFPScratchRegisters; ++i) 8801 fpScratch.append(params.fpScratch(i)); 8802 8803 Box<CCallHelpers::JumpList> exceptions = exceptionHandle->scheduleExitCreation(params)->jumps(jit); 8804 8805 DOMJIT::PatchpointParams domJITParams(WTFMove(regs), WTFMove(gpScratch), WTFMove(fpScratch)); 8806 domJIT->generator()->run(jit, domJITParams); 8807 }); 8808 patchpoint->effects = Effects::forCall(); 8809 setJSValue(patchpoint); 8714 8810 } 8715 8811 -
trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h
r206555 r206846 1210 1210 enum ExceptionCheckKind { NormalExceptionCheck, InvertedExceptionCheck }; 1211 1211 enum ExceptionJumpWidth { NormalJumpWidth, FarJumpWidth }; 1212 J ump emitExceptionCheck(1212 JS_EXPORT_PRIVATE Jump emitExceptionCheck( 1213 1213 ExceptionCheckKind = NormalExceptionCheck, ExceptionJumpWidth = NormalJumpWidth); 1214 J ump emitNonPatchableExceptionCheck();1214 JS_EXPORT_PRIVATE Jump emitNonPatchableExceptionCheck(); 1215 1215 1216 1216 #if ENABLE(SAMPLING_COUNTERS) -
trunk/Source/JavaScriptCore/jsc.cpp
r206653 r206846 29 29 #include "CodeBlock.h" 30 30 #include "Completion.h" 31 #include "DOMJITGetterSetter.h" 32 #include "DOMJITPatchpoint.h" 33 #include "DOMJITPatchpointParams.h" 31 34 #include "Disassembler.h" 32 35 #include "Exception.h" … … 73 76 #include <wtf/CurrentTime.h> 74 77 #include <wtf/MainThread.h> 78 #include <wtf/NeverDestroyed.h> 75 79 #include <wtf/StringPrintStream.h> 76 80 #include <wtf/text/StringBuilder.h> … … 538 542 }; 539 543 544 class DOMJITNode : public JSNonFinalObject { 545 public: 546 DOMJITNode(VM& vm, Structure* structure) 547 : Base(vm, structure) 548 { 549 } 550 551 DECLARE_INFO; 552 typedef JSNonFinalObject Base; 553 static const unsigned StructureFlags = Base::StructureFlags; 554 555 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) 556 { 557 return Structure::create(vm, globalObject, prototype, TypeInfo(JSC::JSType(LastJSCObjectType + 1), StructureFlags), info()); 558 } 559 560 static DOMJITNode* create(VM& vm, Structure* structure) 561 { 562 DOMJITNode* getter = new (NotNull, allocateCell<DOMJITNode>(vm.heap, sizeof(DOMJITNode))) DOMJITNode(vm, structure); 563 getter->finishCreation(vm); 564 return getter; 565 } 566 567 int32_t value() const 568 { 569 return m_value; 570 } 571 572 static ptrdiff_t offsetOfValue() { return OBJECT_OFFSETOF(DOMJITNode, m_value); } 573 574 private: 575 int32_t m_value { 42 }; 576 }; 577 578 class DOMJITGetter : public DOMJITNode { 579 public: 580 DOMJITGetter(VM& vm, Structure* structure) 581 : Base(vm, structure) 582 { 583 } 584 585 DECLARE_INFO; 586 typedef DOMJITNode Base; 587 static const unsigned StructureFlags = Base::StructureFlags; 588 589 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) 590 { 591 return Structure::create(vm, globalObject, prototype, TypeInfo(JSC::JSType(LastJSCObjectType + 1), StructureFlags), info()); 592 } 593 594 static DOMJITGetter* create(VM& vm, Structure* structure) 595 { 596 DOMJITGetter* getter = new (NotNull, allocateCell<DOMJITGetter>(vm.heap, sizeof(DOMJITGetter))) DOMJITGetter(vm, structure); 597 getter->finishCreation(vm); 598 return getter; 599 } 600 601 class DOMJITNodeDOMJIT : public DOMJIT::GetterSetter { 602 public: 603 DOMJITNodeDOMJIT() 604 : DOMJIT::GetterSetter(DOMJITGetter::customGetter, nullptr, DOMJITNode::info()) 605 { 606 } 607 608 Ref<DOMJIT::Patchpoint> checkDOM() override 609 { 610 Ref<DOMJIT::Patchpoint> patchpoint = DOMJIT::Patchpoint::create(); 611 patchpoint->setGenerator([=](CCallHelpers& jit, const DOMJIT::PatchpointParams& params) { 612 CCallHelpers::JumpList failureCases; 613 failureCases.append(jit.branch8( 614 CCallHelpers::NotEqual, 615 CCallHelpers::Address(params[0].gpr(), JSCell::typeInfoTypeOffset()), 616 CCallHelpers::TrustedImm32(JSC::JSType(LastJSCObjectType + 1)))); 617 return failureCases; 618 }); 619 return patchpoint; 620 } 621 622 Ref<DOMJIT::Patchpoint> callDOM() override 623 { 624 Ref<DOMJIT::Patchpoint> patchpoint = DOMJIT::Patchpoint::create(); 625 patchpoint->setGenerator([=](CCallHelpers& jit, const DOMJIT::PatchpointParams& params) { 626 JSValueRegs results = params[0].jsValueRegs(); 627 GPRReg dom = params[2].gpr(); 628 629 jit.load32(CCallHelpers::Address(dom, DOMJITNode::offsetOfValue()), results.payloadGPR()); 630 jit.boxInt32(results.payloadGPR(), results); 631 return CCallHelpers::JumpList(); 632 }); 633 return patchpoint; 634 } 635 }; 636 637 static DOMJIT::GetterSetter* domJITNodeGetterSetter() 638 { 639 static NeverDestroyed<DOMJITNodeDOMJIT> graph; 640 return &graph.get(); 641 } 642 643 private: 644 void finishCreation(VM& vm) 645 { 646 Base::finishCreation(vm); 647 DOMJIT::GetterSetter* domJIT = domJITNodeGetterSetter(); 648 CustomGetterSetter* customGetterSetter = CustomGetterSetter::create(vm, domJIT->getter(), domJIT->setter(), domJIT); 649 putDirectCustomAccessor(vm, Identifier::fromString(&vm, "customGetter"), customGetterSetter, ReadOnly | CustomAccessor); 650 } 651 652 static EncodedJSValue customGetter(ExecState* exec, EncodedJSValue thisValue, PropertyName) 653 { 654 VM& vm = exec->vm(); 655 auto scope = DECLARE_THROW_SCOPE(vm); 656 657 DOMJITNode* thisObject = jsDynamicCast<DOMJITNode*>(JSValue::decode(thisValue)); 658 if (!thisObject) 659 return throwVMTypeError(exec, scope); 660 return JSValue::encode(jsNumber(thisObject->value())); 661 } 662 }; 540 663 541 664 const ClassInfo Element::s_info = { "Element", &Base::s_info, 0, CREATE_METHOD_TABLE(Element) }; … … 544 667 const ClassInfo ImpureGetter::s_info = { "ImpureGetter", &Base::s_info, 0, CREATE_METHOD_TABLE(ImpureGetter) }; 545 668 const ClassInfo CustomGetter::s_info = { "CustomGetter", &Base::s_info, 0, CREATE_METHOD_TABLE(CustomGetter) }; 669 const ClassInfo DOMJITNode::s_info = { "DOMJITNode", &Base::s_info, 0, CREATE_METHOD_TABLE(DOMJITNode) }; 670 const ClassInfo DOMJITGetter::s_info = { "DOMJITGetter", &Base::s_info, 0, CREATE_METHOD_TABLE(DOMJITGetter) }; 546 671 const ClassInfo RuntimeArray::s_info = { "RuntimeArray", &Base::s_info, 0, CREATE_METHOD_TABLE(RuntimeArray) }; 547 672 const ClassInfo SimpleObject::s_info = { "SimpleObject", &Base::s_info, 0, CREATE_METHOD_TABLE(SimpleObject) }; … … 572 697 static EncodedJSValue JSC_HOST_CALL functionCreateImpureGetter(ExecState*); 573 698 static EncodedJSValue JSC_HOST_CALL functionCreateCustomGetterObject(ExecState*); 699 static EncodedJSValue JSC_HOST_CALL functionCreateDOMJITNodeObject(ExecState*); 700 static EncodedJSValue JSC_HOST_CALL functionCreateDOMJITGetterObject(ExecState*); 574 701 static EncodedJSValue JSC_HOST_CALL functionCreateBuiltin(ExecState*); 575 702 static EncodedJSValue JSC_HOST_CALL functionCreateGlobalObject(ExecState*); … … 856 983 addFunction(vm, "createImpureGetter", functionCreateImpureGetter, 1); 857 984 addFunction(vm, "createCustomGetterObject", functionCreateCustomGetterObject, 0); 985 addFunction(vm, "createDOMJITNodeObject", functionCreateDOMJITNodeObject, 0); 986 addFunction(vm, "createDOMJITGetterObject", functionCreateDOMJITGetterObject, 0); 858 987 addFunction(vm, "createBuiltin", functionCreateBuiltin, 2); 859 988 addFunction(vm, "createGlobalObject", functionCreateGlobalObject, 0); … … 1360 1489 } 1361 1490 1491 EncodedJSValue JSC_HOST_CALL functionCreateDOMJITNodeObject(ExecState* exec) 1492 { 1493 JSLockHolder lock(exec); 1494 Structure* structure = DOMJITNode::createStructure(exec->vm(), exec->lexicalGlobalObject(), DOMJITGetter::create(exec->vm(), DOMJITGetter::createStructure(exec->vm(), exec->lexicalGlobalObject(), jsNull()))); 1495 DOMJITNode* result = DOMJITNode::create(exec->vm(), structure); 1496 return JSValue::encode(result); 1497 } 1498 1499 EncodedJSValue JSC_HOST_CALL functionCreateDOMJITGetterObject(ExecState* exec) 1500 { 1501 JSLockHolder lock(exec); 1502 Structure* structure = DOMJITGetter::createStructure(exec->vm(), exec->lexicalGlobalObject(), jsNull()); 1503 DOMJITGetter* result = DOMJITGetter::create(exec->vm(), structure); 1504 return JSValue::encode(result); 1505 } 1506 1362 1507 EncodedJSValue JSC_HOST_CALL functionSetImpureGetterDelegate(ExecState* exec) 1363 1508 { -
trunk/Source/WTF/ChangeLog
r206811 r206846 1 2016-10-05 Yusuke Suzuki <utatane.tea@gmail.com> 2 3 [DOMJIT] Add initial CheckDOM and CallDOM implementations 4 https://bugs.webkit.org/show_bug.cgi?id=162941 5 6 Reviewed by Filip Pizlo. 7 8 * wtf/Box.h: 9 (WTF::Box::Box): 10 1 11 2016-10-05 Zan Dobersek <zdobersek@igalia.com> 2 12 -
trunk/Source/WTF/wtf/Box.h
r193890 r206846 41 41 } 42 42 43 Box(std::nullptr_t) 44 { 45 } 46 43 47 template<typename... Arguments> 44 48 static Box create(Arguments&&... arguments)
Note: See TracChangeset
for help on using the changeset viewer.