Flutter Engine
The Flutter Engine
assembler_test.cc
Go to the documentation of this file.
1// Copyright (c) 2013, 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
7#include "vm/globals.h"
8#include "vm/hash.h"
9#include "vm/os.h"
10#include "vm/random.h"
11#include "vm/simulator.h"
12#include "vm/unit_test.h"
13#include "vm/virtual_memory.h"
14
15namespace dart {
16
17namespace compiler {
18ASSEMBLER_TEST_EXTERN(StoreIntoObject);
19} // namespace compiler
20
21ASSEMBLER_TEST_RUN(StoreIntoObject, test) {
22#define TEST_CODE(value, growable_array, thread) \
23 test->Invoke<void, ObjectPtr, ObjectPtr, Thread*>(value, growable_array, \
24 thread)
25
26 const Array& old_array = Array::Handle(Array::New(3, Heap::kOld));
27 const Array& new_array = Array::Handle(Array::New(3, Heap::kNew));
32 Smi& smi = Smi::Handle();
33 Thread* thread = Thread::Current();
34
35 EXPECT(old_array.ptr() == grow_old_array.data());
36 EXPECT(!thread->StoreBufferContains(grow_old_array.ptr()));
37 EXPECT(old_array.ptr() == grow_new_array.data());
38 EXPECT(!thread->StoreBufferContains(grow_new_array.ptr()));
39
40 // Store Smis into the old object.
41 for (int i = -128; i < 128; i++) {
42 smi = Smi::New(i);
43 TEST_CODE(smi.ptr(), grow_old_array.ptr(), thread);
44 EXPECT(static_cast<CompressedObjectPtr>(smi.ptr()) ==
45 static_cast<CompressedObjectPtr>(grow_old_array.data()));
46 EXPECT(!thread->StoreBufferContains(grow_old_array.ptr()));
47 }
48
49 // Store an old object into the old object.
50 TEST_CODE(old_array.ptr(), grow_old_array.ptr(), thread);
51 EXPECT(old_array.ptr() == grow_old_array.data());
52 EXPECT(!thread->StoreBufferContains(grow_old_array.ptr()));
53
54 // Store a new object into the old object.
55 TEST_CODE(new_array.ptr(), grow_old_array.ptr(), thread);
56 EXPECT(new_array.ptr() == grow_old_array.data());
57 EXPECT(thread->StoreBufferContains(grow_old_array.ptr()));
58
59 // Store a new object into the new object.
60 TEST_CODE(new_array.ptr(), grow_new_array.ptr(), thread);
61 EXPECT(new_array.ptr() == grow_new_array.data());
62 EXPECT(!thread->StoreBufferContains(grow_new_array.ptr()));
63
64 // Store an old object into the new object.
65 TEST_CODE(old_array.ptr(), grow_new_array.ptr(), thread);
66 EXPECT(old_array.ptr() == grow_new_array.data());
67 EXPECT(!thread->StoreBufferContains(grow_new_array.ptr()));
68}
69
70namespace compiler {
71#define __ assembler->
72
73ASSEMBLER_TEST_GENERATE(InstantiateTypeArgumentsHashKeys, assembler) {
74#if defined(TARGET_ARCH_IA32)
75 const Register kArg1Reg = EAX;
76 const Register kArg2Reg = ECX;
79#else
82#endif
86 __ Ret();
87}
88
89#undef __
90} // namespace compiler
91
92ASSEMBLER_TEST_RUN(InstantiateTypeArgumentsHashKeys, test) {
93 typedef uint32_t (*HashKeysCode)(uword hash, uword other) DART_UNUSED;
94
95 auto hash_test = [&](const Expect& expect, uword hash1, uword hash2) {
96 const uint32_t expected = FinalizeHash(CombineHashes(hash1, hash2));
97 const uint32_t got = EXECUTE_TEST_CODE_UWORD_UWORD_UINT32(
98 HashKeysCode, test->entry(), hash1, hash2);
99 if (got == expected) return;
100 TextBuffer buffer(128);
101 buffer.Printf("For hash1 = %" Pu " and hash2 = %" Pu
102 ": expected result %u, got result %u",
103 hash1, hash2, expected, got);
104 expect.Fail("%s", buffer.buffer());
105 };
106
107#define HASH_TEST(hash1, hash2) \
108 hash_test(Expect(__FILE__, __LINE__), hash1, hash2)
109
110 const intptr_t kNumRandomTests = 500;
111 Random random;
112
113 // First, fixed and random 32 bit tests for all architectures.
114 HASH_TEST(1, 1);
115 HASH_TEST(10, 20);
116 HASH_TEST(20, 10);
119
120 for (intptr_t i = 0; i < kNumRandomTests; i++) {
121 const uword hash1 = random.NextUInt32();
122 const uword hash2 = random.NextUInt32();
123 HASH_TEST(hash1, hash2);
124 }
125
126#if defined(TARGET_ARCH_IS_64_BIT)
127 // Now 64-bit tests on 64-bit architectures.
130
131 for (intptr_t i = 0; i < kNumRandomTests; i++) {
132 const uword hash1 = random.NextUInt64();
133 const uword hash2 = random.NextUInt64();
134 HASH_TEST(hash1, hash2);
135 }
136#endif
137#undef HASH_TEST
138}
139
140#define __ assembler->
141
142#if defined(TARGET_ARCH_IA32)
143const Register kArg1Reg = EAX;
144const Register kArg2Reg = ECX;
145#else
148#endif
149
150#define LOAD_FROM_BOX_TEST(SIZE, TYPE, VALUE, SAME_REGISTER) \
151 ASSEMBLER_TEST_GENERATE(Load##SIZE##FromBoxOrSmi##VALUE##SAME_REGISTER, \
152 assembler) { \
153 const bool same_register = SAME_REGISTER; \
154 \
155 const Register src = kArg1Reg; \
156 const Register dst = same_register ? src : kArg2Reg; \
157 const TYPE value = VALUE; \
158 \
159 EnterTestFrame(assembler); \
160 \
161 __ LoadObject(src, Integer::ZoneHandle(Integer::New(value, Heap::kOld))); \
162 __ Load##SIZE##FromBoxOrSmi(dst, src); \
163 __ MoveRegister(CallingConventions::kReturnReg, dst); \
164 \
165 LeaveTestFrame(assembler); \
166 \
167 __ Ret(); \
168 } \
169 \
170 ASSEMBLER_TEST_RUN(Load##SIZE##FromBoxOrSmi##VALUE##SAME_REGISTER, test) { \
171 const int64_t res = test->InvokeWithCodeAndThread<int64_t>(); \
172 EXPECT_EQ(static_cast<TYPE>(VALUE), static_cast<TYPE>(res)); \
173 }
174
175LOAD_FROM_BOX_TEST(Word, intptr_t, 0, true)
176LOAD_FROM_BOX_TEST(Word, intptr_t, 0, false)
177LOAD_FROM_BOX_TEST(Word, intptr_t, 1, true)
178LOAD_FROM_BOX_TEST(Word, intptr_t, 1, false)
179#if defined(TARGET_ARCH_IS_32_BIT)
180LOAD_FROM_BOX_TEST(Word, intptr_t, 0x7FFFFFFF, true)
181LOAD_FROM_BOX_TEST(Word, intptr_t, 0x7FFFFFFF, false)
182LOAD_FROM_BOX_TEST(Word, intptr_t, 0x80000000, true)
183LOAD_FROM_BOX_TEST(Word, intptr_t, 0x80000000, false)
184LOAD_FROM_BOX_TEST(Word, intptr_t, 0xFFFFFFFF, true)
185LOAD_FROM_BOX_TEST(Word, intptr_t, 0xFFFFFFFF, false)
186#else
187LOAD_FROM_BOX_TEST(Word, intptr_t, 0x7FFFFFFFFFFFFFFF, true)
188LOAD_FROM_BOX_TEST(Word, intptr_t, 0x7FFFFFFFFFFFFFFF, false)
189LOAD_FROM_BOX_TEST(Word, intptr_t, 0x8000000000000000, true)
190LOAD_FROM_BOX_TEST(Word, intptr_t, 0x8000000000000000, false)
191LOAD_FROM_BOX_TEST(Word, intptr_t, 0xFFFFFFFFFFFFFFFF, true)
192LOAD_FROM_BOX_TEST(Word, intptr_t, 0xFFFFFFFFFFFFFFFF, false)
193#endif
194
195LOAD_FROM_BOX_TEST(Int32, int32_t, 0, true)
196LOAD_FROM_BOX_TEST(Int32, int32_t, 0, false)
197LOAD_FROM_BOX_TEST(Int32, int32_t, 1, true)
198LOAD_FROM_BOX_TEST(Int32, int32_t, 1, false)
199LOAD_FROM_BOX_TEST(Int32, int32_t, 0x7FFFFFFF, true)
200LOAD_FROM_BOX_TEST(Int32, int32_t, 0x7FFFFFFF, false)
201LOAD_FROM_BOX_TEST(Int32, int32_t, 0x80000000, true)
202LOAD_FROM_BOX_TEST(Int32, int32_t, 0x80000000, false)
203LOAD_FROM_BOX_TEST(Int32, int32_t, 0xFFFFFFFF, true)
204LOAD_FROM_BOX_TEST(Int32, int32_t, 0xFFFFFFFF, false)
205
206#if !defined(TARGET_ARCH_IS_32_BIT)
207LOAD_FROM_BOX_TEST(Int64, int64_t, 0, true)
208LOAD_FROM_BOX_TEST(Int64, int64_t, 0, false)
209LOAD_FROM_BOX_TEST(Int64, int64_t, 1, true)
210LOAD_FROM_BOX_TEST(Int64, int64_t, 1, false)
211LOAD_FROM_BOX_TEST(Int64, int64_t, 0x7FFFFFFFFFFFFFFF, true)
212LOAD_FROM_BOX_TEST(Int64, int64_t, 0x7FFFFFFFFFFFFFFF, false)
213LOAD_FROM_BOX_TEST(Int64, int64_t, 0x8000000000000000, true)
214LOAD_FROM_BOX_TEST(Int64, int64_t, 0x8000000000000000, false)
215LOAD_FROM_BOX_TEST(Int64, int64_t, 0xFFFFFFFFFFFFFFFF, true)
216LOAD_FROM_BOX_TEST(Int64, int64_t, 0xFFFFFFFFFFFFFFFF, false)
217#endif
218
219#if defined(TARGET_ARCH_ARM)
220ISOLATE_UNIT_TEST_CASE(Assembler_Regress54621) {
221 auto zone = thread->zone();
222 const classid_t cid = kTypedDataInt32ArrayCid;
223 const intptr_t index_scale = 1;
224 const intptr_t kMaxAllowedOffsetForExternal = (2 << 11) - 1;
225 auto& smi = Smi::Handle(zone, Smi::New(kMaxAllowedOffsetForExternal));
226 bool needs_base;
228 smi, /*is_load=*/true,
229 /*is_external=*/true, cid, index_scale, &needs_base));
230 EXPECT(!needs_base);
232 smi, /*is_load=*/true,
233 /*is_external=*/false, cid, index_scale, &needs_base));
234 EXPECT(needs_base);
235 // Double-checking we're on a boundary of what's allowed.
236 smi = Smi::New(kMaxAllowedOffsetForExternal + 1);
238 smi, /*is_load=*/true,
239 /*is_external=*/false, cid, index_scale));
241 smi, /*is_load=*/true,
242 /*is_external=*/true, cid, index_scale));
243}
244#endif
245
246} // namespace dart
static uint32_t hash(const SkShaderBase::GradientInfo &v)
#define EXPECT(type, expectedAlignment, expectedSize)
#define __
#define LOAD_FROM_BOX_TEST(SIZE, TYPE, VALUE, SAME_REGISTER)
#define HASH_TEST(hash1, hash2)
#define TEST_CODE(value, growable_array, thread)
static ArrayPtr New(intptr_t len, Heap::Space space=Heap::kNew)
Definition: object.h:10959
static const Register ArgumentRegisters[]
static constexpr Register kReturnReg
void Fail(const char *format,...) const PRINTF_ATTRIBUTE(2
static GrowableObjectArrayPtr New(Heap::Space space=Heap::kNew)
Definition: object.h:11144
ArrayPtr data() const
Definition: object.h:11082
@ kNew
Definition: heap.h:38
@ kOld
Definition: heap.h:39
ObjectPtr ptr() const
Definition: object.h:332
static Object & Handle()
Definition: object.h:407
uint64_t NextUInt64()
Definition: random.h:26
uint32_t NextUInt32()
Definition: random.cc:73
static SmiPtr New(intptr_t value)
Definition: object.h:10006
static Thread * Current()
Definition: thread.h:362
static bool AddressCanHoldConstantIndex(const Object &constant, bool is_load, bool is_external, intptr_t cid, intptr_t index_scale, bool *needs_base=nullptr)
static constexpr intptr_t kWordSize
Definition: runtime_api.h:274
ASSEMBLER_TEST_EXTERN(StoreIntoObject)
ASSEMBLER_TEST_GENERATE(InstantiateTypeArgumentsHashKeys, assembler)
Definition: dart_vm.cc:33
uint32_t CombineHashes(uint32_t hash, uint32_t other_hash)
Definition: hash.h:12
int32_t classid_t
Definition: globals.h:524
constexpr uint64_t kMaxUint64
Definition: globals.h:487
constexpr uint32_t kMaxUint32
Definition: globals.h:484
uintptr_t uword
Definition: globals.h:501
ISOLATE_UNIT_TEST_CASE(StackAllocatedDestruction)
const Register kArg2Reg
const intptr_t cid
ASSEMBLER_TEST_RUN(StoreIntoObject, test)
uint32_t FinalizeHash(uint32_t hash, intptr_t hashbits=kBitsPerInt32)
Definition: hash.h:20
const Register kArg1Reg
constexpr uint16_t kMaxUint16
Definition: globals.h:481
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
Definition: switches.h:126
#define Pu
Definition: globals.h:409
#define DART_UNUSED
Definition: globals.h:269