| 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/escape-analysis-reducer.h" | 5 #include "src/compiler/escape-analysis-reducer.h" |
| 6 | 6 |
| 7 #include "src/compiler/all-nodes.h" | 7 #include "src/compiler/all-nodes.h" |
| 8 #include "src/compiler/js-graph.h" | 8 #include "src/compiler/js-graph.h" |
| 9 #include "src/counters.h" | 9 #include "src/counters.h" |
| 10 | 10 |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 114 Type* const original_type = NodeProperties::GetType(original); | 114 Type* const original_type = NodeProperties::GetType(original); |
| 115 if (!replacement_type->Is(original_type)) { | 115 if (!replacement_type->Is(original_type)) { |
| 116 Node* const control = NodeProperties::GetControlInput(original); | 116 Node* const control = NodeProperties::GetControlInput(original); |
| 117 replacement = jsgraph->graph()->NewNode( | 117 replacement = jsgraph->graph()->NewNode( |
| 118 jsgraph->common()->TypeGuard(original_type), replacement, control); | 118 jsgraph->common()->TypeGuard(original_type), replacement, control); |
| 119 NodeProperties::SetType(replacement, original_type); | 119 NodeProperties::SetType(replacement, original_type); |
| 120 } | 120 } |
| 121 return replacement; | 121 return replacement; |
| 122 } | 122 } |
| 123 | 123 |
| 124 Node* SkipTypeGuards(Node* node) { |
| 125 while (node->opcode() == IrOpcode::kTypeGuard) { |
| 126 node = NodeProperties::GetValueInput(node, 0); |
| 127 } |
| 128 return node; |
| 129 } |
| 130 |
| 124 } // namespace | 131 } // namespace |
| 125 | 132 |
| 126 Reduction EscapeAnalysisReducer::ReduceLoad(Node* node) { | 133 Reduction EscapeAnalysisReducer::ReduceLoad(Node* node) { |
| 127 DCHECK(node->opcode() == IrOpcode::kLoadField || | 134 DCHECK(node->opcode() == IrOpcode::kLoadField || |
| 128 node->opcode() == IrOpcode::kLoadElement); | 135 node->opcode() == IrOpcode::kLoadElement); |
| 129 if (node->id() < static_cast<NodeId>(fully_reduced_.length())) { | 136 if (node->id() < static_cast<NodeId>(fully_reduced_.length())) { |
| 130 fully_reduced_.Add(node->id()); | 137 fully_reduced_.Add(node->id()); |
| 131 } | 138 } |
| 132 if (escape_analysis()->IsVirtual(NodeProperties::GetValueInput(node, 0))) { | 139 if (escape_analysis()->IsVirtual( |
| 140 SkipTypeGuards(NodeProperties::GetValueInput(node, 0)))) { |
| 133 if (Node* rep = escape_analysis()->GetReplacement(node)) { | 141 if (Node* rep = escape_analysis()->GetReplacement(node)) { |
| 134 isolate()->counters()->turbo_escape_loads_replaced()->Increment(); | 142 isolate()->counters()->turbo_escape_loads_replaced()->Increment(); |
| 135 TRACE("Replaced #%d (%s) with #%d (%s)\n", node->id(), | 143 TRACE("Replaced #%d (%s) with #%d (%s)\n", node->id(), |
| 136 node->op()->mnemonic(), rep->id(), rep->op()->mnemonic()); | 144 node->op()->mnemonic(), rep->id(), rep->op()->mnemonic()); |
| 137 rep = MaybeGuard(jsgraph(), zone(), node, rep); | 145 rep = MaybeGuard(jsgraph(), zone(), node, rep); |
| 138 ReplaceWithValue(node, rep); | 146 ReplaceWithValue(node, rep); |
| 139 return Replace(rep); | 147 return Replace(rep); |
| 140 } | 148 } |
| 141 } | 149 } |
| 142 return NoChange(); | 150 return NoChange(); |
| 143 } | 151 } |
| 144 | 152 |
| 145 | 153 |
| 146 Reduction EscapeAnalysisReducer::ReduceStore(Node* node) { | 154 Reduction EscapeAnalysisReducer::ReduceStore(Node* node) { |
| 147 DCHECK(node->opcode() == IrOpcode::kStoreField || | 155 DCHECK(node->opcode() == IrOpcode::kStoreField || |
| 148 node->opcode() == IrOpcode::kStoreElement); | 156 node->opcode() == IrOpcode::kStoreElement); |
| 149 if (node->id() < static_cast<NodeId>(fully_reduced_.length())) { | 157 if (node->id() < static_cast<NodeId>(fully_reduced_.length())) { |
| 150 fully_reduced_.Add(node->id()); | 158 fully_reduced_.Add(node->id()); |
| 151 } | 159 } |
| 152 if (escape_analysis()->IsVirtual(NodeProperties::GetValueInput(node, 0))) { | 160 if (escape_analysis()->IsVirtual( |
| 161 SkipTypeGuards(NodeProperties::GetValueInput(node, 0)))) { |
| 153 TRACE("Removed #%d (%s) from effect chain\n", node->id(), | 162 TRACE("Removed #%d (%s) from effect chain\n", node->id(), |
| 154 node->op()->mnemonic()); | 163 node->op()->mnemonic()); |
| 155 RelaxEffectsAndControls(node); | 164 RelaxEffectsAndControls(node); |
| 156 return Changed(node); | 165 return Changed(node); |
| 157 } | 166 } |
| 158 return NoChange(); | 167 return NoChange(); |
| 159 } | 168 } |
| 160 | 169 |
| 161 | 170 |
| 162 Reduction EscapeAnalysisReducer::ReduceAllocate(Node* node) { | 171 Reduction EscapeAnalysisReducer::ReduceAllocate(Node* node) { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 197 } | 206 } |
| 198 #endif // DEBUG | 207 #endif // DEBUG |
| 199 return Changed(node); | 208 return Changed(node); |
| 200 } | 209 } |
| 201 return NoChange(); | 210 return NoChange(); |
| 202 } | 211 } |
| 203 | 212 |
| 204 | 213 |
| 205 Reduction EscapeAnalysisReducer::ReduceReferenceEqual(Node* node) { | 214 Reduction EscapeAnalysisReducer::ReduceReferenceEqual(Node* node) { |
| 206 DCHECK_EQ(node->opcode(), IrOpcode::kReferenceEqual); | 215 DCHECK_EQ(node->opcode(), IrOpcode::kReferenceEqual); |
| 207 Node* left = NodeProperties::GetValueInput(node, 0); | 216 Node* left = SkipTypeGuards(NodeProperties::GetValueInput(node, 0)); |
| 208 Node* right = NodeProperties::GetValueInput(node, 1); | 217 Node* right = SkipTypeGuards(NodeProperties::GetValueInput(node, 1)); |
| 209 if (escape_analysis()->IsVirtual(left)) { | 218 if (escape_analysis()->IsVirtual(left)) { |
| 210 if (escape_analysis()->IsVirtual(right) && | 219 if (escape_analysis()->IsVirtual(right) && |
| 211 escape_analysis()->CompareVirtualObjects(left, right)) { | 220 escape_analysis()->CompareVirtualObjects(left, right)) { |
| 212 ReplaceWithValue(node, jsgraph()->TrueConstant()); | 221 ReplaceWithValue(node, jsgraph()->TrueConstant()); |
| 213 TRACE("Replaced ref eq #%d with true\n", node->id()); | 222 TRACE("Replaced ref eq #%d with true\n", node->id()); |
| 214 return Replace(jsgraph()->TrueConstant()); | 223 return Replace(jsgraph()->TrueConstant()); |
| 215 } | 224 } |
| 216 // Right-hand side is not a virtual object, or a different one. | 225 // Right-hand side is not a virtual object, or a different one. |
| 217 ReplaceWithValue(node, jsgraph()->FalseConstant()); | 226 ReplaceWithValue(node, jsgraph()->FalseConstant()); |
| 218 TRACE("Replaced ref eq #%d with false\n", node->id()); | 227 TRACE("Replaced ref eq #%d with false\n", node->id()); |
| 219 return Replace(jsgraph()->FalseConstant()); | 228 return Replace(jsgraph()->FalseConstant()); |
| 220 } else if (escape_analysis()->IsVirtual(right)) { | 229 } else if (escape_analysis()->IsVirtual(right)) { |
| 221 // Left-hand side is not a virtual object. | 230 // Left-hand side is not a virtual object. |
| 222 ReplaceWithValue(node, jsgraph()->FalseConstant()); | 231 ReplaceWithValue(node, jsgraph()->FalseConstant()); |
| 223 TRACE("Replaced ref eq #%d with false\n", node->id()); | 232 TRACE("Replaced ref eq #%d with false\n", node->id()); |
| 224 return Replace(jsgraph()->FalseConstant()); | 233 return Replace(jsgraph()->FalseConstant()); |
| 225 } | 234 } |
| 226 return NoChange(); | 235 return NoChange(); |
| 227 } | 236 } |
| 228 | 237 |
| 229 | 238 |
| 230 Reduction EscapeAnalysisReducer::ReduceObjectIsSmi(Node* node) { | 239 Reduction EscapeAnalysisReducer::ReduceObjectIsSmi(Node* node) { |
| 231 DCHECK_EQ(node->opcode(), IrOpcode::kObjectIsSmi); | 240 DCHECK_EQ(node->opcode(), IrOpcode::kObjectIsSmi); |
| 232 Node* input = NodeProperties::GetValueInput(node, 0); | 241 Node* input = SkipTypeGuards(NodeProperties::GetValueInput(node, 0)); |
| 233 if (escape_analysis()->IsVirtual(input)) { | 242 if (escape_analysis()->IsVirtual(input)) { |
| 234 ReplaceWithValue(node, jsgraph()->FalseConstant()); | 243 ReplaceWithValue(node, jsgraph()->FalseConstant()); |
| 235 TRACE("Replaced ObjectIsSmi #%d with false\n", node->id()); | 244 TRACE("Replaced ObjectIsSmi #%d with false\n", node->id()); |
| 236 return Replace(jsgraph()->FalseConstant()); | 245 return Replace(jsgraph()->FalseConstant()); |
| 237 } | 246 } |
| 238 return NoChange(); | 247 return NoChange(); |
| 239 } | 248 } |
| 240 | 249 |
| 241 | 250 |
| 242 Reduction EscapeAnalysisReducer::ReduceFrameStateUses(Node* node) { | 251 Reduction EscapeAnalysisReducer::ReduceFrameStateUses(Node* node) { |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 315 return clone; | 324 return clone; |
| 316 } | 325 } |
| 317 | 326 |
| 318 | 327 |
| 319 // Returns the clone if it duplicated the node, and null otherwise. | 328 // Returns the clone if it duplicated the node, and null otherwise. |
| 320 Node* EscapeAnalysisReducer::ReduceStateValueInput(Node* node, int node_index, | 329 Node* EscapeAnalysisReducer::ReduceStateValueInput(Node* node, int node_index, |
| 321 Node* effect, | 330 Node* effect, |
| 322 bool node_multiused, | 331 bool node_multiused, |
| 323 bool already_cloned, | 332 bool already_cloned, |
| 324 bool multiple_users) { | 333 bool multiple_users) { |
| 325 Node* input = NodeProperties::GetValueInput(node, node_index); | 334 Node* input = SkipTypeGuards(NodeProperties::GetValueInput(node, node_index)); |
| 326 if (node->id() < static_cast<NodeId>(fully_reduced_.length()) && | 335 if (node->id() < static_cast<NodeId>(fully_reduced_.length()) && |
| 327 fully_reduced_.Contains(node->id())) { | 336 fully_reduced_.Contains(node->id())) { |
| 328 return nullptr; | 337 return nullptr; |
| 329 } | 338 } |
| 330 TRACE("Reducing State Input #%d (%s)\n", input->id(), | 339 TRACE("Reducing State Input #%d (%s)\n", input->id(), |
| 331 input->op()->mnemonic()); | 340 input->op()->mnemonic()); |
| 332 Node* clone = nullptr; | 341 Node* clone = nullptr; |
| 333 if (input->opcode() == IrOpcode::kFinishRegion || | 342 if (input->opcode() == IrOpcode::kFinishRegion || |
| 334 input->opcode() == IrOpcode::kAllocate) { | 343 input->opcode() == IrOpcode::kAllocate) { |
| 335 if (escape_analysis()->IsVirtual(input)) { | 344 if (escape_analysis()->IsVirtual(input)) { |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 371 } | 380 } |
| 372 } | 381 } |
| 373 #endif // DEBUG | 382 #endif // DEBUG |
| 374 } | 383 } |
| 375 | 384 |
| 376 Isolate* EscapeAnalysisReducer::isolate() const { return jsgraph_->isolate(); } | 385 Isolate* EscapeAnalysisReducer::isolate() const { return jsgraph_->isolate(); } |
| 377 | 386 |
| 378 } // namespace compiler | 387 } // namespace compiler |
| 379 } // namespace internal | 388 } // namespace internal |
| 380 } // namespace v8 | 389 } // namespace v8 |
| OLD | NEW |