Commit dba86292 authored by Milad Farazmand's avatar Milad Farazmand Committed by Commit Bot

PPC/s390: [builtins] Remove ParameterCount uses from InvokeFunction(Code)

Port 46648402

Original Commit Message:

    CallDebugOnFunctionCall was always using Registers and not Immediates.
    Then ParameterCount is not really needed. Since updating that, we
    could update other functions, e.g InvokeFunction, to only use
    registers too.

    Also removed now irrelevant variables, e.g definitely_mismatches.

R=solanes@chromium.org, joransiu@ca.ibm.com, jyan@ca.ibm.com, michael_dawson@ca.ibm.com
BUG=
LOG=N

Change-Id: Ie0348998503bf4f416440f056e4296d22d064d4d
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1892171Reviewed-by: 's avatarJoran Siu <joransiu@ca.ibm.com>
Commit-Queue: Milad Farazmand <miladfar@ca.ibm.com>
Cr-Commit-Position: refs/heads/master@{#64665}
parent f27919c3
...@@ -144,8 +144,7 @@ void Generate_JSBuiltinsConstructStubHelper(MacroAssembler* masm) { ...@@ -144,8 +144,7 @@ void Generate_JSBuiltinsConstructStubHelper(MacroAssembler* masm) {
// r6: new target // r6: new target
{ {
ConstantPoolUnavailableScope constant_pool_unavailable(masm); ConstantPoolUnavailableScope constant_pool_unavailable(masm);
ParameterCount actual(r3); __ InvokeFunctionWithNewTarget(r4, r6, r3, CALL_FUNCTION);
__ InvokeFunction(r4, r6, actual, CALL_FUNCTION);
} }
// Restore context from the frame. // Restore context from the frame.
...@@ -300,8 +299,7 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { ...@@ -300,8 +299,7 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
// Call the function. // Call the function.
{ {
ConstantPoolUnavailableScope constant_pool_unavailable(masm); ConstantPoolUnavailableScope constant_pool_unavailable(masm);
ParameterCount actual(r3); __ InvokeFunctionWithNewTarget(r4, r6, r3, CALL_FUNCTION);
__ InvokeFunction(r4, r6, actual, CALL_FUNCTION);
} }
// ----------- S t a t e ------------- // ----------- S t a t e -------------
...@@ -2102,9 +2100,7 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm, ...@@ -2102,9 +2100,7 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm,
__ LoadHalfWord( __ LoadHalfWord(
r5, FieldMemOperand(r5, SharedFunctionInfo::kFormalParameterCountOffset)); r5, FieldMemOperand(r5, SharedFunctionInfo::kFormalParameterCountOffset));
ParameterCount actual(r3); __ InvokeFunctionCode(r4, no_reg, r5, r3, JUMP_FUNCTION);
ParameterCount expected(r5);
__ InvokeFunctionCode(r4, no_reg, expected, actual, JUMP_FUNCTION);
// The function is a "classConstructor", need to raise an exception. // The function is a "classConstructor", need to raise an exception.
__ bind(&class_constructor); __ bind(&class_constructor);
......
...@@ -139,8 +139,7 @@ void Generate_JSBuiltinsConstructStubHelper(MacroAssembler* masm) { ...@@ -139,8 +139,7 @@ void Generate_JSBuiltinsConstructStubHelper(MacroAssembler* masm) {
// r3: constructor function // r3: constructor function
// r5: new target // r5: new target
ParameterCount actual(r2); __ InvokeFunctionWithNewTarget(r3, r5, r2, CALL_FUNCTION);
__ InvokeFunction(r3, r5, actual, CALL_FUNCTION);
// Restore context from the frame. // Restore context from the frame.
__ LoadP(cp, MemOperand(fp, ConstructFrameConstants::kContextOffset)); __ LoadP(cp, MemOperand(fp, ConstructFrameConstants::kContextOffset));
...@@ -293,8 +292,7 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { ...@@ -293,8 +292,7 @@ void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
__ bind(&no_args); __ bind(&no_args);
// Call the function. // Call the function.
ParameterCount actual(r2); __ InvokeFunctionWithNewTarget(r3, r5, r2, CALL_FUNCTION);
__ InvokeFunction(r3, r5, actual, CALL_FUNCTION);
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- r0: constructor result // -- r0: constructor result
...@@ -2160,9 +2158,7 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm, ...@@ -2160,9 +2158,7 @@ void Builtins::Generate_CallFunction(MacroAssembler* masm,
__ LoadLogicalHalfWordP( __ LoadLogicalHalfWordP(
r4, FieldMemOperand(r4, SharedFunctionInfo::kFormalParameterCountOffset)); r4, FieldMemOperand(r4, SharedFunctionInfo::kFormalParameterCountOffset));
ParameterCount actual(r2); __ InvokeFunctionCode(r3, no_reg, r4, r2, JUMP_FUNCTION);
ParameterCount expected(r4);
__ InvokeFunctionCode(r3, no_reg, expected, actual, JUMP_FUNCTION);
// The function is a "classConstructor", need to raise an exception. // The function is a "classConstructor", need to raise an exception.
__ bind(&class_constructor); __ bind(&class_constructor);
......
...@@ -1214,12 +1214,9 @@ void TurboAssembler::PrepareForTailCall(const ParameterCount& callee_args_count, ...@@ -1214,12 +1214,9 @@ void TurboAssembler::PrepareForTailCall(const ParameterCount& callee_args_count,
mr(sp, dst_reg); mr(sp, dst_reg);
} }
void MacroAssembler::InvokePrologue(const ParameterCount& expected, void MacroAssembler::InvokePrologue(Register expected_parameter_count,
const ParameterCount& actual, Label* done, Register actual_parameter_count,
bool* definitely_mismatches, Label* done, InvokeFlag flag) {
InvokeFlag flag) {
bool definitely_matches = false;
*definitely_mismatches = false;
Label regular_invoke; Label regular_invoke;
// Check whether the expected and actual arguments count match. If not, // Check whether the expected and actual arguments count match. If not,
...@@ -1232,56 +1229,28 @@ void MacroAssembler::InvokePrologue(const ParameterCount& expected, ...@@ -1232,56 +1229,28 @@ void MacroAssembler::InvokePrologue(const ParameterCount& expected,
// up actual and expected registers according to the contract if values are // up actual and expected registers according to the contract if values are
// passed in registers. // passed in registers.
// The code below is made a lot easier because the calling code already sets
// up actual and expected registers according to the contract.
// ARM has some sanity checks as per below, considering add them for PPC // ARM has some sanity checks as per below, considering add them for PPC
// DCHECK(actual.is_immediate() || actual.reg() == r3); // DCHECK_EQ(actual_parameter_count, r3);
// DCHECK(expected.is_immediate() || expected.reg() == r5); // DCHECK_EQ(expected_parameter_count, r5);
if (expected.is_immediate()) { cmp(expected_parameter_count, actual_parameter_count);
DCHECK(actual.is_immediate()); beq(&regular_invoke);
mov(r3, Operand(actual.immediate()));
if (expected.immediate() == actual.immediate()) { Handle<Code> adaptor = BUILTIN_CODE(isolate(), ArgumentsAdaptorTrampoline);
definitely_matches = true; if (flag == CALL_FUNCTION) {
} else { Call(adaptor);
const int sentinel = SharedFunctionInfo::kDontAdaptArgumentsSentinel; b(done);
if (expected.immediate() == sentinel) {
// Don't worry about adapting arguments for builtins that
// don't want that done. Skip adaption code by making it look
// like we have a match between expected and actual number of
// arguments.
definitely_matches = true;
} else {
*definitely_mismatches = true;
mov(r5, Operand(expected.immediate()));
}
}
} else { } else {
if (actual.is_immediate()) { Jump(adaptor, RelocInfo::CODE_TARGET);
mov(r3, Operand(actual.immediate()));
cmpi(expected.reg(), Operand(actual.immediate()));
beq(&regular_invoke);
} else {
cmp(expected.reg(), actual.reg());
beq(&regular_invoke);
}
} }
if (!definitely_matches) {
Handle<Code> adaptor = BUILTIN_CODE(isolate(), ArgumentsAdaptorTrampoline);
if (flag == CALL_FUNCTION) {
Call(adaptor);
if (!*definitely_mismatches) {
b(done);
}
} else {
Jump(adaptor, RelocInfo::CODE_TARGET);
}
bind(&regular_invoke); bind(&regular_invoke);
}
} }
void MacroAssembler::CheckDebugHook(Register fun, Register new_target, void MacroAssembler::CheckDebugHook(Register fun, Register new_target,
const ParameterCount& expected, Register expected_parameter_count,
const ParameterCount& actual) { Register actual_parameter_count) {
Label skip_hook; Label skip_hook;
ExternalReference debug_hook_active = ExternalReference debug_hook_active =
...@@ -1294,22 +1263,17 @@ void MacroAssembler::CheckDebugHook(Register fun, Register new_target, ...@@ -1294,22 +1263,17 @@ void MacroAssembler::CheckDebugHook(Register fun, Register new_target,
{ {
// Load receiver to pass it later to DebugOnFunctionCall hook. // Load receiver to pass it later to DebugOnFunctionCall hook.
if (actual.is_reg()) { ShiftLeftImm(r7, actual_parameter_count, Operand(kPointerSizeLog2));
ShiftLeftImm(r7, actual.reg(), Operand(kPointerSizeLog2)); LoadPX(r7, MemOperand(sp, r7));
LoadPX(r7, MemOperand(sp, r7));
} else {
LoadP(r7, MemOperand(sp, actual.immediate() << kPointerSizeLog2), r0);
}
FrameScope frame(this, FrameScope frame(this,
has_frame() ? StackFrame::NONE : StackFrame::INTERNAL); has_frame() ? StackFrame::NONE : StackFrame::INTERNAL);
if (expected.is_reg()) {
SmiTag(expected.reg()); SmiTag(expected_parameter_count);
Push(expected.reg()); Push(expected_parameter_count);
}
if (actual.is_reg()) { SmiTag(actual_parameter_count);
SmiTag(actual.reg()); Push(actual_parameter_count);
Push(actual.reg());
}
if (new_target.is_valid()) { if (new_target.is_valid()) {
Push(new_target); Push(new_target);
} }
...@@ -1319,29 +1283,28 @@ void MacroAssembler::CheckDebugHook(Register fun, Register new_target, ...@@ -1319,29 +1283,28 @@ void MacroAssembler::CheckDebugHook(Register fun, Register new_target,
if (new_target.is_valid()) { if (new_target.is_valid()) {
Pop(new_target); Pop(new_target);
} }
if (actual.is_reg()) {
Pop(actual.reg()); Pop(actual_parameter_count);
SmiUntag(actual.reg()); SmiUntag(actual_parameter_count);
}
if (expected.is_reg()) { Pop(expected_parameter_count);
Pop(expected.reg()); SmiUntag(expected_parameter_count);
SmiUntag(expected.reg());
}
} }
bind(&skip_hook); bind(&skip_hook);
} }
void MacroAssembler::InvokeFunctionCode(Register function, Register new_target, void MacroAssembler::InvokeFunctionCode(Register function, Register new_target,
const ParameterCount& expected, Register expected_parameter_count,
const ParameterCount& actual, Register actual_parameter_count,
InvokeFlag flag) { InvokeFlag flag) {
// You can't call a function without a valid frame. // You can't call a function without a valid frame.
DCHECK(flag == JUMP_FUNCTION || has_frame()); DCHECK_IMPLIES(flag == CALL_FUNCTION, has_frame());
DCHECK(function == r4); DCHECK_EQ(function, r4);
DCHECK_IMPLIES(new_target.is_valid(), new_target == r6); DCHECK_IMPLIES(new_target.is_valid(), new_target == r6);
// On function call, call into the debugger if necessary. // On function call, call into the debugger if necessary.
CheckDebugHook(function, new_target, expected, actual); CheckDebugHook(function, new_target, expected_parameter_count,
actual_parameter_count);
// Clear the new.target register if not given. // Clear the new.target register if not given.
if (!new_target.is_valid()) { if (!new_target.is_valid()) {
...@@ -1349,35 +1312,32 @@ void MacroAssembler::InvokeFunctionCode(Register function, Register new_target, ...@@ -1349,35 +1312,32 @@ void MacroAssembler::InvokeFunctionCode(Register function, Register new_target,
} }
Label done; Label done;
bool definitely_mismatches = false; InvokePrologue(expected_parameter_count, actual_parameter_count, &done, flag);
InvokePrologue(expected, actual, &done, &definitely_mismatches, flag); // We call indirectly through the code field in the function to
if (!definitely_mismatches) { // allow recompilation to take effect without changing any of the
// We call indirectly through the code field in the function to // call sites.
// allow recompilation to take effect without changing any of the Register code = kJavaScriptCallCodeStartRegister;
// call sites. LoadP(code, FieldMemOperand(function, JSFunction::kCodeOffset));
Register code = kJavaScriptCallCodeStartRegister; if (flag == CALL_FUNCTION) {
LoadP(code, FieldMemOperand(function, JSFunction::kCodeOffset)); CallCodeObject(code);
if (flag == CALL_FUNCTION) { } else {
CallCodeObject(code); DCHECK(flag == JUMP_FUNCTION);
} else { JumpCodeObject(code);
DCHECK(flag == JUMP_FUNCTION); }
JumpCodeObject(code);
}
// Continue here if InvokePrologue does handle the invocation due to // Continue here if InvokePrologue does handle the invocation due to
// mismatched parameter counts. // mismatched parameter counts.
bind(&done); bind(&done);
}
} }
void MacroAssembler::InvokeFunction(Register fun, Register new_target, void MacroAssembler::InvokeFunctionWithNewTarget(
const ParameterCount& actual, Register fun, Register new_target, Register actual_parameter_count,
InvokeFlag flag) { InvokeFlag flag) {
// You can't call a function without a valid frame. // You can't call a function without a valid frame.
DCHECK(flag == JUMP_FUNCTION || has_frame()); DCHECK_IMPLIES(flag == CALL_FUNCTION, has_frame());
// Contract with called JS functions requires that function is passed in r4. // Contract with called JS functions requires that function is passed in r4.
DCHECK(fun == r4); DCHECK_EQ(fun, r4);
Register expected_reg = r5; Register expected_reg = r5;
Register temp_reg = r7; Register temp_reg = r7;
...@@ -1388,24 +1348,25 @@ void MacroAssembler::InvokeFunction(Register fun, Register new_target, ...@@ -1388,24 +1348,25 @@ void MacroAssembler::InvokeFunction(Register fun, Register new_target,
FieldMemOperand( FieldMemOperand(
temp_reg, SharedFunctionInfo::kFormalParameterCountOffset)); temp_reg, SharedFunctionInfo::kFormalParameterCountOffset));
ParameterCount expected(expected_reg); InvokeFunctionCode(fun, new_target, expected_reg, actual_parameter_count,
InvokeFunctionCode(fun, new_target, expected, actual, flag); flag);
} }
void MacroAssembler::InvokeFunction(Register function, void MacroAssembler::InvokeFunction(Register function,
const ParameterCount& expected, Register expected_parameter_count,
const ParameterCount& actual, Register actual_parameter_count,
InvokeFlag flag) { InvokeFlag flag) {
// You can't call a function without a valid frame. // You can't call a function without a valid frame.
DCHECK(flag == JUMP_FUNCTION || has_frame()); DCHECK_IMPLIES(flag == CALL_FUNCTION, has_frame());
// Contract with called JS functions requires that function is passed in r4. // Contract with called JS functions requires that function is passed in r4.
DCHECK(function == r4); DCHECK_EQ(function, r4);
// Get the function and setup the context. // Get the function and setup the context.
LoadP(cp, FieldMemOperand(r4, JSFunction::kContextOffset)); LoadP(cp, FieldMemOperand(r4, JSFunction::kContextOffset));
InvokeFunctionCode(r4, no_reg, expected, actual, flag); InvokeFunctionCode(r4, no_reg, expected_parameter_count,
actual_parameter_count, flag);
} }
void MacroAssembler::MaybeDropFrames() { void MacroAssembler::MaybeDropFrames() {
......
...@@ -749,21 +749,21 @@ class V8_EXPORT_PRIVATE MacroAssembler : public TurboAssembler { ...@@ -749,21 +749,21 @@ class V8_EXPORT_PRIVATE MacroAssembler : public TurboAssembler {
// Invoke the JavaScript function code by either calling or jumping. // Invoke the JavaScript function code by either calling or jumping.
void InvokeFunctionCode(Register function, Register new_target, void InvokeFunctionCode(Register function, Register new_target,
const ParameterCount& expected, Register expected_parameter_count,
const ParameterCount& actual, InvokeFlag flag); Register actual_parameter_count, InvokeFlag flag);
// On function call, call into the debugger if necessary. // On function call, call into the debugger if necessary.
void CheckDebugHook(Register fun, Register new_target, void CheckDebugHook(Register fun, Register new_target,
const ParameterCount& expected, Register expected_parameter_count,
const ParameterCount& actual); Register actual_parameter_count);
// Invoke the JavaScript function in the given register. Changes the // Invoke the JavaScript function in the given register. Changes the
// current context to the context in the function before invoking. // current context to the context in the function before invoking.
void InvokeFunction(Register function, Register new_target, void InvokeFunctionWithNewTarget(Register function, Register new_target,
const ParameterCount& actual, InvokeFlag flag); Register actual_parameter_count,
InvokeFlag flag);
void InvokeFunction(Register function, const ParameterCount& expected, void InvokeFunction(Register function, Register expected_parameter_count,
const ParameterCount& actual, InvokeFlag flag); Register actual_parameter_count, InvokeFlag flag);
void DebugBreak(); void DebugBreak();
// Frame restart support // Frame restart support
...@@ -950,9 +950,9 @@ class V8_EXPORT_PRIVATE MacroAssembler : public TurboAssembler { ...@@ -950,9 +950,9 @@ class V8_EXPORT_PRIVATE MacroAssembler : public TurboAssembler {
static const int kSmiShift = kSmiTagSize + kSmiShiftSize; static const int kSmiShift = kSmiTagSize + kSmiShiftSize;
// Helper functions for generating invokes. // Helper functions for generating invokes.
void InvokePrologue(const ParameterCount& expected, void InvokePrologue(Register expected_parameter_count,
const ParameterCount& actual, Label* done, Register actual_parameter_count, Label* done,
bool* definitely_mismatches, InvokeFlag flag); InvokeFlag flag);
// Compute memory operands for safepoint stack slots. // Compute memory operands for safepoint stack slots.
static int SafepointRegisterStackIndex(int reg_code); static int SafepointRegisterStackIndex(int reg_code);
......
...@@ -1268,12 +1268,9 @@ void TurboAssembler::PrepareForTailCall(const ParameterCount& callee_args_count, ...@@ -1268,12 +1268,9 @@ void TurboAssembler::PrepareForTailCall(const ParameterCount& callee_args_count,
LoadRR(sp, dst_reg); LoadRR(sp, dst_reg);
} }
void MacroAssembler::InvokePrologue(const ParameterCount& expected, void MacroAssembler::InvokePrologue(Register expected_parameter_count,
const ParameterCount& actual, Label* done, Register actual_parameter_count,
bool* definitely_mismatches, Label* done, InvokeFlag flag) {
InvokeFlag flag) {
bool definitely_matches = false;
*definitely_mismatches = false;
Label regular_invoke; Label regular_invoke;
// Check whether the expected and actual arguments count match. If not, // Check whether the expected and actual arguments count match. If not,
...@@ -1283,59 +1280,27 @@ void MacroAssembler::InvokePrologue(const ParameterCount& expected, ...@@ -1283,59 +1280,27 @@ void MacroAssembler::InvokePrologue(const ParameterCount& expected,
// r4: expected arguments count // r4: expected arguments count
// The code below is made a lot easier because the calling code already sets // The code below is made a lot easier because the calling code already sets
// up actual and expected registers according to the contract if values are // up actual and expected registers according to the contract.
// passed in registers.
// ARM has some sanity checks as per below, considering add them for S390 // ARM has some sanity checks as per below, considering add them for S390
DCHECK(actual.is_immediate() || actual.reg() == r2); DCHECK_EQ(actual_parameter_count, r2);
DCHECK(expected.is_immediate() || expected.reg() == r4); DCHECK_EQ(expected_parameter_count, r4);
if (expected.is_immediate()) { CmpP(expected_parameter_count, actual_parameter_count);
DCHECK(actual.is_immediate()); beq(&regular_invoke);
mov(r2, Operand(actual.immediate()));
if (expected.immediate() == actual.immediate()) { Handle<Code> adaptor = BUILTIN_CODE(isolate(), ArgumentsAdaptorTrampoline);
definitely_matches = true; if (flag == CALL_FUNCTION) {
} else { Call(adaptor);
const int sentinel = SharedFunctionInfo::kDontAdaptArgumentsSentinel; b(done);
if (expected.immediate() == sentinel) {
// Don't worry about adapting arguments for builtins that
// don't want that done. Skip adaption code by making it look
// like we have a match between expected and actual number of
// arguments.
definitely_matches = true;
} else {
*definitely_mismatches = true;
mov(r4, Operand(expected.immediate()));
}
}
} else { } else {
if (actual.is_immediate()) { Jump(adaptor, RelocInfo::CODE_TARGET);
mov(r2, Operand(actual.immediate()));
CmpPH(expected.reg(), Operand(actual.immediate()));
beq(&regular_invoke);
} else {
CmpP(expected.reg(), actual.reg());
beq(&regular_invoke);
}
} }
if (!definitely_matches) {
Handle<Code> adaptor = BUILTIN_CODE(isolate(), ArgumentsAdaptorTrampoline);
if (flag == CALL_FUNCTION) {
Call(adaptor);
if (!*definitely_mismatches) {
b(done);
}
} else {
Jump(adaptor, RelocInfo::CODE_TARGET);
}
bind(&regular_invoke); bind(&regular_invoke);
}
} }
void MacroAssembler::CheckDebugHook(Register fun, Register new_target, void MacroAssembler::CheckDebugHook(Register fun, Register new_target,
const ParameterCount& expected, Register expected_parameter_count,
const ParameterCount& actual) { Register actual_parameter_count) {
Label skip_hook; Label skip_hook;
ExternalReference debug_hook_active = ExternalReference debug_hook_active =
...@@ -1346,23 +1311,17 @@ void MacroAssembler::CheckDebugHook(Register fun, Register new_target, ...@@ -1346,23 +1311,17 @@ void MacroAssembler::CheckDebugHook(Register fun, Register new_target,
{ {
// Load receiver to pass it later to DebugOnFunctionCall hook. // Load receiver to pass it later to DebugOnFunctionCall hook.
if (actual.is_reg()) { ShiftLeftP(r6, actual_parameter_count, Operand(kSystemPointerSizeLog2));
ShiftLeftP(r6, actual.reg(), Operand(kSystemPointerSizeLog2)); LoadP(r6, MemOperand(sp, r6));
LoadP(r6, MemOperand(sp, r6));
} else {
LoadP(r6, MemOperand(sp, actual.immediate() << kSystemPointerSizeLog2),
ip);
}
FrameScope frame(this, FrameScope frame(this,
has_frame() ? StackFrame::NONE : StackFrame::INTERNAL); has_frame() ? StackFrame::NONE : StackFrame::INTERNAL);
if (expected.is_reg()) {
SmiTag(expected.reg()); SmiTag(expected_parameter_count);
Push(expected.reg()); Push(expected_parameter_count);
}
if (actual.is_reg()) { SmiTag(actual_parameter_count);
SmiTag(actual.reg()); Push(actual_parameter_count);
Push(actual.reg());
}
if (new_target.is_valid()) { if (new_target.is_valid()) {
Push(new_target); Push(new_target);
} }
...@@ -1372,30 +1331,28 @@ void MacroAssembler::CheckDebugHook(Register fun, Register new_target, ...@@ -1372,30 +1331,28 @@ void MacroAssembler::CheckDebugHook(Register fun, Register new_target,
if (new_target.is_valid()) { if (new_target.is_valid()) {
Pop(new_target); Pop(new_target);
} }
if (actual.is_reg()) {
Pop(actual.reg()); Pop(actual_parameter_count);
SmiUntag(actual.reg()); SmiUntag(actual_parameter_count);
}
if (expected.is_reg()) { Pop(expected_parameter_count);
Pop(expected.reg()); SmiUntag(expected_parameter_count);
SmiUntag(expected.reg());
}
} }
bind(&skip_hook); bind(&skip_hook);
} }
void MacroAssembler::InvokeFunctionCode(Register function, Register new_target, void MacroAssembler::InvokeFunctionCode(Register function, Register new_target,
const ParameterCount& expected, Register expected_parameter_count,
const ParameterCount& actual, Register actual_parameter_count,
InvokeFlag flag) { InvokeFlag flag) {
// You can't call a function without a valid frame. // You can't call a function without a valid frame.
DCHECK(flag == JUMP_FUNCTION || has_frame()); DCHECK_IMPLIES(flag == CALL_FUNCTION, has_frame());
DCHECK_EQ(function, r3);
DCHECK(function == r3);
DCHECK_IMPLIES(new_target.is_valid(), new_target == r5); DCHECK_IMPLIES(new_target.is_valid(), new_target == r5);
// On function call, call into the debugger if necessary. // On function call, call into the debugger if necessary.
CheckDebugHook(function, new_target, expected, actual); CheckDebugHook(function, new_target, expected_parameter_count,
actual_parameter_count);
// Clear the new.target register if not given. // Clear the new.target register if not given.
if (!new_target.is_valid()) { if (!new_target.is_valid()) {
...@@ -1403,35 +1360,32 @@ void MacroAssembler::InvokeFunctionCode(Register function, Register new_target, ...@@ -1403,35 +1360,32 @@ void MacroAssembler::InvokeFunctionCode(Register function, Register new_target,
} }
Label done; Label done;
bool definitely_mismatches = false; InvokePrologue(expected_parameter_count, actual_parameter_count, &done, flag);
InvokePrologue(expected, actual, &done, &definitely_mismatches, flag); // We call indirectly through the code field in the function to
if (!definitely_mismatches) { // allow recompilation to take effect without changing any of the
// We call indirectly through the code field in the function to // call sites.
// allow recompilation to take effect without changing any of the Register code = kJavaScriptCallCodeStartRegister;
// call sites. LoadP(code, FieldMemOperand(function, JSFunction::kCodeOffset));
Register code = kJavaScriptCallCodeStartRegister; if (flag == CALL_FUNCTION) {
LoadP(code, FieldMemOperand(function, JSFunction::kCodeOffset)); CallCodeObject(code);
if (flag == CALL_FUNCTION) { } else {
CallCodeObject(code); DCHECK(flag == JUMP_FUNCTION);
} else { JumpCodeObject(code);
DCHECK(flag == JUMP_FUNCTION); }
JumpCodeObject(code);
}
// Continue here if InvokePrologue does handle the invocation due to // Continue here if InvokePrologue does handle the invocation due to
// mismatched parameter counts. // mismatched parameter counts.
bind(&done); bind(&done);
}
} }
void MacroAssembler::InvokeFunction(Register fun, Register new_target, void MacroAssembler::InvokeFunctionWithNewTarget(
const ParameterCount& actual, Register fun, Register new_target, Register actual_parameter_count,
InvokeFlag flag) { InvokeFlag flag) {
// You can't call a function without a valid frame. // You can't call a function without a valid frame.
DCHECK(flag == JUMP_FUNCTION || has_frame()); DCHECK_IMPLIES(flag == CALL_FUNCTION, has_frame());
// Contract with called JS functions requires that function is passed in r3. // Contract with called JS functions requires that function is passed in r3.
DCHECK(fun == r3); DCHECK_EQ(fun, r3);
Register expected_reg = r4; Register expected_reg = r4;
Register temp_reg = r6; Register temp_reg = r6;
...@@ -1442,24 +1396,25 @@ void MacroAssembler::InvokeFunction(Register fun, Register new_target, ...@@ -1442,24 +1396,25 @@ void MacroAssembler::InvokeFunction(Register fun, Register new_target,
FieldMemOperand(temp_reg, FieldMemOperand(temp_reg,
SharedFunctionInfo::kFormalParameterCountOffset)); SharedFunctionInfo::kFormalParameterCountOffset));
ParameterCount expected(expected_reg); InvokeFunctionCode(fun, new_target, expected_reg, actual_parameter_count,
InvokeFunctionCode(fun, new_target, expected, actual, flag); flag);
} }
void MacroAssembler::InvokeFunction(Register function, void MacroAssembler::InvokeFunction(Register function,
const ParameterCount& expected, Register expected_parameter_count,
const ParameterCount& actual, Register actual_parameter_count,
InvokeFlag flag) { InvokeFlag flag) {
// You can't call a function without a valid frame. // You can't call a function without a valid frame.
DCHECK(flag == JUMP_FUNCTION || has_frame()); DCHECK_IMPLIES(flag == CALL_FUNCTION, has_frame());
// Contract with called JS functions requires that function is passed in r3. // Contract with called JS functions requires that function is passed in r3.
DCHECK(function == r3); DCHECK_EQ(function, r3);
// Get the function and setup the context. // Get the function and setup the context.
LoadP(cp, FieldMemOperand(r3, JSFunction::kContextOffset)); LoadP(cp, FieldMemOperand(r3, JSFunction::kContextOffset));
InvokeFunctionCode(r3, no_reg, expected, actual, flag); InvokeFunctionCode(r3, no_reg, expected_parameter_count,
actual_parameter_count, flag);
} }
void MacroAssembler::MaybeDropFrames() { void MacroAssembler::MaybeDropFrames() {
......
...@@ -1125,21 +1125,21 @@ class V8_EXPORT_PRIVATE MacroAssembler : public TurboAssembler { ...@@ -1125,21 +1125,21 @@ class V8_EXPORT_PRIVATE MacroAssembler : public TurboAssembler {
// Invoke the JavaScript function code by either calling or jumping. // Invoke the JavaScript function code by either calling or jumping.
void InvokeFunctionCode(Register function, Register new_target, void InvokeFunctionCode(Register function, Register new_target,
const ParameterCount& expected, Register expected_parameter_count,
const ParameterCount& actual, InvokeFlag flag); Register actual_parameter_count, InvokeFlag flag);
// On function call, call into the debugger if necessary. // On function call, call into the debugger if necessary.
void CheckDebugHook(Register fun, Register new_target, void CheckDebugHook(Register fun, Register new_target,
const ParameterCount& expected, Register expected_parameter_count,
const ParameterCount& actual); Register actual_parameter_count);
// Invoke the JavaScript function in the given register. Changes the // Invoke the JavaScript function in the given register. Changes the
// current context to the context in the function before invoking. // current context to the context in the function before invoking.
void InvokeFunction(Register function, Register new_target, void InvokeFunctionWithNewTarget(Register function, Register new_target,
const ParameterCount& actual, InvokeFlag flag); Register actual_parameter_count,
InvokeFlag flag);
void InvokeFunction(Register function, const ParameterCount& expected, void InvokeFunction(Register function, Register expected_parameter_count,
const ParameterCount& actual, InvokeFlag flag); Register actual_parameter_count, InvokeFlag flag);
// Frame restart support // Frame restart support
void MaybeDropFrames(); void MaybeDropFrames();
...@@ -1276,9 +1276,9 @@ class V8_EXPORT_PRIVATE MacroAssembler : public TurboAssembler { ...@@ -1276,9 +1276,9 @@ class V8_EXPORT_PRIVATE MacroAssembler : public TurboAssembler {
private: private:
static const int kSmiShift = kSmiTagSize + kSmiShiftSize; static const int kSmiShift = kSmiTagSize + kSmiShiftSize;
// Helper functions for generating invokes. // Helper functions for generating invokes.
void InvokePrologue(const ParameterCount& expected, void InvokePrologue(Register expected_parameter_count,
const ParameterCount& actual, Label* done, Register actual_parameter_count, Label* done,
bool* definitely_mismatches, InvokeFlag flag); InvokeFlag flag);
// Compute memory operands for safepoint stack slots. // Compute memory operands for safepoint stack slots.
static int SafepointRegisterStackIndex(int reg_code); static int SafepointRegisterStackIndex(int reg_code);
......
...@@ -41,9 +41,7 @@ void DebugCodegen::GenerateFrameDropperTrampoline(MacroAssembler* masm) { ...@@ -41,9 +41,7 @@ void DebugCodegen::GenerateFrameDropperTrampoline(MacroAssembler* masm) {
FieldMemOperand(r3, SharedFunctionInfo::kFormalParameterCountOffset)); FieldMemOperand(r3, SharedFunctionInfo::kFormalParameterCountOffset));
__ mr(r5, r3); __ mr(r5, r3);
ParameterCount dummy1(r5); __ InvokeFunction(r4, r5, r3, JUMP_FUNCTION);
ParameterCount dummy2(r3);
__ InvokeFunction(r4, dummy1, dummy2, JUMP_FUNCTION);
} }
const bool LiveEdit::kFrameDropperSupported = true; const bool LiveEdit::kFrameDropperSupported = true;
......
...@@ -43,9 +43,7 @@ void DebugCodegen::GenerateFrameDropperTrampoline(MacroAssembler* masm) { ...@@ -43,9 +43,7 @@ void DebugCodegen::GenerateFrameDropperTrampoline(MacroAssembler* masm) {
r2, FieldMemOperand(r2, SharedFunctionInfo::kFormalParameterCountOffset)); r2, FieldMemOperand(r2, SharedFunctionInfo::kFormalParameterCountOffset));
__ LoadRR(r4, r2); __ LoadRR(r4, r2);
ParameterCount dummy1(r4); __ InvokeFunction(r3, r4, r2, JUMP_FUNCTION);
ParameterCount dummy2(r2);
__ InvokeFunction(r3, dummy1, dummy2, JUMP_FUNCTION);
} }
const bool LiveEdit::kFrameDropperSupported = true; const bool LiveEdit::kFrameDropperSupported = true;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment