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 |