| 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 |