Index: runtime/vm/precompiler.cc |
diff --git a/runtime/vm/precompiler.cc b/runtime/vm/precompiler.cc |
index 7579680c7f5a3185facd5268bb27924c24bc9981..985617c748d2e4d2b92f757873b2d1a40586703a 100644 |
--- a/runtime/vm/precompiler.cc |
+++ b/runtime/vm/precompiler.cc |
@@ -201,6 +201,92 @@ RawError* Precompiler::CompileAll( |
} |
+bool TypeRangeCache::InstanceOfHasClassRange(const AbstractType& type, |
+ intptr_t* lower_limit, |
+ intptr_t* upper_limit) { |
+ ASSERT(type.IsFinalized() && !type.IsMalformedOrMalbounded()); |
+ |
+ if (!type.IsInstantiated()) return false; |
+ if (type.IsFunctionType()) return false; |
+ |
+ Zone* zone = thread_->zone(); |
+ const TypeArguments& type_arguments = |
+ TypeArguments::Handle(zone, type.arguments()); |
+ if (!type_arguments.IsNull() && |
+ !type_arguments.IsRaw(0, type_arguments.Length())) return false; |
+ |
+ |
+ intptr_t type_cid = type.type_class_id(); |
+ if (lower_limits_[type_cid] == kNotContiguous) return false; |
+ if (lower_limits_[type_cid] != kNotComputed) { |
+ *lower_limit = lower_limits_[type_cid]; |
+ *upper_limit = upper_limits_[type_cid]; |
+ return true; |
+ } |
+ |
+ |
+ *lower_limit = -1; |
+ *upper_limit = -1; |
+ intptr_t last_matching_cid = -1; |
+ |
+ ClassTable* table = thread_->isolate()->class_table(); |
+ Class& cls = Class::Handle(zone); |
+ AbstractType& cls_type = AbstractType::Handle(zone); |
+ for (intptr_t cid = kInstanceCid; cid < table->NumCids(); cid++) { |
+ if (!table->HasValidClassAt(cid)) continue; |
+ if (cid == kVoidCid) continue; |
+ if (cid == kDynamicCid) continue; |
+ cls = table->At(cid); |
+ if (cls.is_abstract()) continue; |
+ if (cls.is_patch()) continue; |
+ if (cls.IsTopLevel()) continue; |
+ |
+ cls_type = cls.RareType(); |
+ if (cls_type.IsSubtypeOf(type, NULL, NULL, Heap::kOld)) { |
+ last_matching_cid = cid; |
+ if (*lower_limit == -1) { |
+ // Found beginning of range. |
+ *lower_limit = cid; |
+ } else if (*upper_limit == -1) { |
+ // Expanding range. |
+ } else { |
+ // Found a second range. |
+ lower_limits_[type_cid] = kNotContiguous; |
+ return false; |
+ } |
+ } else { |
+ if (*lower_limit == -1) { |
+ // Still before range. |
+ } else if (*upper_limit == -1) { |
+ // Found end of range. |
+ *upper_limit = last_matching_cid; |
+ } else { |
+ // After range. |
+ } |
+ } |
+ } |
+ if (*lower_limit == -1) { |
+ // Not implemented by any concrete class. |
+ *lower_limit = kIllegalCid; |
+ *upper_limit = kIllegalCid; |
+ } |
+ |
+ if (*upper_limit == -1) { |
+ ASSERT(last_matching_cid != -1); |
+ *upper_limit = last_matching_cid; |
+ } |
+ |
+ if (FLAG_trace_precompiler) { |
+ THR_Print("Type check for %s is cid range [%" Pd ", %" Pd "]\n", |
+ type.ToCString(), *lower_limit, *upper_limit); |
+ } |
+ |
+ lower_limits_[type_cid] = *lower_limit; |
+ upper_limits_[type_cid] = *upper_limit; |
+ return true; |
+} |
+ |
+ |
Precompiler::Precompiler(Thread* thread, bool reset_fields) : |
thread_(thread), |
zone_(NULL), |
@@ -247,6 +333,7 @@ void Precompiler::DoCompileAll( |
FinalizeAllClasses(); |
SortClasses(); |
+ TypeRangeCache trc(T, I->class_table()->NumCids()); |
// Precompile static initializers to compute result type information. |
PrecompileStaticInitializers(); |
@@ -2587,7 +2674,7 @@ bool PrecompileParsedFunctionHelper::Compile(CompilationPipeline* pipeline) { |
if (val == 0) { |
FlowGraph* flow_graph = NULL; |
- // Class hierarchy analysis is registered with the isolate in the |
+ // Class hierarchy analysis is registered with the thread in the |
// constructor and unregisters itself upon destruction. |
CHA cha(thread()); |