| Index: runtime/vm/precompiler.cc | 
| diff --git a/runtime/vm/precompiler.cc b/runtime/vm/precompiler.cc | 
| index da3473927aa2e45734306dee8c3741f9c906651c..5a0f88eadc96990026eda32056d4ae4cb8d58c0b 100644 | 
| --- a/runtime/vm/precompiler.cc | 
| +++ b/runtime/vm/precompiler.cc | 
| @@ -502,15 +502,7 @@ void Precompiler::DoCompileAll( | 
| BindStaticCalls(); | 
| SwitchICCalls(); | 
|  | 
| -    ShareMegamorphicBuckets(); | 
| -    DedupStackMaps(); | 
| -    DedupCodeSourceMaps(); | 
| -    DedupLists(); | 
| - | 
| -    if (FLAG_dedup_instructions) { | 
| -      // Reduces binary size but obfuscates profiler results. | 
| -      DedupInstructions(); | 
| -    } | 
| +    ProgramVisitor::Dedup(); | 
|  | 
| zone_ = NULL; | 
| } | 
| @@ -2270,240 +2262,6 @@ void Precompiler::SwitchICCalls() { | 
| } | 
|  | 
|  | 
| -void Precompiler::ShareMegamorphicBuckets() { | 
| -  const GrowableObjectArray& table = GrowableObjectArray::Handle( | 
| -      Z, I->object_store()->megamorphic_cache_table()); | 
| -  if (table.IsNull()) return; | 
| -  MegamorphicCache& cache = MegamorphicCache::Handle(Z); | 
| - | 
| -  const intptr_t capacity = 1; | 
| -  const Array& buckets = Array::Handle( | 
| -      Z, Array::New(MegamorphicCache::kEntryLength * capacity, Heap::kOld)); | 
| -  const Function& handler = | 
| -      Function::Handle(Z, MegamorphicCacheTable::miss_handler(I)); | 
| -  MegamorphicCache::SetEntry(buckets, 0, MegamorphicCache::smi_illegal_cid(), | 
| -                             handler); | 
| - | 
| -  for (intptr_t i = 0; i < table.Length(); i++) { | 
| -    cache ^= table.At(i); | 
| -    cache.set_buckets(buckets); | 
| -    cache.set_mask(capacity - 1); | 
| -    cache.set_filled_entry_count(0); | 
| -  } | 
| -} | 
| - | 
| - | 
| -void Precompiler::DedupStackMaps() { | 
| -  class DedupStackMapsVisitor : public FunctionVisitor { | 
| -   public: | 
| -    explicit DedupStackMapsVisitor(Zone* zone) | 
| -        : zone_(zone), | 
| -          canonical_stackmaps_(), | 
| -          code_(Code::Handle(zone)), | 
| -          stackmaps_(Array::Handle(zone)), | 
| -          stackmap_(StackMap::Handle(zone)) {} | 
| - | 
| -    void Visit(const Function& function) { | 
| -      if (!function.HasCode()) { | 
| -        return; | 
| -      } | 
| -      code_ = function.CurrentCode(); | 
| -      stackmaps_ = code_.stackmaps(); | 
| -      if (stackmaps_.IsNull()) return; | 
| -      for (intptr_t i = 0; i < stackmaps_.Length(); i++) { | 
| -        stackmap_ ^= stackmaps_.At(i); | 
| -        stackmap_ = DedupStackMap(stackmap_); | 
| -        stackmaps_.SetAt(i, stackmap_); | 
| -      } | 
| -    } | 
| - | 
| -    RawStackMap* DedupStackMap(const StackMap& stackmap) { | 
| -      const StackMap* canonical_stackmap = | 
| -          canonical_stackmaps_.LookupValue(&stackmap); | 
| -      if (canonical_stackmap == NULL) { | 
| -        canonical_stackmaps_.Insert( | 
| -            &StackMap::ZoneHandle(zone_, stackmap.raw())); | 
| -        return stackmap.raw(); | 
| -      } else { | 
| -        return canonical_stackmap->raw(); | 
| -      } | 
| -    } | 
| - | 
| -   private: | 
| -    Zone* zone_; | 
| -    StackMapSet canonical_stackmaps_; | 
| -    Code& code_; | 
| -    Array& stackmaps_; | 
| -    StackMap& stackmap_; | 
| -  }; | 
| - | 
| -  DedupStackMapsVisitor visitor(Z); | 
| -  ProgramVisitor::VisitFunctions(&visitor); | 
| -} | 
| - | 
| - | 
| -void Precompiler::DedupCodeSourceMaps() { | 
| -  class DedupCodeSourceMapsVisitor : public FunctionVisitor { | 
| -   public: | 
| -    explicit DedupCodeSourceMapsVisitor(Zone* zone) | 
| -        : zone_(zone), | 
| -          canonical_code_source_maps_(), | 
| -          code_(Code::Handle(zone)), | 
| -          code_source_map_(CodeSourceMap::Handle(zone)) {} | 
| - | 
| -    void Visit(const Function& function) { | 
| -      if (!function.HasCode()) { | 
| -        return; | 
| -      } | 
| -      code_ = function.CurrentCode(); | 
| -      code_source_map_ = code_.code_source_map(); | 
| -      ASSERT(!code_source_map_.IsNull()); | 
| -      code_source_map_ = DedupCodeSourceMap(code_source_map_); | 
| -      code_.set_code_source_map(code_source_map_); | 
| -    } | 
| - | 
| -    RawCodeSourceMap* DedupCodeSourceMap(const CodeSourceMap& code_source_map) { | 
| -      const CodeSourceMap* canonical_code_source_map = | 
| -          canonical_code_source_maps_.LookupValue(&code_source_map); | 
| -      if (canonical_code_source_map == NULL) { | 
| -        canonical_code_source_maps_.Insert( | 
| -            &CodeSourceMap::ZoneHandle(zone_, code_source_map.raw())); | 
| -        return code_source_map.raw(); | 
| -      } else { | 
| -        return canonical_code_source_map->raw(); | 
| -      } | 
| -    } | 
| - | 
| -   private: | 
| -    Zone* zone_; | 
| -    CodeSourceMapSet canonical_code_source_maps_; | 
| -    Code& code_; | 
| -    CodeSourceMap& code_source_map_; | 
| -  }; | 
| - | 
| -  DedupCodeSourceMapsVisitor visitor(Z); | 
| -  ProgramVisitor::VisitFunctions(&visitor); | 
| -} | 
| - | 
| - | 
| -void Precompiler::DedupLists() { | 
| -  class DedupListsVisitor : public FunctionVisitor { | 
| -   public: | 
| -    explicit DedupListsVisitor(Zone* zone) | 
| -        : zone_(zone), | 
| -          canonical_lists_(), | 
| -          code_(Code::Handle(zone)), | 
| -          list_(Array::Handle(zone)) {} | 
| - | 
| -    void Visit(const Function& function) { | 
| -      code_ = function.CurrentCode(); | 
| -      if (!code_.IsNull()) { | 
| -        list_ = code_.stackmaps(); | 
| -        if (!list_.IsNull()) { | 
| -          list_ = DedupList(list_); | 
| -          code_.set_stackmaps(list_); | 
| -        } | 
| -        list_ = code_.inlined_id_to_function(); | 
| -        if (!list_.IsNull()) { | 
| -          list_ = DedupList(list_); | 
| -          code_.set_inlined_id_to_function(list_); | 
| -        } | 
| -      } | 
| - | 
| -      list_ = function.parameter_types(); | 
| -      if (!list_.IsNull()) { | 
| -        if (!function.IsSignatureFunction() && !function.IsClosureFunction() && | 
| -            (function.name() != Symbols::Call().raw()) && !list_.InVMHeap()) { | 
| -          // Parameter types not needed for function type tests. | 
| -          for (intptr_t i = 0; i < list_.Length(); i++) { | 
| -            list_.SetAt(i, Object::dynamic_type()); | 
| -          } | 
| -        } | 
| -        list_ = DedupList(list_); | 
| -        function.set_parameter_types(list_); | 
| -      } | 
| - | 
| -      list_ = function.parameter_names(); | 
| -      if (!list_.IsNull()) { | 
| -        if (!function.HasOptionalNamedParameters() && !list_.InVMHeap()) { | 
| -          // Parameter names not needed for resolution. | 
| -          for (intptr_t i = 0; i < list_.Length(); i++) { | 
| -            list_.SetAt(i, Symbols::OptimizedOut()); | 
| -          } | 
| -        } | 
| -        list_ = DedupList(list_); | 
| -        function.set_parameter_names(list_); | 
| -      } | 
| -    } | 
| - | 
| -    RawArray* DedupList(const Array& list) { | 
| -      const Array* canonical_list = canonical_lists_.LookupValue(&list); | 
| -      if (canonical_list == NULL) { | 
| -        canonical_lists_.Insert(&Array::ZoneHandle(zone_, list.raw())); | 
| -        return list.raw(); | 
| -      } else { | 
| -        return canonical_list->raw(); | 
| -      } | 
| -    } | 
| - | 
| -   private: | 
| -    Zone* zone_; | 
| -    ArraySet canonical_lists_; | 
| -    Code& code_; | 
| -    Array& list_; | 
| -  }; | 
| - | 
| -  DedupListsVisitor visitor(Z); | 
| -  ProgramVisitor::VisitFunctions(&visitor); | 
| -} | 
| - | 
| - | 
| -void Precompiler::DedupInstructions() { | 
| -  class DedupInstructionsVisitor : public FunctionVisitor { | 
| -   public: | 
| -    explicit DedupInstructionsVisitor(Zone* zone) | 
| -        : zone_(zone), | 
| -          canonical_instructions_set_(), | 
| -          code_(Code::Handle(zone)), | 
| -          instructions_(Instructions::Handle(zone)) {} | 
| - | 
| -    void Visit(const Function& function) { | 
| -      if (!function.HasCode()) { | 
| -        ASSERT(function.HasImplicitClosureFunction()); | 
| -        return; | 
| -      } | 
| -      code_ = function.CurrentCode(); | 
| -      instructions_ = code_.instructions(); | 
| -      instructions_ = DedupOneInstructions(instructions_); | 
| -      code_.SetActiveInstructions(instructions_); | 
| -      code_.set_instructions(instructions_); | 
| -      function.SetInstructions(code_);  // Update cached entry point. | 
| -    } | 
| - | 
| -    RawInstructions* DedupOneInstructions(const Instructions& instructions) { | 
| -      const Instructions* canonical_instructions = | 
| -          canonical_instructions_set_.LookupValue(&instructions); | 
| -      if (canonical_instructions == NULL) { | 
| -        canonical_instructions_set_.Insert( | 
| -            &Instructions::ZoneHandle(zone_, instructions.raw())); | 
| -        return instructions.raw(); | 
| -      } else { | 
| -        return canonical_instructions->raw(); | 
| -      } | 
| -    } | 
| - | 
| -   private: | 
| -    Zone* zone_; | 
| -    InstructionsSet canonical_instructions_set_; | 
| -    Code& code_; | 
| -    Instructions& instructions_; | 
| -  }; | 
| - | 
| -  DedupInstructionsVisitor visitor(Z); | 
| -  ProgramVisitor::VisitFunctions(&visitor); | 
| -} | 
| - | 
| - | 
| void Precompiler::FinalizeAllClasses() { | 
| Library& lib = Library::Handle(Z); | 
| Class& cls = Class::Handle(Z); | 
|  |