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 |