| 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" | 
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 50     case IrOpcode::kJSCallFunction: | 50     case IrOpcode::kJSCallFunction: | 
| 51       return ReduceJSCallFunction(node); | 51       return ReduceJSCallFunction(node); | 
| 52     case IrOpcode::kJSLoadGlobal: | 52     case IrOpcode::kJSLoadGlobal: | 
| 53       return ReduceJSLoadGlobal(node); | 53       return ReduceJSLoadGlobal(node); | 
| 54     case IrOpcode::kJSStoreGlobal: | 54     case IrOpcode::kJSStoreGlobal: | 
| 55       return ReduceJSStoreGlobal(node); | 55       return ReduceJSStoreGlobal(node); | 
| 56     case IrOpcode::kJSLoadNamed: | 56     case IrOpcode::kJSLoadNamed: | 
| 57       return ReduceJSLoadNamed(node); | 57       return ReduceJSLoadNamed(node); | 
| 58     case IrOpcode::kJSStoreNamed: | 58     case IrOpcode::kJSStoreNamed: | 
| 59       return ReduceJSStoreNamed(node); | 59       return ReduceJSStoreNamed(node); | 
|  | 60     case IrOpcode::kJSLoadProperty: | 
|  | 61       return ReduceJSLoadProperty(node); | 
|  | 62     case IrOpcode::kJSStoreProperty: | 
|  | 63       return ReduceJSStoreProperty(node); | 
| 60     default: | 64     default: | 
| 61       break; | 65       break; | 
| 62   } | 66   } | 
| 63   return NoChange(); | 67   return NoChange(); | 
| 64 } | 68 } | 
| 65 | 69 | 
| 66 | 70 | 
| 67 Reduction JSNativeContextSpecialization::ReduceJSCallFunction(Node* node) { | 71 Reduction JSNativeContextSpecialization::ReduceJSCallFunction(Node* node) { | 
| 68   DCHECK_EQ(IrOpcode::kJSCallFunction, node->opcode()); | 72   DCHECK_EQ(IrOpcode::kJSCallFunction, node->opcode()); | 
| 69   CallFunctionParameters const& p = CallFunctionParametersOf(node->op()); | 73   CallFunctionParameters const& p = CallFunctionParametersOf(node->op()); | 
| (...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 297   effect = graph()->NewNode( | 301   effect = graph()->NewNode( | 
| 298       simplified()->StoreField(AccessBuilder::ForPropertyCellValue()), | 302       simplified()->StoreField(AccessBuilder::ForPropertyCellValue()), | 
| 299       jsgraph()->Constant(property_cell), value, effect, control); | 303       jsgraph()->Constant(property_cell), value, effect, control); | 
| 300   return Replace(node, value, effect, control); | 304   return Replace(node, value, effect, control); | 
| 301 } | 305 } | 
| 302 | 306 | 
| 303 | 307 | 
| 304 Reduction JSNativeContextSpecialization::ReduceNamedAccess( | 308 Reduction JSNativeContextSpecialization::ReduceNamedAccess( | 
| 305     Node* node, Node* value, MapHandleList const& receiver_maps, | 309     Node* node, Node* value, MapHandleList const& receiver_maps, | 
| 306     Handle<Name> name, PropertyAccessMode access_mode, | 310     Handle<Name> name, PropertyAccessMode access_mode, | 
| 307     LanguageMode language_mode) { | 311     LanguageMode language_mode, Node* index) { | 
| 308   DCHECK(node->opcode() == IrOpcode::kJSLoadNamed || | 312   DCHECK(node->opcode() == IrOpcode::kJSLoadNamed || | 
| 309          node->opcode() == IrOpcode::kJSStoreNamed); | 313          node->opcode() == IrOpcode::kJSStoreNamed || | 
|  | 314          node->opcode() == IrOpcode::kJSLoadProperty || | 
|  | 315          node->opcode() == IrOpcode::kJSStoreProperty); | 
| 310   Node* receiver = NodeProperties::GetValueInput(node, 0); | 316   Node* receiver = NodeProperties::GetValueInput(node, 0); | 
| 311   Node* frame_state = NodeProperties::GetFrameStateInput(node, 1); | 317   Node* frame_state = NodeProperties::GetFrameStateInput(node, 1); | 
| 312   Node* effect = NodeProperties::GetEffectInput(node); | 318   Node* effect = NodeProperties::GetEffectInput(node); | 
| 313   Node* control = NodeProperties::GetControlInput(node); | 319   Node* control = NodeProperties::GetControlInput(node); | 
| 314 | 320 | 
| 315   // Not much we can do if deoptimization support is disabled. | 321   // Not much we can do if deoptimization support is disabled. | 
| 316   if (!(flags() & kDeoptimizationEnabled)) return NoChange(); | 322   if (!(flags() & kDeoptimizationEnabled)) return NoChange(); | 
| 317 | 323 | 
| 318   // Compute property access infos for the receiver maps. | 324   // Compute property access infos for the receiver maps. | 
| 319   ZoneVector<PropertyAccessInfo> access_infos(zone()); | 325   ZoneVector<PropertyAccessInfo> access_infos(zone()); | 
| 320   if (!access_info_factory().ComputePropertyAccessInfos( | 326   if (!access_info_factory().ComputePropertyAccessInfos( | 
| 321           receiver_maps, name, access_mode, &access_infos)) { | 327           receiver_maps, name, access_mode, &access_infos)) { | 
| 322     return NoChange(); | 328     return NoChange(); | 
| 323   } | 329   } | 
| 324 | 330 | 
| 325   // Nothing to do if we have no non-deprecated maps. | 331   // Nothing to do if we have no non-deprecated maps. | 
| 326   if (access_infos.empty()) return NoChange(); | 332   if (access_infos.empty()) return NoChange(); | 
| 327 | 333 | 
| 328   // The final states for every polymorphic branch. We join them with | 334   // The final states for every polymorphic branch. We join them with | 
| 329   // Merge++Phi+EffectPhi at the bottom. | 335   // Merge++Phi+EffectPhi at the bottom. | 
| 330   ZoneVector<Node*> values(zone()); | 336   ZoneVector<Node*> values(zone()); | 
| 331   ZoneVector<Node*> effects(zone()); | 337   ZoneVector<Node*> effects(zone()); | 
| 332   ZoneVector<Node*> controls(zone()); | 338   ZoneVector<Node*> controls(zone()); | 
| 333 | 339 | 
| 334   // The list of "exiting" controls, which currently go to a single deoptimize. | 340   // The list of "exiting" controls, which currently go to a single deoptimize. | 
| 335   // TODO(bmeurer): Consider using an IC as fallback. | 341   // TODO(bmeurer): Consider using an IC as fallback. | 
| 336   Node* const exit_effect = effect; | 342   Node* const exit_effect = effect; | 
| 337   ZoneVector<Node*> exit_controls(zone()); | 343   ZoneVector<Node*> exit_controls(zone()); | 
| 338 | 344 | 
|  | 345   // Ensure that {index} matches the specified {name} (if {index} is given). | 
|  | 346   if (index != nullptr) { | 
|  | 347     Node* check = graph()->NewNode(simplified()->ReferenceEqual(Type::Name()), | 
|  | 348                                    index, jsgraph()->HeapConstant(name)); | 
|  | 349     Node* branch = | 
|  | 350         graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control); | 
|  | 351     exit_controls.push_back(graph()->NewNode(common()->IfFalse(), branch)); | 
|  | 352     control = graph()->NewNode(common()->IfTrue(), branch); | 
|  | 353   } | 
|  | 354 | 
| 339   // Ensure that {receiver} is a heap object. | 355   // Ensure that {receiver} is a heap object. | 
| 340   Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), receiver); | 356   Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), receiver); | 
| 341   Node* branch = | 357   Node* branch = | 
| 342       graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control); | 358       graph()->NewNode(common()->Branch(BranchHint::kFalse), check, control); | 
| 343   exit_controls.push_back(graph()->NewNode(common()->IfTrue(), branch)); | 359   exit_controls.push_back(graph()->NewNode(common()->IfTrue(), branch)); | 
| 344   control = graph()->NewNode(common()->IfFalse(), branch); | 360   control = graph()->NewNode(common()->IfFalse(), branch); | 
| 345 | 361 | 
| 346   // Load the {receiver} map. The resulting effect is the dominating effect for | 362   // Load the {receiver} map. The resulting effect is the dominating effect for | 
| 347   // all (polymorphic) branches. | 363   // all (polymorphic) branches. | 
| 348   Node* receiver_map = effect = | 364   Node* receiver_map = effect = | 
| (...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 646   StoreICNexus nexus(p.feedback().vector(), p.feedback().slot()); | 662   StoreICNexus nexus(p.feedback().vector(), p.feedback().slot()); | 
| 647   if (nexus.ExtractMaps(&receiver_maps) == 0) return NoChange(); | 663   if (nexus.ExtractMaps(&receiver_maps) == 0) return NoChange(); | 
| 648   DCHECK_LT(0, receiver_maps.length()); | 664   DCHECK_LT(0, receiver_maps.length()); | 
| 649 | 665 | 
| 650   // Try to lower the named access based on the {receiver_maps}. | 666   // Try to lower the named access based on the {receiver_maps}. | 
| 651   return ReduceNamedAccess(node, value, receiver_maps, p.name(), | 667   return ReduceNamedAccess(node, value, receiver_maps, p.name(), | 
| 652                            PropertyAccessMode::kStore, p.language_mode()); | 668                            PropertyAccessMode::kStore, p.language_mode()); | 
| 653 } | 669 } | 
| 654 | 670 | 
| 655 | 671 | 
|  | 672 Reduction JSNativeContextSpecialization::ReduceKeyedAccess( | 
|  | 673     Node* node, Node* index, Node* value, FeedbackNexus const& nexus, | 
|  | 674     PropertyAccessMode access_mode, LanguageMode language_mode) { | 
|  | 675   DCHECK(node->opcode() == IrOpcode::kJSLoadProperty || | 
|  | 676          node->opcode() == IrOpcode::kJSStoreProperty); | 
|  | 677 | 
|  | 678   // Extract receiver maps from the {nexus}. | 
|  | 679   MapHandleList receiver_maps; | 
|  | 680   if (nexus.ExtractMaps(&receiver_maps) == 0) return NoChange(); | 
|  | 681   DCHECK_LT(0, receiver_maps.length()); | 
|  | 682 | 
|  | 683   // Optimize access for constant {index}. | 
|  | 684   HeapObjectMatcher mindex(index); | 
|  | 685   if (mindex.HasValue() && mindex.Value()->IsPrimitive()) { | 
|  | 686     // Keyed access requires a ToPropertyKey on the {index} first before | 
|  | 687     // looking up the property on the object (see ES6 section 12.3.2.1). | 
|  | 688     // We can only do this for non-observable ToPropertyKey invocations, | 
|  | 689     // so we limit the constant indices to primitives at this point. | 
|  | 690     Handle<Name> name; | 
|  | 691     if (Object::ToName(isolate(), mindex.Value()).ToHandle(&name)) { | 
|  | 692       uint32_t array_index; | 
|  | 693       if (name->AsArrayIndex(&array_index)) { | 
|  | 694         // TODO(bmeurer): Optimize element access with constant {index}. | 
|  | 695       } else { | 
|  | 696         name = factory()->InternalizeName(name); | 
|  | 697         return ReduceNamedAccess(node, value, receiver_maps, name, access_mode, | 
|  | 698                                  language_mode); | 
|  | 699       } | 
|  | 700     } | 
|  | 701   } | 
|  | 702 | 
|  | 703   // Check if we have feedback for a named access. | 
|  | 704   if (Name* name = nexus.FindFirstName()) { | 
|  | 705     return ReduceNamedAccess(node, value, receiver_maps, | 
|  | 706                              handle(name, isolate()), access_mode, | 
|  | 707                              language_mode, index); | 
|  | 708   } | 
|  | 709 | 
|  | 710   return NoChange(); | 
|  | 711 } | 
|  | 712 | 
|  | 713 | 
|  | 714 Reduction JSNativeContextSpecialization::ReduceJSLoadProperty(Node* node) { | 
|  | 715   DCHECK_EQ(IrOpcode::kJSLoadProperty, node->opcode()); | 
|  | 716   PropertyAccess const& p = PropertyAccessOf(node->op()); | 
|  | 717   Node* const index = NodeProperties::GetValueInput(node, 1); | 
|  | 718   Node* const value = jsgraph()->Dead(); | 
|  | 719 | 
|  | 720   // Extract receiver maps from the KEYED_LOAD_IC using the KeyedLoadICNexus. | 
|  | 721   if (!p.feedback().IsValid()) return NoChange(); | 
|  | 722   KeyedLoadICNexus nexus(p.feedback().vector(), p.feedback().slot()); | 
|  | 723 | 
|  | 724   // Try to lower the keyed access based on the {nexus}. | 
|  | 725   return ReduceKeyedAccess(node, index, value, nexus, PropertyAccessMode::kLoad, | 
|  | 726                            p.language_mode()); | 
|  | 727 } | 
|  | 728 | 
|  | 729 | 
|  | 730 Reduction JSNativeContextSpecialization::ReduceJSStoreProperty(Node* node) { | 
|  | 731   DCHECK_EQ(IrOpcode::kJSStoreProperty, node->opcode()); | 
|  | 732   PropertyAccess const& p = PropertyAccessOf(node->op()); | 
|  | 733   Node* const index = NodeProperties::GetValueInput(node, 1); | 
|  | 734   Node* const value = NodeProperties::GetValueInput(node, 2); | 
|  | 735 | 
|  | 736   // Extract receiver maps from the KEYED_STORE_IC using the KeyedStoreICNexus. | 
|  | 737   if (!p.feedback().IsValid()) return NoChange(); | 
|  | 738   KeyedStoreICNexus nexus(p.feedback().vector(), p.feedback().slot()); | 
|  | 739 | 
|  | 740   // Try to lower the keyed access based on the {nexus}. | 
|  | 741   return ReduceKeyedAccess(node, index, value, nexus, | 
|  | 742                            PropertyAccessMode::kStore, p.language_mode()); | 
|  | 743 } | 
|  | 744 | 
|  | 745 | 
| 656 Reduction JSNativeContextSpecialization::Replace(Node* node, | 746 Reduction JSNativeContextSpecialization::Replace(Node* node, | 
| 657                                                  Handle<Object> value) { | 747                                                  Handle<Object> value) { | 
| 658   return Replace(node, jsgraph()->Constant(value)); | 748   return Replace(node, jsgraph()->Constant(value)); | 
| 659 } | 749 } | 
| 660 | 750 | 
| 661 | 751 | 
| 662 bool JSNativeContextSpecialization::LookupInScriptContextTable( | 752 bool JSNativeContextSpecialization::LookupInScriptContextTable( | 
| 663     Handle<Name> name, ScriptContextTableLookupResult* result) { | 753     Handle<Name> name, ScriptContextTableLookupResult* result) { | 
| 664   if (!name->IsString()) return false; | 754   if (!name->IsString()) return false; | 
| 665   Handle<ScriptContextTable> script_context_table( | 755   Handle<ScriptContextTable> script_context_table( | 
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 734 } | 824 } | 
| 735 | 825 | 
| 736 | 826 | 
| 737 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const { | 827 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const { | 
| 738   return jsgraph()->simplified(); | 828   return jsgraph()->simplified(); | 
| 739 } | 829 } | 
| 740 | 830 | 
| 741 }  // namespace compiler | 831 }  // namespace compiler | 
| 742 }  // namespace internal | 832 }  // namespace internal | 
| 743 }  // namespace v8 | 833 }  // namespace v8 | 
| OLD | NEW | 
|---|