Commit 3c64400f authored by oth's avatar oth Committed by Commit bot

[interpreter] Unify meaning of register count operands.

Unifies the meaning of kRegCount8 and kRegCount16 across bytecodes.
Call and CallJSRuntime had a slightly different use of the register
count operand. From this change forth, register count operands are
always based off of the previous register operand.

BUG=v8:4280,v8:4675
LOG=N

Review URL: https://codereview.chromium.org/1659023002

Cr-Commit-Position: refs/heads/master@{#33707}
parent aff7bd54
......@@ -1111,8 +1111,8 @@ void BytecodeGraphBuilder::BuildCall() {
// TODO(ishell): provide correct tail_call_mode value to CallFunction.
const Operator* call = javascript()->CallFunction(
arg_count + 2, language_mode(), feedback, receiver_hint);
Node* value = ProcessCallArguments(call, callee, receiver, arg_count + 2);
arg_count + 1, language_mode(), feedback, receiver_hint);
Node* value = ProcessCallArguments(call, callee, receiver, arg_count + 1);
environment()->BindAccumulator(value, &states);
}
......@@ -1129,8 +1129,8 @@ void BytecodeGraphBuilder::BuildCallJSRuntime() {
// Create node to perform the JS runtime call.
const Operator* call =
javascript()->CallFunction(arg_count + 2, language_mode());
Node* value = ProcessCallArguments(call, callee, receiver, arg_count + 2);
javascript()->CallFunction(arg_count + 1, language_mode());
Node* value = ProcessCallArguments(call, callee, receiver, arg_count + 1);
environment()->BindAccumulator(value, &states);
}
......
......@@ -371,6 +371,9 @@ Node* InterpreterAssembler::IntPtrSub(Node* a, Node* b) {
return raw_assembler_->IntPtrSub(a, b);
}
Node* InterpreterAssembler::Int32Sub(Node* a, Node* b) {
return raw_assembler_->Int32Sub(a, b);
}
Node* InterpreterAssembler::WordShl(Node* value, int shift) {
return raw_assembler_->WordShl(value, Int32Constant(shift));
......
......@@ -88,6 +88,7 @@ class InterpreterAssembler {
// Basic arithmetic operations.
Node* IntPtrAdd(Node* a, Node* b);
Node* IntPtrSub(Node* a, Node* b);
Node* Int32Sub(Node* a, Node* b);
Node* WordShl(Node* value, int shift);
// Load constant at |index| in the constant pool.
......
......@@ -1051,21 +1051,24 @@ void BytecodeArrayBuilder::EnsureReturn() {
}
}
BytecodeArrayBuilder& BytecodeArrayBuilder::Call(Register callable,
Register receiver,
size_t arg_count,
Register receiver_args,
size_t receiver_args_count,
int feedback_slot) {
if (FitsInReg8Operand(callable) && FitsInReg8Operand(receiver) &&
FitsInIdx8Operand(arg_count) && FitsInIdx8Operand(feedback_slot)) {
Output(Bytecode::kCall, callable.ToRawOperand(), receiver.ToRawOperand(),
static_cast<uint8_t>(arg_count),
if (FitsInReg8Operand(callable) && FitsInReg8Operand(receiver_args) &&
FitsInIdx8Operand(receiver_args_count) &&
FitsInIdx8Operand(feedback_slot)) {
Output(Bytecode::kCall, callable.ToRawOperand(),
receiver_args.ToRawOperand(),
static_cast<uint8_t>(receiver_args_count),
static_cast<uint8_t>(feedback_slot));
} else if (FitsInReg16Operand(callable) && FitsInReg16Operand(receiver) &&
FitsInIdx16Operand(arg_count) &&
} else if (FitsInReg16Operand(callable) &&
FitsInReg16Operand(receiver_args) &&
FitsInIdx16Operand(receiver_args_count) &&
FitsInIdx16Operand(feedback_slot)) {
Output(Bytecode::kCallWide, callable.ToRawOperand(),
receiver.ToRawOperand(), static_cast<uint16_t>(arg_count),
receiver_args.ToRawOperand(),
static_cast<uint16_t>(receiver_args_count),
static_cast<uint16_t>(feedback_slot));
} else {
UNIMPLEMENTED();
......@@ -1142,17 +1145,19 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntimeForPair(
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::CallJSRuntime(int context_index,
Register receiver,
size_t arg_count) {
BytecodeArrayBuilder& BytecodeArrayBuilder::CallJSRuntime(
int context_index, Register receiver_args, size_t receiver_args_count) {
DCHECK(FitsInIdx16Operand(context_index));
if (FitsInReg8Operand(receiver) && FitsInIdx8Operand(arg_count)) {
if (FitsInReg8Operand(receiver_args) &&
FitsInIdx8Operand(receiver_args_count)) {
Output(Bytecode::kCallJSRuntime, static_cast<uint16_t>(context_index),
receiver.ToRawOperand(), static_cast<uint8_t>(arg_count));
} else if (FitsInReg16Operand(receiver) && FitsInIdx16Operand(arg_count)) {
receiver_args.ToRawOperand(),
static_cast<uint8_t>(receiver_args_count));
} else if (FitsInReg16Operand(receiver_args) &&
FitsInIdx16Operand(receiver_args_count)) {
Output(Bytecode::kCallJSRuntimeWide, static_cast<uint16_t>(context_index),
receiver.ToRawOperand(), static_cast<uint16_t>(arg_count));
receiver_args.ToRawOperand(),
static_cast<uint16_t>(receiver_args_count));
} else {
UNIMPLEMENTED();
}
......
......@@ -164,11 +164,11 @@ class BytecodeArrayBuilder final : public ZoneObject, private RegisterMover {
BytecodeArrayBuilder& PopContext(Register context);
// Call a JS function. The JSFunction or Callable to be called should be in
// |callable|, the receiver should be in |receiver| and all subsequent
// arguments should be in registers <receiver + 1> to
// <receiver + 1 + arg_count>.
BytecodeArrayBuilder& Call(Register callable, Register receiver,
size_t arg_count, int feedback_slot);
// |callable|, the receiver should be in |receiver_args| and all subsequent
// arguments should be in registers <receiver_args + 1> to
// <receiver_args + receiver_arg_count - 1>.
BytecodeArrayBuilder& Call(Register callable, Register receiver_args,
size_t receiver_arg_count, int feedback_slot);
// Call the new operator. The |constructor| register is followed by
// |arg_count| consecutive registers containing arguments to be
......@@ -178,23 +178,23 @@ class BytecodeArrayBuilder final : public ZoneObject, private RegisterMover {
// Call the runtime function with |function_id|. The first argument should be
// in |first_arg| and all subsequent arguments should be in registers
// <first_arg + 1> to <first_arg + 1 + arg_count>.
// <first_arg + 1> to <first_arg + arg_count - 1>.
BytecodeArrayBuilder& CallRuntime(Runtime::FunctionId function_id,
Register first_arg, size_t arg_count);
// Call the runtime function with |function_id| that returns a pair of values.
// The first argument should be in |first_arg| and all subsequent arguments
// should be in registers <first_arg + 1> to <first_arg + 1 + arg_count>. The
// should be in registers <first_arg + 1> to <first_arg + arg_count - 1>. The
// return values will be returned in <first_return> and <first_return + 1>.
BytecodeArrayBuilder& CallRuntimeForPair(Runtime::FunctionId function_id,
Register first_arg, size_t arg_count,
Register first_return);
// Call the JS runtime function with |context_index|. The the receiver should
// be in |receiver| and all subsequent arguments should be in registers
// <receiver + 1> to <receiver + 1 + arg_count>.
BytecodeArrayBuilder& CallJSRuntime(int context_index, Register receiver,
size_t arg_count);
// be in |receiver_args| and all subsequent arguments should be in registers
// <receiver + 1> to <receiver + receiver_args_count - 1>.
BytecodeArrayBuilder& CallJSRuntime(int context_index, Register receiver_args,
size_t receiver_args_count);
// Operators (register holds the lhs value, accumulator holds the rhs value).
BytecodeArrayBuilder& BinaryOperation(Token::Value binop, Register reg,
......
......@@ -128,9 +128,6 @@ int BytecodeArrayIterator::GetRegisterOperandRange(int operand_index) const {
default: {
if (operand_index + 1 !=
Bytecodes::NumberOfOperands(current_bytecode())) {
// TODO(oth): Ensure all bytecodes specify the full range of registers
// with kRegCount (currently Call/CallJSRuntime are off by one due to
// reciever.
OperandType next_operand_type =
Bytecodes::GetOperandType(current_bytecode(), operand_index + 1);
if (Bytecodes::IsRegisterCountOperandType(next_operand_type)) {
......
......@@ -1956,7 +1956,7 @@ void BytecodeGenerator::VisitCall(Call* expr) {
}
// TODO(rmcilroy): Use CallIC to allow call type feedback.
builder()->Call(callee, receiver, args->length(),
builder()->Call(callee, receiver, 1 + args->length(),
feedback_index(expr->CallFeedbackICSlot()));
execution_result()->SetResultInAccumulator();
}
......@@ -1976,20 +1976,18 @@ void BytecodeGenerator::VisitCallNew(CallNew* expr) {
void BytecodeGenerator::VisitCallRuntime(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
Register receiver;
if (expr->is_jsruntime()) {
// Allocate a register for the receiver and load it with undefined.
register_allocator()->PrepareForConsecutiveAllocations(args->length() + 1);
receiver = register_allocator()->NextConsecutiveRegister();
register_allocator()->PrepareForConsecutiveAllocations(1 + args->length());
Register receiver = register_allocator()->NextConsecutiveRegister();
builder()->LoadUndefined().StoreAccumulatorInRegister(receiver);
}
// Evaluate all arguments to the runtime call.
Register first_arg = VisitArguments(args);
if (expr->is_jsruntime()) {
DCHECK(args->length() == 0 || first_arg.index() == receiver.index() + 1);
builder()->CallJSRuntime(expr->context_index(), receiver, args->length());
Register first_arg = VisitArguments(args);
CHECK(args->length() == 0 || first_arg.index() == receiver.index() + 1);
builder()->CallJSRuntime(expr->context_index(), receiver,
1 + args->length());
} else {
// Evaluate all arguments to the runtime call.
Register first_arg = VisitArguments(args);
Runtime::FunctionId function_id = expr->function()->function_id;
builder()->CallRuntime(function_id, first_arg, args->length());
}
......
......@@ -1078,10 +1078,12 @@ void Interpreter::DoJSCall(compiler::InterpreterAssembler* assembler) {
Node* function_reg = __ BytecodeOperandReg(0);
Node* function = __ LoadRegister(function_reg);
Node* receiver_reg = __ BytecodeOperandReg(1);
Node* first_arg = __ RegisterLocation(receiver_reg);
Node* args_count = __ BytecodeOperandCount(2);
Node* receiver_arg = __ RegisterLocation(receiver_reg);
Node* receiver_args_count = __ BytecodeOperandCount(2);
Node* receiver_count = __ Int32Constant(1);
Node* args_count = __ Int32Sub(receiver_args_count, receiver_count);
// TODO(rmcilroy): Use the call type feedback slot to call via CallIC.
Node* result = __ CallJS(function, first_arg, args_count);
Node* result = __ CallJS(function, receiver_arg, args_count);
__ SetAccumulator(result);
__ Dispatch();
}
......@@ -1186,7 +1188,9 @@ void Interpreter::DoCallJSRuntimeCommon(
Node* context_index = __ BytecodeOperandIdx(0);
Node* receiver_reg = __ BytecodeOperandReg(1);
Node* first_arg = __ RegisterLocation(receiver_reg);
Node* args_count = __ BytecodeOperandCount(2);
Node* receiver_args_count = __ BytecodeOperandCount(2);
Node* receiver_count = __ Int32Constant(1);
Node* args_count = __ Int32Sub(receiver_args_count, receiver_count);
// Get the function to call from the native context.
Node* context = __ GetContext();
......
......@@ -941,7 +941,7 @@ TEST(InterpreterCall) {
0, 1);
builder.LoadNamedProperty(builder.Parameter(0), name, slot_index, i::SLOPPY)
.StoreAccumulatorInRegister(Register(0))
.Call(Register(0), builder.Parameter(0), 0, 0)
.Call(Register(0), builder.Parameter(0), 1, 0)
.Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
......@@ -960,7 +960,7 @@ TEST(InterpreterCall) {
0, 1);
builder.LoadNamedProperty(builder.Parameter(0), name, slot_index, i::SLOPPY)
.StoreAccumulatorInRegister(Register(0))
.Call(Register(0), builder.Parameter(0), 0, 0)
.Call(Register(0), builder.Parameter(0), 1, 0)
.Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
......@@ -988,7 +988,7 @@ TEST(InterpreterCall) {
.StoreAccumulatorInRegister(Register(2))
.LoadLiteral(Smi::FromInt(11))
.StoreAccumulatorInRegister(Register(3))
.Call(Register(0), Register(1), 2, 0)
.Call(Register(0), Register(1), 3, 0)
.Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
......@@ -1031,7 +1031,7 @@ TEST(InterpreterCall) {
.StoreAccumulatorInRegister(Register(10))
.LoadLiteral(factory->NewStringFromAsciiChecked("j"))
.StoreAccumulatorInRegister(Register(11))
.Call(Register(0), Register(1), 10, 0)
.Call(Register(0), Register(1), 11, 0)
.Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
......
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