| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "src/compiler/js-type-feedback-lowering.h" | |
| 6 | |
| 7 #include "src/compiler/access-builder.h" | |
| 8 #include "src/compiler/js-graph.h" | |
| 9 #include "src/compiler/node-properties.h" | |
| 10 #include "src/objects-inl.h" // TODO(mstarzinger): Temporary cycle breaker! | |
| 11 #include "src/type-feedback-vector.h" | |
| 12 | |
| 13 namespace v8 { | |
| 14 namespace internal { | |
| 15 namespace compiler { | |
| 16 | |
| 17 JSTypeFeedbackLowering::JSTypeFeedbackLowering(Editor* editor, Flags flags, | |
| 18 JSGraph* jsgraph) | |
| 19 : AdvancedReducer(editor), flags_(flags), jsgraph_(jsgraph) {} | |
| 20 | |
| 21 | |
| 22 Reduction JSTypeFeedbackLowering::Reduce(Node* node) { | |
| 23 switch (node->opcode()) { | |
| 24 case IrOpcode::kJSLoadNamed: | |
| 25 return ReduceJSLoadNamed(node); | |
| 26 default: | |
| 27 break; | |
| 28 } | |
| 29 return NoChange(); | |
| 30 } | |
| 31 | |
| 32 | |
| 33 Reduction JSTypeFeedbackLowering::ReduceJSLoadNamed(Node* node) { | |
| 34 DCHECK_EQ(IrOpcode::kJSLoadNamed, node->opcode()); | |
| 35 Node* receiver = NodeProperties::GetValueInput(node, 0); | |
| 36 Type* receiver_type = NodeProperties::GetType(receiver); | |
| 37 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1); | |
| 38 Node* effect = NodeProperties::GetEffectInput(node); | |
| 39 Node* control = NodeProperties::GetControlInput(node); | |
| 40 // We need to make optimistic assumptions to continue. | |
| 41 if (!(flags() & kDeoptimizationEnabled)) return NoChange(); | |
| 42 NamedAccess const& p = NamedAccessOf(node->op()); | |
| 43 if (!p.feedback().IsValid()) return NoChange(); // No feedback. | |
| 44 if (p.name().is_identical_to(factory()->length_string())) { | |
| 45 LoadICNexus nexus(p.feedback().vector(), p.feedback().slot()); | |
| 46 MapHandleList maps; | |
| 47 if (nexus.ExtractMaps(&maps) > 0) { | |
| 48 for (Handle<Map> map : maps) { | |
| 49 if (map->instance_type() >= FIRST_NONSTRING_TYPE) return NoChange(); | |
| 50 } | |
| 51 // Optimistic optimization for "length" property of strings. | |
| 52 if (receiver_type->Maybe(Type::TaggedSigned())) { | |
| 53 Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), receiver); | |
| 54 Node* branch = graph()->NewNode(common()->Branch(BranchHint::kFalse), | |
| 55 check, control); | |
| 56 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); | |
| 57 Node* deoptimize = graph()->NewNode(common()->Deoptimize(), frame_state, | |
| 58 effect, if_true); | |
| 59 // TODO(bmeurer): This should be on the AdvancedReducer somehow. | |
| 60 NodeProperties::MergeControlToEnd(graph(), common(), deoptimize); | |
| 61 control = graph()->NewNode(common()->IfFalse(), branch); | |
| 62 } | |
| 63 Node* receiver_map = effect = | |
| 64 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), | |
| 65 receiver, effect, control); | |
| 66 Node* receiver_instance_type = effect = graph()->NewNode( | |
| 67 simplified()->LoadField(AccessBuilder::ForMapInstanceType()), | |
| 68 receiver_map, effect, control); | |
| 69 Node* check = | |
| 70 graph()->NewNode(machine()->Uint32LessThan(), receiver_instance_type, | |
| 71 jsgraph()->Uint32Constant(FIRST_NONSTRING_TYPE)); | |
| 72 Node* branch = | |
| 73 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control); | |
| 74 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); | |
| 75 Node* deoptimize = graph()->NewNode(common()->Deoptimize(), frame_state, | |
| 76 effect, if_false); | |
| 77 // TODO(bmeurer): This should be on the AdvancedReducer somehow. | |
| 78 NodeProperties::MergeControlToEnd(graph(), common(), deoptimize); | |
| 79 control = graph()->NewNode(common()->IfTrue(), branch); | |
| 80 Node* value = effect = | |
| 81 graph()->NewNode(simplified()->LoadField( | |
| 82 AccessBuilder::ForStringLength(graph()->zone())), | |
| 83 receiver, effect, control); | |
| 84 ReplaceWithValue(node, value, effect, control); | |
| 85 return Replace(value); | |
| 86 } | |
| 87 } | |
| 88 return NoChange(); | |
| 89 } | |
| 90 | |
| 91 | |
| 92 Factory* JSTypeFeedbackLowering::factory() const { | |
| 93 return isolate()->factory(); | |
| 94 } | |
| 95 | |
| 96 | |
| 97 CommonOperatorBuilder* JSTypeFeedbackLowering::common() const { | |
| 98 return jsgraph()->common(); | |
| 99 } | |
| 100 | |
| 101 | |
| 102 Graph* JSTypeFeedbackLowering::graph() const { return jsgraph()->graph(); } | |
| 103 | |
| 104 | |
| 105 Isolate* JSTypeFeedbackLowering::isolate() const { | |
| 106 return jsgraph()->isolate(); | |
| 107 } | |
| 108 | |
| 109 | |
| 110 MachineOperatorBuilder* JSTypeFeedbackLowering::machine() const { | |
| 111 return jsgraph()->machine(); | |
| 112 } | |
| 113 | |
| 114 | |
| 115 SimplifiedOperatorBuilder* JSTypeFeedbackLowering::simplified() const { | |
| 116 return jsgraph()->simplified(); | |
| 117 } | |
| 118 | |
| 119 } // namespace compiler | |
| 120 } // namespace internal | |
| 121 } // namespace v8 | |
| OLD | NEW |