OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #ifndef RUNTIME_VM_ASSEMBLER_H_ | 5 #ifndef RUNTIME_VM_ASSEMBLER_H_ |
6 #define RUNTIME_VM_ASSEMBLER_H_ | 6 #define RUNTIME_VM_ASSEMBLER_H_ |
7 | 7 |
8 #include "platform/assert.h" | 8 #include "platform/assert.h" |
9 #include "vm/allocation.h" | 9 #include "vm/allocation.h" |
10 #include "vm/globals.h" | 10 #include "vm/globals.h" |
11 #include "vm/growable_array.h" | 11 #include "vm/growable_array.h" |
12 #include "vm/hash_map.h" | 12 #include "vm/hash_map.h" |
13 #include "vm/object.h" | 13 #include "vm/object.h" |
14 | 14 |
15 namespace dart { | 15 namespace dart { |
16 | 16 |
17 #if defined(TARGET_ARCH_ARM) || \ | 17 #if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64) || \ |
18 defined(TARGET_ARCH_ARM64) || \ | |
19 defined(TARGET_ARCH_MIPS) | 18 defined(TARGET_ARCH_MIPS) |
20 DECLARE_FLAG(bool, use_far_branches); | 19 DECLARE_FLAG(bool, use_far_branches); |
21 #endif | 20 #endif |
22 | 21 |
23 // Forward declarations. | 22 // Forward declarations. |
24 class Assembler; | 23 class Assembler; |
25 class AssemblerFixup; | 24 class AssemblerFixup; |
26 class AssemblerBuffer; | 25 class AssemblerBuffer; |
27 class MemoryRegion; | 26 class MemoryRegion; |
28 | 27 |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
71 }; | 70 }; |
72 | 71 |
73 | 72 |
74 // Assembler buffers are used to emit binary code. They grow on demand. | 73 // Assembler buffers are used to emit binary code. They grow on demand. |
75 class AssemblerBuffer : public ValueObject { | 74 class AssemblerBuffer : public ValueObject { |
76 public: | 75 public: |
77 AssemblerBuffer(); | 76 AssemblerBuffer(); |
78 ~AssemblerBuffer(); | 77 ~AssemblerBuffer(); |
79 | 78 |
80 // Basic support for emitting, loading, and storing. | 79 // Basic support for emitting, loading, and storing. |
81 template<typename T> void Emit(T value) { | 80 template <typename T> |
| 81 void Emit(T value) { |
82 ASSERT(HasEnsuredCapacity()); | 82 ASSERT(HasEnsuredCapacity()); |
83 *reinterpret_cast<T*>(cursor_) = value; | 83 *reinterpret_cast<T*>(cursor_) = value; |
84 cursor_ += sizeof(T); | 84 cursor_ += sizeof(T); |
85 } | 85 } |
86 | 86 |
87 template<typename T> void Remit() { | 87 template <typename T> |
| 88 void Remit() { |
88 ASSERT(Size() >= static_cast<intptr_t>(sizeof(T))); | 89 ASSERT(Size() >= static_cast<intptr_t>(sizeof(T))); |
89 cursor_ -= sizeof(T); | 90 cursor_ -= sizeof(T); |
90 } | 91 } |
91 | 92 |
92 // Return address to code at |position| bytes. | 93 // Return address to code at |position| bytes. |
93 uword Address(intptr_t position) { | 94 uword Address(intptr_t position) { return contents_ + position; } |
94 return contents_ + position; | |
95 } | |
96 | 95 |
97 template<typename T> T Load(intptr_t position) { | 96 template <typename T> |
| 97 T Load(intptr_t position) { |
98 ASSERT(position >= 0 && | 98 ASSERT(position >= 0 && |
99 position <= (Size() - static_cast<intptr_t>(sizeof(T)))); | 99 position <= (Size() - static_cast<intptr_t>(sizeof(T)))); |
100 return *reinterpret_cast<T*>(contents_ + position); | 100 return *reinterpret_cast<T*>(contents_ + position); |
101 } | 101 } |
102 | 102 |
103 template<typename T> void Store(intptr_t position, T value) { | 103 template <typename T> |
| 104 void Store(intptr_t position, T value) { |
104 ASSERT(position >= 0 && | 105 ASSERT(position >= 0 && |
105 position <= (Size() - static_cast<intptr_t>(sizeof(T)))); | 106 position <= (Size() - static_cast<intptr_t>(sizeof(T)))); |
106 *reinterpret_cast<T*>(contents_ + position) = value; | 107 *reinterpret_cast<T*>(contents_ + position) = value; |
107 } | 108 } |
108 | 109 |
109 const ZoneGrowableArray<intptr_t>& pointer_offsets() const { | 110 const ZoneGrowableArray<intptr_t>& pointer_offsets() const { |
110 #if defined(DEBUG) | 111 #if defined(DEBUG) |
111 ASSERT(fixups_processed_); | 112 ASSERT(fixups_processed_); |
112 #endif | 113 #endif |
113 return *pointer_offsets_; | 114 return *pointer_offsets_; |
(...skipping 14 matching lines...) Expand all Loading... |
128 intptr_t CountPointerOffsets() const; | 129 intptr_t CountPointerOffsets() const; |
129 | 130 |
130 // Get the size of the emitted code. | 131 // Get the size of the emitted code. |
131 intptr_t Size() const { return cursor_ - contents_; } | 132 intptr_t Size() const { return cursor_ - contents_; } |
132 uword contents() const { return contents_; } | 133 uword contents() const { return contents_; } |
133 | 134 |
134 // Copy the assembled instructions into the specified memory block | 135 // Copy the assembled instructions into the specified memory block |
135 // and apply all fixups. | 136 // and apply all fixups. |
136 void FinalizeInstructions(const MemoryRegion& region); | 137 void FinalizeInstructions(const MemoryRegion& region); |
137 | 138 |
138 // To emit an instruction to the assembler buffer, the EnsureCapacity helper | 139 // To emit an instruction to the assembler buffer, the EnsureCapacity helper |
139 // must be used to guarantee that the underlying data area is big enough to | 140 // must be used to guarantee that the underlying data area is big enough to |
140 // hold the emitted instruction. Usage: | 141 // hold the emitted instruction. Usage: |
141 // | 142 // |
142 // AssemblerBuffer buffer; | 143 // AssemblerBuffer buffer; |
143 // AssemblerBuffer::EnsureCapacity ensured(&buffer); | 144 // AssemblerBuffer::EnsureCapacity ensured(&buffer); |
144 // ... emit bytes for single instruction ... | 145 // ... emit bytes for single instruction ... |
145 | 146 |
146 #if defined(DEBUG) | 147 #if defined(DEBUG) |
147 class EnsureCapacity : public ValueObject { | 148 class EnsureCapacity : public ValueObject { |
148 public: | 149 public: |
149 explicit EnsureCapacity(AssemblerBuffer* buffer); | 150 explicit EnsureCapacity(AssemblerBuffer* buffer); |
150 ~EnsureCapacity(); | 151 ~EnsureCapacity(); |
151 | 152 |
152 private: | 153 private: |
153 AssemblerBuffer* buffer_; | 154 AssemblerBuffer* buffer_; |
154 intptr_t gap_; | 155 intptr_t gap_; |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
208 return data + capacity - kMinimumGap; | 209 return data + capacity - kMinimumGap; |
209 } | 210 } |
210 | 211 |
211 void ExtendCapacity(); | 212 void ExtendCapacity(); |
212 | 213 |
213 friend class AssemblerFixup; | 214 friend class AssemblerFixup; |
214 }; | 215 }; |
215 | 216 |
216 | 217 |
217 struct ObjectPoolWrapperEntry { | 218 struct ObjectPoolWrapperEntry { |
218 ObjectPoolWrapperEntry() | 219 ObjectPoolWrapperEntry() : raw_value_(), type_(), equivalence_() {} |
219 : raw_value_(), type_(), equivalence_() { } | |
220 explicit ObjectPoolWrapperEntry(const Object* obj) | 220 explicit ObjectPoolWrapperEntry(const Object* obj) |
221 : obj_(obj), type_(ObjectPool::kTaggedObject), equivalence_(obj) { } | 221 : obj_(obj), type_(ObjectPool::kTaggedObject), equivalence_(obj) {} |
222 explicit ObjectPoolWrapperEntry(const Object* obj, const Object* eqv) | 222 explicit ObjectPoolWrapperEntry(const Object* obj, const Object* eqv) |
223 : obj_(obj), type_(ObjectPool::kTaggedObject), equivalence_(eqv) { } | 223 : obj_(obj), type_(ObjectPool::kTaggedObject), equivalence_(eqv) {} |
224 ObjectPoolWrapperEntry(uword value, ObjectPool::EntryType info) | 224 ObjectPoolWrapperEntry(uword value, ObjectPool::EntryType info) |
225 : raw_value_(value), type_(info), equivalence_() { } | 225 : raw_value_(value), type_(info), equivalence_() {} |
226 | 226 |
227 union { | 227 union { |
228 const Object* obj_; | 228 const Object* obj_; |
229 uword raw_value_; | 229 uword raw_value_; |
230 }; | 230 }; |
231 ObjectPool::EntryType type_; | 231 ObjectPool::EntryType type_; |
232 const Object* equivalence_; | 232 const Object* equivalence_; |
233 }; | 233 }; |
234 | 234 |
235 | 235 |
236 // Pair type parameter for DirectChainedHashMap used for the constant pool. | 236 // Pair type parameter for DirectChainedHashMap used for the constant pool. |
237 class ObjIndexPair { | 237 class ObjIndexPair { |
238 public: | 238 public: |
239 // Typedefs needed for the DirectChainedHashMap template. | 239 // Typedefs needed for the DirectChainedHashMap template. |
240 typedef ObjectPoolWrapperEntry Key; | 240 typedef ObjectPoolWrapperEntry Key; |
241 typedef intptr_t Value; | 241 typedef intptr_t Value; |
242 typedef ObjIndexPair Pair; | 242 typedef ObjIndexPair Pair; |
243 | 243 |
244 static const intptr_t kNoIndex = -1; | 244 static const intptr_t kNoIndex = -1; |
245 | 245 |
246 ObjIndexPair() : key_(static_cast<uword>(NULL), ObjectPool::kTaggedObject), | 246 ObjIndexPair() |
247 value_(kNoIndex) { } | 247 : key_(static_cast<uword>(NULL), ObjectPool::kTaggedObject), |
| 248 value_(kNoIndex) {} |
248 | 249 |
249 ObjIndexPair(Key key, Value value) : value_(value) { | 250 ObjIndexPair(Key key, Value value) : value_(value) { |
250 key_.type_ = key.type_; | 251 key_.type_ = key.type_; |
251 if (key.type_ == ObjectPool::kTaggedObject) { | 252 if (key.type_ == ObjectPool::kTaggedObject) { |
252 key_.obj_ = key.obj_; | 253 key_.obj_ = key.obj_; |
253 key_.equivalence_ = key.equivalence_; | 254 key_.equivalence_ = key.equivalence_; |
254 } else { | 255 } else { |
255 key_.raw_value_ = key.raw_value_; | 256 key_.raw_value_ = key.raw_value_; |
256 } | 257 } |
257 } | 258 } |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
291 | 292 |
292 | 293 |
293 enum Patchability { | 294 enum Patchability { |
294 kPatchable, | 295 kPatchable, |
295 kNotPatchable, | 296 kNotPatchable, |
296 }; | 297 }; |
297 | 298 |
298 | 299 |
299 class ObjectPoolWrapper : public ValueObject { | 300 class ObjectPoolWrapper : public ValueObject { |
300 public: | 301 public: |
301 intptr_t AddObject(const Object& obj, | 302 intptr_t AddObject(const Object& obj, Patchability patchable = kNotPatchable); |
302 Patchability patchable = kNotPatchable); | |
303 intptr_t AddImmediate(uword imm); | 303 intptr_t AddImmediate(uword imm); |
304 | 304 |
305 intptr_t FindObject(const Object& obj, | 305 intptr_t FindObject(const Object& obj, |
306 Patchability patchable = kNotPatchable); | 306 Patchability patchable = kNotPatchable); |
307 intptr_t FindObject(const Object& obj, | 307 intptr_t FindObject(const Object& obj, const Object& equivalence); |
308 const Object& equivalence); | |
309 intptr_t FindImmediate(uword imm); | 308 intptr_t FindImmediate(uword imm); |
310 intptr_t FindNativeEntry(const ExternalLabel* label, | 309 intptr_t FindNativeEntry(const ExternalLabel* label, Patchability patchable); |
311 Patchability patchable); | |
312 | 310 |
313 RawObjectPool* MakeObjectPool(); | 311 RawObjectPool* MakeObjectPool(); |
314 | 312 |
315 private: | 313 private: |
316 intptr_t AddObject(ObjectPoolWrapperEntry entry, Patchability patchable); | 314 intptr_t AddObject(ObjectPoolWrapperEntry entry, Patchability patchable); |
317 intptr_t FindObject(ObjectPoolWrapperEntry entry, Patchability patchable); | 315 intptr_t FindObject(ObjectPoolWrapperEntry entry, Patchability patchable); |
318 | 316 |
319 // Objects and jump targets. | 317 // Objects and jump targets. |
320 GrowableArray<ObjectPoolWrapperEntry> object_pool_; | 318 GrowableArray<ObjectPoolWrapperEntry> object_pool_; |
321 | 319 |
322 // Hashmap for fast lookup in object pool. | 320 // Hashmap for fast lookup in object pool. |
323 DirectChainedHashMap<ObjIndexPair> object_pool_index_table_; | 321 DirectChainedHashMap<ObjIndexPair> object_pool_index_table_; |
324 }; | 322 }; |
325 | 323 |
326 | 324 |
327 enum RestorePP { | 325 enum RestorePP { kRestoreCallerPP, kKeepCalleePP }; |
328 kRestoreCallerPP, | |
329 kKeepCalleePP | |
330 }; | |
331 | 326 |
332 } // namespace dart | 327 } // namespace dart |
333 | 328 |
334 | 329 |
335 #if defined(TARGET_ARCH_IA32) | 330 #if defined(TARGET_ARCH_IA32) |
336 #include "vm/assembler_ia32.h" | 331 #include "vm/assembler_ia32.h" |
337 #elif defined(TARGET_ARCH_X64) | 332 #elif defined(TARGET_ARCH_X64) |
338 #include "vm/assembler_x64.h" | 333 #include "vm/assembler_x64.h" |
339 #elif defined(TARGET_ARCH_ARM) | 334 #elif defined(TARGET_ARCH_ARM) |
340 #include "vm/assembler_arm.h" | 335 #include "vm/assembler_arm.h" |
341 #elif defined(TARGET_ARCH_ARM64) | 336 #elif defined(TARGET_ARCH_ARM64) |
342 #include "vm/assembler_arm64.h" | 337 #include "vm/assembler_arm64.h" |
343 #elif defined(TARGET_ARCH_MIPS) | 338 #elif defined(TARGET_ARCH_MIPS) |
344 #include "vm/assembler_mips.h" | 339 #include "vm/assembler_mips.h" |
345 #elif defined(TARGET_ARCH_DBC) | 340 #elif defined(TARGET_ARCH_DBC) |
346 #include "vm/assembler_dbc.h" | 341 #include "vm/assembler_dbc.h" |
347 #else | 342 #else |
348 #error Unknown architecture. | 343 #error Unknown architecture. |
349 #endif | 344 #endif |
350 | 345 |
351 #endif // RUNTIME_VM_ASSEMBLER_H_ | 346 #endif // RUNTIME_VM_ASSEMBLER_H_ |
OLD | NEW |