• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifndef V8_COMPILER_COMPILATION_DEPENDENCIES_H_
6 #define V8_COMPILER_COMPILATION_DEPENDENCIES_H_
7 
8 #include "src/compiler/js-heap-broker.h"
9 #include "src/objects/objects.h"
10 #include "src/zone/zone-containers.h"
11 
12 namespace v8 {
13 namespace internal {
14 namespace compiler {
15 
16 class SlackTrackingPrediction {
17  public:
18   SlackTrackingPrediction(MapRef initial_map, int instance_size);
19 
inobject_property_count()20   int inobject_property_count() const { return inobject_property_count_; }
instance_size()21   int instance_size() const { return instance_size_; }
22 
23  private:
24   int instance_size_;
25   int inobject_property_count_;
26 };
27 
28 class CompilationDependency;
29 
30 // Collects and installs dependencies of the code that is being generated.
31 class V8_EXPORT_PRIVATE CompilationDependencies : public ZoneObject {
32  public:
33   CompilationDependencies(JSHeapBroker* broker, Zone* zone);
34 
35   V8_WARN_UNUSED_RESULT bool Commit(Handle<Code> code);
36 
37   // Return the initial map of {function} and record the assumption that it
38   // stays the initial map.
39   MapRef DependOnInitialMap(const JSFunctionRef& function);
40 
41   // Return the "prototype" property of the given function and record the
42   // assumption that it doesn't change.
43   ObjectRef DependOnPrototypeProperty(const JSFunctionRef& function);
44 
45   // Record the assumption that {map} stays stable.
46   void DependOnStableMap(const MapRef& map);
47 
48   // Depend on the fact that accessing property |property_name| from
49   // |receiver_map| yields the constant value |constant|, which is held by
50   // |holder|. Therefore, must be invalidated if |property_name| is added to any
51   // of the objects between receiver and |holder| on the prototype chain, b) any
52   // of the objects on the prototype chain up to |holder| change prototypes, or
53   // c) the value of |property_name| in |holder| changes.
54   // If PropertyKind is kData, |constant| is the value of the property in
55   // question. In case of PropertyKind::kAccessor, |constant| is the accessor
56   // function (i.e., getter or setter) itself, not the overall AccessorPair.
57   void DependOnConstantInDictionaryPrototypeChain(const MapRef& receiver_map,
58                                                   const NameRef& property_name,
59                                                   const ObjectRef& constant,
60                                                   PropertyKind kind);
61 
62   // Return the pretenure mode of {site} and record the assumption that it does
63   // not change.
64   AllocationType DependOnPretenureMode(const AllocationSiteRef& site);
65 
66   // Return a field's constness and, if kConst, record the assumption that it
67   // remains kConst. The field is identified by the arguments.
68   //
69   // For arrays, arguments objects and value wrappers, only consider the field
70   // kConst if the map is stable (and register stability dependency in that
71   // case).  This is to ensure that fast elements kind transitions cannot be
72   // used to mutate fields without deoptimization of the dependent code.
73   PropertyConstness DependOnFieldConstness(const MapRef& map,
74                                            InternalIndex descriptor);
75 
76   // Record the assumption that neither {cell}'s {CellType} changes, nor the
77   // {IsReadOnly()} flag of {cell}'s {PropertyDetails}.
78   void DependOnGlobalProperty(const PropertyCellRef& cell);
79 
80   // Return the validity of the given protector and, if true, record the
81   // assumption that the protector remains valid.
82   bool DependOnProtector(const PropertyCellRef& cell);
83 
84   // Convenience wrappers around {DependOnProtector}.
85   bool DependOnArrayBufferDetachingProtector();
86   bool DependOnArrayIteratorProtector();
87   bool DependOnArraySpeciesProtector();
88   bool DependOnNoElementsProtector();
89   bool DependOnPromiseHookProtector();
90   bool DependOnPromiseSpeciesProtector();
91   bool DependOnPromiseThenProtector();
92 
93   // Record the assumption that {site}'s {ElementsKind} doesn't change.
94   void DependOnElementsKind(const AllocationSiteRef& site);
95 
96   // Check that an object slot will not change during compilation.
97   void DependOnObjectSlotValue(const HeapObjectRef& object, int offset,
98                                const ObjectRef& value);
99 
100   void DependOnOwnConstantElement(const JSObjectRef& holder, uint32_t index,
101                                   const ObjectRef& element);
102 
103   // Record the assumption that the {value} read from {holder} at {index} on the
104   // background thread is the correct value for a given property.
105   void DependOnOwnConstantDataProperty(const JSObjectRef& holder,
106                                        const MapRef& map,
107                                        Representation representation,
108                                        FieldIndex index,
109                                        const ObjectRef& value);
110 
111   // Record the assumption that the {value} read from {holder} at {index} on the
112   // background thread is the correct value for a given dictionary property.
113   void DependOnOwnConstantDictionaryProperty(const JSObjectRef& holder,
114                                              InternalIndex index,
115                                              const ObjectRef& value);
116 
117   // For each given map, depend on the stability of (the maps of) all prototypes
118   // up to (and including) the {last_prototype}.
119   void DependOnStablePrototypeChains(
120       ZoneVector<MapRef> const& receiver_maps, WhereToStart start,
121       base::Optional<JSObjectRef> last_prototype =
122           base::Optional<JSObjectRef>());
123 
124   // Like DependOnElementsKind but also applies to all nested allocation sites.
125   void DependOnElementsKinds(const AllocationSiteRef& site);
126 
127   void DependOnConsistentJSFunctionView(const JSFunctionRef& function);
128 
129   // Predict the final instance size for {function}'s initial map and record
130   // the assumption that this prediction is correct. In addition, register
131   // the initial map dependency. This method returns the {function}'s the
132   // predicted minimum slack instance size count (wrapped together with
133   // the corresponding in-object property count for convenience).
134   SlackTrackingPrediction DependOnInitialMapInstanceSizePrediction(
135       const JSFunctionRef& function);
136 
137   // Records {dependency} if not null.
138   void RecordDependency(CompilationDependency const* dependency);
139 
140   // The methods below allow for gathering dependencies without actually
141   // recording them. They can be recorded at a later time via RecordDependency
142   // (or they can be ignored).
143 
144   // Gather the assumption that {target_map} can be transitioned to, i.e., that
145   // it does not become deprecated.
146   CompilationDependency const* TransitionDependencyOffTheRecord(
147       const MapRef& target_map) const;
148 
149   // Gather the assumption that the field representation of a field does not
150   // change. The field is identified by the arguments.
151   CompilationDependency const* FieldRepresentationDependencyOffTheRecord(
152       const MapRef& map, InternalIndex descriptor,
153       Representation representation) const;
154 
155   // Gather the assumption that the field type of a field does not change. The
156   // field is identified by the arguments.
157   CompilationDependency const* FieldTypeDependencyOffTheRecord(
158       const MapRef& map, InternalIndex descriptor,
159       const ObjectRef& /* Contains a FieldType underneath. */ type) const;
160 
161 #ifdef DEBUG
162   static bool IsFieldRepresentationDependencyOnMap(
163       const CompilationDependency* dep, const Handle<Map>& receiver_map);
164 #endif  // DEBUG
165 
166   struct CompilationDependencyHash {
167     size_t operator()(const CompilationDependency* dep) const;
168   };
169   struct CompilationDependencyEqual {
170     bool operator()(const CompilationDependency* lhs,
171                     const CompilationDependency* rhs) const;
172   };
173 
174  private:
175   bool PrepareInstall();
176   bool PrepareInstallPredictable();
177 
178   using CompilationDependencySet =
179       ZoneUnorderedSet<const CompilationDependency*, CompilationDependencyHash,
180                        CompilationDependencyEqual>;
181 
182   Zone* const zone_;
183   JSHeapBroker* const broker_;
184   CompilationDependencySet dependencies_;
185 };
186 
187 }  // namespace compiler
188 }  // namespace internal
189 }  // namespace v8
190 
191 #endif  // V8_COMPILER_COMPILATION_DEPENDENCIES_H_
192