| OLD | NEW |
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/compiler/js-native-context-specialization.h" | 5 #include "src/compiler/js-native-context-specialization.h" |
| 6 | 6 |
| 7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
| 8 #include "src/code-factory.h" | 8 #include "src/code-factory.h" |
| 9 #include "src/compilation-dependencies.h" | 9 #include "src/compilation-dependencies.h" |
| 10 #include "src/compiler/access-builder.h" | 10 #include "src/compiler/access-builder.h" |
| 11 #include "src/compiler/js-graph.h" | 11 #include "src/compiler/js-graph.h" |
| 12 #include "src/compiler/js-operator.h" | 12 #include "src/compiler/js-operator.h" |
| 13 #include "src/compiler/linkage.h" | 13 #include "src/compiler/linkage.h" |
| 14 #include "src/compiler/node-matchers.h" | 14 #include "src/compiler/node-matchers.h" |
| 15 #include "src/contexts.h" | |
| 16 #include "src/field-index-inl.h" | 15 #include "src/field-index-inl.h" |
| 17 #include "src/lookup.h" | |
| 18 #include "src/objects-inl.h" // TODO(mstarzinger): Temporary cycle breaker! | 16 #include "src/objects-inl.h" // TODO(mstarzinger): Temporary cycle breaker! |
| 19 #include "src/type-cache.h" | 17 #include "src/type-cache.h" |
| 20 #include "src/type-feedback-vector.h" | 18 #include "src/type-feedback-vector.h" |
| 21 | 19 |
| 22 namespace v8 { | 20 namespace v8 { |
| 23 namespace internal { | 21 namespace internal { |
| 24 namespace compiler { | 22 namespace compiler { |
| 25 | 23 |
| 26 struct JSNativeContextSpecialization::ScriptContextTableLookupResult { | |
| 27 Handle<Context> context; | |
| 28 bool immutable; | |
| 29 int index; | |
| 30 }; | |
| 31 | |
| 32 | |
| 33 JSNativeContextSpecialization::JSNativeContextSpecialization( | 24 JSNativeContextSpecialization::JSNativeContextSpecialization( |
| 34 Editor* editor, JSGraph* jsgraph, Flags flags, | 25 Editor* editor, JSGraph* jsgraph, Flags flags, |
| 35 Handle<JSGlobalObject> global_object, CompilationDependencies* dependencies, | 26 Handle<Context> native_context, CompilationDependencies* dependencies, |
| 36 Zone* zone) | 27 Zone* zone) |
| 37 : AdvancedReducer(editor), | 28 : AdvancedReducer(editor), |
| 38 jsgraph_(jsgraph), | 29 jsgraph_(jsgraph), |
| 39 flags_(flags), | 30 flags_(flags), |
| 40 global_object_(global_object), | 31 native_context_(native_context), |
| 41 native_context_(global_object->native_context(), isolate()), | |
| 42 dependencies_(dependencies), | 32 dependencies_(dependencies), |
| 43 zone_(zone), | 33 zone_(zone), |
| 44 type_cache_(TypeCache::Get()), | 34 type_cache_(TypeCache::Get()), |
| 45 access_info_factory_(dependencies, native_context(), graph()->zone()) {} | 35 access_info_factory_(dependencies, native_context, graph()->zone()) {} |
| 46 | 36 |
| 47 | 37 |
| 48 Reduction JSNativeContextSpecialization::Reduce(Node* node) { | 38 Reduction JSNativeContextSpecialization::Reduce(Node* node) { |
| 49 switch (node->opcode()) { | 39 switch (node->opcode()) { |
| 50 case IrOpcode::kJSCallFunction: | 40 case IrOpcode::kJSCallFunction: |
| 51 return ReduceJSCallFunction(node); | 41 return ReduceJSCallFunction(node); |
| 52 case IrOpcode::kJSLoadGlobal: | |
| 53 return ReduceJSLoadGlobal(node); | |
| 54 case IrOpcode::kJSStoreGlobal: | |
| 55 return ReduceJSStoreGlobal(node); | |
| 56 case IrOpcode::kJSLoadNamed: | 42 case IrOpcode::kJSLoadNamed: |
| 57 return ReduceJSLoadNamed(node); | 43 return ReduceJSLoadNamed(node); |
| 58 case IrOpcode::kJSStoreNamed: | 44 case IrOpcode::kJSStoreNamed: |
| 59 return ReduceJSStoreNamed(node); | 45 return ReduceJSStoreNamed(node); |
| 60 case IrOpcode::kJSLoadProperty: | 46 case IrOpcode::kJSLoadProperty: |
| 61 return ReduceJSLoadProperty(node); | 47 return ReduceJSLoadProperty(node); |
| 62 case IrOpcode::kJSStoreProperty: | 48 case IrOpcode::kJSStoreProperty: |
| 63 return ReduceJSStoreProperty(node); | 49 return ReduceJSStoreProperty(node); |
| 64 default: | 50 default: |
| 65 break; | 51 break; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 83 if (HeapObjectMatcher(target).HasValue()) return NoChange(); | 69 if (HeapObjectMatcher(target).HasValue()) return NoChange(); |
| 84 if (!p.feedback().IsValid()) return NoChange(); | 70 if (!p.feedback().IsValid()) return NoChange(); |
| 85 CallICNexus nexus(p.feedback().vector(), p.feedback().slot()); | 71 CallICNexus nexus(p.feedback().vector(), p.feedback().slot()); |
| 86 Handle<Object> feedback(nexus.GetFeedback(), isolate()); | 72 Handle<Object> feedback(nexus.GetFeedback(), isolate()); |
| 87 if (feedback->IsWeakCell()) { | 73 if (feedback->IsWeakCell()) { |
| 88 Handle<WeakCell> cell = Handle<WeakCell>::cast(feedback); | 74 Handle<WeakCell> cell = Handle<WeakCell>::cast(feedback); |
| 89 if (cell->value()->IsJSFunction()) { | 75 if (cell->value()->IsJSFunction()) { |
| 90 // Avoid cross-context leaks, meaning don't embed references to functions | 76 // Avoid cross-context leaks, meaning don't embed references to functions |
| 91 // in other native contexts. | 77 // in other native contexts. |
| 92 Handle<JSFunction> function(JSFunction::cast(cell->value()), isolate()); | 78 Handle<JSFunction> function(JSFunction::cast(cell->value()), isolate()); |
| 93 if (function->context()->native_context() != | 79 if (function->context()->native_context() != *native_context()) { |
| 94 global_object()->native_context()) { | |
| 95 return NoChange(); | 80 return NoChange(); |
| 96 } | 81 } |
| 97 | 82 |
| 98 // Check that the {target} is still the {target_function}. | 83 // Check that the {target} is still the {target_function}. |
| 99 Node* target_function = jsgraph()->HeapConstant(function); | 84 Node* target_function = jsgraph()->HeapConstant(function); |
| 100 Node* check = graph()->NewNode(simplified()->ReferenceEqual(Type::Any()), | 85 Node* check = graph()->NewNode(simplified()->ReferenceEqual(Type::Any()), |
| 101 target, target_function); | 86 target, target_function); |
| 102 Node* branch = | 87 Node* branch = |
| 103 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control); | 88 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control); |
| 104 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); | 89 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); |
| 105 Node* deoptimize = graph()->NewNode(common()->Deoptimize(), frame_state, | 90 Node* deoptimize = graph()->NewNode(common()->Deoptimize(), frame_state, |
| 106 effect, if_false); | 91 effect, if_false); |
| 107 // TODO(bmeurer): This should be on the AdvancedReducer somehow. | 92 // TODO(bmeurer): This should be on the AdvancedReducer somehow. |
| 108 NodeProperties::MergeControlToEnd(graph(), common(), deoptimize); | 93 NodeProperties::MergeControlToEnd(graph(), common(), deoptimize); |
| 109 control = graph()->NewNode(common()->IfTrue(), branch); | 94 control = graph()->NewNode(common()->IfTrue(), branch); |
| 110 | 95 |
| 111 // Specialize the JSCallFunction node to the {target_function}. | 96 // Specialize the JSCallFunction node to the {target_function}. |
| 112 NodeProperties::ReplaceValueInput(node, target_function, 0); | 97 NodeProperties::ReplaceValueInput(node, target_function, 0); |
| 113 NodeProperties::ReplaceControlInput(node, control); | 98 NodeProperties::ReplaceControlInput(node, control); |
| 114 return Changed(node); | 99 return Changed(node); |
| 115 } | 100 } |
| 116 // TODO(bmeurer): Also support optimizing bound functions and proxies here. | 101 // TODO(bmeurer): Also support optimizing bound functions and proxies here. |
| 117 } | 102 } |
| 118 return NoChange(); | 103 return NoChange(); |
| 119 } | 104 } |
| 120 | 105 |
| 121 | 106 |
| 122 Reduction JSNativeContextSpecialization::ReduceJSLoadGlobal(Node* node) { | |
| 123 DCHECK_EQ(IrOpcode::kJSLoadGlobal, node->opcode()); | |
| 124 Handle<Name> name = LoadGlobalParametersOf(node->op()).name(); | |
| 125 Node* effect = NodeProperties::GetEffectInput(node); | |
| 126 Node* control = NodeProperties::GetControlInput(node); | |
| 127 | |
| 128 // Try to lookup the name on the script context table first (lexical scoping). | |
| 129 ScriptContextTableLookupResult result; | |
| 130 if (LookupInScriptContextTable(name, &result)) { | |
| 131 if (result.context->is_the_hole(result.index)) return NoChange(); | |
| 132 Node* context = jsgraph()->Constant(result.context); | |
| 133 Node* value = effect = graph()->NewNode( | |
| 134 javascript()->LoadContext(0, result.index, result.immutable), context, | |
| 135 context, effect); | |
| 136 return Replace(node, value, effect); | |
| 137 } | |
| 138 | |
| 139 // Lookup on the global object instead. We only deal with own data | |
| 140 // properties of the global object here (represented as PropertyCell). | |
| 141 LookupIterator it(global_object(), name, LookupIterator::OWN); | |
| 142 if (it.state() != LookupIterator::DATA) return NoChange(); | |
| 143 Handle<PropertyCell> property_cell = it.GetPropertyCell(); | |
| 144 PropertyDetails property_details = property_cell->property_details(); | |
| 145 Handle<Object> property_cell_value(property_cell->value(), isolate()); | |
| 146 | |
| 147 // Load from non-configurable, read-only data property on the global | |
| 148 // object can be constant-folded, even without deoptimization support. | |
| 149 if (!property_details.IsConfigurable() && property_details.IsReadOnly()) { | |
| 150 return Replace(node, property_cell_value); | |
| 151 } | |
| 152 | |
| 153 // Load from non-configurable, data property on the global can be lowered to | |
| 154 // a field load, even without deoptimization, because the property cannot be | |
| 155 // deleted or reconfigured to an accessor/interceptor property. Yet, if | |
| 156 // deoptimization support is available, we can constant-fold certain global | |
| 157 // properties or at least lower them to field loads annotated with more | |
| 158 // precise type feedback. | |
| 159 Type* property_cell_value_type = | |
| 160 Type::Intersect(Type::Any(), Type::Tagged(), graph()->zone()); | |
| 161 if (flags() & kDeoptimizationEnabled) { | |
| 162 // Record a code dependency on the cell if we can benefit from the | |
| 163 // additional feedback, or the global property is configurable (i.e. | |
| 164 // can be deleted or reconfigured to an accessor property). | |
| 165 if (property_details.cell_type() != PropertyCellType::kMutable || | |
| 166 property_details.IsConfigurable()) { | |
| 167 dependencies()->AssumePropertyCell(property_cell); | |
| 168 } | |
| 169 | |
| 170 // Load from constant/undefined global property can be constant-folded. | |
| 171 if ((property_details.cell_type() == PropertyCellType::kConstant || | |
| 172 property_details.cell_type() == PropertyCellType::kUndefined)) { | |
| 173 return Replace(node, property_cell_value); | |
| 174 } | |
| 175 | |
| 176 // Load from constant type cell can benefit from type feedback. | |
| 177 if (property_details.cell_type() == PropertyCellType::kConstantType) { | |
| 178 // Compute proper type based on the current value in the cell. | |
| 179 if (property_cell_value->IsSmi()) { | |
| 180 property_cell_value_type = type_cache_.kSmi; | |
| 181 } else if (property_cell_value->IsNumber()) { | |
| 182 property_cell_value_type = type_cache_.kHeapNumber; | |
| 183 } else { | |
| 184 Handle<Map> property_cell_value_map( | |
| 185 Handle<HeapObject>::cast(property_cell_value)->map(), isolate()); | |
| 186 property_cell_value_type = | |
| 187 Type::Class(property_cell_value_map, graph()->zone()); | |
| 188 } | |
| 189 } | |
| 190 } else if (property_details.IsConfigurable()) { | |
| 191 // Access to configurable global properties requires deoptimization support. | |
| 192 return NoChange(); | |
| 193 } | |
| 194 Node* value = effect = graph()->NewNode( | |
| 195 simplified()->LoadField( | |
| 196 AccessBuilder::ForPropertyCellValue(property_cell_value_type)), | |
| 197 jsgraph()->Constant(property_cell), effect, control); | |
| 198 return Replace(node, value, effect); | |
| 199 } | |
| 200 | |
| 201 | |
| 202 Reduction JSNativeContextSpecialization::ReduceJSStoreGlobal(Node* node) { | |
| 203 DCHECK_EQ(IrOpcode::kJSStoreGlobal, node->opcode()); | |
| 204 Handle<Name> name = StoreGlobalParametersOf(node->op()).name(); | |
| 205 Node* value = NodeProperties::GetValueInput(node, 0); | |
| 206 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1); | |
| 207 Node* effect = NodeProperties::GetEffectInput(node); | |
| 208 Node* control = NodeProperties::GetControlInput(node); | |
| 209 | |
| 210 // Try to lookup the name on the script context table first (lexical scoping). | |
| 211 ScriptContextTableLookupResult result; | |
| 212 if (LookupInScriptContextTable(name, &result)) { | |
| 213 if (result.context->is_the_hole(result.index)) return NoChange(); | |
| 214 if (result.immutable) return NoChange(); | |
| 215 Node* context = jsgraph()->Constant(result.context); | |
| 216 effect = graph()->NewNode(javascript()->StoreContext(0, result.index), | |
| 217 context, value, context, effect, control); | |
| 218 return Replace(node, value, effect, control); | |
| 219 } | |
| 220 | |
| 221 // Lookup on the global object instead. We only deal with own data | |
| 222 // properties of the global object here (represented as PropertyCell). | |
| 223 LookupIterator it(global_object(), name, LookupIterator::OWN); | |
| 224 if (it.state() != LookupIterator::DATA) return NoChange(); | |
| 225 Handle<PropertyCell> property_cell = it.GetPropertyCell(); | |
| 226 PropertyDetails property_details = property_cell->property_details(); | |
| 227 Handle<Object> property_cell_value(property_cell->value(), isolate()); | |
| 228 | |
| 229 // Don't even bother trying to lower stores to read-only data properties. | |
| 230 if (property_details.IsReadOnly()) return NoChange(); | |
| 231 switch (property_details.cell_type()) { | |
| 232 case PropertyCellType::kUndefined: { | |
| 233 return NoChange(); | |
| 234 } | |
| 235 case PropertyCellType::kConstant: { | |
| 236 // Store to constant property cell requires deoptimization support, | |
| 237 // because we might even need to eager deoptimize for mismatch. | |
| 238 if (!(flags() & kDeoptimizationEnabled)) return NoChange(); | |
| 239 dependencies()->AssumePropertyCell(property_cell); | |
| 240 Node* check = | |
| 241 graph()->NewNode(simplified()->ReferenceEqual(Type::Tagged()), value, | |
| 242 jsgraph()->Constant(property_cell_value)); | |
| 243 Node* branch = | |
| 244 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control); | |
| 245 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); | |
| 246 Node* deoptimize = graph()->NewNode(common()->Deoptimize(), frame_state, | |
| 247 effect, if_false); | |
| 248 // TODO(bmeurer): This should be on the AdvancedReducer somehow. | |
| 249 NodeProperties::MergeControlToEnd(graph(), common(), deoptimize); | |
| 250 control = graph()->NewNode(common()->IfTrue(), branch); | |
| 251 return Replace(node, value, effect, control); | |
| 252 } | |
| 253 case PropertyCellType::kConstantType: { | |
| 254 // Store to constant-type property cell requires deoptimization support, | |
| 255 // because we might even need to eager deoptimize for mismatch. | |
| 256 if (!(flags() & kDeoptimizationEnabled)) return NoChange(); | |
| 257 dependencies()->AssumePropertyCell(property_cell); | |
| 258 Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), value); | |
| 259 if (property_cell_value->IsHeapObject()) { | |
| 260 Node* branch = graph()->NewNode(common()->Branch(BranchHint::kFalse), | |
| 261 check, control); | |
| 262 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); | |
| 263 Node* deoptimize = graph()->NewNode(common()->Deoptimize(), frame_state, | |
| 264 effect, if_true); | |
| 265 // TODO(bmeurer): This should be on the AdvancedReducer somehow. | |
| 266 NodeProperties::MergeControlToEnd(graph(), common(), deoptimize); | |
| 267 control = graph()->NewNode(common()->IfFalse(), branch); | |
| 268 Node* value_map = | |
| 269 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), | |
| 270 value, effect, control); | |
| 271 Handle<Map> property_cell_value_map( | |
| 272 Handle<HeapObject>::cast(property_cell_value)->map(), isolate()); | |
| 273 check = graph()->NewNode(simplified()->ReferenceEqual(Type::Internal()), | |
| 274 value_map, | |
| 275 jsgraph()->Constant(property_cell_value_map)); | |
| 276 } | |
| 277 Node* branch = | |
| 278 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control); | |
| 279 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); | |
| 280 Node* deoptimize = graph()->NewNode(common()->Deoptimize(), frame_state, | |
| 281 effect, if_false); | |
| 282 // TODO(bmeurer): This should be on the AdvancedReducer somehow. | |
| 283 NodeProperties::MergeControlToEnd(graph(), common(), deoptimize); | |
| 284 control = graph()->NewNode(common()->IfTrue(), branch); | |
| 285 break; | |
| 286 } | |
| 287 case PropertyCellType::kMutable: { | |
| 288 // Store to non-configurable, data property on the global can be lowered | |
| 289 // to a field store, even without deoptimization, because the property | |
| 290 // cannot be deleted or reconfigured to an accessor/interceptor property. | |
| 291 if (property_details.IsConfigurable()) { | |
| 292 // With deoptimization support, we can lower stores even to configurable | |
| 293 // data properties on the global object, by adding a code dependency on | |
| 294 // the cell. | |
| 295 if (!(flags() & kDeoptimizationEnabled)) return NoChange(); | |
| 296 dependencies()->AssumePropertyCell(property_cell); | |
| 297 } | |
| 298 break; | |
| 299 } | |
| 300 } | |
| 301 effect = graph()->NewNode( | |
| 302 simplified()->StoreField(AccessBuilder::ForPropertyCellValue()), | |
| 303 jsgraph()->Constant(property_cell), value, effect, control); | |
| 304 return Replace(node, value, effect, control); | |
| 305 } | |
| 306 | |
| 307 | |
| 308 Reduction JSNativeContextSpecialization::ReduceNamedAccess( | 107 Reduction JSNativeContextSpecialization::ReduceNamedAccess( |
| 309 Node* node, Node* value, MapHandleList const& receiver_maps, | 108 Node* node, Node* value, MapHandleList const& receiver_maps, |
| 310 Handle<Name> name, AccessMode access_mode, LanguageMode language_mode, | 109 Handle<Name> name, AccessMode access_mode, LanguageMode language_mode, |
| 311 Node* index) { | 110 Node* index) { |
| 312 DCHECK(node->opcode() == IrOpcode::kJSLoadNamed || | 111 DCHECK(node->opcode() == IrOpcode::kJSLoadNamed || |
| 313 node->opcode() == IrOpcode::kJSStoreNamed || | 112 node->opcode() == IrOpcode::kJSStoreNamed || |
| 314 node->opcode() == IrOpcode::kJSLoadProperty || | 113 node->opcode() == IrOpcode::kJSLoadProperty || |
| 315 node->opcode() == IrOpcode::kJSStoreProperty); | 114 node->opcode() == IrOpcode::kJSStoreProperty); |
| 316 Node* receiver = NodeProperties::GetValueInput(node, 0); | 115 Node* receiver = NodeProperties::GetValueInput(node, 0); |
| 317 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1); | 116 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1); |
| (...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 647 } else { | 446 } else { |
| 648 control = graph()->NewNode(common()->Merge(control_count), control_count, | 447 control = graph()->NewNode(common()->Merge(control_count), control_count, |
| 649 &controls.front()); | 448 &controls.front()); |
| 650 values.push_back(control); | 449 values.push_back(control); |
| 651 value = graph()->NewNode(common()->Phi(kMachAnyTagged, control_count), | 450 value = graph()->NewNode(common()->Phi(kMachAnyTagged, control_count), |
| 652 control_count + 1, &values.front()); | 451 control_count + 1, &values.front()); |
| 653 effects.push_back(control); | 452 effects.push_back(control); |
| 654 effect = graph()->NewNode(common()->EffectPhi(control_count), | 453 effect = graph()->NewNode(common()->EffectPhi(control_count), |
| 655 control_count + 1, &effects.front()); | 454 control_count + 1, &effects.front()); |
| 656 } | 455 } |
| 657 return Replace(node, value, effect, control); | 456 ReplaceWithValue(node, value, effect, control); |
| 457 return Replace(value); |
| 658 } | 458 } |
| 659 | 459 |
| 660 | 460 |
| 661 Reduction JSNativeContextSpecialization::ReduceJSLoadNamed(Node* node) { | 461 Reduction JSNativeContextSpecialization::ReduceJSLoadNamed(Node* node) { |
| 662 DCHECK_EQ(IrOpcode::kJSLoadNamed, node->opcode()); | 462 DCHECK_EQ(IrOpcode::kJSLoadNamed, node->opcode()); |
| 663 NamedAccess const& p = NamedAccessOf(node->op()); | 463 NamedAccess const& p = NamedAccessOf(node->op()); |
| 664 Node* const value = jsgraph()->Dead(); | 464 Node* const value = jsgraph()->Dead(); |
| 665 | 465 |
| 666 // Extract receiver maps from the LOAD_IC using the LoadICNexus. | 466 // Extract receiver maps from the LOAD_IC using the LoadICNexus. |
| 667 MapHandleList receiver_maps; | 467 MapHandleList receiver_maps; |
| (...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 932 } else { | 732 } else { |
| 933 control = graph()->NewNode(common()->Merge(control_count), control_count, | 733 control = graph()->NewNode(common()->Merge(control_count), control_count, |
| 934 &controls.front()); | 734 &controls.front()); |
| 935 values.push_back(control); | 735 values.push_back(control); |
| 936 value = graph()->NewNode(common()->Phi(kMachAnyTagged, control_count), | 736 value = graph()->NewNode(common()->Phi(kMachAnyTagged, control_count), |
| 937 control_count + 1, &values.front()); | 737 control_count + 1, &values.front()); |
| 938 effects.push_back(control); | 738 effects.push_back(control); |
| 939 effect = graph()->NewNode(common()->EffectPhi(control_count), | 739 effect = graph()->NewNode(common()->EffectPhi(control_count), |
| 940 control_count + 1, &effects.front()); | 740 control_count + 1, &effects.front()); |
| 941 } | 741 } |
| 942 return Replace(node, value, effect, control); | 742 ReplaceWithValue(node, value, effect, control); |
| 743 return Replace(value); |
| 943 } | 744 } |
| 944 | 745 |
| 945 | 746 |
| 946 Reduction JSNativeContextSpecialization::ReduceKeyedAccess( | 747 Reduction JSNativeContextSpecialization::ReduceKeyedAccess( |
| 947 Node* node, Node* index, Node* value, FeedbackNexus const& nexus, | 748 Node* node, Node* index, Node* value, FeedbackNexus const& nexus, |
| 948 AccessMode access_mode, LanguageMode language_mode) { | 749 AccessMode access_mode, LanguageMode language_mode) { |
| 949 DCHECK(node->opcode() == IrOpcode::kJSLoadProperty || | 750 DCHECK(node->opcode() == IrOpcode::kJSLoadProperty || |
| 950 node->opcode() == IrOpcode::kJSStoreProperty); | 751 node->opcode() == IrOpcode::kJSStoreProperty); |
| 951 | 752 |
| 952 // Extract receiver maps from the {nexus}. | 753 // Extract receiver maps from the {nexus}. |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1013 // Extract receiver maps from the KEYED_STORE_IC using the KeyedStoreICNexus. | 814 // Extract receiver maps from the KEYED_STORE_IC using the KeyedStoreICNexus. |
| 1014 if (!p.feedback().IsValid()) return NoChange(); | 815 if (!p.feedback().IsValid()) return NoChange(); |
| 1015 KeyedStoreICNexus nexus(p.feedback().vector(), p.feedback().slot()); | 816 KeyedStoreICNexus nexus(p.feedback().vector(), p.feedback().slot()); |
| 1016 | 817 |
| 1017 // Try to lower the keyed access based on the {nexus}. | 818 // Try to lower the keyed access based on the {nexus}. |
| 1018 return ReduceKeyedAccess(node, index, value, nexus, AccessMode::kStore, | 819 return ReduceKeyedAccess(node, index, value, nexus, AccessMode::kStore, |
| 1019 p.language_mode()); | 820 p.language_mode()); |
| 1020 } | 821 } |
| 1021 | 822 |
| 1022 | 823 |
| 1023 Reduction JSNativeContextSpecialization::Replace(Node* node, | |
| 1024 Handle<Object> value) { | |
| 1025 return Replace(node, jsgraph()->Constant(value)); | |
| 1026 } | |
| 1027 | |
| 1028 | |
| 1029 bool JSNativeContextSpecialization::LookupInScriptContextTable( | |
| 1030 Handle<Name> name, ScriptContextTableLookupResult* result) { | |
| 1031 if (!name->IsString()) return false; | |
| 1032 Handle<ScriptContextTable> script_context_table( | |
| 1033 native_context()->script_context_table()); | |
| 1034 ScriptContextTable::LookupResult lookup_result; | |
| 1035 if (!ScriptContextTable::Lookup(script_context_table, | |
| 1036 Handle<String>::cast(name), &lookup_result)) { | |
| 1037 return false; | |
| 1038 } | |
| 1039 Handle<Context> script_context = ScriptContextTable::GetContext( | |
| 1040 script_context_table, lookup_result.context_index); | |
| 1041 result->context = script_context; | |
| 1042 result->immutable = IsImmutableVariableMode(lookup_result.mode); | |
| 1043 result->index = lookup_result.slot_index; | |
| 1044 return true; | |
| 1045 } | |
| 1046 | |
| 1047 | |
| 1048 void JSNativeContextSpecialization::AssumePrototypesStable( | 824 void JSNativeContextSpecialization::AssumePrototypesStable( |
| 1049 Type* receiver_type, Handle<JSObject> holder) { | 825 Type* receiver_type, Handle<JSObject> holder) { |
| 1050 // Determine actual holder and perform prototype chain checks. | 826 // Determine actual holder and perform prototype chain checks. |
| 1051 for (auto i = receiver_type->Classes(); !i.Done(); i.Advance()) { | 827 for (auto i = receiver_type->Classes(); !i.Done(); i.Advance()) { |
| 1052 Handle<Map> map = i.Current(); | 828 Handle<Map> map = i.Current(); |
| 1053 // Perform the implicit ToObject for primitives here. | 829 // Perform the implicit ToObject for primitives here. |
| 1054 // Implemented according to ES6 section 7.3.2 GetV (V, P). | 830 // Implemented according to ES6 section 7.3.2 GetV (V, P). |
| 1055 Handle<JSFunction> constructor; | 831 Handle<JSFunction> constructor; |
| 1056 if (Map::GetConstructorFunction(map, native_context()) | 832 if (Map::GetConstructorFunction(map, native_context()) |
| 1057 .ToHandle(&constructor)) { | 833 .ToHandle(&constructor)) { |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1113 } | 889 } |
| 1114 | 890 |
| 1115 | 891 |
| 1116 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const { | 892 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const { |
| 1117 return jsgraph()->simplified(); | 893 return jsgraph()->simplified(); |
| 1118 } | 894 } |
| 1119 | 895 |
| 1120 } // namespace compiler | 896 } // namespace compiler |
| 1121 } // namespace internal | 897 } // namespace internal |
| 1122 } // namespace v8 | 898 } // namespace v8 |
| OLD | NEW |