OLD | NEW |
1 // Copyright 2017 the V8 project authors. All rights reserved. | 1 // Copyright 2017 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-type-hint-lowering.h" | 5 #include "src/compiler/js-type-hint-lowering.h" |
6 | 6 |
| 7 #include "src/compiler/access-info.h" |
7 #include "src/compiler/js-graph.h" | 8 #include "src/compiler/js-graph.h" |
8 #include "src/compiler/operator-properties.h" | 9 #include "src/compiler/operator-properties.h" |
| 10 #include "src/compiler/property-access-builder.h" |
9 #include "src/compiler/simplified-operator.h" | 11 #include "src/compiler/simplified-operator.h" |
10 #include "src/feedback-vector.h" | 12 #include "src/feedback-vector.h" |
11 #include "src/type-hints.h" | 13 #include "src/type-hints.h" |
12 | 14 |
13 namespace v8 { | 15 namespace v8 { |
14 namespace internal { | 16 namespace internal { |
15 namespace compiler { | 17 namespace compiler { |
16 | 18 |
17 namespace { | 19 namespace { |
18 | 20 |
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
189 const Operator* op_; | 191 const Operator* op_; |
190 Node* left_; | 192 Node* left_; |
191 Node* right_; | 193 Node* right_; |
192 Node* effect_; | 194 Node* effect_; |
193 Node* control_; | 195 Node* control_; |
194 FeedbackSlot slot_; | 196 FeedbackSlot slot_; |
195 }; | 197 }; |
196 | 198 |
197 JSTypeHintLowering::JSTypeHintLowering(JSGraph* jsgraph, | 199 JSTypeHintLowering::JSTypeHintLowering(JSGraph* jsgraph, |
198 Handle<FeedbackVector> feedback_vector, | 200 Handle<FeedbackVector> feedback_vector, |
| 201 Handle<Context> native_context, |
| 202 CompilationDependencies* dependencies, |
199 Flags flags) | 203 Flags flags) |
200 : jsgraph_(jsgraph), flags_(flags), feedback_vector_(feedback_vector) {} | 204 : jsgraph_(jsgraph), |
| 205 flags_(flags), |
| 206 feedback_vector_(feedback_vector), |
| 207 native_context_(native_context), |
| 208 dependencies_(dependencies) {} |
| 209 |
| 210 Graph* JSTypeHintLowering::graph() const { return jsgraph_->graph(); } |
201 | 211 |
202 Reduction JSTypeHintLowering::ReduceBinaryOperation(const Operator* op, | 212 Reduction JSTypeHintLowering::ReduceBinaryOperation(const Operator* op, |
203 Node* left, Node* right, | 213 Node* left, Node* right, |
204 Node* effect, Node* control, | 214 Node* effect, Node* control, |
205 FeedbackSlot slot) const { | 215 FeedbackSlot slot) const { |
206 switch (op->opcode()) { | 216 switch (op->opcode()) { |
207 case IrOpcode::kJSStrictEqual: | 217 case IrOpcode::kJSStrictEqual: |
208 break; | 218 break; |
209 case IrOpcode::kJSEqual: | 219 case IrOpcode::kJSEqual: |
210 case IrOpcode::kJSLessThan: | 220 case IrOpcode::kJSLessThan: |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
267 jsgraph()->simplified()->CheckNonEmptyString(), input, effect, control); | 277 jsgraph()->simplified()->CheckNonEmptyString(), input, effect, control); |
268 return Reduction(node); | 278 return Reduction(node); |
269 } else if (hint == BinaryOperationHint::kString) { | 279 } else if (hint == BinaryOperationHint::kString) { |
270 Node* node = jsgraph()->graph()->NewNode( | 280 Node* node = jsgraph()->graph()->NewNode( |
271 jsgraph()->simplified()->CheckString(), input, effect, control); | 281 jsgraph()->simplified()->CheckString(), input, effect, control); |
272 return Reduction(node); | 282 return Reduction(node); |
273 } | 283 } |
274 return Reduction(); | 284 return Reduction(); |
275 } | 285 } |
276 | 286 |
277 Reduction JSTypeHintLowering::ReduceLoadNamedOperation( | 287 JSTypeHintLowering::LoweringResult JSTypeHintLowering::ReduceLoadNamedOperation( |
278 const Operator* op, Node* obj, Node* effect, Node* control, | 288 const Operator* op, Node* receiver, Node* effect, Node* control, |
279 FeedbackSlot slot) const { | 289 FeedbackSlot slot) const { |
280 DCHECK_EQ(IrOpcode::kJSLoadNamed, op->opcode()); | 290 DCHECK_EQ(IrOpcode::kJSLoadNamed, op->opcode()); |
281 DCHECK(!slot.IsInvalid()); | 291 DCHECK(!slot.IsInvalid()); |
282 LoadICNexus nexus(feedback_vector(), slot); | 292 LoadICNexus nexus(feedback_vector(), slot); |
283 if (Node* node = TryBuildSoftDeopt( | 293 if (Node* node = TryBuildSoftDeopt( |
284 nexus, effect, control, | 294 nexus, effect, control, |
285 DeoptimizeReason::kInsufficientTypeFeedbackForGenericNamedAccess)) { | 295 DeoptimizeReason::kInsufficientTypeFeedbackForGenericNamedAccess)) { |
286 return Reduction(node); | 296 return LoweringResult::Exit(node); |
287 } | 297 } |
288 return Reduction(); | 298 |
| 299 // Try to extract maps from the feedback vector. Give up if the IC |
| 300 // is megamorphic or unitialized. |
| 301 MapHandles receiver_maps; |
| 302 if (nexus.ExtractMaps(&receiver_maps) == 0) { |
| 303 return LoweringResult::NoChange(); |
| 304 } |
| 305 |
| 306 // Extract information about accesses from the maps. |
| 307 NamedAccess const& p = NamedAccessOf(op); |
| 308 AccessInfoFactory access_info_factory(dependencies(), native_context(), |
| 309 graph()->zone()); |
| 310 // TODO(jarin) Use a temporary zone here. |
| 311 ZoneVector<PropertyAccessInfo> access_infos(graph()->zone()); |
| 312 if (!access_info_factory.ComputePropertyAccessInfos( |
| 313 receiver_maps, p.name(), AccessMode::kLoad, &access_infos)) { |
| 314 return LoweringResult::NoChange(); |
| 315 } |
| 316 |
| 317 // Bail out if not monomorphic. |
| 318 if (access_infos.size() != 1) return LoweringResult::NoChange(); |
| 319 |
| 320 // We only lower data fields and data constants. |
| 321 PropertyAccessInfo const& access_info = access_infos[0]; |
| 322 if (!access_info.IsDataField() && !access_info.IsDataConstant()) { |
| 323 return LoweringResult::NoChange(); |
| 324 } |
| 325 |
| 326 PropertyAccessBuilder access_builder(jsgraph(), dependencies()); |
| 327 if (!access_builder.TryBuildStringCheck(access_info.receiver_maps(), |
| 328 &receiver, &effect, control) && |
| 329 !access_builder.TryBuildNumberCheck(access_info.receiver_maps(), |
| 330 &receiver, &effect, control)) { |
| 331 receiver = access_builder.BuildCheckHeapObject(receiver, &effect, control); |
| 332 access_builder.BuildCheckMaps(receiver, &effect, control, |
| 333 access_info.receiver_maps()); |
| 334 } |
| 335 |
| 336 Handle<JSObject> holder; |
| 337 if (access_info.holder().ToHandle(&holder)) { |
| 338 access_builder.AssumePrototypesStable(native_context(), |
| 339 access_info.receiver_maps(), holder); |
| 340 } |
| 341 |
| 342 Node* value = nullptr; |
| 343 if (access_info.IsDataConstant()) { |
| 344 value = jsgraph()->Constant(access_info.constant()); |
| 345 } else { |
| 346 DCHECK(access_info.IsDataField()); |
| 347 value = access_builder.BuildLoadDataField(p.name(), access_info, receiver, |
| 348 &effect, &control); |
| 349 } |
| 350 return LoweringResult::SideEffectFree(value, effect, control); |
289 } | 351 } |
290 | 352 |
291 Reduction JSTypeHintLowering::ReduceLoadKeyedOperation( | 353 Reduction JSTypeHintLowering::ReduceLoadKeyedOperation( |
292 const Operator* op, Node* obj, Node* key, Node* effect, Node* control, | 354 const Operator* op, Node* obj, Node* key, Node* effect, Node* control, |
293 FeedbackSlot slot) const { | 355 FeedbackSlot slot) const { |
294 DCHECK_EQ(IrOpcode::kJSLoadProperty, op->opcode()); | 356 DCHECK_EQ(IrOpcode::kJSLoadProperty, op->opcode()); |
295 DCHECK(!slot.IsInvalid()); | 357 DCHECK(!slot.IsInvalid()); |
296 KeyedLoadICNexus nexus(feedback_vector(), slot); | 358 KeyedLoadICNexus nexus(feedback_vector(), slot); |
297 if (Node* node = TryBuildSoftDeopt( | 359 if (Node* node = TryBuildSoftDeopt( |
298 nexus, effect, control, | 360 nexus, effect, control, |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
341 Node* frame_state = NodeProperties::FindFrameStateBefore(deoptimize); | 403 Node* frame_state = NodeProperties::FindFrameStateBefore(deoptimize); |
342 deoptimize->ReplaceInput(0, frame_state); | 404 deoptimize->ReplaceInput(0, frame_state); |
343 return deoptimize; | 405 return deoptimize; |
344 } | 406 } |
345 return nullptr; | 407 return nullptr; |
346 } | 408 } |
347 | 409 |
348 } // namespace compiler | 410 } // namespace compiler |
349 } // namespace internal | 411 } // namespace internal |
350 } // namespace v8 | 412 } // namespace v8 |
OLD | NEW |