Commit 6003ed04 authored by rmcilroy's avatar rmcilroy Committed by Commit bot

Reland: [Interpreter] Map runtime id's to intrinsic id's in InvokeIntrinsic bytecode.

Make intrinsic ids a contiguous set of ids so that the switch statement can build
a table switch rather than doing a large if/else tree.

BUG=v8:4822
LOG=N

Committed: https://crrev.com/36abd28a8d9932eb55d7c2bf3ad5e7cfe3eb99ea
Review-Url: https://codereview.chromium.org/2084623002
Cr-Original-Commit-Position: refs/heads/master@{#37135}
Cr-Commit-Position: refs/heads/master@{#37145}
parent dacc5a73
......@@ -1001,8 +1001,7 @@ Node* BytecodeGraphBuilder::ProcessCallRuntimeArguments(
void BytecodeGraphBuilder::VisitCallRuntime() {
FrameStateBeforeAndAfter states(this);
Runtime::FunctionId functionId = static_cast<Runtime::FunctionId>(
bytecode_iterator().GetRuntimeIdOperand(0));
Runtime::FunctionId functionId = bytecode_iterator().GetRuntimeIdOperand(0);
interpreter::Register first_arg = bytecode_iterator().GetRegisterOperand(1);
size_t arg_count = bytecode_iterator().GetRegisterCountOperand(2);
......@@ -1014,8 +1013,7 @@ void BytecodeGraphBuilder::VisitCallRuntime() {
void BytecodeGraphBuilder::VisitCallRuntimeForPair() {
FrameStateBeforeAndAfter states(this);
Runtime::FunctionId functionId = static_cast<Runtime::FunctionId>(
bytecode_iterator().GetRuntimeIdOperand(0));
Runtime::FunctionId functionId = bytecode_iterator().GetRuntimeIdOperand(0);
interpreter::Register first_arg = bytecode_iterator().GetRegisterOperand(1);
size_t arg_count = bytecode_iterator().GetRegisterCountOperand(2);
interpreter::Register first_return =
......@@ -1029,8 +1027,7 @@ void BytecodeGraphBuilder::VisitCallRuntimeForPair() {
void BytecodeGraphBuilder::VisitInvokeIntrinsic() {
FrameStateBeforeAndAfter states(this);
Runtime::FunctionId functionId = static_cast<Runtime::FunctionId>(
bytecode_iterator().GetRuntimeIdOperand(0));
Runtime::FunctionId functionId = bytecode_iterator().GetIntrinsicIdOperand(0);
interpreter::Register first_arg = bytecode_iterator().GetRegisterOperand(1);
size_t arg_count = bytecode_iterator().GetRegisterCountOperand(2);
......
......@@ -581,11 +581,16 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime(
DCHECK_EQ(0u, arg_count);
first_arg = Register(0);
}
Bytecode bytecode = IntrinsicsHelper::IsSupported(function_id)
? Bytecode::kInvokeIntrinsic
: Bytecode::kCallRuntime;
Output(bytecode, static_cast<uint16_t>(function_id),
RegisterOperand(first_arg), UnsignedOperand(arg_count));
Bytecode bytecode;
uint32_t id;
if (IntrinsicsHelper::IsSupported(function_id)) {
bytecode = Bytecode::kInvokeIntrinsic;
id = static_cast<uint32_t>(IntrinsicsHelper::FromRuntimeId(function_id));
} else {
bytecode = Bytecode::kCallRuntime;
id = static_cast<uint32_t>(function_id);
}
Output(bytecode, id, RegisterOperand(first_arg), UnsignedOperand(arg_count));
return *this;
}
......@@ -694,6 +699,7 @@ bool BytecodeArrayBuilder::OperandsAreValid(
break;
}
case OperandType::kFlag8:
case OperandType::kIntrinsicId:
if (Bytecodes::SizeForUnsignedOperand(operands[i]) >
OperandSize::kByte) {
return false;
......
......@@ -4,6 +4,7 @@
#include "src/interpreter/bytecode-array-iterator.h"
#include "src/interpreter/interpreter-intrinsics.h"
#include "src/objects-inl.h"
namespace v8 {
......@@ -140,11 +141,23 @@ int BytecodeArrayIterator::GetRegisterOperandRange(int operand_index) const {
}
}
uint32_t BytecodeArrayIterator::GetRuntimeIdOperand(int operand_index) const {
Runtime::FunctionId BytecodeArrayIterator::GetRuntimeIdOperand(
int operand_index) const {
OperandType operand_type =
Bytecodes::GetOperandType(current_bytecode(), operand_index);
DCHECK(operand_type == OperandType::kRuntimeId);
return GetUnsignedOperand(operand_index, operand_type);
uint32_t raw_id = GetUnsignedOperand(operand_index, operand_type);
return static_cast<Runtime::FunctionId>(raw_id);
}
Runtime::FunctionId BytecodeArrayIterator::GetIntrinsicIdOperand(
int operand_index) const {
OperandType operand_type =
Bytecodes::GetOperandType(current_bytecode(), operand_index);
DCHECK(operand_type == OperandType::kIntrinsicId);
uint32_t raw_id = GetUnsignedOperand(operand_index, operand_type);
return IntrinsicsHelper::ToRuntimeId(
static_cast<IntrinsicsHelper::IntrinsicId>(raw_id));
}
Handle<Object> BytecodeArrayIterator::GetConstantForIndexOperand(
......
......@@ -8,6 +8,7 @@
#include "src/handles.h"
#include "src/interpreter/bytecodes.h"
#include "src/objects.h"
#include "src/runtime/runtime.h"
namespace v8 {
namespace internal {
......@@ -34,7 +35,8 @@ class BytecodeArrayIterator {
uint32_t GetRegisterCountOperand(int operand_index) const;
Register GetRegisterOperand(int operand_index) const;
int GetRegisterOperandRange(int operand_index) const;
uint32_t GetRuntimeIdOperand(int operand_index) const;
Runtime::FunctionId GetRuntimeIdOperand(int operand_index) const;
Runtime::FunctionId GetIntrinsicIdOperand(int operand_index) const;
Handle<Object> GetConstantForIndexOperand(int operand_index) const;
// Returns the absolute offset of the branch target at the current
......
......@@ -737,6 +737,7 @@ std::ostream& Bytecodes::Decode(std::ostream& os, const uint8_t* bytecode_start,
break;
case interpreter::OperandType::kIdx:
case interpreter::OperandType::kRuntimeId:
case interpreter::OperandType::kIntrinsicId:
os << "["
<< DecodeUnsignedOperand(operand_start, op_type, operand_scale)
<< "]";
......
......@@ -30,6 +30,7 @@ namespace interpreter {
#define SCALAR_OPERAND_TYPE_LIST(V) \
V(Flag8, OperandTypeInfo::kFixedUnsignedByte) \
V(IntrinsicId, OperandTypeInfo::kFixedUnsignedByte) \
V(Idx, OperandTypeInfo::kScalableUnsignedByte) \
V(Imm, OperandTypeInfo::kScalableSignedByte) \
V(RegCount, OperandTypeInfo::kScalableUnsignedByte) \
......@@ -180,7 +181,7 @@ namespace interpreter {
OperandType::kReg, OperandType::kRegCount) \
\
/* Intrinsics */ \
V(InvokeIntrinsic, AccumulatorUse::kWrite, OperandType::kRuntimeId, \
V(InvokeIntrinsic, AccumulatorUse::kWrite, OperandType::kIntrinsicId, \
OperandType::kMaybeReg, OperandType::kRegCount) \
\
/* New operator */ \
......
......@@ -363,6 +363,15 @@ Node* InterpreterAssembler::BytecodeOperandRuntimeId(int operand_index) {
return BytecodeUnsignedOperand(operand_index, operand_size);
}
Node* InterpreterAssembler::BytecodeOperandIntrinsicId(int operand_index) {
DCHECK(OperandType::kIntrinsicId ==
Bytecodes::GetOperandType(bytecode_, operand_index));
OperandSize operand_size =
Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale());
DCHECK_EQ(operand_size, OperandSize::kByte);
return BytecodeUnsignedOperand(operand_index, operand_size);
}
Node* InterpreterAssembler::LoadConstantPoolEntry(Node* index) {
Node* constant_pool = LoadObjectField(BytecodeArrayTaggedPointer(),
BytecodeArray::kConstantPoolOffset);
......
......@@ -41,6 +41,9 @@ class InterpreterAssembler : public CodeStubAssembler {
// Returns the runtime id immediate for bytecode operand
// |operand_index| in the current bytecode.
compiler::Node* BytecodeOperandRuntimeId(int operand_index);
// Returns the intrinsic id immediate for bytecode operand
// |operand_index| in the current bytecode.
compiler::Node* BytecodeOperandIntrinsicId(int operand_index);
// Accumulator.
compiler::Node* GetAccumulator();
......
......@@ -15,6 +15,7 @@ using compiler::Node;
IntrinsicsHelper::IntrinsicsHelper(InterpreterAssembler* assembler)
: assembler_(assembler) {}
// static
bool IntrinsicsHelper::IsSupported(Runtime::FunctionId function_id) {
switch (function_id) {
#define SUPPORTED(name, lower_case, count) case Runtime::kInline##name:
......@@ -26,6 +27,36 @@ bool IntrinsicsHelper::IsSupported(Runtime::FunctionId function_id) {
}
}
// static
IntrinsicsHelper::IntrinsicId IntrinsicsHelper::FromRuntimeId(
Runtime::FunctionId function_id) {
switch (function_id) {
#define TO_RUNTIME_ID(name, lower_case, count) \
case Runtime::kInline##name: \
return IntrinsicId::k##name;
INTRINSICS_LIST(TO_RUNTIME_ID)
#undef TO_RUNTIME_ID
default:
UNREACHABLE();
return static_cast<IntrinsicsHelper::IntrinsicId>(-1);
}
}
// static
Runtime::FunctionId IntrinsicsHelper::ToRuntimeId(
IntrinsicsHelper::IntrinsicId intrinsic_id) {
switch (intrinsic_id) {
#define TO_INTRINSIC_ID(name, lower_case, count) \
case IntrinsicId::k##name: \
return Runtime::kInline##name;
INTRINSICS_LIST(TO_INTRINSIC_ID)
#undef TO_INTRINSIC_ID
default:
UNREACHABLE();
return static_cast<Runtime::FunctionId>(-1);
}
}
Node* IntrinsicsHelper::InvokeIntrinsic(Node* function_id, Node* context,
Node* first_arg_reg, Node* arg_count) {
InterpreterAssembler::Label abort(assembler_), end(assembler_);
......@@ -42,7 +73,7 @@ Node* IntrinsicsHelper::InvokeIntrinsic(Node* function_id, Node* context,
#undef LABEL_POINTER
#define CASE(name, lower_case, count) \
static_cast<int32_t>(Runtime::kInline##name),
static_cast<int32_t>(IntrinsicId::k##name),
int32_t cases[] = {INTRINSICS_LIST(CASE)};
#undef CASE
......
......@@ -20,6 +20,8 @@ namespace compiler {
class Node;
} // namespace compiler
namespace interpreter {
// List of supported intrisics, with upper case name, lower case name and
// expected number of arguments (-1 denoting argument count is variable).
#define INTRINSICS_LIST(V) \
......@@ -31,10 +33,16 @@ class Node;
V(IsSmi, is_smi, 1) \
V(IsTypedArray, is_typed_array, 1)
namespace interpreter {
class IntrinsicsHelper {
public:
enum class IntrinsicId {
#define DECLARE_INTRINSIC_ID(name, lower_case, count) k##name,
INTRINSICS_LIST(DECLARE_INTRINSIC_ID)
#undef DECLARE_INTRINSIC_ID
kIdCount
};
STATIC_ASSERT(static_cast<uint32_t>(IntrinsicId::kIdCount) <= kMaxUInt8);
explicit IntrinsicsHelper(InterpreterAssembler* assembler);
compiler::Node* InvokeIntrinsic(compiler::Node* function_id,
......@@ -43,6 +51,8 @@ class IntrinsicsHelper {
compiler::Node* arg_count);
static bool IsSupported(Runtime::FunctionId function_id);
static IntrinsicId FromRuntimeId(Runtime::FunctionId function_id);
static Runtime::FunctionId ToRuntimeId(IntrinsicId intrinsic_id);
private:
enum InstanceTypeCompareMode {
......
......@@ -1045,7 +1045,7 @@ void Interpreter::DoCallRuntime(InterpreterAssembler* assembler) {
// |function_id| with the first argument in |first_arg| and |arg_count|
// arguments in subsequent registers.
void Interpreter::DoInvokeIntrinsic(InterpreterAssembler* assembler) {
Node* function_id = __ BytecodeOperandRuntimeId(0);
Node* function_id = __ BytecodeOperandIntrinsicId(0);
Node* first_arg_reg = __ BytecodeOperandReg(1);
Node* arg_count = __ BytecodeOperandCount(2);
Node* context = __ GetContext();
......
......@@ -19,6 +19,7 @@
#include "src/interpreter/bytecode-array-iterator.h"
#include "src/interpreter/bytecode-generator.h"
#include "src/interpreter/bytecodes.h"
#include "src/interpreter/interpreter-intrinsics.h"
#include "src/interpreter/interpreter.h"
#include "src/interpreter/source-position-table.h"
......@@ -98,12 +99,6 @@ void BytecodeExpectationsPrinter::PrintEscapedString(
}
}
namespace {
i::Runtime::FunctionId IndexToFunctionId(uint32_t index) {
return static_cast<i::Runtime::FunctionId>(index);
}
} // namespace
void BytecodeExpectationsPrinter::PrintBytecodeOperand(
std::ostream& stream, const BytecodeArrayIterator& bytecode_iterator,
const Bytecode& bytecode, int op_index, int parameter_count) const {
......@@ -164,9 +159,15 @@ void BytecodeExpectationsPrinter::PrintBytecodeOperand(
stream << bytecode_iterator.GetRegisterCountOperand(op_index);
break;
case OperandType::kRuntimeId: {
uint32_t operand = bytecode_iterator.GetRuntimeIdOperand(op_index);
stream << "Runtime::k"
<< i::Runtime::FunctionForId(IndexToFunctionId(operand))->name;
Runtime::FunctionId id =
bytecode_iterator.GetRuntimeIdOperand(op_index);
stream << "Runtime::k" << i::Runtime::FunctionForId(id)->name;
break;
}
case OperandType::kIntrinsicId: {
Runtime::FunctionId id =
bytecode_iterator.GetIntrinsicIdOperand(op_index);
stream << "Runtime::k" << i::Runtime::FunctionForId(id)->name;
break;
}
default:
......
......@@ -265,7 +265,7 @@ snippet: "
"
frame size: 17
parameter count: 1
bytecode array length: 779
bytecode array length: 775
bytecodes: [
B(Ldar), R(new_target),
B(JumpIfUndefined), U8(26),
......@@ -353,7 +353,7 @@ bytecodes: [
/* 27 E> */ B(Call), R(12), R(13), U8(1), U8(5),
/* 27 E> */ B(StaContextSlot), R(1), U8(8),
B(Star), R(11),
B(InvokeIntrinsic), U16(Runtime::k_IsJSReceiver), R(11), U8(1),
B(InvokeIntrinsic), U8(Runtime::k_IsJSReceiver), R(11), U8(1),
B(ToBooleanLogicalNot),
B(JumpIfFalse), U8(11),
B(LdrContextSlot), R(1), U8(8), R(11),
......@@ -426,7 +426,7 @@ bytecodes: [
B(PopContext), R(2),
B(LdaZero),
B(StaContextSlot), R(1), U8(9),
B(Wide), B(Jump), U16(-223),
B(Wide), B(Jump), U16(-222),
B(Jump), U8(46),
B(Star), R(12),
B(LdaConstant), U8(11),
......@@ -468,11 +468,11 @@ bytecodes: [
B(LdaNull),
B(TestEqual), R(10),
B(JumpIfFalse), U8(4),
B(Jump), U8(127),
B(Jump), U8(124),
B(LdrContextSlot), R(1), U8(9), R(10),
B(LdaSmi), U8(1),
B(TestEqualStrict), R(10),
B(JumpIfFalse), U8(79),
B(JumpIfFalse), U8(78),
B(LdaContextSlot), R(1), U8(11),
B(TypeOf),
B(Star), R(10),
......@@ -489,7 +489,7 @@ bytecodes: [
B(Mov), R(context), R(10),
B(LdrContextSlot), R(1), U8(11), R(11),
B(LdrContextSlot), R(1), U8(7), R(12),
B(InvokeIntrinsic), U16(Runtime::k_Call), R(11), U8(2),
B(InvokeIntrinsic), U8(Runtime::k_Call), R(11), U8(2),
B(Jump), U8(29),
B(Star), R(12),
B(LdaConstant), U8(11),
......@@ -501,13 +501,13 @@ bytecodes: [
B(Ldar), R(10),
B(PushContext), R(2),
B(PopContext), R(2),
B(Jump), U8(40),
B(Jump), U8(38),
B(LdrContextSlot), R(1), U8(11), R(10),
B(LdrContextSlot), R(1), U8(7), R(11),
B(InvokeIntrinsic), U16(Runtime::k_Call), R(10), U8(2),
B(InvokeIntrinsic), U8(Runtime::k_Call), R(10), U8(2),
B(StaContextSlot), R(1), U8(12),
B(LdrContextSlot), R(1), U8(12), R(10),
B(InvokeIntrinsic), U16(Runtime::k_IsJSReceiver), R(10), U8(1),
B(InvokeIntrinsic), U8(Runtime::k_IsJSReceiver), R(10), U8(1),
B(JumpIfToBooleanFalse), U8(4),
B(Jump), U8(11),
B(LdrContextSlot), R(1), U8(12), R(10),
......@@ -601,9 +601,9 @@ constant pool: [
kInstanceTypeDontCare,
]
handlers: [
[44, 698, 704],
[154, 449, 455],
[157, 403, 405],
[552, 565, 567],
[44, 694, 700],
[154, 448, 454],
[157, 402, 404],
[551, 563, 565],
]
......@@ -229,8 +229,7 @@ TEST_F(BytecodeArrayIteratorTest, IteratesBytecodeArray) {
CHECK_EQ(iterator.current_bytecode(), Bytecode::kCallRuntime);
CHECK_EQ(iterator.current_offset(), offset);
CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
CHECK_EQ(static_cast<Runtime::FunctionId>(iterator.GetRuntimeIdOperand(0)),
Runtime::kLoadIC_Miss);
CHECK_EQ(iterator.GetRuntimeIdOperand(0), Runtime::kLoadIC_Miss);
CHECK_EQ(iterator.GetRegisterOperand(1).index(), reg_0.index());
CHECK_EQ(iterator.GetRegisterCountOperand(2), 1);
CHECK(!iterator.done());
......
......@@ -428,6 +428,10 @@ TARGET_TEST_F(InterpreterAssemblerTest, BytecodeOperand) {
EXPECT_THAT(m.BytecodeOperandRuntimeId(i),
m.IsUnsignedOperand(offset, operand_size));
break;
case interpreter::OperandType::kIntrinsicId:
EXPECT_THAT(m.BytecodeOperandIntrinsicId(i),
m.IsUnsignedOperand(offset, operand_size));
break;
case interpreter::OperandType::kNone:
UNREACHABLE();
break;
......
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