OLD | NEW |
---|---|
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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-context-specialization.h" | 5 #include "src/compiler/js-context-specialization.h" |
6 | 6 |
7 #include "src/compiler/common-operator.h" | 7 #include "src/compiler/common-operator.h" |
8 #include "src/compiler/js-graph.h" | 8 #include "src/compiler/js-graph.h" |
9 #include "src/compiler/js-operator.h" | 9 #include "src/compiler/js-operator.h" |
10 #include "src/compiler/node-matchers.h" | 10 #include "src/compiler/node-matchers.h" |
(...skipping 10 matching lines...) Expand all Loading... | |
21 case IrOpcode::kJSLoadContext: | 21 case IrOpcode::kJSLoadContext: |
22 return ReduceJSLoadContext(node); | 22 return ReduceJSLoadContext(node); |
23 case IrOpcode::kJSStoreContext: | 23 case IrOpcode::kJSStoreContext: |
24 return ReduceJSStoreContext(node); | 24 return ReduceJSStoreContext(node); |
25 default: | 25 default: |
26 break; | 26 break; |
27 } | 27 } |
28 return NoChange(); | 28 return NoChange(); |
29 } | 29 } |
30 | 30 |
31 namespace { | |
31 | 32 |
32 MaybeHandle<Context> JSContextSpecialization::GetSpecializationContext( | 33 Node* GetOuterContext(Node* node, size_t* depth) { |
33 Node* node) { | 34 Node* context = NodeProperties::GetContextInput(node); |
34 DCHECK(node->opcode() == IrOpcode::kJSLoadContext || | 35 while (*depth > 0 && IrOpcode::IsContextExtendingOpcode(context->opcode())) { |
35 node->opcode() == IrOpcode::kJSStoreContext); | 36 context = NodeProperties::GetContextInput(context); |
36 Node* const object = NodeProperties::GetContextInput(node); | 37 (*depth)--; |
37 return NodeProperties::GetSpecializationContext(object, context()); | 38 } |
39 return context; | |
40 } // XXX: Move to node-properties? | |
Michael Starzinger
2017/01/13 13:36:26
nit: s/XXX/TODO/ here. Also maybe move to in front
neis
2017/01/13 14:08:02
I actually moved it to NodeProperties now.
| |
41 | |
42 } // anonymous namespace | |
43 | |
44 Reduction JSContextSpecialization::StrengthenJSLoadContext(Node* node, | |
Michael Starzinger
2017/01/13 13:36:26
random non-actionable rambling: As discussed offli
neis
2017/01/13 14:08:02
Renamed to SimplifyJS...
| |
45 Node* new_context, | |
46 size_t new_depth) { | |
47 DCHECK_EQ(IrOpcode::kJSLoadContext, node->opcode()); | |
48 const ContextAccess& access = ContextAccessOf(node->op()); | |
49 DCHECK_LE(new_depth, access.depth()); | |
50 | |
51 if (new_depth == access.depth() && | |
52 new_context == NodeProperties::GetContextInput(node)) { | |
53 return NoChange(); | |
54 } | |
55 | |
56 const Operator* op = jsgraph_->javascript()->LoadContext( | |
57 new_depth, access.index(), access.immutable()); | |
58 NodeProperties::ReplaceContextInput(node, new_context); | |
59 NodeProperties::ChangeOp(node, op); | |
60 return Changed(node); | |
38 } | 61 } |
39 | 62 |
63 Reduction JSContextSpecialization::StrengthenJSStoreContext(Node* node, | |
64 Node* new_context, | |
65 size_t new_depth) { | |
66 DCHECK_EQ(IrOpcode::kJSStoreContext, node->opcode()); | |
67 const ContextAccess& access = ContextAccessOf(node->op()); | |
68 DCHECK_LE(new_depth, access.depth()); | |
69 | |
70 if (new_depth == access.depth() && | |
71 new_context == NodeProperties::GetContextInput(node)) { | |
72 return NoChange(); | |
73 } | |
74 | |
75 const Operator* op = | |
76 jsgraph_->javascript()->StoreContext(new_depth, access.index()); | |
77 NodeProperties::ReplaceContextInput(node, new_context); | |
78 NodeProperties::ChangeOp(node, op); | |
79 return Changed(node); | |
80 } | |
40 | 81 |
41 Reduction JSContextSpecialization::ReduceJSLoadContext(Node* node) { | 82 Reduction JSContextSpecialization::ReduceJSLoadContext(Node* node) { |
42 DCHECK_EQ(IrOpcode::kJSLoadContext, node->opcode()); | 83 DCHECK_EQ(IrOpcode::kJSLoadContext, node->opcode()); |
43 | 84 |
44 // Get the specialization context from the node. | 85 const ContextAccess& access = ContextAccessOf(node->op()); |
45 Handle<Context> context; | 86 size_t depth = access.depth(); |
46 if (!GetSpecializationContext(node).ToHandle(&context)) return NoChange(); | |
47 | 87 |
48 // Find the right parent context. | 88 // First walk up the context chain in the graph until we reduce the depth to 0 |
49 const ContextAccess& access = ContextAccessOf(node->op()); | 89 // or hit a node that does not have a CreateXYZContext operator. |
50 for (size_t i = access.depth(); i > 0; --i) { | 90 Node* outer = GetOuterContext(node, &depth); |
51 context = handle(context->previous(), isolate()); | 91 |
92 Handle<Context> concrete; | |
93 if (!NodeProperties::GetSpecializationContext(outer, context()) | |
94 .ToHandle(&concrete)) { | |
95 // We do not have a concrete context object, so we can only partially reduce | |
96 // the load by folding-in the outer context node. | |
97 return StrengthenJSLoadContext(node, outer, depth); | |
52 } | 98 } |
53 | 99 |
54 // If the access itself is mutable, only fold-in the parent. | 100 // Now walk up the concrete context chain for the remaining depth. |
101 for (; depth > 0; --depth) { | |
102 concrete = handle(concrete->previous(), isolate()); | |
103 } | |
104 | |
55 if (!access.immutable()) { | 105 if (!access.immutable()) { |
56 // The access does not have to look up a parent, nothing to fold. | 106 // We found the requested context object but since the context slot is |
57 if (access.depth() == 0) { | 107 // mutable we can only partially reduce the load. |
58 return NoChange(); | 108 return StrengthenJSLoadContext(node, jsgraph()->Constant(concrete), depth); |
59 } | |
60 const Operator* op = jsgraph_->javascript()->LoadContext( | |
61 0, access.index(), access.immutable()); | |
62 NodeProperties::ReplaceContextInput(node, jsgraph_->Constant(context)); | |
63 NodeProperties::ChangeOp(node, op); | |
64 return Changed(node); | |
65 } | 109 } |
66 Handle<Object> value = | |
67 handle(context->get(static_cast<int>(access.index())), isolate()); | |
68 | 110 |
69 // Even though the context slot is immutable, the context might have escaped | 111 // Even though the context slot is immutable, the context might have escaped |
70 // before the function to which it belongs has initialized the slot. | 112 // before the function to which it belongs has initialized the slot. |
71 // We must be conservative and check if the value in the slot is currently the | 113 // We must be conservative and check if the value in the slot is currently |
72 // hole or undefined. If it is neither of these, then it must be initialized. | 114 // the hole or undefined. Only if it is neither of these, can we be sure that |
115 // it won't change anymore. | |
116 Handle<Object> value(concrete->get(static_cast<int>(access.index())), | |
117 isolate()); | |
73 if (value->IsUndefined(isolate()) || value->IsTheHole(isolate())) { | 118 if (value->IsUndefined(isolate()) || value->IsTheHole(isolate())) { |
74 return NoChange(); | 119 return StrengthenJSLoadContext(node, jsgraph()->Constant(concrete), depth); |
75 } | 120 } |
76 | 121 |
77 // Success. The context load can be replaced with the constant. | 122 // Success. The context load can be replaced with the constant. |
78 // TODO(titzer): record the specialization for sharing code across multiple | 123 // TODO(titzer): record the specialization for sharing code across multiple |
79 // contexts that have the same value in the corresponding context slot. | 124 // contexts that have the same value in the corresponding context slot. |
80 Node* constant = jsgraph_->Constant(value); | 125 Node* constant = jsgraph_->Constant(value); |
81 ReplaceWithValue(node, constant); | 126 ReplaceWithValue(node, constant); |
82 return Replace(constant); | 127 return Replace(constant); |
83 } | 128 } |
84 | 129 |
85 | 130 |
86 Reduction JSContextSpecialization::ReduceJSStoreContext(Node* node) { | 131 Reduction JSContextSpecialization::ReduceJSStoreContext(Node* node) { |
87 DCHECK_EQ(IrOpcode::kJSStoreContext, node->opcode()); | 132 DCHECK_EQ(IrOpcode::kJSStoreContext, node->opcode()); |
88 | 133 |
89 // Get the specialization context from the node. | 134 const ContextAccess& access = ContextAccessOf(node->op()); |
90 Handle<Context> context; | 135 size_t depth = access.depth(); |
91 if (!GetSpecializationContext(node).ToHandle(&context)) return NoChange(); | |
92 | 136 |
93 // The access does not have to look up a parent, nothing to fold. | 137 // First walk up the context chain in the graph until we reduce the depth to 0 |
94 const ContextAccess& access = ContextAccessOf(node->op()); | 138 // or hit a node that does not have a CreateXYZContext operator. |
95 if (access.depth() == 0) { | 139 Node* outer = GetOuterContext(node, &depth); |
96 return NoChange(); | 140 |
141 Handle<Context> concrete; | |
142 if (!NodeProperties::GetSpecializationContext(outer, context()) | |
143 .ToHandle(&concrete)) { | |
144 // We do not have a concrete context object, so we can only partially reduce | |
145 // the load by folding-in the outer context node. | |
146 return StrengthenJSStoreContext(node, outer, depth); | |
97 } | 147 } |
98 | 148 |
99 // Find the right parent context. | 149 // Now walk up the concrete context chain for the remaining depth. |
100 for (size_t i = access.depth(); i > 0; --i) { | 150 for (; depth > 0; --depth) { |
101 context = handle(context->previous(), isolate()); | 151 concrete = handle(concrete->previous(), isolate()); |
102 } | 152 } |
103 | 153 |
104 NodeProperties::ReplaceContextInput(node, jsgraph_->Constant(context)); | 154 return StrengthenJSStoreContext(node, jsgraph()->Constant(concrete), depth); |
105 NodeProperties::ChangeOp(node, javascript()->StoreContext(0, access.index())); | |
106 return Changed(node); | |
107 } | 155 } |
108 | 156 |
109 | 157 |
110 Isolate* JSContextSpecialization::isolate() const { | 158 Isolate* JSContextSpecialization::isolate() const { |
111 return jsgraph()->isolate(); | 159 return jsgraph()->isolate(); |
112 } | 160 } |
113 | 161 |
114 | 162 |
115 JSOperatorBuilder* JSContextSpecialization::javascript() const { | 163 JSOperatorBuilder* JSContextSpecialization::javascript() const { |
116 return jsgraph()->javascript(); | 164 return jsgraph()->javascript(); |
117 } | 165 } |
118 | 166 |
119 } // namespace compiler | 167 } // namespace compiler |
120 } // namespace internal | 168 } // namespace internal |
121 } // namespace v8 | 169 } // namespace v8 |
OLD | NEW |