Home | History | Annotate | Download | only in src
      1 // Copyright 2015 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "src/compilation-dependencies.h"
      6 
      7 #include "src/factory.h"
      8 #include "src/handles-inl.h"
      9 #include "src/isolate.h"
     10 #include "src/objects-inl.h"
     11 #include "src/zone/zone.h"
     12 
     13 namespace v8 {
     14 namespace internal {
     15 
     16 DependentCode* CompilationDependencies::Get(Handle<Object> object) {
     17   if (object->IsMap()) {
     18     return Handle<Map>::cast(object)->dependent_code();
     19   } else if (object->IsPropertyCell()) {
     20     return Handle<PropertyCell>::cast(object)->dependent_code();
     21   } else if (object->IsAllocationSite()) {
     22     return Handle<AllocationSite>::cast(object)->dependent_code();
     23   }
     24   UNREACHABLE();
     25   return nullptr;
     26 }
     27 
     28 
     29 void CompilationDependencies::Set(Handle<Object> object,
     30                                   Handle<DependentCode> dep) {
     31   if (object->IsMap()) {
     32     Handle<Map>::cast(object)->set_dependent_code(*dep);
     33   } else if (object->IsPropertyCell()) {
     34     Handle<PropertyCell>::cast(object)->set_dependent_code(*dep);
     35   } else if (object->IsAllocationSite()) {
     36     Handle<AllocationSite>::cast(object)->set_dependent_code(*dep);
     37   } else {
     38     UNREACHABLE();
     39   }
     40 }
     41 
     42 
     43 void CompilationDependencies::Insert(DependentCode::DependencyGroup group,
     44                                      Handle<HeapObject> object) {
     45   if (groups_[group] == nullptr) {
     46     groups_[group] = new (zone_) ZoneList<Handle<HeapObject>>(2, zone_);
     47   }
     48   groups_[group]->Add(object, zone_);
     49 
     50   if (object_wrapper_.is_null()) {
     51     // Allocate the wrapper if necessary.
     52     object_wrapper_ =
     53         isolate_->factory()->NewForeign(reinterpret_cast<Address>(this));
     54   }
     55 
     56   // Get the old dependent code list.
     57   Handle<DependentCode> old_dependent_code =
     58       Handle<DependentCode>(Get(object), isolate_);
     59   Handle<DependentCode> new_dependent_code =
     60       DependentCode::InsertCompilationDependencies(old_dependent_code, group,
     61                                                    object_wrapper_);
     62 
     63   // Set the new dependent code list if the head of the list changed.
     64   if (!new_dependent_code.is_identical_to(old_dependent_code)) {
     65     Set(object, new_dependent_code);
     66   }
     67 }
     68 
     69 
     70 void CompilationDependencies::Commit(Handle<Code> code) {
     71   if (IsEmpty()) return;
     72 
     73   DCHECK(!object_wrapper_.is_null());
     74   Handle<WeakCell> cell = Code::WeakCellFor(code);
     75   AllowDeferredHandleDereference get_wrapper;
     76   for (int i = 0; i < DependentCode::kGroupCount; i++) {
     77     ZoneList<Handle<HeapObject>>* group_objects = groups_[i];
     78     if (group_objects == nullptr) continue;
     79     DependentCode::DependencyGroup group =
     80         static_cast<DependentCode::DependencyGroup>(i);
     81     for (int j = 0; j < group_objects->length(); j++) {
     82       DependentCode* dependent_code = Get(group_objects->at(j));
     83       dependent_code->UpdateToFinishedCode(group, *object_wrapper_, *cell);
     84     }
     85     groups_[i] = nullptr;  // Zone-allocated, no need to delete.
     86   }
     87 }
     88 
     89 
     90 void CompilationDependencies::Rollback() {
     91   if (IsEmpty()) return;
     92 
     93   AllowDeferredHandleDereference get_wrapper;
     94   // Unregister from all dependent maps if not yet committed.
     95   for (int i = 0; i < DependentCode::kGroupCount; i++) {
     96     ZoneList<Handle<HeapObject>>* group_objects = groups_[i];
     97     if (group_objects == nullptr) continue;
     98     DependentCode::DependencyGroup group =
     99         static_cast<DependentCode::DependencyGroup>(i);
    100     for (int j = 0; j < group_objects->length(); j++) {
    101       DependentCode* dependent_code = Get(group_objects->at(j));
    102       dependent_code->RemoveCompilationDependencies(group, *object_wrapper_);
    103     }
    104     groups_[i] = nullptr;  // Zone-allocated, no need to delete.
    105   }
    106 }
    107 
    108 
    109 void CompilationDependencies::AssumeMapNotDeprecated(Handle<Map> map) {
    110   DCHECK(!map->is_deprecated());
    111   // Do nothing if the map cannot be deprecated.
    112   if (map->CanBeDeprecated()) {
    113     Insert(DependentCode::kTransitionGroup, map);
    114   }
    115 }
    116 
    117 
    118 void CompilationDependencies::AssumeMapStable(Handle<Map> map) {
    119   DCHECK(map->is_stable());
    120   // Do nothing if the map cannot transition.
    121   if (map->CanTransition()) {
    122     Insert(DependentCode::kPrototypeCheckGroup, map);
    123   }
    124 }
    125 
    126 
    127 void CompilationDependencies::AssumePrototypeMapsStable(
    128     Handle<Map> map, MaybeHandle<JSReceiver> prototype) {
    129   for (PrototypeIterator i(map); !i.IsAtEnd(); i.Advance()) {
    130     Handle<JSReceiver> const current =
    131         PrototypeIterator::GetCurrent<JSReceiver>(i);
    132     AssumeMapStable(handle(current->map()));
    133     Handle<JSReceiver> last;
    134     if (prototype.ToHandle(&last) && last.is_identical_to(current)) {
    135       break;
    136     }
    137   }
    138 }
    139 
    140 
    141 void CompilationDependencies::AssumeTransitionStable(
    142     Handle<AllocationSite> site) {
    143   // Do nothing if the object doesn't have any useful element transitions left.
    144   ElementsKind kind =
    145       site->SitePointsToLiteral()
    146           ? JSObject::cast(site->transition_info())->GetElementsKind()
    147           : site->GetElementsKind();
    148   if (AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE) {
    149     Insert(DependentCode::kAllocationSiteTransitionChangedGroup, site);
    150   }
    151 }
    152 
    153 }  // namespace internal
    154 }  // namespace v8
    155