1*f5c631daSSadaf Ebrahimi // Copyright 2017, VIXL authors
2*f5c631daSSadaf Ebrahimi // All rights reserved.
3*f5c631daSSadaf Ebrahimi //
4*f5c631daSSadaf Ebrahimi // Redistribution and use in source and binary forms, with or without
5*f5c631daSSadaf Ebrahimi // modification, are permitted provided that the following conditions are met:
6*f5c631daSSadaf Ebrahimi //
7*f5c631daSSadaf Ebrahimi // * Redistributions of source code must retain the above copyright notice,
8*f5c631daSSadaf Ebrahimi // this list of conditions and the following disclaimer.
9*f5c631daSSadaf Ebrahimi // * Redistributions in binary form must reproduce the above copyright notice,
10*f5c631daSSadaf Ebrahimi // this list of conditions and the following disclaimer in the documentation
11*f5c631daSSadaf Ebrahimi // and/or other materials provided with the distribution.
12*f5c631daSSadaf Ebrahimi // * Neither the name of ARM Limited nor the names of its contributors may be
13*f5c631daSSadaf Ebrahimi // used to endorse or promote products derived from this software without
14*f5c631daSSadaf Ebrahimi // specific prior written permission.
15*f5c631daSSadaf Ebrahimi //
16*f5c631daSSadaf Ebrahimi // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
17*f5c631daSSadaf Ebrahimi // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18*f5c631daSSadaf Ebrahimi // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19*f5c631daSSadaf Ebrahimi // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
20*f5c631daSSadaf Ebrahimi // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21*f5c631daSSadaf Ebrahimi // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22*f5c631daSSadaf Ebrahimi // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23*f5c631daSSadaf Ebrahimi // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24*f5c631daSSadaf Ebrahimi // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25*f5c631daSSadaf Ebrahimi // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*f5c631daSSadaf Ebrahimi
27*f5c631daSSadaf Ebrahimi #include "test-pool-manager.h"
28*f5c631daSSadaf Ebrahimi
29*f5c631daSSadaf Ebrahimi #include <stdio.h>
30*f5c631daSSadaf Ebrahimi
31*f5c631daSSadaf Ebrahimi #include "pool-manager-impl.h"
32*f5c631daSSadaf Ebrahimi #include "pool-manager.h"
33*f5c631daSSadaf Ebrahimi #include "test-runner.h"
34*f5c631daSSadaf Ebrahimi
35*f5c631daSSadaf Ebrahimi #define TEST(Name) TEST_(POOL_MANAGER_##Name)
36*f5c631daSSadaf Ebrahimi
37*f5c631daSSadaf Ebrahimi #define IF_VERBOSE(exp) \
38*f5c631daSSadaf Ebrahimi if (Test::verbose()) exp
39*f5c631daSSadaf Ebrahimi
40*f5c631daSSadaf Ebrahimi #define BUFFER_ALIGNMENT 16
41*f5c631daSSadaf Ebrahimi
42*f5c631daSSadaf Ebrahimi using namespace vixl;
43*f5c631daSSadaf Ebrahimi
Random()44*f5c631daSSadaf Ebrahimi static int Random() { return static_cast<int>(std::abs(mrand48())); }
45*f5c631daSSadaf Ebrahimi
RandomObjectID(size_t num_objects)46*f5c631daSSadaf Ebrahimi static int RandomObjectID(size_t num_objects) { return Random() % num_objects; }
47*f5c631daSSadaf Ebrahimi
RandomObjectSize()48*f5c631daSSadaf Ebrahimi static int RandomObjectSize() { return 1 + Random() % 256; }
49*f5c631daSSadaf Ebrahimi
RandomObjectAlignment(int size)50*f5c631daSSadaf Ebrahimi static int RandomObjectAlignment(int size) {
51*f5c631daSSadaf Ebrahimi const int limit = static_cast<int>(floor(log2(BUFFER_ALIGNMENT)));
52*f5c631daSSadaf Ebrahimi int log2Size = static_cast<int>(floor(log2(size)));
53*f5c631daSSadaf Ebrahimi // Restrict alignment due to buffer alignment.
54*f5c631daSSadaf Ebrahimi log2Size = std::min(log2Size, limit);
55*f5c631daSSadaf Ebrahimi return (1 << (Random() % (1 + log2Size)));
56*f5c631daSSadaf Ebrahimi }
57*f5c631daSSadaf Ebrahimi
58*f5c631daSSadaf Ebrahimi // The size of the instruction.
RandomReferenceSize()59*f5c631daSSadaf Ebrahimi static int RandomReferenceSize() { return (Random() % 2) ? 2 : 4; }
60*f5c631daSSadaf Ebrahimi
61*f5c631daSSadaf Ebrahimi // The alignment of an instruction is either 2 or 4.
RandomInstructionAlignment()62*f5c631daSSadaf Ebrahimi static int RandomInstructionAlignment() { return (Random() % 2) ? 2 : 4; }
63*f5c631daSSadaf Ebrahimi
RandomMinOffset()64*f5c631daSSadaf Ebrahimi static int32_t RandomMinOffset() {
65*f5c631daSSadaf Ebrahimi const int N = 3;
66*f5c631daSSadaf Ebrahimi static const int offsets[N] = {0, 2, 4};
67*f5c631daSSadaf Ebrahimi return offsets[Random() % N];
68*f5c631daSSadaf Ebrahimi }
69*f5c631daSSadaf Ebrahimi
RandomMaxOffset()70*f5c631daSSadaf Ebrahimi static int32_t RandomMaxOffset() {
71*f5c631daSSadaf Ebrahimi const int N = 5;
72*f5c631daSSadaf Ebrahimi static const int offsets[N] = {255, 1020, 1024, 4096, 16384};
73*f5c631daSSadaf Ebrahimi return offsets[Random() % N];
74*f5c631daSSadaf Ebrahimi }
75*f5c631daSSadaf Ebrahimi
RandomBranchMaxOffset()76*f5c631daSSadaf Ebrahimi static int32_t RandomBranchMaxOffset() {
77*f5c631daSSadaf Ebrahimi const int N = 10;
78*f5c631daSSadaf Ebrahimi // The maximum offsets used for testing are taken from A32 and T32.
79*f5c631daSSadaf Ebrahimi static const int offsets[N] =
80*f5c631daSSadaf Ebrahimi {126, 254, 255, 1020, 1024, 2046, 4095, 1048574, 16777214, 33554428};
81*f5c631daSSadaf Ebrahimi return offsets[Random() % N];
82*f5c631daSSadaf Ebrahimi }
83*f5c631daSSadaf Ebrahimi
RandomPCIncrement()84*f5c631daSSadaf Ebrahimi static int RandomPCIncrement() {
85*f5c631daSSadaf Ebrahimi // A multiple of two.
86*f5c631daSSadaf Ebrahimi return 2 * (Random() % 4 + 1);
87*f5c631daSSadaf Ebrahimi }
88*f5c631daSSadaf Ebrahimi
89*f5c631daSSadaf Ebrahimi class TestObject : public LocationBase<int32_t> {
90*f5c631daSSadaf Ebrahimi public:
TestObject(int size,int alignment,int id=0)91*f5c631daSSadaf Ebrahimi TestObject(int size, int alignment, int id = 0)
92*f5c631daSSadaf Ebrahimi : LocationBase(0 /*type*/, size, alignment), id_(id) {}
93*f5c631daSSadaf Ebrahimi
EmitPoolObject(MacroAssemblerInterface * masm)94*f5c631daSSadaf Ebrahimi void EmitPoolObject(MacroAssemblerInterface *masm) VIXL_OVERRIDE {
95*f5c631daSSadaf Ebrahimi USE(masm);
96*f5c631daSSadaf Ebrahimi }
97*f5c631daSSadaf Ebrahimi
ShouldDeletePoolObjectOnPlacement() const98*f5c631daSSadaf Ebrahimi bool ShouldDeletePoolObjectOnPlacement() const VIXL_OVERRIDE { return true; }
99*f5c631daSSadaf Ebrahimi
100*f5c631daSSadaf Ebrahimi // Update the references to this object.
ResolveReferences(internal::AssemblerBase * assembler)101*f5c631daSSadaf Ebrahimi void ResolveReferences(internal::AssemblerBase *assembler) VIXL_OVERRIDE {
102*f5c631daSSadaf Ebrahimi int32_t location = GetLocation();
103*f5c631daSSadaf Ebrahimi USE(assembler);
104*f5c631daSSadaf Ebrahimi for (std::vector<ForwardReference<int32_t> *>::iterator iter =
105*f5c631daSSadaf Ebrahimi references_.begin();
106*f5c631daSSadaf Ebrahimi iter != references_.end();) {
107*f5c631daSSadaf Ebrahimi ForwardReference<int32_t> *ref = *iter;
108*f5c631daSSadaf Ebrahimi VIXL_ASSERT(ref->LocationIsEncodable(location));
109*f5c631daSSadaf Ebrahimi delete ref;
110*f5c631daSSadaf Ebrahimi iter = references_.erase(iter);
111*f5c631daSSadaf Ebrahimi }
112*f5c631daSSadaf Ebrahimi IF_VERBOSE(printf("Placed object %d at location: 0x%x (%u)\n",
113*f5c631daSSadaf Ebrahimi id_,
114*f5c631daSSadaf Ebrahimi location,
115*f5c631daSSadaf Ebrahimi location));
116*f5c631daSSadaf Ebrahimi }
117*f5c631daSSadaf Ebrahimi
AddReference(ForwardReference<int32_t> * ref)118*f5c631daSSadaf Ebrahimi void AddReference(ForwardReference<int32_t> *ref) {
119*f5c631daSSadaf Ebrahimi references_.push_back(ref);
120*f5c631daSSadaf Ebrahimi }
121*f5c631daSSadaf Ebrahimi
GetID()122*f5c631daSSadaf Ebrahimi int GetID() { return id_; }
123*f5c631daSSadaf Ebrahimi
CreateRandom(int id)124*f5c631daSSadaf Ebrahimi static TestObject *CreateRandom(int id) {
125*f5c631daSSadaf Ebrahimi int size = RandomObjectSize();
126*f5c631daSSadaf Ebrahimi int alignment = RandomObjectAlignment(size);
127*f5c631daSSadaf Ebrahimi IF_VERBOSE(printf("Object %d -> size = %d, alignment = %d\n",
128*f5c631daSSadaf Ebrahimi id,
129*f5c631daSSadaf Ebrahimi size,
130*f5c631daSSadaf Ebrahimi alignment));
131*f5c631daSSadaf Ebrahimi return new TestObject(size, alignment, id);
132*f5c631daSSadaf Ebrahimi }
133*f5c631daSSadaf Ebrahimi
134*f5c631daSSadaf Ebrahimi private:
135*f5c631daSSadaf Ebrahimi // Store pointers to ForwardReference objects - TestObject is responsible
136*f5c631daSSadaf Ebrahimi // for deleting them.
137*f5c631daSSadaf Ebrahimi std::vector<ForwardReference<int32_t> *> references_;
138*f5c631daSSadaf Ebrahimi // Object id used for debugging.
139*f5c631daSSadaf Ebrahimi int id_;
140*f5c631daSSadaf Ebrahimi };
141*f5c631daSSadaf Ebrahimi
142*f5c631daSSadaf Ebrahimi class TestBranchObject : public LocationBase<int32_t> {
143*f5c631daSSadaf Ebrahimi public:
TestBranchObject(int size,int alignment,int id=0)144*f5c631daSSadaf Ebrahimi TestBranchObject(int size, int alignment, int id = 0)
145*f5c631daSSadaf Ebrahimi : LocationBase(1 /* type */, size, alignment), id_(id) {}
146*f5c631daSSadaf Ebrahimi
UsePoolObjectEmissionMargin() const147*f5c631daSSadaf Ebrahimi bool UsePoolObjectEmissionMargin() const VIXL_OVERRIDE { return true; }
GetPoolObjectEmissionMargin() const148*f5c631daSSadaf Ebrahimi int32_t GetPoolObjectEmissionMargin() const VIXL_OVERRIDE {
149*f5c631daSSadaf Ebrahimi return 1 * KBytes;
150*f5c631daSSadaf Ebrahimi }
151*f5c631daSSadaf Ebrahimi
152*f5c631daSSadaf Ebrahimi // Do nothing for now.
EmitPoolObject(MacroAssemblerInterface * masm)153*f5c631daSSadaf Ebrahimi void EmitPoolObject(MacroAssemblerInterface *masm) VIXL_OVERRIDE {
154*f5c631daSSadaf Ebrahimi USE(masm);
155*f5c631daSSadaf Ebrahimi }
156*f5c631daSSadaf Ebrahimi
ShouldDeletePoolObjectOnPlacement() const157*f5c631daSSadaf Ebrahimi bool ShouldDeletePoolObjectOnPlacement() const VIXL_OVERRIDE { return false; }
158*f5c631daSSadaf Ebrahimi
UpdatePoolObject(PoolObject<int32_t> * object)159*f5c631daSSadaf Ebrahimi virtual void UpdatePoolObject(PoolObject<int32_t> *object) VIXL_OVERRIDE {
160*f5c631daSSadaf Ebrahimi // Reference from the last emitted veneer:
161*f5c631daSSadaf Ebrahimi int32_t min = location_ + min_offset_;
162*f5c631daSSadaf Ebrahimi int32_t max = location_ + max_offset_;
163*f5c631daSSadaf Ebrahimi // The alignment that the new "veneer" requires of the label.
164*f5c631daSSadaf Ebrahimi int reference_alignment = RandomInstructionAlignment();
165*f5c631daSSadaf Ebrahimi reference_alignment =
166*f5c631daSSadaf Ebrahimi std::max(reference_alignment, GetPoolObjectAlignment());
167*f5c631daSSadaf Ebrahimi ForwardReference<int32_t> *ref =
168*f5c631daSSadaf Ebrahimi new ForwardReference<int32_t>(location_,
169*f5c631daSSadaf Ebrahimi 4 /*size*/,
170*f5c631daSSadaf Ebrahimi min,
171*f5c631daSSadaf Ebrahimi max,
172*f5c631daSSadaf Ebrahimi reference_alignment);
173*f5c631daSSadaf Ebrahimi AddReference(ref);
174*f5c631daSSadaf Ebrahimi object->Update(min, max, reference_alignment);
175*f5c631daSSadaf Ebrahimi }
176*f5c631daSSadaf Ebrahimi
177*f5c631daSSadaf Ebrahimi // Update the references to this object.
ResolveReferences(internal::AssemblerBase * assembler)178*f5c631daSSadaf Ebrahimi void ResolveReferences(internal::AssemblerBase *assembler) VIXL_OVERRIDE {
179*f5c631daSSadaf Ebrahimi int32_t location = GetLocation();
180*f5c631daSSadaf Ebrahimi USE(assembler);
181*f5c631daSSadaf Ebrahimi for (std::vector<ForwardReference<int32_t> *>::iterator iter =
182*f5c631daSSadaf Ebrahimi references_.begin();
183*f5c631daSSadaf Ebrahimi iter != references_.end();) {
184*f5c631daSSadaf Ebrahimi ForwardReference<int32_t> *ref = *iter;
185*f5c631daSSadaf Ebrahimi VIXL_ASSERT(ref->LocationIsEncodable(location));
186*f5c631daSSadaf Ebrahimi delete ref;
187*f5c631daSSadaf Ebrahimi iter = references_.erase(iter);
188*f5c631daSSadaf Ebrahimi }
189*f5c631daSSadaf Ebrahimi IF_VERBOSE(printf("Veneer %d placed at location: 0x%x (%u)\n",
190*f5c631daSSadaf Ebrahimi id_,
191*f5c631daSSadaf Ebrahimi location,
192*f5c631daSSadaf Ebrahimi location));
193*f5c631daSSadaf Ebrahimi }
194*f5c631daSSadaf Ebrahimi
AddReference(ForwardReference<int32_t> * ref)195*f5c631daSSadaf Ebrahimi void AddReference(ForwardReference<int32_t> *ref) {
196*f5c631daSSadaf Ebrahimi references_.push_back(ref);
197*f5c631daSSadaf Ebrahimi }
198*f5c631daSSadaf Ebrahimi
GetMaxAlignment() const199*f5c631daSSadaf Ebrahimi virtual int GetMaxAlignment() const VIXL_OVERRIDE {
200*f5c631daSSadaf Ebrahimi int max_alignment = GetPoolObjectAlignment();
201*f5c631daSSadaf Ebrahimi for (std::vector<ForwardReference<int32_t> *>::const_iterator iter =
202*f5c631daSSadaf Ebrahimi references_.begin();
203*f5c631daSSadaf Ebrahimi iter != references_.end();
204*f5c631daSSadaf Ebrahimi ++iter) {
205*f5c631daSSadaf Ebrahimi const ForwardReference<int32_t> *ref = *iter;
206*f5c631daSSadaf Ebrahimi if (ref->GetAlignment() > max_alignment)
207*f5c631daSSadaf Ebrahimi max_alignment = ref->GetAlignment();
208*f5c631daSSadaf Ebrahimi }
209*f5c631daSSadaf Ebrahimi return max_alignment;
210*f5c631daSSadaf Ebrahimi }
GetMinLocation() const211*f5c631daSSadaf Ebrahimi virtual int32_t GetMinLocation() const VIXL_OVERRIDE {
212*f5c631daSSadaf Ebrahimi int32_t min_location = 0;
213*f5c631daSSadaf Ebrahimi for (std::vector<ForwardReference<int32_t> *>::const_iterator iter =
214*f5c631daSSadaf Ebrahimi references_.begin();
215*f5c631daSSadaf Ebrahimi iter != references_.end();
216*f5c631daSSadaf Ebrahimi ++iter) {
217*f5c631daSSadaf Ebrahimi const ForwardReference<int32_t> *ref = *iter;
218*f5c631daSSadaf Ebrahimi if (ref->GetMinLocation() > min_location)
219*f5c631daSSadaf Ebrahimi min_location = ref->GetMinLocation();
220*f5c631daSSadaf Ebrahimi }
221*f5c631daSSadaf Ebrahimi return min_location;
222*f5c631daSSadaf Ebrahimi }
223*f5c631daSSadaf Ebrahimi
GetID()224*f5c631daSSadaf Ebrahimi int GetID() { return id_; }
225*f5c631daSSadaf Ebrahimi
CreateRandom(int id)226*f5c631daSSadaf Ebrahimi static TestBranchObject *CreateRandom(int id) {
227*f5c631daSSadaf Ebrahimi int size = RandomReferenceSize();
228*f5c631daSSadaf Ebrahimi int alignment = size;
229*f5c631daSSadaf Ebrahimi IF_VERBOSE(printf("Object %d -> size = %d, alignment = %d\n",
230*f5c631daSSadaf Ebrahimi id,
231*f5c631daSSadaf Ebrahimi size,
232*f5c631daSSadaf Ebrahimi alignment));
233*f5c631daSSadaf Ebrahimi return new TestBranchObject(size, alignment, id);
234*f5c631daSSadaf Ebrahimi }
235*f5c631daSSadaf Ebrahimi
236*f5c631daSSadaf Ebrahimi private:
237*f5c631daSSadaf Ebrahimi // Store pointers to ForwardReference objects - TestBranchObject is
238*f5c631daSSadaf Ebrahimi // responsible for deleting them.
239*f5c631daSSadaf Ebrahimi std::vector<ForwardReference<int32_t> *> references_;
240*f5c631daSSadaf Ebrahimi // Object id used for debugging.
241*f5c631daSSadaf Ebrahimi int id_;
242*f5c631daSSadaf Ebrahimi
243*f5c631daSSadaf Ebrahimi // These are the min and max offsets of the type of branch used for the
244*f5c631daSSadaf Ebrahimi // veneer.
245*f5c631daSSadaf Ebrahimi static const int32_t min_offset_ = 0;
246*f5c631daSSadaf Ebrahimi static const int32_t max_offset_ = 16 * 1024 * 1024;
247*f5c631daSSadaf Ebrahimi };
248*f5c631daSSadaf Ebrahimi
249*f5c631daSSadaf Ebrahimi // MacroAssembler implementation that does nothing but print in verbose mode.
250*f5c631daSSadaf Ebrahimi class TestMacroAssembler : public MacroAssemblerInterface {
251*f5c631daSSadaf Ebrahimi public:
TestMacroAssembler()252*f5c631daSSadaf Ebrahimi TestMacroAssembler() : assembler_(128) {}
253*f5c631daSSadaf Ebrahimi
EmitPoolHeader()254*f5c631daSSadaf Ebrahimi void EmitPoolHeader() VIXL_OVERRIDE {
255*f5c631daSSadaf Ebrahimi IF_VERBOSE(printf("[MASM] Emitting pool header.\n"));
256*f5c631daSSadaf Ebrahimi }
EmitPoolFooter()257*f5c631daSSadaf Ebrahimi void EmitPoolFooter() VIXL_OVERRIDE {
258*f5c631daSSadaf Ebrahimi IF_VERBOSE(printf("[MASM] Emitting pool footer.\n"));
259*f5c631daSSadaf Ebrahimi }
EmitPaddingBytes(int n)260*f5c631daSSadaf Ebrahimi void EmitPaddingBytes(int n) VIXL_OVERRIDE {
261*f5c631daSSadaf Ebrahimi IF_VERBOSE(printf("[MASM] Added %d bytes of padding.\n", n));
262*f5c631daSSadaf Ebrahimi }
EmitNopBytes(int n)263*f5c631daSSadaf Ebrahimi void EmitNopBytes(int n) VIXL_OVERRIDE {
264*f5c631daSSadaf Ebrahimi IF_VERBOSE(printf("[MASM] Added %d bytes of NOPs.\n", n));
265*f5c631daSSadaf Ebrahimi }
ArePoolsBlocked() const266*f5c631daSSadaf Ebrahimi bool ArePoolsBlocked() const VIXL_OVERRIDE { return false; }
AllowMacroInstructions() const267*f5c631daSSadaf Ebrahimi bool AllowMacroInstructions() const VIXL_OVERRIDE { return false; }
SetAllowMacroInstructions(bool allow)268*f5c631daSSadaf Ebrahimi void SetAllowMacroInstructions(bool allow) VIXL_OVERRIDE { USE(allow); }
269*f5c631daSSadaf Ebrahimi
BlockPools()270*f5c631daSSadaf Ebrahimi void BlockPools() VIXL_OVERRIDE {}
ReleasePools()271*f5c631daSSadaf Ebrahimi void ReleasePools() VIXL_OVERRIDE {}
EnsureEmitPoolsFor(size_t)272*f5c631daSSadaf Ebrahimi void EnsureEmitPoolsFor(size_t) VIXL_OVERRIDE {}
AsAssemblerBase()273*f5c631daSSadaf Ebrahimi internal::AssemblerBase *AsAssemblerBase() VIXL_OVERRIDE {
274*f5c631daSSadaf Ebrahimi return &assembler_;
275*f5c631daSSadaf Ebrahimi }
276*f5c631daSSadaf Ebrahimi
277*f5c631daSSadaf Ebrahimi private:
278*f5c631daSSadaf Ebrahimi internal::AssemblerBase assembler_;
279*f5c631daSSadaf Ebrahimi };
280*f5c631daSSadaf Ebrahimi
281*f5c631daSSadaf Ebrahimi // Used for debugging.
282*f5c631daSSadaf Ebrahimi namespace vixl {
283*f5c631daSSadaf Ebrahimi template <>
DumpCurrentState(int32_t pc) const284*f5c631daSSadaf Ebrahimi void PoolManager<int32_t>::DumpCurrentState(int32_t pc) const {
285*f5c631daSSadaf Ebrahimi IF_VERBOSE(
286*f5c631daSSadaf Ebrahimi printf("Number of objects: %d\n", static_cast<int>(objects_.size())));
287*f5c631daSSadaf Ebrahimi IF_VERBOSE(printf("Current pc = 0x%x (%d)\n", pc, pc));
288*f5c631daSSadaf Ebrahimi
289*f5c631daSSadaf Ebrahimi for (int i = 0; i < static_cast<int>(objects_.size()); ++i) {
290*f5c631daSSadaf Ebrahimi const PoolObject<int32_t> &object = objects_[i];
291*f5c631daSSadaf Ebrahimi IF_VERBOSE(
292*f5c631daSSadaf Ebrahimi printf("Object %d -> size = %d, alignment = %d, range = (%d,%d)\n",
293*f5c631daSSadaf Ebrahimi i,
294*f5c631daSSadaf Ebrahimi object.label_base_->GetPoolObjectSizeInBytes(),
295*f5c631daSSadaf Ebrahimi object.alignment_,
296*f5c631daSSadaf Ebrahimi object.min_location_,
297*f5c631daSSadaf Ebrahimi object.max_location_));
298*f5c631daSSadaf Ebrahimi }
299*f5c631daSSadaf Ebrahimi }
300*f5c631daSSadaf Ebrahimi }
301*f5c631daSSadaf Ebrahimi
302*f5c631daSSadaf Ebrahimi // Basic test - checks that emitting a very simple pool works.
TEST(Basic)303*f5c631daSSadaf Ebrahimi TEST(Basic) {
304*f5c631daSSadaf Ebrahimi TestMacroAssembler masm;
305*f5c631daSSadaf Ebrahimi
306*f5c631daSSadaf Ebrahimi PoolManager<int32_t> pool_manager(4 /*header_size*/,
307*f5c631daSSadaf Ebrahimi 2 /*header_alignment*/,
308*f5c631daSSadaf Ebrahimi BUFFER_ALIGNMENT);
309*f5c631daSSadaf Ebrahimi TestObject object1(4 /*size*/, 4 /*alignment*/);
310*f5c631daSSadaf Ebrahimi TestObject object2(128 /*size*/, 4 /*alignment*/);
311*f5c631daSSadaf Ebrahimi ForwardReference<int32_t> *ref1_obj1 =
312*f5c631daSSadaf Ebrahimi new ForwardReference<int32_t>(0 /*location*/, 2 /*size*/, 0, 200);
313*f5c631daSSadaf Ebrahimi ForwardReference<int32_t> *ref2_obj1 =
314*f5c631daSSadaf Ebrahimi new ForwardReference<int32_t>(2 /*location*/, 2 /*size*/, 2, 202);
315*f5c631daSSadaf Ebrahimi ForwardReference<int32_t> *ref3_obj1 =
316*f5c631daSSadaf Ebrahimi new ForwardReference<int32_t>(4 /*location*/, 2 /*size*/, 4, 204);
317*f5c631daSSadaf Ebrahimi object1.AddReference(ref1_obj1);
318*f5c631daSSadaf Ebrahimi object1.AddReference(ref2_obj1);
319*f5c631daSSadaf Ebrahimi object1.AddReference(ref3_obj1);
320*f5c631daSSadaf Ebrahimi ForwardReference<int32_t> *ref1_obj2 =
321*f5c631daSSadaf Ebrahimi new ForwardReference<int32_t>(8 /*location*/, 2 /*size*/, 8, 500);
322*f5c631daSSadaf Ebrahimi ForwardReference<int32_t> *ref2_obj2 =
323*f5c631daSSadaf Ebrahimi new ForwardReference<int32_t>(12 /*location*/, 4 /*size*/, 12, 300);
324*f5c631daSSadaf Ebrahimi ForwardReference<int32_t> *ref3_obj2 =
325*f5c631daSSadaf Ebrahimi new ForwardReference<int32_t>(16 /*location*/, 4 /*size*/, 16, 400);
326*f5c631daSSadaf Ebrahimi object2.AddReference(ref1_obj2);
327*f5c631daSSadaf Ebrahimi object2.AddReference(ref2_obj2);
328*f5c631daSSadaf Ebrahimi object2.AddReference(ref3_obj2);
329*f5c631daSSadaf Ebrahimi
330*f5c631daSSadaf Ebrahimi pool_manager.AddObjectReference(ref1_obj1, &object1);
331*f5c631daSSadaf Ebrahimi pool_manager.AddObjectReference(ref2_obj1, &object1);
332*f5c631daSSadaf Ebrahimi pool_manager.AddObjectReference(ref3_obj1, &object1);
333*f5c631daSSadaf Ebrahimi pool_manager.AddObjectReference(ref1_obj2, &object2);
334*f5c631daSSadaf Ebrahimi pool_manager.AddObjectReference(ref2_obj2, &object2);
335*f5c631daSSadaf Ebrahimi pool_manager.AddObjectReference(ref3_obj2, &object2);
336*f5c631daSSadaf Ebrahimi
337*f5c631daSSadaf Ebrahimi pool_manager.Emit(&masm, 20);
338*f5c631daSSadaf Ebrahimi }
339*f5c631daSSadaf Ebrahimi
CreateReference(int id,int32_t pc,int size,int32_t min_offset,int32_t max_offset,int alignment)340*f5c631daSSadaf Ebrahimi static ForwardReference<int32_t> *CreateReference(int id,
341*f5c631daSSadaf Ebrahimi int32_t pc,
342*f5c631daSSadaf Ebrahimi int size,
343*f5c631daSSadaf Ebrahimi int32_t min_offset,
344*f5c631daSSadaf Ebrahimi int32_t max_offset,
345*f5c631daSSadaf Ebrahimi int alignment) {
346*f5c631daSSadaf Ebrahimi IF_VERBOSE(printf(
347*f5c631daSSadaf Ebrahimi "About to add a new reference to object %d with min location = %d, max "
348*f5c631daSSadaf Ebrahimi "location = %d, alignment = %d, size = %d\n",
349*f5c631daSSadaf Ebrahimi id,
350*f5c631daSSadaf Ebrahimi min_offset + pc,
351*f5c631daSSadaf Ebrahimi max_offset + pc,
352*f5c631daSSadaf Ebrahimi alignment,
353*f5c631daSSadaf Ebrahimi size));
354*f5c631daSSadaf Ebrahimi return new ForwardReference<int32_t>(pc,
355*f5c631daSSadaf Ebrahimi size,
356*f5c631daSSadaf Ebrahimi min_offset + pc,
357*f5c631daSSadaf Ebrahimi max_offset + pc,
358*f5c631daSSadaf Ebrahimi alignment);
359*f5c631daSSadaf Ebrahimi }
360*f5c631daSSadaf Ebrahimi
361*f5c631daSSadaf Ebrahimi // Fuzz test that uses literal-like objects, that get deleted when they are
362*f5c631daSSadaf Ebrahimi // placed.
TEST(FuzzObjectDeletedWhenPlaced)363*f5c631daSSadaf Ebrahimi TEST(FuzzObjectDeletedWhenPlaced) {
364*f5c631daSSadaf Ebrahimi TestMacroAssembler masm;
365*f5c631daSSadaf Ebrahimi PoolManager<int32_t> pool_manager(4 /*header_size*/,
366*f5c631daSSadaf Ebrahimi 2 /*header_alignment*/,
367*f5c631daSSadaf Ebrahimi BUFFER_ALIGNMENT);
368*f5c631daSSadaf Ebrahimi
369*f5c631daSSadaf Ebrahimi const int kObjectNum = 100;
370*f5c631daSSadaf Ebrahimi std::vector<TestObject *> objects;
371*f5c631daSSadaf Ebrahimi
372*f5c631daSSadaf Ebrahimi // Create objects.
373*f5c631daSSadaf Ebrahimi for (int i = 0; i < kObjectNum; ++i) {
374*f5c631daSSadaf Ebrahimi objects.push_back(TestObject::CreateRandom(i));
375*f5c631daSSadaf Ebrahimi }
376*f5c631daSSadaf Ebrahimi
377*f5c631daSSadaf Ebrahimi int32_t pc = 0;
378*f5c631daSSadaf Ebrahimi for (int i = 0; !objects.empty(); ++i) {
379*f5c631daSSadaf Ebrahimi IF_VERBOSE(printf("PC = 0x%x (%d)\n", pc, pc));
380*f5c631daSSadaf Ebrahimi int32_t pc_increment = RandomPCIncrement();
381*f5c631daSSadaf Ebrahimi IF_VERBOSE(printf("Attempting to increment PC by %d\n", pc_increment));
382*f5c631daSSadaf Ebrahimi if (pool_manager.MustEmit(pc, pc_increment)) {
383*f5c631daSSadaf Ebrahimi pc = pool_manager.Emit(&masm, pc, pc_increment);
384*f5c631daSSadaf Ebrahimi }
385*f5c631daSSadaf Ebrahimi pc += pc_increment;
386*f5c631daSSadaf Ebrahimi // Pick an object, randomly.
387*f5c631daSSadaf Ebrahimi TestObject *object = objects[RandomObjectID(objects.size())];
388*f5c631daSSadaf Ebrahimi int32_t min_offset = RandomMinOffset();
389*f5c631daSSadaf Ebrahimi int32_t max_offset = RandomMaxOffset();
390*f5c631daSSadaf Ebrahimi int32_t size = RandomReferenceSize();
391*f5c631daSSadaf Ebrahimi int32_t alignment =
392*f5c631daSSadaf Ebrahimi RandomObjectAlignment(object->GetPoolObjectSizeInBytes());
393*f5c631daSSadaf Ebrahimi ForwardReference<int32_t> *ref = CreateReference(object->GetID(),
394*f5c631daSSadaf Ebrahimi pc,
395*f5c631daSSadaf Ebrahimi size,
396*f5c631daSSadaf Ebrahimi min_offset,
397*f5c631daSSadaf Ebrahimi max_offset,
398*f5c631daSSadaf Ebrahimi alignment);
399*f5c631daSSadaf Ebrahimi if (pool_manager.MustEmit(pc, size, ref, object)) {
400*f5c631daSSadaf Ebrahimi pc = pool_manager.Emit(&masm, pc, size, ref, object);
401*f5c631daSSadaf Ebrahimi delete ref;
402*f5c631daSSadaf Ebrahimi // We must recreate the reference, the PC has changed, but only if
403*f5c631daSSadaf Ebrahimi // it still is a forward reference.
404*f5c631daSSadaf Ebrahimi if (!object->IsBound()) {
405*f5c631daSSadaf Ebrahimi ref = CreateReference(object->GetID(),
406*f5c631daSSadaf Ebrahimi pc,
407*f5c631daSSadaf Ebrahimi size,
408*f5c631daSSadaf Ebrahimi min_offset,
409*f5c631daSSadaf Ebrahimi max_offset,
410*f5c631daSSadaf Ebrahimi alignment);
411*f5c631daSSadaf Ebrahimi }
412*f5c631daSSadaf Ebrahimi }
413*f5c631daSSadaf Ebrahimi IF_VERBOSE(printf("Incrementing PC by size of reference (%d).\n", size));
414*f5c631daSSadaf Ebrahimi pc += size;
415*f5c631daSSadaf Ebrahimi // We only need to track the reference if it's a forward reference.
416*f5c631daSSadaf Ebrahimi if (!object->IsBound()) {
417*f5c631daSSadaf Ebrahimi object->AddReference(ref);
418*f5c631daSSadaf Ebrahimi pool_manager.AddObjectReference(ref, object);
419*f5c631daSSadaf Ebrahimi }
420*f5c631daSSadaf Ebrahimi VIXL_ASSERT(!pool_manager.MustEmit(pc - 1));
421*f5c631daSSadaf Ebrahimi // Remove bound objects.
422*f5c631daSSadaf Ebrahimi for (std::vector<TestObject *>::iterator iter = objects.begin();
423*f5c631daSSadaf Ebrahimi iter != objects.end();) {
424*f5c631daSSadaf Ebrahimi TestObject *obj = *iter;
425*f5c631daSSadaf Ebrahimi if (obj->IsBound()) {
426*f5c631daSSadaf Ebrahimi delete obj;
427*f5c631daSSadaf Ebrahimi iter = objects.erase(iter);
428*f5c631daSSadaf Ebrahimi } else {
429*f5c631daSSadaf Ebrahimi ++iter;
430*f5c631daSSadaf Ebrahimi }
431*f5c631daSSadaf Ebrahimi }
432*f5c631daSSadaf Ebrahimi }
433*f5c631daSSadaf Ebrahimi
434*f5c631daSSadaf Ebrahimi pool_manager.Emit(&masm, pc);
435*f5c631daSSadaf Ebrahimi }
436*f5c631daSSadaf Ebrahimi
437*f5c631daSSadaf Ebrahimi // Fuzz test that uses veneer-like objects, that get updated when they are
438*f5c631daSSadaf Ebrahimi // placed and get deleted when they are bound by the user.
TEST(FuzzObjectUpdatedWhenPlaced)439*f5c631daSSadaf Ebrahimi TEST(FuzzObjectUpdatedWhenPlaced) {
440*f5c631daSSadaf Ebrahimi TestMacroAssembler masm;
441*f5c631daSSadaf Ebrahimi PoolManager<int32_t> pool_manager(4 /*header_size*/,
442*f5c631daSSadaf Ebrahimi 2 /*header_alignment*/,
443*f5c631daSSadaf Ebrahimi BUFFER_ALIGNMENT);
444*f5c631daSSadaf Ebrahimi const int kObjectNum = 1000;
445*f5c631daSSadaf Ebrahimi std::vector<TestBranchObject *> objects;
446*f5c631daSSadaf Ebrahimi
447*f5c631daSSadaf Ebrahimi // Create objects.
448*f5c631daSSadaf Ebrahimi for (int i = 0; i < kObjectNum; ++i) {
449*f5c631daSSadaf Ebrahimi objects.push_back(TestBranchObject::CreateRandom(i));
450*f5c631daSSadaf Ebrahimi }
451*f5c631daSSadaf Ebrahimi
452*f5c631daSSadaf Ebrahimi int32_t pc = 0;
453*f5c631daSSadaf Ebrahimi for (int i = 0; !objects.empty(); ++i) {
454*f5c631daSSadaf Ebrahimi IF_VERBOSE(printf("PC = 0x%x (%d)\n", pc, pc));
455*f5c631daSSadaf Ebrahimi
456*f5c631daSSadaf Ebrahimi int32_t pc_increment = RandomPCIncrement();
457*f5c631daSSadaf Ebrahimi IF_VERBOSE(printf("Attempting to increment PC by %d\n", pc_increment));
458*f5c631daSSadaf Ebrahimi
459*f5c631daSSadaf Ebrahimi if (pool_manager.MustEmit(pc, pc_increment)) {
460*f5c631daSSadaf Ebrahimi pc = pool_manager.Emit(&masm, pc, pc_increment);
461*f5c631daSSadaf Ebrahimi }
462*f5c631daSSadaf Ebrahimi pc += pc_increment;
463*f5c631daSSadaf Ebrahimi
464*f5c631daSSadaf Ebrahimi // Pick a random object.
465*f5c631daSSadaf Ebrahimi TestBranchObject *object = objects[RandomObjectID(objects.size())];
466*f5c631daSSadaf Ebrahimi int32_t min_offset = RandomMinOffset();
467*f5c631daSSadaf Ebrahimi int32_t max_offset = RandomBranchMaxOffset();
468*f5c631daSSadaf Ebrahimi int32_t size = RandomReferenceSize();
469*f5c631daSSadaf Ebrahimi int32_t alignment =
470*f5c631daSSadaf Ebrahimi RandomObjectAlignment(object->GetPoolObjectSizeInBytes());
471*f5c631daSSadaf Ebrahimi ForwardReference<int32_t> *ref = CreateReference(object->GetID(),
472*f5c631daSSadaf Ebrahimi pc,
473*f5c631daSSadaf Ebrahimi size,
474*f5c631daSSadaf Ebrahimi min_offset,
475*f5c631daSSadaf Ebrahimi max_offset,
476*f5c631daSSadaf Ebrahimi alignment);
477*f5c631daSSadaf Ebrahimi if (pool_manager.MustEmit(pc, size, ref, object)) {
478*f5c631daSSadaf Ebrahimi pc = pool_manager.Emit(&masm, pc, size);
479*f5c631daSSadaf Ebrahimi delete ref;
480*f5c631daSSadaf Ebrahimi // We must recreate the reference, the PC has changed.
481*f5c631daSSadaf Ebrahimi ref = CreateReference(object->GetID(),
482*f5c631daSSadaf Ebrahimi pc,
483*f5c631daSSadaf Ebrahimi size,
484*f5c631daSSadaf Ebrahimi min_offset,
485*f5c631daSSadaf Ebrahimi max_offset,
486*f5c631daSSadaf Ebrahimi alignment);
487*f5c631daSSadaf Ebrahimi }
488*f5c631daSSadaf Ebrahimi IF_VERBOSE(printf("Incrementing PC by size of reference (%d).\n", size));
489*f5c631daSSadaf Ebrahimi pc += size;
490*f5c631daSSadaf Ebrahimi object->AddReference(ref);
491*f5c631daSSadaf Ebrahimi pool_manager.AddObjectReference(ref, object);
492*f5c631daSSadaf Ebrahimi VIXL_ASSERT(!pool_manager.MustEmit(pc - 1));
493*f5c631daSSadaf Ebrahimi
494*f5c631daSSadaf Ebrahimi // Pick another random label to bind.
495*f5c631daSSadaf Ebrahimi const int kProbabilityToBind = 20;
496*f5c631daSSadaf Ebrahimi if ((Random() % 100) < kProbabilityToBind) {
497*f5c631daSSadaf Ebrahimi TestBranchObject *object2 = objects[RandomObjectID(objects.size())];
498*f5c631daSSadaf Ebrahimi // Binding can cause the pool emission, so check if we need to emit
499*f5c631daSSadaf Ebrahimi // the pools. The actual backends will know the max alignment we
500*f5c631daSSadaf Ebrahimi // might need here, so can simplify the check (won't need to check
501*f5c631daSSadaf Ebrahimi // the object references).
502*f5c631daSSadaf Ebrahimi int max_padding = object->GetMaxAlignment() - 1;
503*f5c631daSSadaf Ebrahimi if (pool_manager.MustEmit(pc, max_padding)) {
504*f5c631daSSadaf Ebrahimi pc = pool_manager.Emit(&masm, pc, max_padding);
505*f5c631daSSadaf Ebrahimi }
506*f5c631daSSadaf Ebrahimi pc = pool_manager.Bind(&masm, object2, pc);
507*f5c631daSSadaf Ebrahimi }
508*f5c631daSSadaf Ebrahimi
509*f5c631daSSadaf Ebrahimi // Remove bound objects.
510*f5c631daSSadaf Ebrahimi for (std::vector<TestBranchObject *>::iterator iter = objects.begin();
511*f5c631daSSadaf Ebrahimi iter != objects.end();) {
512*f5c631daSSadaf Ebrahimi TestBranchObject *obj = *iter;
513*f5c631daSSadaf Ebrahimi if (obj->IsBound()) {
514*f5c631daSSadaf Ebrahimi delete obj;
515*f5c631daSSadaf Ebrahimi iter = objects.erase(iter);
516*f5c631daSSadaf Ebrahimi } else {
517*f5c631daSSadaf Ebrahimi ++iter;
518*f5c631daSSadaf Ebrahimi }
519*f5c631daSSadaf Ebrahimi }
520*f5c631daSSadaf Ebrahimi }
521*f5c631daSSadaf Ebrahimi
522*f5c631daSSadaf Ebrahimi pool_manager.Emit(&masm, pc);
523*f5c631daSSadaf Ebrahimi }
524*f5c631daSSadaf Ebrahimi
525*f5c631daSSadaf Ebrahimi // Test that binding an unused label works.
TEST(BindUnusedLabel)526*f5c631daSSadaf Ebrahimi TEST(BindUnusedLabel) {
527*f5c631daSSadaf Ebrahimi TestMacroAssembler masm;
528*f5c631daSSadaf Ebrahimi
529*f5c631daSSadaf Ebrahimi PoolManager<int32_t> pool_manager(4 /*header_size*/,
530*f5c631daSSadaf Ebrahimi 2 /*header_alignment*/,
531*f5c631daSSadaf Ebrahimi BUFFER_ALIGNMENT);
532*f5c631daSSadaf Ebrahimi TestBranchObject *object = new TestBranchObject(4 /*size*/, 4 /*alignment*/);
533*f5c631daSSadaf Ebrahimi int32_t pc = 0;
534*f5c631daSSadaf Ebrahimi pool_manager.Bind(&masm, object, pc);
535*f5c631daSSadaf Ebrahimi delete object;
536*f5c631daSSadaf Ebrahimi }
537*f5c631daSSadaf Ebrahimi
538*f5c631daSSadaf Ebrahimi // Test that binding a label adds necessary padding.
TEST(BindLabelNeedsPadding)539*f5c631daSSadaf Ebrahimi TEST(BindLabelNeedsPadding) {
540*f5c631daSSadaf Ebrahimi TestMacroAssembler masm;
541*f5c631daSSadaf Ebrahimi
542*f5c631daSSadaf Ebrahimi PoolManager<int32_t> pool_manager(4 /*header_size*/,
543*f5c631daSSadaf Ebrahimi 2 /*header_alignment*/,
544*f5c631daSSadaf Ebrahimi BUFFER_ALIGNMENT);
545*f5c631daSSadaf Ebrahimi
546*f5c631daSSadaf Ebrahimi // Label that needs padding because of the minimum location of the reference.
547*f5c631daSSadaf Ebrahimi TestBranchObject *object = new TestBranchObject(4 /*size*/, 2 /*alignment*/);
548*f5c631daSSadaf Ebrahimi ForwardReference<int32_t> *ref =
549*f5c631daSSadaf Ebrahimi new ForwardReference<int32_t>(0 /*location*/,
550*f5c631daSSadaf Ebrahimi 2 /*size*/,
551*f5c631daSSadaf Ebrahimi 4 /*min_location*/,
552*f5c631daSSadaf Ebrahimi 500 /*max_location*/);
553*f5c631daSSadaf Ebrahimi object->AddReference(ref);
554*f5c631daSSadaf Ebrahimi pool_manager.AddObjectReference(ref, object);
555*f5c631daSSadaf Ebrahimi int32_t pc = 2;
556*f5c631daSSadaf Ebrahimi pc = pool_manager.Bind(&masm, object, pc);
557*f5c631daSSadaf Ebrahimi VIXL_ASSERT(pc == 4);
558*f5c631daSSadaf Ebrahimi delete object;
559*f5c631daSSadaf Ebrahimi
560*f5c631daSSadaf Ebrahimi // Label that needs padding because of the alignment of the object.
561*f5c631daSSadaf Ebrahimi object = new TestBranchObject(4 /*size*/, 4 /*alignment*/);
562*f5c631daSSadaf Ebrahimi ref = new ForwardReference<int32_t>(0 /*location*/,
563*f5c631daSSadaf Ebrahimi 2 /*size*/,
564*f5c631daSSadaf Ebrahimi 0 /*min_location*/,
565*f5c631daSSadaf Ebrahimi 500 /*max_location*/);
566*f5c631daSSadaf Ebrahimi object->AddReference(ref);
567*f5c631daSSadaf Ebrahimi pool_manager.AddObjectReference(ref, object);
568*f5c631daSSadaf Ebrahimi
569*f5c631daSSadaf Ebrahimi pc = 2;
570*f5c631daSSadaf Ebrahimi pc = pool_manager.Bind(&masm, object, pc);
571*f5c631daSSadaf Ebrahimi VIXL_ASSERT(pc == 4);
572*f5c631daSSadaf Ebrahimi delete object;
573*f5c631daSSadaf Ebrahimi
574*f5c631daSSadaf Ebrahimi // Label that needs padding because of the alignment of the reference.
575*f5c631daSSadaf Ebrahimi object = new TestBranchObject(4 /*size*/, 1 /*alignment*/);
576*f5c631daSSadaf Ebrahimi ref = new ForwardReference<int32_t>(0 /*location*/,
577*f5c631daSSadaf Ebrahimi 2 /*size*/,
578*f5c631daSSadaf Ebrahimi 0 /*min_location*/,
579*f5c631daSSadaf Ebrahimi 500 /*max_location*/,
580*f5c631daSSadaf Ebrahimi 4 /*alignment*/);
581*f5c631daSSadaf Ebrahimi object->AddReference(ref);
582*f5c631daSSadaf Ebrahimi pool_manager.AddObjectReference(ref, object);
583*f5c631daSSadaf Ebrahimi
584*f5c631daSSadaf Ebrahimi pc = 2;
585*f5c631daSSadaf Ebrahimi pc = pool_manager.Bind(&masm, object, pc);
586*f5c631daSSadaf Ebrahimi VIXL_ASSERT(pc == 4);
587*f5c631daSSadaf Ebrahimi delete object;
588*f5c631daSSadaf Ebrahimi }
589*f5c631daSSadaf Ebrahimi
590*f5c631daSSadaf Ebrahimi // This test checks that when we omit the pool header, we insert any padding
591*f5c631daSSadaf Ebrahimi // needed in order to meet the minimum location of the first object.
TEST(PoolWithoutHeaderMinLocation)592*f5c631daSSadaf Ebrahimi TEST(PoolWithoutHeaderMinLocation) {
593*f5c631daSSadaf Ebrahimi TestMacroAssembler masm;
594*f5c631daSSadaf Ebrahimi
595*f5c631daSSadaf Ebrahimi PoolManager<int32_t> pool_manager(4 /*header_size*/,
596*f5c631daSSadaf Ebrahimi 2 /*header_alignment*/,
597*f5c631daSSadaf Ebrahimi BUFFER_ALIGNMENT);
598*f5c631daSSadaf Ebrahimi int object_size = 4;
599*f5c631daSSadaf Ebrahimi int object_alignment = 1; // Do not restrict alignment for this test.
600*f5c631daSSadaf Ebrahimi int min_location = 4; // We emit the pool at location 2, so need padding.
601*f5c631daSSadaf Ebrahimi int max_location = 500;
602*f5c631daSSadaf Ebrahimi TestObject object(object_size, object_alignment);
603*f5c631daSSadaf Ebrahimi ForwardReference<int32_t> *ref = new ForwardReference<int32_t>(0 /*location*/,
604*f5c631daSSadaf Ebrahimi 2 /*size*/,
605*f5c631daSSadaf Ebrahimi min_location,
606*f5c631daSSadaf Ebrahimi max_location);
607*f5c631daSSadaf Ebrahimi object.AddReference(ref);
608*f5c631daSSadaf Ebrahimi pool_manager.AddObjectReference(ref, &object);
609*f5c631daSSadaf Ebrahimi
610*f5c631daSSadaf Ebrahimi int32_t new_pc = pool_manager.Emit(&masm,
611*f5c631daSSadaf Ebrahimi 2,
612*f5c631daSSadaf Ebrahimi 0, /* no new code added */
613*f5c631daSSadaf Ebrahimi NULL,
614*f5c631daSSadaf Ebrahimi NULL,
615*f5c631daSSadaf Ebrahimi PoolManager<int32_t>::kNoBranchRequired);
616*f5c631daSSadaf Ebrahimi USE(new_pc);
617*f5c631daSSadaf Ebrahimi VIXL_ASSERT(new_pc == min_location + object_size);
618*f5c631daSSadaf Ebrahimi }
619*f5c631daSSadaf Ebrahimi
620*f5c631daSSadaf Ebrahimi // This test checks that when we omit the pool header, we insert any padding
621*f5c631daSSadaf Ebrahimi // needed in order to meet the alignment of the first object.
TEST(PoolWithoutHeaderAlignment)622*f5c631daSSadaf Ebrahimi TEST(PoolWithoutHeaderAlignment) {
623*f5c631daSSadaf Ebrahimi TestMacroAssembler masm;
624*f5c631daSSadaf Ebrahimi
625*f5c631daSSadaf Ebrahimi PoolManager<int32_t> pool_manager(4 /*header_size*/,
626*f5c631daSSadaf Ebrahimi 2 /*header_alignment*/,
627*f5c631daSSadaf Ebrahimi BUFFER_ALIGNMENT);
628*f5c631daSSadaf Ebrahimi int object_size = 4;
629*f5c631daSSadaf Ebrahimi int object_alignment = 4; // We emit the pool at location 2, so need padding.
630*f5c631daSSadaf Ebrahimi int min_location = 0; // Do not restrict this for this test.
631*f5c631daSSadaf Ebrahimi int max_location = 500;
632*f5c631daSSadaf Ebrahimi TestObject object(object_size, object_alignment);
633*f5c631daSSadaf Ebrahimi ForwardReference<int32_t> *ref = new ForwardReference<int32_t>(0 /*location*/,
634*f5c631daSSadaf Ebrahimi 2 /*size*/,
635*f5c631daSSadaf Ebrahimi min_location,
636*f5c631daSSadaf Ebrahimi max_location);
637*f5c631daSSadaf Ebrahimi object.AddReference(ref);
638*f5c631daSSadaf Ebrahimi pool_manager.AddObjectReference(ref, &object);
639*f5c631daSSadaf Ebrahimi
640*f5c631daSSadaf Ebrahimi int32_t pc = 2;
641*f5c631daSSadaf Ebrahimi int32_t new_pc = pool_manager.Emit(&masm,
642*f5c631daSSadaf Ebrahimi pc,
643*f5c631daSSadaf Ebrahimi 0, /* no new code added */
644*f5c631daSSadaf Ebrahimi NULL,
645*f5c631daSSadaf Ebrahimi NULL,
646*f5c631daSSadaf Ebrahimi PoolManager<int32_t>::kNoBranchRequired);
647*f5c631daSSadaf Ebrahimi USE(pc);
648*f5c631daSSadaf Ebrahimi USE(new_pc);
649*f5c631daSSadaf Ebrahimi VIXL_ASSERT(new_pc == AlignUp(pc, object_alignment) + object_size);
650*f5c631daSSadaf Ebrahimi }
651*f5c631daSSadaf Ebrahimi
AddNBranches(PoolManager<int32_t> * pool_manager,int32_t pc,TestBranchObject * labels[],int num_branches,int branch_size,int veneer_size,int veneer_alignment,int branch_range)652*f5c631daSSadaf Ebrahimi static int32_t AddNBranches(PoolManager<int32_t> *pool_manager,
653*f5c631daSSadaf Ebrahimi int32_t pc,
654*f5c631daSSadaf Ebrahimi TestBranchObject *labels[],
655*f5c631daSSadaf Ebrahimi int num_branches,
656*f5c631daSSadaf Ebrahimi int branch_size,
657*f5c631daSSadaf Ebrahimi int veneer_size,
658*f5c631daSSadaf Ebrahimi int veneer_alignment,
659*f5c631daSSadaf Ebrahimi int branch_range) {
660*f5c631daSSadaf Ebrahimi for (int i = 0; i < num_branches; ++i) {
661*f5c631daSSadaf Ebrahimi labels[i] = new TestBranchObject(veneer_size, veneer_alignment);
662*f5c631daSSadaf Ebrahimi int32_t min_location = pc;
663*f5c631daSSadaf Ebrahimi int32_t max_location = pc + branch_range;
664*f5c631daSSadaf Ebrahimi ForwardReference<int32_t> *ref =
665*f5c631daSSadaf Ebrahimi new ForwardReference<int32_t>(pc,
666*f5c631daSSadaf Ebrahimi branch_size,
667*f5c631daSSadaf Ebrahimi min_location,
668*f5c631daSSadaf Ebrahimi max_location);
669*f5c631daSSadaf Ebrahimi labels[i]->AddReference(ref);
670*f5c631daSSadaf Ebrahimi // We have picked the object sizes so that we do not need to emit now.
671*f5c631daSSadaf Ebrahimi VIXL_ASSERT(!pool_manager->MustEmit(pc, branch_size, ref, labels[i]));
672*f5c631daSSadaf Ebrahimi pool_manager->AddObjectReference(ref, labels[i]);
673*f5c631daSSadaf Ebrahimi pc += branch_size;
674*f5c631daSSadaf Ebrahimi }
675*f5c631daSSadaf Ebrahimi return pc;
676*f5c631daSSadaf Ebrahimi }
677*f5c631daSSadaf Ebrahimi
TEST(MustEmitNewReferenceDueToRange)678*f5c631daSSadaf Ebrahimi TEST(MustEmitNewReferenceDueToRange) {
679*f5c631daSSadaf Ebrahimi const int kHeaderSize = 4;
680*f5c631daSSadaf Ebrahimi const int kHeaderAlignment = 2;
681*f5c631daSSadaf Ebrahimi const int kNumBranches = 550;
682*f5c631daSSadaf Ebrahimi const int kBranchSize = 4;
683*f5c631daSSadaf Ebrahimi const int kVeneerSize = 4;
684*f5c631daSSadaf Ebrahimi const int kVeneerAlignment = 2;
685*f5c631daSSadaf Ebrahimi const int kBranchRange = 1 * MBytes;
686*f5c631daSSadaf Ebrahimi int32_t pc = 0;
687*f5c631daSSadaf Ebrahimi
688*f5c631daSSadaf Ebrahimi TestMacroAssembler masm;
689*f5c631daSSadaf Ebrahimi TestBranchObject *labels[kNumBranches];
690*f5c631daSSadaf Ebrahimi PoolManager<int32_t> pool_manager(kHeaderSize,
691*f5c631daSSadaf Ebrahimi kHeaderAlignment,
692*f5c631daSSadaf Ebrahimi BUFFER_ALIGNMENT);
693*f5c631daSSadaf Ebrahimi AddNBranches(&pool_manager,
694*f5c631daSSadaf Ebrahimi pc,
695*f5c631daSSadaf Ebrahimi labels,
696*f5c631daSSadaf Ebrahimi kNumBranches,
697*f5c631daSSadaf Ebrahimi kBranchSize,
698*f5c631daSSadaf Ebrahimi kVeneerSize,
699*f5c631daSSadaf Ebrahimi kVeneerAlignment,
700*f5c631daSSadaf Ebrahimi kBranchRange);
701*f5c631daSSadaf Ebrahimi
702*f5c631daSSadaf Ebrahimi // Increment PC to close to the checkpoint of the pools.
703*f5c631daSSadaf Ebrahimi TestPoolManager test(&pool_manager);
704*f5c631daSSadaf Ebrahimi pc = test.GetPoolCheckpoint() - 4;
705*f5c631daSSadaf Ebrahimi VIXL_ASSERT(!pool_manager.MustEmit(pc));
706*f5c631daSSadaf Ebrahimi
707*f5c631daSSadaf Ebrahimi // Now, attempt to add a reference that would make the problem impossible.
708*f5c631daSSadaf Ebrahimi // We need to emit the pool immediately after this new instruction, and
709*f5c631daSSadaf Ebrahimi // the current size of the pool is kVeneerSize * kNumBranches, so adding a
710*f5c631daSSadaf Ebrahimi // short-range (smaller than the pool size) reference should trigger pool
711*f5c631daSSadaf Ebrahimi // emission.
712*f5c631daSSadaf Ebrahimi const int kPoolSize = kVeneerSize * kNumBranches + kHeaderSize;
713*f5c631daSSadaf Ebrahimi
714*f5c631daSSadaf Ebrahimi const int kNewObjectSize = 2;
715*f5c631daSSadaf Ebrahimi TestObject new_object(kNewObjectSize, 1);
716*f5c631daSSadaf Ebrahimi
717*f5c631daSSadaf Ebrahimi ForwardReference<int32_t> temp_ref(pc,
718*f5c631daSSadaf Ebrahimi kBranchSize,
719*f5c631daSSadaf Ebrahimi pc,
720*f5c631daSSadaf Ebrahimi pc + kPoolSize + kBranchSize - 1);
721*f5c631daSSadaf Ebrahimi VIXL_ASSERT(pool_manager.MustEmit(pc, kBranchSize, &temp_ref, &new_object));
722*f5c631daSSadaf Ebrahimi
723*f5c631daSSadaf Ebrahimi // Before actually emitting the pool, try a few different references to make
724*f5c631daSSadaf Ebrahimi // sure that this works as expected.
725*f5c631daSSadaf Ebrahimi {
726*f5c631daSSadaf Ebrahimi // This reference has a large enough range, so should not force pool
727*f5c631daSSadaf Ebrahimi // emission.
728*f5c631daSSadaf Ebrahimi ForwardReference<int32_t> far_ref(pc,
729*f5c631daSSadaf Ebrahimi kBranchSize,
730*f5c631daSSadaf Ebrahimi pc,
731*f5c631daSSadaf Ebrahimi pc + kPoolSize + kBranchSize);
732*f5c631daSSadaf Ebrahimi VIXL_ASSERT(!pool_manager.MustEmit(pc, kBranchSize, &far_ref, &new_object));
733*f5c631daSSadaf Ebrahimi
734*f5c631daSSadaf Ebrahimi // This reference had a large enough range but will be restricted by
735*f5c631daSSadaf Ebrahimi // alignment so should force pool emission.
736*f5c631daSSadaf Ebrahimi int alignment = 16;
737*f5c631daSSadaf Ebrahimi VIXL_ASSERT((pc & (alignment - 1)) != 0);
738*f5c631daSSadaf Ebrahimi ForwardReference<int32_t> aligned_ref(pc,
739*f5c631daSSadaf Ebrahimi kBranchSize,
740*f5c631daSSadaf Ebrahimi pc,
741*f5c631daSSadaf Ebrahimi pc + kPoolSize + kBranchSize,
742*f5c631daSSadaf Ebrahimi alignment);
743*f5c631daSSadaf Ebrahimi VIXL_ASSERT(
744*f5c631daSSadaf Ebrahimi pool_manager.MustEmit(pc, kBranchSize, &aligned_ref, &new_object));
745*f5c631daSSadaf Ebrahimi }
746*f5c631daSSadaf Ebrahimi
747*f5c631daSSadaf Ebrahimi // Emit the pool and check its size.
748*f5c631daSSadaf Ebrahimi int32_t new_pc =
749*f5c631daSSadaf Ebrahimi pool_manager.Emit(&masm, pc, kBranchSize, &temp_ref, &new_object);
750*f5c631daSSadaf Ebrahimi VIXL_ASSERT(pc % kHeaderAlignment == 0); // No need for padding.
751*f5c631daSSadaf Ebrahimi VIXL_ASSERT(new_pc == pc + kPoolSize);
752*f5c631daSSadaf Ebrahimi pc = new_pc;
753*f5c631daSSadaf Ebrahimi
754*f5c631daSSadaf Ebrahimi // Add the new reference, safely.
755*f5c631daSSadaf Ebrahimi ForwardReference<int32_t> *ref =
756*f5c631daSSadaf Ebrahimi new ForwardReference<int32_t>(pc, 4 /*size*/, pc, pc + kBranchRange);
757*f5c631daSSadaf Ebrahimi new_object.AddReference(ref);
758*f5c631daSSadaf Ebrahimi pool_manager.AddObjectReference(ref, &new_object);
759*f5c631daSSadaf Ebrahimi pc += 4;
760*f5c631daSSadaf Ebrahimi
761*f5c631daSSadaf Ebrahimi // Emit the pool again.
762*f5c631daSSadaf Ebrahimi new_pc = pool_manager.Emit(&masm, pc);
763*f5c631daSSadaf Ebrahimi VIXL_ASSERT(pc % kHeaderAlignment == 0); // No need for padding.
764*f5c631daSSadaf Ebrahimi VIXL_ASSERT(new_pc == pc + kNewObjectSize + kHeaderSize);
765*f5c631daSSadaf Ebrahimi pc = new_pc;
766*f5c631daSSadaf Ebrahimi
767*f5c631daSSadaf Ebrahimi // Finally, bind the labels.
768*f5c631daSSadaf Ebrahimi for (int i = 0; i < kNumBranches; ++i) {
769*f5c631daSSadaf Ebrahimi pc = pool_manager.Bind(&masm, labels[i], pc);
770*f5c631daSSadaf Ebrahimi delete labels[i];
771*f5c631daSSadaf Ebrahimi }
772*f5c631daSSadaf Ebrahimi }
773*f5c631daSSadaf Ebrahimi
TEST(MustEmitNewReferenceDueToSizeOfObject)774*f5c631daSSadaf Ebrahimi TEST(MustEmitNewReferenceDueToSizeOfObject) {
775*f5c631daSSadaf Ebrahimi const int kHeaderSize = 4;
776*f5c631daSSadaf Ebrahimi const int kHeaderAlignment = 2;
777*f5c631daSSadaf Ebrahimi const int kNumBranches = 550;
778*f5c631daSSadaf Ebrahimi const int kBranchSize = 4;
779*f5c631daSSadaf Ebrahimi const int kVeneerSize = 4;
780*f5c631daSSadaf Ebrahimi const int kVeneerAlignment = 2;
781*f5c631daSSadaf Ebrahimi const int kBranchRange = 1 * MBytes;
782*f5c631daSSadaf Ebrahimi int32_t pc = 0;
783*f5c631daSSadaf Ebrahimi
784*f5c631daSSadaf Ebrahimi TestMacroAssembler masm;
785*f5c631daSSadaf Ebrahimi PoolManager<int32_t> pool_manager(kHeaderSize,
786*f5c631daSSadaf Ebrahimi kHeaderAlignment,
787*f5c631daSSadaf Ebrahimi BUFFER_ALIGNMENT);
788*f5c631daSSadaf Ebrahimi TestBranchObject *labels[kNumBranches];
789*f5c631daSSadaf Ebrahimi AddNBranches(&pool_manager,
790*f5c631daSSadaf Ebrahimi pc,
791*f5c631daSSadaf Ebrahimi labels,
792*f5c631daSSadaf Ebrahimi kNumBranches,
793*f5c631daSSadaf Ebrahimi kBranchSize,
794*f5c631daSSadaf Ebrahimi kVeneerSize,
795*f5c631daSSadaf Ebrahimi kVeneerAlignment,
796*f5c631daSSadaf Ebrahimi kBranchRange);
797*f5c631daSSadaf Ebrahimi
798*f5c631daSSadaf Ebrahimi
799*f5c631daSSadaf Ebrahimi // Increment PC to close to the checkpoint of the pools minus a known
800*f5c631daSSadaf Ebrahimi // thershold.
801*f5c631daSSadaf Ebrahimi const int kBigObjectSize = 1024;
802*f5c631daSSadaf Ebrahimi TestPoolManager test(&pool_manager);
803*f5c631daSSadaf Ebrahimi pc = test.GetPoolCheckpoint() - kBigObjectSize;
804*f5c631daSSadaf Ebrahimi VIXL_ASSERT(!pool_manager.MustEmit(pc));
805*f5c631daSSadaf Ebrahimi
806*f5c631daSSadaf Ebrahimi // Now, attempt to add a reference that would make the problem impossible.
807*f5c631daSSadaf Ebrahimi // If we add a short-range (smaller than the pool size) reference with a
808*f5c631daSSadaf Ebrahimi // large size (larger than the margin we have until pool emission), pool
809*f5c631daSSadaf Ebrahimi // emission should be triggered.
810*f5c631daSSadaf Ebrahimi const int kPoolSize = kVeneerSize * kNumBranches + kHeaderSize;
811*f5c631daSSadaf Ebrahimi
812*f5c631daSSadaf Ebrahimi TestObject new_object(kBigObjectSize, 1);
813*f5c631daSSadaf Ebrahimi ForwardReference<int32_t> temp_ref(pc, kBranchSize, pc, pc + kPoolSize);
814*f5c631daSSadaf Ebrahimi VIXL_ASSERT(pool_manager.MustEmit(pc, kBranchSize, &temp_ref, &new_object));
815*f5c631daSSadaf Ebrahimi
816*f5c631daSSadaf Ebrahimi // Before actually emitting the pool, try a few different references to make
817*f5c631daSSadaf Ebrahimi // sure that this works as expected.
818*f5c631daSSadaf Ebrahimi {
819*f5c631daSSadaf Ebrahimi // If the object is smaller, we can emit the reference.
820*f5c631daSSadaf Ebrahimi TestObject smaller_object(kBigObjectSize - 4, 1);
821*f5c631daSSadaf Ebrahimi ForwardReference<int32_t> temp_ref2(pc, kBranchSize, pc, pc + kPoolSize);
822*f5c631daSSadaf Ebrahimi VIXL_ASSERT(
823*f5c631daSSadaf Ebrahimi !pool_manager.MustEmit(pc, kBranchSize, &temp_ref2, &smaller_object));
824*f5c631daSSadaf Ebrahimi
825*f5c631daSSadaf Ebrahimi // If the reference is going to be added after the current objects in the
826*f5c631daSSadaf Ebrahimi // pool, we can still emit it.
827*f5c631daSSadaf Ebrahimi ForwardReference<int32_t> far_ref(pc, kBranchSize, pc, pc + kBranchRange);
828*f5c631daSSadaf Ebrahimi VIXL_ASSERT(!pool_manager.MustEmit(pc, kBranchSize, &far_ref, &new_object));
829*f5c631daSSadaf Ebrahimi }
830*f5c631daSSadaf Ebrahimi
831*f5c631daSSadaf Ebrahimi // Emit the pool and check its size.
832*f5c631daSSadaf Ebrahimi int32_t new_pc =
833*f5c631daSSadaf Ebrahimi pool_manager.Emit(&masm, pc, kBranchSize, &temp_ref, &new_object);
834*f5c631daSSadaf Ebrahimi VIXL_ASSERT(pc % kHeaderAlignment == 0); // No need for padding.
835*f5c631daSSadaf Ebrahimi VIXL_ASSERT(new_pc == pc + kPoolSize);
836*f5c631daSSadaf Ebrahimi pc = new_pc;
837*f5c631daSSadaf Ebrahimi
838*f5c631daSSadaf Ebrahimi // Add the new reference, safely.
839*f5c631daSSadaf Ebrahimi ForwardReference<int32_t> *ref =
840*f5c631daSSadaf Ebrahimi new ForwardReference<int32_t>(pc, 4 /*size*/, pc, pc + kBranchRange);
841*f5c631daSSadaf Ebrahimi new_object.AddReference(ref);
842*f5c631daSSadaf Ebrahimi pool_manager.AddObjectReference(ref, &new_object);
843*f5c631daSSadaf Ebrahimi pc += 4;
844*f5c631daSSadaf Ebrahimi
845*f5c631daSSadaf Ebrahimi // Emit the pool again.
846*f5c631daSSadaf Ebrahimi new_pc = pool_manager.Emit(&masm, pc);
847*f5c631daSSadaf Ebrahimi VIXL_ASSERT(pc % kHeaderAlignment == 0); // No need for padding.
848*f5c631daSSadaf Ebrahimi VIXL_ASSERT(new_pc == pc + kBigObjectSize + kHeaderSize);
849*f5c631daSSadaf Ebrahimi pc = new_pc;
850*f5c631daSSadaf Ebrahimi
851*f5c631daSSadaf Ebrahimi // Finally, bind the labels.
852*f5c631daSSadaf Ebrahimi for (int i = 0; i < kNumBranches; ++i) {
853*f5c631daSSadaf Ebrahimi pc = pool_manager.Bind(&masm, labels[i], pc);
854*f5c631daSSadaf Ebrahimi delete labels[i];
855*f5c631daSSadaf Ebrahimi }
856*f5c631daSSadaf Ebrahimi }
857*f5c631daSSadaf Ebrahimi
858*f5c631daSSadaf Ebrahimi template <typename ObjectType>
ManagedLocationBaseTestHelper()859*f5c631daSSadaf Ebrahimi void ManagedLocationBaseTestHelper() {
860*f5c631daSSadaf Ebrahimi TestMacroAssembler masm;
861*f5c631daSSadaf Ebrahimi
862*f5c631daSSadaf Ebrahimi PoolManager<int32_t> pool_manager(4 /*header_size*/,
863*f5c631daSSadaf Ebrahimi 2 /*header_alignment*/,
864*f5c631daSSadaf Ebrahimi BUFFER_ALIGNMENT);
865*f5c631daSSadaf Ebrahimi ObjectType *object1 = new ObjectType();
866*f5c631daSSadaf Ebrahimi ObjectType *object2 = new ObjectType();
867*f5c631daSSadaf Ebrahimi ForwardReference<int32_t> *ref_obj1 =
868*f5c631daSSadaf Ebrahimi new ForwardReference<int32_t>(0 /*location*/, 2 /*size*/, 0, 200);
869*f5c631daSSadaf Ebrahimi object1->AddReference(ref_obj1);
870*f5c631daSSadaf Ebrahimi ForwardReference<int32_t> *ref_obj2 =
871*f5c631daSSadaf Ebrahimi new ForwardReference<int32_t>(8 /*location*/, 2 /*size*/, 8, 500);
872*f5c631daSSadaf Ebrahimi object2->AddReference(ref_obj2);
873*f5c631daSSadaf Ebrahimi
874*f5c631daSSadaf Ebrahimi pool_manager.AddObjectReference(ref_obj1, object1);
875*f5c631daSSadaf Ebrahimi pool_manager.AddObjectReference(ref_obj2, object2);
876*f5c631daSSadaf Ebrahimi
877*f5c631daSSadaf Ebrahimi pool_manager.Emit(&masm, 20);
878*f5c631daSSadaf Ebrahimi }
879*f5c631daSSadaf Ebrahimi
880*f5c631daSSadaf Ebrahimi class TestObjectDeletedOnPlacement : public TestObject {
881*f5c631daSSadaf Ebrahimi public:
TestObjectDeletedOnPlacement()882*f5c631daSSadaf Ebrahimi TestObjectDeletedOnPlacement() : TestObject(4 /*size*/, 4 /*alignment*/) {}
883*f5c631daSSadaf Ebrahimi // After passing ownership of this type of object to the pool manager, it is
884*f5c631daSSadaf Ebrahimi // not safe to use it anymore.
ShouldBeDeletedOnPlacementByPoolManager() const885*f5c631daSSadaf Ebrahimi virtual bool ShouldBeDeletedOnPlacementByPoolManager() const VIXL_OVERRIDE {
886*f5c631daSSadaf Ebrahimi return true;
887*f5c631daSSadaf Ebrahimi }
888*f5c631daSSadaf Ebrahimi };
889*f5c631daSSadaf Ebrahimi
TEST(DeleteLocationBaseOnPlacement)890*f5c631daSSadaf Ebrahimi TEST(DeleteLocationBaseOnPlacement) {
891*f5c631daSSadaf Ebrahimi ManagedLocationBaseTestHelper<TestObjectDeletedOnPlacement>();
892*f5c631daSSadaf Ebrahimi }
893*f5c631daSSadaf Ebrahimi
894*f5c631daSSadaf Ebrahimi class TestObjectDeletedOnPoolManagerDestruction : public TestObject {
895*f5c631daSSadaf Ebrahimi public:
TestObjectDeletedOnPoolManagerDestruction()896*f5c631daSSadaf Ebrahimi TestObjectDeletedOnPoolManagerDestruction()
897*f5c631daSSadaf Ebrahimi : TestObject(4 /*size*/, 4 /*alignment*/) {}
898*f5c631daSSadaf Ebrahimi // We can continue using this type of object after passing its ownership to
899*f5c631daSSadaf Ebrahimi // the pool manager, as it will be deleted only when the pool manager is
900*f5c631daSSadaf Ebrahimi // destroyed.
ShouldBeDeletedOnPoolManagerDestruction() const901*f5c631daSSadaf Ebrahimi virtual bool ShouldBeDeletedOnPoolManagerDestruction() const VIXL_OVERRIDE {
902*f5c631daSSadaf Ebrahimi return true;
903*f5c631daSSadaf Ebrahimi }
904*f5c631daSSadaf Ebrahimi };
905*f5c631daSSadaf Ebrahimi
906*f5c631daSSadaf Ebrahimi
TEST(DeleteLocationBaseOnPoolManagerDestruction)907*f5c631daSSadaf Ebrahimi TEST(DeleteLocationBaseOnPoolManagerDestruction) {
908*f5c631daSSadaf Ebrahimi ManagedLocationBaseTestHelper<TestObjectDeletedOnPoolManagerDestruction>();
909*f5c631daSSadaf Ebrahimi }
910