Flutter Engine
The Flutter Engine
native_location.cc
Go to the documentation of this file.
1// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
6
8
9namespace dart {
10
11namespace compiler {
12
13namespace ffi {
14
15#if !defined(FFI_UNIT_TESTS)
17 switch (loc.kind()) {
18 case Location::Kind::kRegister:
19 case Location::Kind::kFpuRegister:
20 case Location::Kind::kStackSlot:
21 case Location::Kind::kDoubleStackSlot:
22 return true;
23 default:
24 break;
25 }
26 if (loc.IsPairLocation()) {
27 return false;
28 }
29 return false;
30}
31
33 Location loc,
34 Representation rep) {
36
37 const NativeType& native_rep = NativeType::FromRepresentation(zone, rep);
38
39 switch (loc.kind()) {
40 case Location::Kind::kRegister:
41 return *new (zone)
42 NativeRegistersLocation(zone, native_rep, native_rep, loc.reg());
43 case Location::Kind::kFpuRegister:
44 return *new (zone)
45 NativeFpuRegistersLocation(native_rep, native_rep, loc.fpu_reg());
46 case Location::Kind::kStackSlot:
47 return *new (zone)
48 NativeStackLocation(native_rep, native_rep, loc.base_reg(),
50 case Location::Kind::kDoubleStackSlot:
51 return *new (zone)
52 NativeStackLocation(native_rep, native_rep, loc.base_reg(),
54 default:
55 break;
56 }
57
59}
60
62 Location pair_loc,
63 Representation pair_rep,
64 intptr_t index) {
65 ASSERT(pair_loc.IsPairLocation());
66 ASSERT(index == 0 || index == 1);
67 const Representation rep = NativeType::FromRepresentation(zone, pair_rep)
68 .Split(zone, index)
70 const Location loc = pair_loc.AsPairLocation()->At(index);
71 return FromLocation(zone, loc, rep);
72}
73#endif
74
77 return static_cast<const NativeRegistersLocation&>(*this);
78}
79
82 return static_cast<const NativeFpuRegistersLocation&>(*this);
83}
84
86 ASSERT(IsStack());
87 return static_cast<const NativeStackLocation&>(*this);
88}
89
92 return static_cast<const MultipleNativeLocations&>(*this);
93}
94
97 return static_cast<const PointerToMemoryLocation&>(*this);
98}
99
101 ASSERT(IsBoth());
102 return static_cast<const BothNativeLocations&>(*this);
103}
104
105#if !defined(FFI_UNIT_TESTS)
108 switch (num_regs()) {
109 case 1:
110 return Location::RegisterLocation(regs_->At(0));
111 case 2:
113 Location::RegisterLocation(regs_->At(1)));
114 }
116}
117
120 if (payload_type().IsInt()) {
121 const intptr_t size = payload_type().SizeInBytes();
122 const intptr_t size_slots = size / compiler::target::kWordSize;
123 switch (size_slots) {
124 case 1:
125 return Location::StackSlot(offset_in_words(), base_register_);
126 case 2:
127 return Location::Pair(
128 Location::StackSlot(offset_in_words(), base_register_),
129 Location::StackSlot(offset_in_words() + 1, base_register_));
130 }
131 } else {
132 ASSERT(payload_type().IsFloat());
133 if (payload_type().AsPrimitive().representation() == kFloat) {
134 return Location::StackSlot(offset_in_words(), base_register_);
135 } else {
136 ASSERT(payload_type().AsPrimitive().representation() == kDouble);
137 return Location::DoubleStackSlot(offset_in_words(), base_register_);
138 }
139 }
141}
142#endif
143
145 intptr_t num_parts,
146 intptr_t index) const {
147 ASSERT(num_parts == 2);
148 ASSERT(num_regs() == num_parts);
149 return *new (zone) NativeRegistersLocation(
150 zone, payload_type().Split(zone, index),
151 container_type().Split(zone, index), reg_at(index));
152}
153
155 intptr_t num_parts,
156 intptr_t index) const {
157 const intptr_t size = payload_type().SizeInBytes();
158
159 if (payload_type().IsPrimitive()) {
160 ASSERT(num_parts == 2);
161 return *new (zone) NativeStackLocation(
162 payload_type().Split(zone, index), container_type().Split(zone, index),
163 base_register_, offset_in_bytes_ + size / num_parts * index);
164 } else {
165 const intptr_t size_rounded_up =
167 ASSERT(size_rounded_up / compiler::target::kWordSize == num_parts);
168
169 // Blocks of compiler::target::kWordSize.
170 return *new (zone) NativeStackLocation(
171 *new (zone) NativePrimitiveType(
173 *new (zone) NativePrimitiveType(
175 base_register_, offset_in_bytes_ + compiler::target::kWordSize * index);
176 }
177}
178
180 intptr_t height = 0;
181 for (int i = 0; i < locations_.length(); i++) {
182 height = Utils::Maximum(height, locations_[i]->StackTopInBytes());
183 }
184 return height;
185}
186
190}
191
195}
196
197#if defined(TARGET_ARCH_ARM)
198const NativeLocation& NativeLocation::WidenToQFpuRegister(Zone* zone) const {
199 if (!IsFpuRegisters()) {
200 return *this;
201 }
202 const auto& fpu_loc = AsFpuRegisters();
203 switch (fpu_loc.fpu_reg_kind()) {
204 case kQuadFpuReg:
205 return *this;
206 case kDoubleFpuReg: {
207 return *new (zone) NativeFpuRegistersLocation(
208 payload_type_, container_type_, QRegisterOf(fpu_loc.fpu_d_reg()));
209 }
210 case kSingleFpuReg: {
211 return *new (zone) NativeFpuRegistersLocation(
212 payload_type_, container_type_, QRegisterOf(fpu_loc.fpu_s_reg()));
213 }
214 }
216}
217#endif // defined(TARGET_ARCH_ARM)
218
220 if (!other.IsRegisters()) {
221 return false;
222 }
223 const auto& other_regs = other.AsRegisters();
224 if (other_regs.num_regs() != num_regs()) {
225 return false;
226 }
227 for (intptr_t i = 0; i < num_regs(); i++) {
228 if (other_regs.reg_at(i) != reg_at(i)) {
229 return false;
230 }
231 }
232 return true;
233}
234
236 if (!other.IsFpuRegisters()) {
237 return false;
238 }
239 auto& other_fpu_reg = other.AsFpuRegisters();
240 if (other_fpu_reg.fpu_reg_kind() != fpu_reg_kind()) {
241 return false;
242 }
243 // We can only compare `fpu_reg_` if the kind is the same.
244 // Q5 is not the same register as (nor overlaps) D5.
245 return other_fpu_reg.fpu_reg_ == fpu_reg_;
246}
247
249 if (!other.IsStack()) {
250 return false;
251 }
252 const auto& other_stack = other.AsStack();
253 if (other_stack.base_register_ != base_register_) {
254 return false;
255 }
256 return other_stack.offset_in_bytes_ == offset_in_bytes_;
257}
258
260 if (!other.IsPointerToMemory()) {
261 return false;
262 }
263 const auto& other_pointer = other.AsPointerToMemory();
264 if (!other_pointer.pointer_location_.Equals(pointer_location_)) {
265 return false;
266 }
267 return other_pointer.payload_type().Equals(payload_type());
268}
269
270#if !defined(FFI_UNIT_TESTS)
272 const NativeStackLocation& loc) {
274}
275#endif
276
278 f->AddString(" ");
279 loc.container_type().PrintTo(f, /*multi_line=*/false, /*verbose=*/false);
280 if (!loc.container_type().Equals(loc.payload_type())) {
281 f->AddString("[");
282 loc.payload_type().PrintTo(f, /*multi_line=*/false, /*verbose=*/false);
283 f->AddString("]");
284 }
285}
286
288 f->AddString("I");
289 PrintRepresentations(f, *this);
290}
291
293 if (num_regs() == 1) {
294 f->Printf("%s", RegisterNames::RegisterAbiName(regs_->At(0)));
295 } else {
296 f->AddString("(");
297 for (intptr_t i = 0; i < num_regs(); i++) {
298 if (i != 0) {
299 f->Printf(", ");
300 }
301 f->Printf("%s", RegisterNames::RegisterAbiName(regs_->At(i)));
302 }
303 f->AddString(")");
304 }
305 PrintRepresentations(f, *this);
306}
307
309 switch (fpu_reg_kind()) {
310 case kQuadFpuReg:
311 f->Printf("%s", RegisterNames::FpuRegisterName(fpu_reg()));
312 break;
313#if defined(TARGET_ARCH_ARM)
314 case kDoubleFpuReg:
315 f->Printf("%s", RegisterNames::FpuDRegisterName(fpu_d_reg()));
316 break;
317 case kSingleFpuReg:
318 f->Printf("%s", RegisterNames::FpuSRegisterName(fpu_s_reg()));
319 break;
320#endif // defined(TARGET_ARCH_ARM)
321 default:
323 }
324
325 PrintRepresentations(f, *this);
326}
327
329 if (base_register_ != SPREG) {
330 f->Printf("S(%s)+%" Pd, RegisterNames::RegisterAbiName(base_register_),
331 offset_in_bytes_);
332 } else {
333 f->Printf("S+%" Pd, offset_in_bytes_);
334 }
335 PrintRepresentations(f, *this);
336}
337
338const char* NativeLocation::ToCString(Zone* zone) const {
339 ZoneTextBuffer textBuffer(zone);
340 PrintTo(&textBuffer);
341 return textBuffer.buffer();
342}
343
345 f->Printf("P(");
348 f->Printf(", ret:");
350 }
351 f->Printf(")");
352 PrintRepresentations(f, *this);
353}
354
356 f->Printf("M(");
357 for (intptr_t i = 0; i < locations_.length(); i++) {
358 if (i != 0) f->Printf(", ");
359 locations_[i]->PrintTo(f);
360 }
361 f->Printf(")");
362 PrintRepresentations(f, *this);
363}
364
366 f->Printf("B(");
367 location0_.PrintTo(f);
368 f->Printf(", ");
369 location1_.PrintTo(f);
370 f->Printf(")");
371}
372
373#if !defined(FFI_UNIT_TESTS)
374const char* NativeLocation::ToCString() const {
375 return ToCString(Thread::Current()->zone());
376}
377#endif
378
380 switch (kind) {
381 case kQuadFpuReg:
382 return 16;
383 case kDoubleFpuReg:
384 return 8;
385 case kSingleFpuReg:
386 return 4;
387 }
388 UNREACHABLE();
389}
390enum FpuRegisterKind FpuRegisterKindFromSize(intptr_t size_in_bytes) {
391 switch (size_in_bytes) {
392 case 16:
393 return kQuadFpuReg;
394 case 8:
395 return kDoubleFpuReg;
396 case 4:
397 return kSingleFpuReg;
398 }
399 UNREACHABLE();
400}
401
402#if defined(TARGET_ARCH_ARM)
403DRegister NativeFpuRegistersLocation::fpu_as_d_reg() const {
404 switch (fpu_reg_kind_) {
405 case kQuadFpuReg:
406 return EvenDRegisterOf(fpu_reg());
407 case kDoubleFpuReg:
408 return fpu_d_reg();
409 case kSingleFpuReg:
410 return DRegisterOf(fpu_s_reg());
411 }
413}
414
415SRegister NativeFpuRegistersLocation::fpu_as_s_reg() const {
416 switch (fpu_reg_kind_) {
417 case kQuadFpuReg:
419 case kDoubleFpuReg:
420 return EvenSRegisterOf(fpu_d_reg());
421 case kSingleFpuReg:
422 return fpu_s_reg();
423 }
425}
426
427bool NativeFpuRegistersLocation::IsLowestBits() const {
428 switch (fpu_reg_kind()) {
429 case kQuadFpuReg:
430 return true;
431 case kDoubleFpuReg: {
432 return fpu_d_reg() % 2 == 0;
433 }
434 case kSingleFpuReg: {
435 return fpu_s_reg() % 4 == 0;
436 }
437 }
439}
440#endif // defined(TARGET_ARCH_ARM)
441
442} // namespace ffi
443
444} // namespace compiler
445
446} // namespace dart
#define UNREACHABLE()
Definition: assert.h:248
const T & At(intptr_t index) const
intptr_t length() const
char * buffer() const
Definition: text_buffer.h:35
static Location StackSlot(intptr_t stack_index, Register base)
Definition: locations.h:447
static Location Pair(Location first, Location second)
Definition: locations.cc:271
Register reg() const
Definition: locations.h:404
static Location DoubleStackSlot(intptr_t stack_index, Register base)
Definition: locations.h:458
intptr_t stack_index() const
Definition: locations.h:485
Kind kind() const
Definition: locations.h:523
Register base_reg() const
Definition: locations.h:480
static Location RegisterLocation(Register reg)
Definition: locations.h:398
PairLocation * AsPairLocation() const
Definition: locations.cc:280
bool IsPairLocation() const
Definition: locations.h:316
FpuRegister fpu_reg() const
Definition: locations.h:416
Location At(intptr_t i) const
Definition: locations.h:618
static const char * FpuRegisterName(FpuRegister reg)
Definition: constants.h:54
static const char * RegisterAbiName(Register reg)
Definition: constants.h:50
static Thread * Current()
Definition: thread.h:362
static constexpr T Maximum(T x, T y)
Definition: utils.h:41
static constexpr T RoundUp(T x, uintptr_t alignment, uintptr_t offset=0)
Definition: utils.h:120
virtual void PrintTo(BaseTextBuffer *f) const
virtual void PrintTo(BaseTextBuffer *f) const
virtual bool Equals(const NativeLocation &other) const
virtual void PrintTo(BaseTextBuffer *f) const
virtual bool IsPointerToMemory() const
NativeLocation & WidenTo8Bytes(Zone *zone) const
const MultipleNativeLocations & AsMultiple() const
const NativeType & container_type() const
virtual void PrintTo(BaseTextBuffer *f) const
const NativeRegistersLocation & AsRegisters() const
static bool LocationCanBeExpressed(Location loc, Representation rep)
const PointerToMemoryLocation & AsPointerToMemory() const
static NativeLocation & FromLocation(Zone *zone, Location loc, Representation rep)
const NativeStackLocation & AsStack() const
virtual NativeLocation & WithOtherNativeType(Zone *zone, const NativeType &new_payload_type, const NativeType &new_container_type) const =0
NativeLocation & WidenTo4Bytes(Zone *zone) const
static NativeLocation & FromPairLocation(Zone *zone, Location loc, Representation rep, intptr_t index)
const BothNativeLocations & AsBoth() const
const NativeFpuRegistersLocation & AsFpuRegisters() const
const NativeType & payload_type() const
virtual Representation AsRepresentation() const
Definition: native_type.cc:313
virtual NativePrimitiveType & Split(Zone *zone, intptr_t part) const
Definition: native_type.cc:396
NativeRegistersLocation(const NativeType &payload_type, const NativeType &container_type, ZoneGrowableArray< Register > *registers)
virtual bool Equals(const NativeLocation &other) const
virtual NativeRegistersLocation & Split(Zone *zone, intptr_t num_parts, intptr_t index) const
Register reg_at(intptr_t index) const
virtual void PrintTo(BaseTextBuffer *f) const
virtual NativeStackLocation & Split(Zone *zone, intptr_t num_parts, intptr_t index) const
NativeStackLocation(const NativeType &payload_type, const NativeType &container_type, Register base_register, intptr_t offset_in_bytes)
virtual void PrintTo(BaseTextBuffer *f) const
virtual bool Equals(const NativeLocation &other) const
virtual void PrintTo(BaseTextBuffer *f, bool multi_line=false, bool verbose=true) const
Definition: native_type.cc:715
virtual intptr_t SizeInBytes() const =0
static NativePrimitiveType & FromRepresentation(Zone *zone, Representation rep)
Definition: native_type.cc:632
virtual NativeType & Split(Zone *zone, intptr_t index) const
Definition: native_type.h:130
virtual bool Equals(const NativeType &other) const
Definition: native_type.h:127
const NativeLocation & pointer_location() const
virtual void PrintTo(BaseTextBuffer *f) const
virtual bool Equals(const NativeLocation &other) const
const NativeLocation & pointer_return_location() const
#define ASSERT(E)
intptr_t SizeFromFpuRegisterKind(enum FpuRegisterKind kind)
static void PrintRepresentations(BaseTextBuffer *f, const NativeLocation &loc)
compiler::Address NativeLocationToStackSlotAddress(const NativeStackLocation &loc)
enum FpuRegisterKind FpuRegisterKindFromSize(intptr_t size_in_bytes)
static constexpr intptr_t kWordSize
Definition: runtime_api.h:274
Definition: dart_vm.cc:33
static DRegister EvenDRegisterOf(QRegister q)
Representation
Definition: locations.h:66
static DRegister DRegisterOf(SRegister s)
static QRegister QRegisterOf(DRegister d)
const Register SPREG
static SRegister EvenSRegisterOf(DRegister d)
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
#define UNREACHABLE_THIS()
Definition: native_type.h:25
#define Pd
Definition: globals.h:408
int32_t height