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

Side by Side Diff: runtime/vm/class_finalizer.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/class_finalizer.h ('k') | runtime/vm/class_table.h » ('j') | 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) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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/class_finalizer.h" 5 #include "vm/class_finalizer.h"
6 6
7 #include "vm/code_generator.h" 7 #include "vm/code_generator.h"
8 #include "vm/flags.h" 8 #include "vm/flags.h"
9 #include "vm/hash_table.h"
9 #include "vm/heap.h" 10 #include "vm/heap.h"
10 #include "vm/isolate.h" 11 #include "vm/isolate.h"
11 #include "vm/longjump.h" 12 #include "vm/longjump.h"
12 #include "vm/log.h" 13 #include "vm/log.h"
13 #include "vm/object_store.h" 14 #include "vm/object_store.h"
15 #include "vm/program_visitor.h"
14 #include "vm/symbols.h" 16 #include "vm/symbols.h"
15 #include "vm/timeline.h" 17 #include "vm/timeline.h"
18 #include "vm/type_table.h"
16 19
17 namespace dart { 20 namespace dart {
18 21
19 DEFINE_FLAG(bool, print_classes, false, "Prints details about loaded classes."); 22 DEFINE_FLAG(bool, print_classes, false, "Prints details about loaded classes.");
20 DEFINE_FLAG(bool, reify, true, "Reify type arguments of generic types."); 23 DEFINE_FLAG(bool, reify, true, "Reify type arguments of generic types.");
21 DEFINE_FLAG(bool, trace_class_finalization, false, "Trace class finalization."); 24 DEFINE_FLAG(bool, trace_class_finalization, false, "Trace class finalization.");
22 DEFINE_FLAG(bool, trace_type_finalization, false, "Trace type finalization."); 25 DEFINE_FLAG(bool, trace_type_finalization, false, "Trace type finalization.");
23 26
24 27
25 bool ClassFinalizer::AllClassesFinalized() { 28 bool ClassFinalizer::AllClassesFinalized() {
(...skipping 3408 matching lines...) Expand 10 before | Expand all | Expand 10 after
3434 fields_array ^= cls.fields(); 3437 fields_array ^= cls.fields();
3435 ASSERT(fields_array.Length() == ByteBuffer::NumberOfFields()); 3438 ASSERT(fields_array.Length() == ByteBuffer::NumberOfFields());
3436 field ^= fields_array.At(0); 3439 field ^= fields_array.At(0);
3437 ASSERT(field.Offset() == ByteBuffer::data_offset()); 3440 ASSERT(field.Offset() == ByteBuffer::data_offset());
3438 name ^= field.name(); 3441 name ^= field.name();
3439 expected_name ^= String::New("_data"); 3442 expected_name ^= String::New("_data");
3440 ASSERT(String::EqualsIgnoringPrivateKey(name, expected_name)); 3443 ASSERT(String::EqualsIgnoringPrivateKey(name, expected_name));
3441 #endif 3444 #endif
3442 } 3445 }
3443 3446
3447
3448 void ClassFinalizer::SortClasses() {
3449 Thread* T = Thread::Current();
3450 Zone* Z = T->zone();
3451 Isolate* I = T->isolate();
3452 ClassTable* table = I->class_table();
3453 intptr_t num_cids = table->NumCids();
3454 intptr_t* old_to_new_cid = new intptr_t[num_cids];
3455 for (intptr_t cid = 0; cid < kNumPredefinedCids; cid++) {
3456 old_to_new_cid[cid] = cid; // The predefined classes cannot change cids.
3457 }
3458 for (intptr_t cid = kNumPredefinedCids; cid < num_cids; cid++) {
3459 old_to_new_cid[cid] = -1;
3460 }
3461
3462 intptr_t next_new_cid = kNumPredefinedCids;
3463 GrowableArray<intptr_t> dfs_stack;
3464 Class& cls = Class::Handle(Z);
3465 GrowableObjectArray& subclasses = GrowableObjectArray::Handle(Z);
3466
3467 // Object doesn't use its subclasses list.
3468 for (intptr_t cid = kNumPredefinedCids; cid < num_cids; cid++) {
3469 if (!table->HasValidClassAt(cid)) {
3470 continue;
3471 }
3472 cls = table->At(cid);
3473 if (cls.is_patch()) {
3474 continue;
3475 }
3476 if (cls.SuperClass() == I->object_store()->object_class()) {
3477 dfs_stack.Add(cid);
3478 }
3479 }
3480
3481 while (dfs_stack.length() > 0) {
3482 intptr_t cid = dfs_stack.RemoveLast();
3483 ASSERT(table->HasValidClassAt(cid));
3484 cls = table->At(cid);
3485 ASSERT(!cls.IsNull());
3486 if (old_to_new_cid[cid] == -1) {
3487 old_to_new_cid[cid] = next_new_cid++;
3488 if (FLAG_trace_class_finalization) {
3489 THR_Print("%" Pd ": %s, was %" Pd "\n", old_to_new_cid[cid],
3490 cls.ToCString(), cid);
3491 }
3492 }
3493 subclasses = cls.direct_subclasses();
3494 if (!subclasses.IsNull()) {
3495 for (intptr_t i = 0; i < subclasses.Length(); i++) {
3496 cls ^= subclasses.At(i);
3497 ASSERT(!cls.IsNull());
3498 dfs_stack.Add(cls.id());
3499 }
3500 }
3501 }
3502
3503 // Top-level classes, typedefs, patch classes, etc.
3504 for (intptr_t cid = kNumPredefinedCids; cid < num_cids; cid++) {
3505 if (old_to_new_cid[cid] == -1) {
3506 old_to_new_cid[cid] = next_new_cid++;
3507 if (FLAG_trace_class_finalization && table->HasValidClassAt(cid)) {
3508 cls = table->At(cid);
3509 THR_Print("%" Pd ": %s, was %" Pd "\n", old_to_new_cid[cid],
3510 cls.ToCString(), cid);
3511 }
3512 }
3513 }
3514 ASSERT(next_new_cid == num_cids);
3515
3516 RemapClassIds(old_to_new_cid);
3517 delete[] old_to_new_cid;
3518 RehashTypes(); // Types use cid's as part of their hashes.
3519 }
3520
3521
3522 class CidRewriteVisitor : public ObjectVisitor {
3523 public:
3524 explicit CidRewriteVisitor(intptr_t* old_to_new_cids)
3525 : old_to_new_cids_(old_to_new_cids) {}
3526
3527 intptr_t Map(intptr_t cid) {
3528 ASSERT(cid != -1);
3529 return old_to_new_cids_[cid];
3530 }
3531
3532 void VisitObject(RawObject* obj) {
3533 if (obj->IsClass()) {
3534 RawClass* cls = Class::RawCast(obj);
3535 cls->ptr()->id_ = Map(cls->ptr()->id_);
3536 } else if (obj->IsField()) {
3537 RawField* field = Field::RawCast(obj);
3538 field->ptr()->guarded_cid_ = Map(field->ptr()->guarded_cid_);
3539 field->ptr()->is_nullable_ = Map(field->ptr()->is_nullable_);
3540 } else if (obj->IsTypeParameter()) {
3541 RawTypeParameter* param = TypeParameter::RawCast(obj);
3542 param->ptr()->parameterized_class_id_ =
3543 Map(param->ptr()->parameterized_class_id_);
3544 } else if (obj->IsType()) {
3545 RawType* type = Type::RawCast(obj);
3546 RawObject* id = type->ptr()->type_class_id_;
3547 if (!id->IsHeapObject()) {
3548 type->ptr()->type_class_id_ =
3549 Smi::New(Map(Smi::Value(Smi::RawCast(id))));
3550 }
3551 } else {
3552 intptr_t old_cid = obj->GetClassId();
3553 intptr_t new_cid = Map(old_cid);
3554 if (old_cid != new_cid) {
3555 // Don't touch objects that are unchanged. In particular, Instructions,
3556 // which are write-protected.
3557 obj->SetClassId(new_cid);
3558 }
3559 }
3560 }
3561
3562 private:
3563 intptr_t* old_to_new_cids_;
3564 };
3565
3566
3567 void ClassFinalizer::RemapClassIds(intptr_t* old_to_new_cid) {
3568 Isolate* I = Thread::Current()->isolate();
3569
3570 // Code, ICData, allocation stubs have now-invalid cids.
3571 ClearAllCode();
3572
3573 {
3574 HeapIterationScope his;
3575 I->set_remapping_cids(true);
3576
3577 // Update the class table. Do it before rewriting cids in headers, as the
3578 // heap walkers load an object's size *after* calling the visitor.
3579 I->class_table()->Remap(old_to_new_cid);
3580
3581 // Rewrite cids in headers and cids in Classes, Fields, Types and
3582 // TypeParameters.
3583 {
3584 CidRewriteVisitor visitor(old_to_new_cid);
3585 I->heap()->VisitObjects(&visitor);
3586 }
3587 I->set_remapping_cids(false);
3588 }
3589
3590 #if defined(DEBUG)
3591 I->class_table()->Validate();
3592 I->heap()->Verify();
3593 #endif
3594 }
3595
3596
3597 class ClearTypeHashVisitor : public ObjectVisitor {
3598 public:
3599 explicit ClearTypeHashVisitor(Zone* zone)
3600 : type_param_(TypeParameter::Handle(zone)),
3601 type_(Type::Handle(zone)),
3602 type_args_(TypeArguments::Handle(zone)),
3603 bounded_type_(BoundedType::Handle(zone)) {}
3604
3605 void VisitObject(RawObject* obj) {
3606 if (obj->IsTypeParameter()) {
3607 type_param_ ^= obj;
3608 type_param_.SetHash(0);
3609 } else if (obj->IsType()) {
3610 type_ ^= obj;
3611 type_.SetHash(0);
3612 } else if (obj->IsBoundedType()) {
3613 bounded_type_ ^= obj;
3614 bounded_type_.SetHash(0);
3615 } else if (obj->IsTypeArguments()) {
3616 type_args_ ^= obj;
3617 type_args_.SetHash(0);
3618 }
3619 }
3620
3621 private:
3622 TypeParameter& type_param_;
3623 Type& type_;
3624 TypeArguments& type_args_;
3625 BoundedType& bounded_type_;
3626 };
3627
3628
3629 void ClassFinalizer::RehashTypes() {
3630 Thread* T = Thread::Current();
3631 Zone* Z = T->zone();
3632 Isolate* I = T->isolate();
3633
3634 // Clear all cached hash values.
3635 {
3636 HeapIterationScope his;
3637 ClearTypeHashVisitor visitor(Z);
3638 I->heap()->VisitObjects(&visitor);
3639 }
3640
3641 // Rehash the canonical Types table.
3642 ObjectStore* object_store = I->object_store();
3643 GrowableObjectArray& types =
3644 GrowableObjectArray::Handle(Z, GrowableObjectArray::New());
3645 Array& types_array = Array::Handle(Z);
3646 Type& type = Type::Handle(Z);
3647 {
3648 CanonicalTypeSet types_table(Z, object_store->canonical_types());
3649 types_array = HashTables::ToArray(types_table, false);
3650 for (intptr_t i = 0; i < types_array.Length(); i++) {
3651 type ^= types_array.At(i);
3652 types.Add(type);
3653 }
3654 types_table.Release();
3655 }
3656
3657 intptr_t dict_size = Utils::RoundUpToPowerOfTwo(types.Length() * 4 / 3);
3658 types_array = HashTables::New<CanonicalTypeSet>(dict_size, Heap::kOld);
3659 CanonicalTypeSet types_table(Z, types_array.raw());
3660 for (intptr_t i = 0; i < types.Length(); i++) {
3661 type ^= types.At(i);
3662 bool present = types_table.Insert(type);
3663 ASSERT(!present || type.IsRecursive());
3664 }
3665 object_store->set_canonical_types(types_table.Release());
3666
3667 // Rehash the canonical TypeArguments table.
3668 Array& typeargs_array = Array::Handle(Z);
3669 GrowableObjectArray& typeargs =
3670 GrowableObjectArray::Handle(Z, GrowableObjectArray::New());
3671 TypeArguments& typearg = TypeArguments::Handle(Z);
3672 {
3673 CanonicalTypeArgumentsSet typeargs_table(
3674 Z, object_store->canonical_type_arguments());
3675 typeargs_array = HashTables::ToArray(typeargs_table, false);
3676 for (intptr_t i = 0; i < typeargs_array.Length(); i++) {
3677 typearg ^= typeargs_array.At(i);
3678 typeargs.Add(typearg);
3679 }
3680 typeargs_table.Release();
3681 }
3682
3683 dict_size = Utils::RoundUpToPowerOfTwo(typeargs.Length() * 4 / 3);
3684 typeargs_array =
3685 HashTables::New<CanonicalTypeArgumentsSet>(dict_size, Heap::kOld);
3686 CanonicalTypeArgumentsSet typeargs_table(Z, typeargs_array.raw());
3687 for (intptr_t i = 0; i < typeargs.Length(); i++) {
3688 typearg ^= typeargs.At(i);
3689 bool present = typeargs_table.Insert(typearg);
3690 ASSERT(!present || typearg.IsRecursive());
3691 }
3692 object_store->set_canonical_type_arguments(typeargs_table.Release());
3693 }
3694
3695
3696 void ClassFinalizer::ClearAllCode() {
3697 class ClearCodeFunctionVisitor : public FunctionVisitor {
3698 void Visit(const Function& function) {
3699 function.ClearCode();
3700 function.ClearICDataArray();
3701 }
3702 };
3703 ClearCodeFunctionVisitor function_visitor;
3704 ProgramVisitor::VisitFunctions(&function_visitor);
3705
3706 class ClearCodeClassVisitor : public ClassVisitor {
3707 void Visit(const Class& cls) { cls.DisableAllocationStub(); }
3708 };
3709 ClearCodeClassVisitor class_visitor;
3710 ProgramVisitor::VisitClasses(&class_visitor);
3711 }
3712
3444 } // namespace dart 3713 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/class_finalizer.h ('k') | runtime/vm/class_table.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698