| 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/instruction-selector.h" | 5 #include "src/compiler/instruction-selector.h" |
| 6 | 6 |
| 7 #include "src/compiler/instruction-selector-impl.h" | 7 #include "src/compiler/instruction-selector-impl.h" |
| 8 #include "src/compiler/node-matchers.h" | 8 #include "src/compiler/node-matchers.h" |
| 9 #include "src/compiler/node-properties-inl.h" | 9 #include "src/compiler/node-properties-inl.h" |
| 10 #include "src/compiler/pipeline.h" | 10 #include "src/compiler/pipeline.h" |
| (...skipping 12 matching lines...) Expand all Loading... |
| 23 defined_(graph()->NodeCount(), false, BoolVector::allocator_type(zone())), | 23 defined_(graph()->NodeCount(), false, BoolVector::allocator_type(zone())), |
| 24 used_(graph()->NodeCount(), false, BoolVector::allocator_type(zone())) {} | 24 used_(graph()->NodeCount(), false, BoolVector::allocator_type(zone())) {} |
| 25 | 25 |
| 26 | 26 |
| 27 void InstructionSelector::SelectInstructions() { | 27 void InstructionSelector::SelectInstructions() { |
| 28 // Mark the inputs of all phis in loop headers as used. | 28 // Mark the inputs of all phis in loop headers as used. |
| 29 BasicBlockVector* blocks = schedule()->rpo_order(); | 29 BasicBlockVector* blocks = schedule()->rpo_order(); |
| 30 for (BasicBlockVectorIter i = blocks->begin(); i != blocks->end(); ++i) { | 30 for (BasicBlockVectorIter i = blocks->begin(); i != blocks->end(); ++i) { |
| 31 BasicBlock* block = *i; | 31 BasicBlock* block = *i; |
| 32 if (!block->IsLoopHeader()) continue; | 32 if (!block->IsLoopHeader()) continue; |
| 33 ASSERT_NE(0, block->PredecessorCount()); | 33 DCHECK_NE(0, block->PredecessorCount()); |
| 34 ASSERT_NE(1, block->PredecessorCount()); | 34 DCHECK_NE(1, block->PredecessorCount()); |
| 35 for (BasicBlock::const_iterator j = block->begin(); j != block->end(); | 35 for (BasicBlock::const_iterator j = block->begin(); j != block->end(); |
| 36 ++j) { | 36 ++j) { |
| 37 Node* phi = *j; | 37 Node* phi = *j; |
| 38 if (phi->opcode() != IrOpcode::kPhi) continue; | 38 if (phi->opcode() != IrOpcode::kPhi) continue; |
| 39 | 39 |
| 40 // Mark all inputs as used. | 40 // Mark all inputs as used. |
| 41 Node::Inputs inputs = phi->inputs(); | 41 Node::Inputs inputs = phi->inputs(); |
| 42 for (InputIter k = inputs.begin(); k != inputs.end(); ++k) { | 42 for (InputIter k = inputs.begin(); k != inputs.end(); ++k) { |
| 43 MarkAsUsed(*k); | 43 MarkAsUsed(*k); |
| 44 } | 44 } |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 144 } | 144 } |
| 145 | 145 |
| 146 | 146 |
| 147 bool InstructionSelector::CanCover(Node* user, Node* node) const { | 147 bool InstructionSelector::CanCover(Node* user, Node* node) const { |
| 148 return node->OwnedBy(user) && | 148 return node->OwnedBy(user) && |
| 149 schedule()->block(node) == schedule()->block(user); | 149 schedule()->block(node) == schedule()->block(user); |
| 150 } | 150 } |
| 151 | 151 |
| 152 | 152 |
| 153 bool InstructionSelector::IsDefined(Node* node) const { | 153 bool InstructionSelector::IsDefined(Node* node) const { |
| 154 ASSERT_NOT_NULL(node); | 154 DCHECK_NOT_NULL(node); |
| 155 NodeId id = node->id(); | 155 NodeId id = node->id(); |
| 156 ASSERT(id >= 0); | 156 DCHECK(id >= 0); |
| 157 ASSERT(id < static_cast<NodeId>(defined_.size())); | 157 DCHECK(id < static_cast<NodeId>(defined_.size())); |
| 158 return defined_[id]; | 158 return defined_[id]; |
| 159 } | 159 } |
| 160 | 160 |
| 161 | 161 |
| 162 void InstructionSelector::MarkAsDefined(Node* node) { | 162 void InstructionSelector::MarkAsDefined(Node* node) { |
| 163 ASSERT_NOT_NULL(node); | 163 DCHECK_NOT_NULL(node); |
| 164 NodeId id = node->id(); | 164 NodeId id = node->id(); |
| 165 ASSERT(id >= 0); | 165 DCHECK(id >= 0); |
| 166 ASSERT(id < static_cast<NodeId>(defined_.size())); | 166 DCHECK(id < static_cast<NodeId>(defined_.size())); |
| 167 defined_[id] = true; | 167 defined_[id] = true; |
| 168 } | 168 } |
| 169 | 169 |
| 170 | 170 |
| 171 bool InstructionSelector::IsUsed(Node* node) const { | 171 bool InstructionSelector::IsUsed(Node* node) const { |
| 172 if (!node->op()->HasProperty(Operator::kEliminatable)) return true; | 172 if (!node->op()->HasProperty(Operator::kEliminatable)) return true; |
| 173 NodeId id = node->id(); | 173 NodeId id = node->id(); |
| 174 ASSERT(id >= 0); | 174 DCHECK(id >= 0); |
| 175 ASSERT(id < static_cast<NodeId>(used_.size())); | 175 DCHECK(id < static_cast<NodeId>(used_.size())); |
| 176 return used_[id]; | 176 return used_[id]; |
| 177 } | 177 } |
| 178 | 178 |
| 179 | 179 |
| 180 void InstructionSelector::MarkAsUsed(Node* node) { | 180 void InstructionSelector::MarkAsUsed(Node* node) { |
| 181 ASSERT_NOT_NULL(node); | 181 DCHECK_NOT_NULL(node); |
| 182 NodeId id = node->id(); | 182 NodeId id = node->id(); |
| 183 ASSERT(id >= 0); | 183 DCHECK(id >= 0); |
| 184 ASSERT(id < static_cast<NodeId>(used_.size())); | 184 DCHECK(id < static_cast<NodeId>(used_.size())); |
| 185 used_[id] = true; | 185 used_[id] = true; |
| 186 } | 186 } |
| 187 | 187 |
| 188 | 188 |
| 189 bool InstructionSelector::IsDouble(const Node* node) const { | 189 bool InstructionSelector::IsDouble(const Node* node) const { |
| 190 ASSERT_NOT_NULL(node); | 190 DCHECK_NOT_NULL(node); |
| 191 return sequence()->IsDouble(node->id()); | 191 return sequence()->IsDouble(node->id()); |
| 192 } | 192 } |
| 193 | 193 |
| 194 | 194 |
| 195 void InstructionSelector::MarkAsDouble(Node* node) { | 195 void InstructionSelector::MarkAsDouble(Node* node) { |
| 196 ASSERT_NOT_NULL(node); | 196 DCHECK_NOT_NULL(node); |
| 197 ASSERT(!IsReference(node)); | 197 DCHECK(!IsReference(node)); |
| 198 sequence()->MarkAsDouble(node->id()); | 198 sequence()->MarkAsDouble(node->id()); |
| 199 | 199 |
| 200 // Propagate "doubleness" throughout phis. | 200 // Propagate "doubleness" throughout phis. |
| 201 for (UseIter i = node->uses().begin(); i != node->uses().end(); ++i) { | 201 for (UseIter i = node->uses().begin(); i != node->uses().end(); ++i) { |
| 202 Node* user = *i; | 202 Node* user = *i; |
| 203 if (user->opcode() != IrOpcode::kPhi) continue; | 203 if (user->opcode() != IrOpcode::kPhi) continue; |
| 204 if (IsDouble(user)) continue; | 204 if (IsDouble(user)) continue; |
| 205 MarkAsDouble(user); | 205 MarkAsDouble(user); |
| 206 } | 206 } |
| 207 } | 207 } |
| 208 | 208 |
| 209 | 209 |
| 210 bool InstructionSelector::IsReference(const Node* node) const { | 210 bool InstructionSelector::IsReference(const Node* node) const { |
| 211 ASSERT_NOT_NULL(node); | 211 DCHECK_NOT_NULL(node); |
| 212 return sequence()->IsReference(node->id()); | 212 return sequence()->IsReference(node->id()); |
| 213 } | 213 } |
| 214 | 214 |
| 215 | 215 |
| 216 void InstructionSelector::MarkAsReference(Node* node) { | 216 void InstructionSelector::MarkAsReference(Node* node) { |
| 217 ASSERT_NOT_NULL(node); | 217 DCHECK_NOT_NULL(node); |
| 218 ASSERT(!IsDouble(node)); | 218 DCHECK(!IsDouble(node)); |
| 219 sequence()->MarkAsReference(node->id()); | 219 sequence()->MarkAsReference(node->id()); |
| 220 | 220 |
| 221 // Propagate "referenceness" throughout phis. | 221 // Propagate "referenceness" throughout phis. |
| 222 for (UseIter i = node->uses().begin(); i != node->uses().end(); ++i) { | 222 for (UseIter i = node->uses().begin(); i != node->uses().end(); ++i) { |
| 223 Node* user = *i; | 223 Node* user = *i; |
| 224 if (user->opcode() != IrOpcode::kPhi) continue; | 224 if (user->opcode() != IrOpcode::kPhi) continue; |
| 225 if (IsReference(user)) continue; | 225 if (IsReference(user)) continue; |
| 226 MarkAsReference(user); | 226 MarkAsReference(user); |
| 227 } | 227 } |
| 228 } | 228 } |
| 229 | 229 |
| 230 | 230 |
| 231 void InstructionSelector::MarkAsRepresentation(MachineRepresentation rep, | 231 void InstructionSelector::MarkAsRepresentation(MachineRepresentation rep, |
| 232 Node* node) { | 232 Node* node) { |
| 233 ASSERT_NOT_NULL(node); | 233 DCHECK_NOT_NULL(node); |
| 234 if (rep == kMachineFloat64) MarkAsDouble(node); | 234 if (rep == kMachineFloat64) MarkAsDouble(node); |
| 235 if (rep == kMachineTagged) MarkAsReference(node); | 235 if (rep == kMachineTagged) MarkAsReference(node); |
| 236 } | 236 } |
| 237 | 237 |
| 238 | 238 |
| 239 // TODO(bmeurer): Get rid of the CallBuffer business and make | 239 // TODO(bmeurer): Get rid of the CallBuffer business and make |
| 240 // InstructionSelector::VisitCall platform independent instead. | 240 // InstructionSelector::VisitCall platform independent instead. |
| 241 CallBuffer::CallBuffer(Zone* zone, CallDescriptor* d) | 241 CallBuffer::CallBuffer(Zone* zone, CallDescriptor* d) |
| 242 : output_count(0), | 242 : output_count(0), |
| 243 descriptor(d), | 243 descriptor(d), |
| (...skipping 12 matching lines...) Expand all Loading... |
| 256 | 256 |
| 257 | 257 |
| 258 // TODO(bmeurer): Get rid of the CallBuffer business and make | 258 // TODO(bmeurer): Get rid of the CallBuffer business and make |
| 259 // InstructionSelector::VisitCall platform independent instead. | 259 // InstructionSelector::VisitCall platform independent instead. |
| 260 void InstructionSelector::InitializeCallBuffer(Node* call, CallBuffer* buffer, | 260 void InstructionSelector::InitializeCallBuffer(Node* call, CallBuffer* buffer, |
| 261 bool call_code_immediate, | 261 bool call_code_immediate, |
| 262 bool call_address_immediate, | 262 bool call_address_immediate, |
| 263 BasicBlock* cont_node, | 263 BasicBlock* cont_node, |
| 264 BasicBlock* deopt_node) { | 264 BasicBlock* deopt_node) { |
| 265 OperandGenerator g(this); | 265 OperandGenerator g(this); |
| 266 ASSERT_EQ(call->op()->OutputCount(), buffer->descriptor->ReturnCount()); | 266 DCHECK_EQ(call->op()->OutputCount(), buffer->descriptor->ReturnCount()); |
| 267 ASSERT_EQ(NodeProperties::GetValueInputCount(call), buffer->input_count()); | 267 DCHECK_EQ(NodeProperties::GetValueInputCount(call), buffer->input_count()); |
| 268 | 268 |
| 269 if (buffer->descriptor->ReturnCount() > 0) { | 269 if (buffer->descriptor->ReturnCount() > 0) { |
| 270 // Collect the projections that represent multiple outputs from this call. | 270 // Collect the projections that represent multiple outputs from this call. |
| 271 if (buffer->descriptor->ReturnCount() == 1) { | 271 if (buffer->descriptor->ReturnCount() == 1) { |
| 272 buffer->output_nodes[0] = call; | 272 buffer->output_nodes[0] = call; |
| 273 } else { | 273 } else { |
| 274 call->CollectProjections(buffer->descriptor->ReturnCount(), | 274 call->CollectProjections(buffer->descriptor->ReturnCount(), |
| 275 buffer->output_nodes); | 275 buffer->output_nodes); |
| 276 } | 276 } |
| 277 | 277 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 311 } | 311 } |
| 312 | 312 |
| 313 int input_count = buffer->input_count(); | 313 int input_count = buffer->input_count(); |
| 314 | 314 |
| 315 // Split the arguments into pushed_nodes and fixed_args. Pushed arguments | 315 // Split the arguments into pushed_nodes and fixed_args. Pushed arguments |
| 316 // require an explicit push instruction before the call and do not appear | 316 // require an explicit push instruction before the call and do not appear |
| 317 // as arguments to the call. Everything else ends up as an InstructionOperand | 317 // as arguments to the call. Everything else ends up as an InstructionOperand |
| 318 // argument to the call. | 318 // argument to the call. |
| 319 InputIter iter(call->inputs().begin()); | 319 InputIter iter(call->inputs().begin()); |
| 320 for (int index = 0; index < input_count; ++iter, ++index) { | 320 for (int index = 0; index < input_count; ++iter, ++index) { |
| 321 ASSERT(iter != call->inputs().end()); | 321 DCHECK(iter != call->inputs().end()); |
| 322 ASSERT(index == iter.index()); | 322 DCHECK(index == iter.index()); |
| 323 if (index == 0) continue; // The first argument (callee) is already done. | 323 if (index == 0) continue; // The first argument (callee) is already done. |
| 324 InstructionOperand* op = | 324 InstructionOperand* op = |
| 325 g.UseLocation(*iter, buffer->descriptor->GetInputLocation(index)); | 325 g.UseLocation(*iter, buffer->descriptor->GetInputLocation(index)); |
| 326 if (UnallocatedOperand::cast(op)->HasFixedSlotPolicy()) { | 326 if (UnallocatedOperand::cast(op)->HasFixedSlotPolicy()) { |
| 327 int stack_index = -UnallocatedOperand::cast(op)->fixed_slot_index() - 1; | 327 int stack_index = -UnallocatedOperand::cast(op)->fixed_slot_index() - 1; |
| 328 ASSERT(buffer->pushed_nodes[stack_index] == NULL); | 328 DCHECK(buffer->pushed_nodes[stack_index] == NULL); |
| 329 buffer->pushed_nodes[stack_index] = *iter; | 329 buffer->pushed_nodes[stack_index] = *iter; |
| 330 buffer->pushed_count++; | 330 buffer->pushed_count++; |
| 331 } else { | 331 } else { |
| 332 buffer->fixed_and_control_args[buffer->fixed_count] = op; | 332 buffer->fixed_and_control_args[buffer->fixed_count] = op; |
| 333 buffer->fixed_count++; | 333 buffer->fixed_count++; |
| 334 } | 334 } |
| 335 } | 335 } |
| 336 | 336 |
| 337 // If the call can deoptimize, we add the continuation and deoptimization | 337 // If the call can deoptimize, we add the continuation and deoptimization |
| 338 // block labels. | 338 // block labels. |
| 339 if (buffer->descriptor->CanLazilyDeoptimize()) { | 339 if (buffer->descriptor->CanLazilyDeoptimize()) { |
| 340 ASSERT(cont_node != NULL); | 340 DCHECK(cont_node != NULL); |
| 341 ASSERT(deopt_node != NULL); | 341 DCHECK(deopt_node != NULL); |
| 342 buffer->fixed_and_control_args[buffer->fixed_count] = g.Label(cont_node); | 342 buffer->fixed_and_control_args[buffer->fixed_count] = g.Label(cont_node); |
| 343 buffer->fixed_and_control_args[buffer->fixed_count + 1] = | 343 buffer->fixed_and_control_args[buffer->fixed_count + 1] = |
| 344 g.Label(deopt_node); | 344 g.Label(deopt_node); |
| 345 } else { | 345 } else { |
| 346 ASSERT(cont_node == NULL); | 346 DCHECK(cont_node == NULL); |
| 347 ASSERT(deopt_node == NULL); | 347 DCHECK(deopt_node == NULL); |
| 348 } | 348 } |
| 349 | 349 |
| 350 ASSERT(input_count == (buffer->fixed_count + buffer->pushed_count)); | 350 DCHECK(input_count == (buffer->fixed_count + buffer->pushed_count)); |
| 351 } | 351 } |
| 352 | 352 |
| 353 | 353 |
| 354 void InstructionSelector::VisitBlock(BasicBlock* block) { | 354 void InstructionSelector::VisitBlock(BasicBlock* block) { |
| 355 ASSERT_EQ(NULL, current_block_); | 355 DCHECK_EQ(NULL, current_block_); |
| 356 current_block_ = block; | 356 current_block_ = block; |
| 357 int current_block_end = static_cast<int>(instructions_.size()); | 357 int current_block_end = static_cast<int>(instructions_.size()); |
| 358 | 358 |
| 359 // Generate code for the block control "top down", but schedule the code | 359 // Generate code for the block control "top down", but schedule the code |
| 360 // "bottom up". | 360 // "bottom up". |
| 361 VisitControl(block); | 361 VisitControl(block); |
| 362 std::reverse(instructions_.begin() + current_block_end, instructions_.end()); | 362 std::reverse(instructions_.begin() + current_block_end, instructions_.end()); |
| 363 | 363 |
| 364 // Visit code in reverse control flow order, because architecture-specific | 364 // Visit code in reverse control flow order, because architecture-specific |
| 365 // matching may cover more than one node at a time. | 365 // matching may cover more than one node at a time. |
| (...skipping 28 matching lines...) Expand all Loading... |
| 394 #endif | 394 #endif |
| 395 } | 395 } |
| 396 | 396 |
| 397 | 397 |
| 398 void InstructionSelector::VisitControl(BasicBlock* block) { | 398 void InstructionSelector::VisitControl(BasicBlock* block) { |
| 399 Node* input = block->control_input_; | 399 Node* input = block->control_input_; |
| 400 switch (block->control_) { | 400 switch (block->control_) { |
| 401 case BasicBlockData::kGoto: | 401 case BasicBlockData::kGoto: |
| 402 return VisitGoto(block->SuccessorAt(0)); | 402 return VisitGoto(block->SuccessorAt(0)); |
| 403 case BasicBlockData::kBranch: { | 403 case BasicBlockData::kBranch: { |
| 404 ASSERT_EQ(IrOpcode::kBranch, input->opcode()); | 404 DCHECK_EQ(IrOpcode::kBranch, input->opcode()); |
| 405 BasicBlock* tbranch = block->SuccessorAt(0); | 405 BasicBlock* tbranch = block->SuccessorAt(0); |
| 406 BasicBlock* fbranch = block->SuccessorAt(1); | 406 BasicBlock* fbranch = block->SuccessorAt(1); |
| 407 // SSA deconstruction requires targets of branches not to have phis. | 407 // SSA deconstruction requires targets of branches not to have phis. |
| 408 // Edge split form guarantees this property, but is more strict. | 408 // Edge split form guarantees this property, but is more strict. |
| 409 CheckNoPhis(tbranch); | 409 CheckNoPhis(tbranch); |
| 410 CheckNoPhis(fbranch); | 410 CheckNoPhis(fbranch); |
| 411 if (tbranch == fbranch) return VisitGoto(tbranch); | 411 if (tbranch == fbranch) return VisitGoto(tbranch); |
| 412 return VisitBranch(input, tbranch, fbranch); | 412 return VisitBranch(input, tbranch, fbranch); |
| 413 } | 413 } |
| 414 case BasicBlockData::kReturn: { | 414 case BasicBlockData::kReturn: { |
| 415 // If the result itself is a return, return its input. | 415 // If the result itself is a return, return its input. |
| 416 Node* value = (input != NULL && input->opcode() == IrOpcode::kReturn) | 416 Node* value = (input != NULL && input->opcode() == IrOpcode::kReturn) |
| 417 ? input->InputAt(0) | 417 ? input->InputAt(0) |
| 418 : input; | 418 : input; |
| 419 return VisitReturn(value); | 419 return VisitReturn(value); |
| 420 } | 420 } |
| 421 case BasicBlockData::kThrow: | 421 case BasicBlockData::kThrow: |
| 422 return VisitThrow(input); | 422 return VisitThrow(input); |
| 423 case BasicBlockData::kDeoptimize: | 423 case BasicBlockData::kDeoptimize: |
| 424 return VisitDeoptimization(input); | 424 return VisitDeoptimization(input); |
| 425 case BasicBlockData::kCall: { | 425 case BasicBlockData::kCall: { |
| 426 BasicBlock* deoptimization = block->SuccessorAt(0); | 426 BasicBlock* deoptimization = block->SuccessorAt(0); |
| 427 BasicBlock* continuation = block->SuccessorAt(1); | 427 BasicBlock* continuation = block->SuccessorAt(1); |
| 428 VisitCall(input, continuation, deoptimization); | 428 VisitCall(input, continuation, deoptimization); |
| 429 break; | 429 break; |
| 430 } | 430 } |
| 431 case BasicBlockData::kNone: { | 431 case BasicBlockData::kNone: { |
| 432 // TODO(titzer): exit block doesn't have control. | 432 // TODO(titzer): exit block doesn't have control. |
| 433 ASSERT(input == NULL); | 433 DCHECK(input == NULL); |
| 434 break; | 434 break; |
| 435 } | 435 } |
| 436 default: | 436 default: |
| 437 UNREACHABLE(); | 437 UNREACHABLE(); |
| 438 break; | 438 break; |
| 439 } | 439 } |
| 440 } | 440 } |
| 441 | 441 |
| 442 | 442 |
| 443 void InstructionSelector::VisitNode(Node* node) { | 443 void InstructionSelector::VisitNode(Node* node) { |
| 444 ASSERT_NOT_NULL(schedule()->block(node)); // should only use scheduled nodes. | 444 DCHECK_NOT_NULL(schedule()->block(node)); // should only use scheduled nodes. |
| 445 SourcePosition source_position = source_positions_->GetSourcePosition(node); | 445 SourcePosition source_position = source_positions_->GetSourcePosition(node); |
| 446 if (!source_position.IsUnknown()) { | 446 if (!source_position.IsUnknown()) { |
| 447 ASSERT(!source_position.IsInvalid()); | 447 DCHECK(!source_position.IsInvalid()); |
| 448 if (FLAG_turbo_source_positions || node->opcode() == IrOpcode::kCall) { | 448 if (FLAG_turbo_source_positions || node->opcode() == IrOpcode::kCall) { |
| 449 Emit(SourcePositionInstruction::New(instruction_zone(), source_position)); | 449 Emit(SourcePositionInstruction::New(instruction_zone(), source_position)); |
| 450 } | 450 } |
| 451 } | 451 } |
| 452 switch (node->opcode()) { | 452 switch (node->opcode()) { |
| 453 case IrOpcode::kStart: | 453 case IrOpcode::kStart: |
| 454 case IrOpcode::kLoop: | 454 case IrOpcode::kLoop: |
| 455 case IrOpcode::kEnd: | 455 case IrOpcode::kEnd: |
| 456 case IrOpcode::kBranch: | 456 case IrOpcode::kBranch: |
| 457 case IrOpcode::kIfTrue: | 457 case IrOpcode::kIfTrue: |
| (...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 789 | 789 |
| 790 void InstructionSelector::VisitProjection(Node* node) { | 790 void InstructionSelector::VisitProjection(Node* node) { |
| 791 OperandGenerator g(this); | 791 OperandGenerator g(this); |
| 792 Node* value = node->InputAt(0); | 792 Node* value = node->InputAt(0); |
| 793 switch (value->opcode()) { | 793 switch (value->opcode()) { |
| 794 case IrOpcode::kInt32AddWithOverflow: | 794 case IrOpcode::kInt32AddWithOverflow: |
| 795 case IrOpcode::kInt32SubWithOverflow: | 795 case IrOpcode::kInt32SubWithOverflow: |
| 796 if (OpParameter<int32_t>(node) == 0) { | 796 if (OpParameter<int32_t>(node) == 0) { |
| 797 Emit(kArchNop, g.DefineSameAsFirst(node), g.Use(value)); | 797 Emit(kArchNop, g.DefineSameAsFirst(node), g.Use(value)); |
| 798 } else { | 798 } else { |
| 799 ASSERT_EQ(1, OpParameter<int32_t>(node)); | 799 DCHECK_EQ(1, OpParameter<int32_t>(node)); |
| 800 MarkAsUsed(value); | 800 MarkAsUsed(value); |
| 801 } | 801 } |
| 802 break; | 802 break; |
| 803 default: | 803 default: |
| 804 break; | 804 break; |
| 805 } | 805 } |
| 806 } | 806 } |
| 807 | 807 |
| 808 | 808 |
| 809 void InstructionSelector::VisitConstant(Node* node) { | 809 void InstructionSelector::VisitConstant(Node* node) { |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 945 } | 945 } |
| 946 } | 946 } |
| 947 | 947 |
| 948 | 948 |
| 949 void InstructionSelector::VisitThrow(Node* value) { | 949 void InstructionSelector::VisitThrow(Node* value) { |
| 950 UNIMPLEMENTED(); // TODO(titzer) | 950 UNIMPLEMENTED(); // TODO(titzer) |
| 951 } | 951 } |
| 952 | 952 |
| 953 | 953 |
| 954 void InstructionSelector::VisitDeoptimization(Node* deopt) { | 954 void InstructionSelector::VisitDeoptimization(Node* deopt) { |
| 955 ASSERT(deopt->op()->opcode() == IrOpcode::kDeoptimize); | 955 DCHECK(deopt->op()->opcode() == IrOpcode::kDeoptimize); |
| 956 Node* state = deopt->InputAt(0); | 956 Node* state = deopt->InputAt(0); |
| 957 ASSERT(state->op()->opcode() == IrOpcode::kFrameState); | 957 DCHECK(state->op()->opcode() == IrOpcode::kFrameState); |
| 958 FrameStateDescriptor descriptor = OpParameter<FrameStateDescriptor>(state); | 958 FrameStateDescriptor descriptor = OpParameter<FrameStateDescriptor>(state); |
| 959 // TODO(jarin) We should also add an instruction input for every input to | 959 // TODO(jarin) We should also add an instruction input for every input to |
| 960 // the framestate node (and recurse for the inlined framestates). | 960 // the framestate node (and recurse for the inlined framestates). |
| 961 int deoptimization_id = sequence()->AddDeoptimizationEntry(descriptor); | 961 int deoptimization_id = sequence()->AddDeoptimizationEntry(descriptor); |
| 962 Emit(kArchDeoptimize | MiscField::encode(deoptimization_id), NULL); | 962 Emit(kArchDeoptimize | MiscField::encode(deoptimization_id), NULL); |
| 963 } | 963 } |
| 964 | 964 |
| 965 | 965 |
| 966 #if !V8_TURBOFAN_TARGET | 966 #if !V8_TURBOFAN_TARGET |
| 967 | 967 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1001 | 1001 |
| 1002 | 1002 |
| 1003 void InstructionSelector::VisitCall(Node* call, BasicBlock* continuation, | 1003 void InstructionSelector::VisitCall(Node* call, BasicBlock* continuation, |
| 1004 BasicBlock* deoptimization) {} | 1004 BasicBlock* deoptimization) {} |
| 1005 | 1005 |
| 1006 #endif // !V8_TURBOFAN_TARGET | 1006 #endif // !V8_TURBOFAN_TARGET |
| 1007 | 1007 |
| 1008 } // namespace compiler | 1008 } // namespace compiler |
| 1009 } // namespace internal | 1009 } // namespace internal |
| 1010 } // namespace v8 | 1010 } // namespace v8 |
| OLD | NEW |