void HashMapTest::testIsEmpty() { HashMap<int, std::string> hashMap; CPPUNIT_ASSERT_MESSAGE("Returned false for new map", hashMap.isEmpty()); hashMap.put(1, "1"); CPPUNIT_ASSERT_MESSAGE("Returned true for non-empty", !hashMap.isEmpty()); hashMap.clear(); CPPUNIT_ASSERT_MESSAGE("Returned false for cleared map", hashMap.isEmpty()); }
String CSSMutableStyleDeclaration::removeProperty(int propertyID, bool notifyChanged, bool returnText, ExceptionCode& ec) { ec = 0; static HashMap<int, PropertyLonghand> shorthandMap; if (shorthandMap.isEmpty()) initShorthandMap(shorthandMap); PropertyLonghand longhand = shorthandMap.get(propertyID); if (longhand.length()) { removePropertiesInSet(longhand.properties(), longhand.length(), notifyChanged); // FIXME: Return an equivalent shorthand when possible. return String(); } String value; DeprecatedValueListIterator<CSSProperty> end; for (DeprecatedValueListIterator<CSSProperty> it = m_values.fromLast(); it != end; --it) { if (propertyID == (*it).m_id) { if (returnText) value = (*it).value()->cssText(); if ((*it).value()->isVariableDependentValue()) m_variableDependentValueCount--; m_values.remove(it); if (notifyChanged) setChanged(); break; } } return value; }
static void initMIMETypeEntensionMap() { if (mimetypeMap.isEmpty()) { //fill with initial values mimetypeMap.add("txt", "text/plain"); mimetypeMap.add("pdf", "application/pdf"); mimetypeMap.add("ps", "application/postscript"); mimetypeMap.add("html", "text/html"); mimetypeMap.add("htm", "text/html"); mimetypeMap.add("xml", "text/xml"); mimetypeMap.add("xsl", "text/xsl"); mimetypeMap.add("js", "application/x-javascript"); mimetypeMap.add("xhtml", "application/xhtml+xml"); mimetypeMap.add("rss", "application/rss+xml"); mimetypeMap.add("webarchive", "application/x-webarchive"); mimetypeMap.add("svg", "image/svg+xml"); mimetypeMap.add("svgz", "image/svg+xml"); mimetypeMap.add("jpg", "image/jpeg"); mimetypeMap.add("jpeg", "image/jpeg"); mimetypeMap.add("png", "image/png"); mimetypeMap.add("tif", "image/tiff"); mimetypeMap.add("tiff", "image/tiff"); mimetypeMap.add("ico", "image/ico"); mimetypeMap.add("cur", "image/ico"); mimetypeMap.add("bmp", "image/bmp"); mimetypeMap.add("css", "text/css"); // FIXME: Custom font works only when MIME is "text/plain" mimetypeMap.add("ttf", "text/plain"); // "font/ttf" mimetypeMap.add("otf", "text/plain"); // "font/otf" } }
void disconnectAccessibilityCallbacks() { // Only disconnect if logging is off and there is no notification handler. if (loggingAccessibilityEvents || !notificationHandlers.isEmpty()) return; // AtkObject signals. if (stateChangeListenerId) { atk_remove_global_event_listener(stateChangeListenerId); stateChangeListenerId = 0; } if (focusEventListenerId) { atk_remove_global_event_listener(focusEventListenerId); focusEventListenerId = 0; } if (activeDescendantChangedListenerId) { atk_remove_global_event_listener(activeDescendantChangedListenerId); activeDescendantChangedListenerId = 0; } if (childrenChangedListenerId) { atk_remove_global_event_listener(childrenChangedListenerId); childrenChangedListenerId = 0; } if (propertyChangedListenerId) { atk_remove_global_event_listener(propertyChangedListenerId); propertyChangedListenerId = 0; } if (visibleDataChangedListenerId) { atk_remove_global_event_listener(visibleDataChangedListenerId); visibleDataChangedListenerId = 0; } }
void HashMapTest::testRemove() { { HashMap<int, std::string> hashMap; populateMap(hashMap); int size = hashMap.size(); CPPUNIT_ASSERT_NO_THROW_MESSAGE("Remove returned incorrect value", hashMap.remove(9)); CPPUNIT_ASSERT_THROW_MESSAGE( "Should have thrown a NoSuchElementException on get of non-existent key.", hashMap.get(9), NoSuchElementException); CPPUNIT_ASSERT_MESSAGE("Failed to decrement size", hashMap.size() == (size - 1)); CPPUNIT_ASSERT_THROW_MESSAGE( "Should have thrown a NoSuchElementException on remove of non-existent key.", hashMap.remove(9), NoSuchElementException); } { HashMap<int, std::string> hashMap; for (int i = 0; i < 8192; i++) { hashMap.put(i, "const"); } for (int i = 0; i < 8192; i++) { hashMap.put(i, Integer::toString(i)); } for (int i = 8191; i >= 0; i--) { std::string iValue = Integer::toString(i); CPPUNIT_ASSERT_MESSAGE(std::string("Failed to replace value: ") + iValue, hashMap.containsValue(iValue)); hashMap.remove(i); CPPUNIT_ASSERT_MESSAGE(std::string("Failed to remove same value: ") + iValue, !hashMap.containsValue(iValue)); } } { // Ensure keys with identical hashcode are stored separately and removed correctly. HashMap<MyKey, std::string> map; // Put non-equal object with same hashcode MyKey aKey; CPPUNIT_ASSERT(!map.containsKey(aKey)); map.put(aKey, "value"); MyKey aKey2; CPPUNIT_ASSERT_THROW_MESSAGE( "Should have thrown NoSuchElementException", map.remove(aKey2), NoSuchElementException); MyKey aKey3; map.put(aKey3, "foobar"); CPPUNIT_ASSERT_EQUAL(std::string("foobar"), map.get(aKey3)); CPPUNIT_ASSERT_EQUAL(std::string("value"), map.get(aKey)); map.remove(aKey); map.remove(aKey3); CPPUNIT_ASSERT(!map.containsKey(aKey)); CPPUNIT_ASSERT(map.isEmpty()); } }
void CSSAnimations::calculateTransitionActiveInterpolations(CSSAnimationUpdate* update, const Element* element, double timelineCurrentTime) { ActiveAnimations* activeAnimations = element ? element->activeAnimations() : 0; AnimationStack* animationStack = activeAnimations ? &activeAnimations->defaultStack() : 0; HashMap<CSSPropertyID, RefPtr<Interpolation> > activeInterpolationsForTransitions; if (update->newTransitions().isEmpty() && update->cancelledTransitions().isEmpty()) { activeInterpolationsForTransitions = AnimationStack::activeInterpolations(animationStack, 0, 0, Animation::TransitionPriority, timelineCurrentTime); } else { Vector<RawPtr<InertAnimation> > newTransitions; for (CSSAnimationUpdate::NewTransitionMap::const_iterator iter = update->newTransitions().begin(); iter != update->newTransitions().end(); ++iter) newTransitions.append(iter->value.animation.get()); HashSet<RawPtr<const AnimationPlayer> > cancelledAnimationPlayers; if (!update->cancelledTransitions().isEmpty()) { ASSERT(activeAnimations); const TransitionMap& transitionMap = activeAnimations->cssAnimations().m_transitions; for (HashSet<CSSPropertyID>::iterator iter = update->cancelledTransitions().begin(); iter != update->cancelledTransitions().end(); ++iter) { ASSERT(transitionMap.contains(*iter)); cancelledAnimationPlayers.add(transitionMap.get(*iter).player.get()); } } activeInterpolationsForTransitions = AnimationStack::activeInterpolations(animationStack, &newTransitions, &cancelledAnimationPlayers, Animation::TransitionPriority, timelineCurrentTime); } // Properties being animated by animations don't get values from transitions applied. if (!update->activeInterpolationsForAnimations().isEmpty() && !activeInterpolationsForTransitions.isEmpty()) { for (HashMap<CSSPropertyID, RefPtr<Interpolation> >::const_iterator iter = update->activeInterpolationsForAnimations().begin(); iter != update->activeInterpolationsForAnimations().end(); ++iter) activeInterpolationsForTransitions.remove(iter->key); } update->adoptActiveInterpolationsForTransitions(activeInterpolationsForTransitions); }
void HashMapTest::testConstructor() { HashMap<int, std::string> map; CPPUNIT_ASSERT(map.isEmpty()); CPPUNIT_ASSERT_EQUAL(0, map.size()); CPPUNIT_ASSERT_EQUAL(false, map.containsKey(1)); CPPUNIT_ASSERT_EQUAL(false, map.containsValue("test")); }
PassOwnPtr<MutationObserverInterestGroup> MutationObserverInterestGroup::createIfNeeded(Node* target, WebKitMutationObserver::MutationType type, const AtomicString& attributeName, MutationRecordDeliveryOptions oldValueFlag) { HashMap<WebKitMutationObserver*, MutationRecordDeliveryOptions> observers; target->getRegisteredMutationObserversOfType(observers, type, attributeName); if (observers.isEmpty()) return nullptr; return adoptPtr(new MutationObserverInterestGroup(observers, oldValueFlag)); }
void WebPreferences::removeReferenceForIdentifier(String identifier) { if (!identifier || webPreferencesInstances.isEmpty()) return; WebPreferences* webPreference = webPreferencesInstances.get(identifier); if (webPreference) webPreferencesInstances.remove(identifier); }
PassOwnPtr<MutationObserverInterestGroup> MutationObserverInterestGroup::createIfNeeded(Node& target, MutationObserver::MutationType type, MutationRecordDeliveryOptions oldValueFlag, const QualifiedName* attributeName) { ASSERT((type == MutationObserver::Attributes && attributeName) || !attributeName); HashMap<RawPtr<MutationObserver>, MutationRecordDeliveryOptions> observers; target.getRegisteredMutationObserversOfType(observers, type, attributeName); if (observers.isEmpty()) return nullptr; return adoptPtr(new MutationObserverInterestGroup(observers, oldValueFlag)); }
void WebPreferences::removeReferenceForIdentifier(BSTR identifier) { if (!identifier || webPreferencesInstances.isEmpty()) return; WebCore::String identifierString(identifier, SysStringLen(identifier)); WebPreferences* webPreference = webPreferencesInstances.get(identifierString).get(); if (webPreference && webPreference->m_refCount == 1) webPreferencesInstances.remove(identifierString); }
static bool isAxisName(const String& name, Step::Axis& type) { static HashMap<String, Step::Axis> axisNames; if (axisNames.isEmpty()) setUpAxisNamesMap(axisNames); HashMap<String, Step::Axis>::iterator it = axisNames.find(name); if (it == axisNames.end()) return false; type = it->second; return true; }
static bool isDefaultPortForProtocol(unsigned short port, const String& protocol) { if (protocol.isEmpty()) return false; static HashMap<String, unsigned> defaultPorts; if (defaultPorts.isEmpty()) { defaultPorts.set("http", 80); defaultPorts.set("https", 443); defaultPorts.set("ftp", 21); defaultPorts.set("ftps", 990); } return defaultPorts.get(protocol) == port; }
CSSSegmentedFontFace* CSSFontSelector::getFontFace(const FontDescription& fontDescription, const AtomicString& family) { HashMap<unsigned, RefPtr<CSSSegmentedFontFace> >* familyFontFaces = m_fontFaces.get(family); if (!familyFontFaces || familyFontFaces->isEmpty()) return 0; OwnPtr<HashMap<unsigned, RefPtr<CSSSegmentedFontFace> > >& segmentedFontFaceCache = m_fonts.add(family, nullptr).iterator->value; if (!segmentedFontFaceCache) segmentedFontFaceCache = adoptPtr(new HashMap<unsigned, RefPtr<CSSSegmentedFontFace> >); FontTraitsMask traitsMask = fontDescription.traitsMask(); RefPtr<CSSSegmentedFontFace>& face = segmentedFontFaceCache->add(traitsMask, 0).iterator->value; if (!face) { for (HashMap<unsigned, RefPtr<CSSSegmentedFontFace> >::const_iterator i = familyFontFaces->begin(); i != familyFontFaces->end(); ++i) { CSSSegmentedFontFace* candidate = i->value.get(); unsigned candidateTraitsMask = candidate->traitsMask(); if ((traitsMask & FontStyleNormalMask) && !(candidateTraitsMask & FontStyleNormalMask)) continue; if ((traitsMask & FontVariantNormalMask) && !(candidateTraitsMask & FontVariantNormalMask)) continue; #if ENABLE(SVG_FONTS) // For SVG Fonts that specify that they only support the "normal" variant, we will assume they are incapable // of small-caps synthesis and just ignore the font face as a candidate. if (candidate->hasSVGFontFaceSource() && (traitsMask & FontVariantSmallCapsMask) && !(candidateTraitsMask & FontVariantSmallCapsMask)) continue; #endif if (!face || compareFontFaces(candidate, face.get(), traitsMask)) face = candidate; } if (Vector<RefPtr<CSSSegmentedFontFace> >* familyLocallyInstalledFontFaces = m_locallyInstalledFontFaces.get(family)) { unsigned numLocallyInstalledFontFaces = familyLocallyInstalledFontFaces->size(); for (unsigned i = 0; i < numLocallyInstalledFontFaces; ++i) { CSSSegmentedFontFace* candidate = familyLocallyInstalledFontFaces->at(i).get(); unsigned candidateTraitsMask = candidate->traitsMask(); if ((traitsMask & FontStyleNormalMask) && !(candidateTraitsMask & FontStyleNormalMask)) continue; if ((traitsMask & FontVariantNormalMask) && !(candidateTraitsMask & FontVariantNormalMask)) continue; if (!face || compareFontFaces(candidate, face.get(), traitsMask)) face = candidate; } } } return face.get(); }
void EditorClient::generateEditorCommands(const KeyboardEvent* event) { ASSERT(event->type() == eventNames().keydownEvent || event->type() == eventNames().keypressEvent); m_pendingEditorCommands.clear(); // First try to interpret the command as a native GTK+ key binding. gtk_bindings_activate_event(GTK_OBJECT(m_nativeWidget.get()), event->keyEvent()->gdkEventKey()); if (m_pendingEditorCommands.size() > 0) return; static HashMap<int, const char*> keyDownCommandsMap; static HashMap<int, const char*> keyPressCommandsMap; if (keyDownCommandsMap.isEmpty()) { for (unsigned i = 0; i < G_N_ELEMENTS(keyDownEntries); i++) keyDownCommandsMap.set(keyDownEntries[i].modifiers << 16 | keyDownEntries[i].virtualKey, keyDownEntries[i].name); for (unsigned i = 0; i < G_N_ELEMENTS(keyPressEntries); i++) keyPressCommandsMap.set(keyPressEntries[i].modifiers << 16 | keyPressEntries[i].charCode, keyPressEntries[i].name); } unsigned modifiers = 0; if (event->shiftKey()) modifiers |= ShiftKey; if (event->altKey()) modifiers |= AltKey; if (event->ctrlKey()) modifiers |= CtrlKey; if (event->type() == eventNames().keydownEvent) { int mapKey = modifiers << 16 | event->keyCode(); if (mapKey) m_pendingEditorCommands.append(keyDownCommandsMap.get(mapKey)); return; } int mapKey = modifiers << 16 | event->charCode(); if (mapKey) m_pendingEditorCommands.append(keyPressCommandsMap.get(mapKey)); }
String MIMETypeRegistry::getMIMETypeForExtension(const String &ext) { if (ext.isEmpty()) return String(); static HashMap<String, String> mimetypeMap; if (mimetypeMap.isEmpty()) { //fill with initial values mimetypeMap.add("txt", "text/plain"); mimetypeMap.add("pdf", "application/pdf"); mimetypeMap.add("ps", "application/postscript"); mimetypeMap.add("html", "text/html"); mimetypeMap.add("htm", "text/html"); mimetypeMap.add("xml", "text/xml"); mimetypeMap.add("xsl", "text/xsl"); mimetypeMap.add("js", "application/x-javascript"); mimetypeMap.add("xhtml", "application/xhtml+xml"); mimetypeMap.add("rss", "application/rss+xml"); mimetypeMap.add("webarchive", "application/x-webarchive"); mimetypeMap.add("svg", "image/svg+xml"); mimetypeMap.add("svgz", "image/svg+xml"); mimetypeMap.add("jpg", "image/jpeg"); mimetypeMap.add("jpeg", "image/jpeg"); mimetypeMap.add("png", "image/png"); mimetypeMap.add("tif", "image/tiff"); mimetypeMap.add("tiff", "image/tiff"); mimetypeMap.add("ico", "image/ico"); mimetypeMap.add("cur", "image/ico"); mimetypeMap.add("bmp", "image/bmp"); mimetypeMap.add("wml", "text/vnd.wap.wml"); mimetypeMap.add("wmlc", "application/vnd.wap.wmlc"); } String result = mimetypeMap.get(ext); if (result.isEmpty()) { result = mimeTypeForExtension(ext); if (!result.isEmpty()) mimetypeMap.add(ext, result); } return result; }
static String mimeTypeForExtension(const String& file) { static HashMap<String, String, CaseFoldingHash> extensionToMime; if (extensionToMime.isEmpty()) { extensionToMime.set("txt", "text/plain"); extensionToMime.set("html", "text/html"); extensionToMime.set("htm", "text/html"); extensionToMime.set("png", "image/png"); extensionToMime.set("jpeg", "image/jpeg"); extensionToMime.set("jpg", "image/jpeg"); extensionToMime.set("gif", "image/gif"); extensionToMime.set("ico", "image/x-icon"); extensionToMime.set("js", "text/javascript"); } int dot = file.reverseFind('.'); String mime("text/plain"); if (dot != -1) { String ext = file.substring(dot + 1); if (extensionToMime.contains(ext)) mime = extensionToMime.get(ext); } return mime; }
const char* editorCommandForKeyDownEvent(const KeyboardEvent* event) { if (event->type() != eventNames().keydownEvent) return ""; static HashMap<int, const char*> keyDownCommandsMap; if (keyDownCommandsMap.isEmpty()) { unsigned numEntries = sizeof(keyDownEntries) / sizeof((keyDownEntries)[0]); for (unsigned i = 0; i < numEntries; i++) keyDownCommandsMap.set(keyDownEntries[i].modifiers << 16 | keyDownEntries[i].virtualKey, keyDownEntries[i].editorCommand); } unsigned modifiers = 0; if (event->shiftKey()) modifiers |= ShiftKey; if (event->altKey()) modifiers |= AltKey; if (event->ctrlKey()) modifiers |= CtrlKey; int mapKey = modifiers << 16 | event->keyCode(); return mapKey ? keyDownCommandsMap.get(mapKey) : 0; }
gpointer createHTMLElementWrapper(PassRefPtr<WebCore::HTMLElement> element) { static HashMap<WTF::AtomicStringImpl*, CreateHTMLElementWrapperFunction> map; if (map.isEmpty()) { map.set(aTag.localName().impl(), createAnchorWrapper); map.set(appletTag.localName().impl(), createAppletWrapper); #if ENABLE(VIDEO) map.set(audioTag.localName().impl(), createAudioWrapper); map.set(videoTag.localName().impl(), createVideoWrapper); #endif map.set(areaTag.localName().impl(), createAreaWrapper); map.set(baseTag.localName().impl(), createBaseWrapper); map.set(basefontTag.localName().impl(), createBaseFontWrapper); map.set(blockquoteTag.localName().impl(), createQuoteWrapper); map.set(bodyTag.localName().impl(), createBodyWrapper); map.set(brTag.localName().impl(), createBRWrapper); map.set(buttonTag.localName().impl(), createButtonWrapper); map.set(canvasTag.localName().impl(), createCanvasWrapper); map.set(captionTag.localName().impl(), createTableCaptionWrapper); map.set(colTag.localName().impl(), createTableColWrapper); map.set(delTag.localName().impl(), createModWrapper); map.set(dirTag.localName().impl(), createDirectoryWrapper); map.set(divTag.localName().impl(), createDivWrapper); map.set(dlTag.localName().impl(), createDListWrapper); map.set(embedTag.localName().impl(), createEmbedWrapper); map.set(fieldsetTag.localName().impl(), createFieldSetWrapper); map.set(fontTag.localName().impl(), createFontWrapper); map.set(formTag.localName().impl(), createFormWrapper); map.set(frameTag.localName().impl(), createFrameWrapper); map.set(framesetTag.localName().impl(), createFrameSetWrapper); map.set(h1Tag.localName().impl(), createHeadingWrapper); map.set(headTag.localName().impl(), createHeadWrapper); map.set(hrTag.localName().impl(), createHRWrapper); map.set(htmlTag.localName().impl(), createHtmlWrapper); map.set(iframeTag.localName().impl(), createIFrameWrapper); map.set(imgTag.localName().impl(), createImageWrapper); map.set(inputTag.localName().impl(), createInputWrapper); map.set(isindexTag.localName().impl(), createIsIndexWrapper); map.set(labelTag.localName().impl(), createLabelWrapper); map.set(legendTag.localName().impl(), createLegendWrapper); map.set(liTag.localName().impl(), createLIWrapper); map.set(linkTag.localName().impl(), createLinkWrapper); map.set(mapTag.localName().impl(), createMapWrapper); map.set(marqueeTag.localName().impl(), createMarqueeWrapper); map.set(menuTag.localName().impl(), createMenuWrapper); map.set(metaTag.localName().impl(), createMetaWrapper); map.set(objectTag.localName().impl(), createObjectWrapper); map.set(olTag.localName().impl(), createOListWrapper); map.set(optgroupTag.localName().impl(), createOptGroupWrapper); map.set(optionTag.localName().impl(), createOptionWrapper); map.set(pTag.localName().impl(), createParagraphWrapper); map.set(paramTag.localName().impl(), createParamWrapper); map.set(preTag.localName().impl(), createPreWrapper); map.set(qTag.localName().impl(), createQuoteWrapper); map.set(scriptTag.localName().impl(), createScriptWrapper); map.set(selectTag.localName().impl(), createSelectWrapper); map.set(styleTag.localName().impl(), createStyleWrapper); map.set(tableTag.localName().impl(), createTableWrapper); map.set(tbodyTag.localName().impl(), createTableSectionWrapper); map.set(tdTag.localName().impl(), createTableCellWrapper); map.set(textareaTag.localName().impl(), createTextAreaWrapper); map.set(titleTag.localName().impl(), createTitleWrapper); map.set(trTag.localName().impl(), createTableRowWrapper); map.set(ulTag.localName().impl(), createUListWrapper); map.set(colgroupTag.localName().impl(), createTableColWrapper); map.set(h2Tag.localName().impl(), createHeadingWrapper); map.set(h3Tag.localName().impl(), createHeadingWrapper); map.set(h4Tag.localName().impl(), createHeadingWrapper); map.set(h5Tag.localName().impl(), createHeadingWrapper); map.set(h6Tag.localName().impl(), createHeadingWrapper); map.set(imageTag.localName().impl(), createImageWrapper); map.set(insTag.localName().impl(), createModWrapper); map.set(keygenTag.localName().impl(), createKeygenWrapper); map.set(listingTag.localName().impl(), createPreWrapper); map.set(tfootTag.localName().impl(), createTableSectionWrapper); map.set(thTag.localName().impl(), createTableCellWrapper); map.set(theadTag.localName().impl(), createTableSectionWrapper); map.set(xmpTag.localName().impl(), createPreWrapper); } CreateHTMLElementWrapperFunction createWrapperFunction = map.get(element->localName().impl()); if (createWrapperFunction) return createWrapperFunction(element); return wrapHTMLElement(element.get()); }
void JSTailCall::emit(JITCode& jitCode, CCallHelpers& jit) { StackMaps::Record* record { nullptr }; for (unsigned i = jitCode.stackmaps.records.size(); i--;) { record = &jitCode.stackmaps.records[i]; if (record->patchpointID == m_stackmapID) break; } RELEASE_ASSERT(record->patchpointID == m_stackmapID); m_callLinkInfo = jit.codeBlock()->addCallLinkInfo(); CallFrameShuffleData shuffleData; // The callee was the first passed argument, and must be in a GPR because // we used the "anyregcc" calling convention auto calleeLocation = FTL::Location::forStackmaps(nullptr, record->locations[0]); GPRReg calleeGPR = calleeLocation.directGPR(); shuffleData.callee = ValueRecovery::inGPR(calleeGPR, DataFormatJS); // The tag type number was the second argument, if there was one auto tagTypeNumberLocation = FTL::Location::forStackmaps(&jitCode.stackmaps, record->locations[1]); if (tagTypeNumberLocation.isGPR() && !tagTypeNumberLocation.addend()) shuffleData.tagTypeNumber = tagTypeNumberLocation.directGPR(); shuffleData.args.grow(numArguments()); HashMap<Reg, Vector<std::pair<ValueRecovery*, int32_t>>> withAddend; size_t numAddends { 0 }; for (size_t i = 0; i < numArguments(); ++i) { shuffleData.args[i] = recoveryFor(m_arguments[i], *record, jitCode.stackmaps); if (FTL::Location addend = getRegisterWithAddend(m_arguments[i], *record, jitCode.stackmaps)) { withAddend.add( addend.reg(), Vector<std::pair<ValueRecovery*, int32_t>>()).iterator->value.append( std::make_pair(&shuffleData.args[i], addend.addend())); numAddends++; } } numAddends = WTF::roundUpToMultipleOf(stackAlignmentRegisters(), numAddends); shuffleData.numLocals = static_cast<int64_t>(jitCode.stackmaps.stackSizeForLocals()) / sizeof(void*) + numAddends; ASSERT(!numAddends == withAddend.isEmpty()); if (!withAddend.isEmpty()) { jit.subPtr(MacroAssembler::TrustedImm32(numAddends * sizeof(void*)), MacroAssembler::stackPointerRegister); VirtualRegister spillBase { 1 - static_cast<int>(shuffleData.numLocals) }; for (auto entry : withAddend) { for (auto pair : entry.value) { ASSERT(numAddends > 0); VirtualRegister spillSlot { spillBase + --numAddends }; ASSERT(entry.key.isGPR()); jit.addPtr(MacroAssembler::TrustedImm32(pair.second), entry.key.gpr()); jit.storePtr(entry.key.gpr(), CCallHelpers::addressFor(spillSlot)); jit.subPtr(MacroAssembler::TrustedImm32(pair.second), entry.key.gpr()); *pair.first = ValueRecovery::displacedInJSStack(spillSlot, pair.first->dataFormat()); } } ASSERT(numAddends < stackAlignmentRegisters()); } shuffleData.args.resize(numArguments()); for (size_t i = 0; i < numArguments(); ++i) shuffleData.args[i] = recoveryFor(m_arguments[i], *record, jitCode.stackmaps); shuffleData.setupCalleeSaveRegisters(jit.codeBlock()); CCallHelpers::Jump slowPath = jit.branchPtrWithPatch( CCallHelpers::NotEqual, calleeGPR, m_targetToCheck, CCallHelpers::TrustedImmPtr(0)); m_callLinkInfo->setFrameShuffleData(shuffleData); CallFrameShuffler(jit, shuffleData).prepareForTailCall(); m_fastCall = jit.nearTailCall(); slowPath.link(&jit); CallFrameShuffler slowPathShuffler(jit, shuffleData); slowPathShuffler.setCalleeJSValueRegs(JSValueRegs { GPRInfo::regT0 }); slowPathShuffler.prepareForSlowPath(); jit.move(CCallHelpers::TrustedImmPtr(m_callLinkInfo), GPRInfo::regT2); m_slowCall = jit.nearCall(); jit.abortWithReason(JITDidReturnFromTailCall); m_callLinkInfo->setUpCall(m_type, m_semanticeOrigin, calleeGPR); }
bool fixSSA(Procedure& proc) { PhaseScope phaseScope(proc, "fixSSA"); // Collect the stack "variables". If there aren't any, then we don't have anything to do. // That's a fairly common case. HashMap<StackSlotValue*, Type> stackVariable; for (Value* value : proc.values()) { if (StackSlotValue* stack = value->as<StackSlotValue>()) { if (stack->kind() == StackSlotKind::Anonymous) stackVariable.add(stack, Void); } } if (stackVariable.isEmpty()) return false; // Make sure that we know how to optimize all of these. We only know how to handle Load and // Store on anonymous variables. for (Value* value : proc.values()) { auto reject = [&] (Value* value) { if (StackSlotValue* stack = value->as<StackSlotValue>()) stackVariable.remove(stack); }; auto handleAccess = [&] (Value* access, Type type) { StackSlotValue* stack = access->lastChild()->as<StackSlotValue>(); if (!stack) return; if (value->as<MemoryValue>()->offset()) { stackVariable.remove(stack); return; } auto result = stackVariable.find(stack); if (result == stackVariable.end()) return; if (result->value == Void) { result->value = type; return; } if (result->value == type) return; stackVariable.remove(result); }; switch (value->opcode()) { case Load: // We're OK with loads from stack variables at an offset of zero. handleAccess(value, value->type()); break; case Store: // We're OK with stores to stack variables, but not storing stack variables. reject(value->child(0)); handleAccess(value, value->child(0)->type()); break; default: for (Value* child : value->children()) reject(child); break; } } Vector<StackSlotValue*> deadValues; for (auto& entry : stackVariable) { if (entry.value == Void) deadValues.append(entry.key); } for (StackSlotValue* deadValue : deadValues) { deadValue->replaceWithNop(); stackVariable.remove(deadValue); } if (stackVariable.isEmpty()) return false; // We know that we have variables to optimize, so do that now. breakCriticalEdges(proc); SSACalculator ssa(proc); // Create a SSACalculator::Variable for every stack variable. Vector<StackSlotValue*> variableToStack; HashMap<StackSlotValue*, SSACalculator::Variable*> stackToVariable; for (auto& entry : stackVariable) { StackSlotValue* stack = entry.key; SSACalculator::Variable* variable = ssa.newVariable(); RELEASE_ASSERT(variable->index() == variableToStack.size()); variableToStack.append(stack); stackToVariable.add(stack, variable); } // Create Defs for all of the stores to the stack variable. for (BasicBlock* block : proc) { for (Value* value : *block) { if (value->opcode() != Store) continue; StackSlotValue* stack = value->child(1)->as<StackSlotValue>(); if (!stack) continue; if (SSACalculator::Variable* variable = stackToVariable.get(stack)) ssa.newDef(variable, block, value->child(0)); } } // Decide where Phis are to be inserted. This creates them but does not insert them. ssa.computePhis( [&] (SSACalculator::Variable* variable, BasicBlock* block) -> Value* { StackSlotValue* stack = variableToStack[variable->index()]; Value* phi = proc.add<Value>(Phi, stackVariable.get(stack), stack->origin()); if (verbose) { dataLog( "Adding Phi for ", pointerDump(stack), " at ", *block, ": ", deepDump(proc, phi), "\n"); } return phi; }); // Now perform the conversion. InsertionSet insertionSet(proc); HashMap<StackSlotValue*, Value*> mapping; for (BasicBlock* block : proc.blocksInPreOrder()) { mapping.clear(); for (auto& entry : stackToVariable) { StackSlotValue* stack = entry.key; SSACalculator::Variable* variable = entry.value; SSACalculator::Def* def = ssa.reachingDefAtHead(block, variable); if (def) mapping.set(stack, def->value()); } for (SSACalculator::Def* phiDef : ssa.phisForBlock(block)) { StackSlotValue* stack = variableToStack[phiDef->variable()->index()]; insertionSet.insertValue(0, phiDef->value()); mapping.set(stack, phiDef->value()); } for (unsigned valueIndex = 0; valueIndex < block->size(); ++valueIndex) { Value* value = block->at(valueIndex); value->performSubstitution(); switch (value->opcode()) { case Load: { if (StackSlotValue* stack = value->child(0)->as<StackSlotValue>()) { if (Value* replacement = mapping.get(stack)) value->replaceWithIdentity(replacement); } break; } case Store: { if (StackSlotValue* stack = value->child(1)->as<StackSlotValue>()) { if (stackToVariable.contains(stack)) { mapping.set(stack, value->child(0)); value->replaceWithNop(); } } break; } default: break; } } unsigned upsilonInsertionPoint = block->size() - 1; Origin upsilonOrigin = block->last()->origin(); for (BasicBlock* successorBlock : block->successorBlocks()) { for (SSACalculator::Def* phiDef : ssa.phisForBlock(successorBlock)) { Value* phi = phiDef->value(); SSACalculator::Variable* variable = phiDef->variable(); StackSlotValue* stack = variableToStack[variable->index()]; Value* mappedValue = mapping.get(stack); if (verbose) { dataLog( "Mapped value for ", *stack, " with successor Phi ", *phi, " at end of ", *block, ": ", pointerDump(mappedValue), "\n"); } if (!mappedValue) mappedValue = insertionSet.insertBottom(upsilonInsertionPoint, phi); insertionSet.insert<UpsilonValue>( upsilonInsertionPoint, upsilonOrigin, mappedValue, phi); } } insertionSet.execute(block); } // Finally, kill the stack slots. for (StackSlotValue* stack : variableToStack) stack->replaceWithNop(); if (verbose) { dataLog("B3 after SSA conversion:\n"); dataLog(proc); } return true; }
MutationObserverInterestGroup::MutationObserverInterestGroup(HashMap<RawPtr<MutationObserver>, MutationRecordDeliveryOptions>& observers, MutationRecordDeliveryOptions oldValueFlag) : m_oldValueFlag(oldValueFlag) { ASSERT(!observers.isEmpty()); m_observers.swap(observers); }
map.insert( 2, 'b' ); map.insert( 45, 'd' ); bool failed = map.insert( 72, 'r' ); REQUIRE( failed == false ); char val; map.print(std::cout); REQUIRE( map.search(1, val) == true ); REQUIRE( val == 'a' ); REQUIRE( map.search(2, val) == true ); REQUIRE( val == 'b' ); std::cout << std::endl; map.remove(6 , val); REQUIRE( val == 'f' ); map.print(std::cout); std::cout << std::endl; REQUIRE( map.isEmpty() == false ); map.clear(); REQUIRE( map.isEmpty() == true ); } } TEST_CASE ( "Testing bucketmap", "[BucketMap]" ) { BucketMap map(5); SECTION ( "Test insert method", "[insert]" ) { map.insert( 1, 'a' ); map.insert( 6, 'f' ); map.insert( 11, 'k' ); map.insert( 2, 'b' ); map.insert( 45, 'd' ); map.insert( 72, 'r' ); char val;
void StorageAreaSync::sync(bool clearItems, const HashMap<String, String>& items) { ASSERT(!isMainThread()); if (items.isEmpty() && !clearItems && !m_syncCloseDatabase) return; if (m_databaseOpenFailed) return; if (!m_database.isOpen() && m_syncCloseDatabase) { m_syncCloseDatabase = false; return; } if (!m_database.isOpen()) openDatabase(CreateIfNonExistent); if (!m_database.isOpen()) return; // Closing this db because it is about to be deleted by StorageTracker. // The delete will be cancelled if StorageAreaSync needs to reopen the db // to write new items created after the request to delete the db. if (m_syncCloseDatabase) { m_syncCloseDatabase = false; m_database.close(); return; } SQLiteTransactionInProgressAutoCounter transactionCounter; // If the clear flag is set, then we clear all items out before we write any new ones in. if (clearItems) { SQLiteStatement clear(m_database, "DELETE FROM ItemTable"); if (clear.prepare() != SQLITE_OK) { LOG_ERROR("Failed to prepare clear statement - cannot write to local storage database"); return; } int result = clear.step(); if (result != SQLITE_DONE) { LOG_ERROR("Failed to clear all items in the local storage database - %i", result); return; } } SQLiteStatement insert(m_database, "INSERT INTO ItemTable VALUES (?, ?)"); if (insert.prepare() != SQLITE_OK) { LOG_ERROR("Failed to prepare insert statement - cannot write to local storage database"); return; } SQLiteStatement remove(m_database, "DELETE FROM ItemTable WHERE key=?"); if (remove.prepare() != SQLITE_OK) { LOG_ERROR("Failed to prepare delete statement - cannot write to local storage database"); return; } HashMap<String, String>::const_iterator end = items.end(); SQLiteTransaction transaction(m_database); transaction.begin(); for (HashMap<String, String>::const_iterator it = items.begin(); it != end; ++it) { // Based on the null-ness of the second argument, decide whether this is an insert or a delete. SQLiteStatement& query = it->value.isNull() ? remove : insert; query.bindText(1, it->key); // If the second argument is non-null, we're doing an insert, so bind it as the value. if (!it->value.isNull()) query.bindBlob(2, it->value); int result = query.step(); if (result != SQLITE_DONE) { LOG_ERROR("Failed to update item in the local storage database - %i", result); break; } query.reset(); } transaction.commit(); }