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-global-specialization.h" | 5 #include "src/compiler/js-global-specialization.h" |
6 | 6 |
7 #include "src/compilation-dependencies.h" | 7 #include "src/compilation-dependencies.h" |
8 #include "src/compiler/access-builder.h" | 8 #include "src/compiler/access-builder.h" |
9 #include "src/compiler/js-graph.h" | 9 #include "src/compiler/js-graph.h" |
10 #include "src/compiler/js-operator.h" | 10 #include "src/compiler/js-operator.h" |
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
177 jsgraph()->Constant(property_cell), effect, control); | 177 jsgraph()->Constant(property_cell), effect, control); |
178 return Replace(node, value, effect); | 178 return Replace(node, value, effect); |
179 } | 179 } |
180 | 180 |
181 | 181 |
182 Reduction JSGlobalSpecialization::ReduceStoreToPropertyCell( | 182 Reduction JSGlobalSpecialization::ReduceStoreToPropertyCell( |
183 Node* node, Handle<PropertyCell> property_cell) { | 183 Node* node, Handle<PropertyCell> property_cell) { |
184 Node* value = NodeProperties::GetValueInput(node, 2); | 184 Node* value = NodeProperties::GetValueInput(node, 2); |
185 Node* effect = NodeProperties::GetEffectInput(node); | 185 Node* effect = NodeProperties::GetEffectInput(node); |
186 Node* control = NodeProperties::GetControlInput(node); | 186 Node* control = NodeProperties::GetControlInput(node); |
187 Node* frame_state = NodeProperties::GetFrameStateInput(node, 1); | |
187 // We only specialize global data property access. | 188 // We only specialize global data property access. |
188 PropertyDetails property_details = property_cell->property_details(); | 189 PropertyDetails property_details = property_cell->property_details(); |
189 DCHECK_EQ(kData, property_details.kind()); | 190 DCHECK_EQ(kData, property_details.kind()); |
190 Handle<Object> property_cell_value(property_cell->value(), isolate()); | 191 Handle<Object> property_cell_value(property_cell->value(), isolate()); |
191 DCHECK(!property_cell_value->IsTheHole()); | 192 DCHECK(!property_cell_value->IsTheHole()); |
192 // Don't even bother trying to lower stores to read-only data properties. | 193 // Don't even bother trying to lower stores to read-only data properties. |
193 if (property_details.IsReadOnly()) return NoChange(); | 194 if (property_details.IsReadOnly()) return NoChange(); |
194 // Not much we can do if we run the generic pipeline here. | 195 // Not much we can do if we run the generic pipeline here. |
195 if (!(flags() & kTypingEnabled)) return NoChange(); | 196 if (!(flags() & kTypingEnabled)) return NoChange(); |
196 // TODO(bmeurer): For now we deal only with cells in mutable state. | 197 switch (property_details.cell_type()) { |
197 if (property_details.cell_type() != PropertyCellType::kMutable) { | 198 case PropertyCellType::kUndefined: { |
198 return NoChange(); | 199 return NoChange(); |
199 } | 200 } |
200 // Store to non-configurable, data property on the global can be lowered to | 201 case PropertyCellType::kConstant: { |
201 // a field store, even without deoptimization, because the property cannot be | 202 // Store to constant property cell requires deoptimization support, |
202 // deleted or reconfigured to an accessor/interceptor property. | 203 // because we might even need to eager deoptimize for mismatch. |
203 if (property_details.IsConfigurable()) { | 204 if (!(flags() & kDeoptimizationEnabled)) return NoChange(); |
204 // With deoptimization support, we can lower stores even to configurable | 205 dependencies()->AssumePropertyCell(property_cell); |
205 // data properties on the global object, by adding a code dependency on | 206 Node* check = |
206 // the cell. | 207 graph()->NewNode(simplified()->ReferenceEqual(Type::Tagged()), value, |
207 if (!(flags() & kDeoptimizationEnabled)) return NoChange(); | 208 jsgraph()->Constant(property_cell_value)); |
208 dependencies()->AssumePropertyCell(property_cell); | 209 Node* branch = |
210 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control); | |
211 Node* if_false = graph()->NewNode(common()->IfFalse(), branch); | |
212 Node* deoptimize = graph()->NewNode(common()->Deoptimize(), frame_state, | |
213 effect, if_false); | |
214 // TODO(bmeurer): This should be on the AdvancedReducer somehow. | |
215 NodeProperties::MergeControlToEnd(graph(), common(), deoptimize); | |
216 control = graph()->NewNode(common()->IfTrue(), branch); | |
217 return Replace(node, value, effect, control); | |
218 } | |
219 case PropertyCellType::kConstantType: { | |
220 // Store to constant-type property cell requires deoptimization support, | |
221 // because we might even need to eager deoptimize for mismatch. | |
222 if (!(flags() & kDeoptimizationEnabled)) return NoChange(); | |
223 dependencies()->AssumePropertyCell(property_cell); | |
224 Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), value); | |
225 if (property_cell_value->IsHeapObject()) { | |
226 Node* branch = graph()->NewNode(common()->Branch(BranchHint::kFalse), | |
227 check, control); | |
Jarin
2015/10/08 12:41:32
Hmm, interesting code reuse...
Benedikt Meurer
2015/10/08 12:52:28
Acknowledged.
| |
228 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); | |
229 Node* deoptimize = graph()->NewNode(common()->Deoptimize(), frame_state, | |
230 effect, if_true); | |
231 // TODO(bmeurer): This should be on the AdvancedReducer somehow. | |
232 NodeProperties::MergeControlToEnd(graph(), common(), deoptimize); | |
233 control = graph()->NewNode(common()->IfFalse(), branch); | |
234 Node* value_map = | |
235 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), | |
236 value, effect, control); | |
237 Handle<Map> property_cell_value_map( | |
238 Handle<HeapObject>::cast(property_cell_value)->map(), isolate()); | |
239 check = graph()->NewNode(simplified()->ReferenceEqual(Type::Internal()), | |
240 value_map, | |
241 jsgraph()->Constant(property_cell_value_map)); | |
242 } | |
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 break; | |
252 } | |
253 case PropertyCellType::kMutable: { | |
254 // Store to non-configurable, data property on the global can be lowered | |
255 // to a field store, even without deoptimization, because the property | |
256 // cannot be deleted or reconfigured to an accessor/interceptor property. | |
257 if (property_details.IsConfigurable()) { | |
258 // With deoptimization support, we can lower stores even to configurable | |
259 // data properties on the global object, by adding a code dependency on | |
260 // the cell. | |
261 if (!(flags() & kDeoptimizationEnabled)) return NoChange(); | |
262 dependencies()->AssumePropertyCell(property_cell); | |
263 } | |
264 break; | |
265 } | |
209 } | 266 } |
210 effect = graph()->NewNode( | 267 effect = graph()->NewNode( |
211 simplified()->StoreField(AccessBuilder::ForPropertyCellValue()), | 268 simplified()->StoreField(AccessBuilder::ForPropertyCellValue()), |
212 jsgraph()->Constant(property_cell), value, effect, control); | 269 jsgraph()->Constant(property_cell), value, effect, control); |
213 return Replace(node, value, effect, control); | 270 return Replace(node, value, effect, control); |
214 } | 271 } |
215 | 272 |
216 | 273 |
217 Reduction JSGlobalSpecialization::Replace(Node* node, Handle<Object> value) { | 274 Reduction JSGlobalSpecialization::Replace(Node* node, Handle<Object> value) { |
218 if (value->IsConsString()) { | 275 if (value->IsConsString()) { |
219 value = String::Flatten(Handle<String>::cast(value), TENURED); | 276 value = String::Flatten(Handle<String>::cast(value), TENURED); |
220 } | 277 } |
221 return Replace(node, jsgraph()->Constant(value)); | 278 return Replace(node, jsgraph()->Constant(value)); |
222 } | 279 } |
223 | 280 |
224 | 281 |
225 Graph* JSGlobalSpecialization::graph() const { return jsgraph()->graph(); } | 282 Graph* JSGlobalSpecialization::graph() const { return jsgraph()->graph(); } |
226 | 283 |
227 | 284 |
228 Isolate* JSGlobalSpecialization::isolate() const { | 285 Isolate* JSGlobalSpecialization::isolate() const { |
229 return jsgraph()->isolate(); | 286 return jsgraph()->isolate(); |
230 } | 287 } |
231 | 288 |
232 | 289 |
290 CommonOperatorBuilder* JSGlobalSpecialization::common() const { | |
291 return jsgraph()->common(); | |
292 } | |
293 | |
294 | |
233 JSOperatorBuilder* JSGlobalSpecialization::javascript() const { | 295 JSOperatorBuilder* JSGlobalSpecialization::javascript() const { |
234 return jsgraph()->javascript(); | 296 return jsgraph()->javascript(); |
235 } | 297 } |
236 | 298 |
237 } // namespace compiler | 299 } // namespace compiler |
238 } // namespace internal | 300 } // namespace internal |
239 } // namespace v8 | 301 } // namespace v8 |
OLD | NEW |