1*a65addddSAndroid Build Coastguard Worker /*
2*a65addddSAndroid Build Coastguard Worker * Copyright 2014 Google Inc. All rights reserved.
3*a65addddSAndroid Build Coastguard Worker *
4*a65addddSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*a65addddSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*a65addddSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*a65addddSAndroid Build Coastguard Worker *
8*a65addddSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*a65addddSAndroid Build Coastguard Worker *
10*a65addddSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*a65addddSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*a65addddSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*a65addddSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*a65addddSAndroid Build Coastguard Worker * limitations under the License.
15*a65addddSAndroid Build Coastguard Worker */
16*a65addddSAndroid Build Coastguard Worker
17*a65addddSAndroid Build Coastguard Worker #define IN_FRUIT_CPP_FILE 1
18*a65addddSAndroid Build Coastguard Worker
19*a65addddSAndroid Build Coastguard Worker #include <algorithm>
20*a65addddSAndroid Build Coastguard Worker #include <cstdlib>
21*a65addddSAndroid Build Coastguard Worker #include <fruit/impl/util/type_info.h>
22*a65addddSAndroid Build Coastguard Worker #include <iostream>
23*a65addddSAndroid Build Coastguard Worker #include <memory>
24*a65addddSAndroid Build Coastguard Worker #include <vector>
25*a65addddSAndroid Build Coastguard Worker
26*a65addddSAndroid Build Coastguard Worker #include <fruit/impl/data_structures/semistatic_graph.templates.h>
27*a65addddSAndroid Build Coastguard Worker #include <fruit/impl/injector/injector_storage.h>
28*a65addddSAndroid Build Coastguard Worker #include <fruit/impl/normalized_component_storage/binding_normalization.h>
29*a65addddSAndroid Build Coastguard Worker #include <fruit/impl/normalized_component_storage/binding_normalization.templates.h>
30*a65addddSAndroid Build Coastguard Worker #include <fruit/impl/normalized_component_storage/normalized_component_storage.h>
31*a65addddSAndroid Build Coastguard Worker
32*a65addddSAndroid Build Coastguard Worker using std::cout;
33*a65addddSAndroid Build Coastguard Worker using std::endl;
34*a65addddSAndroid Build Coastguard Worker
35*a65addddSAndroid Build Coastguard Worker namespace fruit {
36*a65addddSAndroid Build Coastguard Worker namespace impl {
37*a65addddSAndroid Build Coastguard Worker
printLazyComponentInstallationLoop(const std::vector<ComponentStorageEntry,ArenaAllocator<ComponentStorageEntry>> & entries_to_process,const ComponentStorageEntry & last_entry)38*a65addddSAndroid Build Coastguard Worker void BindingNormalization::printLazyComponentInstallationLoop(
39*a65addddSAndroid Build Coastguard Worker const std::vector<ComponentStorageEntry, ArenaAllocator<ComponentStorageEntry>>& entries_to_process,
40*a65addddSAndroid Build Coastguard Worker const ComponentStorageEntry& last_entry) {
41*a65addddSAndroid Build Coastguard Worker std::cerr << "Found a loop while expanding components passed to PartialComponent::install()." << std::endl;
42*a65addddSAndroid Build Coastguard Worker std::cerr << "Component installation trace (from top-level to the most deeply-nested):" << std::endl;
43*a65addddSAndroid Build Coastguard Worker for (const ComponentStorageEntry& entry : entries_to_process) {
44*a65addddSAndroid Build Coastguard Worker switch (entry.kind) {
45*a65addddSAndroid Build Coastguard Worker case ComponentStorageEntry::Kind::COMPONENT_WITH_ARGS_END_MARKER:
46*a65addddSAndroid Build Coastguard Worker if (entry.type_id == last_entry.type_id &&
47*a65addddSAndroid Build Coastguard Worker last_entry.kind == ComponentStorageEntry::Kind::LAZY_COMPONENT_WITH_ARGS &&
48*a65addddSAndroid Build Coastguard Worker *entry.lazy_component_with_args.component == *last_entry.lazy_component_with_args.component) {
49*a65addddSAndroid Build Coastguard Worker std::cerr << "<-- The loop starts here" << std::endl;
50*a65addddSAndroid Build Coastguard Worker }
51*a65addddSAndroid Build Coastguard Worker std::cerr << std::string(entry.lazy_component_with_args.component->getFunTypeId()) << std::endl;
52*a65addddSAndroid Build Coastguard Worker break;
53*a65addddSAndroid Build Coastguard Worker
54*a65addddSAndroid Build Coastguard Worker case ComponentStorageEntry::Kind::COMPONENT_WITHOUT_ARGS_END_MARKER:
55*a65addddSAndroid Build Coastguard Worker if (entry.type_id == last_entry.type_id &&
56*a65addddSAndroid Build Coastguard Worker last_entry.kind == ComponentStorageEntry::Kind::LAZY_COMPONENT_WITH_NO_ARGS &&
57*a65addddSAndroid Build Coastguard Worker entry.lazy_component_with_no_args.erased_fun == last_entry.lazy_component_with_no_args.erased_fun) {
58*a65addddSAndroid Build Coastguard Worker std::cerr << "<-- The loop starts here" << std::endl;
59*a65addddSAndroid Build Coastguard Worker }
60*a65addddSAndroid Build Coastguard Worker std::cerr << std::string(entry.type_id) << std::endl;
61*a65addddSAndroid Build Coastguard Worker break;
62*a65addddSAndroid Build Coastguard Worker
63*a65addddSAndroid Build Coastguard Worker default:
64*a65addddSAndroid Build Coastguard Worker break;
65*a65addddSAndroid Build Coastguard Worker }
66*a65addddSAndroid Build Coastguard Worker }
67*a65addddSAndroid Build Coastguard Worker
68*a65addddSAndroid Build Coastguard Worker switch (last_entry.kind) { // LCOV_EXCL_BR_LINE
69*a65addddSAndroid Build Coastguard Worker case ComponentStorageEntry::Kind::LAZY_COMPONENT_WITH_ARGS:
70*a65addddSAndroid Build Coastguard Worker std::cerr << std::string(last_entry.lazy_component_with_args.component->getFunTypeId()) << std::endl;
71*a65addddSAndroid Build Coastguard Worker break;
72*a65addddSAndroid Build Coastguard Worker
73*a65addddSAndroid Build Coastguard Worker case ComponentStorageEntry::Kind::LAZY_COMPONENT_WITH_NO_ARGS:
74*a65addddSAndroid Build Coastguard Worker std::cerr << std::string(last_entry.type_id) << std::endl;
75*a65addddSAndroid Build Coastguard Worker break;
76*a65addddSAndroid Build Coastguard Worker
77*a65addddSAndroid Build Coastguard Worker default:
78*a65addddSAndroid Build Coastguard Worker FRUIT_UNREACHABLE; // LCOV_EXCL_LINE
79*a65addddSAndroid Build Coastguard Worker }
80*a65addddSAndroid Build Coastguard Worker
81*a65addddSAndroid Build Coastguard Worker exit(1);
82*a65addddSAndroid Build Coastguard Worker }
83*a65addddSAndroid Build Coastguard Worker
printMultipleBindingsError(TypeId type)84*a65addddSAndroid Build Coastguard Worker void BindingNormalization::printMultipleBindingsError(TypeId type) {
85*a65addddSAndroid Build Coastguard Worker std::cerr << "Fatal injection error: the type " << type.type_info->name()
86*a65addddSAndroid Build Coastguard Worker << " was provided more than once, with different bindings." << std::endl
87*a65addddSAndroid Build Coastguard Worker << "This was not caught at compile time because at least one of the involved components bound this type "
88*a65addddSAndroid Build Coastguard Worker << "but didn't expose it in the component signature." << std::endl
89*a65addddSAndroid Build Coastguard Worker << "If the type has a default constructor or an Inject annotation, this problem may arise even if this "
90*a65addddSAndroid Build Coastguard Worker << "type is bound/provided by only one component (and then hidden), if this type is auto-injected in "
91*a65addddSAndroid Build Coastguard Worker << "another component." << std::endl
92*a65addddSAndroid Build Coastguard Worker << "If the source of the problem is unclear, try exposing this type in all the component signatures where "
93*a65addddSAndroid Build Coastguard Worker << "it's bound; if no component hides it this can't happen." << std::endl;
94*a65addddSAndroid Build Coastguard Worker exit(1);
95*a65addddSAndroid Build Coastguard Worker }
96*a65addddSAndroid Build Coastguard Worker
printIncompatibleComponentReplacementsError(const ComponentStorageEntry & replaced_component_entry,const ComponentStorageEntry & replacement_component_entry1,const ComponentStorageEntry & replacement_component_entry2)97*a65addddSAndroid Build Coastguard Worker void BindingNormalization::printIncompatibleComponentReplacementsError(
98*a65addddSAndroid Build Coastguard Worker const ComponentStorageEntry& replaced_component_entry, const ComponentStorageEntry& replacement_component_entry1,
99*a65addddSAndroid Build Coastguard Worker const ComponentStorageEntry& replacement_component_entry2) {
100*a65addddSAndroid Build Coastguard Worker using fun_t = void (*)();
101*a65addddSAndroid Build Coastguard Worker
102*a65addddSAndroid Build Coastguard Worker fun_t replaced_fun_address;
103*a65addddSAndroid Build Coastguard Worker switch (replaced_component_entry.kind) {
104*a65addddSAndroid Build Coastguard Worker case ComponentStorageEntry::Kind::REPLACED_LAZY_COMPONENT_WITH_ARGS:
105*a65addddSAndroid Build Coastguard Worker replaced_fun_address = replaced_component_entry.lazy_component_with_args.component->erased_fun;
106*a65addddSAndroid Build Coastguard Worker break;
107*a65addddSAndroid Build Coastguard Worker
108*a65addddSAndroid Build Coastguard Worker case ComponentStorageEntry::Kind::REPLACED_LAZY_COMPONENT_WITH_NO_ARGS:
109*a65addddSAndroid Build Coastguard Worker replaced_fun_address = replaced_component_entry.lazy_component_with_no_args.erased_fun;
110*a65addddSAndroid Build Coastguard Worker break;
111*a65addddSAndroid Build Coastguard Worker
112*a65addddSAndroid Build Coastguard Worker default:
113*a65addddSAndroid Build Coastguard Worker FRUIT_UNREACHABLE; // LCOV_EXCL_LINE
114*a65addddSAndroid Build Coastguard Worker }
115*a65addddSAndroid Build Coastguard Worker
116*a65addddSAndroid Build Coastguard Worker fun_t replacement_fun_address1;
117*a65addddSAndroid Build Coastguard Worker switch (replacement_component_entry1.kind) {
118*a65addddSAndroid Build Coastguard Worker case ComponentStorageEntry::Kind::REPLACEMENT_LAZY_COMPONENT_WITH_ARGS:
119*a65addddSAndroid Build Coastguard Worker replacement_fun_address1 = replacement_component_entry1.lazy_component_with_args.component->erased_fun;
120*a65addddSAndroid Build Coastguard Worker break;
121*a65addddSAndroid Build Coastguard Worker
122*a65addddSAndroid Build Coastguard Worker case ComponentStorageEntry::Kind::REPLACEMENT_LAZY_COMPONENT_WITH_NO_ARGS:
123*a65addddSAndroid Build Coastguard Worker replacement_fun_address1 = replacement_component_entry1.lazy_component_with_no_args.erased_fun;
124*a65addddSAndroid Build Coastguard Worker break;
125*a65addddSAndroid Build Coastguard Worker
126*a65addddSAndroid Build Coastguard Worker default:
127*a65addddSAndroid Build Coastguard Worker FRUIT_UNREACHABLE; // LCOV_EXCL_LINE
128*a65addddSAndroid Build Coastguard Worker }
129*a65addddSAndroid Build Coastguard Worker
130*a65addddSAndroid Build Coastguard Worker fun_t replacement_fun_address2;
131*a65addddSAndroid Build Coastguard Worker switch (replacement_component_entry2.kind) {
132*a65addddSAndroid Build Coastguard Worker case ComponentStorageEntry::Kind::REPLACEMENT_LAZY_COMPONENT_WITH_ARGS:
133*a65addddSAndroid Build Coastguard Worker replacement_fun_address2 = replacement_component_entry2.lazy_component_with_args.component->erased_fun;
134*a65addddSAndroid Build Coastguard Worker break;
135*a65addddSAndroid Build Coastguard Worker
136*a65addddSAndroid Build Coastguard Worker case ComponentStorageEntry::Kind::REPLACEMENT_LAZY_COMPONENT_WITH_NO_ARGS:
137*a65addddSAndroid Build Coastguard Worker replacement_fun_address2 = replacement_component_entry2.lazy_component_with_no_args.erased_fun;
138*a65addddSAndroid Build Coastguard Worker break;
139*a65addddSAndroid Build Coastguard Worker
140*a65addddSAndroid Build Coastguard Worker default:
141*a65addddSAndroid Build Coastguard Worker FRUIT_UNREACHABLE; // LCOV_EXCL_LINE
142*a65addddSAndroid Build Coastguard Worker }
143*a65addddSAndroid Build Coastguard Worker
144*a65addddSAndroid Build Coastguard Worker constexpr static bool function_pointers_have_same_size = sizeof(void*) == sizeof(fun_t);
145*a65addddSAndroid Build Coastguard Worker if (function_pointers_have_same_size) {
146*a65addddSAndroid Build Coastguard Worker std::cerr << "Fatal injection error: the component function at " << reinterpret_cast<void*>(replaced_fun_address)
147*a65addddSAndroid Build Coastguard Worker << " with signature " << std::string(replaced_component_entry.type_id)
148*a65addddSAndroid Build Coastguard Worker << " was replaced (using .replace(...).with(...)) with both the component function at "
149*a65addddSAndroid Build Coastguard Worker << reinterpret_cast<void*>(replacement_fun_address1) << " with signature "
150*a65addddSAndroid Build Coastguard Worker << std::string(replacement_component_entry1.type_id) << " and the component function at "
151*a65addddSAndroid Build Coastguard Worker << reinterpret_cast<void*>(replacement_fun_address2) << " with signature "
152*a65addddSAndroid Build Coastguard Worker << std::string(replacement_component_entry2.type_id) << " ." << std::endl;
153*a65addddSAndroid Build Coastguard Worker } else {
154*a65addddSAndroid Build Coastguard Worker std::cerr << "Fatal injection error: a component function with signature "
155*a65addddSAndroid Build Coastguard Worker << std::string(replaced_component_entry.type_id)
156*a65addddSAndroid Build Coastguard Worker << " was replaced (using .replace(...).with(...)) with both a component function with signature "
157*a65addddSAndroid Build Coastguard Worker << std::string(replacement_component_entry1.type_id) << " and another component function with signature "
158*a65addddSAndroid Build Coastguard Worker << std::string(replacement_component_entry2.type_id) << " ." << std::endl;
159*a65addddSAndroid Build Coastguard Worker }
160*a65addddSAndroid Build Coastguard Worker exit(1);
161*a65addddSAndroid Build Coastguard Worker }
162*a65addddSAndroid Build Coastguard Worker
printComponentReplacementFailedBecauseTargetAlreadyExpanded(const ComponentStorageEntry & replaced_component_entry,const ComponentStorageEntry & replacement_component_entry)163*a65addddSAndroid Build Coastguard Worker void BindingNormalization::printComponentReplacementFailedBecauseTargetAlreadyExpanded(
164*a65addddSAndroid Build Coastguard Worker const ComponentStorageEntry& replaced_component_entry, const ComponentStorageEntry& replacement_component_entry) {
165*a65addddSAndroid Build Coastguard Worker using fun_t = void (*)();
166*a65addddSAndroid Build Coastguard Worker
167*a65addddSAndroid Build Coastguard Worker fun_t replaced_fun_address;
168*a65addddSAndroid Build Coastguard Worker switch (replaced_component_entry.kind) {
169*a65addddSAndroid Build Coastguard Worker case ComponentStorageEntry::Kind::REPLACED_LAZY_COMPONENT_WITH_ARGS:
170*a65addddSAndroid Build Coastguard Worker replaced_fun_address = replaced_component_entry.lazy_component_with_args.component->erased_fun;
171*a65addddSAndroid Build Coastguard Worker break;
172*a65addddSAndroid Build Coastguard Worker
173*a65addddSAndroid Build Coastguard Worker case ComponentStorageEntry::Kind::REPLACED_LAZY_COMPONENT_WITH_NO_ARGS:
174*a65addddSAndroid Build Coastguard Worker replaced_fun_address = replaced_component_entry.lazy_component_with_no_args.erased_fun;
175*a65addddSAndroid Build Coastguard Worker break;
176*a65addddSAndroid Build Coastguard Worker
177*a65addddSAndroid Build Coastguard Worker default:
178*a65addddSAndroid Build Coastguard Worker FRUIT_UNREACHABLE; // LCOV_EXCL_LINE
179*a65addddSAndroid Build Coastguard Worker }
180*a65addddSAndroid Build Coastguard Worker
181*a65addddSAndroid Build Coastguard Worker fun_t replacement_fun_address1;
182*a65addddSAndroid Build Coastguard Worker switch (replacement_component_entry.kind) {
183*a65addddSAndroid Build Coastguard Worker case ComponentStorageEntry::Kind::REPLACEMENT_LAZY_COMPONENT_WITH_ARGS:
184*a65addddSAndroid Build Coastguard Worker replacement_fun_address1 = replacement_component_entry.lazy_component_with_args.component->erased_fun;
185*a65addddSAndroid Build Coastguard Worker break;
186*a65addddSAndroid Build Coastguard Worker
187*a65addddSAndroid Build Coastguard Worker case ComponentStorageEntry::Kind::REPLACEMENT_LAZY_COMPONENT_WITH_NO_ARGS:
188*a65addddSAndroid Build Coastguard Worker replacement_fun_address1 = replacement_component_entry.lazy_component_with_no_args.erased_fun;
189*a65addddSAndroid Build Coastguard Worker break;
190*a65addddSAndroid Build Coastguard Worker
191*a65addddSAndroid Build Coastguard Worker default:
192*a65addddSAndroid Build Coastguard Worker FRUIT_UNREACHABLE; // LCOV_EXCL_LINE
193*a65addddSAndroid Build Coastguard Worker }
194*a65addddSAndroid Build Coastguard Worker
195*a65addddSAndroid Build Coastguard Worker constexpr static bool function_pointers_have_same_size = sizeof(void*) == sizeof(fun_t);
196*a65addddSAndroid Build Coastguard Worker if (function_pointers_have_same_size) {
197*a65addddSAndroid Build Coastguard Worker std::cerr << "Fatal injection error: unable to replace (using .replace(...).with(...)) the component function at "
198*a65addddSAndroid Build Coastguard Worker << reinterpret_cast<void*>(replaced_fun_address) << " with signature "
199*a65addddSAndroid Build Coastguard Worker << std::string(replaced_component_entry.type_id) << " with the component function at "
200*a65addddSAndroid Build Coastguard Worker << reinterpret_cast<void*>(replacement_fun_address1) << " with signature "
201*a65addddSAndroid Build Coastguard Worker << std::string(replacement_component_entry.type_id)
202*a65addddSAndroid Build Coastguard Worker << " because the former component function was installed before the .replace(...).with(...)." << std::endl
203*a65addddSAndroid Build Coastguard Worker << "You should change the order of installation of subcomponents so that .replace(...).with(...) is "
204*a65addddSAndroid Build Coastguard Worker << "processed before the installation of the component to replace.";
205*a65addddSAndroid Build Coastguard Worker } else {
206*a65addddSAndroid Build Coastguard Worker std::cerr << "Fatal injection error: unable to replace (using .replace(...).with(...)) a component function with "
207*a65addddSAndroid Build Coastguard Worker << "signature " << std::string(replaced_component_entry.type_id)
208*a65addddSAndroid Build Coastguard Worker << " with a component function at with signature " << std::string(replacement_component_entry.type_id)
209*a65addddSAndroid Build Coastguard Worker << " because the former component function was installed before the .replace(...).with(...)." << std::endl
210*a65addddSAndroid Build Coastguard Worker << "You should change the order of installation of subcomponents so that .replace(...).with(...) is "
211*a65addddSAndroid Build Coastguard Worker << "processed before the installation of the component to replace.";
212*a65addddSAndroid Build Coastguard Worker }
213*a65addddSAndroid Build Coastguard Worker exit(1);
214*a65addddSAndroid Build Coastguard Worker }
215*a65addddSAndroid Build Coastguard Worker
addMultibindings(std::unordered_map<TypeId,NormalizedMultibindingSet> & multibindings,FixedSizeAllocator::FixedSizeAllocatorData & fixed_size_allocator_data,const multibindings_vector_t & multibindingsVector)216*a65addddSAndroid Build Coastguard Worker void BindingNormalization::addMultibindings(std::unordered_map<TypeId, NormalizedMultibindingSet>& multibindings,
217*a65addddSAndroid Build Coastguard Worker FixedSizeAllocator::FixedSizeAllocatorData& fixed_size_allocator_data,
218*a65addddSAndroid Build Coastguard Worker const multibindings_vector_t& multibindingsVector) {
219*a65addddSAndroid Build Coastguard Worker
220*a65addddSAndroid Build Coastguard Worker #if FRUIT_EXTRA_DEBUG
221*a65addddSAndroid Build Coastguard Worker std::cout << "InjectorStorage: adding multibindings:" << std::endl;
222*a65addddSAndroid Build Coastguard Worker #endif
223*a65addddSAndroid Build Coastguard Worker // Now we must merge multiple bindings for the same type.
224*a65addddSAndroid Build Coastguard Worker for (auto i = multibindingsVector.begin(); i != multibindingsVector.end(); ++i) {
225*a65addddSAndroid Build Coastguard Worker const ComponentStorageEntry& multibinding_entry = i->first;
226*a65addddSAndroid Build Coastguard Worker const ComponentStorageEntry& multibinding_vector_creator_entry = i->second;
227*a65addddSAndroid Build Coastguard Worker FruitAssert(multibinding_entry.kind ==
228*a65addddSAndroid Build Coastguard Worker ComponentStorageEntry::Kind::MULTIBINDING_FOR_OBJECT_TO_CONSTRUCT_THAT_NEEDS_NO_ALLOCATION ||
229*a65addddSAndroid Build Coastguard Worker multibinding_entry.kind ==
230*a65addddSAndroid Build Coastguard Worker ComponentStorageEntry::Kind::MULTIBINDING_FOR_OBJECT_TO_CONSTRUCT_THAT_NEEDS_ALLOCATION ||
231*a65addddSAndroid Build Coastguard Worker multibinding_entry.kind == ComponentStorageEntry::Kind::MULTIBINDING_FOR_CONSTRUCTED_OBJECT);
232*a65addddSAndroid Build Coastguard Worker FruitAssert(multibinding_vector_creator_entry.kind == ComponentStorageEntry::Kind::MULTIBINDING_VECTOR_CREATOR);
233*a65addddSAndroid Build Coastguard Worker NormalizedMultibindingSet& b = multibindings[multibinding_entry.type_id];
234*a65addddSAndroid Build Coastguard Worker
235*a65addddSAndroid Build Coastguard Worker // Might be set already, but we need to set it if there was no multibinding for this type.
236*a65addddSAndroid Build Coastguard Worker b.get_multibindings_vector = multibinding_vector_creator_entry.multibinding_vector_creator.get_multibindings_vector;
237*a65addddSAndroid Build Coastguard Worker
238*a65addddSAndroid Build Coastguard Worker switch (i->first.kind) { // LCOV_EXCL_BR_LINE
239*a65addddSAndroid Build Coastguard Worker case ComponentStorageEntry::Kind::MULTIBINDING_FOR_CONSTRUCTED_OBJECT: {
240*a65addddSAndroid Build Coastguard Worker NormalizedMultibinding normalized_multibinding;
241*a65addddSAndroid Build Coastguard Worker normalized_multibinding.is_constructed = true;
242*a65addddSAndroid Build Coastguard Worker normalized_multibinding.object = i->first.multibinding_for_constructed_object.object_ptr;
243*a65addddSAndroid Build Coastguard Worker b.elems.push_back(normalized_multibinding);
244*a65addddSAndroid Build Coastguard Worker } break;
245*a65addddSAndroid Build Coastguard Worker
246*a65addddSAndroid Build Coastguard Worker case ComponentStorageEntry::Kind::MULTIBINDING_FOR_OBJECT_TO_CONSTRUCT_THAT_NEEDS_NO_ALLOCATION: {
247*a65addddSAndroid Build Coastguard Worker fixed_size_allocator_data.addExternallyAllocatedType(i->first.type_id);
248*a65addddSAndroid Build Coastguard Worker NormalizedMultibinding normalized_multibinding;
249*a65addddSAndroid Build Coastguard Worker normalized_multibinding.is_constructed = false;
250*a65addddSAndroid Build Coastguard Worker normalized_multibinding.create = i->first.multibinding_for_object_to_construct.create;
251*a65addddSAndroid Build Coastguard Worker b.elems.push_back(normalized_multibinding);
252*a65addddSAndroid Build Coastguard Worker } break;
253*a65addddSAndroid Build Coastguard Worker
254*a65addddSAndroid Build Coastguard Worker case ComponentStorageEntry::Kind::MULTIBINDING_FOR_OBJECT_TO_CONSTRUCT_THAT_NEEDS_ALLOCATION: {
255*a65addddSAndroid Build Coastguard Worker fixed_size_allocator_data.addType(i->first.type_id);
256*a65addddSAndroid Build Coastguard Worker NormalizedMultibinding normalized_multibinding;
257*a65addddSAndroid Build Coastguard Worker normalized_multibinding.is_constructed = false;
258*a65addddSAndroid Build Coastguard Worker normalized_multibinding.create = i->first.multibinding_for_object_to_construct.create;
259*a65addddSAndroid Build Coastguard Worker b.elems.push_back(normalized_multibinding);
260*a65addddSAndroid Build Coastguard Worker } break;
261*a65addddSAndroid Build Coastguard Worker
262*a65addddSAndroid Build Coastguard Worker default:
263*a65addddSAndroid Build Coastguard Worker #if FRUIT_EXTRA_DEBUG
264*a65addddSAndroid Build Coastguard Worker std::cerr << "Unexpected kind: " << (std::size_t)i->first.kind << std::endl;
265*a65addddSAndroid Build Coastguard Worker #endif
266*a65addddSAndroid Build Coastguard Worker FRUIT_UNREACHABLE; // LCOV_EXCL_LINE
267*a65addddSAndroid Build Coastguard Worker }
268*a65addddSAndroid Build Coastguard Worker }
269*a65addddSAndroid Build Coastguard Worker }
270*a65addddSAndroid Build Coastguard Worker
normalizeBindingsWithUndoableBindingCompression(FixedSizeVector<ComponentStorageEntry> && toplevel_entries,FixedSizeAllocator::FixedSizeAllocatorData & fixed_size_allocator_data,MemoryPool & memory_pool,MemoryPool & memory_pool_for_fully_expanded_components_maps,MemoryPool & memory_pool_for_component_replacements_maps,const std::vector<TypeId,ArenaAllocator<TypeId>> & exposed_types,std::vector<ComponentStorageEntry,ArenaAllocator<ComponentStorageEntry>> & bindings_vector,std::unordered_map<TypeId,NormalizedMultibindingSet> & multibindings,BindingCompressionInfoMap & bindingCompressionInfoMap,LazyComponentWithNoArgsSet & fully_expanded_components_with_no_args,LazyComponentWithArgsSet & fully_expanded_components_with_args,LazyComponentWithNoArgsReplacementMap & component_with_no_args_replacements,LazyComponentWithArgsReplacementMap & component_with_args_replacements)271*a65addddSAndroid Build Coastguard Worker void BindingNormalization::normalizeBindingsWithUndoableBindingCompression(
272*a65addddSAndroid Build Coastguard Worker FixedSizeVector<ComponentStorageEntry>&& toplevel_entries,
273*a65addddSAndroid Build Coastguard Worker FixedSizeAllocator::FixedSizeAllocatorData& fixed_size_allocator_data, MemoryPool& memory_pool,
274*a65addddSAndroid Build Coastguard Worker MemoryPool& memory_pool_for_fully_expanded_components_maps, MemoryPool& memory_pool_for_component_replacements_maps,
275*a65addddSAndroid Build Coastguard Worker const std::vector<TypeId, ArenaAllocator<TypeId>>& exposed_types,
276*a65addddSAndroid Build Coastguard Worker std::vector<ComponentStorageEntry, ArenaAllocator<ComponentStorageEntry>>& bindings_vector,
277*a65addddSAndroid Build Coastguard Worker std::unordered_map<TypeId, NormalizedMultibindingSet>& multibindings,
278*a65addddSAndroid Build Coastguard Worker BindingCompressionInfoMap& bindingCompressionInfoMap,
279*a65addddSAndroid Build Coastguard Worker LazyComponentWithNoArgsSet& fully_expanded_components_with_no_args,
280*a65addddSAndroid Build Coastguard Worker LazyComponentWithArgsSet& fully_expanded_components_with_args,
281*a65addddSAndroid Build Coastguard Worker LazyComponentWithNoArgsReplacementMap& component_with_no_args_replacements,
282*a65addddSAndroid Build Coastguard Worker LazyComponentWithArgsReplacementMap& component_with_args_replacements) {
283*a65addddSAndroid Build Coastguard Worker
284*a65addddSAndroid Build Coastguard Worker FruitAssert(bindingCompressionInfoMap.empty());
285*a65addddSAndroid Build Coastguard Worker
286*a65addddSAndroid Build Coastguard Worker normalizeBindingsWithBindingCompression(
287*a65addddSAndroid Build Coastguard Worker std::move(toplevel_entries), fixed_size_allocator_data, memory_pool,
288*a65addddSAndroid Build Coastguard Worker memory_pool_for_fully_expanded_components_maps, memory_pool_for_component_replacements_maps, exposed_types,
289*a65addddSAndroid Build Coastguard Worker bindings_vector, multibindings,
290*a65addddSAndroid Build Coastguard Worker [&bindingCompressionInfoMap](TypeId c_type_id, NormalizedComponentStorage::CompressedBindingUndoInfo undo_info) {
291*a65addddSAndroid Build Coastguard Worker bindingCompressionInfoMap[c_type_id] = undo_info;
292*a65addddSAndroid Build Coastguard Worker },
293*a65addddSAndroid Build Coastguard Worker [&fully_expanded_components_with_no_args, &memory_pool](LazyComponentWithNoArgsSet& fully_expanded_components) {
294*a65addddSAndroid Build Coastguard Worker fully_expanded_components_with_no_args = std::move(fully_expanded_components);
295*a65addddSAndroid Build Coastguard Worker fully_expanded_components = NormalizedComponentStorage::createLazyComponentWithNoArgsSet(0, memory_pool);
296*a65addddSAndroid Build Coastguard Worker },
297*a65addddSAndroid Build Coastguard Worker [&fully_expanded_components_with_args, &memory_pool](LazyComponentWithArgsSet& fully_expanded_components) {
298*a65addddSAndroid Build Coastguard Worker fully_expanded_components_with_args = std::move(fully_expanded_components);
299*a65addddSAndroid Build Coastguard Worker fully_expanded_components = NormalizedComponentStorage::createLazyComponentWithArgsSet(0, memory_pool);
300*a65addddSAndroid Build Coastguard Worker },
301*a65addddSAndroid Build Coastguard Worker [&component_with_no_args_replacements, &memory_pool](LazyComponentWithNoArgsReplacementMap& component_replacements) {
302*a65addddSAndroid Build Coastguard Worker component_with_no_args_replacements = std::move(component_replacements);
303*a65addddSAndroid Build Coastguard Worker component_replacements = NormalizedComponentStorage::createLazyComponentWithNoArgsReplacementMap(0, memory_pool);
304*a65addddSAndroid Build Coastguard Worker },
305*a65addddSAndroid Build Coastguard Worker [&component_with_args_replacements, &memory_pool](LazyComponentWithArgsReplacementMap& component_replacements) {
306*a65addddSAndroid Build Coastguard Worker component_with_args_replacements = std::move(component_replacements);
307*a65addddSAndroid Build Coastguard Worker component_replacements = NormalizedComponentStorage::createLazyComponentWithArgsReplacementMap(0, memory_pool);
308*a65addddSAndroid Build Coastguard Worker });
309*a65addddSAndroid Build Coastguard Worker }
310*a65addddSAndroid Build Coastguard Worker
normalizeBindingsWithPermanentBindingCompression(FixedSizeVector<ComponentStorageEntry> && toplevel_entries,FixedSizeAllocator::FixedSizeAllocatorData & fixed_size_allocator_data,MemoryPool & memory_pool,const std::vector<TypeId,ArenaAllocator<TypeId>> & exposed_types,std::vector<ComponentStorageEntry,ArenaAllocator<ComponentStorageEntry>> & bindings_vector,std::unordered_map<TypeId,NormalizedMultibindingSet> & multibindings)311*a65addddSAndroid Build Coastguard Worker void BindingNormalization::normalizeBindingsWithPermanentBindingCompression(
312*a65addddSAndroid Build Coastguard Worker FixedSizeVector<ComponentStorageEntry>&& toplevel_entries,
313*a65addddSAndroid Build Coastguard Worker FixedSizeAllocator::FixedSizeAllocatorData& fixed_size_allocator_data, MemoryPool& memory_pool,
314*a65addddSAndroid Build Coastguard Worker const std::vector<TypeId, ArenaAllocator<TypeId>>& exposed_types,
315*a65addddSAndroid Build Coastguard Worker std::vector<ComponentStorageEntry, ArenaAllocator<ComponentStorageEntry>>& bindings_vector,
316*a65addddSAndroid Build Coastguard Worker std::unordered_map<TypeId, NormalizedMultibindingSet>& multibindings) {
317*a65addddSAndroid Build Coastguard Worker normalizeBindingsWithBindingCompression(
318*a65addddSAndroid Build Coastguard Worker std::move(toplevel_entries), fixed_size_allocator_data, memory_pool, memory_pool, memory_pool, exposed_types,
319*a65addddSAndroid Build Coastguard Worker bindings_vector, multibindings, [](TypeId, NormalizedComponentStorage::CompressedBindingUndoInfo) {},
320*a65addddSAndroid Build Coastguard Worker [](LazyComponentWithNoArgsSet&) {}, [](LazyComponentWithArgsSet&) {},
321*a65addddSAndroid Build Coastguard Worker [](LazyComponentWithNoArgsReplacementMap&) {}, [](LazyComponentWithArgsReplacementMap&) {});
322*a65addddSAndroid Build Coastguard Worker }
323*a65addddSAndroid Build Coastguard Worker
normalizeBindingsAndAddTo(FixedSizeVector<ComponentStorageEntry> && toplevel_entries,MemoryPool & memory_pool,const NormalizedComponentStorage & base_normalized_component,FixedSizeAllocator::FixedSizeAllocatorData & fixed_size_allocator_data,std::vector<ComponentStorageEntry,ArenaAllocator<ComponentStorageEntry>> & new_bindings_vector,std::unordered_map<TypeId,NormalizedMultibindingSet> & multibindings)324*a65addddSAndroid Build Coastguard Worker void BindingNormalization::normalizeBindingsAndAddTo(
325*a65addddSAndroid Build Coastguard Worker FixedSizeVector<ComponentStorageEntry>&& toplevel_entries, MemoryPool& memory_pool,
326*a65addddSAndroid Build Coastguard Worker const NormalizedComponentStorage& base_normalized_component,
327*a65addddSAndroid Build Coastguard Worker FixedSizeAllocator::FixedSizeAllocatorData& fixed_size_allocator_data,
328*a65addddSAndroid Build Coastguard Worker std::vector<ComponentStorageEntry, ArenaAllocator<ComponentStorageEntry>>& new_bindings_vector,
329*a65addddSAndroid Build Coastguard Worker std::unordered_map<TypeId, NormalizedMultibindingSet>& multibindings) {
330*a65addddSAndroid Build Coastguard Worker
331*a65addddSAndroid Build Coastguard Worker multibindings = base_normalized_component.multibindings;
332*a65addddSAndroid Build Coastguard Worker
333*a65addddSAndroid Build Coastguard Worker fixed_size_allocator_data = base_normalized_component.fixed_size_allocator_data;
334*a65addddSAndroid Build Coastguard Worker
335*a65addddSAndroid Build Coastguard Worker multibindings_vector_t multibindings_vector =
336*a65addddSAndroid Build Coastguard Worker multibindings_vector_t(ArenaAllocator<multibindings_vector_elem_t>(memory_pool));
337*a65addddSAndroid Build Coastguard Worker
338*a65addddSAndroid Build Coastguard Worker HashMapWithArenaAllocator<TypeId, ComponentStorageEntry> binding_data_map =
339*a65addddSAndroid Build Coastguard Worker createHashMapWithArenaAllocator<TypeId, ComponentStorageEntry>(20 /* capacity */, memory_pool);
340*a65addddSAndroid Build Coastguard Worker
341*a65addddSAndroid Build Coastguard Worker using Graph = NormalizedComponentStorage::Graph;
342*a65addddSAndroid Build Coastguard Worker
343*a65addddSAndroid Build Coastguard Worker normalizeBindings(
344*a65addddSAndroid Build Coastguard Worker std::move(toplevel_entries), fixed_size_allocator_data, memory_pool, memory_pool, memory_pool, binding_data_map,
345*a65addddSAndroid Build Coastguard Worker [](ComponentStorageEntry) {},
346*a65addddSAndroid Build Coastguard Worker [&multibindings_vector](ComponentStorageEntry multibinding, ComponentStorageEntry multibinding_vector_creator) {
347*a65addddSAndroid Build Coastguard Worker multibindings_vector.emplace_back(multibinding, multibinding_vector_creator);
348*a65addddSAndroid Build Coastguard Worker },
349*a65addddSAndroid Build Coastguard Worker [&base_normalized_component](TypeId type_id) { return base_normalized_component.bindings.find(type_id); },
350*a65addddSAndroid Build Coastguard Worker [&base_normalized_component](Graph::const_node_iterator itr) {
351*a65addddSAndroid Build Coastguard Worker return !(itr == base_normalized_component.bindings.end());
352*a65addddSAndroid Build Coastguard Worker },
353*a65addddSAndroid Build Coastguard Worker [](Graph::const_node_iterator itr) { return itr.isTerminal(); },
354*a65addddSAndroid Build Coastguard Worker [](Graph::const_node_iterator itr) { return itr.getNode().object; },
355*a65addddSAndroid Build Coastguard Worker [](Graph::const_node_iterator itr) { return itr.getNode().create; },
356*a65addddSAndroid Build Coastguard Worker [&base_normalized_component](const LazyComponentWithNoArgs& lazy_component) {
357*a65addddSAndroid Build Coastguard Worker return base_normalized_component.fully_expanded_components_with_no_args.count(lazy_component) != 0;
358*a65addddSAndroid Build Coastguard Worker },
359*a65addddSAndroid Build Coastguard Worker [&base_normalized_component](const LazyComponentWithArgs& lazy_component) {
360*a65addddSAndroid Build Coastguard Worker return base_normalized_component.fully_expanded_components_with_args.count(lazy_component) != 0;
361*a65addddSAndroid Build Coastguard Worker },
362*a65addddSAndroid Build Coastguard Worker [](LazyComponentWithNoArgsSet&) {}, [](LazyComponentWithArgsSet&) {},
363*a65addddSAndroid Build Coastguard Worker [&base_normalized_component](const LazyComponentWithNoArgs& lazy_component) {
364*a65addddSAndroid Build Coastguard Worker return base_normalized_component.component_with_no_args_replacements.find(lazy_component);
365*a65addddSAndroid Build Coastguard Worker },
366*a65addddSAndroid Build Coastguard Worker [&base_normalized_component](const LazyComponentWithArgs& lazy_component) {
367*a65addddSAndroid Build Coastguard Worker return base_normalized_component.component_with_args_replacements.find(lazy_component);
368*a65addddSAndroid Build Coastguard Worker },
369*a65addddSAndroid Build Coastguard Worker [&base_normalized_component](typename LazyComponentWithNoArgsReplacementMap::const_iterator itr) {
370*a65addddSAndroid Build Coastguard Worker return itr != base_normalized_component.component_with_no_args_replacements.end();
371*a65addddSAndroid Build Coastguard Worker },
372*a65addddSAndroid Build Coastguard Worker [&base_normalized_component](typename LazyComponentWithArgsReplacementMap::const_iterator itr) {
373*a65addddSAndroid Build Coastguard Worker return itr != base_normalized_component.component_with_args_replacements.end();
374*a65addddSAndroid Build Coastguard Worker },
375*a65addddSAndroid Build Coastguard Worker [](typename LazyComponentWithNoArgsReplacementMap::const_iterator itr) { return itr->second; },
376*a65addddSAndroid Build Coastguard Worker [](typename LazyComponentWithArgsReplacementMap::const_iterator itr) { return itr->second; },
377*a65addddSAndroid Build Coastguard Worker [](LazyComponentWithNoArgsReplacementMap&) {}, [](LazyComponentWithArgsReplacementMap&) {});
378*a65addddSAndroid Build Coastguard Worker
379*a65addddSAndroid Build Coastguard Worker // Copy the normalized bindings into the result vector.
380*a65addddSAndroid Build Coastguard Worker new_bindings_vector.clear();
381*a65addddSAndroid Build Coastguard Worker new_bindings_vector.reserve(binding_data_map.size());
382*a65addddSAndroid Build Coastguard Worker for (auto& p : binding_data_map) {
383*a65addddSAndroid Build Coastguard Worker new_bindings_vector.push_back(p.second);
384*a65addddSAndroid Build Coastguard Worker }
385*a65addddSAndroid Build Coastguard Worker
386*a65addddSAndroid Build Coastguard Worker // Determine what binding compressions must be undone.
387*a65addddSAndroid Build Coastguard Worker
388*a65addddSAndroid Build Coastguard Worker HashSetWithArenaAllocator<TypeId> binding_compressions_to_undo =
389*a65addddSAndroid Build Coastguard Worker createHashSetWithArenaAllocator<TypeId>(20 /* capacity */, memory_pool);
390*a65addddSAndroid Build Coastguard Worker for (const ComponentStorageEntry& entry : new_bindings_vector) {
391*a65addddSAndroid Build Coastguard Worker switch (entry.kind) { // LCOV_EXCL_BR_LINE
392*a65addddSAndroid Build Coastguard Worker case ComponentStorageEntry::Kind::BINDING_FOR_CONSTRUCTED_OBJECT:
393*a65addddSAndroid Build Coastguard Worker break;
394*a65addddSAndroid Build Coastguard Worker
395*a65addddSAndroid Build Coastguard Worker case ComponentStorageEntry::Kind::BINDING_FOR_OBJECT_TO_CONSTRUCT_THAT_NEEDS_NO_ALLOCATION:
396*a65addddSAndroid Build Coastguard Worker case ComponentStorageEntry::Kind::BINDING_FOR_OBJECT_TO_CONSTRUCT_THAT_NEEDS_ALLOCATION:
397*a65addddSAndroid Build Coastguard Worker case ComponentStorageEntry::Kind::BINDING_FOR_OBJECT_TO_CONSTRUCT_WITH_UNKNOWN_ALLOCATION: {
398*a65addddSAndroid Build Coastguard Worker const BindingDeps* entry_deps = entry.binding_for_object_to_construct.deps;
399*a65addddSAndroid Build Coastguard Worker for (std::size_t i = 0; i < entry_deps->num_deps; ++i) {
400*a65addddSAndroid Build Coastguard Worker auto binding_compression_itr = base_normalized_component.binding_compression_info_map.find(entry_deps->deps[i]);
401*a65addddSAndroid Build Coastguard Worker if (binding_compression_itr != base_normalized_component.binding_compression_info_map.end() &&
402*a65addddSAndroid Build Coastguard Worker binding_compression_itr->second.i_type_id != entry.type_id) {
403*a65addddSAndroid Build Coastguard Worker // The binding compression for `p.second.getDeps()->deps[i]' must be undone because something
404*a65addddSAndroid Build Coastguard Worker // different from binding_compression_itr->iTypeId is now bound to it.
405*a65addddSAndroid Build Coastguard Worker binding_compressions_to_undo.insert(entry_deps->deps[i]);
406*a65addddSAndroid Build Coastguard Worker }
407*a65addddSAndroid Build Coastguard Worker }
408*a65addddSAndroid Build Coastguard Worker } break;
409*a65addddSAndroid Build Coastguard Worker
410*a65addddSAndroid Build Coastguard Worker default:
411*a65addddSAndroid Build Coastguard Worker #if FRUIT_EXTRA_DEBUG
412*a65addddSAndroid Build Coastguard Worker std::cerr << "Unexpected kind: " << (std::size_t)entry.kind << std::endl;
413*a65addddSAndroid Build Coastguard Worker #endif
414*a65addddSAndroid Build Coastguard Worker FRUIT_UNREACHABLE; // LCOV_EXCL_LINE
415*a65addddSAndroid Build Coastguard Worker break;
416*a65addddSAndroid Build Coastguard Worker }
417*a65addddSAndroid Build Coastguard Worker }
418*a65addddSAndroid Build Coastguard Worker
419*a65addddSAndroid Build Coastguard Worker // Step 3: undo any binding compressions that can no longer be applied.
420*a65addddSAndroid Build Coastguard Worker for (TypeId cTypeId : binding_compressions_to_undo) {
421*a65addddSAndroid Build Coastguard Worker auto binding_compression_itr = base_normalized_component.binding_compression_info_map.find(cTypeId);
422*a65addddSAndroid Build Coastguard Worker FruitAssert(binding_compression_itr != base_normalized_component.binding_compression_info_map.end());
423*a65addddSAndroid Build Coastguard Worker FruitAssert(!(base_normalized_component.bindings.find(binding_compression_itr->second.i_type_id) ==
424*a65addddSAndroid Build Coastguard Worker base_normalized_component.bindings.end()));
425*a65addddSAndroid Build Coastguard Worker
426*a65addddSAndroid Build Coastguard Worker ComponentStorageEntry c_binding;
427*a65addddSAndroid Build Coastguard Worker c_binding.type_id = cTypeId;
428*a65addddSAndroid Build Coastguard Worker c_binding.kind = ComponentStorageEntry::Kind::BINDING_FOR_OBJECT_TO_CONSTRUCT_WITH_UNKNOWN_ALLOCATION;
429*a65addddSAndroid Build Coastguard Worker c_binding.binding_for_object_to_construct = binding_compression_itr->second.c_binding;
430*a65addddSAndroid Build Coastguard Worker
431*a65addddSAndroid Build Coastguard Worker ComponentStorageEntry i_binding;
432*a65addddSAndroid Build Coastguard Worker i_binding.type_id = binding_compression_itr->second.i_type_id;
433*a65addddSAndroid Build Coastguard Worker i_binding.kind = ComponentStorageEntry::Kind::BINDING_FOR_OBJECT_TO_CONSTRUCT_THAT_NEEDS_NO_ALLOCATION;
434*a65addddSAndroid Build Coastguard Worker i_binding.binding_for_object_to_construct = binding_compression_itr->second.i_binding;
435*a65addddSAndroid Build Coastguard Worker
436*a65addddSAndroid Build Coastguard Worker new_bindings_vector.push_back(c_binding);
437*a65addddSAndroid Build Coastguard Worker // This TypeId is already in normalized_component.bindings, we overwrite it here.
438*a65addddSAndroid Build Coastguard Worker new_bindings_vector.push_back(i_binding);
439*a65addddSAndroid Build Coastguard Worker
440*a65addddSAndroid Build Coastguard Worker #if FRUIT_EXTRA_DEBUG
441*a65addddSAndroid Build Coastguard Worker std::cout << "InjectorStorage: undoing binding compression for: " << binding_compression_itr->second.i_type_id
442*a65addddSAndroid Build Coastguard Worker << "->" << cTypeId << std::endl;
443*a65addddSAndroid Build Coastguard Worker #endif
444*a65addddSAndroid Build Coastguard Worker }
445*a65addddSAndroid Build Coastguard Worker
446*a65addddSAndroid Build Coastguard Worker // Step 4: Add multibindings.
447*a65addddSAndroid Build Coastguard Worker BindingNormalization::addMultibindings(multibindings, fixed_size_allocator_data, multibindings_vector);
448*a65addddSAndroid Build Coastguard Worker }
449*a65addddSAndroid Build Coastguard Worker
handlePreexistingLazyComponentWithArgsReplacement(ComponentStorageEntry & replaced_component_entry,const ComponentStorageEntry & preexisting_replacement,ComponentStorageEntry & new_replacement)450*a65addddSAndroid Build Coastguard Worker void BindingNormalization::handlePreexistingLazyComponentWithArgsReplacement(
451*a65addddSAndroid Build Coastguard Worker ComponentStorageEntry& replaced_component_entry, const ComponentStorageEntry& preexisting_replacement,
452*a65addddSAndroid Build Coastguard Worker ComponentStorageEntry& new_replacement) {
453*a65addddSAndroid Build Coastguard Worker switch (new_replacement.kind) { // LCOV_EXCL_BR_LINE
454*a65addddSAndroid Build Coastguard Worker case ComponentStorageEntry::Kind::REPLACEMENT_LAZY_COMPONENT_WITH_NO_ARGS:
455*a65addddSAndroid Build Coastguard Worker if (preexisting_replacement.kind != ComponentStorageEntry::Kind::REPLACEMENT_LAZY_COMPONENT_WITH_NO_ARGS ||
456*a65addddSAndroid Build Coastguard Worker preexisting_replacement.lazy_component_with_no_args.erased_fun !=
457*a65addddSAndroid Build Coastguard Worker new_replacement.lazy_component_with_no_args.erased_fun) {
458*a65addddSAndroid Build Coastguard Worker printIncompatibleComponentReplacementsError(replaced_component_entry, new_replacement, preexisting_replacement);
459*a65addddSAndroid Build Coastguard Worker FRUIT_UNREACHABLE; // LCOV_EXCL_LINE
460*a65addddSAndroid Build Coastguard Worker }
461*a65addddSAndroid Build Coastguard Worker
462*a65addddSAndroid Build Coastguard Worker // Duplicate but consistent replacement, we'll ignore it.
463*a65addddSAndroid Build Coastguard Worker replaced_component_entry.lazy_component_with_args.destroy();
464*a65addddSAndroid Build Coastguard Worker break;
465*a65addddSAndroid Build Coastguard Worker
466*a65addddSAndroid Build Coastguard Worker case ComponentStorageEntry::Kind::REPLACEMENT_LAZY_COMPONENT_WITH_ARGS:
467*a65addddSAndroid Build Coastguard Worker if (preexisting_replacement.kind != ComponentStorageEntry::Kind::REPLACEMENT_LAZY_COMPONENT_WITH_ARGS ||
468*a65addddSAndroid Build Coastguard Worker !(*preexisting_replacement.lazy_component_with_args.component ==
469*a65addddSAndroid Build Coastguard Worker *new_replacement.lazy_component_with_args.component)) {
470*a65addddSAndroid Build Coastguard Worker printIncompatibleComponentReplacementsError(replaced_component_entry, new_replacement, preexisting_replacement);
471*a65addddSAndroid Build Coastguard Worker FRUIT_UNREACHABLE; // LCOV_EXCL_LINE
472*a65addddSAndroid Build Coastguard Worker }
473*a65addddSAndroid Build Coastguard Worker
474*a65addddSAndroid Build Coastguard Worker // Duplicate but consistent replacement, we'll ignore it.
475*a65addddSAndroid Build Coastguard Worker replaced_component_entry.lazy_component_with_args.destroy();
476*a65addddSAndroid Build Coastguard Worker new_replacement.lazy_component_with_args.destroy();
477*a65addddSAndroid Build Coastguard Worker break;
478*a65addddSAndroid Build Coastguard Worker
479*a65addddSAndroid Build Coastguard Worker default:
480*a65addddSAndroid Build Coastguard Worker FRUIT_UNREACHABLE; // LCOV_EXCL_LINE
481*a65addddSAndroid Build Coastguard Worker }
482*a65addddSAndroid Build Coastguard Worker }
483*a65addddSAndroid Build Coastguard Worker
handlePreexistingLazyComponentWithNoArgsReplacement(ComponentStorageEntry & replaced_component_entry,const ComponentStorageEntry & preexisting_replacement,ComponentStorageEntry & new_replacement)484*a65addddSAndroid Build Coastguard Worker void BindingNormalization::handlePreexistingLazyComponentWithNoArgsReplacement(
485*a65addddSAndroid Build Coastguard Worker ComponentStorageEntry& replaced_component_entry, const ComponentStorageEntry& preexisting_replacement,
486*a65addddSAndroid Build Coastguard Worker ComponentStorageEntry& new_replacement) {
487*a65addddSAndroid Build Coastguard Worker switch (new_replacement.kind) { // LCOV_EXCL_BR_LINE
488*a65addddSAndroid Build Coastguard Worker case ComponentStorageEntry::Kind::REPLACEMENT_LAZY_COMPONENT_WITH_NO_ARGS:
489*a65addddSAndroid Build Coastguard Worker if (preexisting_replacement.kind != ComponentStorageEntry::Kind::REPLACEMENT_LAZY_COMPONENT_WITH_NO_ARGS ||
490*a65addddSAndroid Build Coastguard Worker preexisting_replacement.lazy_component_with_no_args.erased_fun !=
491*a65addddSAndroid Build Coastguard Worker new_replacement.lazy_component_with_no_args.erased_fun) {
492*a65addddSAndroid Build Coastguard Worker printIncompatibleComponentReplacementsError(replaced_component_entry, new_replacement, preexisting_replacement);
493*a65addddSAndroid Build Coastguard Worker FRUIT_UNREACHABLE; // LCOV_EXCL_LINE
494*a65addddSAndroid Build Coastguard Worker }
495*a65addddSAndroid Build Coastguard Worker
496*a65addddSAndroid Build Coastguard Worker // Duplicate but consistent replacement, we'll ignore it.
497*a65addddSAndroid Build Coastguard Worker break;
498*a65addddSAndroid Build Coastguard Worker
499*a65addddSAndroid Build Coastguard Worker case ComponentStorageEntry::Kind::REPLACEMENT_LAZY_COMPONENT_WITH_ARGS:
500*a65addddSAndroid Build Coastguard Worker if (new_replacement.kind != ComponentStorageEntry::Kind::REPLACEMENT_LAZY_COMPONENT_WITH_ARGS ||
501*a65addddSAndroid Build Coastguard Worker !(*preexisting_replacement.lazy_component_with_args.component ==
502*a65addddSAndroid Build Coastguard Worker *new_replacement.lazy_component_with_args.component)) {
503*a65addddSAndroid Build Coastguard Worker printIncompatibleComponentReplacementsError(replaced_component_entry, new_replacement, preexisting_replacement);
504*a65addddSAndroid Build Coastguard Worker FRUIT_UNREACHABLE; // LCOV_EXCL_LINE
505*a65addddSAndroid Build Coastguard Worker }
506*a65addddSAndroid Build Coastguard Worker
507*a65addddSAndroid Build Coastguard Worker // Duplicate but consistent replacement, we'll ignore it.
508*a65addddSAndroid Build Coastguard Worker new_replacement.lazy_component_with_args.destroy();
509*a65addddSAndroid Build Coastguard Worker break;
510*a65addddSAndroid Build Coastguard Worker
511*a65addddSAndroid Build Coastguard Worker default:
512*a65addddSAndroid Build Coastguard Worker FRUIT_UNREACHABLE; // LCOV_EXCL_LINE
513*a65addddSAndroid Build Coastguard Worker }
514*a65addddSAndroid Build Coastguard Worker }
515*a65addddSAndroid Build Coastguard Worker
516*a65addddSAndroid Build Coastguard Worker } // namespace impl
517*a65addddSAndroid Build Coastguard Worker // We need a LCOV_EXCL_BR_LINE below because for some reason gcov/lcov think there's a branch there.
518*a65addddSAndroid Build Coastguard Worker } // namespace fruit LCOV_EXCL_BR_LINE
519