| 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/js-graph.h" | 7 #include "src/compiler/js-graph.h" |
| 8 #include "src/counters.h" | 8 #include "src/counters.h" |
| 9 | 9 |
| 10 namespace v8 { | 10 namespace v8 { |
| 11 namespace internal { | 11 namespace internal { |
| 12 namespace compiler { | 12 namespace compiler { |
| 13 | 13 |
| 14 #ifdef DEBUG | 14 #ifdef DEBUG |
| 15 #define TRACE(...) \ | 15 #define TRACE(...) \ |
| 16 do { \ | 16 do { \ |
| 17 if (FLAG_trace_turbo_escape) PrintF(__VA_ARGS__); \ | 17 if (FLAG_trace_turbo_escape) PrintF(__VA_ARGS__); \ |
| 18 } while (false) | 18 } while (false) |
| 19 #else | 19 #else |
| 20 #define TRACE(...) | 20 #define TRACE(...) |
| 21 #endif // DEBUG | 21 #endif // DEBUG |
| 22 | 22 |
| 23 EscapeAnalysisReducer::EscapeAnalysisReducer(Editor* editor, JSGraph* jsgraph, | 23 EscapeAnalysisReducer::EscapeAnalysisReducer(Editor* editor, JSGraph* jsgraph, |
| 24 EscapeAnalysis* escape_analysis, | 24 EscapeAnalysis* escape_analysis, |
| 25 Zone* zone) | 25 Zone* zone) |
| 26 : AdvancedReducer(editor), | 26 : AdvancedReducer(editor), |
| 27 jsgraph_(jsgraph), | 27 jsgraph_(jsgraph), |
| 28 escape_analysis_(escape_analysis), | 28 escape_analysis_(escape_analysis), |
| 29 zone_(zone), | 29 zone_(zone), |
| 30 visited_(static_cast<int>(jsgraph->graph()->NodeCount() * 2), zone), | 30 fully_reduced_(static_cast<int>(jsgraph->graph()->NodeCount() * 2), zone), |
| 31 exists_virtual_allocate_(true) {} | 31 exists_virtual_allocate_(true) {} |
| 32 | 32 |
| 33 | 33 |
| 34 Reduction EscapeAnalysisReducer::Reduce(Node* node) { | 34 Reduction EscapeAnalysisReducer::Reduce(Node* node) { |
| 35 if (node->id() < static_cast<NodeId>(fully_reduced_.length()) && |
| 36 fully_reduced_.Contains(node->id())) { |
| 37 return NoChange(); |
| 38 } |
| 39 |
| 35 switch (node->opcode()) { | 40 switch (node->opcode()) { |
| 36 case IrOpcode::kLoadField: | 41 case IrOpcode::kLoadField: |
| 37 case IrOpcode::kLoadElement: | 42 case IrOpcode::kLoadElement: |
| 38 return ReduceLoad(node); | 43 return ReduceLoad(node); |
| 39 case IrOpcode::kStoreField: | 44 case IrOpcode::kStoreField: |
| 40 case IrOpcode::kStoreElement: | 45 case IrOpcode::kStoreElement: |
| 41 return ReduceStore(node); | 46 return ReduceStore(node); |
| 42 case IrOpcode::kAllocate: | 47 case IrOpcode::kAllocate: |
| 43 return ReduceAllocate(node); | 48 return ReduceAllocate(node); |
| 44 case IrOpcode::kFinishRegion: | 49 case IrOpcode::kFinishRegion: |
| 45 return ReduceFinishRegion(node); | 50 return ReduceFinishRegion(node); |
| 46 case IrOpcode::kReferenceEqual: | 51 case IrOpcode::kReferenceEqual: |
| 47 return ReduceReferenceEqual(node); | 52 return ReduceReferenceEqual(node); |
| 48 case IrOpcode::kObjectIsSmi: | 53 case IrOpcode::kObjectIsSmi: |
| 49 return ReduceObjectIsSmi(node); | 54 return ReduceObjectIsSmi(node); |
| 55 // FrameStates and Value nodes are preprocessed here, |
| 56 // and visited via ReduceFrameStateUses from their user nodes. |
| 50 case IrOpcode::kFrameState: | 57 case IrOpcode::kFrameState: |
| 51 case IrOpcode::kStateValues: { | 58 case IrOpcode::kStateValues: { |
| 52 if (node->id() >= static_cast<NodeId>(visited_.length()) || | 59 if (node->id() >= static_cast<NodeId>(fully_reduced_.length()) || |
| 53 visited_.Contains(node->id())) { | 60 fully_reduced_.Contains(node->id())) { |
| 54 break; | 61 break; |
| 55 } | 62 } |
| 56 bool needs_visit = false; | 63 bool depends_on_object_state = false; |
| 57 for (int i = 0; i < node->InputCount(); i++) { | 64 for (int i = 0; i < node->InputCount(); i++) { |
| 58 Node* input = node->InputAt(i); | 65 Node* input = node->InputAt(i); |
| 59 switch (input->opcode()) { | 66 switch (input->opcode()) { |
| 60 case IrOpcode::kAllocate: | 67 case IrOpcode::kAllocate: |
| 61 case IrOpcode::kFinishRegion: | 68 case IrOpcode::kFinishRegion: |
| 62 needs_visit = needs_visit || escape_analysis()->IsVirtual(input); | 69 depends_on_object_state = |
| 70 depends_on_object_state || escape_analysis()->IsVirtual(input); |
| 63 break; | 71 break; |
| 64 case IrOpcode::kFrameState: | 72 case IrOpcode::kFrameState: |
| 65 case IrOpcode::kStateValues: | 73 case IrOpcode::kStateValues: |
| 66 needs_visit = | 74 depends_on_object_state = |
| 67 needs_visit || | 75 depends_on_object_state || |
| 68 input->id() >= static_cast<NodeId>(visited_.length()) || | 76 input->id() >= static_cast<NodeId>(fully_reduced_.length()) || |
| 69 !visited_.Contains(input->id()); | 77 !fully_reduced_.Contains(input->id()); |
| 70 break; | 78 break; |
| 71 default: | 79 default: |
| 72 break; | 80 break; |
| 73 } | 81 } |
| 74 } | 82 } |
| 75 if (!needs_visit) { | 83 if (!depends_on_object_state) { |
| 76 visited_.Add(node->id()); | 84 fully_reduced_.Add(node->id()); |
| 77 } | 85 } |
| 78 break; | 86 return NoChange(); |
| 79 } | 87 } |
| 80 default: | 88 default: |
| 81 // TODO(sigurds): Change this to GetFrameStateInputCount once | 89 // TODO(sigurds): Change this to GetFrameStateInputCount once |
| 82 // it is working. For now we use EffectInputCount > 0 to determine | 90 // it is working. For now we use EffectInputCount > 0 to determine |
| 83 // whether a node might have a frame state input. | 91 // whether a node might have a frame state input. |
| 84 if (exists_virtual_allocate_ && node->op()->EffectInputCount() > 0) { | 92 if (exists_virtual_allocate_ && node->op()->EffectInputCount() > 0) { |
| 85 return ReduceFrameStateUses(node); | 93 return ReduceFrameStateUses(node); |
| 86 } | 94 } |
| 87 break; | 95 break; |
| 88 } | 96 } |
| 89 return NoChange(); | 97 return NoChange(); |
| 90 } | 98 } |
| 91 | 99 |
| 92 | 100 |
| 93 Reduction EscapeAnalysisReducer::ReduceLoad(Node* node) { | 101 Reduction EscapeAnalysisReducer::ReduceLoad(Node* node) { |
| 94 DCHECK(node->opcode() == IrOpcode::kLoadField || | 102 DCHECK(node->opcode() == IrOpcode::kLoadField || |
| 95 node->opcode() == IrOpcode::kLoadElement); | 103 node->opcode() == IrOpcode::kLoadElement); |
| 96 if (visited_.Contains(node->id())) return NoChange(); | 104 if (node->id() < static_cast<NodeId>(fully_reduced_.length())) { |
| 97 visited_.Add(node->id()); | 105 fully_reduced_.Add(node->id()); |
| 106 } |
| 98 if (Node* rep = escape_analysis()->GetReplacement(node)) { | 107 if (Node* rep = escape_analysis()->GetReplacement(node)) { |
| 99 visited_.Add(node->id()); | |
| 100 counters()->turbo_escape_loads_replaced()->Increment(); | 108 counters()->turbo_escape_loads_replaced()->Increment(); |
| 101 TRACE("Replaced #%d (%s) with #%d (%s)\n", node->id(), | 109 TRACE("Replaced #%d (%s) with #%d (%s)\n", node->id(), |
| 102 node->op()->mnemonic(), rep->id(), rep->op()->mnemonic()); | 110 node->op()->mnemonic(), rep->id(), rep->op()->mnemonic()); |
| 103 ReplaceWithValue(node, rep); | 111 ReplaceWithValue(node, rep); |
| 104 return Changed(rep); | 112 return Changed(rep); |
| 105 } | 113 } |
| 106 return NoChange(); | 114 return NoChange(); |
| 107 } | 115 } |
| 108 | 116 |
| 109 | 117 |
| 110 Reduction EscapeAnalysisReducer::ReduceStore(Node* node) { | 118 Reduction EscapeAnalysisReducer::ReduceStore(Node* node) { |
| 111 DCHECK(node->opcode() == IrOpcode::kStoreField || | 119 DCHECK(node->opcode() == IrOpcode::kStoreField || |
| 112 node->opcode() == IrOpcode::kStoreElement); | 120 node->opcode() == IrOpcode::kStoreElement); |
| 113 if (visited_.Contains(node->id())) return NoChange(); | 121 if (node->id() < static_cast<NodeId>(fully_reduced_.length())) { |
| 114 visited_.Add(node->id()); | 122 fully_reduced_.Add(node->id()); |
| 123 } |
| 115 if (escape_analysis()->IsVirtual(NodeProperties::GetValueInput(node, 0))) { | 124 if (escape_analysis()->IsVirtual(NodeProperties::GetValueInput(node, 0))) { |
| 116 TRACE("Removed #%d (%s) from effect chain\n", node->id(), | 125 TRACE("Removed #%d (%s) from effect chain\n", node->id(), |
| 117 node->op()->mnemonic()); | 126 node->op()->mnemonic()); |
| 118 RelaxEffectsAndControls(node); | 127 RelaxEffectsAndControls(node); |
| 119 return Changed(node); | 128 return Changed(node); |
| 120 } | 129 } |
| 121 return NoChange(); | 130 return NoChange(); |
| 122 } | 131 } |
| 123 | 132 |
| 124 | 133 |
| 125 Reduction EscapeAnalysisReducer::ReduceAllocate(Node* node) { | 134 Reduction EscapeAnalysisReducer::ReduceAllocate(Node* node) { |
| 126 DCHECK_EQ(node->opcode(), IrOpcode::kAllocate); | 135 DCHECK_EQ(node->opcode(), IrOpcode::kAllocate); |
| 127 if (visited_.Contains(node->id())) return NoChange(); | |
| 128 visited_.Add(node->id()); | |
| 129 if (escape_analysis()->IsVirtual(node)) { | 136 if (escape_analysis()->IsVirtual(node)) { |
| 130 RelaxEffectsAndControls(node); | 137 RelaxEffectsAndControls(node); |
| 131 counters()->turbo_escape_allocs_replaced()->Increment(); | 138 counters()->turbo_escape_allocs_replaced()->Increment(); |
| 132 TRACE("Removed allocate #%d from effect chain\n", node->id()); | 139 TRACE("Removed allocate #%d from effect chain\n", node->id()); |
| 133 return Changed(node); | 140 return Changed(node); |
| 134 } | 141 } |
| 135 return NoChange(); | 142 return NoChange(); |
| 136 } | 143 } |
| 137 | 144 |
| 138 | 145 |
| 139 Reduction EscapeAnalysisReducer::ReduceFinishRegion(Node* node) { | 146 Reduction EscapeAnalysisReducer::ReduceFinishRegion(Node* node) { |
| 140 DCHECK_EQ(node->opcode(), IrOpcode::kFinishRegion); | 147 DCHECK_EQ(node->opcode(), IrOpcode::kFinishRegion); |
| 141 Node* effect = NodeProperties::GetEffectInput(node, 0); | 148 Node* effect = NodeProperties::GetEffectInput(node, 0); |
| 142 if (effect->opcode() == IrOpcode::kBeginRegion) { | 149 if (effect->opcode() == IrOpcode::kBeginRegion) { |
| 150 if (node->id() < static_cast<NodeId>(fully_reduced_.length())) { |
| 151 fully_reduced_.Add(node->id()); |
| 152 } |
| 143 RelaxEffectsAndControls(effect); | 153 RelaxEffectsAndControls(effect); |
| 144 RelaxEffectsAndControls(node); | 154 RelaxEffectsAndControls(node); |
| 145 #ifdef DEBUG | 155 #ifdef DEBUG |
| 146 if (FLAG_trace_turbo_escape) { | 156 if (FLAG_trace_turbo_escape) { |
| 147 PrintF("Removed region #%d / #%d from effect chain,", effect->id(), | 157 PrintF("Removed region #%d / #%d from effect chain,", effect->id(), |
| 148 node->id()); | 158 node->id()); |
| 149 PrintF(" %d user(s) of #%d remain(s):", node->UseCount(), node->id()); | 159 PrintF(" %d user(s) of #%d remain(s):", node->UseCount(), node->id()); |
| 150 for (Edge edge : node->use_edges()) { | 160 for (Edge edge : node->use_edges()) { |
| 151 PrintF(" #%d", edge.from()->id()); | 161 PrintF(" #%d", edge.from()->id()); |
| 152 } | 162 } |
| (...skipping 17 matching lines...) Expand all Loading... |
| 170 TRACE("Replaced ref eq #%d with true\n", node->id()); | 180 TRACE("Replaced ref eq #%d with true\n", node->id()); |
| 171 } | 181 } |
| 172 // Right-hand side is not a virtual object, or a different one. | 182 // Right-hand side is not a virtual object, or a different one. |
| 173 ReplaceWithValue(node, jsgraph()->FalseConstant()); | 183 ReplaceWithValue(node, jsgraph()->FalseConstant()); |
| 174 TRACE("Replaced ref eq #%d with false\n", node->id()); | 184 TRACE("Replaced ref eq #%d with false\n", node->id()); |
| 175 return Replace(node); | 185 return Replace(node); |
| 176 } else if (escape_analysis()->IsVirtual(right)) { | 186 } else if (escape_analysis()->IsVirtual(right)) { |
| 177 // Left-hand side is not a virtual object. | 187 // Left-hand side is not a virtual object. |
| 178 ReplaceWithValue(node, jsgraph()->FalseConstant()); | 188 ReplaceWithValue(node, jsgraph()->FalseConstant()); |
| 179 TRACE("Replaced ref eq #%d with false\n", node->id()); | 189 TRACE("Replaced ref eq #%d with false\n", node->id()); |
| 190 return Replace(node); |
| 180 } | 191 } |
| 181 return NoChange(); | 192 return NoChange(); |
| 182 } | 193 } |
| 183 | 194 |
| 184 | 195 |
| 185 Reduction EscapeAnalysisReducer::ReduceObjectIsSmi(Node* node) { | 196 Reduction EscapeAnalysisReducer::ReduceObjectIsSmi(Node* node) { |
| 186 DCHECK_EQ(node->opcode(), IrOpcode::kObjectIsSmi); | 197 DCHECK_EQ(node->opcode(), IrOpcode::kObjectIsSmi); |
| 187 Node* input = NodeProperties::GetValueInput(node, 0); | 198 Node* input = NodeProperties::GetValueInput(node, 0); |
| 188 if (escape_analysis()->IsVirtual(input)) { | 199 if (escape_analysis()->IsVirtual(input)) { |
| 189 ReplaceWithValue(node, jsgraph()->FalseConstant()); | 200 ReplaceWithValue(node, jsgraph()->FalseConstant()); |
| 190 TRACE("Replaced ObjectIsSmi #%d with false\n", node->id()); | 201 TRACE("Replaced ObjectIsSmi #%d with false\n", node->id()); |
| 191 return Replace(node); | 202 return Replace(node); |
| 192 } | 203 } |
| 193 return NoChange(); | 204 return NoChange(); |
| 194 } | 205 } |
| 195 | 206 |
| 196 | 207 |
| 197 Reduction EscapeAnalysisReducer::ReduceFrameStateUses(Node* node) { | 208 Reduction EscapeAnalysisReducer::ReduceFrameStateUses(Node* node) { |
| 198 if (visited_.Contains(node->id())) return NoChange(); | |
| 199 visited_.Add(node->id()); | |
| 200 DCHECK_GE(node->op()->EffectInputCount(), 1); | 209 DCHECK_GE(node->op()->EffectInputCount(), 1); |
| 201 bool changed = false; | 210 bool changed = false; |
| 202 for (int i = 0; i < node->InputCount(); ++i) { | 211 for (int i = 0; i < node->InputCount(); ++i) { |
| 203 Node* input = node->InputAt(i); | 212 Node* input = node->InputAt(i); |
| 204 if (input->opcode() == IrOpcode::kFrameState) { | 213 if (input->opcode() == IrOpcode::kFrameState) { |
| 205 if (Node* ret = ReduceDeoptState(input, node, false)) { | 214 if (Node* ret = ReduceDeoptState(input, node, false)) { |
| 206 node->ReplaceInput(i, ret); | 215 node->ReplaceInput(i, ret); |
| 207 changed = true; | 216 changed = true; |
| 208 } | 217 } |
| 209 } | 218 } |
| 210 } | 219 } |
| 211 if (changed) { | 220 if (changed) { |
| 212 return Changed(node); | 221 return Changed(node); |
| 213 } | 222 } |
| 214 return NoChange(); | 223 return NoChange(); |
| 215 } | 224 } |
| 216 | 225 |
| 217 | 226 |
| 218 // Returns the clone if it duplicated the node, and null otherwise. | 227 // Returns the clone if it duplicated the node, and null otherwise. |
| 219 Node* EscapeAnalysisReducer::ReduceDeoptState(Node* node, Node* effect, | 228 Node* EscapeAnalysisReducer::ReduceDeoptState(Node* node, Node* effect, |
| 220 bool multiple_users) { | 229 bool multiple_users) { |
| 221 DCHECK(node->opcode() == IrOpcode::kFrameState || | 230 DCHECK(node->opcode() == IrOpcode::kFrameState || |
| 222 node->opcode() == IrOpcode::kStateValues); | 231 node->opcode() == IrOpcode::kStateValues); |
| 223 if (node->id() < static_cast<NodeId>(visited_.length()) && | 232 if (node->id() < static_cast<NodeId>(fully_reduced_.length()) && |
| 224 visited_.Contains(node->id())) { | 233 fully_reduced_.Contains(node->id())) { |
| 225 return nullptr; | 234 return nullptr; |
| 226 } | 235 } |
| 227 TRACE("Reducing %s %d\n", node->op()->mnemonic(), node->id()); | 236 TRACE("Reducing %s %d\n", node->op()->mnemonic(), node->id()); |
| 228 Node* clone = nullptr; | 237 Node* clone = nullptr; |
| 229 bool node_multiused = node->UseCount() > 1; | 238 bool node_multiused = node->UseCount() > 1; |
| 230 bool multiple_users_rec = multiple_users || node_multiused; | 239 bool multiple_users_rec = multiple_users || node_multiused; |
| 231 for (int i = 0; i < node->op()->ValueInputCount(); ++i) { | 240 for (int i = 0; i < node->op()->ValueInputCount(); ++i) { |
| 232 Node* input = NodeProperties::GetValueInput(node, i); | 241 Node* input = NodeProperties::GetValueInput(node, i); |
| 233 if (input->opcode() == IrOpcode::kStateValues) { | 242 if (input->opcode() == IrOpcode::kStateValues) { |
| 234 if (Node* ret = ReduceDeoptState(input, effect, multiple_users_rec)) { | 243 if (Node* ret = ReduceDeoptState(input, effect, multiple_users_rec)) { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 256 ReduceDeoptState(outer_frame_state, effect, multiple_users_rec)) { | 265 ReduceDeoptState(outer_frame_state, effect, multiple_users_rec)) { |
| 257 if (node_multiused || (multiple_users && !clone)) { | 266 if (node_multiused || (multiple_users && !clone)) { |
| 258 TRACE(" Cloning #%d", node->id()); | 267 TRACE(" Cloning #%d", node->id()); |
| 259 node = clone = jsgraph()->graph()->CloneNode(node); | 268 node = clone = jsgraph()->graph()->CloneNode(node); |
| 260 TRACE(" to #%d\n", node->id()); | 269 TRACE(" to #%d\n", node->id()); |
| 261 } | 270 } |
| 262 NodeProperties::ReplaceFrameStateInput(node, 0, ret); | 271 NodeProperties::ReplaceFrameStateInput(node, 0, ret); |
| 263 } | 272 } |
| 264 } | 273 } |
| 265 } | 274 } |
| 275 if (node->id() < static_cast<NodeId>(fully_reduced_.length())) { |
| 276 fully_reduced_.Add(node->id()); |
| 277 } |
| 266 return clone; | 278 return clone; |
| 267 } | 279 } |
| 268 | 280 |
| 269 | 281 |
| 270 // Returns the clone if it duplicated the node, and null otherwise. | 282 // Returns the clone if it duplicated the node, and null otherwise. |
| 271 Node* EscapeAnalysisReducer::ReduceStateValueInput(Node* node, int node_index, | 283 Node* EscapeAnalysisReducer::ReduceStateValueInput(Node* node, int node_index, |
| 272 Node* effect, | 284 Node* effect, |
| 273 bool node_multiused, | 285 bool node_multiused, |
| 274 bool already_cloned, | 286 bool already_cloned, |
| 275 bool multiple_users) { | 287 bool multiple_users) { |
| 276 Node* input = NodeProperties::GetValueInput(node, node_index); | 288 Node* input = NodeProperties::GetValueInput(node, node_index); |
| 289 if (node->id() < static_cast<NodeId>(fully_reduced_.length()) && |
| 290 fully_reduced_.Contains(node->id())) { |
| 291 return nullptr; |
| 292 } |
| 277 TRACE("Reducing State Input #%d (%s)\n", input->id(), | 293 TRACE("Reducing State Input #%d (%s)\n", input->id(), |
| 278 input->op()->mnemonic()); | 294 input->op()->mnemonic()); |
| 279 Node* clone = nullptr; | 295 Node* clone = nullptr; |
| 280 if (input->opcode() == IrOpcode::kFinishRegion || | 296 if (input->opcode() == IrOpcode::kFinishRegion || |
| 281 input->opcode() == IrOpcode::kAllocate) { | 297 input->opcode() == IrOpcode::kAllocate) { |
| 282 if (escape_analysis()->IsVirtual(input)) { | 298 if (escape_analysis()->IsVirtual(input)) { |
| 283 if (Node* object_state = | 299 if (Node* object_state = |
| 284 escape_analysis()->GetOrCreateObjectState(effect, input)) { | 300 escape_analysis()->GetOrCreateObjectState(effect, input)) { |
| 285 if (node_multiused || (multiple_users && !already_cloned)) { | 301 if (node_multiused || (multiple_users && !already_cloned)) { |
| 286 TRACE("Cloning #%d", node->id()); | 302 TRACE("Cloning #%d", node->id()); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 300 } | 316 } |
| 301 } | 317 } |
| 302 return clone; | 318 return clone; |
| 303 } | 319 } |
| 304 | 320 |
| 305 | 321 |
| 306 Counters* EscapeAnalysisReducer::counters() const { | 322 Counters* EscapeAnalysisReducer::counters() const { |
| 307 return jsgraph_->isolate()->counters(); | 323 return jsgraph_->isolate()->counters(); |
| 308 } | 324 } |
| 309 | 325 |
| 326 |
| 327 class EscapeAnalysisVerifier final : public AdvancedReducer { |
| 328 public: |
| 329 EscapeAnalysisVerifier(Editor* editor, EscapeAnalysis* escape_analysis) |
| 330 : AdvancedReducer(editor), escape_analysis_(escape_analysis) {} |
| 331 |
| 332 Reduction Reduce(Node* node) final { |
| 333 switch (node->opcode()) { |
| 334 case IrOpcode::kAllocate: |
| 335 CHECK(!escape_analysis_->IsVirtual(node)); |
| 336 break; |
| 337 default: |
| 338 break; |
| 339 } |
| 340 return NoChange(); |
| 341 } |
| 342 |
| 343 private: |
| 344 EscapeAnalysis* escape_analysis_; |
| 345 }; |
| 346 |
| 347 void EscapeAnalysisReducer::VerifyReplacement() const { |
| 348 #ifdef DEBUG |
| 349 GraphReducer graph_reducer(zone(), jsgraph()->graph()); |
| 350 EscapeAnalysisVerifier verifier(&graph_reducer, escape_analysis()); |
| 351 graph_reducer.AddReducer(&verifier); |
| 352 graph_reducer.ReduceGraph(); |
| 353 #endif // DEBUG |
| 354 } |
| 355 |
| 310 } // namespace compiler | 356 } // namespace compiler |
| 311 } // namespace internal | 357 } // namespace internal |
| 312 } // namespace v8 | 358 } // namespace v8 |
| OLD | NEW |