| 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 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 253 GetFrameStateDescriptor(instr, frame_state_offset); | 253 GetFrameStateDescriptor(instr, frame_state_offset); |
| 254 int pc_offset = masm()->pc_offset(); | 254 int pc_offset = masm()->pc_offset(); |
| 255 int deopt_state_id = BuildTranslation(instr, pc_offset, frame_state_offset, | 255 int deopt_state_id = BuildTranslation(instr, pc_offset, frame_state_offset, |
| 256 descriptor->state_combine()); | 256 descriptor->state_combine()); |
| 257 // If the pre-call frame state differs from the post-call one, produce the | 257 // If the pre-call frame state differs from the post-call one, produce the |
| 258 // pre-call frame state, too. | 258 // pre-call frame state, too. |
| 259 // TODO(jarin) We might want to avoid building the pre-call frame state | 259 // TODO(jarin) We might want to avoid building the pre-call frame state |
| 260 // because it is only used to get locals and arguments (by the debugger and | 260 // because it is only used to get locals and arguments (by the debugger and |
| 261 // f.arguments), and those are the same in the pre-call and post-call | 261 // f.arguments), and those are the same in the pre-call and post-call |
| 262 // states. | 262 // states. |
| 263 if (descriptor->state_combine() != kIgnoreOutput) { | 263 if (!descriptor->state_combine().IsOutputIgnored()) { |
| 264 deopt_state_id = | 264 deopt_state_id = BuildTranslation(instr, -1, frame_state_offset, |
| 265 BuildTranslation(instr, -1, frame_state_offset, kIgnoreOutput); | 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->size(); 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->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( |
| 300 FrameStateDescriptor* descriptor, Instruction* instr, |
| 301 size_t frame_state_offset, size_t index, OutputFrameStateCombine combine) { |
| 302 DCHECK(index < descriptor->GetSize(combine)); |
| 303 switch (combine.kind()) { |
| 304 case OutputFrameStateCombine::kPushOutput: { |
| 305 DCHECK(combine.GetPushCount() <= instr->OutputCount()); |
| 306 size_t size_without_output = |
| 307 descriptor->GetSize(OutputFrameStateCombine::Ignore()); |
| 308 // If the index is past the existing stack items, return the output. |
| 309 if (index >= size_without_output) { |
| 310 return instr->OutputAt(index - size_without_output); |
| 311 } |
| 312 break; |
| 313 } |
| 314 case OutputFrameStateCombine::kPokeAt: |
| 315 size_t index_from_top = |
| 316 descriptor->GetSize(combine) - 1 - combine.GetOffsetToPokeAt(); |
| 317 if (index >= index_from_top && |
| 318 index < index_from_top + instr->OutputCount()) { |
| 319 return instr->OutputAt(index - index_from_top); |
| 320 } |
| 321 break; |
| 322 } |
| 323 return instr->InputAt(frame_state_offset + index); |
| 324 } |
| 325 |
| 299 | 326 |
| 300 void CodeGenerator::BuildTranslationForFrameStateDescriptor( | 327 void CodeGenerator::BuildTranslationForFrameStateDescriptor( |
| 301 FrameStateDescriptor* descriptor, Instruction* instr, | 328 FrameStateDescriptor* descriptor, Instruction* instr, |
| 302 Translation* translation, size_t frame_state_offset, | 329 Translation* translation, size_t frame_state_offset, |
| 303 OutputFrameStateCombine state_combine) { | 330 OutputFrameStateCombine state_combine) { |
| 304 // Outer-most state must be added to translation first. | 331 // Outer-most state must be added to translation first. |
| 305 if (descriptor->outer_state() != NULL) { | 332 if (descriptor->outer_state() != NULL) { |
| 306 BuildTranslationForFrameStateDescriptor(descriptor->outer_state(), instr, | 333 BuildTranslationForFrameStateDescriptor(descriptor->outer_state(), instr, |
| 307 translation, frame_state_offset, | 334 translation, frame_state_offset, |
| 308 kIgnoreOutput); | 335 OutputFrameStateCombine::Ignore()); |
| 309 } | 336 } |
| 310 | 337 |
| 311 int id = Translation::kSelfLiteralId; | 338 int id = Translation::kSelfLiteralId; |
| 312 if (!descriptor->jsfunction().is_null()) { | 339 if (!descriptor->jsfunction().is_null()) { |
| 313 id = DefineDeoptimizationLiteral( | 340 id = DefineDeoptimizationLiteral( |
| 314 Handle<Object>::cast(descriptor->jsfunction().ToHandleChecked())); | 341 Handle<Object>::cast(descriptor->jsfunction().ToHandleChecked())); |
| 315 } | 342 } |
| 316 | 343 |
| 317 switch (descriptor->type()) { | 344 switch (descriptor->type()) { |
| 318 case JS_FRAME: | 345 case JS_FRAME: |
| 319 translation->BeginJSFrame( | 346 translation->BeginJSFrame( |
| 320 descriptor->bailout_id(), id, | 347 descriptor->bailout_id(), id, |
| 321 static_cast<unsigned int>(descriptor->GetHeight(state_combine))); | 348 static_cast<unsigned int>(descriptor->GetSize(state_combine) - |
| 349 descriptor->parameters_count())); |
| 322 break; | 350 break; |
| 323 case ARGUMENTS_ADAPTOR: | 351 case ARGUMENTS_ADAPTOR: |
| 324 translation->BeginArgumentsAdaptorFrame( | 352 translation->BeginArgumentsAdaptorFrame( |
| 325 id, static_cast<unsigned int>(descriptor->parameters_count())); | 353 id, static_cast<unsigned int>(descriptor->parameters_count())); |
| 326 break; | 354 break; |
| 327 } | 355 } |
| 328 | 356 |
| 329 frame_state_offset += descriptor->outer_state()->GetTotalSize(); | 357 frame_state_offset += descriptor->outer_state()->GetTotalSize(); |
| 330 for (size_t i = 0; i < descriptor->size(); i++) { | 358 for (size_t i = 0; i < descriptor->GetSize(state_combine); i++) { |
| 331 AddTranslationForOperand( | 359 InstructionOperand* op = OperandForFrameState( |
| 332 translation, instr, | 360 descriptor, instr, frame_state_offset, i, state_combine); |
| 333 instr->InputAt(static_cast<int>(frame_state_offset + i))); | 361 AddTranslationForOperand(translation, instr, op); |
| 334 } | |
| 335 | |
| 336 switch (state_combine) { | |
| 337 case kPushOutput: | |
| 338 DCHECK(instr->OutputCount() == 1); | |
| 339 AddTranslationForOperand(translation, instr, instr->OutputAt(0)); | |
| 340 break; | |
| 341 case kIgnoreOutput: | |
| 342 break; | |
| 343 } | 362 } |
| 344 } | 363 } |
| 345 | 364 |
| 346 | 365 |
| 347 int CodeGenerator::BuildTranslation(Instruction* instr, int pc_offset, | 366 int CodeGenerator::BuildTranslation(Instruction* instr, int pc_offset, |
| 348 size_t frame_state_offset, | 367 size_t frame_state_offset, |
| 349 OutputFrameStateCombine state_combine) { | 368 OutputFrameStateCombine state_combine) { |
| 350 FrameStateDescriptor* descriptor = | 369 FrameStateDescriptor* descriptor = |
| 351 GetFrameStateDescriptor(instr, frame_state_offset); | 370 GetFrameStateDescriptor(instr, frame_state_offset); |
| 352 frame_state_offset++; | 371 frame_state_offset++; |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 451 } | 470 } |
| 452 | 471 |
| 453 | 472 |
| 454 void CodeGenerator::AddNopForSmiCodeInlining() { UNIMPLEMENTED(); } | 473 void CodeGenerator::AddNopForSmiCodeInlining() { UNIMPLEMENTED(); } |
| 455 | 474 |
| 456 #endif // !V8_TURBOFAN_BACKEND | 475 #endif // !V8_TURBOFAN_BACKEND |
| 457 | 476 |
| 458 } // namespace compiler | 477 } // namespace compiler |
| 459 } // namespace internal | 478 } // namespace internal |
| 460 } // namespace v8 | 479 } // namespace v8 |
| OLD | NEW |