ALWAYS_INLINE void SelectorDataList::execute(ContainerNode& rootNode, typename SelectorQueryTrait::OutputType& output) const { ContainerNode* searchRootNode = &rootNode; switch (m_matchType) { case RightMostWithIdMatch: { const SelectorData& selectorData = m_selectors.first(); if (const CSSSelector* idSelector = selectorForIdLookup(*searchRootNode, *selectorData.selector)) { executeFastPathForIdSelector<SelectorQueryTrait>(*searchRootNode, m_selectors.first(), idSelector, output); break; } #if ENABLE(CSS_SELECTOR_JIT) if (selectorData.compilationStatus == SelectorCompilationStatus::SimpleSelectorChecker) goto CompiledSingleCase; #endif } FALLTHROUGH; case CompilableSingleWithRootFilter: case CompilableSingle: { #if ENABLE(CSS_SELECTOR_JIT) const SelectorData& selectorData = m_selectors.first(); ASSERT(m_matchType == RightMostWithIdMatch || selectorData.compilationStatus == SelectorCompilationStatus::NotCompiled); JSC::VM& vm = searchRootNode->document().scriptExecutionContext()->vm(); selectorData.compilationStatus = SelectorCompiler::compileSelector(selectorData.selector, &vm, SelectorCompiler::SelectorContext::QuerySelector, selectorData.compiledSelectorCodeRef); RELEASE_ASSERT(selectorData.compilationStatus != SelectorCompilationStatus::SelectorCheckerWithCheckingContext); if (selectorData.compilationStatus == SelectorCompilationStatus::SimpleSelectorChecker) { if (m_matchType == CompilableSingle) { m_matchType = CompiledSingle; goto CompiledSingleCase; } if (m_matchType == CompilableSingleWithRootFilter) { m_matchType = CompiledSingleWithRootFilter; goto CompiledSingleWithRootFilterCase; } goto CompiledSingleCase; } if (m_matchType != RightMostWithIdMatch) m_matchType = SingleSelector; goto SingleSelectorCase; ASSERT_NOT_REACHED(); break; #else FALLTHROUGH; #endif // ENABLE(CSS_SELECTOR_JIT) } case CompiledSingleWithRootFilter: #if ENABLE(CSS_SELECTOR_JIT) CompiledSingleWithRootFilterCase: searchRootNode = &filterRootById(*searchRootNode, *m_selectors.first().selector); #endif // ENABLE(CSS_SELECTOR_JIT) FALLTHROUGH; case CompiledSingle: #if ENABLE(CSS_SELECTOR_JIT) { CompiledSingleCase: const SelectorData& selectorData = m_selectors.first(); void* compiledSelectorChecker = selectorData.compiledSelectorCodeRef.code().executableAddress(); SelectorCompiler::SimpleSelectorChecker selectorChecker = SelectorCompiler::simpleSelectorCheckerFunction(compiledSelectorChecker, selectorData.compilationStatus); executeCompiledSimpleSelectorChecker<SelectorQueryTrait>(*searchRootNode, selectorChecker, output); break; } #else FALLTHROUGH; #endif // ENABLE(CSS_SELECTOR_JIT) case SingleSelector: #if ENABLE(CSS_SELECTOR_JIT) SingleSelectorCase: #endif executeSingleSelectorData<SelectorQueryTrait>(*searchRootNode, m_selectors.first(), output); break; case TagNameMatch: executeSingleTagNameSelectorData<SelectorQueryTrait>(*searchRootNode, m_selectors.first(), output); break; case ClassNameMatch: executeSingleClassNameSelectorData<SelectorQueryTrait>(*searchRootNode, m_selectors.first(), output); break; case MultipleSelectorMatch: executeSingleMultiSelectorData<SelectorQueryTrait>(*searchRootNode, output); break; } }
ALWAYS_INLINE void SelectorDataList::execute(ContainerNode& rootNode, typename SelectorQueryTrait::OutputType& output) const { ContainerNode* searchRootNode = &rootNode; switch (m_matchType) { case RightMostWithIdMatch: { const SelectorData& selectorData = m_selectors.first(); if (const CSSSelector* idSelector = selectorForIdLookup(*searchRootNode, *selectorData.selector)) { executeFastPathForIdSelector<SelectorQueryTrait>(*searchRootNode, m_selectors.first(), idSelector, output); break; } #if ENABLE(CSS_SELECTOR_JIT) if (compileSelector(selectorData, *searchRootNode)) goto CompiledSingleCase; #endif // ENABLE(CSS_SELECTOR_JIT) goto SingleSelectorCase; ASSERT_NOT_REACHED(); } case CompilableSingleWithRootFilter: case CompilableSingle: { #if ENABLE(CSS_SELECTOR_JIT) const SelectorData& selectorData = m_selectors.first(); ASSERT(selectorData.compilationStatus == SelectorCompilationStatus::NotCompiled); ASSERT(m_matchType == CompilableSingle || m_matchType == CompilableSingleWithRootFilter); if (compileSelector(selectorData, *searchRootNode)) { if (m_matchType == CompilableSingle) { m_matchType = CompiledSingle; goto CompiledSingleCase; } ASSERT(m_matchType == CompilableSingleWithRootFilter); m_matchType = CompiledSingleWithRootFilter; goto CompiledSingleWithRootFilterCase; } #endif // ENABLE(CSS_SELECTOR_JIT) if (m_matchType == CompilableSingle) { m_matchType = SingleSelector; goto SingleSelectorCase; } ASSERT(m_matchType == CompilableSingleWithRootFilter); m_matchType = SingleSelectorWithRootFilter; goto SingleSelectorWithRootFilterCase; ASSERT_NOT_REACHED(); } #if ENABLE(CSS_SELECTOR_JIT) case CompiledSingleWithRootFilter: CompiledSingleWithRootFilterCase: searchRootNode = &filterRootById(*searchRootNode, *m_selectors.first().selector); FALLTHROUGH; case CompiledSingle: { CompiledSingleCase: const SelectorData& selectorData = m_selectors.first(); void* compiledSelectorChecker = selectorData.compiledSelectorCodeRef.code().executableAddress(); if (selectorData.compilationStatus == SelectorCompilationStatus::SimpleSelectorChecker) { SelectorCompiler::QuerySelectorSimpleSelectorChecker selectorChecker = SelectorCompiler::querySelectorSimpleSelectorCheckerFunction(compiledSelectorChecker, selectorData.compilationStatus); executeCompiledSimpleSelectorChecker<SelectorQueryTrait>(*searchRootNode, selectorChecker, output, selectorData); } else { ASSERT(selectorData.compilationStatus == SelectorCompilationStatus::SelectorCheckerWithCheckingContext); SelectorCompiler::QuerySelectorSelectorCheckerWithCheckingContext selectorChecker = SelectorCompiler::querySelectorSelectorCheckerFunctionWithCheckingContext(compiledSelectorChecker, selectorData.compilationStatus); executeCompiledSelectorCheckerWithCheckingContext<SelectorQueryTrait>(rootNode, *searchRootNode, selectorChecker, output, selectorData); } break; } #else case CompiledSingleWithRootFilter: case CompiledSingle: ASSERT_NOT_REACHED(); #if ASSERT_DISABLED FALLTHROUGH; #endif #endif // ENABLE(CSS_SELECTOR_JIT) case SingleSelectorWithRootFilter: SingleSelectorWithRootFilterCase: searchRootNode = &filterRootById(*searchRootNode, *m_selectors.first().selector); FALLTHROUGH; case SingleSelector: SingleSelectorCase: executeSingleSelectorData<SelectorQueryTrait>(rootNode, *searchRootNode, m_selectors.first(), output); break; case TagNameMatch: executeSingleTagNameSelectorData<SelectorQueryTrait>(*searchRootNode, m_selectors.first(), output); break; case ClassNameMatch: executeSingleClassNameSelectorData<SelectorQueryTrait>(*searchRootNode, m_selectors.first(), output); break; case CompilableMultipleSelectorMatch: #if ENABLE(CSS_SELECTOR_JIT) { for (auto& selector : m_selectors) { if (!compileSelector(selector, *searchRootNode)) { m_matchType = MultipleSelectorMatch; goto MultipleSelectorMatch; } } m_matchType = CompiledMultipleSelectorMatch; goto CompiledMultipleSelectorMatch; } #else FALLTHROUGH; #endif // ENABLE(CSS_SELECTOR_JIT) case CompiledMultipleSelectorMatch: #if ENABLE(CSS_SELECTOR_JIT) CompiledMultipleSelectorMatch: executeCompiledSingleMultiSelectorData<SelectorQueryTrait>(*searchRootNode, output); break; #else FALLTHROUGH; #endif // ENABLE(CSS_SELECTOR_JIT) case MultipleSelectorMatch: #if ENABLE(CSS_SELECTOR_JIT) MultipleSelectorMatch: #endif executeSingleMultiSelectorData<SelectorQueryTrait>(*searchRootNode, output); break; } }