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_JS_NATIVE_CONTEXT_SPECIALIZATION_H_ 6 #define V8_COMPILER_JS_NATIVE_CONTEXT_SPECIALIZATION_H_ 7 8 #include "src/base/flags.h" 9 #include "src/compiler/graph-reducer.h" 10 #include "src/compiler/js-heap-broker.h" 11 #include "src/deoptimizer/deoptimize-reason.h" 12 #include "src/objects/map.h" 13 14 namespace v8 { 15 namespace internal { 16 17 // Forward declarations. 18 class Factory; 19 class JSGlobalObject; 20 class JSGlobalProxy; 21 class StringConstantBase; 22 23 namespace compiler { 24 25 // Forward declarations. 26 enum class AccessMode; 27 class CommonOperatorBuilder; 28 class CompilationDependencies; 29 class ElementAccessInfo; 30 class JSGraph; 31 class JSHeapBroker; 32 class JSOperatorBuilder; 33 class MachineOperatorBuilder; 34 class PropertyAccessInfo; 35 class SimplifiedOperatorBuilder; 36 class TypeCache; 37 38 // Specializes a given JSGraph to a given native context, potentially constant 39 // folding some {LoadGlobal} nodes or strength reducing some {StoreGlobal} 40 // nodes. And also specializes {LoadNamed} and {StoreNamed} nodes according 41 // to type feedback (if available). 42 class V8_EXPORT_PRIVATE JSNativeContextSpecialization final 43 : public AdvancedReducer { 44 public: 45 // Flags that control the mode of operation. 46 enum Flag { 47 kNoFlags = 0u, 48 kBailoutOnUninitialized = 1u << 0, 49 }; 50 using Flags = base::Flags<Flag>; 51 52 JSNativeContextSpecialization(Editor* editor, JSGraph* jsgraph, 53 JSHeapBroker* broker, Flags flags, 54 CompilationDependencies* dependencies, 55 Zone* zone, Zone* shared_zone); 56 JSNativeContextSpecialization(const JSNativeContextSpecialization&) = delete; 57 JSNativeContextSpecialization& operator=( 58 const JSNativeContextSpecialization&) = delete; 59 reducer_name()60 const char* reducer_name() const override { 61 return "JSNativeContextSpecialization"; 62 } 63 64 Reduction Reduce(Node* node) final; 65 66 // Utility for folding string constant concatenation. 67 // Supports JSAdd nodes and nodes typed as string or number. 68 // Public for the sake of unit testing. 69 static base::Optional<size_t> GetMaxStringLength(JSHeapBroker* broker, 70 Node* node); 71 72 private: 73 Reduction ReduceJSAdd(Node* node); 74 Reduction ReduceJSAsyncFunctionEnter(Node* node); 75 Reduction ReduceJSAsyncFunctionReject(Node* node); 76 Reduction ReduceJSAsyncFunctionResolve(Node* node); 77 Reduction ReduceJSGetSuperConstructor(Node* node); 78 Reduction ReduceJSInstanceOf(Node* node); 79 Reduction ReduceJSHasInPrototypeChain(Node* node); 80 Reduction ReduceJSOrdinaryHasInstance(Node* node); 81 Reduction ReduceJSPromiseResolve(Node* node); 82 Reduction ReduceJSResolvePromise(Node* node); 83 Reduction ReduceJSLoadGlobal(Node* node); 84 Reduction ReduceJSStoreGlobal(Node* node); 85 Reduction ReduceJSLoadNamed(Node* node); 86 Reduction ReduceJSLoadNamedFromSuper(Node* node); 87 Reduction ReduceJSGetIterator(Node* node); 88 Reduction ReduceJSStoreNamed(Node* node); 89 Reduction ReduceJSHasProperty(Node* node); 90 Reduction ReduceJSLoadProperty(Node* node); 91 Reduction ReduceJSStoreProperty(Node* node); 92 Reduction ReduceJSStoreNamedOwn(Node* node); 93 Reduction ReduceJSStoreDataPropertyInLiteral(Node* node); 94 Reduction ReduceJSStoreInArrayLiteral(Node* node); 95 Reduction ReduceJSToObject(Node* node); 96 97 Reduction ReduceElementAccess(Node* node, Node* index, Node* value, 98 ElementAccessFeedback const& feedback); 99 // In the case of non-keyed (named) accesses, pass the name as {static_name} 100 // and use {nullptr} for {key} (load/store modes are irrelevant). 101 Reduction ReducePropertyAccess(Node* node, Node* key, 102 base::Optional<NameRef> static_name, 103 Node* value, FeedbackSource const& source, 104 AccessMode access_mode); 105 Reduction ReduceNamedAccess(Node* node, Node* value, 106 NamedAccessFeedback const& feedback, 107 AccessMode access_mode, Node* key = nullptr); 108 Reduction ReduceMinimorphicPropertyAccess( 109 Node* node, Node* value, 110 MinimorphicLoadPropertyAccessFeedback const& feedback, 111 FeedbackSource const& source); 112 Reduction ReduceGlobalAccess(Node* node, Node* lookup_start_object, 113 Node* receiver, Node* value, NameRef const& name, 114 AccessMode access_mode, Node* key = nullptr, 115 Node* effect = nullptr); 116 Reduction ReduceGlobalAccess(Node* node, Node* lookup_start_object, 117 Node* receiver, Node* value, NameRef const& name, 118 AccessMode access_mode, Node* key, 119 PropertyCellRef const& property_cell, 120 Node* effect = nullptr); 121 Reduction ReduceElementLoadFromHeapConstant(Node* node, Node* key, 122 AccessMode access_mode, 123 KeyedAccessLoadMode load_mode); 124 Reduction ReduceElementAccessOnString(Node* node, Node* index, Node* value, 125 KeyedAccessMode const& keyed_mode); 126 127 Reduction ReduceSoftDeoptimize(Node* node, DeoptimizeReason reason); 128 Reduction ReduceJSToString(Node* node); 129 130 Reduction ReduceJSLoadPropertyWithEnumeratedKey(Node* node); 131 132 const StringConstantBase* CreateDelayedStringConstant(Node* node); 133 134 // A triple of nodes that represents a continuation. 135 class ValueEffectControl final { 136 public: ValueEffectControl()137 ValueEffectControl() 138 : value_(nullptr), effect_(nullptr), control_(nullptr) {} ValueEffectControl(Node * value,Node * effect,Node * control)139 ValueEffectControl(Node* value, Node* effect, Node* control) 140 : value_(value), effect_(effect), control_(control) {} 141 value()142 Node* value() const { return value_; } effect()143 Node* effect() const { return effect_; } control()144 Node* control() const { return control_; } 145 146 private: 147 Node* value_; 148 Node* effect_; 149 Node* control_; 150 }; 151 152 // Construct the appropriate subgraph for property access. 153 ValueEffectControl BuildPropertyAccess( 154 Node* lookup_start_object, Node* receiver, Node* value, Node* context, 155 Node* frame_state, Node* effect, Node* control, NameRef const& name, 156 ZoneVector<Node*>* if_exceptions, PropertyAccessInfo const& access_info, 157 AccessMode access_mode); 158 ValueEffectControl BuildPropertyLoad(Node* lookup_start_object, 159 Node* receiver, Node* context, 160 Node* frame_state, Node* effect, 161 Node* control, NameRef const& name, 162 ZoneVector<Node*>* if_exceptions, 163 PropertyAccessInfo const& access_info); 164 165 ValueEffectControl BuildPropertyStore(Node* receiver, Node* value, 166 Node* context, Node* frame_state, 167 Node* effect, Node* control, 168 NameRef const& name, 169 ZoneVector<Node*>* if_exceptions, 170 PropertyAccessInfo const& access_info, 171 AccessMode access_mode); 172 173 ValueEffectControl BuildPropertyTest(Node* effect, Node* control, 174 PropertyAccessInfo const& access_info); 175 176 // Helpers for accessor inlining. 177 Node* InlinePropertyGetterCall(Node* receiver, Node* context, 178 Node* frame_state, Node** effect, 179 Node** control, 180 ZoneVector<Node*>* if_exceptions, 181 PropertyAccessInfo const& access_info); 182 void InlinePropertySetterCall(Node* receiver, Node* value, Node* context, 183 Node* frame_state, Node** effect, 184 Node** control, 185 ZoneVector<Node*>* if_exceptions, 186 PropertyAccessInfo const& access_info); 187 Node* InlineApiCall(Node* receiver, Node* holder, Node* frame_state, 188 Node* value, Node** effect, Node** control, 189 SharedFunctionInfoRef const& shared_info, 190 FunctionTemplateInfoRef const& function_template_info); 191 192 // Construct the appropriate subgraph for element access. 193 ValueEffectControl BuildElementAccess(Node* receiver, Node* index, 194 Node* value, Node* effect, 195 Node* control, 196 ElementAccessInfo const& access_info, 197 KeyedAccessMode const& keyed_mode); 198 199 // Construct appropriate subgraph to load from a String. 200 Node* BuildIndexedStringLoad(Node* receiver, Node* index, Node* length, 201 Node** effect, Node** control, 202 KeyedAccessLoadMode load_mode); 203 204 // Construct appropriate subgraph to extend properties backing store. 205 Node* BuildExtendPropertiesBackingStore(const MapRef& map, Node* properties, 206 Node* effect, Node* control); 207 208 // Construct appropriate subgraph to check that the {value} matches 209 // the previously recorded {name} feedback. 210 Node* BuildCheckEqualsName(NameRef const& name, Node* value, Node* effect, 211 Node* control); 212 213 // Checks if we can turn the hole into undefined when loading an element 214 // from an object with one of the {receiver_maps}; sets up appropriate 215 // code dependencies and might use the array protector cell. 216 bool CanTreatHoleAsUndefined(ZoneVector<Handle<Map>> const& receiver_maps); 217 218 void RemoveImpossibleMaps(Node* object, ZoneVector<Handle<Map>>* maps) const; 219 220 ElementAccessFeedback const& TryRefineElementAccessFeedback( 221 ElementAccessFeedback const& feedback, Node* receiver, 222 Node* effect) const; 223 224 // Try to infer maps for the given {object} at the current {effect}. 225 bool InferMaps(Node* object, Node* effect, 226 ZoneVector<Handle<Map>>* maps) const; 227 228 // Try to infer a root map for the {object} independent of the current program 229 // location. 230 base::Optional<MapRef> InferRootMap(Node* object) const; 231 232 // Checks if we know at compile time that the {receiver} either definitely 233 // has the {prototype} in it's prototype chain, or the {receiver} definitely 234 // doesn't have the {prototype} in it's prototype chain. 235 enum InferHasInPrototypeChainResult { 236 kIsInPrototypeChain, 237 kIsNotInPrototypeChain, 238 kMayBeInPrototypeChain 239 }; 240 InferHasInPrototypeChainResult InferHasInPrototypeChain( 241 Node* receiver, Node* effect, HeapObjectRef const& prototype); 242 243 Node* BuildLoadPrototypeFromObject(Node* object, Node* effect, Node* control); 244 245 Graph* graph() const; jsgraph()246 JSGraph* jsgraph() const { return jsgraph_; } 247 broker()248 JSHeapBroker* broker() const { return broker_; } 249 Isolate* isolate() const; 250 Factory* factory() const; 251 CommonOperatorBuilder* common() const; 252 JSOperatorBuilder* javascript() const; 253 SimplifiedOperatorBuilder* simplified() const; flags()254 Flags flags() const { return flags_; } global_object()255 Handle<JSGlobalObject> global_object() const { return global_object_; } global_proxy()256 Handle<JSGlobalProxy> global_proxy() const { return global_proxy_; } native_context()257 NativeContextRef native_context() const { 258 return broker()->target_native_context(); 259 } dependencies()260 CompilationDependencies* dependencies() const { return dependencies_; } zone()261 Zone* zone() const { return zone_; } shared_zone()262 Zone* shared_zone() const { return shared_zone_; } 263 bool should_disallow_heap_access() const; 264 265 JSGraph* const jsgraph_; 266 JSHeapBroker* const broker_; 267 Flags const flags_; 268 Handle<JSGlobalObject> global_object_; 269 Handle<JSGlobalProxy> global_proxy_; 270 CompilationDependencies* const dependencies_; 271 Zone* const zone_; 272 Zone* const shared_zone_; 273 TypeCache const* type_cache_; 274 }; 275 276 DEFINE_OPERATORS_FOR_FLAGS(JSNativeContextSpecialization::Flags) 277 278 } // namespace compiler 279 } // namespace internal 280 } // namespace v8 281 282 #endif // V8_COMPILER_JS_NATIVE_CONTEXT_SPECIALIZATION_H_ 283