dom/xslt/xpath/txResultRecycler.cpp

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

michael@0 1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #include "txResultRecycler.h"
michael@0 7 #include "txExprResult.h"
michael@0 8 #include "txNodeSet.h"
michael@0 9
michael@0 10 txResultRecycler::txResultRecycler()
michael@0 11 : mEmptyStringResult(nullptr),
michael@0 12 mTrueResult(nullptr),
michael@0 13 mFalseResult(nullptr)
michael@0 14 {
michael@0 15 }
michael@0 16
michael@0 17 txResultRecycler::~txResultRecycler()
michael@0 18 {
michael@0 19 txStackIterator stringIter(&mStringResults);
michael@0 20 while (stringIter.hasNext()) {
michael@0 21 delete static_cast<StringResult*>(stringIter.next());
michael@0 22 }
michael@0 23 txStackIterator nodesetIter(&mNodeSetResults);
michael@0 24 while (nodesetIter.hasNext()) {
michael@0 25 delete static_cast<txNodeSet*>(nodesetIter.next());
michael@0 26 }
michael@0 27 txStackIterator numberIter(&mNumberResults);
michael@0 28 while (numberIter.hasNext()) {
michael@0 29 delete static_cast<NumberResult*>(numberIter.next());
michael@0 30 }
michael@0 31
michael@0 32 NS_IF_RELEASE(mEmptyStringResult);
michael@0 33 NS_IF_RELEASE(mTrueResult);
michael@0 34 NS_IF_RELEASE(mFalseResult);
michael@0 35 }
michael@0 36
michael@0 37
michael@0 38 nsresult
michael@0 39 txResultRecycler::init()
michael@0 40 {
michael@0 41 NS_ASSERTION(!mEmptyStringResult && !mTrueResult && !mFalseResult,
michael@0 42 "Already inited");
michael@0 43 mEmptyStringResult = new StringResult(nullptr);
michael@0 44 NS_ENSURE_TRUE(mEmptyStringResult, NS_ERROR_OUT_OF_MEMORY);
michael@0 45
michael@0 46 NS_ADDREF(mEmptyStringResult);
michael@0 47
michael@0 48 mTrueResult = new BooleanResult(true);
michael@0 49 NS_ENSURE_TRUE(mTrueResult, NS_ERROR_OUT_OF_MEMORY);
michael@0 50
michael@0 51 NS_ADDREF(mTrueResult);
michael@0 52
michael@0 53 mFalseResult = new BooleanResult(false);
michael@0 54 NS_ENSURE_TRUE(mFalseResult, NS_ERROR_OUT_OF_MEMORY);
michael@0 55
michael@0 56 NS_ADDREF(mFalseResult);
michael@0 57
michael@0 58 return NS_OK;
michael@0 59 }
michael@0 60
michael@0 61
michael@0 62 void
michael@0 63 txResultRecycler::recycle(txAExprResult* aResult)
michael@0 64 {
michael@0 65 NS_ASSERTION(aResult->mRefCnt == 0, "In-use txAExprResult recycled");
michael@0 66 nsRefPtr<txResultRecycler> kungFuDeathGrip;
michael@0 67 aResult->mRecycler.swap(kungFuDeathGrip);
michael@0 68
michael@0 69 nsresult rv = NS_OK;
michael@0 70 switch (aResult->getResultType()) {
michael@0 71 case txAExprResult::STRING:
michael@0 72 {
michael@0 73 rv = mStringResults.push(static_cast<StringResult*>(aResult));
michael@0 74 if (NS_FAILED(rv)) {
michael@0 75 delete aResult;
michael@0 76 }
michael@0 77 return;
michael@0 78 }
michael@0 79 case txAExprResult::NODESET:
michael@0 80 {
michael@0 81 static_cast<txNodeSet*>(aResult)->clear();
michael@0 82 rv = mNodeSetResults.push(static_cast<txNodeSet*>(aResult));
michael@0 83 if (NS_FAILED(rv)) {
michael@0 84 delete aResult;
michael@0 85 }
michael@0 86 return;
michael@0 87 }
michael@0 88 case txAExprResult::NUMBER:
michael@0 89 {
michael@0 90 rv = mNumberResults.push(static_cast<NumberResult*>(aResult));
michael@0 91 if (NS_FAILED(rv)) {
michael@0 92 delete aResult;
michael@0 93 }
michael@0 94 return;
michael@0 95 }
michael@0 96 default:
michael@0 97 {
michael@0 98 delete aResult;
michael@0 99 }
michael@0 100 }
michael@0 101 }
michael@0 102
michael@0 103 nsresult
michael@0 104 txResultRecycler::getStringResult(StringResult** aResult)
michael@0 105 {
michael@0 106 if (mStringResults.isEmpty()) {
michael@0 107 *aResult = new StringResult(this);
michael@0 108 NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY);
michael@0 109 }
michael@0 110 else {
michael@0 111 *aResult = static_cast<StringResult*>(mStringResults.pop());
michael@0 112 (*aResult)->mValue.Truncate();
michael@0 113 (*aResult)->mRecycler = this;
michael@0 114 }
michael@0 115 NS_ADDREF(*aResult);
michael@0 116
michael@0 117 return NS_OK;
michael@0 118 }
michael@0 119
michael@0 120 nsresult
michael@0 121 txResultRecycler::getStringResult(const nsAString& aValue,
michael@0 122 txAExprResult** aResult)
michael@0 123 {
michael@0 124 if (mStringResults.isEmpty()) {
michael@0 125 *aResult = new StringResult(aValue, this);
michael@0 126 NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY);
michael@0 127 }
michael@0 128 else {
michael@0 129 StringResult* strRes =
michael@0 130 static_cast<StringResult*>(mStringResults.pop());
michael@0 131 strRes->mValue = aValue;
michael@0 132 strRes->mRecycler = this;
michael@0 133 *aResult = strRes;
michael@0 134 }
michael@0 135 NS_ADDREF(*aResult);
michael@0 136
michael@0 137 return NS_OK;
michael@0 138 }
michael@0 139
michael@0 140 void
michael@0 141 txResultRecycler::getEmptyStringResult(txAExprResult** aResult)
michael@0 142 {
michael@0 143 *aResult = mEmptyStringResult;
michael@0 144 NS_ADDREF(*aResult);
michael@0 145 }
michael@0 146
michael@0 147 nsresult
michael@0 148 txResultRecycler::getNodeSet(txNodeSet** aResult)
michael@0 149 {
michael@0 150 if (mNodeSetResults.isEmpty()) {
michael@0 151 *aResult = new txNodeSet(this);
michael@0 152 NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY);
michael@0 153 }
michael@0 154 else {
michael@0 155 *aResult = static_cast<txNodeSet*>(mNodeSetResults.pop());
michael@0 156 (*aResult)->mRecycler = this;
michael@0 157 }
michael@0 158 NS_ADDREF(*aResult);
michael@0 159
michael@0 160 return NS_OK;
michael@0 161 }
michael@0 162
michael@0 163 nsresult
michael@0 164 txResultRecycler::getNodeSet(txNodeSet* aNodeSet, txNodeSet** aResult)
michael@0 165 {
michael@0 166 if (mNodeSetResults.isEmpty()) {
michael@0 167 *aResult = new txNodeSet(*aNodeSet, this);
michael@0 168 NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY);
michael@0 169 }
michael@0 170 else {
michael@0 171 *aResult = static_cast<txNodeSet*>(mNodeSetResults.pop());
michael@0 172 (*aResult)->append(*aNodeSet);
michael@0 173 (*aResult)->mRecycler = this;
michael@0 174 }
michael@0 175 NS_ADDREF(*aResult);
michael@0 176
michael@0 177 return NS_OK;
michael@0 178 }
michael@0 179
michael@0 180 nsresult
michael@0 181 txResultRecycler::getNodeSet(const txXPathNode& aNode, txAExprResult** aResult)
michael@0 182 {
michael@0 183 if (mNodeSetResults.isEmpty()) {
michael@0 184 *aResult = new txNodeSet(aNode, this);
michael@0 185 NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY);
michael@0 186 }
michael@0 187 else {
michael@0 188 txNodeSet* nodes = static_cast<txNodeSet*>(mNodeSetResults.pop());
michael@0 189 nodes->append(aNode);
michael@0 190 nodes->mRecycler = this;
michael@0 191 *aResult = nodes;
michael@0 192 }
michael@0 193 NS_ADDREF(*aResult);
michael@0 194
michael@0 195 return NS_OK;
michael@0 196 }
michael@0 197
michael@0 198 nsresult
michael@0 199 txResultRecycler::getNumberResult(double aValue, txAExprResult** aResult)
michael@0 200 {
michael@0 201 if (mNumberResults.isEmpty()) {
michael@0 202 *aResult = new NumberResult(aValue, this);
michael@0 203 NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY);
michael@0 204 }
michael@0 205 else {
michael@0 206 NumberResult* numRes =
michael@0 207 static_cast<NumberResult*>(mNumberResults.pop());
michael@0 208 numRes->value = aValue;
michael@0 209 numRes->mRecycler = this;
michael@0 210 *aResult = numRes;
michael@0 211 }
michael@0 212 NS_ADDREF(*aResult);
michael@0 213
michael@0 214 return NS_OK;
michael@0 215 }
michael@0 216
michael@0 217 void
michael@0 218 txResultRecycler::getBoolResult(bool aValue, txAExprResult** aResult)
michael@0 219 {
michael@0 220 *aResult = aValue ? mTrueResult : mFalseResult;
michael@0 221 NS_ADDREF(*aResult);
michael@0 222 }
michael@0 223
michael@0 224 nsresult
michael@0 225 txResultRecycler::getNonSharedNodeSet(txNodeSet* aNodeSet, txNodeSet** aResult)
michael@0 226 {
michael@0 227 if (aNodeSet->mRefCnt > 1) {
michael@0 228 return getNodeSet(aNodeSet, aResult);
michael@0 229 }
michael@0 230
michael@0 231 *aResult = aNodeSet;
michael@0 232 NS_ADDREF(*aResult);
michael@0 233
michael@0 234 return NS_OK;
michael@0 235 }
michael@0 236
michael@0 237 void
michael@0 238 txAExprResult::Release()
michael@0 239 {
michael@0 240 --mRefCnt;
michael@0 241 NS_LOG_RELEASE(this, mRefCnt, "txAExprResult");
michael@0 242 if (mRefCnt == 0) {
michael@0 243 if (mRecycler) {
michael@0 244 mRecycler->recycle(this);
michael@0 245 }
michael@0 246 else {
michael@0 247 delete this;
michael@0 248 }
michael@0 249 }
michael@0 250 }

mercurial