| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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/code-generator.h" | 5 #include "src/compiler/code-generator.h" |
| 6 | 6 |
| 7 #include "src/compiler/code-generator-impl.h" | 7 #include "src/compiler/code-generator-impl.h" |
| 8 #include "src/compiler/linkage.h" | 8 #include "src/compiler/linkage.h" |
| 9 #include "src/compiler/pipeline.h" | 9 #include "src/compiler/pipeline.h" |
| 10 | 10 |
| (...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 263 if (!descriptor->state_combine().IsOutputIgnored()) { | 263 if (!descriptor->state_combine().IsOutputIgnored()) { |
| 264 deopt_state_id = BuildTranslation(instr, -1, frame_state_offset, | 264 deopt_state_id = BuildTranslation(instr, -1, frame_state_offset, |
| 265 OutputFrameStateCombine::Ignore()); | 265 OutputFrameStateCombine::Ignore()); |
| 266 } | 266 } |
| 267 #if DEBUG | 267 #if DEBUG |
| 268 // Make sure all the values live in stack slots or they are immediates. | 268 // Make sure all the values live in stack slots or they are immediates. |
| 269 // (The values should not live in register because registers are clobbered | 269 // (The values should not live in register because registers are clobbered |
| 270 // by calls.) | 270 // by calls.) |
| 271 for (size_t i = 0; i < descriptor->GetSize(); i++) { | 271 for (size_t i = 0; i < descriptor->GetSize(); i++) { |
| 272 InstructionOperand* op = instr->InputAt(frame_state_offset + 1 + i); | 272 InstructionOperand* op = instr->InputAt(frame_state_offset + 1 + i); |
| 273 CHECK(op->IsStackSlot() || op->IsImmediate()); | 273 CHECK(op->IsStackSlot() || op->IsDoubleStackSlot() || op->IsImmediate()); |
| 274 } | 274 } |
| 275 #endif | 275 #endif |
| 276 safepoints()->RecordLazyDeoptimizationIndex(deopt_state_id); | 276 safepoints()->RecordLazyDeoptimizationIndex(deopt_state_id); |
| 277 } | 277 } |
| 278 } | 278 } |
| 279 | 279 |
| 280 | 280 |
| 281 int CodeGenerator::DefineDeoptimizationLiteral(Handle<Object> literal) { | 281 int CodeGenerator::DefineDeoptimizationLiteral(Handle<Object> literal) { |
| 282 int result = static_cast<int>(deoptimization_literals_.size()); | 282 int result = static_cast<int>(deoptimization_literals_.size()); |
| 283 for (unsigned i = 0; i < deoptimization_literals_.size(); ++i) { | 283 for (unsigned i = 0; i < deoptimization_literals_.size(); ++i) { |
| 284 if (deoptimization_literals_[i].is_identical_to(literal)) return i; | 284 if (deoptimization_literals_[i].is_identical_to(literal)) return i; |
| 285 } | 285 } |
| 286 deoptimization_literals_.push_back(literal); | 286 deoptimization_literals_.push_back(literal); |
| 287 return result; | 287 return result; |
| 288 } | 288 } |
| 289 | 289 |
| 290 | 290 |
| 291 FrameStateDescriptor* CodeGenerator::GetFrameStateDescriptor( | 291 FrameStateDescriptor* CodeGenerator::GetFrameStateDescriptor( |
| 292 Instruction* instr, size_t frame_state_offset) { | 292 Instruction* instr, size_t frame_state_offset) { |
| 293 InstructionOperandConverter i(this, instr); | 293 InstructionOperandConverter i(this, instr); |
| 294 InstructionSequence::StateId state_id = InstructionSequence::StateId::FromInt( | 294 InstructionSequence::StateId state_id = InstructionSequence::StateId::FromInt( |
| 295 i.InputInt32(static_cast<int>(frame_state_offset))); | 295 i.InputInt32(static_cast<int>(frame_state_offset))); |
| 296 return code()->GetFrameStateDescriptor(state_id); | 296 return code()->GetFrameStateDescriptor(state_id); |
| 297 } | 297 } |
| 298 | 298 |
| 299 static InstructionOperand* OperandForFrameState( | 299 struct OperandAndType { |
| 300 OperandAndType(InstructionOperand* operand, MachineType type) |
| 301 : operand_(operand), type_(type) {} |
| 302 |
| 303 InstructionOperand* operand_; |
| 304 MachineType type_; |
| 305 }; |
| 306 |
| 307 static OperandAndType TypedOperandForFrameState( |
| 300 FrameStateDescriptor* descriptor, Instruction* instr, | 308 FrameStateDescriptor* descriptor, Instruction* instr, |
| 301 size_t frame_state_offset, size_t index, OutputFrameStateCombine combine) { | 309 size_t frame_state_offset, size_t index, OutputFrameStateCombine combine) { |
| 302 DCHECK(index < descriptor->GetSize(combine)); | 310 DCHECK(index < descriptor->GetSize(combine)); |
| 303 switch (combine.kind()) { | 311 switch (combine.kind()) { |
| 304 case OutputFrameStateCombine::kPushOutput: { | 312 case OutputFrameStateCombine::kPushOutput: { |
| 305 DCHECK(combine.GetPushCount() <= instr->OutputCount()); | 313 DCHECK(combine.GetPushCount() <= instr->OutputCount()); |
| 306 size_t size_without_output = | 314 size_t size_without_output = |
| 307 descriptor->GetSize(OutputFrameStateCombine::Ignore()); | 315 descriptor->GetSize(OutputFrameStateCombine::Ignore()); |
| 308 // If the index is past the existing stack items, return the output. | 316 // If the index is past the existing stack items, return the output. |
| 309 if (index >= size_without_output) { | 317 if (index >= size_without_output) { |
| 310 return instr->OutputAt(index - size_without_output); | 318 return OperandAndType(instr->OutputAt(index - size_without_output), |
| 319 kMachAnyTagged); |
| 311 } | 320 } |
| 312 break; | 321 break; |
| 313 } | 322 } |
| 314 case OutputFrameStateCombine::kPokeAt: | 323 case OutputFrameStateCombine::kPokeAt: |
| 315 size_t index_from_top = | 324 size_t index_from_top = |
| 316 descriptor->GetSize(combine) - 1 - combine.GetOffsetToPokeAt(); | 325 descriptor->GetSize(combine) - 1 - combine.GetOffsetToPokeAt(); |
| 317 if (index >= index_from_top && | 326 if (index >= index_from_top && |
| 318 index < index_from_top + instr->OutputCount()) { | 327 index < index_from_top + instr->OutputCount()) { |
| 319 return instr->OutputAt(index - index_from_top); | 328 return OperandAndType(instr->OutputAt(index - index_from_top), |
| 329 kMachAnyTagged); |
| 320 } | 330 } |
| 321 break; | 331 break; |
| 322 } | 332 } |
| 323 return instr->InputAt(frame_state_offset + index); | 333 return OperandAndType(instr->InputAt(frame_state_offset + index), |
| 334 descriptor->GetType(index)); |
| 324 } | 335 } |
| 325 | 336 |
| 326 | 337 |
| 327 void CodeGenerator::BuildTranslationForFrameStateDescriptor( | 338 void CodeGenerator::BuildTranslationForFrameStateDescriptor( |
| 328 FrameStateDescriptor* descriptor, Instruction* instr, | 339 FrameStateDescriptor* descriptor, Instruction* instr, |
| 329 Translation* translation, size_t frame_state_offset, | 340 Translation* translation, size_t frame_state_offset, |
| 330 OutputFrameStateCombine state_combine) { | 341 OutputFrameStateCombine state_combine) { |
| 331 // Outer-most state must be added to translation first. | 342 // Outer-most state must be added to translation first. |
| 332 if (descriptor->outer_state() != NULL) { | 343 if (descriptor->outer_state() != NULL) { |
| 333 BuildTranslationForFrameStateDescriptor(descriptor->outer_state(), instr, | 344 BuildTranslationForFrameStateDescriptor(descriptor->outer_state(), instr, |
| (...skipping 15 matching lines...) Expand all Loading... |
| 349 descriptor->parameters_count())); | 360 descriptor->parameters_count())); |
| 350 break; | 361 break; |
| 351 case ARGUMENTS_ADAPTOR: | 362 case ARGUMENTS_ADAPTOR: |
| 352 translation->BeginArgumentsAdaptorFrame( | 363 translation->BeginArgumentsAdaptorFrame( |
| 353 id, static_cast<unsigned int>(descriptor->parameters_count())); | 364 id, static_cast<unsigned int>(descriptor->parameters_count())); |
| 354 break; | 365 break; |
| 355 } | 366 } |
| 356 | 367 |
| 357 frame_state_offset += descriptor->outer_state()->GetTotalSize(); | 368 frame_state_offset += descriptor->outer_state()->GetTotalSize(); |
| 358 for (size_t i = 0; i < descriptor->GetSize(state_combine); i++) { | 369 for (size_t i = 0; i < descriptor->GetSize(state_combine); i++) { |
| 359 InstructionOperand* op = OperandForFrameState( | 370 OperandAndType op = TypedOperandForFrameState( |
| 360 descriptor, instr, frame_state_offset, i, state_combine); | 371 descriptor, instr, frame_state_offset, i, state_combine); |
| 361 AddTranslationForOperand(translation, instr, op); | 372 AddTranslationForOperand(translation, instr, op.operand_, op.type_); |
| 362 } | 373 } |
| 363 } | 374 } |
| 364 | 375 |
| 365 | 376 |
| 366 int CodeGenerator::BuildTranslation(Instruction* instr, int pc_offset, | 377 int CodeGenerator::BuildTranslation(Instruction* instr, int pc_offset, |
| 367 size_t frame_state_offset, | 378 size_t frame_state_offset, |
| 368 OutputFrameStateCombine state_combine) { | 379 OutputFrameStateCombine state_combine) { |
| 369 FrameStateDescriptor* descriptor = | 380 FrameStateDescriptor* descriptor = |
| 370 GetFrameStateDescriptor(instr, frame_state_offset); | 381 GetFrameStateDescriptor(instr, frame_state_offset); |
| 371 frame_state_offset++; | 382 frame_state_offset++; |
| 372 | 383 |
| 373 Translation translation( | 384 Translation translation( |
| 374 &translations_, static_cast<int>(descriptor->GetFrameCount()), | 385 &translations_, static_cast<int>(descriptor->GetFrameCount()), |
| 375 static_cast<int>(descriptor->GetJSFrameCount()), zone()); | 386 static_cast<int>(descriptor->GetJSFrameCount()), zone()); |
| 376 BuildTranslationForFrameStateDescriptor(descriptor, instr, &translation, | 387 BuildTranslationForFrameStateDescriptor(descriptor, instr, &translation, |
| 377 frame_state_offset, state_combine); | 388 frame_state_offset, state_combine); |
| 378 | 389 |
| 379 int deoptimization_id = static_cast<int>(deoptimization_states_.size()); | 390 int deoptimization_id = static_cast<int>(deoptimization_states_.size()); |
| 380 | 391 |
| 381 deoptimization_states_.push_back(new (zone()) DeoptimizationState( | 392 deoptimization_states_.push_back(new (zone()) DeoptimizationState( |
| 382 descriptor->bailout_id(), translation.index(), pc_offset)); | 393 descriptor->bailout_id(), translation.index(), pc_offset)); |
| 383 | 394 |
| 384 return deoptimization_id; | 395 return deoptimization_id; |
| 385 } | 396 } |
| 386 | 397 |
| 387 | 398 |
| 388 void CodeGenerator::AddTranslationForOperand(Translation* translation, | 399 void CodeGenerator::AddTranslationForOperand(Translation* translation, |
| 389 Instruction* instr, | 400 Instruction* instr, |
| 390 InstructionOperand* op) { | 401 InstructionOperand* op, |
| 402 MachineType type) { |
| 391 if (op->IsStackSlot()) { | 403 if (op->IsStackSlot()) { |
| 392 translation->StoreStackSlot(op->index()); | 404 if (type == kMachBool || type == kMachInt32 || type == kMachInt8 || |
| 405 type == kMachInt16) { |
| 406 translation->StoreInt32StackSlot(op->index()); |
| 407 } else if (type == kMachUint32) { |
| 408 translation->StoreUint32StackSlot(op->index()); |
| 409 } else if ((type & kRepMask) == kRepTagged) { |
| 410 translation->StoreStackSlot(op->index()); |
| 411 } else { |
| 412 CHECK(false); |
| 413 } |
| 393 } else if (op->IsDoubleStackSlot()) { | 414 } else if (op->IsDoubleStackSlot()) { |
| 415 DCHECK((type & (kRepFloat32 | kRepFloat64)) != 0); |
| 394 translation->StoreDoubleStackSlot(op->index()); | 416 translation->StoreDoubleStackSlot(op->index()); |
| 395 } else if (op->IsRegister()) { | 417 } else if (op->IsRegister()) { |
| 396 InstructionOperandConverter converter(this, instr); | 418 InstructionOperandConverter converter(this, instr); |
| 397 translation->StoreRegister(converter.ToRegister(op)); | 419 if (type == kMachBool || type == kMachInt32 || type == kMachInt8 || |
| 420 type == kMachInt16) { |
| 421 translation->StoreInt32Register(converter.ToRegister(op)); |
| 422 } else if (type == kMachUint32) { |
| 423 translation->StoreUint32Register(converter.ToRegister(op)); |
| 424 } else if ((type & kRepMask) == kRepTagged) { |
| 425 translation->StoreRegister(converter.ToRegister(op)); |
| 426 } else { |
| 427 CHECK(false); |
| 428 } |
| 398 } else if (op->IsDoubleRegister()) { | 429 } else if (op->IsDoubleRegister()) { |
| 430 DCHECK((type & (kRepFloat32 | kRepFloat64)) != 0); |
| 399 InstructionOperandConverter converter(this, instr); | 431 InstructionOperandConverter converter(this, instr); |
| 400 translation->StoreDoubleRegister(converter.ToDoubleRegister(op)); | 432 translation->StoreDoubleRegister(converter.ToDoubleRegister(op)); |
| 401 } else if (op->IsImmediate()) { | 433 } else if (op->IsImmediate()) { |
| 402 InstructionOperandConverter converter(this, instr); | 434 InstructionOperandConverter converter(this, instr); |
| 403 Constant constant = converter.ToConstant(op); | 435 Constant constant = converter.ToConstant(op); |
| 404 Handle<Object> constant_object; | 436 Handle<Object> constant_object; |
| 405 switch (constant.type()) { | 437 switch (constant.type()) { |
| 406 case Constant::kInt32: | 438 case Constant::kInt32: |
| 439 DCHECK(type == kMachInt32 || type == kMachUint32); |
| 407 constant_object = | 440 constant_object = |
| 408 isolate()->factory()->NewNumberFromInt(constant.ToInt32()); | 441 isolate()->factory()->NewNumberFromInt(constant.ToInt32()); |
| 409 break; | 442 break; |
| 410 case Constant::kFloat64: | 443 case Constant::kFloat64: |
| 444 DCHECK(type == kMachFloat64 || type == kMachAnyTagged); |
| 411 constant_object = isolate()->factory()->NewNumber(constant.ToFloat64()); | 445 constant_object = isolate()->factory()->NewNumber(constant.ToFloat64()); |
| 412 break; | 446 break; |
| 413 case Constant::kHeapObject: | 447 case Constant::kHeapObject: |
| 448 DCHECK((type & kRepMask) == kRepTagged); |
| 414 constant_object = constant.ToHeapObject(); | 449 constant_object = constant.ToHeapObject(); |
| 415 break; | 450 break; |
| 416 default: | 451 default: |
| 417 UNREACHABLE(); | 452 CHECK(false); |
| 418 } | 453 } |
| 419 int literal_id = DefineDeoptimizationLiteral(constant_object); | 454 int literal_id = DefineDeoptimizationLiteral(constant_object); |
| 420 translation->StoreLiteral(literal_id); | 455 translation->StoreLiteral(literal_id); |
| 421 } else { | 456 } else { |
| 422 UNREACHABLE(); | 457 CHECK(false); |
| 423 } | 458 } |
| 424 } | 459 } |
| 425 | 460 |
| 426 | 461 |
| 427 void CodeGenerator::MarkLazyDeoptSite() { | 462 void CodeGenerator::MarkLazyDeoptSite() { |
| 428 last_lazy_deopt_pc_ = masm()->pc_offset(); | 463 last_lazy_deopt_pc_ = masm()->pc_offset(); |
| 429 } | 464 } |
| 430 | 465 |
| 431 #if !V8_TURBOFAN_BACKEND | 466 #if !V8_TURBOFAN_BACKEND |
| 432 | 467 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 470 } | 505 } |
| 471 | 506 |
| 472 | 507 |
| 473 void CodeGenerator::AddNopForSmiCodeInlining() { UNIMPLEMENTED(); } | 508 void CodeGenerator::AddNopForSmiCodeInlining() { UNIMPLEMENTED(); } |
| 474 | 509 |
| 475 #endif // !V8_TURBOFAN_BACKEND | 510 #endif // !V8_TURBOFAN_BACKEND |
| 476 | 511 |
| 477 } // namespace compiler | 512 } // namespace compiler |
| 478 } // namespace internal | 513 } // namespace internal |
| 479 } // namespace v8 | 514 } // namespace v8 |
| OLD | NEW |