bool RegExpCompartment::get(ExclusiveContext *cx, JSAtom *source, RegExpFlag flags, RegExpGuard *g) { Key key(source, flags); Map::AddPtr p = map_.lookupForAdd(key); if (p) { g->init(*p->value()); return true; } uint64_t gcNumber = cx->zone()->gcNumber(); ScopedJSDeletePtr<RegExpShared> shared(cx->new_<RegExpShared>(source, flags, gcNumber)); if (!shared) return false; /* Add to RegExpShared sharing hashmap. */ if (!map_.add(p, key, shared)) { js_ReportOutOfMemory(cx); return false; } /* Add to list of all RegExpShared objects in this RegExpCompartment. */ if (!inUse_.put(shared)) { map_.remove(key); js_ReportOutOfMemory(cx); return false; } /* Since error deletes |shared|, only guard |shared| on success. */ g->init(*shared.forget()); return true; }
bool InnerViewTable::addView(JSContext* cx, ArrayBufferObject* buffer, ArrayBufferViewObject* view) { // ArrayBufferObject entries are only added when there are multiple views. MOZ_ASSERT(buffer->firstView()); if (!map.initialized() && !map.init()) { ReportOutOfMemory(cx); return false; } Map::AddPtr p = map.lookupForAdd(buffer); MOZ_ASSERT(!gc::IsInsideNursery(buffer)); bool addToNursery = nurseryKeysValid && gc::IsInsideNursery(view); if (p) { ViewVector& views = p->value(); MOZ_ASSERT(!views.empty()); if (addToNursery) { // Only add the entry to |nurseryKeys| if it isn't already there. if (views.length() >= VIEW_LIST_MAX_LENGTH) { // To avoid quadratic blowup, skip the loop below if we end up // adding enormous numbers of views for the same object. nurseryKeysValid = false; } else { for (size_t i = 0; i < views.length(); i++) { if (gc::IsInsideNursery(views[i])) { addToNursery = false; break; } } } } if (!views.append(view)) { ReportOutOfMemory(cx); return false; } } else { if (!map.add(p, buffer, ViewVector())) { ReportOutOfMemory(cx); return false; } // ViewVector has one inline element, so the first insertion is // guaranteed to succeed. MOZ_ALWAYS_TRUE(p->value().append(view)); } if (addToNursery && !nurseryKeys.append(buffer)) nurseryKeysValid = false; return true; }
bool InnerViewTable::addView(JSContext *cx, ArrayBufferObject *obj, ArrayBufferViewObject *view) { // ArrayBufferObject entries are only added when there are multiple views. MOZ_ASSERT(obj->firstView()); if (!map.initialized() && !map.init()) return false; Map::AddPtr p = map.lookupForAdd(obj); MOZ_ASSERT(!gc::IsInsideNursery(obj)); bool addToNursery = nurseryKeysValid && gc::IsInsideNursery(view); if (p) { ViewVector &views = p->value(); MOZ_ASSERT(!views.empty()); if (addToNursery) { // Only add the entry to |nurseryKeys| if it isn't already there. if (views.length() >= VIEW_LIST_MAX_LENGTH) { // To avoid quadratic blowup, skip the loop below if we end up // adding enormous numbers of views for the same object. nurseryKeysValid = false; } else { for (size_t i = 0; i < views.length(); i++) { if (gc::IsInsideNursery(views[i])) addToNursery = false; } } } if (!views.append(view)) return false; } else { if (!map.add(p, obj, ViewVector())) return false; JS_ALWAYS_TRUE(p->value().append(view)); } if (addToNursery && !nurseryKeys.append(obj)) nurseryKeysValid = false; return true; }
bool allocateSigId(JSContext* cx, const Sig& sig, const void** sigId) { Map::AddPtr p = map_.lookupForAdd(sig); if (p) { MOZ_ASSERT(p->value() > 0); p->value()++; *sigId = p->key(); return true; } UniquePtr<Sig> clone = MakeUnique<Sig>(); if (!clone || !clone->clone(sig) || !map_.add(p, clone.get(), 1)) { ReportOutOfMemory(cx); return false; } *sigId = clone.release(); MOZ_ASSERT(!(uintptr_t(*sigId) & SigIdDesc::ImmediateBit)); return true; }