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

Unified Diff: runtime/vm/precompiler.cc

Issue 2281263002: AOT: Reassign class ids so class hierarchies have contiguous ranges. (Closed)
Patch Set: . Created 4 years, 4 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 side-by-side diff with in-line comments
Download patch
Index: runtime/vm/precompiler.cc
diff --git a/runtime/vm/precompiler.cc b/runtime/vm/precompiler.cc
index 4fa23bc72312adc8dd19a3bfe88af5e15cd750bf..6c0f9526927a6f2678ac270452fe248a590fb3fd 100644
--- a/runtime/vm/precompiler.cc
+++ b/runtime/vm/precompiler.cc
@@ -198,6 +198,8 @@ void Precompiler::DoCompileAll(
// because their class hasn't been finalized yet.
FinalizeAllClasses();
+ SortClasses();
+
// Precompile static initializers to compute result type information.
PrecompileStaticInitializers();
@@ -344,8 +346,16 @@ void Precompiler::ClearAllCode() {
function.ClearICDataArray();
}
};
- ClearCodeFunctionVisitor visitor;
- VisitFunctions(&visitor);
+ ClearCodeFunctionVisitor function_visitor;
+ VisitFunctions(&function_visitor);
+
+ class ClearCodeClassVisitor : public ClassVisitor {
+ void Visit(const Class& cls) {
+ cls.DisableAllocationStub();
+ }
+ };
+ ClearCodeClassVisitor class_visitor;
+ VisitClasses(&class_visitor);
}
@@ -2206,6 +2216,147 @@ 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;
+ }
+ cls = cls.SuperClass();
+ if (!cls.IsNull() && cls.IsObjectClass()) {
Florian Schneider 2016/08/26 22:14:34 cls.SuperClass() == I->object_store()->object_clas
rmacnak 2016/08/26 23:12:32 Done.
+ 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;
+}
+
+
+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
+}
+
+
void Precompiler::ResetPrecompilerState() {
changed_ = false;
function_count_ = 0;
« runtime/vm/precompiler.h ('K') | « runtime/vm/precompiler.h ('k') | runtime/vm/profiler.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698