OLD | NEW |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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/program_visitor.h" | 5 #include "vm/program_visitor.h" |
6 | 6 |
7 #include "vm/deopt_instructions.h" | 7 #include "vm/deopt_instructions.h" |
8 #include "vm/hash_map.h" | 8 #include "vm/hash_map.h" |
9 #include "vm/object.h" | 9 #include "vm/object.h" |
10 #include "vm/object_store.h" | 10 #include "vm/object_store.h" |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
143 void ProgramVisitor::DedupStackMaps() { | 143 void ProgramVisitor::DedupStackMaps() { |
144 class DedupStackMapsVisitor : public FunctionVisitor { | 144 class DedupStackMapsVisitor : public FunctionVisitor { |
145 public: | 145 public: |
146 explicit DedupStackMapsVisitor(Zone* zone) | 146 explicit DedupStackMapsVisitor(Zone* zone) |
147 : zone_(zone), | 147 : zone_(zone), |
148 canonical_stackmaps_(), | 148 canonical_stackmaps_(), |
149 code_(Code::Handle(zone)), | 149 code_(Code::Handle(zone)), |
150 stackmaps_(Array::Handle(zone)), | 150 stackmaps_(Array::Handle(zone)), |
151 stackmap_(StackMap::Handle(zone)) {} | 151 stackmap_(StackMap::Handle(zone)) {} |
152 | 152 |
| 153 void AddStackMap(const StackMap& stackmap) { |
| 154 canonical_stackmaps_.Insert(&StackMap::ZoneHandle(zone_, stackmap.raw())); |
| 155 } |
| 156 |
153 void Visit(const Function& function) { | 157 void Visit(const Function& function) { |
154 if (!function.HasCode()) { | 158 if (!function.HasCode()) { |
155 return; | 159 return; |
156 } | 160 } |
157 code_ = function.CurrentCode(); | 161 code_ = function.CurrentCode(); |
158 stackmaps_ = code_.stackmaps(); | 162 stackmaps_ = code_.stackmaps(); |
159 if (stackmaps_.IsNull()) return; | 163 if (stackmaps_.IsNull()) return; |
160 for (intptr_t i = 0; i < stackmaps_.Length(); i++) { | 164 for (intptr_t i = 0; i < stackmaps_.Length(); i++) { |
161 stackmap_ ^= stackmaps_.At(i); | 165 stackmap_ ^= stackmaps_.At(i); |
162 stackmap_ = DedupStackMap(stackmap_); | 166 stackmap_ = DedupStackMap(stackmap_); |
163 stackmaps_.SetAt(i, stackmap_); | 167 stackmaps_.SetAt(i, stackmap_); |
164 } | 168 } |
165 } | 169 } |
166 | 170 |
167 RawStackMap* DedupStackMap(const StackMap& stackmap) { | 171 RawStackMap* DedupStackMap(const StackMap& stackmap) { |
168 const StackMap* canonical_stackmap = | 172 const StackMap* canonical_stackmap = |
169 canonical_stackmaps_.LookupValue(&stackmap); | 173 canonical_stackmaps_.LookupValue(&stackmap); |
170 if (canonical_stackmap == NULL) { | 174 if (canonical_stackmap == NULL) { |
171 canonical_stackmaps_.Insert( | 175 AddStackMap(stackmap); |
172 &StackMap::ZoneHandle(zone_, stackmap.raw())); | |
173 return stackmap.raw(); | 176 return stackmap.raw(); |
174 } else { | 177 } else { |
175 return canonical_stackmap->raw(); | 178 return canonical_stackmap->raw(); |
176 } | 179 } |
177 } | 180 } |
178 | 181 |
179 private: | 182 private: |
180 Zone* zone_; | 183 Zone* zone_; |
181 StackMapSet canonical_stackmaps_; | 184 StackMapSet canonical_stackmaps_; |
182 Code& code_; | 185 Code& code_; |
183 Array& stackmaps_; | 186 Array& stackmaps_; |
184 StackMap& stackmap_; | 187 StackMap& stackmap_; |
185 }; | 188 }; |
186 | 189 |
187 DedupStackMapsVisitor visitor(Thread::Current()->zone()); | 190 DedupStackMapsVisitor visitor(Thread::Current()->zone()); |
| 191 if (Snapshot::IncludesCode(Dart::vm_snapshot_kind())) { |
| 192 // Prefer existing objects in the VM isolate. |
| 193 const Array& object_table = Object::vm_isolate_snapshot_object_table(); |
| 194 Object& object = Object::Handle(); |
| 195 for (intptr_t i = 0; i < object_table.Length(); i++) { |
| 196 object = object_table.At(i); |
| 197 if (object.IsStackMap()) { |
| 198 visitor.AddStackMap(StackMap::Cast(object)); |
| 199 } |
| 200 } |
| 201 } |
188 ProgramVisitor::VisitFunctions(&visitor); | 202 ProgramVisitor::VisitFunctions(&visitor); |
189 } | 203 } |
190 | 204 |
191 class PcDescriptorsKeyValueTrait { | 205 class PcDescriptorsKeyValueTrait { |
192 public: | 206 public: |
193 // Typedefs needed for the DirectChainedHashMap template. | 207 // Typedefs needed for the DirectChainedHashMap template. |
194 typedef const PcDescriptors* Key; | 208 typedef const PcDescriptors* Key; |
195 typedef const PcDescriptors* Value; | 209 typedef const PcDescriptors* Value; |
196 typedef const PcDescriptors* Pair; | 210 typedef const PcDescriptors* Pair; |
197 | 211 |
(...skipping 12 matching lines...) Expand all Loading... |
210 | 224 |
211 void ProgramVisitor::DedupPcDescriptors() { | 225 void ProgramVisitor::DedupPcDescriptors() { |
212 class DedupPcDescriptorsVisitor : public FunctionVisitor { | 226 class DedupPcDescriptorsVisitor : public FunctionVisitor { |
213 public: | 227 public: |
214 explicit DedupPcDescriptorsVisitor(Zone* zone) | 228 explicit DedupPcDescriptorsVisitor(Zone* zone) |
215 : zone_(zone), | 229 : zone_(zone), |
216 canonical_pc_descriptors_(), | 230 canonical_pc_descriptors_(), |
217 code_(Code::Handle(zone)), | 231 code_(Code::Handle(zone)), |
218 pc_descriptor_(PcDescriptors::Handle(zone)) {} | 232 pc_descriptor_(PcDescriptors::Handle(zone)) {} |
219 | 233 |
| 234 void AddPcDescriptor(const PcDescriptors& pc_descriptor) { |
| 235 canonical_pc_descriptors_.Insert( |
| 236 &PcDescriptors::ZoneHandle(zone_, pc_descriptor.raw())); |
| 237 } |
| 238 |
220 void Visit(const Function& function) { | 239 void Visit(const Function& function) { |
221 if (!function.HasCode()) { | 240 if (!function.HasCode()) { |
222 return; | 241 return; |
223 } | 242 } |
224 code_ = function.CurrentCode(); | 243 code_ = function.CurrentCode(); |
225 pc_descriptor_ = code_.pc_descriptors(); | 244 pc_descriptor_ = code_.pc_descriptors(); |
226 if (pc_descriptor_.IsNull()) return; | 245 if (pc_descriptor_.IsNull()) return; |
227 pc_descriptor_ = DedupPcDescriptor(pc_descriptor_); | 246 pc_descriptor_ = DedupPcDescriptor(pc_descriptor_); |
228 code_.set_pc_descriptors(pc_descriptor_); | 247 code_.set_pc_descriptors(pc_descriptor_); |
229 } | 248 } |
230 | 249 |
231 RawPcDescriptors* DedupPcDescriptor(const PcDescriptors& pc_descriptor) { | 250 RawPcDescriptors* DedupPcDescriptor(const PcDescriptors& pc_descriptor) { |
232 const PcDescriptors* canonical_pc_descriptor = | 251 const PcDescriptors* canonical_pc_descriptor = |
233 canonical_pc_descriptors_.LookupValue(&pc_descriptor); | 252 canonical_pc_descriptors_.LookupValue(&pc_descriptor); |
234 if (canonical_pc_descriptor == NULL) { | 253 if (canonical_pc_descriptor == NULL) { |
235 canonical_pc_descriptors_.Insert( | 254 AddPcDescriptor(pc_descriptor); |
236 &PcDescriptors::ZoneHandle(zone_, pc_descriptor.raw())); | |
237 return pc_descriptor.raw(); | 255 return pc_descriptor.raw(); |
238 } else { | 256 } else { |
239 return canonical_pc_descriptor->raw(); | 257 return canonical_pc_descriptor->raw(); |
240 } | 258 } |
241 } | 259 } |
242 | 260 |
243 private: | 261 private: |
244 Zone* zone_; | 262 Zone* zone_; |
245 PcDescriptorsSet canonical_pc_descriptors_; | 263 PcDescriptorsSet canonical_pc_descriptors_; |
246 Code& code_; | 264 Code& code_; |
247 PcDescriptors& pc_descriptor_; | 265 PcDescriptors& pc_descriptor_; |
248 }; | 266 }; |
249 | 267 |
250 DedupPcDescriptorsVisitor visitor(Thread::Current()->zone()); | 268 DedupPcDescriptorsVisitor visitor(Thread::Current()->zone()); |
| 269 if (Snapshot::IncludesCode(Dart::vm_snapshot_kind())) { |
| 270 // Prefer existing objects in the VM isolate. |
| 271 const Array& object_table = Object::vm_isolate_snapshot_object_table(); |
| 272 Object& object = Object::Handle(); |
| 273 for (intptr_t i = 0; i < object_table.Length(); i++) { |
| 274 object = object_table.At(i); |
| 275 if (object.IsPcDescriptors()) { |
| 276 visitor.AddPcDescriptor(PcDescriptors::Cast(object)); |
| 277 } |
| 278 } |
| 279 } |
251 ProgramVisitor::VisitFunctions(&visitor); | 280 ProgramVisitor::VisitFunctions(&visitor); |
252 } | 281 } |
253 | 282 |
254 class TypedDataKeyValueTrait { | 283 class TypedDataKeyValueTrait { |
255 public: | 284 public: |
256 // Typedefs needed for the DirectChainedHashMap template. | 285 // Typedefs needed for the DirectChainedHashMap template. |
257 typedef const TypedData* Key; | 286 typedef const TypedData* Key; |
258 typedef const TypedData* Value; | 287 typedef const TypedData* Value; |
259 typedef const TypedData* Pair; | 288 typedef const TypedData* Pair; |
260 | 289 |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
354 | 383 |
355 void ProgramVisitor::DedupCodeSourceMaps() { | 384 void ProgramVisitor::DedupCodeSourceMaps() { |
356 class DedupCodeSourceMapsVisitor : public FunctionVisitor { | 385 class DedupCodeSourceMapsVisitor : public FunctionVisitor { |
357 public: | 386 public: |
358 explicit DedupCodeSourceMapsVisitor(Zone* zone) | 387 explicit DedupCodeSourceMapsVisitor(Zone* zone) |
359 : zone_(zone), | 388 : zone_(zone), |
360 canonical_code_source_maps_(), | 389 canonical_code_source_maps_(), |
361 code_(Code::Handle(zone)), | 390 code_(Code::Handle(zone)), |
362 code_source_map_(CodeSourceMap::Handle(zone)) {} | 391 code_source_map_(CodeSourceMap::Handle(zone)) {} |
363 | 392 |
| 393 void AddCodeSourceMap(const CodeSourceMap& code_source_map) { |
| 394 canonical_code_source_maps_.Insert( |
| 395 &CodeSourceMap::ZoneHandle(zone_, code_source_map.raw())); |
| 396 } |
| 397 |
364 void Visit(const Function& function) { | 398 void Visit(const Function& function) { |
365 if (!function.HasCode()) { | 399 if (!function.HasCode()) { |
366 return; | 400 return; |
367 } | 401 } |
368 code_ = function.CurrentCode(); | 402 code_ = function.CurrentCode(); |
369 code_source_map_ = code_.code_source_map(); | 403 code_source_map_ = code_.code_source_map(); |
370 ASSERT(!code_source_map_.IsNull()); | 404 ASSERT(!code_source_map_.IsNull()); |
371 code_source_map_ = DedupCodeSourceMap(code_source_map_); | 405 code_source_map_ = DedupCodeSourceMap(code_source_map_); |
372 code_.set_code_source_map(code_source_map_); | 406 code_.set_code_source_map(code_source_map_); |
373 } | 407 } |
374 | 408 |
375 RawCodeSourceMap* DedupCodeSourceMap(const CodeSourceMap& code_source_map) { | 409 RawCodeSourceMap* DedupCodeSourceMap(const CodeSourceMap& code_source_map) { |
376 const CodeSourceMap* canonical_code_source_map = | 410 const CodeSourceMap* canonical_code_source_map = |
377 canonical_code_source_maps_.LookupValue(&code_source_map); | 411 canonical_code_source_maps_.LookupValue(&code_source_map); |
378 if (canonical_code_source_map == NULL) { | 412 if (canonical_code_source_map == NULL) { |
379 canonical_code_source_maps_.Insert( | 413 AddCodeSourceMap(code_source_map); |
380 &CodeSourceMap::ZoneHandle(zone_, code_source_map.raw())); | |
381 return code_source_map.raw(); | 414 return code_source_map.raw(); |
382 } else { | 415 } else { |
383 return canonical_code_source_map->raw(); | 416 return canonical_code_source_map->raw(); |
384 } | 417 } |
385 } | 418 } |
386 | 419 |
387 private: | 420 private: |
388 Zone* zone_; | 421 Zone* zone_; |
389 CodeSourceMapSet canonical_code_source_maps_; | 422 CodeSourceMapSet canonical_code_source_maps_; |
390 Code& code_; | 423 Code& code_; |
391 CodeSourceMap& code_source_map_; | 424 CodeSourceMap& code_source_map_; |
392 }; | 425 }; |
393 | 426 |
394 DedupCodeSourceMapsVisitor visitor(Thread::Current()->zone()); | 427 DedupCodeSourceMapsVisitor visitor(Thread::Current()->zone()); |
| 428 if (Snapshot::IncludesCode(Dart::vm_snapshot_kind())) { |
| 429 // Prefer existing objects in the VM isolate. |
| 430 const Array& object_table = Object::vm_isolate_snapshot_object_table(); |
| 431 Object& object = Object::Handle(); |
| 432 for (intptr_t i = 0; i < object_table.Length(); i++) { |
| 433 object = object_table.At(i); |
| 434 if (object.IsCodeSourceMap()) { |
| 435 visitor.AddCodeSourceMap(CodeSourceMap::Cast(object)); |
| 436 } |
| 437 } |
| 438 } |
395 ProgramVisitor::VisitFunctions(&visitor); | 439 ProgramVisitor::VisitFunctions(&visitor); |
396 } | 440 } |
397 | 441 |
398 class ArrayKeyValueTrait { | 442 class ArrayKeyValueTrait { |
399 public: | 443 public: |
400 // Typedefs needed for the DirectChainedHashMap template. | 444 // Typedefs needed for the DirectChainedHashMap template. |
401 typedef const Array* Key; | 445 typedef const Array* Key; |
402 typedef const Array* Value; | 446 typedef const Array* Value; |
403 typedef const Array* Pair; | 447 typedef const Array* Pair; |
404 | 448 |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
534 static inline intptr_t Hashcode(Key key) { return key->Size(); } | 578 static inline intptr_t Hashcode(Key key) { return key->Size(); } |
535 | 579 |
536 static inline bool IsKeyEqual(Pair pair, Key key) { | 580 static inline bool IsKeyEqual(Pair pair, Key key) { |
537 return pair->Equals(*key); | 581 return pair->Equals(*key); |
538 } | 582 } |
539 }; | 583 }; |
540 | 584 |
541 typedef DirectChainedHashMap<InstructionsKeyValueTrait> InstructionsSet; | 585 typedef DirectChainedHashMap<InstructionsKeyValueTrait> InstructionsSet; |
542 | 586 |
543 void ProgramVisitor::DedupInstructions() { | 587 void ProgramVisitor::DedupInstructions() { |
544 class DedupInstructionsVisitor : public FunctionVisitor { | 588 class DedupInstructionsVisitor : public FunctionVisitor, |
| 589 public ObjectVisitor { |
545 public: | 590 public: |
546 explicit DedupInstructionsVisitor(Zone* zone) | 591 explicit DedupInstructionsVisitor(Zone* zone) |
547 : zone_(zone), | 592 : zone_(zone), |
548 canonical_instructions_set_(), | 593 canonical_instructions_set_(), |
549 code_(Code::Handle(zone)), | 594 code_(Code::Handle(zone)), |
550 instructions_(Instructions::Handle(zone)) {} | 595 instructions_(Instructions::Handle(zone)) {} |
551 | 596 |
| 597 void VisitObject(RawObject* obj) { |
| 598 if (obj->IsInstructions()) { |
| 599 canonical_instructions_set_.Insert( |
| 600 &Instructions::ZoneHandle(zone_, Instructions::RawCast(obj))); |
| 601 } |
| 602 } |
| 603 |
552 void Visit(const Function& function) { | 604 void Visit(const Function& function) { |
553 if (!function.HasCode()) { | 605 if (!function.HasCode()) { |
554 return; | 606 return; |
555 } | 607 } |
556 code_ = function.CurrentCode(); | 608 code_ = function.CurrentCode(); |
557 instructions_ = code_.instructions(); | 609 instructions_ = code_.instructions(); |
558 instructions_ = DedupOneInstructions(instructions_); | 610 instructions_ = DedupOneInstructions(instructions_); |
559 code_.SetActiveInstructions(instructions_); | 611 code_.SetActiveInstructions(instructions_); |
560 code_.set_instructions(instructions_); | 612 code_.set_instructions(instructions_); |
561 function.SetInstructions(code_); // Update cached entry point. | 613 function.SetInstructions(code_); // Update cached entry point. |
(...skipping 12 matching lines...) Expand all Loading... |
574 } | 626 } |
575 | 627 |
576 private: | 628 private: |
577 Zone* zone_; | 629 Zone* zone_; |
578 InstructionsSet canonical_instructions_set_; | 630 InstructionsSet canonical_instructions_set_; |
579 Code& code_; | 631 Code& code_; |
580 Instructions& instructions_; | 632 Instructions& instructions_; |
581 }; | 633 }; |
582 | 634 |
583 DedupInstructionsVisitor visitor(Thread::Current()->zone()); | 635 DedupInstructionsVisitor visitor(Thread::Current()->zone()); |
| 636 if (Snapshot::IncludesCode(Dart::vm_snapshot_kind())) { |
| 637 // Prefer existing objects in the VM isolate. |
| 638 Dart::vm_isolate()->heap()->VisitObjectsImagePages(&visitor); |
| 639 } |
584 ProgramVisitor::VisitFunctions(&visitor); | 640 ProgramVisitor::VisitFunctions(&visitor); |
585 } | 641 } |
586 | 642 |
587 void ProgramVisitor::Dedup() { | 643 void ProgramVisitor::Dedup() { |
588 Thread* thread = Thread::Current(); | 644 Thread* thread = Thread::Current(); |
589 StackZone stack_zone(thread); | 645 StackZone stack_zone(thread); |
590 HANDLESCOPE(thread); | 646 HANDLESCOPE(thread); |
591 | 647 |
592 // TODO(rmacnak): Bind static calls whose target has been compiled. Forward | 648 // TODO(rmacnak): Bind static calls whose target has been compiled. Forward |
593 // references to disabled code. | 649 // references to disabled code. |
594 ShareMegamorphicBuckets(); | 650 ShareMegamorphicBuckets(); |
595 DedupStackMaps(); | 651 DedupStackMaps(); |
596 DedupPcDescriptors(); | 652 DedupPcDescriptors(); |
597 NOT_IN_PRECOMPILED(DedupDeoptEntries()); | 653 NOT_IN_PRECOMPILED(DedupDeoptEntries()); |
598 DedupCodeSourceMaps(); | 654 DedupCodeSourceMaps(); |
599 DedupLists(); | 655 DedupLists(); |
600 | 656 |
601 #if defined(PRODUCT) | 657 #if defined(PRODUCT) |
602 // Reduces binary size but obfuscates profiler results. | 658 // Reduces binary size but obfuscates profiler results. |
603 DedupInstructions(); | 659 DedupInstructions(); |
604 #endif | 660 #endif |
605 } | 661 } |
606 | 662 |
607 } // namespace dart | 663 } // namespace dart |
OLD | NEW |