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 |