Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(957)

Side by Side Diff: src/compiler/js-native-context-specialization.cc

Issue 1414013004: [turbofan] Add support for keyed access to named properties. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@JSNativeContextSpecialization_NotFound
Patch Set: Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/compiler/js-native-context-specialization.h ('k') | src/factory.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/compiler/js-native-context-specialization.h ('k') | src/factory.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698