Index: src/s390/macro-assembler-s390.cc |
diff --git a/src/s390/macro-assembler-s390.cc b/src/s390/macro-assembler-s390.cc |
index d6fdc4bf2e00bd1446c9fa2963a312f66b05ffc8..aede01dade2d1148d0d7587e80b12dde6549b3a4 100644 |
--- a/src/s390/macro-assembler-s390.cc |
+++ b/src/s390/macro-assembler-s390.cc |
@@ -558,23 +558,40 @@ void MacroAssembler::RememberedSetHelper(Register object, // For debug tests. |
} |
} |
-void MacroAssembler::PushFixedFrame(Register marker_reg) { |
+void MacroAssembler::PushCommonFrame(Register marker_reg) { |
+ int fp_delta = 0; |
CleanseP(r14); |
if (marker_reg.is_valid()) { |
- Push(r14, fp, cp, marker_reg); |
+ Push(r14, fp, marker_reg); |
+ fp_delta = 1; |
} else { |
- Push(r14, fp, cp); |
+ Push(r14, fp); |
+ fp_delta = 0; |
} |
+ la(fp, MemOperand(sp, fp_delta * kPointerSize)); |
} |
-void MacroAssembler::PopFixedFrame(Register marker_reg) { |
+void MacroAssembler::PopCommonFrame(Register marker_reg) { |
if (marker_reg.is_valid()) { |
- Pop(r14, fp, cp, marker_reg); |
+ Pop(r14, fp, marker_reg); |
} else { |
- Pop(r14, fp, cp); |
+ Pop(r14, fp); |
} |
} |
+void MacroAssembler::PushStandardFrame(Register function_reg) { |
+ int fp_delta = 0; |
+ CleanseP(r14); |
+ if (function_reg.is_valid()) { |
+ Push(r14, fp, cp, function_reg); |
+ fp_delta = 2; |
+ } else { |
+ Push(r14, fp, cp); |
+ fp_delta = 1; |
+ } |
+ la(fp, MemOperand(sp, fp_delta * kPointerSize)); |
+} |
+ |
void MacroAssembler::RestoreFrameStateForTailCall() { |
// if (FLAG_enable_embedded_constant_pool) { |
// LoadP(kConstantPoolRegister, |
@@ -868,6 +885,59 @@ void MacroAssembler::ConvertDoubleToUnsignedInt64( |
clgdbr(m, Condition(0), dst, double_input); |
ldgr(double_dst, dst); |
} |
+ |
+#endif |
+ |
+#if !V8_TARGET_ARCH_S390X |
+void MacroAssembler::ShiftLeftPair(Register dst_low, Register dst_high, |
+ Register src_low, Register src_high, |
+ Register scratch, Register shift) { |
+ DCHECK(!AreAliased(dst_low, src_high, shift)); |
+ DCHECK(!AreAliased(dst_high, src_low, shift)); |
+ UNIMPLEMENTED(); |
+} |
+ |
+void MacroAssembler::ShiftLeftPair(Register dst_low, Register dst_high, |
+ Register src_low, Register src_high, |
+ uint32_t shift) { |
+ DCHECK(!AreAliased(dst_low, src_high)); |
+ DCHECK(!AreAliased(dst_high, src_low)); |
+ UNIMPLEMENTED(); |
+ Label less_than_32; |
+ Label done; |
+} |
+ |
+void MacroAssembler::ShiftRightPair(Register dst_low, Register dst_high, |
+ Register src_low, Register src_high, |
+ Register scratch, Register shift) { |
+ DCHECK(!AreAliased(dst_low, src_high, shift)); |
+ DCHECK(!AreAliased(dst_high, src_low, shift)); |
+ UNIMPLEMENTED(); |
+} |
+ |
+void MacroAssembler::ShiftRightPair(Register dst_low, Register dst_high, |
+ Register src_low, Register src_high, |
+ uint32_t shift) { |
+ DCHECK(!AreAliased(dst_low, src_high)); |
+ DCHECK(!AreAliased(dst_high, src_low)); |
+ UNIMPLEMENTED(); |
+} |
+ |
+void MacroAssembler::ShiftRightArithPair(Register dst_low, Register dst_high, |
+ Register src_low, Register src_high, |
+ Register scratch, Register shift) { |
+ DCHECK(!AreAliased(dst_low, src_high, shift)); |
+ DCHECK(!AreAliased(dst_high, src_low, shift)); |
+ UNIMPLEMENTED(); |
+} |
+ |
+void MacroAssembler::ShiftRightArithPair(Register dst_low, Register dst_high, |
+ Register src_low, Register src_high, |
+ uint32_t shift) { |
+ DCHECK(!AreAliased(dst_low, src_high)); |
+ DCHECK(!AreAliased(dst_high, src_low)); |
+ UNIMPLEMENTED(); |
+} |
#endif |
void MacroAssembler::MovDoubleToInt64(Register dst, DoubleRegister src) { |
@@ -878,11 +948,10 @@ void MacroAssembler::MovInt64ToDouble(DoubleRegister dst, Register src) { |
ldgr(dst, src); |
} |
-void MacroAssembler::StubPrologue(Register base, int prologue_offset) { |
- PushFixedFrame(); |
- Push(Smi::FromInt(StackFrame::STUB)); |
- // Adjust FP to point to saved FP. |
- la(fp, MemOperand(sp, StandardFrameConstants::kFixedFrameSizeFromFp)); |
+void MacroAssembler::StubPrologue(StackFrame::Type type, Register base, |
+ int prologue_offset) { |
+ LoadSmiLiteral(r1, Smi::FromInt(type)); |
+ PushCommonFrame(r1); |
} |
void MacroAssembler::Prologue(bool code_pre_aging, Register base, |
@@ -911,9 +980,7 @@ void MacroAssembler::Prologue(bool code_pre_aging, Register base, |
} |
} else { |
// This matches the code found in GetNoCodeAgeSequence() |
- PushFixedFrame(r3); |
- // Adjust fp to point to saved fp. |
- la(fp, MemOperand(sp, StandardFrameConstants::kFixedFrameSizeFromFp)); |
+ PushStandardFrame(r3); |
} |
} |
} |
@@ -935,13 +1002,12 @@ void MacroAssembler::EnterFrame(StackFrame::Type type, |
// CodeObject <-- new sp |
LoadSmiLiteral(ip, Smi::FromInt(type)); |
- PushFixedFrame(ip); |
+ PushCommonFrame(ip); |
- mov(r0, Operand(CodeObject())); |
- push(r0); |
- // Adjust FP to point to saved FP |
- la(fp, MemOperand( |
- sp, StandardFrameConstants::kFixedFrameSizeFromFp + kPointerSize)); |
+ if (type == StackFrame::INTERNAL) { |
+ mov(r0, Operand(CodeObject())); |
+ push(r0); |
+ } |
} |
int MacroAssembler::LeaveFrame(StackFrame::Type type, int stack_adjustment) { |
@@ -991,10 +1057,10 @@ void MacroAssembler::EnterExitFrame(bool save_doubles, int stack_space) { |
// all of the pushes that have happened inside of V8 |
// since we were called from C code |
CleanseP(r14); |
- Push(r14, fp); |
- LoadRR(fp, sp); |
+ LoadSmiLiteral(r1, Smi::FromInt(StackFrame::EXIT)); |
+ PushCommonFrame(r1); |
// Reserve room for saved entry sp and code object. |
- lay(sp, MemOperand(sp, -ExitFrameConstants::kFrameSize)); |
+ lay(sp, MemOperand(fp, -ExitFrameConstants::kFixedFrameSizeFromFp)); |
if (emit_debug_code()) { |
StoreP(MemOperand(fp, ExitFrameConstants::kSPOffset), Operand::Zero(), r1); |
@@ -1070,7 +1136,7 @@ void MacroAssembler::LeaveExitFrame(bool save_doubles, Register argument_count, |
if (save_doubles) { |
// Calculate the stack location of the saved doubles and restore them. |
const int kNumRegs = kNumCallerSavedDoubles; |
- lay(r5, MemOperand(fp, -(ExitFrameConstants::kFrameSize + |
+ lay(r5, MemOperand(fp, -(ExitFrameConstants::kFixedFrameSizeFromFp + |
kNumRegs * kDoubleSize))); |
MultiPopDoubles(kCallerSavedDoubles, r5); |
} |
@@ -1108,6 +1174,71 @@ void MacroAssembler::MovFromFloatParameter(const DoubleRegister dst) { |
Move(dst, d0); |
} |
+void MacroAssembler::PrepareForTailCall(const ParameterCount& callee_args_count, |
+ Register caller_args_count_reg, |
+ Register scratch0, Register scratch1) { |
+#if DEBUG |
+ if (callee_args_count.is_reg()) { |
+ DCHECK(!AreAliased(callee_args_count.reg(), caller_args_count_reg, scratch0, |
+ scratch1)); |
+ } else { |
+ DCHECK(!AreAliased(caller_args_count_reg, scratch0, scratch1)); |
+ } |
+#endif |
+ |
+ // Calculate the end of destination area where we will put the arguments |
+ // after we drop current frame. We AddP kPointerSize to count the receiver |
+ // argument which is not included into formal parameters count. |
+ Register dst_reg = scratch0; |
+ ShiftLeftP(dst_reg, caller_args_count_reg, Operand(kPointerSizeLog2)); |
+ AddP(dst_reg, fp, dst_reg); |
+ AddP(dst_reg, dst_reg, |
+ Operand(StandardFrameConstants::kCallerSPOffset + kPointerSize)); |
+ |
+ Register src_reg = caller_args_count_reg; |
+ // Calculate the end of source area. +kPointerSize is for the receiver. |
+ if (callee_args_count.is_reg()) { |
+ ShiftLeftP(src_reg, callee_args_count.reg(), Operand(kPointerSizeLog2)); |
+ AddP(src_reg, sp, src_reg); |
+ AddP(src_reg, src_reg, Operand(kPointerSize)); |
+ } else { |
+ mov(src_reg, Operand((callee_args_count.immediate() + 1) * kPointerSize)); |
+ AddP(src_reg, src_reg, sp); |
+ } |
+ |
+ if (FLAG_debug_code) { |
+ CmpLogicalP(src_reg, dst_reg); |
+ Check(lt, kStackAccessBelowStackPointer); |
+ } |
+ |
+ // Restore caller's frame pointer and return address now as they will be |
+ // overwritten by the copying loop. |
+ RestoreFrameStateForTailCall(); |
+ |
+ // Now copy callee arguments to the caller frame going backwards to avoid |
+ // callee arguments corruption (source and destination areas could overlap). |
+ |
+ // Both src_reg and dst_reg are pointing to the word after the one to copy, |
+ // so they must be pre-decremented in the loop. |
+ Register tmp_reg = scratch1; |
+ Label loop; |
+ if (callee_args_count.is_reg()) { |
+ AddP(tmp_reg, callee_args_count.reg(), Operand(1)); // +1 for receiver |
+ } else { |
+ mov(tmp_reg, Operand(callee_args_count.immediate() + 1)); |
+ } |
+ LoadRR(r1, tmp_reg); |
+ bind(&loop); |
+ LoadP(tmp_reg, MemOperand(src_reg, -kPointerSize)); |
+ StoreP(tmp_reg, MemOperand(dst_reg, -kPointerSize)); |
+ lay(src_reg, MemOperand(src_reg, -kPointerSize)); |
+ lay(dst_reg, MemOperand(dst_reg, -kPointerSize)); |
+ BranchOnCount(r1, &loop); |
+ |
+ // Leave current frame. |
+ LoadRR(sp, dst_reg); |
+} |
+ |
void MacroAssembler::InvokePrologue(const ParameterCount& expected, |
const ParameterCount& actual, Label* done, |
bool* definitely_mismatches, |
@@ -1379,8 +1510,20 @@ void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg, |
DCHECK(!holder_reg.is(ip)); |
DCHECK(!scratch.is(ip)); |
- // Load current lexical context from the stack frame. |
- LoadP(scratch, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
+ // Load current lexical context from the active StandardFrame, which |
+ // may require crawling past STUB frames. |
+ Label load_context; |
+ Label has_context; |
+ DCHECK(!ip.is(scratch)); |
+ LoadRR(ip, fp); |
+ bind(&load_context); |
+ LoadP(scratch, |
+ MemOperand(ip, CommonFrameConstants::kContextOrFrameTypeOffset)); |
+ JumpIfNotSmi(scratch, &has_context); |
+ LoadP(ip, MemOperand(ip, CommonFrameConstants::kCallerFPOffset)); |
+ b(&load_context); |
+ bind(&has_context); |
+ |
// In debug mode, make sure the lexical context is set. |
#ifdef DEBUG |
CmpP(scratch, Operand::Zero()); |