| 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 #include "vm/assembler.h" | 5 #include "vm/assembler.h" |
| 6 | 6 |
| 7 #include "platform/utils.h" | 7 #include "platform/utils.h" |
| 8 #include "vm/cpu.h" | 8 #include "vm/cpu.h" |
| 9 #include "vm/heap.h" | 9 #include "vm/heap.h" |
| 10 #include "vm/memory_region.h" | 10 #include "vm/memory_region.h" |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 57 // Unmark the buffer, so we cannot emit after this. | 57 // Unmark the buffer, so we cannot emit after this. |
| 58 buffer_->has_ensured_capacity_ = false; | 58 buffer_->has_ensured_capacity_ = false; |
| 59 // Make sure the generated instruction doesn't take up more | 59 // Make sure the generated instruction doesn't take up more |
| 60 // space than the minimum gap. | 60 // space than the minimum gap. |
| 61 intptr_t delta = gap_ - ComputeGap(); | 61 intptr_t delta = gap_ - ComputeGap(); |
| 62 ASSERT(delta <= kMinimumGap); | 62 ASSERT(delta <= kMinimumGap); |
| 63 } | 63 } |
| 64 #endif | 64 #endif |
| 65 | 65 |
| 66 | 66 |
| 67 AssemblerBuffer::AssemblerBuffer() | 67 AssemblerBuffer::AssemblerBuffer(Assembler* assembler) |
| 68 : pointer_offsets_(new ZoneGrowableArray<intptr_t>(16)) { | 68 : assembler_(assembler), |
| 69 pointer_offsets_(new ZoneGrowableArray<intptr_t>(16)) { |
| 69 static const intptr_t kInitialBufferCapacity = 4 * KB; | 70 static const intptr_t kInitialBufferCapacity = 4 * KB; |
| 70 contents_ = NewContents(kInitialBufferCapacity); | 71 contents_ = NewContents(kInitialBufferCapacity); |
| 71 cursor_ = contents_; | 72 cursor_ = contents_; |
| 72 limit_ = ComputeLimit(contents_, kInitialBufferCapacity); | 73 limit_ = ComputeLimit(contents_, kInitialBufferCapacity); |
| 73 fixup_ = NULL; | 74 fixup_ = NULL; |
| 74 #if defined(DEBUG) | 75 #if defined(DEBUG) |
| 75 has_ensured_capacity_ = false; | 76 has_ensured_capacity_ = false; |
| 76 fixups_processed_ = false; | 77 fixups_processed_ = false; |
| 77 #endif | 78 #endif |
| 78 | 79 |
| 79 // Verify internal state. | 80 // Verify internal state. |
| 80 ASSERT(Capacity() == kInitialBufferCapacity); | 81 ASSERT(Capacity() == kInitialBufferCapacity); |
| 81 ASSERT(Size() == 0); | 82 ASSERT(Size() == 0); |
| 82 } | 83 } |
| 83 | 84 |
| 84 | 85 |
| 85 AssemblerBuffer::~AssemblerBuffer() { | 86 AssemblerBuffer::~AssemblerBuffer() { |
| 86 } | 87 } |
| 87 | 88 |
| 88 | 89 |
| 89 void AssemblerBuffer::ProcessFixups(const MemoryRegion& region) { | 90 void AssemblerBuffer::ProcessFixups(const MemoryRegion& region) { |
| 90 AssemblerFixup* fixup = fixup_; | 91 AssemblerFixup* fixup = fixup_; |
| 91 while (fixup != NULL) { | 92 while (fixup != NULL) { |
| 92 fixup->Process(region, fixup->position()); | 93 fixup->Process(region, fixup->position(), assembler_); |
| 93 fixup = fixup->previous(); | 94 fixup = fixup->previous(); |
| 94 } | 95 } |
| 95 } | 96 } |
| 96 | 97 |
| 97 | 98 |
| 98 void AssemblerBuffer::FinalizeInstructions(const MemoryRegion& instructions) { | 99 void AssemblerBuffer::FinalizeInstructions(const MemoryRegion& instructions) { |
| 99 // Copy the instructions from the buffer. | 100 // Copy the instructions from the buffer. |
| 100 MemoryRegion from(reinterpret_cast<void*>(contents()), Size()); | 101 MemoryRegion from(reinterpret_cast<void*>(contents()), Size()); |
| 101 instructions.CopyFrom(0, from); | 102 instructions.CopyFrom(0, from); |
| 102 | 103 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 137 } | 138 } |
| 138 | 139 |
| 139 | 140 |
| 140 class PatchCodeWithHandle : public AssemblerFixup { | 141 class PatchCodeWithHandle : public AssemblerFixup { |
| 141 public: | 142 public: |
| 142 PatchCodeWithHandle(ZoneGrowableArray<intptr_t>* pointer_offsets, | 143 PatchCodeWithHandle(ZoneGrowableArray<intptr_t>* pointer_offsets, |
| 143 const Object& object) | 144 const Object& object) |
| 144 : pointer_offsets_(pointer_offsets), object_(object) { | 145 : pointer_offsets_(pointer_offsets), object_(object) { |
| 145 } | 146 } |
| 146 | 147 |
| 147 void Process(const MemoryRegion& region, intptr_t position) { | 148 void Process(const MemoryRegion& region, |
| 149 intptr_t position, |
| 150 Assembler* assembler) { |
| 148 // Patch the handle into the code. Once the instructions are installed into | 151 // Patch the handle into the code. Once the instructions are installed into |
| 149 // a raw code object and the pointer offsets are setup, the handle is | 152 // a raw code object and the pointer offsets are setup, the handle is |
| 150 // resolved. | 153 // resolved. |
| 151 region.Store<const Object*>(position, &object_); | 154 region.Store<const Object*>(position, &object_); |
| 152 pointer_offsets_->Add(position); | 155 pointer_offsets_->Add(position); |
| 153 } | 156 } |
| 154 | 157 |
| 155 virtual bool IsPointerOffset() const { return true; } | 158 virtual bool IsPointerOffset() const { return true; } |
| 156 | 159 |
| 157 private: | 160 private: |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 235 | 238 |
| 236 for (intptr_t i = 0; i < comments_.length(); i++) { | 239 for (intptr_t i = 0; i < comments_.length(); i++) { |
| 237 comments.SetPCOffsetAt(i, comments_[i]->pc_offset()); | 240 comments.SetPCOffsetAt(i, comments_[i]->pc_offset()); |
| 238 comments.SetCommentAt(i, comments_[i]->comment()); | 241 comments.SetCommentAt(i, comments_[i]->comment()); |
| 239 } | 242 } |
| 240 | 243 |
| 241 return comments; | 244 return comments; |
| 242 } | 245 } |
| 243 | 246 |
| 244 | 247 |
| 245 intptr_t ObjectPool::AddObject(const Object& obj, Patchability patchable) { | 248 intptr_t ObjectPoolHelper::AddObject(const Object& obj) { |
| 246 // The object pool cannot be used in the vm isolate. | 249 // The object pool cannot be used in the vm isolate. |
| 247 ASSERT(Isolate::Current() != Dart::vm_isolate()); | 250 ASSERT(Isolate::Current() != Dart::vm_isolate()); |
| 248 if (object_pool_.IsNull()) { | 251 ASSERT(obj.IsNotTemporaryScopedHandle()); |
| 249 object_pool_ = GrowableObjectArray::New(Heap::kOld); | 252 tagged_entries_.Add(&obj); |
| 250 } | 253 // The object isn't patchable. Record the index for fast lookup. |
| 251 object_pool_.Add(obj, Heap::kOld); | 254 intptr_t index = Assembler::kNumFixedEntries + tagged_entries_.length() - 1; |
| 252 patchable_pool_entries_.Add(patchable); | 255 object_index_table_.Insert(ObjIndexPair(&obj, index)); |
| 253 if (patchable == kNotPatchable) { | 256 return index; |
| 254 // The object isn't patchable. Record the index for fast lookup. | |
| 255 object_pool_index_table_.Insert( | |
| 256 ObjIndexPair(&obj, object_pool_.Length() - 1)); | |
| 257 } | |
| 258 return object_pool_.Length() - 1; | |
| 259 } | 257 } |
| 260 | 258 |
| 261 | 259 |
| 262 intptr_t ObjectPool::AddExternalLabel(const ExternalLabel* label, | 260 intptr_t ObjectPoolHelper::AddFixedObject(const Object& obj) { |
| 263 Patchability patchable) { | 261 // The object pool cannot be used in the vm isolate. |
| 264 ASSERT(Isolate::Current() != Dart::vm_isolate()); | 262 ASSERT(Isolate::Current() != Dart::vm_isolate()); |
| 265 const uword address = label->address(); | 263 ASSERT(obj.IsNotTemporaryScopedHandle()); |
| 266 ASSERT(Utils::IsAligned(address, 4)); | 264 fixed_entries_.Add(ObjectPool::Entry(&obj)); |
| 267 // The address is stored in the object array as a RawSmi. | 265 // The object isn't patchable. Record the index for fast lookup. |
| 268 const Smi& smi = Smi::Handle(reinterpret_cast<RawSmi*>(address)); | 266 object_index_table_.Insert( |
| 269 return AddObject(smi, patchable); | 267 ObjIndexPair(&obj, fixed_entries_.length() - 1)); |
| 268 return fixed_entries_.length() - 1; |
| 270 } | 269 } |
| 271 | 270 |
| 272 | 271 |
| 273 intptr_t ObjectPool::FindObject(const Object& obj, Patchability patchable) { | 272 intptr_t ObjectPoolHelper::AddFixedExternalLabel(const ExternalLabel* label) { |
| 273 ASSERT(Isolate::Current() != Dart::vm_isolate()); |
| 274 uword value = label->address(); |
| 275 fixed_entries_.Add(ObjectPool::Entry(value)); |
| 276 ASSERT(fixed_entries_.length() <= Assembler::kNumFixedEntries); |
| 277 untagged_index_table_.Insert( |
| 278 UntaggedIndexPair(value, fixed_entries_.length() - 1)); |
| 279 return fixed_entries_.length() - 1; |
| 280 } |
| 281 |
| 282 |
| 283 intptr_t ObjectPoolHelper::AddUntagged(uword value, Patchability patchable) { |
| 284 ASSERT(Isolate::Current() != Dart::vm_isolate()); |
| 285 untagged_entries_.Add(value); |
| 286 intptr_t index = |
| 287 Assembler::kNumFixedEntries + untagged_entries_.length() - 1; |
| 288 if (patchable == kNotPatchable) { |
| 289 // The entry isn't patchable. Record the index for fast lookup. |
| 290 untagged_index_table_.Insert(UntaggedIndexPair(value, index)); |
| 291 } |
| 292 return index; |
| 293 } |
| 294 |
| 295 |
| 296 intptr_t ObjectPoolHelper::AddExternalLabel(const ExternalLabel* label, |
| 297 Patchability patchable) { |
| 298 return AddUntagged(label->address(), patchable); |
| 299 } |
| 300 |
| 301 |
| 302 intptr_t ObjectPoolHelper::AddImmediate(uword imm) { |
| 303 return AddUntagged(imm, kNotPatchable); |
| 304 } |
| 305 |
| 306 |
| 307 intptr_t ObjectPoolHelper::FindObject(const Object& obj) { |
| 274 // The object pool cannot be used in the vm isolate. | 308 // The object pool cannot be used in the vm isolate. |
| 275 ASSERT(Isolate::Current() != Dart::vm_isolate()); | 309 ASSERT(Isolate::Current() != Dart::vm_isolate()); |
| 310 // Check if we've already got it in the object pool. |
| 311 intptr_t idx = object_index_table_.Lookup(&obj); |
| 312 return (idx != ObjIndexPair::kNoIndex) ? idx : AddObject(obj); |
| 313 } |
| 276 | 314 |
| 277 // If the object is not patchable, check if we've already got it in the | 315 |
| 278 // object pool. | 316 intptr_t ObjectPoolHelper::FindUntagged(uword value, Patchability patchable) { |
| 279 if (patchable == kNotPatchable && !object_pool_.IsNull()) { | 317 // The object pool cannot be used in the vm isolate. |
| 280 intptr_t idx = object_pool_index_table_.Lookup(&obj); | 318 ASSERT(Isolate::Current() != Dart::vm_isolate()); |
| 281 if (idx != ObjIndexPair::kNoIndex) { | 319 if (patchable == kNotPatchable) { |
| 282 ASSERT(patchable_pool_entries_[idx] == kNotPatchable); | 320 // Check if we've already got it in the object pool. |
| 321 intptr_t idx = untagged_index_table_.Lookup(value); |
| 322 if (idx != UntaggedIndexPair::kNoIndex) { |
| 283 return idx; | 323 return idx; |
| 284 } | 324 } |
| 285 } | 325 } |
| 286 | 326 return AddUntagged(value, patchable); |
| 287 return AddObject(obj, patchable); | |
| 288 } | 327 } |
| 289 | 328 |
| 290 | 329 |
| 291 intptr_t ObjectPool::FindExternalLabel(const ExternalLabel* label, | 330 intptr_t ObjectPoolHelper::FindExternalLabel(const ExternalLabel* label, |
| 292 Patchability patchable) { | 331 Patchability patchable) { |
| 293 // The object pool cannot be used in the vm isolate. | 332 return FindUntagged(label->address(), patchable); |
| 294 ASSERT(Isolate::Current() != Dart::vm_isolate()); | |
| 295 const uword address = label->address(); | |
| 296 ASSERT(Utils::IsAligned(address, 4)); | |
| 297 // The address is stored in the object array as a RawSmi. | |
| 298 const Smi& smi = Smi::Handle(reinterpret_cast<RawSmi*>(address)); | |
| 299 return FindObject(smi, patchable); | |
| 300 } | 333 } |
| 301 | 334 |
| 302 | 335 |
| 336 intptr_t ObjectPoolHelper::FindImmediate(uword imm) { |
| 337 return FindUntagged(imm, kNotPatchable); |
| 338 } |
| 339 |
| 340 |
| 341 RawObjectPool* ObjectPoolHelper::MakeObjectPool() { |
| 342 // Code in the VM isolate does not use object pool. |
| 343 if (Isolate::Current() == Dart::vm_isolate()) { |
| 344 return Object::empty_object_pool().raw(); |
| 345 } |
| 346 |
| 347 intptr_t length = |
| 348 Assembler::kNumFixedEntries + |
| 349 tagged_entries_.length() + |
| 350 untagged_entries_.length(); |
| 351 const ObjectPool& object_pool = ObjectPool::Handle( |
| 352 ObjectPool::New(length, tagged_entries_.length())); |
| 353 intptr_t i = 0; |
| 354 for (; i < Assembler::kNumFixedObjectEntries; ++i) { |
| 355 object_pool.SetObjectAt(i, *fixed_entries_[i].obj_); |
| 356 } |
| 357 for (; i < Assembler::kNumFixedEntries; ++i) { |
| 358 object_pool.SetRawValueAt(i, fixed_entries_[i].raw_value_); |
| 359 } |
| 360 for (i = 0; i < tagged_entries_.length(); ++i) { |
| 361 object_pool.SetObjectAt(Assembler::kNumFixedEntries + i, |
| 362 *tagged_entries_[i]); |
| 363 } |
| 364 for (intptr_t j = 0; j < untagged_entries_.length(); ++j) { |
| 365 object_pool.SetRawValueAt(Assembler::kNumFixedEntries + i + j, |
| 366 untagged_entries_[j]); |
| 367 } |
| 368 return object_pool.raw(); |
| 369 } |
| 370 |
| 371 |
| 372 void ObjectPoolIndexFixup::Process(const MemoryRegion& region, |
| 373 intptr_t position, |
| 374 Assembler* assembler) { |
| 375 int32_t index = region.Load<int32_t>(position - sizeof(int32_t)); |
| 376 index += assembler->object_pool().UntaggedEntryStart() * kWordSize; |
| 377 region.Store<int32_t>(position - sizeof(int32_t), index); |
| 378 } |
| 379 |
| 303 } // namespace dart | 380 } // namespace dart |
| OLD | NEW |