Index: runtime/vm/precompiler.cc |
diff --git a/runtime/vm/precompiler.cc b/runtime/vm/precompiler.cc |
index a053603d4dbec6a7e7fa61da145c8fe3d921ddfa..f3b5822ec4a73c024e8f59ff59839252eff2df0a 100644 |
--- a/runtime/vm/precompiler.cc |
+++ b/runtime/vm/precompiler.cc |
@@ -9,6 +9,7 @@ |
#include "vm/ast_printer.h" |
#include "vm/branch_optimizer.h" |
#include "vm/cha.h" |
+#include "vm/class_finalizer.h" |
#include "vm/code_generator.h" |
#include "vm/code_patcher.h" |
#include "vm/compiler.h" |
@@ -427,7 +428,7 @@ void Precompiler::DoCompileAll( |
// because their class hasn't been finalized yet. |
FinalizeAllClasses(); |
- SortClasses(); |
+ ClassFinalizer::SortClasses(); |
TypeRangeCache trc(this, T, I->class_table()->NumCids()); |
VerifyJITFeedback(); |
@@ -435,7 +436,7 @@ void Precompiler::DoCompileAll( |
PrecompileStaticInitializers(); |
// Precompile constructors to compute type information for final fields. |
- ClearAllCode(); |
+ ClassFinalizer::ClearAllCode(); |
PrecompileConstructors(); |
for (intptr_t round = 0; round < FLAG_precompiler_rounds; round++) { |
@@ -455,7 +456,7 @@ void Precompiler::DoCompileAll( |
// - method-extractors |
// that are needed in early iterations but optimized away in later |
// iterations. |
- ClearAllCode(); |
+ ClassFinalizer::ClearAllCode(); |
CollectDynamicFunctionNames(); |
@@ -619,24 +620,6 @@ void Precompiler::PrecompileConstructors() { |
} |
-void Precompiler::ClearAllCode() { |
- class ClearCodeFunctionVisitor : public FunctionVisitor { |
- void Visit(const Function& function) { |
- function.ClearCode(); |
- function.ClearICDataArray(); |
- } |
- }; |
- ClearCodeFunctionVisitor function_visitor; |
- ProgramVisitor::VisitFunctions(&function_visitor); |
- |
- class ClearCodeClassVisitor : public ClassVisitor { |
- void Visit(const Class& cls) { cls.DisableAllocationStub(); } |
- }; |
- ClearCodeClassVisitor class_visitor; |
- ProgramVisitor::VisitClasses(&class_visitor); |
-} |
- |
- |
void Precompiler::AddRoots(Dart_QualifiedFunctionName embedder_entry_points[]) { |
// Note that <rootlibrary>.main is not a root. The appropriate main will be |
// discovered through _getMainClosure. |
@@ -2543,242 +2526,6 @@ void Precompiler::FinalizeAllClasses() { |
} |
-void Precompiler::SortClasses() { |
- ClassTable* table = I->class_table(); |
- intptr_t num_cids = table->NumCids(); |
- intptr_t* old_to_new_cid = new intptr_t[num_cids]; |
- for (intptr_t cid = 0; cid < kNumPredefinedCids; cid++) { |
- old_to_new_cid[cid] = cid; // The predefined classes cannot change cids. |
- } |
- for (intptr_t cid = kNumPredefinedCids; cid < num_cids; cid++) { |
- old_to_new_cid[cid] = -1; |
- } |
- |
- intptr_t next_new_cid = kNumPredefinedCids; |
- GrowableArray<intptr_t> dfs_stack; |
- Class& cls = Class::Handle(Z); |
- GrowableObjectArray& subclasses = GrowableObjectArray::Handle(Z); |
- |
- // Object doesn't use its subclasses list. |
- for (intptr_t cid = kNumPredefinedCids; cid < num_cids; cid++) { |
- if (!table->HasValidClassAt(cid)) { |
- continue; |
- } |
- cls = table->At(cid); |
- if (cls.is_patch()) { |
- continue; |
- } |
- if (cls.SuperClass() == I->object_store()->object_class()) { |
- dfs_stack.Add(cid); |
- } |
- } |
- |
- while (dfs_stack.length() > 0) { |
- intptr_t cid = dfs_stack.RemoveLast(); |
- ASSERT(table->HasValidClassAt(cid)); |
- cls = table->At(cid); |
- ASSERT(!cls.IsNull()); |
- if (old_to_new_cid[cid] == -1) { |
- old_to_new_cid[cid] = next_new_cid++; |
- if (FLAG_trace_precompiler) { |
- THR_Print("%" Pd ": %s, was %" Pd "\n", old_to_new_cid[cid], |
- cls.ToCString(), cid); |
- } |
- } |
- subclasses = cls.direct_subclasses(); |
- if (!subclasses.IsNull()) { |
- for (intptr_t i = 0; i < subclasses.Length(); i++) { |
- cls ^= subclasses.At(i); |
- ASSERT(!cls.IsNull()); |
- dfs_stack.Add(cls.id()); |
- } |
- } |
- } |
- |
- // Top-level classes, typedefs, patch classes, etc. |
- for (intptr_t cid = kNumPredefinedCids; cid < num_cids; cid++) { |
- if (old_to_new_cid[cid] == -1) { |
- old_to_new_cid[cid] = next_new_cid++; |
- if (FLAG_trace_precompiler && table->HasValidClassAt(cid)) { |
- cls = table->At(cid); |
- THR_Print("%" Pd ": %s, was %" Pd "\n", old_to_new_cid[cid], |
- cls.ToCString(), cid); |
- } |
- } |
- } |
- ASSERT(next_new_cid == num_cids); |
- |
- RemapClassIds(old_to_new_cid); |
- delete[] old_to_new_cid; |
- RehashTypes(); // Types use cid's as part of their hashes. |
-} |
- |
- |
-class CidRewriteVisitor : public ObjectVisitor { |
- public: |
- explicit CidRewriteVisitor(intptr_t* old_to_new_cids) |
- : old_to_new_cids_(old_to_new_cids) {} |
- |
- intptr_t Map(intptr_t cid) { |
- ASSERT(cid != -1); |
- return old_to_new_cids_[cid]; |
- } |
- |
- void VisitObject(RawObject* obj) { |
- if (obj->IsClass()) { |
- RawClass* cls = Class::RawCast(obj); |
- cls->ptr()->id_ = Map(cls->ptr()->id_); |
- } else if (obj->IsField()) { |
- RawField* field = Field::RawCast(obj); |
- field->ptr()->guarded_cid_ = Map(field->ptr()->guarded_cid_); |
- field->ptr()->is_nullable_ = Map(field->ptr()->is_nullable_); |
- } else if (obj->IsTypeParameter()) { |
- RawTypeParameter* param = TypeParameter::RawCast(obj); |
- param->ptr()->parameterized_class_id_ = |
- Map(param->ptr()->parameterized_class_id_); |
- } else if (obj->IsType()) { |
- RawType* type = Type::RawCast(obj); |
- RawObject* id = type->ptr()->type_class_id_; |
- if (!id->IsHeapObject()) { |
- type->ptr()->type_class_id_ = |
- Smi::New(Map(Smi::Value(Smi::RawCast(id)))); |
- } |
- } else { |
- intptr_t old_cid = obj->GetClassId(); |
- intptr_t new_cid = Map(old_cid); |
- if (old_cid != new_cid) { |
- // Don't touch objects that are unchanged. In particular, Instructions, |
- // which are write-protected. |
- obj->SetClassId(new_cid); |
- } |
- } |
- } |
- |
- private: |
- intptr_t* old_to_new_cids_; |
-}; |
- |
- |
-void Precompiler::RemapClassIds(intptr_t* old_to_new_cid) { |
- // Code, ICData, allocation stubs have now-invalid cids. |
- ClearAllCode(); |
- |
- { |
- HeapIterationScope his; |
- |
- // Update the class table. Do it before rewriting cids in headers, as the |
- // heap walkers load an object's size *after* calling the visitor. |
- I->class_table()->Remap(old_to_new_cid); |
- |
- // Rewrite cids in headers and cids in Classes, Fields, Types and |
- // TypeParameters. |
- { |
- CidRewriteVisitor visitor(old_to_new_cid); |
- I->heap()->VisitObjects(&visitor); |
- } |
- } |
- |
-#if defined(DEBUG) |
- I->class_table()->Validate(); |
- I->heap()->Verify(); |
-#endif |
-} |
- |
- |
-class ClearTypeHashVisitor : public ObjectVisitor { |
- public: |
- explicit ClearTypeHashVisitor(Zone* zone) |
- : type_param_(TypeParameter::Handle(zone)), |
- type_(Type::Handle(zone)), |
- type_args_(TypeArguments::Handle(zone)), |
- bounded_type_(BoundedType::Handle(zone)) {} |
- |
- void VisitObject(RawObject* obj) { |
- if (obj->IsTypeParameter()) { |
- type_param_ ^= obj; |
- type_param_.SetHash(0); |
- } else if (obj->IsType()) { |
- type_ ^= obj; |
- type_.SetHash(0); |
- } else if (obj->IsBoundedType()) { |
- bounded_type_ ^= obj; |
- bounded_type_.SetHash(0); |
- } else if (obj->IsTypeArguments()) { |
- type_args_ ^= obj; |
- type_args_.SetHash(0); |
- } |
- } |
- |
- private: |
- TypeParameter& type_param_; |
- Type& type_; |
- TypeArguments& type_args_; |
- BoundedType& bounded_type_; |
-}; |
- |
- |
-void Precompiler::RehashTypes() { |
- // Clear all cached hash values. |
- { |
- HeapIterationScope his; |
- ClearTypeHashVisitor visitor(Z); |
- I->heap()->VisitObjects(&visitor); |
- } |
- |
- // Rehash the canonical Types table. |
- ObjectStore* object_store = I->object_store(); |
- GrowableObjectArray& types = |
- GrowableObjectArray::Handle(Z, GrowableObjectArray::New()); |
- Array& types_array = Array::Handle(Z); |
- Type& type = Type::Handle(Z); |
- { |
- CanonicalTypeSet types_table(Z, object_store->canonical_types()); |
- types_array = HashTables::ToArray(types_table, false); |
- for (intptr_t i = 0; i < types_array.Length(); i++) { |
- type ^= types_array.At(i); |
- types.Add(type); |
- } |
- types_table.Release(); |
- } |
- |
- intptr_t dict_size = Utils::RoundUpToPowerOfTwo(types.Length() * 4 / 3); |
- types_array = HashTables::New<CanonicalTypeSet>(dict_size, Heap::kOld); |
- CanonicalTypeSet types_table(Z, types_array.raw()); |
- for (intptr_t i = 0; i < types.Length(); i++) { |
- type ^= types.At(i); |
- bool present = types_table.Insert(type); |
- ASSERT(!present || type.IsRecursive()); |
- } |
- object_store->set_canonical_types(types_table.Release()); |
- |
- // Rehash the canonical TypeArguments table. |
- Array& typeargs_array = Array::Handle(Z); |
- GrowableObjectArray& typeargs = |
- GrowableObjectArray::Handle(Z, GrowableObjectArray::New()); |
- TypeArguments& typearg = TypeArguments::Handle(Z); |
- { |
- CanonicalTypeArgumentsSet typeargs_table( |
- Z, object_store->canonical_type_arguments()); |
- typeargs_array = HashTables::ToArray(typeargs_table, false); |
- for (intptr_t i = 0; i < typeargs_array.Length(); i++) { |
- typearg ^= typeargs_array.At(i); |
- typeargs.Add(typearg); |
- } |
- typeargs_table.Release(); |
- } |
- |
- dict_size = Utils::RoundUpToPowerOfTwo(typeargs.Length() * 4 / 3); |
- typeargs_array = |
- HashTables::New<CanonicalTypeArgumentsSet>(dict_size, Heap::kOld); |
- CanonicalTypeArgumentsSet typeargs_table(Z, typeargs_array.raw()); |
- for (intptr_t i = 0; i < typeargs.Length(); i++) { |
- typearg ^= typeargs.At(i); |
- bool present = typeargs_table.Insert(typearg); |
- ASSERT(!present || typearg.IsRecursive()); |
- } |
- object_store->set_canonical_type_arguments(typeargs_table.Release()); |
-} |
- |
void Precompiler::VerifyJITFeedback() { |
if (jit_feedback_ == NULL) return; |