Upgrade V8 to 5.1.281.57 DO NOT MERGE
FPIIM-449
Change-Id: Id981b686b4d587ac31697662eb98bb34be42ad90
(cherry picked from commit 3b9bc31999c9787eb726ecdbfd5796bfdec32a18)
diff --git a/src/compiler/ppc/code-generator-ppc.cc b/src/compiler/ppc/code-generator-ppc.cc
index 7fc6dd9..6f1e588 100644
--- a/src/compiler/ppc/code-generator-ppc.cc
+++ b/src/compiler/ppc/code-generator-ppc.cc
@@ -32,6 +32,7 @@
RCBit OutputRCBit() const {
switch (instr_->flags_mode()) {
case kFlags_branch:
+ case kFlags_deoptimize:
case kFlags_set:
return SetRC;
case kFlags_none:
@@ -103,8 +104,11 @@
MemOperand ToMemOperand(InstructionOperand* op) const {
DCHECK_NOT_NULL(op);
DCHECK(op->IsStackSlot() || op->IsDoubleStackSlot());
- FrameOffset offset = frame_access_state()->GetFrameOffset(
- AllocatedOperand::cast(op)->index());
+ return SlotToMemOperand(AllocatedOperand::cast(op)->index());
+ }
+
+ MemOperand SlotToMemOperand(int slot) const {
+ FrameOffset offset = frame_access_state()->GetFrameOffset(slot);
return MemOperand(offset.from_stack_pointer() ? sp : fp, offset.offset());
}
};
@@ -183,7 +187,8 @@
value_(value),
scratch0_(scratch0),
scratch1_(scratch1),
- mode_(mode) {}
+ mode_(mode),
+ must_save_lr_(!gen->frame_access_state()->has_frame()) {}
void Generate() final {
if (mode_ > RecordWriteMode::kValueIsPointer) {
@@ -197,7 +202,7 @@
: OMIT_REMEMBERED_SET;
SaveFPRegsMode const save_fp_mode =
frame()->DidAllocateDoubleRegisters() ? kSaveFPRegs : kDontSaveFPRegs;
- if (!frame()->needs_frame()) {
+ if (must_save_lr_) {
// We need to save and restore lr if the frame was elided.
__ mflr(scratch1_);
__ Push(scratch1_);
@@ -211,7 +216,7 @@
__ add(scratch1_, object_, offset_);
}
__ CallStub(&stub);
- if (!frame()->needs_frame()) {
+ if (must_save_lr_) {
// We need to save and restore lr if the frame was elided.
__ Pop(scratch1_);
__ mtlr(scratch1_);
@@ -226,6 +231,7 @@
Register const scratch0_;
Register const scratch1_;
RecordWriteMode const mode_;
+ bool must_save_lr_;
};
@@ -293,20 +299,24 @@
} // namespace
-#define ASSEMBLE_FLOAT_UNOP_RC(asm_instr) \
+#define ASSEMBLE_FLOAT_UNOP_RC(asm_instr, round) \
do { \
__ asm_instr(i.OutputDoubleRegister(), i.InputDoubleRegister(0), \
i.OutputRCBit()); \
+ if (round) { \
+ __ frsp(i.OutputDoubleRegister(), i.OutputDoubleRegister()); \
+ } \
} while (0)
-
-#define ASSEMBLE_FLOAT_BINOP_RC(asm_instr) \
+#define ASSEMBLE_FLOAT_BINOP_RC(asm_instr, round) \
do { \
__ asm_instr(i.OutputDoubleRegister(), i.InputDoubleRegister(0), \
i.InputDoubleRegister(1), i.OutputRCBit()); \
+ if (round) { \
+ __ frsp(i.OutputDoubleRegister(), i.OutputDoubleRegister()); \
+ } \
} while (0)
-
#define ASSEMBLE_BINOP(asm_instr_reg, asm_instr_imm) \
do { \
if (HasRegisterInput(instr, 1)) { \
@@ -662,6 +672,11 @@
DCHECK_EQ(LeaveRC, i.OutputRCBit()); \
} while (0)
+void CodeGenerator::AssembleDeconstructFrame() {
+ __ LeaveFrame(StackFrame::MANUAL);
+}
+
+void CodeGenerator::AssembleSetupStackPointer() {}
void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) {
int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta);
@@ -678,12 +693,36 @@
__ Add(sp, sp, sp_slot_delta * kPointerSize, r0);
frame_access_state()->IncreaseSPDelta(-sp_slot_delta);
}
- if (frame()->needs_frame()) {
+ if (frame_access_state()->has_frame()) {
__ RestoreFrameStateForTailCall();
}
frame_access_state()->SetFrameAccessToSP();
}
+void CodeGenerator::AssemblePopArgumentsAdaptorFrame(Register args_reg,
+ Register scratch1,
+ Register scratch2,
+ Register scratch3) {
+ DCHECK(!AreAliased(args_reg, scratch1, scratch2, scratch3));
+ Label done;
+
+ // Check if current frame is an arguments adaptor frame.
+ __ LoadP(scratch1, MemOperand(fp, StandardFrameConstants::kContextOffset));
+ __ CmpSmiLiteral(scratch1, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR), r0);
+ __ bne(&done);
+
+ // Load arguments count from current arguments adaptor frame (note, it
+ // does not include receiver).
+ Register caller_args_count_reg = scratch1;
+ __ LoadP(caller_args_count_reg,
+ MemOperand(fp, ArgumentsAdaptorFrameConstants::kLengthOffset));
+ __ SmiUntag(caller_args_count_reg);
+
+ ParameterCount callee_args_count(args_reg);
+ __ PrepareForTailCall(callee_args_count, caller_args_count_reg, scratch2,
+ scratch3);
+ __ bind(&done);
+}
// Assembles an instruction after register allocation, producing machine code.
void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
@@ -708,9 +747,15 @@
frame_access_state()->ClearSPDelta();
break;
}
+ case kArchTailCallCodeObjectFromJSFunction:
case kArchTailCallCodeObject: {
int stack_param_delta = i.InputInt32(instr->InputCount() - 1);
AssembleDeconstructActivationRecord(stack_param_delta);
+ if (opcode == kArchTailCallCodeObjectFromJSFunction) {
+ AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister,
+ i.TempRegister(0), i.TempRegister(1),
+ i.TempRegister(2));
+ }
if (HasRegisterInput(instr, 0)) {
__ addi(ip, i.InputRegister(0),
Operand(Code::kHeaderSize - kHeapObjectTag));
@@ -745,6 +790,7 @@
frame_access_state()->ClearSPDelta();
break;
}
+ case kArchTailCallJSFunctionFromJSFunction:
case kArchTailCallJSFunction: {
Register func = i.InputRegister(0);
if (FLAG_debug_code) {
@@ -756,6 +802,11 @@
}
int stack_param_delta = i.InputInt32(instr->InputCount() - 1);
AssembleDeconstructActivationRecord(stack_param_delta);
+ if (opcode == kArchTailCallJSFunctionFromJSFunction) {
+ AssemblePopArgumentsAdaptorFrame(kJavaScriptCallArgCountRegister,
+ i.TempRegister(0), i.TempRegister(1),
+ i.TempRegister(2));
+ }
__ LoadP(ip, FieldMemOperand(func, JSFunction::kCodeEntryOffset));
__ Jump(ip);
DCHECK_EQ(LeaveRC, i.OutputRCBit());
@@ -823,7 +874,7 @@
DCHECK_EQ(LeaveRC, i.OutputRCBit());
break;
case kArchParentFramePointer:
- if (frame_access_state()->frame()->needs_frame()) {
+ if (frame_access_state()->has_frame()) {
__ LoadP(i.OutputRegister(), MemOperand(fp, 0));
} else {
__ mr(i.OutputRegister(), fp);
@@ -928,6 +979,71 @@
ASSEMBLE_BINOP_INT_RC(srad, sradi);
break;
#endif
+#if !V8_TARGET_ARCH_PPC64
+ case kPPC_AddPair:
+ // i.InputRegister(0) ... left low word.
+ // i.InputRegister(1) ... left high word.
+ // i.InputRegister(2) ... right low word.
+ // i.InputRegister(3) ... right high word.
+ __ addc(i.OutputRegister(0), i.InputRegister(0), i.InputRegister(2));
+ __ adde(i.OutputRegister(1), i.InputRegister(1), i.InputRegister(3));
+ DCHECK_EQ(LeaveRC, i.OutputRCBit());
+ break;
+ case kPPC_SubPair:
+ // i.InputRegister(0) ... left low word.
+ // i.InputRegister(1) ... left high word.
+ // i.InputRegister(2) ... right low word.
+ // i.InputRegister(3) ... right high word.
+ __ subc(i.OutputRegister(0), i.InputRegister(0), i.InputRegister(2));
+ __ sube(i.OutputRegister(1), i.InputRegister(1), i.InputRegister(3));
+ DCHECK_EQ(LeaveRC, i.OutputRCBit());
+ break;
+ case kPPC_MulPair:
+ // i.InputRegister(0) ... left low word.
+ // i.InputRegister(1) ... left high word.
+ // i.InputRegister(2) ... right low word.
+ // i.InputRegister(3) ... right high word.
+ __ mullw(i.TempRegister(0), i.InputRegister(0), i.InputRegister(3));
+ __ mullw(i.TempRegister(1), i.InputRegister(2), i.InputRegister(1));
+ __ add(i.TempRegister(0), i.TempRegister(0), i.TempRegister(1));
+ __ mullw(i.OutputRegister(0), i.InputRegister(0), i.InputRegister(2));
+ __ mulhwu(i.OutputRegister(1), i.InputRegister(0), i.InputRegister(2));
+ __ add(i.OutputRegister(1), i.OutputRegister(1), i.TempRegister(0));
+ break;
+ case kPPC_ShiftLeftPair:
+ if (instr->InputAt(2)->IsImmediate()) {
+ __ ShiftLeftPair(i.OutputRegister(0), i.OutputRegister(1),
+ i.InputRegister(0), i.InputRegister(1),
+ i.InputInt32(2));
+ } else {
+ __ ShiftLeftPair(i.OutputRegister(0), i.OutputRegister(1),
+ i.InputRegister(0), i.InputRegister(1), kScratchReg,
+ i.InputRegister(2));
+ }
+ break;
+ case kPPC_ShiftRightPair:
+ if (instr->InputAt(2)->IsImmediate()) {
+ __ ShiftRightPair(i.OutputRegister(0), i.OutputRegister(1),
+ i.InputRegister(0), i.InputRegister(1),
+ i.InputInt32(2));
+ } else {
+ __ ShiftRightPair(i.OutputRegister(0), i.OutputRegister(1),
+ i.InputRegister(0), i.InputRegister(1), kScratchReg,
+ i.InputRegister(2));
+ }
+ break;
+ case kPPC_ShiftRightAlgPair:
+ if (instr->InputAt(2)->IsImmediate()) {
+ __ ShiftRightAlgPair(i.OutputRegister(0), i.OutputRegister(1),
+ i.InputRegister(0), i.InputRegister(1),
+ i.InputInt32(2));
+ } else {
+ __ ShiftRightAlgPair(i.OutputRegister(0), i.OutputRegister(1),
+ i.InputRegister(0), i.InputRegister(1),
+ kScratchReg, i.InputRegister(2));
+ }
+ break;
+#endif
case kPPC_RotRight32:
if (HasRegisterInput(instr, 1)) {
__ subfic(kScratchReg, i.InputRegister(1), Operand(32));
@@ -992,7 +1108,7 @@
ASSEMBLE_ADD_WITH_OVERFLOW32();
break;
case kPPC_AddDouble:
- ASSEMBLE_FLOAT_BINOP_RC(fadd);
+ ASSEMBLE_FLOAT_BINOP_RC(fadd, MiscField::decode(instr->opcode()));
break;
case kPPC_Sub:
#if V8_TARGET_ARCH_PPC64
@@ -1015,7 +1131,7 @@
ASSEMBLE_SUB_WITH_OVERFLOW32();
break;
case kPPC_SubDouble:
- ASSEMBLE_FLOAT_BINOP_RC(fsub);
+ ASSEMBLE_FLOAT_BINOP_RC(fsub, MiscField::decode(instr->opcode()));
break;
case kPPC_Mul32:
__ mullw(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1),
@@ -1036,7 +1152,7 @@
i.OutputRCBit());
break;
case kPPC_MulDouble:
- ASSEMBLE_FLOAT_BINOP_RC(fmul);
+ ASSEMBLE_FLOAT_BINOP_RC(fmul, MiscField::decode(instr->opcode()));
break;
case kPPC_Div32:
__ divw(i.OutputRegister(), i.InputRegister(0), i.InputRegister(1));
@@ -1059,7 +1175,7 @@
break;
#endif
case kPPC_DivDouble:
- ASSEMBLE_FLOAT_BINOP_RC(fdiv);
+ ASSEMBLE_FLOAT_BINOP_RC(fdiv, MiscField::decode(instr->opcode()));
break;
case kPPC_Mod32:
ASSEMBLE_MODULO(divw, mullw);
@@ -1092,25 +1208,25 @@
ASSEMBLE_FLOAT_MIN(kScratchDoubleReg);
break;
case kPPC_AbsDouble:
- ASSEMBLE_FLOAT_UNOP_RC(fabs);
+ ASSEMBLE_FLOAT_UNOP_RC(fabs, 0);
break;
case kPPC_SqrtDouble:
- ASSEMBLE_FLOAT_UNOP_RC(fsqrt);
+ ASSEMBLE_FLOAT_UNOP_RC(fsqrt, MiscField::decode(instr->opcode()));
break;
case kPPC_FloorDouble:
- ASSEMBLE_FLOAT_UNOP_RC(frim);
+ ASSEMBLE_FLOAT_UNOP_RC(frim, MiscField::decode(instr->opcode()));
break;
case kPPC_CeilDouble:
- ASSEMBLE_FLOAT_UNOP_RC(frip);
+ ASSEMBLE_FLOAT_UNOP_RC(frip, MiscField::decode(instr->opcode()));
break;
case kPPC_TruncateDouble:
- ASSEMBLE_FLOAT_UNOP_RC(friz);
+ ASSEMBLE_FLOAT_UNOP_RC(friz, MiscField::decode(instr->opcode()));
break;
case kPPC_RoundDouble:
- ASSEMBLE_FLOAT_UNOP_RC(frin);
+ ASSEMBLE_FLOAT_UNOP_RC(frin, MiscField::decode(instr->opcode()));
break;
case kPPC_NegDouble:
- ASSEMBLE_FLOAT_UNOP_RC(fneg);
+ ASSEMBLE_FLOAT_UNOP_RC(fneg, 0);
break;
case kPPC_Cntlz32:
__ cntlzw_(i.OutputRegister(), i.InputRegister(0));
@@ -1316,7 +1432,7 @@
}
#endif
case kPPC_DoubleToFloat32:
- ASSEMBLE_FLOAT_UNOP_RC(frsp);
+ ASSEMBLE_FLOAT_UNOP_RC(frsp, 0);
break;
case kPPC_Float32ToDouble:
// Nothing to do.
@@ -1589,36 +1705,36 @@
int deoptimization_id, Deoptimizer::BailoutType bailout_type) {
Address deopt_entry = Deoptimizer::GetDeoptimizationEntry(
isolate(), deoptimization_id, bailout_type);
+ // TODO(turbofan): We should be able to generate better code by sharing the
+ // actual final call site and just bl'ing to it here, similar to what we do
+ // in the lithium backend.
__ Call(deopt_entry, RelocInfo::RUNTIME_ENTRY);
}
void CodeGenerator::AssemblePrologue() {
CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
- if (descriptor->IsCFunctionCall()) {
- __ function_descriptor();
- __ mflr(r0);
- if (FLAG_enable_embedded_constant_pool) {
- __ Push(r0, fp, kConstantPoolRegister);
- // Adjust FP to point to saved FP.
- __ subi(fp, sp, Operand(StandardFrameConstants::kConstantPoolOffset));
+ if (frame_access_state()->has_frame()) {
+ if (descriptor->IsCFunctionCall()) {
+ __ function_descriptor();
+ __ mflr(r0);
+ if (FLAG_enable_embedded_constant_pool) {
+ __ Push(r0, fp, kConstantPoolRegister);
+ // Adjust FP to point to saved FP.
+ __ subi(fp, sp, Operand(StandardFrameConstants::kConstantPoolOffset));
+ } else {
+ __ Push(r0, fp);
+ __ mr(fp, sp);
+ }
+ } else if (descriptor->IsJSFunctionCall()) {
+ __ Prologue(this->info()->GeneratePreagedPrologue(), ip);
} else {
- __ Push(r0, fp);
- __ mr(fp, sp);
+ StackFrame::Type type = info()->GetOutputStackFrameType();
+ // TODO(mbrandy): Detect cases where ip is the entrypoint (for
+ // efficient intialization of the constant pool pointer register).
+ __ StubPrologue(type);
}
- } else if (descriptor->IsJSFunctionCall()) {
- __ Prologue(this->info()->GeneratePreagedPrologue(), ip);
- } else if (frame()->needs_frame()) {
- if (!ABI_CALL_VIA_IP && info()->output_code_kind() == Code::WASM_FUNCTION) {
- // TODO(mbrandy): Restrict only to the wasm wrapper case.
- __ StubPrologue();
- } else {
- __ StubPrologue(ip);
- }
- } else {
- frame()->SetElidedFrameSizeInSlots(0);
}
- frame_access_state()->SetFrameAccessToDefault();
int stack_shrink_slots = frame()->GetSpillSlotCount();
if (info()->is_osr()) {
@@ -1687,20 +1803,18 @@
}
if (descriptor->IsCFunctionCall()) {
- __ LeaveFrame(StackFrame::MANUAL, pop_count * kPointerSize);
- } else if (frame()->needs_frame()) {
+ AssembleDeconstructFrame();
+ } else if (frame_access_state()->has_frame()) {
// Canonicalize JSFunction return sites for now.
if (return_label_.is_bound()) {
__ b(&return_label_);
return;
} else {
__ bind(&return_label_);
- __ LeaveFrame(StackFrame::MANUAL, pop_count * kPointerSize);
+ AssembleDeconstructFrame();
}
- } else {
- __ Drop(pop_count);
}
- __ Ret();
+ __ Ret(pop_count);
}
@@ -1753,9 +1867,9 @@
case Constant::kHeapObject: {
Handle<HeapObject> src_object = src.ToHeapObject();
Heap::RootListIndex index;
- int offset;
- if (IsMaterializableFromFrame(src_object, &offset)) {
- __ LoadP(dst, MemOperand(fp, offset));
+ int slot;
+ if (IsMaterializableFromFrame(src_object, &slot)) {
+ __ LoadP(dst, g.SlotToMemOperand(slot));
} else if (IsMaterializableFromRoot(src_object, &index)) {
__ LoadRoot(dst, index);
} else {