19#if defined(DART_PRECOMPILER) && !defined(TARGET_ARCH_IA32)
24struct RelocatorTestHelper {
25 const intptr_t kTrampolineSize =
31#if defined(TARGET_ARCH_ARM64)
32 static constexpr intptr_t kOffsetOfCall = 4;
33#elif defined(TARGET_ARCH_ARM)
34 static constexpr intptr_t kOffsetOfCall = 4;
35#elif defined(TARGET_ARCH_RISCV32)
36 static constexpr intptr_t kOffsetOfCall = 4;
37#elif defined(TARGET_ARCH_RISCV64)
38 static constexpr intptr_t kOffsetOfCall = 4;
40 static constexpr intptr_t kOffsetOfCall = 0;
43 explicit RelocatorTestHelper(Thread* thread)
45 locker(thread, thread->isolate_group()->program_lock()),
48 FLAG_precompiled_mode =
true;
50 FLAG_lower_pc_relative_call_distance = -128;
51 FLAG_upper_pc_relative_call_distance = 128;
53 ~RelocatorTestHelper() { FLAG_precompiled_mode =
false; }
55 void CreateInstructions(std::initializer_list<intptr_t> sizes) {
56 for (
auto size : sizes) {
61 CodePtr AllocationInstruction(uintptr_t
size) {
66 for (uintptr_t
i = 0;
i < (
size / 4); ++
i) {
67 *
reinterpret_cast<uint32_t*
>(
addr + 4 *
i) =
72 code.SetActiveInstructions(instructions, 0);
73 code.set_instructions(instructions);
77 void EmitPcRelativeCallFunction(intptr_t idx, intptr_t to_idx) {
78 const Code&
code = *codes[idx];
79 const Code&
target = *codes[to_idx];
82#if defined(TARGET_ARCH_ARM64)
83 SPILLS_RETURN_ADDRESS_FROM_LR_TO_REGISTER(
87#elif defined(TARGET_ARCH_ARM)
88 SPILLS_RETURN_ADDRESS_FROM_LR_TO_REGISTER(
__ PushList((1 <<
LR)));
89#elif defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64)
92 __ GenerateUnRelocatedPcRelativeCall();
94#if defined(TARGET_ARCH_ARM64)
95 RESTORES_RETURN_ADDRESS_FROM_REGISTER_TO_LR(
99#elif defined(TARGET_ARCH_ARM)
100 RESTORES_RETURN_ADDRESS_FROM_REGISTER_TO_LR(
__ PopList((1 <<
LR)));
101#elif defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64)
108 void EmitReturn42Function(intptr_t idx) {
109 const Code&
code = *codes[idx];
111#if defined(TARGET_ARCH_X64)
112 __ LoadImmediate(
RAX, 42);
113#elif defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64)
114 __ LoadImmediate(
R0, 42);
115#elif defined(TARGET_ARCH_RISCV32) || defined(TARGET_ARCH_RISCV64)
116 __ LoadImmediate(
A0, 42);
126 compiler::Assembler assembler(
nullptr);
130 memmove(
reinterpret_cast<void*
>(
addr),
131 reinterpret_cast<void*
>(assembler.CodeAddress(0)),
132 assembler.CodeSize());
134 if (FLAG_disassemble) {
140 void AddPcRelativeCallTargetAt(intptr_t
offset,
150 void AddCall(
const Code&
code,
152 const Smi& kind_and_offset) {
154 if (call_targets.IsNull()) {
167 code.set_static_calls_target_table(call_targets);
170 void BuildImageAndRunTest(
174 uword entrypoint = 0;
176 GrowableArray<CodePtr> raw_codes;
177 for (
auto code : codes) {
178 raw_codes.Add(
code->ptr());
181 GrowableArray<ImageWriterCommand>
commands;
182 CodeRelocator::Relocate(thread, &raw_codes, &
commands,
185 uword expected_offset = 0;
189 entrypoint =
image.EntryPoint() + expected_offset;
193 delete[]
commands[
i].insert_trampoline_bytes.buffer;
194 commands[
i].insert_trampoline_bytes.buffer =
nullptr;
199#if defined(TARGET_ARCH_X64)
200 EXPECT_EQ(42,
reinterpret_cast<Fun
>(entrypoint)());
201#elif defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_RISCV32)
202 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT32(Fun, entrypoint));
203#elif defined(TARGET_ARCH_ARM64) || defined(TARGET_ARCH_RISCV64)
204 EXPECT_EQ(42, EXECUTE_TEST_CODE_INT64(Fun, entrypoint));
208 InstructionsPtr BuildImage(GrowableArray<ImageWriterCommand>*
commands) {
210 for (intptr_t
i = 0;
i <
commands->length(); ++
i) {
213 size += (*commands)[
i].insert_trampoline_bytes.buffer_length;
216 size += (*commands)[
i].insert_padding.padding_length;
220 (*
commands)[
i].insert_instruction_of_code.code));
226 size,
false,
false));
228 uword addr = instructions.PayloadStart();
229 for (intptr_t
i = 0;
i <
commands->length(); ++
i) {
232 const auto entry = (*commands)[
i].insert_trampoline_bytes;
233 const auto current_size = entry.buffer_length;
234 ASSERT(
addr + current_size <= instructions.PayloadStart() +
size);
235 memmove(
reinterpret_cast<void*
>(
addr), entry.buffer, current_size);
236 addr += current_size;
240 const auto entry = (*commands)[
i].insert_padding;
241 const auto current_size = entry.padding_length;
242 ASSERT(
addr + current_size <= instructions.PayloadStart() +
size);
243 memset(
reinterpret_cast<void*
>(
addr), 0, current_size);
244 addr += current_size;
248 const auto entry = (*commands)[
i].insert_instruction_of_code;
249 const auto current_size =
251 ASSERT(
addr + current_size <= instructions.PayloadStart() +
size);
252 memmove(
reinterpret_cast<void*
>(
addr),
256 addr += current_size;
262 if (FLAG_write_protect_code) {
264 const auto size = instructions.ptr()->untag()->HeapSize();
270 return instructions.ptr();
274 SafepointWriteRwLocker locker;
275 ForceGrowthSafepointOperationScope safepoint_and_growth_scope;
276 GrowableArray<const Code*> codes;
280 RelocatorTestHelper helper(thread);
281 const intptr_t fmax = FLAG_upper_pc_relative_call_distance;
288 helper.CreateInstructions({
290 fmax - (20 - helper.kOffsetOfCall) - 8,
293 helper.EmitPcRelativeCallFunction(0, 2);
294 helper.EmitReturn42Function(2);
295 helper.BuildImageAndRunTest(
296 [&](
const GrowableArray<ImageWriterCommand>&
commands,
297 uword* entry_point) {
306 *entry_point =
commands[0].expected_offset;
311 RelocatorTestHelper helper(thread);
312 const intptr_t fmax = FLAG_upper_pc_relative_call_distance;
314 helper.CreateInstructions({
316 fmax - (20 - helper.kOffsetOfCall) + 4,
319 helper.EmitPcRelativeCallFunction(0, 2);
320 helper.EmitReturn42Function(2);
321 helper.BuildImageAndRunTest([&](
const GrowableArray<ImageWriterCommand>&
323 uword* entry_point) {
336 *entry_point =
commands[0].expected_offset;
341 RelocatorTestHelper helper(thread);
342 const intptr_t bmax = -FLAG_lower_pc_relative_call_distance;
344 helper.CreateInstructions({
346 bmax - 8 - helper.kOffsetOfCall,
349 helper.EmitReturn42Function(0);
350 helper.EmitPcRelativeCallFunction(2, 0);
351 helper.BuildImageAndRunTest(
352 [&](
const GrowableArray<ImageWriterCommand>&
commands,
353 uword* entry_point) {
362 *entry_point =
commands[2].expected_offset;
367 RelocatorTestHelper helper(thread);
368 const intptr_t bmax = -FLAG_lower_pc_relative_call_distance;
369 const intptr_t fmax = FLAG_upper_pc_relative_call_distance;
371 helper.CreateInstructions({
373 bmax - 8 - helper.kOffsetOfCall + 4,
375 fmax - (20 - helper.kOffsetOfCall) -
380 helper.EmitReturn42Function(0);
381 helper.EmitPcRelativeCallFunction(2, 0);
382 helper.BuildImageAndRunTest([&](
const GrowableArray<ImageWriterCommand>&
384 uword* entry_point) {
402 *entry_point =
commands[2].expected_offset;
407 RelocatorTestHelper helper(thread);
408 const intptr_t bmax = -FLAG_lower_pc_relative_call_distance;
410 helper.CreateInstructions({
412 bmax - 8 - helper.kOffsetOfCall + 4,
416 helper.EmitReturn42Function(0);
417 helper.EmitPcRelativeCallFunction(2, 0);
418 helper.BuildImageAndRunTest(
419 [&](
const GrowableArray<ImageWriterCommand>&
commands,
420 uword* entry_point) {
436 *entry_point =
commands[4].expected_offset;
444 PcRelativeCallPattern pattern(
reinterpret_cast<uword>(&instruction));
455 PcRelativeTailCallPattern pattern(
reinterpret_cast<uword>(&instruction));
static ArrayPtr New(intptr_t len, Heap::Space space=Heap::kNew)
static ArrayPtr Grow(const Array &source, intptr_t new_length, Heap::Space space=Heap::kNew)
static constexpr intptr_t encode(CallKind value)
static void FlushICache(uword start, uword size)
static InstructionsPtr InstructionsOf(const CodePtr code)
@ kSCallTableFunctionTarget
@ kSCallTableCodeOrTypeTarget
@ kSCallTableKindAndOffset
static intptr_t SizeInSnapshot(ObjectPtr object)
uword PayloadStart() const
static void static void PrintErr(const char *format,...) PRINTF_ATTRIBUTE(1
static constexpr int kLengthInBytes
static constexpr int32_t kLowerCallingRange
static constexpr int kLengthInBytes
static constexpr int32_t kUpperCallingRange
static constexpr int32_t kUpperCallingRange
static constexpr int32_t kLowerCallingRange
static constexpr int kLengthInBytes
static SmiPtr New(intptr_t value)
static uword ToAddr(const UntaggedObject *raw_obj)
static constexpr T RoundUp(T x, uintptr_t alignment, uintptr_t offset=0)
static void Protect(void *address, intptr_t size, Protection mode)
static const word kBarePayloadAlignment
Dart_NativeFunction function
sk_sp< const SkImage > image
static void EmitCodeFor(FlowGraphCompiler *compiler, FlowGraph *graph)
UNIT_TEST_CASE(PRIORITY_HEAP_WITH_INDEX__INCREASING)
constexpr uword kBreakInstructionFiller
ISOLATE_UNIT_TEST_CASE(StackAllocatedDestruction)
constexpr intptr_t kWordSize
ArrayOfTuplesView< Code::SCallTableEntry, std::tuple< Smi, Object, Function > > StaticCallsTable
DECLARE_FLAG(bool, show_invisible_frames)
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
@ InsertInstructionOfCode
@ InsertBytesOfTrampoline