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/deoptimize-reason.h" 11 #include "src/objects/map.h" 12 13 namespace v8 { 14 namespace internal { 15 16 // Forward declarations. 17 class Factory; 18 class FeedbackNexus; 19 20 namespace compiler { 21 22 // Forward declarations. 23 enum class AccessMode; 24 class CommonOperatorBuilder; 25 class CompilationDependencies; 26 class ElementAccessInfo; 27 class JSGraph; 28 class JSHeapBroker; 29 class JSOperatorBuilder; 30 class MachineOperatorBuilder; 31 class PropertyAccessInfo; 32 class SimplifiedOperatorBuilder; 33 class TypeCache; 34 35 // Specializes a given JSGraph to a given native context, potentially constant 36 // folding some {LoadGlobal} nodes or strength reducing some {StoreGlobal} 37 // nodes. And also specializes {LoadNamed} and {StoreNamed} nodes according 38 // to type feedback (if available). 39 class JSNativeContextSpecialization final : public AdvancedReducer { 40 public: 41 // Flags that control the mode of operation. 42 enum Flag { 43 kNoFlags = 0u, 44 kAccessorInliningEnabled = 1u << 0, 45 kBailoutOnUninitialized = 1u << 1 46 }; 47 typedef base::Flags<Flag> Flags; 48 49 JSNativeContextSpecialization(Editor* editor, JSGraph* jsgraph, 50 JSHeapBroker* js_heap_broker, Flags flags, 51 Handle<Context> native_context, 52 CompilationDependencies* dependencies, 53 Zone* zone); 54 reducer_name()55 const char* reducer_name() const override { 56 return "JSNativeContextSpecialization"; 57 } 58 59 Reduction Reduce(Node* node) final; 60 61 private: 62 Reduction ReduceJSAdd(Node* node); 63 Reduction ReduceJSGetSuperConstructor(Node* node); 64 Reduction ReduceJSInstanceOf(Node* node); 65 Reduction ReduceJSHasInPrototypeChain(Node* node); 66 Reduction ReduceJSOrdinaryHasInstance(Node* node); 67 Reduction ReduceJSPromiseResolve(Node* node); 68 Reduction ReduceJSResolvePromise(Node* node); 69 Reduction ReduceJSLoadContext(Node* node); 70 Reduction ReduceJSLoadGlobal(Node* node); 71 Reduction ReduceJSStoreGlobal(Node* node); 72 Reduction ReduceJSLoadNamed(Node* node); 73 Reduction ReduceJSStoreNamed(Node* node); 74 Reduction ReduceJSLoadProperty(Node* node); 75 Reduction ReduceJSStoreProperty(Node* node); 76 Reduction ReduceJSStoreNamedOwn(Node* node); 77 Reduction ReduceJSStoreDataPropertyInLiteral(Node* node); 78 Reduction ReduceJSStoreInArrayLiteral(Node* node); 79 Reduction ReduceJSToObject(Node* node); 80 81 Reduction ReduceElementAccess(Node* node, Node* index, Node* value, 82 MapHandles const& receiver_maps, 83 AccessMode access_mode, 84 KeyedAccessLoadMode load_mode, 85 KeyedAccessStoreMode store_mode); 86 Reduction ReduceKeyedAccess(Node* node, Node* index, Node* value, 87 FeedbackNexus const& nexus, 88 AccessMode access_mode, 89 KeyedAccessLoadMode load_mode, 90 KeyedAccessStoreMode store_mode); 91 Reduction ReduceNamedAccessFromNexus(Node* node, Node* value, 92 FeedbackNexus const& nexus, 93 Handle<Name> name, 94 AccessMode access_mode); 95 Reduction ReduceNamedAccess(Node* node, Node* value, 96 MapHandles const& receiver_maps, 97 Handle<Name> name, AccessMode access_mode, 98 Node* index = nullptr); 99 Reduction ReduceGlobalAccess(Node* node, Node* receiver, Node* value, 100 Handle<Name> name, AccessMode access_mode, 101 Node* index = nullptr); 102 103 Reduction ReduceSoftDeoptimize(Node* node, DeoptimizeReason reason); 104 105 // A triple of nodes that represents a continuation. 106 class ValueEffectControl final { 107 public: ValueEffectControl()108 ValueEffectControl() 109 : value_(nullptr), effect_(nullptr), control_(nullptr) {} ValueEffectControl(Node * value,Node * effect,Node * control)110 ValueEffectControl(Node* value, Node* effect, Node* control) 111 : value_(value), effect_(effect), control_(control) {} 112 value()113 Node* value() const { return value_; } effect()114 Node* effect() const { return effect_; } control()115 Node* control() const { return control_; } 116 117 private: 118 Node* value_; 119 Node* effect_; 120 Node* control_; 121 }; 122 123 // Construct the appropriate subgraph for property access. 124 ValueEffectControl BuildPropertyAccess(Node* receiver, Node* value, 125 Node* context, Node* frame_state, 126 Node* effect, Node* control, 127 Handle<Name> name, 128 ZoneVector<Node*>* if_exceptions, 129 PropertyAccessInfo const& access_info, 130 AccessMode access_mode); 131 ValueEffectControl BuildPropertyLoad(Node* receiver, Node* context, 132 Node* frame_state, Node* effect, 133 Node* control, Handle<Name> name, 134 ZoneVector<Node*>* if_exceptions, 135 PropertyAccessInfo const& access_info); 136 137 ValueEffectControl BuildPropertyStore(Node* receiver, Node* value, 138 Node* context, Node* frame_state, 139 Node* effect, Node* control, 140 Handle<Name> name, 141 ZoneVector<Node*>* if_exceptions, 142 PropertyAccessInfo const& access_info, 143 AccessMode access_mode); 144 145 // Helpers for accessor inlining. 146 Node* InlinePropertyGetterCall(Node* receiver, Node* context, 147 Node* frame_state, Node** effect, 148 Node** control, 149 ZoneVector<Node*>* if_exceptions, 150 PropertyAccessInfo const& access_info); 151 void InlinePropertySetterCall(Node* receiver, Node* value, Node* context, 152 Node* frame_state, Node** effect, 153 Node** control, 154 ZoneVector<Node*>* if_exceptions, 155 PropertyAccessInfo const& access_info); 156 Node* InlineApiCall(Node* receiver, Node* holder, Node* frame_state, 157 Node* value, Node** effect, Node** control, 158 Handle<SharedFunctionInfo> shared_info, 159 Handle<FunctionTemplateInfo> function_template_info); 160 161 // Construct the appropriate subgraph for element access. 162 ValueEffectControl BuildElementAccess( 163 Node* receiver, Node* index, Node* value, Node* effect, Node* control, 164 ElementAccessInfo const& access_info, AccessMode access_mode, 165 KeyedAccessLoadMode load_mode, KeyedAccessStoreMode store_mode); 166 167 // Construct appropriate subgraph to load from a String. 168 Node* BuildIndexedStringLoad(Node* receiver, Node* index, Node* length, 169 Node** effect, Node** control, 170 KeyedAccessLoadMode load_mode); 171 172 // Construct appropriate subgraph to extend properties backing store. 173 Node* BuildExtendPropertiesBackingStore(Handle<Map> map, Node* properties, 174 Node* effect, Node* control); 175 176 // Construct appropriate subgraph to check that the {value} matches 177 // the previously recorded {name} feedback. 178 Node* BuildCheckEqualsName(Handle<Name> name, Node* value, Node* effect, 179 Node* control); 180 181 // Checks if we can turn the hole into undefined when loading an element 182 // from an object with one of the {receiver_maps}; sets up appropriate 183 // code dependencies and might use the array protector cell. 184 bool CanTreatHoleAsUndefined(MapHandles const& receiver_maps); 185 186 // Extract receiver maps from {nexus} and filter based on {receiver} if 187 // possible. 188 bool ExtractReceiverMaps(Node* receiver, Node* effect, 189 FeedbackNexus const& nexus, 190 MapHandles* receiver_maps); 191 192 // Try to infer maps for the given {receiver} at the current {effect}. 193 // If maps are returned then you can be sure that the {receiver} definitely 194 // has one of the returned maps at this point in the program (identified 195 // by {effect}). 196 bool InferReceiverMaps(Node* receiver, Node* effect, 197 MapHandles* receiver_maps); 198 // Try to infer a root map for the {receiver} independent of the current 199 // program location. 200 MaybeHandle<Map> InferReceiverRootMap(Node* receiver); 201 202 // Checks if we know at compile time that the {receiver} either definitely 203 // has the {prototype} in it's prototype chain, or the {receiver} definitely 204 // doesn't have the {prototype} in it's prototype chain. 205 enum InferHasInPrototypeChainResult { 206 kIsInPrototypeChain, 207 kIsNotInPrototypeChain, 208 kMayBeInPrototypeChain 209 }; 210 InferHasInPrototypeChainResult InferHasInPrototypeChain( 211 Node* receiver, Node* effect, Handle<HeapObject> prototype); 212 213 // Script context lookup logic. 214 struct ScriptContextTableLookupResult; 215 bool LookupInScriptContextTable(Handle<Name> name, 216 ScriptContextTableLookupResult* result); 217 218 Graph* graph() const; jsgraph()219 JSGraph* jsgraph() const { return jsgraph_; } 220 js_heap_broker()221 JSHeapBroker* js_heap_broker() const { return js_heap_broker_; } 222 Isolate* isolate() const; 223 Factory* factory() const; 224 CommonOperatorBuilder* common() const; 225 JSOperatorBuilder* javascript() const; 226 SimplifiedOperatorBuilder* simplified() const; flags()227 Flags flags() const { return flags_; } global_object()228 Handle<JSGlobalObject> global_object() const { return global_object_; } global_proxy()229 Handle<JSGlobalProxy> global_proxy() const { return global_proxy_; } native_context()230 const NativeContextRef& native_context() const { return native_context_; } dependencies()231 CompilationDependencies* dependencies() const { return dependencies_; } zone()232 Zone* zone() const { return zone_; } 233 234 JSGraph* const jsgraph_; 235 JSHeapBroker* const js_heap_broker_; 236 Flags const flags_; 237 Handle<JSGlobalObject> global_object_; 238 Handle<JSGlobalProxy> global_proxy_; 239 NativeContextRef native_context_; 240 CompilationDependencies* const dependencies_; 241 Zone* const zone_; 242 TypeCache const& type_cache_; 243 244 DISALLOW_COPY_AND_ASSIGN(JSNativeContextSpecialization); 245 }; 246 247 DEFINE_OPERATORS_FOR_FLAGS(JSNativeContextSpecialization::Flags) 248 249 } // namespace compiler 250 } // namespace internal 251 } // namespace v8 252 253 #endif // V8_COMPILER_JS_NATIVE_CONTEXT_SPECIALIZATION_H_ 254