| 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/code-generator.h" | 5 #include "src/compiler/code-generator.h" |
| 6 #include "src/compiler/code-generator-impl.h" | 6 #include "src/compiler/code-generator-impl.h" |
| 7 #include "src/compiler/gap-resolver.h" | 7 #include "src/compiler/gap-resolver.h" |
| 8 #include "src/compiler/node-matchers.h" | 8 #include "src/compiler/node-matchers.h" |
| 9 #include "src/compiler/osr.h" | 9 #include "src/compiler/osr.h" |
| 10 #include "src/mips/macro-assembler-mips.h" | 10 #include "src/mips/macro-assembler-mips.h" |
| (...skipping 428 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 439 __ mov_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); \ | 439 __ mov_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); \ |
| 440 __ asm_instr(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); \ | 440 __ asm_instr(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); \ |
| 441 __ dmfc1(at, i.OutputDoubleRegister()); \ | 441 __ dmfc1(at, i.OutputDoubleRegister()); \ |
| 442 __ Branch(USE_DELAY_SLOT, ool->entry(), eq, at, Operand(zero_reg)); \ | 442 __ Branch(USE_DELAY_SLOT, ool->entry(), eq, at, Operand(zero_reg)); \ |
| 443 __ cvt_d_l(i.OutputDoubleRegister(), i.OutputDoubleRegister()); \ | 443 __ cvt_d_l(i.OutputDoubleRegister(), i.OutputDoubleRegister()); \ |
| 444 __ bind(ool->exit()); \ | 444 __ bind(ool->exit()); \ |
| 445 __ bind(&done); \ | 445 __ bind(&done); \ |
| 446 } while (0) | 446 } while (0) |
| 447 | 447 |
| 448 | 448 |
| 449 void CodeGenerator::AssembleDeconstructActivationRecord() { | 449 void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) { |
| 450 CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); | 450 CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); |
| 451 int stack_slots = frame()->GetSpillSlotCount(); | 451 int stack_slots = frame()->GetSpillSlotCount(); |
| 452 int stack_pointer_delta = 0; |
| 452 if (descriptor->IsJSFunctionCall() || stack_slots > 0) { | 453 if (descriptor->IsJSFunctionCall() || stack_slots > 0) { |
| 453 __ LeaveFrame(StackFrame::MANUAL); | 454 __ mov(sp, fp); |
| 455 __ ld(fp, MemOperand(sp, 0 * kPointerSize)); |
| 456 __ ld(ra, MemOperand(sp, 1 * kPointerSize)); |
| 457 stack_pointer_delta = 2 * kPointerSize; |
| 458 } |
| 459 if (stack_param_delta < 0) { |
| 460 stack_pointer_delta += -stack_param_delta * kPointerSize; |
| 461 } |
| 462 if (stack_pointer_delta != 0) { |
| 463 __ daddiu(sp, sp, stack_pointer_delta); |
| 454 } | 464 } |
| 455 } | 465 } |
| 456 | 466 |
| 457 | 467 |
| 458 // Assembles an instruction after register allocation, producing machine code. | 468 // Assembles an instruction after register allocation, producing machine code. |
| 459 void CodeGenerator::AssembleArchInstruction(Instruction* instr) { | 469 void CodeGenerator::AssembleArchInstruction(Instruction* instr) { |
| 460 MipsOperandConverter i(this, instr); | 470 MipsOperandConverter i(this, instr); |
| 461 InstructionCode opcode = instr->opcode(); | 471 InstructionCode opcode = instr->opcode(); |
| 462 | 472 |
| 463 switch (ArchOpcodeField::decode(opcode)) { | 473 switch (ArchOpcodeField::decode(opcode)) { |
| 464 case kArchCallCodeObject: { | 474 case kArchCallCodeObject: { |
| 465 EnsureSpaceForLazyDeopt(); | 475 EnsureSpaceForLazyDeopt(); |
| 466 if (instr->InputAt(0)->IsImmediate()) { | 476 if (instr->InputAt(0)->IsImmediate()) { |
| 467 __ Call(Handle<Code>::cast(i.InputHeapObject(0)), | 477 __ Call(Handle<Code>::cast(i.InputHeapObject(0)), |
| 468 RelocInfo::CODE_TARGET); | 478 RelocInfo::CODE_TARGET); |
| 469 } else { | 479 } else { |
| 470 __ daddiu(at, i.InputRegister(0), Code::kHeaderSize - kHeapObjectTag); | 480 __ daddiu(at, i.InputRegister(0), Code::kHeaderSize - kHeapObjectTag); |
| 471 __ Call(at); | 481 __ Call(at); |
| 472 } | 482 } |
| 473 RecordCallPosition(instr); | 483 RecordCallPosition(instr); |
| 474 break; | 484 break; |
| 475 } | 485 } |
| 476 case kArchTailCallCodeObject: { | 486 case kArchTailCallCodeObject: { |
| 477 AssembleDeconstructActivationRecord(); | 487 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); |
| 488 AssembleDeconstructActivationRecord(stack_param_delta); |
| 478 if (instr->InputAt(0)->IsImmediate()) { | 489 if (instr->InputAt(0)->IsImmediate()) { |
| 479 __ Jump(Handle<Code>::cast(i.InputHeapObject(0)), | 490 __ Jump(Handle<Code>::cast(i.InputHeapObject(0)), |
| 480 RelocInfo::CODE_TARGET); | 491 RelocInfo::CODE_TARGET); |
| 481 } else { | 492 } else { |
| 482 __ daddiu(at, i.InputRegister(0), Code::kHeaderSize - kHeapObjectTag); | 493 __ daddiu(at, i.InputRegister(0), Code::kHeaderSize - kHeapObjectTag); |
| 483 __ Jump(at); | 494 __ Jump(at); |
| 484 } | 495 } |
| 485 break; | 496 break; |
| 486 } | 497 } |
| 487 case kArchCallJSFunction: { | 498 case kArchCallJSFunction: { |
| 488 EnsureSpaceForLazyDeopt(); | 499 EnsureSpaceForLazyDeopt(); |
| 489 Register func = i.InputRegister(0); | 500 Register func = i.InputRegister(0); |
| 490 if (FLAG_debug_code) { | 501 if (FLAG_debug_code) { |
| 491 // Check the function's context matches the context argument. | 502 // Check the function's context matches the context argument. |
| 492 __ ld(kScratchReg, FieldMemOperand(func, JSFunction::kContextOffset)); | 503 __ ld(kScratchReg, FieldMemOperand(func, JSFunction::kContextOffset)); |
| 493 __ Assert(eq, kWrongFunctionContext, cp, Operand(kScratchReg)); | 504 __ Assert(eq, kWrongFunctionContext, cp, Operand(kScratchReg)); |
| 494 } | 505 } |
| 495 __ ld(at, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); | 506 __ ld(at, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); |
| 496 __ Call(at); | 507 __ Call(at); |
| 497 RecordCallPosition(instr); | 508 RecordCallPosition(instr); |
| 498 break; | 509 break; |
| 499 } | 510 } |
| 500 case kArchTailCallJSFunction: { | 511 case kArchTailCallJSFunction: { |
| 501 Register func = i.InputRegister(0); | 512 Register func = i.InputRegister(0); |
| 502 if (FLAG_debug_code) { | 513 if (FLAG_debug_code) { |
| 503 // Check the function's context matches the context argument. | 514 // Check the function's context matches the context argument. |
| 504 __ ld(kScratchReg, FieldMemOperand(func, JSFunction::kContextOffset)); | 515 __ ld(kScratchReg, FieldMemOperand(func, JSFunction::kContextOffset)); |
| 505 __ Assert(eq, kWrongFunctionContext, cp, Operand(kScratchReg)); | 516 __ Assert(eq, kWrongFunctionContext, cp, Operand(kScratchReg)); |
| 506 } | 517 } |
| 507 AssembleDeconstructActivationRecord(); | 518 int stack_param_delta = i.InputInt32(instr->InputCount() - 1); |
| 519 AssembleDeconstructActivationRecord(stack_param_delta); |
| 508 __ ld(at, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); | 520 __ ld(at, FieldMemOperand(func, JSFunction::kCodeEntryOffset)); |
| 509 __ Jump(at); | 521 __ Jump(at); |
| 510 break; | 522 break; |
| 511 } | 523 } |
| 512 case kArchLazyBailout: { | 524 case kArchLazyBailout: { |
| 513 EnsureSpaceForLazyDeopt(); | 525 EnsureSpaceForLazyDeopt(); |
| 514 RecordCallPosition(instr); | 526 RecordCallPosition(instr); |
| 515 break; | 527 break; |
| 516 } | 528 } |
| 517 case kArchPrepareCallCFunction: { | 529 case kArchPrepareCallCFunction: { |
| (...skipping 1147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1665 padding_size -= v8::internal::Assembler::kInstrSize; | 1677 padding_size -= v8::internal::Assembler::kInstrSize; |
| 1666 } | 1678 } |
| 1667 } | 1679 } |
| 1668 } | 1680 } |
| 1669 | 1681 |
| 1670 #undef __ | 1682 #undef __ |
| 1671 | 1683 |
| 1672 } // namespace compiler | 1684 } // namespace compiler |
| 1673 } // namespace internal | 1685 } // namespace internal |
| 1674 } // namespace v8 | 1686 } // namespace v8 |
| OLD | NEW |