Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(393)

Side by Side Diff: runtime/vm/precompiler.cc

Issue 2699853002: Sort class IDs before training AppJIT snapshots (Closed)
Patch Set: Add DeleteAllCode Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/vm/precompiler.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « runtime/vm/precompiler.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698