Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 : /* This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #include "mozilla/IncrementalClearCOMRuleArray.h"
8 :
9 : #include <algorithm> // For std::min
10 : #include "nsCycleCollector.h"
11 : #include "mozilla/DeferredFinalize.h"
12 : #include "nsTArray.h"
13 : #include "nsCCUncollectableMarker.h"
14 :
15 : using namespace mozilla;
16 :
17 : typedef nsCOMArray<css::Rule> RuleArray;
18 : typedef nsTArray<RuleArray> RuleArrayArray;
19 :
20 :
21 : // These methods are based on those in DeferredFinalizerImpl.
22 :
23 : static void*
24 0 : AppendRulesArrayPointer(void* aData, void* aObject)
25 : {
26 0 : RuleArrayArray* rulesArray = static_cast<RuleArrayArray*>(aData);
27 0 : RuleArray* oldRules = static_cast<RuleArray*>(aObject);
28 :
29 0 : if (!rulesArray) {
30 0 : rulesArray = new RuleArrayArray();
31 : }
32 :
33 0 : RuleArray* newRules = rulesArray->AppendElement();
34 0 : newRules->SwapElements(*oldRules);
35 :
36 0 : return rulesArray;
37 : }
38 :
39 : // Remove up to |aSliceBudget| css::Rules from the arrays, starting at
40 : // the end of the last array.
41 : static bool
42 0 : DeferredFinalizeRulesArray(uint32_t aSliceBudget, void* aData)
43 : {
44 0 : MOZ_ASSERT(aSliceBudget > 0, "nonsensical/useless call with aSliceBudget == 0");
45 0 : RuleArrayArray* rulesArray = static_cast<RuleArrayArray*>(aData);
46 :
47 0 : size_t newOuterLen = rulesArray->Length();
48 :
49 0 : while (aSliceBudget > 0 && newOuterLen > 0) {
50 0 : RuleArray& lastArray = rulesArray->ElementAt(newOuterLen - 1);
51 0 : uint32_t innerLen = lastArray.Length();
52 0 : uint32_t currSlice = std::min(innerLen, aSliceBudget);
53 0 : uint32_t newInnerLen = innerLen - currSlice;
54 0 : lastArray.TruncateLength(newInnerLen);
55 0 : aSliceBudget -= currSlice;
56 0 : if (newInnerLen == 0) {
57 0 : newOuterLen -= 1;
58 : }
59 : }
60 :
61 0 : rulesArray->TruncateLength(newOuterLen);
62 :
63 0 : if (newOuterLen == 0) {
64 0 : delete rulesArray;
65 0 : return true;
66 : }
67 0 : return false;
68 : }
69 :
70 : void
71 81 : IncrementalClearCOMRuleArray::Clear()
72 : {
73 : // Destroy the array incrementally if it is long and we
74 : // haven't started shutting down.
75 81 : if (Length() > 10 && nsCCUncollectableMarker::sGeneration) {
76 0 : DeferredFinalize(AppendRulesArrayPointer, DeferredFinalizeRulesArray, this);
77 : } else {
78 81 : nsCOMArray<css::Rule>::Clear();
79 : }
80 81 : MOZ_ASSERT(Length() == 0);
81 81 : }
|