| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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/pipeline.h" | 5 #include "src/compiler/pipeline.h" |
| 6 #include "src/compiler/scheduler.h" | 6 #include "src/compiler/scheduler.h" |
| 7 #include "src/compiler/structured-machine-assembler.h" | 7 #include "src/compiler/structured-machine-assembler.h" |
| 8 | 8 |
| 9 namespace v8 { | 9 namespace v8 { |
| 10 namespace internal { | 10 namespace internal { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 31 if (parameter_count() == 0) return; | 31 if (parameter_count() == 0) return; |
| 32 parameters_ = zone()->NewArray<Node*>(parameter_count()); | 32 parameters_ = zone()->NewArray<Node*>(parameter_count()); |
| 33 for (int i = 0; i < parameter_count(); ++i) { | 33 for (int i = 0; i < parameter_count(); ++i) { |
| 34 parameters_[i] = NewNode(common()->Parameter(i)); | 34 parameters_[i] = NewNode(common()->Parameter(i)); |
| 35 } | 35 } |
| 36 } | 36 } |
| 37 | 37 |
| 38 | 38 |
| 39 Schedule* StructuredMachineAssembler::Export() { | 39 Schedule* StructuredMachineAssembler::Export() { |
| 40 // Compute the correct codegen order. | 40 // Compute the correct codegen order. |
| 41 ASSERT(schedule_->rpo_order()->empty()); | 41 DCHECK(schedule_->rpo_order()->empty()); |
| 42 Scheduler scheduler(zone(), graph(), schedule_); | 42 Scheduler scheduler(zone(), graph(), schedule_); |
| 43 scheduler.ComputeSpecialRPO(); | 43 scheduler.ComputeSpecialRPO(); |
| 44 // Invalidate MachineAssembler. | 44 // Invalidate MachineAssembler. |
| 45 Schedule* schedule = schedule_; | 45 Schedule* schedule = schedule_; |
| 46 schedule_ = NULL; | 46 schedule_ = NULL; |
| 47 return schedule; | 47 return schedule; |
| 48 } | 48 } |
| 49 | 49 |
| 50 | 50 |
| 51 Node* StructuredMachineAssembler::Parameter(int index) { | 51 Node* StructuredMachineAssembler::Parameter(int index) { |
| 52 ASSERT(0 <= index && index < parameter_count()); | 52 DCHECK(0 <= index && index < parameter_count()); |
| 53 return parameters_[index]; | 53 return parameters_[index]; |
| 54 } | 54 } |
| 55 | 55 |
| 56 | 56 |
| 57 Node* StructuredMachineAssembler::MakeNode(Operator* op, int input_count, | 57 Node* StructuredMachineAssembler::MakeNode(Operator* op, int input_count, |
| 58 Node** inputs) { | 58 Node** inputs) { |
| 59 ASSERT(ScheduleValid()); | 59 DCHECK(ScheduleValid()); |
| 60 ASSERT(current_environment_ != NULL); | 60 DCHECK(current_environment_ != NULL); |
| 61 Node* node = graph()->NewNode(op, input_count, inputs); | 61 Node* node = graph()->NewNode(op, input_count, inputs); |
| 62 BasicBlock* block = NULL; | 62 BasicBlock* block = NULL; |
| 63 switch (op->opcode()) { | 63 switch (op->opcode()) { |
| 64 case IrOpcode::kParameter: | 64 case IrOpcode::kParameter: |
| 65 case IrOpcode::kInt32Constant: | 65 case IrOpcode::kInt32Constant: |
| 66 case IrOpcode::kInt64Constant: | 66 case IrOpcode::kInt64Constant: |
| 67 case IrOpcode::kFloat64Constant: | 67 case IrOpcode::kFloat64Constant: |
| 68 case IrOpcode::kExternalConstant: | 68 case IrOpcode::kExternalConstant: |
| 69 case IrOpcode::kNumberConstant: | 69 case IrOpcode::kNumberConstant: |
| 70 case IrOpcode::kHeapConstant: | 70 case IrOpcode::kHeapConstant: |
| 71 // Parameters and constants must be in start. | 71 // Parameters and constants must be in start. |
| 72 block = schedule()->start(); | 72 block = schedule()->start(); |
| 73 break; | 73 break; |
| 74 default: | 74 default: |
| 75 // Verify all leaf nodes handled above. | 75 // Verify all leaf nodes handled above. |
| 76 ASSERT((op->OutputCount() == 0) == (op->opcode() == IrOpcode::kStore)); | 76 DCHECK((op->OutputCount() == 0) == (op->opcode() == IrOpcode::kStore)); |
| 77 block = current_environment_->block_; | 77 block = current_environment_->block_; |
| 78 break; | 78 break; |
| 79 } | 79 } |
| 80 if (block != NULL) { | 80 if (block != NULL) { |
| 81 schedule()->AddNode(block, node); | 81 schedule()->AddNode(block, node); |
| 82 } | 82 } |
| 83 return node; | 83 return node; |
| 84 } | 84 } |
| 85 | 85 |
| 86 | 86 |
| 87 Variable StructuredMachineAssembler::NewVariable(Node* initial_value) { | 87 Variable StructuredMachineAssembler::NewVariable(Node* initial_value) { |
| 88 CHECK(initial_value != NULL); | 88 CHECK(initial_value != NULL); |
| 89 int offset = number_of_variables_++; | 89 int offset = number_of_variables_++; |
| 90 // Extend current environment to correct number of values. | 90 // Extend current environment to correct number of values. |
| 91 NodeVector* variables = CurrentVars(); | 91 NodeVector* variables = CurrentVars(); |
| 92 size_t to_add = number_of_variables_ - variables->size(); | 92 size_t to_add = number_of_variables_ - variables->size(); |
| 93 if (to_add != 0) { | 93 if (to_add != 0) { |
| 94 variables->reserve(number_of_variables_); | 94 variables->reserve(number_of_variables_); |
| 95 variables->insert(variables->end(), to_add, NULL); | 95 variables->insert(variables->end(), to_add, NULL); |
| 96 } | 96 } |
| 97 variables->at(offset) = initial_value; | 97 variables->at(offset) = initial_value; |
| 98 return Variable(this, offset); | 98 return Variable(this, offset); |
| 99 } | 99 } |
| 100 | 100 |
| 101 | 101 |
| 102 Node* StructuredMachineAssembler::GetVariable(int offset) { | 102 Node* StructuredMachineAssembler::GetVariable(int offset) { |
| 103 ASSERT(ScheduleValid()); | 103 DCHECK(ScheduleValid()); |
| 104 return VariableAt(current_environment_, offset); | 104 return VariableAt(current_environment_, offset); |
| 105 } | 105 } |
| 106 | 106 |
| 107 | 107 |
| 108 void StructuredMachineAssembler::SetVariable(int offset, Node* value) { | 108 void StructuredMachineAssembler::SetVariable(int offset, Node* value) { |
| 109 ASSERT(ScheduleValid()); | 109 DCHECK(ScheduleValid()); |
| 110 Node*& ref = VariableAt(current_environment_, offset); | 110 Node*& ref = VariableAt(current_environment_, offset); |
| 111 ref = value; | 111 ref = value; |
| 112 } | 112 } |
| 113 | 113 |
| 114 | 114 |
| 115 Node*& StructuredMachineAssembler::VariableAt(Environment* environment, | 115 Node*& StructuredMachineAssembler::VariableAt(Environment* environment, |
| 116 int32_t offset) { | 116 int32_t offset) { |
| 117 // Variable used out of scope. | 117 // Variable used out of scope. |
| 118 CHECK(static_cast<size_t>(offset) < environment->variables_.size()); | 118 CHECK(static_cast<size_t>(offset) < environment->variables_.size()); |
| 119 Node*& value = environment->variables_.at(offset); | 119 Node*& value = environment->variables_.at(offset); |
| 120 CHECK(value != NULL); // Variable used out of scope. | 120 CHECK(value != NULL); // Variable used out of scope. |
| 121 return value; | 121 return value; |
| 122 } | 122 } |
| 123 | 123 |
| 124 | 124 |
| 125 void StructuredMachineAssembler::Return(Node* value) { | 125 void StructuredMachineAssembler::Return(Node* value) { |
| 126 BasicBlock* block = current_environment_->block_; | 126 BasicBlock* block = current_environment_->block_; |
| 127 if (block != NULL) { | 127 if (block != NULL) { |
| 128 schedule()->AddReturn(block, value); | 128 schedule()->AddReturn(block, value); |
| 129 } | 129 } |
| 130 CopyCurrentAsDead(); | 130 CopyCurrentAsDead(); |
| 131 } | 131 } |
| 132 | 132 |
| 133 | 133 |
| 134 void StructuredMachineAssembler::CopyCurrentAsDead() { | 134 void StructuredMachineAssembler::CopyCurrentAsDead() { |
| 135 ASSERT(current_environment_ != NULL); | 135 DCHECK(current_environment_ != NULL); |
| 136 bool is_dead = current_environment_->is_dead_; | 136 bool is_dead = current_environment_->is_dead_; |
| 137 current_environment_->is_dead_ = true; | 137 current_environment_->is_dead_ = true; |
| 138 Environment* next = Copy(current_environment_); | 138 Environment* next = Copy(current_environment_); |
| 139 current_environment_->is_dead_ = is_dead; | 139 current_environment_->is_dead_ = is_dead; |
| 140 current_environment_ = next; | 140 current_environment_ = next; |
| 141 } | 141 } |
| 142 | 142 |
| 143 | 143 |
| 144 StructuredMachineAssembler::Environment* StructuredMachineAssembler::Copy( | 144 StructuredMachineAssembler::Environment* StructuredMachineAssembler::Copy( |
| 145 Environment* env, int truncate_at) { | 145 Environment* env, int truncate_at) { |
| 146 Environment* new_env = new (zone()) Environment(zone(), NULL, env->is_dead_); | 146 Environment* new_env = new (zone()) Environment(zone(), NULL, env->is_dead_); |
| 147 if (!new_env->is_dead_) { | 147 if (!new_env->is_dead_) { |
| 148 new_env->block_ = schedule()->NewBasicBlock(); | 148 new_env->block_ = schedule()->NewBasicBlock(); |
| 149 } | 149 } |
| 150 new_env->variables_.reserve(truncate_at); | 150 new_env->variables_.reserve(truncate_at); |
| 151 NodeVectorIter end = env->variables_.end(); | 151 NodeVectorIter end = env->variables_.end(); |
| 152 ASSERT(truncate_at <= static_cast<int>(env->variables_.size())); | 152 DCHECK(truncate_at <= static_cast<int>(env->variables_.size())); |
| 153 end -= static_cast<int>(env->variables_.size()) - truncate_at; | 153 end -= static_cast<int>(env->variables_.size()) - truncate_at; |
| 154 new_env->variables_.insert(new_env->variables_.begin(), | 154 new_env->variables_.insert(new_env->variables_.begin(), |
| 155 env->variables_.begin(), end); | 155 env->variables_.begin(), end); |
| 156 return new_env; | 156 return new_env; |
| 157 } | 157 } |
| 158 | 158 |
| 159 | 159 |
| 160 StructuredMachineAssembler::Environment* | 160 StructuredMachineAssembler::Environment* |
| 161 StructuredMachineAssembler::CopyForLoopHeader(Environment* env) { | 161 StructuredMachineAssembler::CopyForLoopHeader(Environment* env) { |
| 162 Environment* new_env = new (zone()) Environment(zone(), NULL, env->is_dead_); | 162 Environment* new_env = new (zone()) Environment(zone(), NULL, env->is_dead_); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 194 if (phi == NULL) continue; | 194 if (phi == NULL) continue; |
| 195 phi->set_op(common()->Phi(phi->InputCount() + 1)); | 195 phi->set_op(common()->Phi(phi->InputCount() + 1)); |
| 196 phi->AppendInput(zone(), VariableAt(from, i)); | 196 phi->AppendInput(zone(), VariableAt(from, i)); |
| 197 } | 197 } |
| 198 } | 198 } |
| 199 } | 199 } |
| 200 | 200 |
| 201 | 201 |
| 202 void StructuredMachineAssembler::Merge(EnvironmentVector* environments, | 202 void StructuredMachineAssembler::Merge(EnvironmentVector* environments, |
| 203 int truncate_at) { | 203 int truncate_at) { |
| 204 ASSERT(current_environment_ == NULL || current_environment_->is_dead_); | 204 DCHECK(current_environment_ == NULL || current_environment_->is_dead_); |
| 205 Environment* next = new (zone()) Environment(zone(), NULL, false); | 205 Environment* next = new (zone()) Environment(zone(), NULL, false); |
| 206 current_environment_ = next; | 206 current_environment_ = next; |
| 207 size_t n_vars = number_of_variables_; | 207 size_t n_vars = number_of_variables_; |
| 208 NodeVector& vars = next->variables_; | 208 NodeVector& vars = next->variables_; |
| 209 vars.reserve(n_vars); | 209 vars.reserve(n_vars); |
| 210 Node** scratch = NULL; | 210 Node** scratch = NULL; |
| 211 size_t n_envs = environments->size(); | 211 size_t n_envs = environments->size(); |
| 212 Environment** live_environments = reinterpret_cast<Environment**>( | 212 Environment** live_environments = reinterpret_cast<Environment**>( |
| 213 alloca(sizeof(environments->at(0)) * n_envs)); | 213 alloca(sizeof(environments->at(0)) * n_envs)); |
| 214 size_t n_live = 0; | 214 size_t n_live = 0; |
| 215 for (size_t i = 0; i < n_envs; i++) { | 215 for (size_t i = 0; i < n_envs; i++) { |
| 216 if (environments->at(i)->is_dead_) continue; | 216 if (environments->at(i)->is_dead_) continue; |
| 217 live_environments[n_live++] = environments->at(i); | 217 live_environments[n_live++] = environments->at(i); |
| 218 } | 218 } |
| 219 n_envs = n_live; | 219 n_envs = n_live; |
| 220 if (n_live == 0) next->is_dead_ = true; | 220 if (n_live == 0) next->is_dead_ = true; |
| 221 if (!next->is_dead_) { | 221 if (!next->is_dead_) { |
| 222 next->block_ = schedule()->NewBasicBlock(); | 222 next->block_ = schedule()->NewBasicBlock(); |
| 223 } | 223 } |
| 224 for (size_t j = 0; j < n_vars; ++j) { | 224 for (size_t j = 0; j < n_vars; ++j) { |
| 225 Node* resolved = NULL; | 225 Node* resolved = NULL; |
| 226 // Find first non equal variable. | 226 // Find first non equal variable. |
| 227 size_t i = 0; | 227 size_t i = 0; |
| 228 for (; i < n_envs; i++) { | 228 for (; i < n_envs; i++) { |
| 229 ASSERT(live_environments[i]->variables_.size() <= n_vars); | 229 DCHECK(live_environments[i]->variables_.size() <= n_vars); |
| 230 Node* val = NULL; | 230 Node* val = NULL; |
| 231 if (j < static_cast<size_t>(truncate_at)) { | 231 if (j < static_cast<size_t>(truncate_at)) { |
| 232 val = live_environments[i]->variables_.at(j); | 232 val = live_environments[i]->variables_.at(j); |
| 233 // TODO(dcarney): record start position at time of split. | 233 // TODO(dcarney): record start position at time of split. |
| 234 // all variables after this should not be NULL. | 234 // all variables after this should not be NULL. |
| 235 if (val != NULL) { | 235 if (val != NULL) { |
| 236 val = VariableAt(live_environments[i], static_cast<int>(j)); | 236 val = VariableAt(live_environments[i], static_cast<int>(j)); |
| 237 } | 237 } |
| 238 } | 238 } |
| 239 if (val == resolved) continue; | 239 if (val == resolved) continue; |
| (...skipping 20 matching lines...) Expand all Loading... |
| 260 schedule()->AddNode(next->block_, resolved); | 260 schedule()->AddNode(next->block_, resolved); |
| 261 } | 261 } |
| 262 } | 262 } |
| 263 vars.push_back(resolved); | 263 vars.push_back(resolved); |
| 264 } | 264 } |
| 265 } | 265 } |
| 266 | 266 |
| 267 | 267 |
| 268 void StructuredMachineAssembler::AddGoto(Environment* from, Environment* to) { | 268 void StructuredMachineAssembler::AddGoto(Environment* from, Environment* to) { |
| 269 if (to->is_dead_) { | 269 if (to->is_dead_) { |
| 270 ASSERT(from->is_dead_); | 270 DCHECK(from->is_dead_); |
| 271 return; | 271 return; |
| 272 } | 272 } |
| 273 ASSERT(!from->is_dead_); | 273 DCHECK(!from->is_dead_); |
| 274 schedule()->AddGoto(from->block_, to->block_); | 274 schedule()->AddGoto(from->block_, to->block_); |
| 275 } | 275 } |
| 276 | 276 |
| 277 | 277 |
| 278 // TODO(dcarney): add pass before rpo to schedule to compute these. | 278 // TODO(dcarney): add pass before rpo to schedule to compute these. |
| 279 BasicBlock* StructuredMachineAssembler::TrampolineFor(BasicBlock* block) { | 279 BasicBlock* StructuredMachineAssembler::TrampolineFor(BasicBlock* block) { |
| 280 BasicBlock* trampoline = schedule()->NewBasicBlock(); | 280 BasicBlock* trampoline = schedule()->NewBasicBlock(); |
| 281 schedule()->AddGoto(trampoline, block); | 281 schedule()->AddGoto(trampoline, block); |
| 282 return trampoline; | 282 return trampoline; |
| 283 } | 283 } |
| 284 | 284 |
| 285 | 285 |
| 286 void StructuredMachineAssembler::AddBranch(Environment* environment, | 286 void StructuredMachineAssembler::AddBranch(Environment* environment, |
| 287 Node* condition, | 287 Node* condition, |
| 288 Environment* true_val, | 288 Environment* true_val, |
| 289 Environment* false_val) { | 289 Environment* false_val) { |
| 290 ASSERT(environment->is_dead_ == true_val->is_dead_); | 290 DCHECK(environment->is_dead_ == true_val->is_dead_); |
| 291 ASSERT(environment->is_dead_ == false_val->is_dead_); | 291 DCHECK(environment->is_dead_ == false_val->is_dead_); |
| 292 if (true_val->block_ == false_val->block_) { | 292 if (true_val->block_ == false_val->block_) { |
| 293 if (environment->is_dead_) return; | 293 if (environment->is_dead_) return; |
| 294 AddGoto(environment, true_val); | 294 AddGoto(environment, true_val); |
| 295 return; | 295 return; |
| 296 } | 296 } |
| 297 Node* branch = graph()->NewNode(common()->Branch(), condition); | 297 Node* branch = graph()->NewNode(common()->Branch(), condition); |
| 298 if (environment->is_dead_) return; | 298 if (environment->is_dead_) return; |
| 299 BasicBlock* true_block = TrampolineFor(true_val->block_); | 299 BasicBlock* true_block = TrampolineFor(true_val->block_); |
| 300 BasicBlock* false_block = TrampolineFor(false_val->block_); | 300 BasicBlock* false_block = TrampolineFor(false_val->block_); |
| 301 schedule()->AddBranch(environment->block_, branch, true_block, false_block); | 301 schedule()->AddBranch(environment->block_, branch, true_block, false_block); |
| 302 } | 302 } |
| 303 | 303 |
| 304 | 304 |
| 305 StructuredMachineAssembler::Environment::Environment(Zone* zone, | 305 StructuredMachineAssembler::Environment::Environment(Zone* zone, |
| 306 BasicBlock* block, | 306 BasicBlock* block, |
| 307 bool is_dead) | 307 bool is_dead) |
| 308 : block_(block), | 308 : block_(block), |
| 309 variables_(NodeVector::allocator_type(zone)), | 309 variables_(NodeVector::allocator_type(zone)), |
| 310 is_dead_(is_dead) {} | 310 is_dead_(is_dead) {} |
| 311 | 311 |
| 312 | 312 |
| 313 StructuredMachineAssembler::IfBuilder::IfBuilder( | 313 StructuredMachineAssembler::IfBuilder::IfBuilder( |
| 314 StructuredMachineAssembler* smasm) | 314 StructuredMachineAssembler* smasm) |
| 315 : smasm_(smasm), | 315 : smasm_(smasm), |
| 316 if_clauses_(IfClauses::allocator_type(smasm_->zone())), | 316 if_clauses_(IfClauses::allocator_type(smasm_->zone())), |
| 317 pending_exit_merges_(EnvironmentVector::allocator_type(smasm_->zone())) { | 317 pending_exit_merges_(EnvironmentVector::allocator_type(smasm_->zone())) { |
| 318 ASSERT(smasm_->current_environment_ != NULL); | 318 DCHECK(smasm_->current_environment_ != NULL); |
| 319 PushNewIfClause(); | 319 PushNewIfClause(); |
| 320 ASSERT(!IsDone()); | 320 DCHECK(!IsDone()); |
| 321 } | 321 } |
| 322 | 322 |
| 323 | 323 |
| 324 StructuredMachineAssembler::IfBuilder& | 324 StructuredMachineAssembler::IfBuilder& |
| 325 StructuredMachineAssembler::IfBuilder::If() { | 325 StructuredMachineAssembler::IfBuilder::If() { |
| 326 ASSERT(smasm_->current_environment_ != NULL); | 326 DCHECK(smasm_->current_environment_ != NULL); |
| 327 IfClause* clause = CurrentClause(); | 327 IfClause* clause = CurrentClause(); |
| 328 if (clause->then_environment_ != NULL || clause->else_environment_ != NULL) { | 328 if (clause->then_environment_ != NULL || clause->else_environment_ != NULL) { |
| 329 PushNewIfClause(); | 329 PushNewIfClause(); |
| 330 } | 330 } |
| 331 return *this; | 331 return *this; |
| 332 } | 332 } |
| 333 | 333 |
| 334 | 334 |
| 335 StructuredMachineAssembler::IfBuilder& | 335 StructuredMachineAssembler::IfBuilder& |
| 336 StructuredMachineAssembler::IfBuilder::If(Node* condition) { | 336 StructuredMachineAssembler::IfBuilder::If(Node* condition) { |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 398 pending_else_merges_(PendingMergeStack::allocator_type(zone)), | 398 pending_else_merges_(PendingMergeStack::allocator_type(zone)), |
| 399 then_environment_(NULL), | 399 then_environment_(NULL), |
| 400 else_environment_(NULL) { | 400 else_environment_(NULL) { |
| 401 PushNewExpressionState(); | 401 PushNewExpressionState(); |
| 402 } | 402 } |
| 403 | 403 |
| 404 | 404 |
| 405 StructuredMachineAssembler::IfBuilder::PendingMergeStackRange | 405 StructuredMachineAssembler::IfBuilder::PendingMergeStackRange |
| 406 StructuredMachineAssembler::IfBuilder::IfClause::ComputeRelevantMerges( | 406 StructuredMachineAssembler::IfBuilder::IfClause::ComputeRelevantMerges( |
| 407 CombineType combine_type) { | 407 CombineType combine_type) { |
| 408 ASSERT(!expression_states_.empty()); | 408 DCHECK(!expression_states_.empty()); |
| 409 PendingMergeStack* stack; | 409 PendingMergeStack* stack; |
| 410 int start; | 410 int start; |
| 411 if (combine_type == kCombineThen) { | 411 if (combine_type == kCombineThen) { |
| 412 stack = &pending_then_merges_; | 412 stack = &pending_then_merges_; |
| 413 start = expression_states_.back().pending_then_size_; | 413 start = expression_states_.back().pending_then_size_; |
| 414 } else { | 414 } else { |
| 415 ASSERT(combine_type == kCombineElse); | 415 DCHECK(combine_type == kCombineElse); |
| 416 stack = &pending_else_merges_; | 416 stack = &pending_else_merges_; |
| 417 start = expression_states_.back().pending_else_size_; | 417 start = expression_states_.back().pending_else_size_; |
| 418 } | 418 } |
| 419 PendingMergeStackRange data; | 419 PendingMergeStackRange data; |
| 420 data.merge_stack_ = stack; | 420 data.merge_stack_ = stack; |
| 421 data.start_ = start; | 421 data.start_ = start; |
| 422 data.size_ = static_cast<int>(stack->size()) - start; | 422 data.size_ = static_cast<int>(stack->size()) - start; |
| 423 return data; | 423 return data; |
| 424 } | 424 } |
| 425 | 425 |
| 426 | 426 |
| 427 void StructuredMachineAssembler::IfBuilder::IfClause::ResolvePendingMerges( | 427 void StructuredMachineAssembler::IfBuilder::IfClause::ResolvePendingMerges( |
| 428 StructuredMachineAssembler* smasm, CombineType combine_type, | 428 StructuredMachineAssembler* smasm, CombineType combine_type, |
| 429 ResolutionType resolution_type) { | 429 ResolutionType resolution_type) { |
| 430 ASSERT(smasm->current_environment_ == NULL); | 430 DCHECK(smasm->current_environment_ == NULL); |
| 431 PendingMergeStackRange data = ComputeRelevantMerges(combine_type); | 431 PendingMergeStackRange data = ComputeRelevantMerges(combine_type); |
| 432 ASSERT_EQ(data.merge_stack_->back(), unresolved_list_tail_); | 432 DCHECK_EQ(data.merge_stack_->back(), unresolved_list_tail_); |
| 433 ASSERT(data.size_ > 0); | 433 DCHECK(data.size_ > 0); |
| 434 // TODO(dcarney): assert no new variables created during expression building. | 434 // TODO(dcarney): assert no new variables created during expression building. |
| 435 int truncate_at = initial_environment_size_; | 435 int truncate_at = initial_environment_size_; |
| 436 if (data.size_ == 1) { | 436 if (data.size_ == 1) { |
| 437 // Just copy environment in common case. | 437 // Just copy environment in common case. |
| 438 smasm->current_environment_ = | 438 smasm->current_environment_ = |
| 439 smasm->Copy(unresolved_list_tail_->environment_, truncate_at); | 439 smasm->Copy(unresolved_list_tail_->environment_, truncate_at); |
| 440 } else { | 440 } else { |
| 441 EnvironmentVector environments( | 441 EnvironmentVector environments( |
| 442 EnvironmentVector::allocator_type(smasm->zone())); | 442 EnvironmentVector::allocator_type(smasm->zone())); |
| 443 environments.reserve(data.size_); | 443 environments.reserve(data.size_); |
| 444 CopyEnvironments(data, &environments); | 444 CopyEnvironments(data, &environments); |
| 445 ASSERT(static_cast<int>(environments.size()) == data.size_); | 445 DCHECK(static_cast<int>(environments.size()) == data.size_); |
| 446 smasm->Merge(&environments, truncate_at); | 446 smasm->Merge(&environments, truncate_at); |
| 447 } | 447 } |
| 448 Environment* then_environment = then_environment_; | 448 Environment* then_environment = then_environment_; |
| 449 Environment* else_environment = NULL; | 449 Environment* else_environment = NULL; |
| 450 if (resolution_type == kExpressionDone) { | 450 if (resolution_type == kExpressionDone) { |
| 451 ASSERT(expression_states_.size() == 1); | 451 DCHECK(expression_states_.size() == 1); |
| 452 // Set the current then_ or else_environment_ to the new merged environment. | 452 // Set the current then_ or else_environment_ to the new merged environment. |
| 453 if (combine_type == kCombineThen) { | 453 if (combine_type == kCombineThen) { |
| 454 ASSERT(then_environment_ == NULL && else_environment_ == NULL); | 454 DCHECK(then_environment_ == NULL && else_environment_ == NULL); |
| 455 this->then_environment_ = smasm->current_environment_; | 455 this->then_environment_ = smasm->current_environment_; |
| 456 } else { | 456 } else { |
| 457 ASSERT(else_environment_ == NULL); | 457 DCHECK(else_environment_ == NULL); |
| 458 this->else_environment_ = smasm->current_environment_; | 458 this->else_environment_ = smasm->current_environment_; |
| 459 } | 459 } |
| 460 } else { | 460 } else { |
| 461 ASSERT(resolution_type == kExpressionTerm); | 461 DCHECK(resolution_type == kExpressionTerm); |
| 462 ASSERT(then_environment_ == NULL && else_environment_ == NULL); | 462 DCHECK(then_environment_ == NULL && else_environment_ == NULL); |
| 463 } | 463 } |
| 464 if (combine_type == kCombineThen) { | 464 if (combine_type == kCombineThen) { |
| 465 then_environment = smasm->current_environment_; | 465 then_environment = smasm->current_environment_; |
| 466 } else { | 466 } else { |
| 467 ASSERT(combine_type == kCombineElse); | 467 DCHECK(combine_type == kCombineElse); |
| 468 else_environment = smasm->current_environment_; | 468 else_environment = smasm->current_environment_; |
| 469 } | 469 } |
| 470 // Finalize branches and clear the pending stack. | 470 // Finalize branches and clear the pending stack. |
| 471 FinalizeBranches(smasm, data, combine_type, then_environment, | 471 FinalizeBranches(smasm, data, combine_type, then_environment, |
| 472 else_environment); | 472 else_environment); |
| 473 } | 473 } |
| 474 | 474 |
| 475 | 475 |
| 476 void StructuredMachineAssembler::IfBuilder::IfClause::CopyEnvironments( | 476 void StructuredMachineAssembler::IfBuilder::IfClause::CopyEnvironments( |
| 477 const PendingMergeStackRange& data, EnvironmentVector* environments) { | 477 const PendingMergeStackRange& data, EnvironmentVector* environments) { |
| 478 PendingMergeStack::iterator i = data.merge_stack_->begin(); | 478 PendingMergeStack::iterator i = data.merge_stack_->begin(); |
| 479 PendingMergeStack::iterator end = data.merge_stack_->end(); | 479 PendingMergeStack::iterator end = data.merge_stack_->end(); |
| 480 for (i += data.start_; i != end; ++i) { | 480 for (i += data.start_; i != end; ++i) { |
| 481 environments->push_back((*i)->environment_); | 481 environments->push_back((*i)->environment_); |
| 482 } | 482 } |
| 483 } | 483 } |
| 484 | 484 |
| 485 | 485 |
| 486 void StructuredMachineAssembler::IfBuilder::IfClause::PushNewExpressionState() { | 486 void StructuredMachineAssembler::IfBuilder::IfClause::PushNewExpressionState() { |
| 487 ExpressionState next; | 487 ExpressionState next; |
| 488 next.pending_then_size_ = static_cast<int>(pending_then_merges_.size()); | 488 next.pending_then_size_ = static_cast<int>(pending_then_merges_.size()); |
| 489 next.pending_else_size_ = static_cast<int>(pending_else_merges_.size()); | 489 next.pending_else_size_ = static_cast<int>(pending_else_merges_.size()); |
| 490 expression_states_.push_back(next); | 490 expression_states_.push_back(next); |
| 491 } | 491 } |
| 492 | 492 |
| 493 | 493 |
| 494 void StructuredMachineAssembler::IfBuilder::IfClause::PopExpressionState() { | 494 void StructuredMachineAssembler::IfBuilder::IfClause::PopExpressionState() { |
| 495 expression_states_.pop_back(); | 495 expression_states_.pop_back(); |
| 496 ASSERT(!expression_states_.empty()); | 496 DCHECK(!expression_states_.empty()); |
| 497 } | 497 } |
| 498 | 498 |
| 499 | 499 |
| 500 void StructuredMachineAssembler::IfBuilder::IfClause::FinalizeBranches( | 500 void StructuredMachineAssembler::IfBuilder::IfClause::FinalizeBranches( |
| 501 StructuredMachineAssembler* smasm, const PendingMergeStackRange& data, | 501 StructuredMachineAssembler* smasm, const PendingMergeStackRange& data, |
| 502 CombineType combine_type, Environment* const then_environment, | 502 CombineType combine_type, Environment* const then_environment, |
| 503 Environment* const else_environment) { | 503 Environment* const else_environment) { |
| 504 ASSERT(unresolved_list_tail_ != NULL); | 504 DCHECK(unresolved_list_tail_ != NULL); |
| 505 ASSERT(smasm->current_environment_ != NULL); | 505 DCHECK(smasm->current_environment_ != NULL); |
| 506 if (data.size_ == 0) return; | 506 if (data.size_ == 0) return; |
| 507 PendingMergeStack::iterator curr = data.merge_stack_->begin(); | 507 PendingMergeStack::iterator curr = data.merge_stack_->begin(); |
| 508 PendingMergeStack::iterator end = data.merge_stack_->end(); | 508 PendingMergeStack::iterator end = data.merge_stack_->end(); |
| 509 // Finalize everything but the head first, | 509 // Finalize everything but the head first, |
| 510 // in the order the branches enter the merge block. | 510 // in the order the branches enter the merge block. |
| 511 end -= 1; | 511 end -= 1; |
| 512 Environment* true_val = then_environment; | 512 Environment* true_val = then_environment; |
| 513 Environment* false_val = else_environment; | 513 Environment* false_val = else_environment; |
| 514 Environment** next; | 514 Environment** next; |
| 515 if (combine_type == kCombineThen) { | 515 if (combine_type == kCombineThen) { |
| 516 next = &false_val; | 516 next = &false_val; |
| 517 } else { | 517 } else { |
| 518 ASSERT(combine_type == kCombineElse); | 518 DCHECK(combine_type == kCombineElse); |
| 519 next = &true_val; | 519 next = &true_val; |
| 520 } | 520 } |
| 521 for (curr += data.start_; curr != end; ++curr) { | 521 for (curr += data.start_; curr != end; ++curr) { |
| 522 UnresolvedBranch* branch = *curr; | 522 UnresolvedBranch* branch = *curr; |
| 523 *next = branch->next_->environment_; | 523 *next = branch->next_->environment_; |
| 524 smasm->AddBranch(branch->environment_, branch->condition_, true_val, | 524 smasm->AddBranch(branch->environment_, branch->condition_, true_val, |
| 525 false_val); | 525 false_val); |
| 526 } | 526 } |
| 527 ASSERT(curr + 1 == data.merge_stack_->end()); | 527 DCHECK(curr + 1 == data.merge_stack_->end()); |
| 528 // Now finalize the tail if possible. | 528 // Now finalize the tail if possible. |
| 529 if (then_environment != NULL && else_environment != NULL) { | 529 if (then_environment != NULL && else_environment != NULL) { |
| 530 UnresolvedBranch* branch = *curr; | 530 UnresolvedBranch* branch = *curr; |
| 531 smasm->AddBranch(branch->environment_, branch->condition_, then_environment, | 531 smasm->AddBranch(branch->environment_, branch->condition_, then_environment, |
| 532 else_environment); | 532 else_environment); |
| 533 } | 533 } |
| 534 // Clear the merge stack. | 534 // Clear the merge stack. |
| 535 PendingMergeStack::iterator begin = data.merge_stack_->begin(); | 535 PendingMergeStack::iterator begin = data.merge_stack_->begin(); |
| 536 begin += data.start_; | 536 begin += data.start_; |
| 537 data.merge_stack_->erase(begin, data.merge_stack_->end()); | 537 data.merge_stack_->erase(begin, data.merge_stack_->end()); |
| 538 ASSERT_EQ(static_cast<int>(data.merge_stack_->size()), data.start_); | 538 DCHECK_EQ(static_cast<int>(data.merge_stack_->size()), data.start_); |
| 539 } | 539 } |
| 540 | 540 |
| 541 | 541 |
| 542 void StructuredMachineAssembler::IfBuilder::End() { | 542 void StructuredMachineAssembler::IfBuilder::End() { |
| 543 ASSERT(!IsDone()); | 543 DCHECK(!IsDone()); |
| 544 AddCurrentToPending(); | 544 AddCurrentToPending(); |
| 545 size_t current_pending = pending_exit_merges_.size(); | 545 size_t current_pending = pending_exit_merges_.size(); |
| 546 // All unresolved branch edges are now set to pending. | 546 // All unresolved branch edges are now set to pending. |
| 547 for (IfClauses::iterator i = if_clauses_.begin(); i != if_clauses_.end(); | 547 for (IfClauses::iterator i = if_clauses_.begin(); i != if_clauses_.end(); |
| 548 ++i) { | 548 ++i) { |
| 549 IfClause* clause = *i; | 549 IfClause* clause = *i; |
| 550 ASSERT(clause->expression_states_.size() == 1); | 550 DCHECK(clause->expression_states_.size() == 1); |
| 551 PendingMergeStackRange data; | 551 PendingMergeStackRange data; |
| 552 // Copy then environments. | 552 // Copy then environments. |
| 553 data = clause->ComputeRelevantMerges(kCombineThen); | 553 data = clause->ComputeRelevantMerges(kCombineThen); |
| 554 clause->CopyEnvironments(data, &pending_exit_merges_); | 554 clause->CopyEnvironments(data, &pending_exit_merges_); |
| 555 Environment* head = NULL; | 555 Environment* head = NULL; |
| 556 // Will resolve the head node in the else_merge | 556 // Will resolve the head node in the else_merge |
| 557 if (data.size_ > 0 && clause->then_environment_ == NULL && | 557 if (data.size_ > 0 && clause->then_environment_ == NULL && |
| 558 clause->else_environment_ == NULL) { | 558 clause->else_environment_ == NULL) { |
| 559 head = pending_exit_merges_.back(); | 559 head = pending_exit_merges_.back(); |
| 560 pending_exit_merges_.pop_back(); | 560 pending_exit_merges_.pop_back(); |
| 561 } | 561 } |
| 562 // Copy else environments. | 562 // Copy else environments. |
| 563 data = clause->ComputeRelevantMerges(kCombineElse); | 563 data = clause->ComputeRelevantMerges(kCombineElse); |
| 564 clause->CopyEnvironments(data, &pending_exit_merges_); | 564 clause->CopyEnvironments(data, &pending_exit_merges_); |
| 565 if (head != NULL) { | 565 if (head != NULL) { |
| 566 // Must have data to merge, or else head will never get a branch. | 566 // Must have data to merge, or else head will never get a branch. |
| 567 ASSERT(data.size_ != 0); | 567 DCHECK(data.size_ != 0); |
| 568 pending_exit_merges_.push_back(head); | 568 pending_exit_merges_.push_back(head); |
| 569 } | 569 } |
| 570 } | 570 } |
| 571 smasm_->Merge(&pending_exit_merges_, | 571 smasm_->Merge(&pending_exit_merges_, |
| 572 if_clauses_[0]->initial_environment_size_); | 572 if_clauses_[0]->initial_environment_size_); |
| 573 // Anything initally pending jumps into the new environment. | 573 // Anything initally pending jumps into the new environment. |
| 574 for (size_t i = 0; i < current_pending; ++i) { | 574 for (size_t i = 0; i < current_pending; ++i) { |
| 575 smasm_->AddGoto(pending_exit_merges_[i], smasm_->current_environment_); | 575 smasm_->AddGoto(pending_exit_merges_[i], smasm_->current_environment_); |
| 576 } | 576 } |
| 577 // Resolve all branches. | 577 // Resolve all branches. |
| (...skipping 16 matching lines...) Expand all Loading... |
| 594 if (else_environment == NULL) { | 594 if (else_environment == NULL) { |
| 595 else_environment = smasm_->current_environment_; | 595 else_environment = smasm_->current_environment_; |
| 596 } | 596 } |
| 597 data = clause->ComputeRelevantMerges(kCombineElse); | 597 data = clause->ComputeRelevantMerges(kCombineElse); |
| 598 clause->FinalizeBranches(smasm_, data, kCombineElse, then_environment, | 598 clause->FinalizeBranches(smasm_, data, kCombineElse, then_environment, |
| 599 else_environment); | 599 else_environment); |
| 600 } | 600 } |
| 601 // Future accesses to this builder should crash immediately. | 601 // Future accesses to this builder should crash immediately. |
| 602 pending_exit_merges_.clear(); | 602 pending_exit_merges_.clear(); |
| 603 if_clauses_.clear(); | 603 if_clauses_.clear(); |
| 604 ASSERT(IsDone()); | 604 DCHECK(IsDone()); |
| 605 } | 605 } |
| 606 | 606 |
| 607 | 607 |
| 608 StructuredMachineAssembler::LoopBuilder::LoopBuilder( | 608 StructuredMachineAssembler::LoopBuilder::LoopBuilder( |
| 609 StructuredMachineAssembler* smasm) | 609 StructuredMachineAssembler* smasm) |
| 610 : smasm_(smasm), | 610 : smasm_(smasm), |
| 611 header_environment_(NULL), | 611 header_environment_(NULL), |
| 612 pending_header_merges_(EnvironmentVector::allocator_type(smasm_->zone())), | 612 pending_header_merges_(EnvironmentVector::allocator_type(smasm_->zone())), |
| 613 pending_exit_merges_(EnvironmentVector::allocator_type(smasm_->zone())) { | 613 pending_exit_merges_(EnvironmentVector::allocator_type(smasm_->zone())) { |
| 614 ASSERT(smasm_->current_environment_ != NULL); | 614 DCHECK(smasm_->current_environment_ != NULL); |
| 615 // Create header environment. | 615 // Create header environment. |
| 616 header_environment_ = smasm_->CopyForLoopHeader(smasm_->current_environment_); | 616 header_environment_ = smasm_->CopyForLoopHeader(smasm_->current_environment_); |
| 617 smasm_->AddGoto(smasm_->current_environment_, header_environment_); | 617 smasm_->AddGoto(smasm_->current_environment_, header_environment_); |
| 618 // Create body environment. | 618 // Create body environment. |
| 619 Environment* body = smasm_->Copy(header_environment_); | 619 Environment* body = smasm_->Copy(header_environment_); |
| 620 smasm_->AddGoto(header_environment_, body); | 620 smasm_->AddGoto(header_environment_, body); |
| 621 smasm_->current_environment_ = body; | 621 smasm_->current_environment_ = body; |
| 622 ASSERT(!IsDone()); | 622 DCHECK(!IsDone()); |
| 623 } | 623 } |
| 624 | 624 |
| 625 | 625 |
| 626 void StructuredMachineAssembler::LoopBuilder::Continue() { | 626 void StructuredMachineAssembler::LoopBuilder::Continue() { |
| 627 ASSERT(!IsDone()); | 627 DCHECK(!IsDone()); |
| 628 pending_header_merges_.push_back(smasm_->current_environment_); | 628 pending_header_merges_.push_back(smasm_->current_environment_); |
| 629 smasm_->CopyCurrentAsDead(); | 629 smasm_->CopyCurrentAsDead(); |
| 630 } | 630 } |
| 631 | 631 |
| 632 | 632 |
| 633 void StructuredMachineAssembler::LoopBuilder::Break() { | 633 void StructuredMachineAssembler::LoopBuilder::Break() { |
| 634 ASSERT(!IsDone()); | 634 DCHECK(!IsDone()); |
| 635 pending_exit_merges_.push_back(smasm_->current_environment_); | 635 pending_exit_merges_.push_back(smasm_->current_environment_); |
| 636 smasm_->CopyCurrentAsDead(); | 636 smasm_->CopyCurrentAsDead(); |
| 637 } | 637 } |
| 638 | 638 |
| 639 | 639 |
| 640 void StructuredMachineAssembler::LoopBuilder::End() { | 640 void StructuredMachineAssembler::LoopBuilder::End() { |
| 641 ASSERT(!IsDone()); | 641 DCHECK(!IsDone()); |
| 642 if (smasm_->current_environment_ != NULL) { | 642 if (smasm_->current_environment_ != NULL) { |
| 643 Continue(); | 643 Continue(); |
| 644 } | 644 } |
| 645 // Do loop header merges. | 645 // Do loop header merges. |
| 646 smasm_->MergeBackEdgesToLoopHeader(header_environment_, | 646 smasm_->MergeBackEdgesToLoopHeader(header_environment_, |
| 647 &pending_header_merges_); | 647 &pending_header_merges_); |
| 648 int initial_size = static_cast<int>(header_environment_->variables_.size()); | 648 int initial_size = static_cast<int>(header_environment_->variables_.size()); |
| 649 // Do loop exit merges, truncating loop variables away. | 649 // Do loop exit merges, truncating loop variables away. |
| 650 smasm_->Merge(&pending_exit_merges_, initial_size); | 650 smasm_->Merge(&pending_exit_merges_, initial_size); |
| 651 for (EnvironmentVector::iterator i = pending_exit_merges_.begin(); | 651 for (EnvironmentVector::iterator i = pending_exit_merges_.begin(); |
| 652 i != pending_exit_merges_.end(); ++i) { | 652 i != pending_exit_merges_.end(); ++i) { |
| 653 smasm_->AddGoto(*i, smasm_->current_environment_); | 653 smasm_->AddGoto(*i, smasm_->current_environment_); |
| 654 } | 654 } |
| 655 pending_header_merges_.clear(); | 655 pending_header_merges_.clear(); |
| 656 pending_exit_merges_.clear(); | 656 pending_exit_merges_.clear(); |
| 657 header_environment_ = NULL; | 657 header_environment_ = NULL; |
| 658 ASSERT(IsDone()); | 658 DCHECK(IsDone()); |
| 659 } | 659 } |
| 660 | 660 |
| 661 } // namespace compiler | 661 } // namespace compiler |
| 662 } // namespace internal | 662 } // namespace internal |
| 663 } // namespace v8 | 663 } // namespace v8 |
| OLD | NEW |