v8/src/interpreter/bytecode-traits.h
rmcilroy e5ac75c635 [Interpreter] Optimize BytecodeArrayBuilder and BytecodeArrayWriter.
This CL optimizes the code in BytecodeArrayBuilder and
BytecodeArrayWriter by making the following main changes:

 - Move operand scale calculation out of BytecodeArrayWriter to the
BytecodeNode constructor, where the decision on which operands are
scalable can generally be statically decided by the compiler.
 - Move the maximum register calculation out of BytecodeArrayWriter
and into BytecodeRegisterOptimizer (which is the only place outside
BytecodeGenerator which updates which registers are used). This
avoids the BytecodeArrayWriter needing to know the operand types
of a node as it writes it.
 - Modify EmitBytecodes to use individual push_backs rather than
building a buffer and calling insert, since this turns out to be faster.
 - Initialize BytecodeArrayWriter's bytecode vector by reserving 512
bytes,
 - Make common functions in Bytecodes constexpr so that they
can be statically calculated by the compiler.
 - Move common functions and constructors in Bytecodes and
BytecodeNode to the header so that they can be inlined.
 - Change large static switch statements in Bytecodes to const array
lookups, and move to the header to allow inlining.

I also took the opportunity to remove a number of unused helper
functions, and rework some others for consistency.

This reduces the percentage of time spent in making BytecodeArrays
 in  CodeLoad from ~15% to ~11% according to perf. The
CoadLoad score increase by around 2%.

BUG=v8:4280

Committed: https://crrev.com/b11a8b4d41bf09d6b3d6cf214fe3fb61faf01a64
Review-Url: https://codereview.chromium.org/2351763002
Cr-Original-Commit-Position: refs/heads/master@{#39599}
Cr-Commit-Position: refs/heads/master@{#39637}
2016-09-22 16:34:31 +00:00

156 lines
6.4 KiB
C++

// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_INTERPRETER_BYTECODE_TRAITS_H_
#define V8_INTERPRETER_BYTECODE_TRAITS_H_
#include "src/interpreter/bytecode-operands.h"
namespace v8 {
namespace internal {
namespace interpreter {
template <OperandTypeInfo>
struct OperandTypeInfoTraits {
static const bool kIsScalable = false;
static const bool kIsUnsigned = false;
static const OperandSize kUnscaledSize = OperandSize::kNone;
};
#define DECLARE_OPERAND_TYPE_INFO(Name, Scalable, Unsigned, BaseSize) \
template <> \
struct OperandTypeInfoTraits<OperandTypeInfo::k##Name> { \
static const bool kIsScalable = Scalable; \
static const bool kIsUnsigned = Unsigned; \
static const OperandSize kUnscaledSize = BaseSize; \
};
OPERAND_TYPE_INFO_LIST(DECLARE_OPERAND_TYPE_INFO)
#undef DECLARE_OPERAND_TYPE_INFO
template <OperandType>
struct OperandTraits {
typedef OperandTypeInfoTraits<OperandTypeInfo::kNone> TypeInfoTraits;
static const OperandTypeInfo kOperandTypeInfo = OperandTypeInfo::kNone;
};
#define DECLARE_OPERAND_TYPE_TRAITS(Name, InfoType) \
template <> \
struct OperandTraits<OperandType::k##Name> { \
typedef OperandTypeInfoTraits<InfoType> TypeInfoTraits; \
static const OperandTypeInfo kOperandTypeInfo = InfoType; \
};
OPERAND_TYPE_LIST(DECLARE_OPERAND_TYPE_TRAITS)
#undef DECLARE_OPERAND_TYPE_TRAITS
template <OperandType operand_type, OperandScale operand_scale>
struct OperandScaler {
template <bool, OperandSize, OperandScale>
struct Helper {
static const int kSize = 0;
};
template <OperandSize size, OperandScale scale>
struct Helper<false, size, scale> {
static const int kSize = static_cast<int>(size);
};
template <OperandSize size, OperandScale scale>
struct Helper<true, size, scale> {
static const int kSize = static_cast<int>(size) * static_cast<int>(scale);
};
static const int kSize =
Helper<OperandTraits<operand_type>::TypeInfoTraits::kIsScalable,
OperandTraits<operand_type>::TypeInfoTraits::kUnscaledSize,
operand_scale>::kSize;
static const OperandSize kOperandSize = static_cast<OperandSize>(kSize);
};
template <int... values>
struct SumHelper;
template <int value>
struct SumHelper<value> {
static const int kValue = value;
};
template <int value, int... values>
struct SumHelper<value, values...> {
static const int kValue = value + SumHelper<values...>::kValue;
};
template <AccumulatorUse accumulator_use, OperandType... operands>
struct BytecodeTraits {
static const OperandType kOperandTypes[];
static const OperandTypeInfo kOperandTypeInfos[];
static const OperandSize kSingleScaleOperandSizes[];
static const OperandSize kDoubleScaleOperandSizes[];
static const OperandSize kQuadrupleScaleOperandSizes[];
static const int kSingleScaleSize = SumHelper<
1, OperandScaler<operands, OperandScale::kSingle>::kSize...>::kValue;
static const int kDoubleScaleSize = SumHelper<
1, OperandScaler<operands, OperandScale::kDouble>::kSize...>::kValue;
static const int kQuadrupleScaleSize = SumHelper<
1, OperandScaler<operands, OperandScale::kQuadruple>::kSize...>::kValue;
static const AccumulatorUse kAccumulatorUse = accumulator_use;
static const int kOperandCount = sizeof...(operands);
};
template <AccumulatorUse accumulator_use, OperandType... operands>
STATIC_CONST_MEMBER_DEFINITION const OperandType
BytecodeTraits<accumulator_use, operands...>::kOperandTypes[] = {
operands...};
template <AccumulatorUse accumulator_use, OperandType... operands>
STATIC_CONST_MEMBER_DEFINITION const OperandTypeInfo
BytecodeTraits<accumulator_use, operands...>::kOperandTypeInfos[] = {
OperandTraits<operands>::kOperandTypeInfo...};
template <AccumulatorUse accumulator_use, OperandType... operands>
STATIC_CONST_MEMBER_DEFINITION const OperandSize
BytecodeTraits<accumulator_use, operands...>::kSingleScaleOperandSizes[] = {
OperandScaler<operands, OperandScale::kSingle>::kOperandSize...};
template <AccumulatorUse accumulator_use, OperandType... operands>
STATIC_CONST_MEMBER_DEFINITION const OperandSize
BytecodeTraits<accumulator_use, operands...>::kDoubleScaleOperandSizes[] = {
OperandScaler<operands, OperandScale::kDouble>::kOperandSize...};
template <AccumulatorUse accumulator_use, OperandType... operands>
STATIC_CONST_MEMBER_DEFINITION const OperandSize BytecodeTraits<
accumulator_use, operands...>::kQuadrupleScaleOperandSizes[] = {
OperandScaler<operands, OperandScale::kQuadruple>::kOperandSize...};
template <AccumulatorUse accumulator_use>
struct BytecodeTraits<accumulator_use> {
static const OperandType kOperandTypes[];
static const OperandTypeInfo kOperandTypeInfos[];
static const OperandSize kSingleScaleOperandSizes[];
static const OperandSize kDoubleScaleOperandSizes[];
static const OperandSize kQuadrupleScaleOperandSizes[];
static const int kSingleScaleSize = 1;
static const int kDoubleScaleSize = 1;
static const int kQuadrupleScaleSize = 1;
static const AccumulatorUse kAccumulatorUse = accumulator_use;
static const int kOperandCount = 0;
};
template <AccumulatorUse accumulator_use>
STATIC_CONST_MEMBER_DEFINITION const OperandType
BytecodeTraits<accumulator_use>::kOperandTypes[] = {OperandType::kNone};
template <AccumulatorUse accumulator_use>
STATIC_CONST_MEMBER_DEFINITION const OperandTypeInfo
BytecodeTraits<accumulator_use>::kOperandTypeInfos[] = {
OperandTypeInfo::kNone};
template <AccumulatorUse accumulator_use>
STATIC_CONST_MEMBER_DEFINITION const OperandSize
BytecodeTraits<accumulator_use>::kSingleScaleOperandSizes[] = {
OperandSize::kNone};
template <AccumulatorUse accumulator_use>
STATIC_CONST_MEMBER_DEFINITION const OperandSize
BytecodeTraits<accumulator_use>::kDoubleScaleOperandSizes[] = {
OperandSize::kNone};
template <AccumulatorUse accumulator_use>
STATIC_CONST_MEMBER_DEFINITION const OperandSize
BytecodeTraits<accumulator_use>::kQuadrupleScaleOperandSizes[] = {
OperandSize::kNone};
} // namespace interpreter
} // namespace internal
} // namespace v8
#endif // V8_INTERPRETER_BYTECODE_TRAITS_H_