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); |
| 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 |