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/linkage.h" | 10 #include "src/compiler/linkage.h" |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
76 return NoChange(); | 76 return NoChange(); |
77 } | 77 } |
78 | 78 |
79 const Operator* op = | 79 const Operator* op = |
80 jsgraph_->javascript()->StoreContext(new_depth, access.index()); | 80 jsgraph_->javascript()->StoreContext(new_depth, access.index()); |
81 NodeProperties::ReplaceContextInput(node, new_context); | 81 NodeProperties::ReplaceContextInput(node, new_context); |
82 NodeProperties::ChangeOp(node, op); | 82 NodeProperties::ChangeOp(node, op); |
83 return Changed(node); | 83 return Changed(node); |
84 } | 84 } |
85 | 85 |
| 86 namespace { |
| 87 |
| 88 bool IsContextParameter(Node* node) { |
| 89 DCHECK_EQ(IrOpcode::kParameter, node->opcode()); |
| 90 Node* const start = NodeProperties::GetValueInput(node, 0); |
| 91 DCHECK_EQ(IrOpcode::kStart, start->opcode()); |
| 92 int const index = ParameterIndexOf(node->op()); |
| 93 // The context is always the last parameter to a JavaScript function, and |
| 94 // {Parameter} indices start at -1, so value outputs of {Start} look like |
| 95 // this: closure, receiver, param0, ..., paramN, context. |
| 96 return index == start->op()->ValueOutputCount() - 2; |
| 97 } |
| 98 |
| 99 // Given a context {node} and the {distance} from that context to the target |
| 100 // context (which we want to read from or store to), try to return a |
| 101 // specialization context. If successful, update {distance} to whatever |
| 102 // distance remains from the specialization context. |
| 103 MaybeHandle<Context> GetSpecializationContext(Node* node, size_t* distance, |
| 104 Maybe<OuterContext> maybe_outer) { |
| 105 switch (node->opcode()) { |
| 106 case IrOpcode::kHeapConstant: |
| 107 return Handle<Context>::cast(OpParameter<Handle<HeapObject>>(node)); |
| 108 case IrOpcode::kParameter: { |
| 109 OuterContext outer; |
| 110 if (maybe_outer.To(&outer) && IsContextParameter(node) && |
| 111 *distance >= outer.distance) { |
| 112 *distance -= outer.distance; |
| 113 return outer.context; |
| 114 } |
| 115 break; |
| 116 } |
| 117 default: |
| 118 break; |
| 119 } |
| 120 return MaybeHandle<Context>(); |
| 121 } |
| 122 |
| 123 } // anonymous namespace |
| 124 |
86 Reduction JSContextSpecialization::ReduceJSLoadContext(Node* node) { | 125 Reduction JSContextSpecialization::ReduceJSLoadContext(Node* node) { |
87 DCHECK_EQ(IrOpcode::kJSLoadContext, node->opcode()); | 126 DCHECK_EQ(IrOpcode::kJSLoadContext, node->opcode()); |
88 | 127 |
89 const ContextAccess& access = ContextAccessOf(node->op()); | 128 const ContextAccess& access = ContextAccessOf(node->op()); |
90 size_t depth = access.depth(); | 129 size_t depth = access.depth(); |
91 | 130 |
92 // First walk up the context chain in the graph as far as possible. | 131 // First walk up the context chain in the graph as far as possible. |
93 Node* outer = NodeProperties::GetOuterContext(node, &depth); | 132 Node* context = NodeProperties::GetOuterContext(node, &depth); |
94 | 133 |
95 Handle<Context> concrete; | 134 Handle<Context> concrete; |
96 if (!NodeProperties::GetSpecializationContext(outer, context()) | 135 if (!GetSpecializationContext(context, &depth, outer()).ToHandle(&concrete)) { |
97 .ToHandle(&concrete)) { | |
98 // We do not have a concrete context object, so we can only partially reduce | 136 // We do not have a concrete context object, so we can only partially reduce |
99 // the load by folding-in the outer context node. | 137 // the load by folding-in the outer context node. |
100 return SimplifyJSLoadContext(node, outer, depth); | 138 return SimplifyJSLoadContext(node, context, depth); |
101 } | 139 } |
102 | 140 |
103 // Now walk up the concrete context chain for the remaining depth. | 141 // Now walk up the concrete context chain for the remaining depth. |
104 for (; depth > 0; --depth) { | 142 for (; depth > 0; --depth) { |
105 concrete = handle(concrete->previous(), isolate()); | 143 concrete = handle(concrete->previous(), isolate()); |
106 } | 144 } |
107 | 145 |
108 if (!access.immutable()) { | 146 if (!access.immutable()) { |
109 // We found the requested context object but since the context slot is | 147 // We found the requested context object but since the context slot is |
110 // mutable we can only partially reduce the load. | 148 // mutable we can only partially reduce the load. |
(...skipping 21 matching lines...) Expand all Loading... |
132 | 170 |
133 | 171 |
134 Reduction JSContextSpecialization::ReduceJSStoreContext(Node* node) { | 172 Reduction JSContextSpecialization::ReduceJSStoreContext(Node* node) { |
135 DCHECK_EQ(IrOpcode::kJSStoreContext, node->opcode()); | 173 DCHECK_EQ(IrOpcode::kJSStoreContext, node->opcode()); |
136 | 174 |
137 const ContextAccess& access = ContextAccessOf(node->op()); | 175 const ContextAccess& access = ContextAccessOf(node->op()); |
138 size_t depth = access.depth(); | 176 size_t depth = access.depth(); |
139 | 177 |
140 // First walk up the context chain in the graph until we reduce the depth to 0 | 178 // First walk up the context chain in the graph until we reduce the depth to 0 |
141 // or hit a node that does not have a CreateXYZContext operator. | 179 // or hit a node that does not have a CreateXYZContext operator. |
142 Node* outer = NodeProperties::GetOuterContext(node, &depth); | 180 Node* context = NodeProperties::GetOuterContext(node, &depth); |
143 | 181 |
144 Handle<Context> concrete; | 182 Handle<Context> concrete; |
145 if (!NodeProperties::GetSpecializationContext(outer, context()) | 183 if (!GetSpecializationContext(context, &depth, outer()).ToHandle(&concrete)) { |
146 .ToHandle(&concrete)) { | |
147 // We do not have a concrete context object, so we can only partially reduce | 184 // We do not have a concrete context object, so we can only partially reduce |
148 // the load by folding-in the outer context node. | 185 // the load by folding-in the outer context node. |
149 return SimplifyJSStoreContext(node, outer, depth); | 186 return SimplifyJSStoreContext(node, context, depth); |
150 } | 187 } |
151 | 188 |
152 // Now walk up the concrete context chain for the remaining depth. | 189 // Now walk up the concrete context chain for the remaining depth. |
153 for (; depth > 0; --depth) { | 190 for (; depth > 0; --depth) { |
154 concrete = handle(concrete->previous(), isolate()); | 191 concrete = handle(concrete->previous(), isolate()); |
155 } | 192 } |
156 | 193 |
157 return SimplifyJSStoreContext(node, jsgraph()->Constant(concrete), depth); | 194 return SimplifyJSStoreContext(node, jsgraph()->Constant(concrete), depth); |
158 } | 195 } |
159 | 196 |
160 | 197 |
161 Isolate* JSContextSpecialization::isolate() const { | 198 Isolate* JSContextSpecialization::isolate() const { |
162 return jsgraph()->isolate(); | 199 return jsgraph()->isolate(); |
163 } | 200 } |
164 | 201 |
165 | 202 |
166 JSOperatorBuilder* JSContextSpecialization::javascript() const { | 203 JSOperatorBuilder* JSContextSpecialization::javascript() const { |
167 return jsgraph()->javascript(); | 204 return jsgraph()->javascript(); |
168 } | 205 } |
169 | 206 |
170 } // namespace compiler | 207 } // namespace compiler |
171 } // namespace internal | 208 } // namespace internal |
172 } // namespace v8 | 209 } // namespace v8 |
OLD | NEW |