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-object-specialization.h" | 5 #include "src/compiler/js-global-object-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/common-operator.h" | 9 #include "src/compiler/common-operator.h" |
10 #include "src/compiler/js-graph.h" | 10 #include "src/compiler/js-graph.h" |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
42 return ReduceJSStoreGlobal(node); | 42 return ReduceJSStoreGlobal(node); |
43 default: | 43 default: |
44 break; | 44 break; |
45 } | 45 } |
46 return NoChange(); | 46 return NoChange(); |
47 } | 47 } |
48 | 48 |
49 namespace { | 49 namespace { |
50 | 50 |
51 FieldAccess ForPropertyCellValue(MachineRepresentation representation, | 51 FieldAccess ForPropertyCellValue(MachineRepresentation representation, |
52 Type* type, Handle<Name> name) { | 52 Type* type, MaybeHandle<Map> map, |
| 53 Handle<Name> name) { |
53 WriteBarrierKind kind = kFullWriteBarrier; | 54 WriteBarrierKind kind = kFullWriteBarrier; |
54 if (representation == MachineRepresentation::kTaggedSigned) { | 55 if (representation == MachineRepresentation::kTaggedSigned) { |
55 kind = kNoWriteBarrier; | 56 kind = kNoWriteBarrier; |
56 } else if (representation == MachineRepresentation::kTaggedPointer) { | 57 } else if (representation == MachineRepresentation::kTaggedPointer) { |
57 kind = kPointerWriteBarrier; | 58 kind = kPointerWriteBarrier; |
58 } | 59 } |
59 MachineType r = MachineType::TypeForRepresentation(representation); | 60 MachineType r = MachineType::TypeForRepresentation(representation); |
60 FieldAccess access = {kTaggedBase, PropertyCell::kValueOffset, name, type, r, | 61 FieldAccess access = { |
61 kind}; | 62 kTaggedBase, PropertyCell::kValueOffset, name, map, type, r, kind}; |
62 return access; | 63 return access; |
63 } | 64 } |
64 } // namespace | 65 } // namespace |
65 | 66 |
66 Reduction JSGlobalObjectSpecialization::ReduceJSLoadGlobal(Node* node) { | 67 Reduction JSGlobalObjectSpecialization::ReduceJSLoadGlobal(Node* node) { |
67 DCHECK_EQ(IrOpcode::kJSLoadGlobal, node->opcode()); | 68 DCHECK_EQ(IrOpcode::kJSLoadGlobal, node->opcode()); |
68 Handle<Name> name = LoadGlobalParametersOf(node->op()).name(); | 69 Handle<Name> name = LoadGlobalParametersOf(node->op()).name(); |
69 Node* effect = NodeProperties::GetEffectInput(node); | 70 Node* effect = NodeProperties::GetEffectInput(node); |
70 Node* control = NodeProperties::GetControlInput(node); | 71 Node* control = NodeProperties::GetControlInput(node); |
71 | 72 |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
108 | 109 |
109 // Load from constant/undefined global property can be constant-folded. | 110 // Load from constant/undefined global property can be constant-folded. |
110 if (property_details.cell_type() == PropertyCellType::kConstant || | 111 if (property_details.cell_type() == PropertyCellType::kConstant || |
111 property_details.cell_type() == PropertyCellType::kUndefined) { | 112 property_details.cell_type() == PropertyCellType::kUndefined) { |
112 Node* value = jsgraph()->Constant(property_cell_value); | 113 Node* value = jsgraph()->Constant(property_cell_value); |
113 ReplaceWithValue(node, value); | 114 ReplaceWithValue(node, value); |
114 return Replace(value); | 115 return Replace(value); |
115 } | 116 } |
116 | 117 |
117 // Load from constant type cell can benefit from type feedback. | 118 // Load from constant type cell can benefit from type feedback. |
| 119 MaybeHandle<Map> map; |
118 Type* property_cell_value_type = Type::NonInternal(); | 120 Type* property_cell_value_type = Type::NonInternal(); |
119 MachineRepresentation representation = MachineRepresentation::kTagged; | 121 MachineRepresentation representation = MachineRepresentation::kTagged; |
120 if (property_details.cell_type() == PropertyCellType::kConstantType) { | 122 if (property_details.cell_type() == PropertyCellType::kConstantType) { |
121 // Compute proper type based on the current value in the cell. | 123 // Compute proper type based on the current value in the cell. |
122 if (property_cell_value->IsSmi()) { | 124 if (property_cell_value->IsSmi()) { |
123 property_cell_value_type = Type::SignedSmall(); | 125 property_cell_value_type = Type::SignedSmall(); |
124 representation = MachineRepresentation::kTaggedSigned; | 126 representation = MachineRepresentation::kTaggedSigned; |
125 } else if (property_cell_value->IsNumber()) { | 127 } else if (property_cell_value->IsNumber()) { |
126 property_cell_value_type = Type::Number(); | 128 property_cell_value_type = Type::Number(); |
127 representation = MachineRepresentation::kTaggedPointer; | 129 representation = MachineRepresentation::kTaggedPointer; |
128 } else { | 130 } else { |
129 // TODO(turbofan): Track the property_cell_value_map on the FieldAccess | |
130 // below and use it in LoadElimination to eliminate map checks. | |
131 Handle<Map> property_cell_value_map( | 131 Handle<Map> property_cell_value_map( |
132 Handle<HeapObject>::cast(property_cell_value)->map(), isolate()); | 132 Handle<HeapObject>::cast(property_cell_value)->map(), isolate()); |
133 property_cell_value_type = Type::For(property_cell_value_map); | 133 property_cell_value_type = Type::For(property_cell_value_map); |
134 representation = MachineRepresentation::kTaggedPointer; | 134 representation = MachineRepresentation::kTaggedPointer; |
| 135 |
| 136 // We can only use the property cell value map for map check elimination |
| 137 // if it's stable, i.e. the HeapObject wasn't mutated without the cell |
| 138 // state being updated. |
| 139 if (property_cell_value_map->is_stable()) { |
| 140 dependencies()->AssumeMapStable(property_cell_value_map); |
| 141 map = property_cell_value_map; |
| 142 } |
135 } | 143 } |
136 } | 144 } |
137 Node* value = effect = | 145 Node* value = effect = graph()->NewNode( |
138 graph()->NewNode(simplified()->LoadField(ForPropertyCellValue( | 146 simplified()->LoadField(ForPropertyCellValue( |
139 representation, property_cell_value_type, name)), | 147 representation, property_cell_value_type, map, name)), |
140 jsgraph()->HeapConstant(property_cell), effect, control); | 148 jsgraph()->HeapConstant(property_cell), effect, control); |
141 ReplaceWithValue(node, value, effect, control); | 149 ReplaceWithValue(node, value, effect, control); |
142 return Replace(value); | 150 return Replace(value); |
143 } | 151 } |
144 | 152 |
145 | 153 |
146 Reduction JSGlobalObjectSpecialization::ReduceJSStoreGlobal(Node* node) { | 154 Reduction JSGlobalObjectSpecialization::ReduceJSStoreGlobal(Node* node) { |
147 DCHECK_EQ(IrOpcode::kJSStoreGlobal, node->opcode()); | 155 DCHECK_EQ(IrOpcode::kJSStoreGlobal, node->opcode()); |
148 Handle<Name> name = StoreGlobalParametersOf(node->op()).name(); | 156 Handle<Name> name = StoreGlobalParametersOf(node->op()).name(); |
149 Node* value = NodeProperties::GetValueInput(node, 0); | 157 Node* value = NodeProperties::GetValueInput(node, 0); |
150 Node* effect = NodeProperties::GetEffectInput(node); | 158 Node* effect = NodeProperties::GetEffectInput(node); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
211 value, effect, control); | 219 value, effect, control); |
212 property_cell_value_type = Type::OtherInternal(); | 220 property_cell_value_type = Type::OtherInternal(); |
213 representation = MachineRepresentation::kTaggedPointer; | 221 representation = MachineRepresentation::kTaggedPointer; |
214 } else { | 222 } else { |
215 // Check that the {value} is a Smi. | 223 // Check that the {value} is a Smi. |
216 value = effect = | 224 value = effect = |
217 graph()->NewNode(simplified()->CheckSmi(), value, effect, control); | 225 graph()->NewNode(simplified()->CheckSmi(), value, effect, control); |
218 property_cell_value_type = Type::SignedSmall(); | 226 property_cell_value_type = Type::SignedSmall(); |
219 representation = MachineRepresentation::kTaggedSigned; | 227 representation = MachineRepresentation::kTaggedSigned; |
220 } | 228 } |
221 effect = graph()->NewNode( | 229 effect = graph()->NewNode(simplified()->StoreField(ForPropertyCellValue( |
222 simplified()->StoreField(ForPropertyCellValue( | 230 representation, property_cell_value_type, |
223 representation, property_cell_value_type, name)), | 231 MaybeHandle<Map>(), name)), |
224 jsgraph()->HeapConstant(property_cell), value, effect, control); | 232 jsgraph()->HeapConstant(property_cell), value, |
| 233 effect, control); |
225 break; | 234 break; |
226 } | 235 } |
227 case PropertyCellType::kMutable: { | 236 case PropertyCellType::kMutable: { |
228 // Record a code dependency on the cell, and just deoptimize if the | 237 // Record a code dependency on the cell, and just deoptimize if the |
229 // property ever becomes read-only. | 238 // property ever becomes read-only. |
230 dependencies()->AssumePropertyCell(property_cell); | 239 dependencies()->AssumePropertyCell(property_cell); |
231 effect = graph()->NewNode( | 240 effect = graph()->NewNode( |
232 simplified()->StoreField(ForPropertyCellValue( | 241 simplified()->StoreField(ForPropertyCellValue( |
233 MachineRepresentation::kTagged, Type::NonInternal(), name)), | 242 MachineRepresentation::kTagged, Type::NonInternal(), |
| 243 MaybeHandle<Map>(), name)), |
234 jsgraph()->HeapConstant(property_cell), value, effect, control); | 244 jsgraph()->HeapConstant(property_cell), value, effect, control); |
235 break; | 245 break; |
236 } | 246 } |
237 } | 247 } |
238 ReplaceWithValue(node, value, effect, control); | 248 ReplaceWithValue(node, value, effect, control); |
239 return Replace(value); | 249 return Replace(value); |
240 } | 250 } |
241 | 251 |
242 bool JSGlobalObjectSpecialization::LookupInScriptContextTable( | 252 bool JSGlobalObjectSpecialization::LookupInScriptContextTable( |
243 Handle<Name> name, ScriptContextTableLookupResult* result) { | 253 Handle<Name> name, ScriptContextTableLookupResult* result) { |
(...skipping 29 matching lines...) Expand all Loading... |
273 return jsgraph()->javascript(); | 283 return jsgraph()->javascript(); |
274 } | 284 } |
275 | 285 |
276 SimplifiedOperatorBuilder* JSGlobalObjectSpecialization::simplified() const { | 286 SimplifiedOperatorBuilder* JSGlobalObjectSpecialization::simplified() const { |
277 return jsgraph()->simplified(); | 287 return jsgraph()->simplified(); |
278 } | 288 } |
279 | 289 |
280 } // namespace compiler | 290 } // namespace compiler |
281 } // namespace internal | 291 } // namespace internal |
282 } // namespace v8 | 292 } // namespace v8 |
OLD | NEW |