| 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/precompiler.h" | 5 #include "vm/precompiler.h" |
| 6 | 6 |
| 7 #include "vm/aot_optimizer.h" | 7 #include "vm/aot_optimizer.h" |
| 8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
| 9 #include "vm/ast_printer.h" | 9 #include "vm/ast_printer.h" |
| 10 #include "vm/branch_optimizer.h" | 10 #include "vm/branch_optimizer.h" |
| 11 #include "vm/cha.h" | 11 #include "vm/cha.h" |
| 12 #include "vm/class_finalizer.h" |
| 12 #include "vm/code_generator.h" | 13 #include "vm/code_generator.h" |
| 13 #include "vm/code_patcher.h" | 14 #include "vm/code_patcher.h" |
| 14 #include "vm/compiler.h" | 15 #include "vm/compiler.h" |
| 15 #include "vm/constant_propagator.h" | 16 #include "vm/constant_propagator.h" |
| 16 #include "vm/dart_entry.h" | 17 #include "vm/dart_entry.h" |
| 17 #include "vm/disassembler.h" | 18 #include "vm/disassembler.h" |
| 18 #include "vm/exceptions.h" | 19 #include "vm/exceptions.h" |
| 19 #include "vm/flags.h" | 20 #include "vm/flags.h" |
| 20 #include "vm/flow_graph.h" | 21 #include "vm/flow_graph.h" |
| 21 #include "vm/flow_graph_allocator.h" | 22 #include "vm/flow_graph_allocator.h" |
| (...skipping 398 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 420 StackZone stack_zone(T); | 421 StackZone stack_zone(T); |
| 421 zone_ = stack_zone.GetZone(); | 422 zone_ = stack_zone.GetZone(); |
| 422 | 423 |
| 423 { | 424 { |
| 424 HANDLESCOPE(T); | 425 HANDLESCOPE(T); |
| 425 // Make sure class hierarchy is stable before compilation so that CHA | 426 // Make sure class hierarchy is stable before compilation so that CHA |
| 426 // can be used. Also ensures lookup of entry points won't miss functions | 427 // can be used. Also ensures lookup of entry points won't miss functions |
| 427 // because their class hasn't been finalized yet. | 428 // because their class hasn't been finalized yet. |
| 428 FinalizeAllClasses(); | 429 FinalizeAllClasses(); |
| 429 | 430 |
| 430 SortClasses(); | 431 ClassFinalizer::SortClasses(); |
| 431 TypeRangeCache trc(this, T, I->class_table()->NumCids()); | 432 TypeRangeCache trc(this, T, I->class_table()->NumCids()); |
| 432 VerifyJITFeedback(); | 433 VerifyJITFeedback(); |
| 433 | 434 |
| 434 // Precompile static initializers to compute result type information. | 435 // Precompile static initializers to compute result type information. |
| 435 PrecompileStaticInitializers(); | 436 PrecompileStaticInitializers(); |
| 436 | 437 |
| 437 // Precompile constructors to compute type information for final fields. | 438 // Precompile constructors to compute type information for final fields. |
| 438 ClearAllCode(); | 439 ClassFinalizer::ClearAllCode(); |
| 439 PrecompileConstructors(); | 440 PrecompileConstructors(); |
| 440 | 441 |
| 441 for (intptr_t round = 0; round < FLAG_precompiler_rounds; round++) { | 442 for (intptr_t round = 0; round < FLAG_precompiler_rounds; round++) { |
| 442 if (FLAG_trace_precompiler) { | 443 if (FLAG_trace_precompiler) { |
| 443 THR_Print("Precompiler round %" Pd "\n", round); | 444 THR_Print("Precompiler round %" Pd "\n", round); |
| 444 } | 445 } |
| 445 | 446 |
| 446 if (round > 0) { | 447 if (round > 0) { |
| 447 ResetPrecompilerState(); | 448 ResetPrecompilerState(); |
| 448 } | 449 } |
| 449 | 450 |
| 450 // TODO(rmacnak): We should be able to do a more thorough job and drop | 451 // TODO(rmacnak): We should be able to do a more thorough job and drop |
| 451 // some | 452 // some |
| 452 // - implicit static closures | 453 // - implicit static closures |
| 453 // - field initializers | 454 // - field initializers |
| 454 // - invoke-field-dispatchers | 455 // - invoke-field-dispatchers |
| 455 // - method-extractors | 456 // - method-extractors |
| 456 // that are needed in early iterations but optimized away in later | 457 // that are needed in early iterations but optimized away in later |
| 457 // iterations. | 458 // iterations. |
| 458 ClearAllCode(); | 459 ClassFinalizer::ClearAllCode(); |
| 459 | 460 |
| 460 CollectDynamicFunctionNames(); | 461 CollectDynamicFunctionNames(); |
| 461 | 462 |
| 462 // Start with the allocations and invocations that happen from C++. | 463 // Start with the allocations and invocations that happen from C++. |
| 463 AddRoots(embedder_entry_points); | 464 AddRoots(embedder_entry_points); |
| 464 | 465 |
| 465 // Compile newly found targets and add their callees until we reach a | 466 // Compile newly found targets and add their callees until we reach a |
| 466 // fixed point. | 467 // fixed point. |
| 467 Iterate(); | 468 Iterate(); |
| 468 } | 469 } |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 612 current->field_->set_is_nullable(cid == kNullCid || cid == kDynamicCid); | 613 current->field_->set_is_nullable(cid == kNullCid || cid == kDynamicCid); |
| 613 if (FLAG_trace_precompiler) { | 614 if (FLAG_trace_precompiler) { |
| 614 THR_Print( | 615 THR_Print( |
| 615 "Field %s <- Type %s\n", current->field_->ToCString(), | 616 "Field %s <- Type %s\n", current->field_->ToCString(), |
| 616 Class::Handle(T->isolate()->class_table()->At(cid)).ToCString()); | 617 Class::Handle(T->isolate()->class_table()->At(cid)).ToCString()); |
| 617 } | 618 } |
| 618 } | 619 } |
| 619 } | 620 } |
| 620 | 621 |
| 621 | 622 |
| 622 void Precompiler::ClearAllCode() { | |
| 623 class ClearCodeFunctionVisitor : public FunctionVisitor { | |
| 624 void Visit(const Function& function) { | |
| 625 function.ClearCode(); | |
| 626 function.ClearICDataArray(); | |
| 627 } | |
| 628 }; | |
| 629 ClearCodeFunctionVisitor function_visitor; | |
| 630 ProgramVisitor::VisitFunctions(&function_visitor); | |
| 631 | |
| 632 class ClearCodeClassVisitor : public ClassVisitor { | |
| 633 void Visit(const Class& cls) { cls.DisableAllocationStub(); } | |
| 634 }; | |
| 635 ClearCodeClassVisitor class_visitor; | |
| 636 ProgramVisitor::VisitClasses(&class_visitor); | |
| 637 } | |
| 638 | |
| 639 | |
| 640 void Precompiler::AddRoots(Dart_QualifiedFunctionName embedder_entry_points[]) { | 623 void Precompiler::AddRoots(Dart_QualifiedFunctionName embedder_entry_points[]) { |
| 641 // Note that <rootlibrary>.main is not a root. The appropriate main will be | 624 // Note that <rootlibrary>.main is not a root. The appropriate main will be |
| 642 // discovered through _getMainClosure. | 625 // discovered through _getMainClosure. |
| 643 | 626 |
| 644 AddSelector(Symbols::NoSuchMethod()); | 627 AddSelector(Symbols::NoSuchMethod()); |
| 645 | 628 |
| 646 AddSelector(Symbols::Call()); // For speed, not correctness. | 629 AddSelector(Symbols::Call()); // For speed, not correctness. |
| 647 | 630 |
| 648 // Allocated from C++. | 631 // Allocated from C++. |
| 649 Class& cls = Class::Handle(Z); | 632 Class& cls = Class::Handle(Z); |
| (...skipping 1886 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2536 error_ = cls.EnsureIsFinalized(T); | 2519 error_ = cls.EnsureIsFinalized(T); |
| 2537 if (!error_.IsNull()) { | 2520 if (!error_.IsNull()) { |
| 2538 Jump(error_); | 2521 Jump(error_); |
| 2539 } | 2522 } |
| 2540 } | 2523 } |
| 2541 } | 2524 } |
| 2542 I->set_all_classes_finalized(true); | 2525 I->set_all_classes_finalized(true); |
| 2543 } | 2526 } |
| 2544 | 2527 |
| 2545 | 2528 |
| 2546 void Precompiler::SortClasses() { | |
| 2547 ClassTable* table = I->class_table(); | |
| 2548 intptr_t num_cids = table->NumCids(); | |
| 2549 intptr_t* old_to_new_cid = new intptr_t[num_cids]; | |
| 2550 for (intptr_t cid = 0; cid < kNumPredefinedCids; cid++) { | |
| 2551 old_to_new_cid[cid] = cid; // The predefined classes cannot change cids. | |
| 2552 } | |
| 2553 for (intptr_t cid = kNumPredefinedCids; cid < num_cids; cid++) { | |
| 2554 old_to_new_cid[cid] = -1; | |
| 2555 } | |
| 2556 | |
| 2557 intptr_t next_new_cid = kNumPredefinedCids; | |
| 2558 GrowableArray<intptr_t> dfs_stack; | |
| 2559 Class& cls = Class::Handle(Z); | |
| 2560 GrowableObjectArray& subclasses = GrowableObjectArray::Handle(Z); | |
| 2561 | |
| 2562 // Object doesn't use its subclasses list. | |
| 2563 for (intptr_t cid = kNumPredefinedCids; cid < num_cids; cid++) { | |
| 2564 if (!table->HasValidClassAt(cid)) { | |
| 2565 continue; | |
| 2566 } | |
| 2567 cls = table->At(cid); | |
| 2568 if (cls.is_patch()) { | |
| 2569 continue; | |
| 2570 } | |
| 2571 if (cls.SuperClass() == I->object_store()->object_class()) { | |
| 2572 dfs_stack.Add(cid); | |
| 2573 } | |
| 2574 } | |
| 2575 | |
| 2576 while (dfs_stack.length() > 0) { | |
| 2577 intptr_t cid = dfs_stack.RemoveLast(); | |
| 2578 ASSERT(table->HasValidClassAt(cid)); | |
| 2579 cls = table->At(cid); | |
| 2580 ASSERT(!cls.IsNull()); | |
| 2581 if (old_to_new_cid[cid] == -1) { | |
| 2582 old_to_new_cid[cid] = next_new_cid++; | |
| 2583 if (FLAG_trace_precompiler) { | |
| 2584 THR_Print("%" Pd ": %s, was %" Pd "\n", old_to_new_cid[cid], | |
| 2585 cls.ToCString(), cid); | |
| 2586 } | |
| 2587 } | |
| 2588 subclasses = cls.direct_subclasses(); | |
| 2589 if (!subclasses.IsNull()) { | |
| 2590 for (intptr_t i = 0; i < subclasses.Length(); i++) { | |
| 2591 cls ^= subclasses.At(i); | |
| 2592 ASSERT(!cls.IsNull()); | |
| 2593 dfs_stack.Add(cls.id()); | |
| 2594 } | |
| 2595 } | |
| 2596 } | |
| 2597 | |
| 2598 // Top-level classes, typedefs, patch classes, etc. | |
| 2599 for (intptr_t cid = kNumPredefinedCids; cid < num_cids; cid++) { | |
| 2600 if (old_to_new_cid[cid] == -1) { | |
| 2601 old_to_new_cid[cid] = next_new_cid++; | |
| 2602 if (FLAG_trace_precompiler && table->HasValidClassAt(cid)) { | |
| 2603 cls = table->At(cid); | |
| 2604 THR_Print("%" Pd ": %s, was %" Pd "\n", old_to_new_cid[cid], | |
| 2605 cls.ToCString(), cid); | |
| 2606 } | |
| 2607 } | |
| 2608 } | |
| 2609 ASSERT(next_new_cid == num_cids); | |
| 2610 | |
| 2611 RemapClassIds(old_to_new_cid); | |
| 2612 delete[] old_to_new_cid; | |
| 2613 RehashTypes(); // Types use cid's as part of their hashes. | |
| 2614 } | |
| 2615 | |
| 2616 | |
| 2617 class CidRewriteVisitor : public ObjectVisitor { | |
| 2618 public: | |
| 2619 explicit CidRewriteVisitor(intptr_t* old_to_new_cids) | |
| 2620 : old_to_new_cids_(old_to_new_cids) {} | |
| 2621 | |
| 2622 intptr_t Map(intptr_t cid) { | |
| 2623 ASSERT(cid != -1); | |
| 2624 return old_to_new_cids_[cid]; | |
| 2625 } | |
| 2626 | |
| 2627 void VisitObject(RawObject* obj) { | |
| 2628 if (obj->IsClass()) { | |
| 2629 RawClass* cls = Class::RawCast(obj); | |
| 2630 cls->ptr()->id_ = Map(cls->ptr()->id_); | |
| 2631 } else if (obj->IsField()) { | |
| 2632 RawField* field = Field::RawCast(obj); | |
| 2633 field->ptr()->guarded_cid_ = Map(field->ptr()->guarded_cid_); | |
| 2634 field->ptr()->is_nullable_ = Map(field->ptr()->is_nullable_); | |
| 2635 } else if (obj->IsTypeParameter()) { | |
| 2636 RawTypeParameter* param = TypeParameter::RawCast(obj); | |
| 2637 param->ptr()->parameterized_class_id_ = | |
| 2638 Map(param->ptr()->parameterized_class_id_); | |
| 2639 } else if (obj->IsType()) { | |
| 2640 RawType* type = Type::RawCast(obj); | |
| 2641 RawObject* id = type->ptr()->type_class_id_; | |
| 2642 if (!id->IsHeapObject()) { | |
| 2643 type->ptr()->type_class_id_ = | |
| 2644 Smi::New(Map(Smi::Value(Smi::RawCast(id)))); | |
| 2645 } | |
| 2646 } else { | |
| 2647 intptr_t old_cid = obj->GetClassId(); | |
| 2648 intptr_t new_cid = Map(old_cid); | |
| 2649 if (old_cid != new_cid) { | |
| 2650 // Don't touch objects that are unchanged. In particular, Instructions, | |
| 2651 // which are write-protected. | |
| 2652 obj->SetClassId(new_cid); | |
| 2653 } | |
| 2654 } | |
| 2655 } | |
| 2656 | |
| 2657 private: | |
| 2658 intptr_t* old_to_new_cids_; | |
| 2659 }; | |
| 2660 | |
| 2661 | |
| 2662 void Precompiler::RemapClassIds(intptr_t* old_to_new_cid) { | |
| 2663 // Code, ICData, allocation stubs have now-invalid cids. | |
| 2664 ClearAllCode(); | |
| 2665 | |
| 2666 { | |
| 2667 HeapIterationScope his; | |
| 2668 | |
| 2669 // Update the class table. Do it before rewriting cids in headers, as the | |
| 2670 // heap walkers load an object's size *after* calling the visitor. | |
| 2671 I->class_table()->Remap(old_to_new_cid); | |
| 2672 | |
| 2673 // Rewrite cids in headers and cids in Classes, Fields, Types and | |
| 2674 // TypeParameters. | |
| 2675 { | |
| 2676 CidRewriteVisitor visitor(old_to_new_cid); | |
| 2677 I->heap()->VisitObjects(&visitor); | |
| 2678 } | |
| 2679 } | |
| 2680 | |
| 2681 #if defined(DEBUG) | |
| 2682 I->class_table()->Validate(); | |
| 2683 I->heap()->Verify(); | |
| 2684 #endif | |
| 2685 } | |
| 2686 | |
| 2687 | |
| 2688 class ClearTypeHashVisitor : public ObjectVisitor { | |
| 2689 public: | |
| 2690 explicit ClearTypeHashVisitor(Zone* zone) | |
| 2691 : type_param_(TypeParameter::Handle(zone)), | |
| 2692 type_(Type::Handle(zone)), | |
| 2693 type_args_(TypeArguments::Handle(zone)), | |
| 2694 bounded_type_(BoundedType::Handle(zone)) {} | |
| 2695 | |
| 2696 void VisitObject(RawObject* obj) { | |
| 2697 if (obj->IsTypeParameter()) { | |
| 2698 type_param_ ^= obj; | |
| 2699 type_param_.SetHash(0); | |
| 2700 } else if (obj->IsType()) { | |
| 2701 type_ ^= obj; | |
| 2702 type_.SetHash(0); | |
| 2703 } else if (obj->IsBoundedType()) { | |
| 2704 bounded_type_ ^= obj; | |
| 2705 bounded_type_.SetHash(0); | |
| 2706 } else if (obj->IsTypeArguments()) { | |
| 2707 type_args_ ^= obj; | |
| 2708 type_args_.SetHash(0); | |
| 2709 } | |
| 2710 } | |
| 2711 | |
| 2712 private: | |
| 2713 TypeParameter& type_param_; | |
| 2714 Type& type_; | |
| 2715 TypeArguments& type_args_; | |
| 2716 BoundedType& bounded_type_; | |
| 2717 }; | |
| 2718 | |
| 2719 | |
| 2720 void Precompiler::RehashTypes() { | |
| 2721 // Clear all cached hash values. | |
| 2722 { | |
| 2723 HeapIterationScope his; | |
| 2724 ClearTypeHashVisitor visitor(Z); | |
| 2725 I->heap()->VisitObjects(&visitor); | |
| 2726 } | |
| 2727 | |
| 2728 // Rehash the canonical Types table. | |
| 2729 ObjectStore* object_store = I->object_store(); | |
| 2730 GrowableObjectArray& types = | |
| 2731 GrowableObjectArray::Handle(Z, GrowableObjectArray::New()); | |
| 2732 Array& types_array = Array::Handle(Z); | |
| 2733 Type& type = Type::Handle(Z); | |
| 2734 { | |
| 2735 CanonicalTypeSet types_table(Z, object_store->canonical_types()); | |
| 2736 types_array = HashTables::ToArray(types_table, false); | |
| 2737 for (intptr_t i = 0; i < types_array.Length(); i++) { | |
| 2738 type ^= types_array.At(i); | |
| 2739 types.Add(type); | |
| 2740 } | |
| 2741 types_table.Release(); | |
| 2742 } | |
| 2743 | |
| 2744 intptr_t dict_size = Utils::RoundUpToPowerOfTwo(types.Length() * 4 / 3); | |
| 2745 types_array = HashTables::New<CanonicalTypeSet>(dict_size, Heap::kOld); | |
| 2746 CanonicalTypeSet types_table(Z, types_array.raw()); | |
| 2747 for (intptr_t i = 0; i < types.Length(); i++) { | |
| 2748 type ^= types.At(i); | |
| 2749 bool present = types_table.Insert(type); | |
| 2750 ASSERT(!present || type.IsRecursive()); | |
| 2751 } | |
| 2752 object_store->set_canonical_types(types_table.Release()); | |
| 2753 | |
| 2754 // Rehash the canonical TypeArguments table. | |
| 2755 Array& typeargs_array = Array::Handle(Z); | |
| 2756 GrowableObjectArray& typeargs = | |
| 2757 GrowableObjectArray::Handle(Z, GrowableObjectArray::New()); | |
| 2758 TypeArguments& typearg = TypeArguments::Handle(Z); | |
| 2759 { | |
| 2760 CanonicalTypeArgumentsSet typeargs_table( | |
| 2761 Z, object_store->canonical_type_arguments()); | |
| 2762 typeargs_array = HashTables::ToArray(typeargs_table, false); | |
| 2763 for (intptr_t i = 0; i < typeargs_array.Length(); i++) { | |
| 2764 typearg ^= typeargs_array.At(i); | |
| 2765 typeargs.Add(typearg); | |
| 2766 } | |
| 2767 typeargs_table.Release(); | |
| 2768 } | |
| 2769 | |
| 2770 dict_size = Utils::RoundUpToPowerOfTwo(typeargs.Length() * 4 / 3); | |
| 2771 typeargs_array = | |
| 2772 HashTables::New<CanonicalTypeArgumentsSet>(dict_size, Heap::kOld); | |
| 2773 CanonicalTypeArgumentsSet typeargs_table(Z, typeargs_array.raw()); | |
| 2774 for (intptr_t i = 0; i < typeargs.Length(); i++) { | |
| 2775 typearg ^= typeargs.At(i); | |
| 2776 bool present = typeargs_table.Insert(typearg); | |
| 2777 ASSERT(!present || typearg.IsRecursive()); | |
| 2778 } | |
| 2779 object_store->set_canonical_type_arguments(typeargs_table.Release()); | |
| 2780 } | |
| 2781 | |
| 2782 | 2529 |
| 2783 void Precompiler::VerifyJITFeedback() { | 2530 void Precompiler::VerifyJITFeedback() { |
| 2784 if (jit_feedback_ == NULL) return; | 2531 if (jit_feedback_ == NULL) return; |
| 2785 | 2532 |
| 2786 ParsedJSONString* js_vmversion = jit_feedback_->StringAt("vmVersion"); | 2533 ParsedJSONString* js_vmversion = jit_feedback_->StringAt("vmVersion"); |
| 2787 if ((js_vmversion == NULL) || | 2534 if ((js_vmversion == NULL) || |
| 2788 strcmp(js_vmversion->value(), Version::CommitString()) != 0) { | 2535 strcmp(js_vmversion->value(), Version::CommitString()) != 0) { |
| 2789 THR_Print( | 2536 THR_Print( |
| 2790 "JIT feedback contains invalid vm version " | 2537 "JIT feedback contains invalid vm version " |
| 2791 "(saw %s, expected %s).\n", | 2538 "(saw %s, expected %s).\n", |
| (...skipping 1013 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3805 | 3552 |
| 3806 ASSERT(FLAG_precompiled_mode); | 3553 ASSERT(FLAG_precompiled_mode); |
| 3807 const bool optimized = function.IsOptimizable(); // False for natives. | 3554 const bool optimized = function.IsOptimizable(); // False for natives. |
| 3808 DartPrecompilationPipeline pipeline(zone, field_type_map); | 3555 DartPrecompilationPipeline pipeline(zone, field_type_map); |
| 3809 return PrecompileFunctionHelper(precompiler, &pipeline, function, optimized); | 3556 return PrecompileFunctionHelper(precompiler, &pipeline, function, optimized); |
| 3810 } | 3557 } |
| 3811 | 3558 |
| 3812 #endif // DART_PRECOMPILER | 3559 #endif // DART_PRECOMPILER |
| 3813 | 3560 |
| 3814 } // namespace dart | 3561 } // namespace dart |
| OLD | NEW |