Revert of [interpreter] Reduce dependencies in bytecodes.{h,cc} (patchset #8 id:140001 of https://codereview.chromium.org/2135273002/ )
Reason for revert: Breaks the roll, possibly win gn: https://codereview.chromium.org/2148863002/ Original issue's description: > [interpreter] Reduce dependencies in bytecodes.{h,cc} > > This CL reduces the number of dependencies bytecodes.{h,cc} to facilitate > generating the bytecode peephole optimizer table during build. Specifically, > it avoids depending on v8_base. > > BUG=v8:4280 > LOG=N > > Committed: https://crrev.com/4edebb1cd870ae6c1359ad54f83e618e185883b1 > Cr-Commit-Position: refs/heads/master@{#37715} TBR=mstarzinger@chromium.org,rmcilroy@chromium.org,oth@chromium.org # Skipping CQ checks because original CL landed less than 1 days ago. NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true BUG=v8:4280 Review-Url: https://codereview.chromium.org/2151693003 Cr-Commit-Position: refs/heads/master@{#37743}
This commit is contained in:
parent
e6a195d4dd
commit
8aaa91efe6
6
BUILD.gn
6
BUILD.gn
@ -1282,10 +1282,6 @@ v8_source_set("v8_base") {
|
||||
"src/interpreter/bytecode-array-writer.h",
|
||||
"src/interpreter/bytecode-dead-code-optimizer.cc",
|
||||
"src/interpreter/bytecode-dead-code-optimizer.h",
|
||||
"src/interpreter/bytecode-decoder.cc",
|
||||
"src/interpreter/bytecode-decoder.h",
|
||||
"src/interpreter/bytecode-flags.cc",
|
||||
"src/interpreter/bytecode-flags.h",
|
||||
"src/interpreter/bytecode-generator.cc",
|
||||
"src/interpreter/bytecode-generator.h",
|
||||
"src/interpreter/bytecode-label.h",
|
||||
@ -1297,8 +1293,6 @@ v8_source_set("v8_base") {
|
||||
"src/interpreter/bytecode-register-allocator.h",
|
||||
"src/interpreter/bytecode-register-optimizer.cc",
|
||||
"src/interpreter/bytecode-register-optimizer.h",
|
||||
"src/interpreter/bytecode-register.cc",
|
||||
"src/interpreter/bytecode-register.h",
|
||||
"src/interpreter/bytecode-traits.h",
|
||||
"src/interpreter/bytecodes.cc",
|
||||
"src/interpreter/bytecodes.h",
|
||||
|
3
src/DEPS
3
src/DEPS
@ -10,9 +10,6 @@ include_rules = [
|
||||
"+src/heap/heap-inl.h",
|
||||
"-src/interpreter",
|
||||
"+src/interpreter/bytecode-array-iterator.h",
|
||||
"+src/interpreter/bytecode-decoder.h",
|
||||
"+src/interpreter/bytecode-flags.h",
|
||||
"+src/interpreter/bytecode-register.h",
|
||||
"+src/interpreter/bytecodes.h",
|
||||
"+src/interpreter/interpreter.h",
|
||||
"-src/libplatform",
|
||||
|
@ -9,7 +9,6 @@
|
||||
#include "src/compiler/bytecode-branch-analysis.h"
|
||||
#include "src/compiler/js-graph.h"
|
||||
#include "src/interpreter/bytecode-array-iterator.h"
|
||||
#include "src/interpreter/bytecode-flags.h"
|
||||
#include "src/interpreter/bytecodes.h"
|
||||
|
||||
namespace v8 {
|
||||
|
@ -4,7 +4,6 @@
|
||||
|
||||
#include "src/extensions/ignition-statistics-extension.h"
|
||||
|
||||
#include "src/base/logging.h"
|
||||
#include "src/interpreter/bytecodes.h"
|
||||
#include "src/interpreter/interpreter.h"
|
||||
#include "src/isolate.h"
|
||||
|
@ -8,7 +8,6 @@
|
||||
#include "src/ast/ast.h"
|
||||
#include "src/interpreter/bytecode-array-writer.h"
|
||||
#include "src/interpreter/bytecode-register-allocator.h"
|
||||
#include "src/interpreter/bytecode-register.h"
|
||||
#include "src/interpreter/bytecodes.h"
|
||||
#include "src/interpreter/constant-array-builder.h"
|
||||
#include "src/interpreter/handler-table-builder.h"
|
||||
|
@ -4,7 +4,6 @@
|
||||
|
||||
#include "src/interpreter/bytecode-array-iterator.h"
|
||||
|
||||
#include "src/interpreter/bytecode-decoder.h"
|
||||
#include "src/interpreter/interpreter-intrinsics.h"
|
||||
#include "src/objects-inl.h"
|
||||
|
||||
@ -71,8 +70,8 @@ uint32_t BytecodeArrayIterator::GetUnsignedOperand(
|
||||
current_prefix_offset() +
|
||||
Bytecodes::GetOperandOffset(current_bytecode(), operand_index,
|
||||
current_operand_scale());
|
||||
return BytecodeDecoder::DecodeUnsignedOperand(operand_start, operand_type,
|
||||
current_operand_scale());
|
||||
return Bytecodes::DecodeUnsignedOperand(operand_start, operand_type,
|
||||
current_operand_scale());
|
||||
}
|
||||
|
||||
int32_t BytecodeArrayIterator::GetSignedOperand(
|
||||
@ -87,8 +86,8 @@ int32_t BytecodeArrayIterator::GetSignedOperand(
|
||||
current_prefix_offset() +
|
||||
Bytecodes::GetOperandOffset(current_bytecode(), operand_index,
|
||||
current_operand_scale());
|
||||
return BytecodeDecoder::DecodeSignedOperand(operand_start, operand_type,
|
||||
current_operand_scale());
|
||||
return Bytecodes::DecodeSignedOperand(operand_start, operand_type,
|
||||
current_operand_scale());
|
||||
}
|
||||
|
||||
uint32_t BytecodeArrayIterator::GetFlagOperand(int operand_index) const {
|
||||
@ -125,8 +124,8 @@ Register BytecodeArrayIterator::GetRegisterOperand(int operand_index) const {
|
||||
current_prefix_offset() +
|
||||
Bytecodes::GetOperandOffset(current_bytecode(), operand_index,
|
||||
current_operand_scale());
|
||||
return BytecodeDecoder::DecodeRegisterOperand(operand_start, operand_type,
|
||||
current_operand_scale());
|
||||
return Bytecodes::DecodeRegisterOperand(operand_start, operand_type,
|
||||
current_operand_scale());
|
||||
}
|
||||
|
||||
int BytecodeArrayIterator::GetRegisterOperandRange(int operand_index) const {
|
||||
|
@ -6,7 +6,6 @@
|
||||
#define V8_INTERPRETER_BYTECODE_ARRAY_ITERATOR_H_
|
||||
|
||||
#include "src/handles.h"
|
||||
#include "src/interpreter/bytecode-register.h"
|
||||
#include "src/interpreter/bytecodes.h"
|
||||
#include "src/objects.h"
|
||||
#include "src/runtime/runtime.h"
|
||||
|
@ -6,7 +6,6 @@
|
||||
|
||||
#include "src/api.h"
|
||||
#include "src/interpreter/bytecode-label.h"
|
||||
#include "src/interpreter/bytecode-register.h"
|
||||
#include "src/interpreter/constant-array-builder.h"
|
||||
#include "src/log.h"
|
||||
|
||||
|
@ -1,157 +0,0 @@
|
||||
// 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.
|
||||
|
||||
#include "src/interpreter/bytecode-decoder.h"
|
||||
|
||||
#include <iomanip>
|
||||
|
||||
#include "src/utils.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
namespace interpreter {
|
||||
|
||||
// static
|
||||
Register BytecodeDecoder::DecodeRegisterOperand(const uint8_t* operand_start,
|
||||
OperandType operand_type,
|
||||
OperandScale operand_scale) {
|
||||
DCHECK(Bytecodes::IsRegisterOperandType(operand_type));
|
||||
int32_t operand =
|
||||
DecodeSignedOperand(operand_start, operand_type, operand_scale);
|
||||
return Register::FromOperand(operand);
|
||||
}
|
||||
|
||||
// static
|
||||
int32_t BytecodeDecoder::DecodeSignedOperand(const uint8_t* operand_start,
|
||||
OperandType operand_type,
|
||||
OperandScale operand_scale) {
|
||||
DCHECK(!Bytecodes::IsUnsignedOperandType(operand_type));
|
||||
switch (Bytecodes::SizeOfOperand(operand_type, operand_scale)) {
|
||||
case OperandSize::kByte:
|
||||
return static_cast<int8_t>(*operand_start);
|
||||
case OperandSize::kShort:
|
||||
return static_cast<int16_t>(ReadUnalignedUInt16(operand_start));
|
||||
case OperandSize::kQuad:
|
||||
return static_cast<int32_t>(ReadUnalignedUInt32(operand_start));
|
||||
case OperandSize::kNone:
|
||||
UNREACHABLE();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// static
|
||||
uint32_t BytecodeDecoder::DecodeUnsignedOperand(const uint8_t* operand_start,
|
||||
OperandType operand_type,
|
||||
OperandScale operand_scale) {
|
||||
DCHECK(Bytecodes::IsUnsignedOperandType(operand_type));
|
||||
switch (Bytecodes::SizeOfOperand(operand_type, operand_scale)) {
|
||||
case OperandSize::kByte:
|
||||
return *operand_start;
|
||||
case OperandSize::kShort:
|
||||
return ReadUnalignedUInt16(operand_start);
|
||||
case OperandSize::kQuad:
|
||||
return ReadUnalignedUInt32(operand_start);
|
||||
case OperandSize::kNone:
|
||||
UNREACHABLE();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// static
|
||||
std::ostream& BytecodeDecoder::Decode(std::ostream& os,
|
||||
const uint8_t* bytecode_start,
|
||||
int parameter_count) {
|
||||
Bytecode bytecode = Bytecodes::FromByte(bytecode_start[0]);
|
||||
int prefix_offset = 0;
|
||||
OperandScale operand_scale = OperandScale::kSingle;
|
||||
if (Bytecodes::IsPrefixScalingBytecode(bytecode)) {
|
||||
prefix_offset = 1;
|
||||
operand_scale = Bytecodes::PrefixBytecodeToOperandScale(bytecode);
|
||||
bytecode = Bytecodes::FromByte(bytecode_start[1]);
|
||||
}
|
||||
|
||||
// Prepare to print bytecode and operands as hex digits.
|
||||
std::ios saved_format(nullptr);
|
||||
saved_format.copyfmt(saved_format);
|
||||
os.fill('0');
|
||||
os.flags(std::ios::hex);
|
||||
|
||||
int bytecode_size = Bytecodes::Size(bytecode, operand_scale);
|
||||
for (int i = 0; i < prefix_offset + bytecode_size; i++) {
|
||||
os << std::setw(2) << static_cast<uint32_t>(bytecode_start[i]) << ' ';
|
||||
}
|
||||
os.copyfmt(saved_format);
|
||||
|
||||
const int kBytecodeColumnSize = 6;
|
||||
for (int i = prefix_offset + bytecode_size; i < kBytecodeColumnSize; i++) {
|
||||
os << " ";
|
||||
}
|
||||
|
||||
os << Bytecodes::ToString(bytecode, operand_scale) << " ";
|
||||
|
||||
// Operands for the debug break are from the original instruction.
|
||||
if (Bytecodes::IsDebugBreak(bytecode)) return os;
|
||||
|
||||
int number_of_operands = Bytecodes::NumberOfOperands(bytecode);
|
||||
int range = 0;
|
||||
for (int i = 0; i < number_of_operands; i++) {
|
||||
OperandType op_type = Bytecodes::GetOperandType(bytecode, i);
|
||||
int operand_offset =
|
||||
Bytecodes::GetOperandOffset(bytecode, i, operand_scale);
|
||||
const uint8_t* operand_start =
|
||||
&bytecode_start[prefix_offset + operand_offset];
|
||||
switch (op_type) {
|
||||
case interpreter::OperandType::kRegCount:
|
||||
os << "#"
|
||||
<< DecodeUnsignedOperand(operand_start, op_type, operand_scale);
|
||||
break;
|
||||
case interpreter::OperandType::kIdx:
|
||||
case interpreter::OperandType::kRuntimeId:
|
||||
case interpreter::OperandType::kIntrinsicId:
|
||||
os << "["
|
||||
<< DecodeUnsignedOperand(operand_start, op_type, operand_scale)
|
||||
<< "]";
|
||||
break;
|
||||
case interpreter::OperandType::kImm:
|
||||
os << "[" << DecodeSignedOperand(operand_start, op_type, operand_scale)
|
||||
<< "]";
|
||||
break;
|
||||
case interpreter::OperandType::kFlag8:
|
||||
os << "#"
|
||||
<< DecodeUnsignedOperand(operand_start, op_type, operand_scale);
|
||||
break;
|
||||
case interpreter::OperandType::kMaybeReg:
|
||||
case interpreter::OperandType::kReg:
|
||||
case interpreter::OperandType::kRegOut: {
|
||||
Register reg =
|
||||
DecodeRegisterOperand(operand_start, op_type, operand_scale);
|
||||
os << reg.ToString(parameter_count);
|
||||
break;
|
||||
}
|
||||
case interpreter::OperandType::kRegOutTriple:
|
||||
range += 1;
|
||||
case interpreter::OperandType::kRegOutPair:
|
||||
case interpreter::OperandType::kRegPair: {
|
||||
range += 1;
|
||||
Register first_reg =
|
||||
DecodeRegisterOperand(operand_start, op_type, operand_scale);
|
||||
Register last_reg = Register(first_reg.index() + range);
|
||||
os << first_reg.ToString(parameter_count) << "-"
|
||||
<< last_reg.ToString(parameter_count);
|
||||
break;
|
||||
}
|
||||
case interpreter::OperandType::kNone:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
if (i != number_of_operands - 1) {
|
||||
os << ", ";
|
||||
}
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
} // namespace interpreter
|
||||
} // namespace internal
|
||||
} // namespace v8
|
@ -1,43 +0,0 @@
|
||||
// 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_DECODER_H_
|
||||
#define V8_INTERPRETER_BYTECODE_DECODER_H_
|
||||
|
||||
#include <iosfwd>
|
||||
|
||||
#include "src/interpreter/bytecode-register.h"
|
||||
#include "src/interpreter/bytecodes.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
namespace interpreter {
|
||||
|
||||
class BytecodeDecoder final {
|
||||
public:
|
||||
// Decodes a register operand in a byte array.
|
||||
static Register DecodeRegisterOperand(const uint8_t* operand_start,
|
||||
OperandType operand_type,
|
||||
OperandScale operand_scale);
|
||||
|
||||
// Decodes a signed operand in a byte array.
|
||||
static int32_t DecodeSignedOperand(const uint8_t* operand_start,
|
||||
OperandType operand_type,
|
||||
OperandScale operand_scale);
|
||||
|
||||
// Decodes an unsigned operand in a byte array.
|
||||
static uint32_t DecodeUnsignedOperand(const uint8_t* operand_start,
|
||||
OperandType operand_type,
|
||||
OperandScale operand_scale);
|
||||
|
||||
// Decode a single bytecode and operands to |os|.
|
||||
static std::ostream& Decode(std::ostream& os, const uint8_t* bytecode_start,
|
||||
int number_of_parameters);
|
||||
};
|
||||
|
||||
} // namespace interpreter
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
||||
#endif // V8_INTERPRETER_BYTECODE_DECODER_H_
|
@ -1,42 +0,0 @@
|
||||
// Copyright 2016 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.
|
||||
|
||||
#include "src/interpreter/bytecode-flags.h"
|
||||
|
||||
#include "src/code-stubs.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
namespace interpreter {
|
||||
|
||||
// static
|
||||
uint8_t CreateObjectLiteralFlags::Encode(bool fast_clone_supported,
|
||||
int properties_count,
|
||||
int runtime_flags) {
|
||||
uint8_t result = FlagsBits::encode(runtime_flags);
|
||||
if (fast_clone_supported) {
|
||||
STATIC_ASSERT(
|
||||
FastCloneShallowObjectStub::kMaximumClonedProperties <=
|
||||
1 << CreateObjectLiteralFlags::FastClonePropertiesCountBits::kShift);
|
||||
DCHECK_LE(properties_count,
|
||||
FastCloneShallowObjectStub::kMaximumClonedProperties);
|
||||
result |= CreateObjectLiteralFlags::FastClonePropertiesCountBits::encode(
|
||||
properties_count);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// static
|
||||
uint8_t CreateClosureFlags::Encode(bool pretenure, bool is_function_scope) {
|
||||
uint8_t result = PretenuredBit::encode(pretenure);
|
||||
if (!FLAG_always_opt && !FLAG_prepare_always_opt &&
|
||||
pretenure == NOT_TENURED && is_function_scope) {
|
||||
result |= FastNewClosureBit::encode(true);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace interpreter
|
||||
} // namespace internal
|
||||
} // namespace v8
|
@ -1,42 +0,0 @@
|
||||
// Copyright 2016 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_FLAGS_H_
|
||||
#define V8_INTERPRETER_BYTECODE_FLAGS_H_
|
||||
|
||||
#include "src/utils.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
namespace interpreter {
|
||||
|
||||
class CreateObjectLiteralFlags {
|
||||
public:
|
||||
class FlagsBits : public BitField8<int, 0, 3> {};
|
||||
class FastClonePropertiesCountBits
|
||||
: public BitField8<int, FlagsBits::kNext, 3> {};
|
||||
|
||||
static uint8_t Encode(bool fast_clone_supported, int properties_count,
|
||||
int runtime_flags);
|
||||
|
||||
private:
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(CreateObjectLiteralFlags);
|
||||
};
|
||||
|
||||
class CreateClosureFlags {
|
||||
public:
|
||||
class PretenuredBit : public BitField8<bool, 0, 1> {};
|
||||
class FastNewClosureBit : public BitField8<bool, PretenuredBit::kNext, 1> {};
|
||||
|
||||
static uint8_t Encode(bool pretenure, bool is_function_scope);
|
||||
|
||||
private:
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(CreateClosureFlags);
|
||||
};
|
||||
|
||||
} // namespace interpreter
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
||||
#endif // V8_INTERPRETER_BYTECODE_FLAGS_H_
|
@ -7,7 +7,6 @@
|
||||
#include "src/ast/scopes.h"
|
||||
#include "src/code-stubs.h"
|
||||
#include "src/compiler.h"
|
||||
#include "src/interpreter/bytecode-flags.h"
|
||||
#include "src/interpreter/bytecode-register-allocator.h"
|
||||
#include "src/interpreter/control-flow-builders.h"
|
||||
#include "src/objects.h"
|
||||
|
@ -8,7 +8,6 @@
|
||||
#include "src/ast/ast.h"
|
||||
#include "src/interpreter/bytecode-array-builder.h"
|
||||
#include "src/interpreter/bytecode-label.h"
|
||||
#include "src/interpreter/bytecode-register.h"
|
||||
#include "src/interpreter/bytecodes.h"
|
||||
|
||||
namespace v8 {
|
||||
|
@ -6,9 +6,7 @@
|
||||
#define V8_INTERPRETER_BYTECODE_PIPELINE_H_
|
||||
|
||||
#include "src/interpreter/bytecode-register-allocator.h"
|
||||
#include "src/interpreter/bytecode-register.h"
|
||||
#include "src/interpreter/bytecodes.h"
|
||||
#include "src/objects.h"
|
||||
#include "src/zone-containers.h"
|
||||
|
||||
namespace v8 {
|
||||
|
@ -1,149 +0,0 @@
|
||||
// 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.
|
||||
|
||||
#include "src/interpreter/bytecode-register.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
namespace interpreter {
|
||||
|
||||
static const int kLastParamRegisterIndex =
|
||||
(InterpreterFrameConstants::kRegisterFileFromFp -
|
||||
InterpreterFrameConstants::kLastParamFromFp) /
|
||||
kPointerSize;
|
||||
static const int kFunctionClosureRegisterIndex =
|
||||
(InterpreterFrameConstants::kRegisterFileFromFp -
|
||||
StandardFrameConstants::kFunctionOffset) /
|
||||
kPointerSize;
|
||||
static const int kCurrentContextRegisterIndex =
|
||||
(InterpreterFrameConstants::kRegisterFileFromFp -
|
||||
StandardFrameConstants::kContextOffset) /
|
||||
kPointerSize;
|
||||
static const int kNewTargetRegisterIndex =
|
||||
(InterpreterFrameConstants::kRegisterFileFromFp -
|
||||
InterpreterFrameConstants::kNewTargetFromFp) /
|
||||
kPointerSize;
|
||||
static const int kBytecodeArrayRegisterIndex =
|
||||
(InterpreterFrameConstants::kRegisterFileFromFp -
|
||||
InterpreterFrameConstants::kBytecodeArrayFromFp) /
|
||||
kPointerSize;
|
||||
static const int kBytecodeOffsetRegisterIndex =
|
||||
(InterpreterFrameConstants::kRegisterFileFromFp -
|
||||
InterpreterFrameConstants::kBytecodeOffsetFromFp) /
|
||||
kPointerSize;
|
||||
static const int kCallerPCOffsetRegisterIndex =
|
||||
(InterpreterFrameConstants::kRegisterFileFromFp -
|
||||
InterpreterFrameConstants::kCallerPCOffsetFromFp) /
|
||||
kPointerSize;
|
||||
|
||||
Register Register::FromParameterIndex(int index, int parameter_count) {
|
||||
DCHECK_GE(index, 0);
|
||||
DCHECK_LT(index, parameter_count);
|
||||
int register_index = kLastParamRegisterIndex - parameter_count + index + 1;
|
||||
DCHECK_LT(register_index, 0);
|
||||
return Register(register_index);
|
||||
}
|
||||
|
||||
int Register::ToParameterIndex(int parameter_count) const {
|
||||
DCHECK(is_parameter());
|
||||
return index() - kLastParamRegisterIndex + parameter_count - 1;
|
||||
}
|
||||
|
||||
Register Register::function_closure() {
|
||||
return Register(kFunctionClosureRegisterIndex);
|
||||
}
|
||||
|
||||
bool Register::is_function_closure() const {
|
||||
return index() == kFunctionClosureRegisterIndex;
|
||||
}
|
||||
|
||||
Register Register::current_context() {
|
||||
return Register(kCurrentContextRegisterIndex);
|
||||
}
|
||||
|
||||
bool Register::is_current_context() const {
|
||||
return index() == kCurrentContextRegisterIndex;
|
||||
}
|
||||
|
||||
Register Register::new_target() { return Register(kNewTargetRegisterIndex); }
|
||||
|
||||
bool Register::is_new_target() const {
|
||||
return index() == kNewTargetRegisterIndex;
|
||||
}
|
||||
|
||||
Register Register::bytecode_array() {
|
||||
return Register(kBytecodeArrayRegisterIndex);
|
||||
}
|
||||
|
||||
bool Register::is_bytecode_array() const {
|
||||
return index() == kBytecodeArrayRegisterIndex;
|
||||
}
|
||||
|
||||
Register Register::bytecode_offset() {
|
||||
return Register(kBytecodeOffsetRegisterIndex);
|
||||
}
|
||||
|
||||
bool Register::is_bytecode_offset() const {
|
||||
return index() == kBytecodeOffsetRegisterIndex;
|
||||
}
|
||||
|
||||
// static
|
||||
Register Register::virtual_accumulator() {
|
||||
return Register(kCallerPCOffsetRegisterIndex);
|
||||
}
|
||||
|
||||
OperandSize Register::SizeOfOperand() const {
|
||||
int32_t operand = ToOperand();
|
||||
if (operand >= kMinInt8 && operand <= kMaxInt8) {
|
||||
return OperandSize::kByte;
|
||||
} else if (operand >= kMinInt16 && operand <= kMaxInt16) {
|
||||
return OperandSize::kShort;
|
||||
} else {
|
||||
return OperandSize::kQuad;
|
||||
}
|
||||
}
|
||||
|
||||
bool Register::AreContiguous(Register reg1, Register reg2, Register reg3,
|
||||
Register reg4, Register reg5) {
|
||||
if (reg1.index() + 1 != reg2.index()) {
|
||||
return false;
|
||||
}
|
||||
if (reg3.is_valid() && reg2.index() + 1 != reg3.index()) {
|
||||
return false;
|
||||
}
|
||||
if (reg4.is_valid() && reg3.index() + 1 != reg4.index()) {
|
||||
return false;
|
||||
}
|
||||
if (reg5.is_valid() && reg4.index() + 1 != reg5.index()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string Register::ToString(int parameter_count) {
|
||||
if (is_current_context()) {
|
||||
return std::string("<context>");
|
||||
} else if (is_function_closure()) {
|
||||
return std::string("<closure>");
|
||||
} else if (is_new_target()) {
|
||||
return std::string("<new.target>");
|
||||
} else if (is_parameter()) {
|
||||
int parameter_index = ToParameterIndex(parameter_count);
|
||||
if (parameter_index == 0) {
|
||||
return std::string("<this>");
|
||||
} else {
|
||||
std::ostringstream s;
|
||||
s << "a" << parameter_index - 1;
|
||||
return s.str();
|
||||
}
|
||||
} else {
|
||||
std::ostringstream s;
|
||||
s << "r" << index();
|
||||
return s.str();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace interpreter
|
||||
} // namespace internal
|
||||
} // namespace v8
|
@ -1,104 +0,0 @@
|
||||
// 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_REGISTER_H_
|
||||
#define V8_INTERPRETER_BYTECODE_REGISTER_H_
|
||||
|
||||
#include "src/frames.h"
|
||||
#include "src/interpreter/bytecodes.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
namespace interpreter {
|
||||
|
||||
// An interpreter Register which is located in the function's Register file
|
||||
// in its stack-frame. Register hold parameters, this, and expression values.
|
||||
class Register final {
|
||||
public:
|
||||
explicit Register(int index = kInvalidIndex) : index_(index) {}
|
||||
|
||||
int index() const { return index_; }
|
||||
bool is_parameter() const { return index() < 0; }
|
||||
bool is_valid() const { return index_ != kInvalidIndex; }
|
||||
|
||||
static Register FromParameterIndex(int index, int parameter_count);
|
||||
int ToParameterIndex(int parameter_count) const;
|
||||
|
||||
// Returns an invalid register.
|
||||
static Register invalid_value() { return Register(); }
|
||||
|
||||
// Returns the register for the function's closure object.
|
||||
static Register function_closure();
|
||||
bool is_function_closure() const;
|
||||
|
||||
// Returns the register which holds the current context object.
|
||||
static Register current_context();
|
||||
bool is_current_context() const;
|
||||
|
||||
// Returns the register for the incoming new target value.
|
||||
static Register new_target();
|
||||
bool is_new_target() const;
|
||||
|
||||
// Returns the register for the bytecode array.
|
||||
static Register bytecode_array();
|
||||
bool is_bytecode_array() const;
|
||||
|
||||
// Returns the register for the saved bytecode offset.
|
||||
static Register bytecode_offset();
|
||||
bool is_bytecode_offset() const;
|
||||
|
||||
// Returns a register that can be used to represent the accumulator
|
||||
// within code in the interpreter, but should never be emitted in
|
||||
// bytecode.
|
||||
static Register virtual_accumulator();
|
||||
|
||||
OperandSize SizeOfOperand() const;
|
||||
|
||||
int32_t ToOperand() const { return kRegisterFileStartOffset - index_; }
|
||||
static Register FromOperand(int32_t operand) {
|
||||
return Register(kRegisterFileStartOffset - operand);
|
||||
}
|
||||
|
||||
static bool AreContiguous(Register reg1, Register reg2,
|
||||
Register reg3 = Register(),
|
||||
Register reg4 = Register(),
|
||||
Register reg5 = Register());
|
||||
|
||||
std::string ToString(int parameter_count);
|
||||
|
||||
bool operator==(const Register& other) const {
|
||||
return index() == other.index();
|
||||
}
|
||||
bool operator!=(const Register& other) const {
|
||||
return index() != other.index();
|
||||
}
|
||||
bool operator<(const Register& other) const {
|
||||
return index() < other.index();
|
||||
}
|
||||
bool operator<=(const Register& other) const {
|
||||
return index() <= other.index();
|
||||
}
|
||||
bool operator>(const Register& other) const {
|
||||
return index() > other.index();
|
||||
}
|
||||
bool operator>=(const Register& other) const {
|
||||
return index() >= other.index();
|
||||
}
|
||||
|
||||
private:
|
||||
static const int kInvalidIndex = kMaxInt;
|
||||
static const int kRegisterFileStartOffset =
|
||||
InterpreterFrameConstants::kRegisterFileFromFp / kPointerSize;
|
||||
|
||||
void* operator new(size_t size) = delete;
|
||||
void operator delete(void* p) = delete;
|
||||
|
||||
int index_;
|
||||
};
|
||||
|
||||
} // namespace interpreter
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
||||
#endif // V8_INTERPRETER_BYTECODE_REGISTER_H_
|
@ -7,8 +7,10 @@
|
||||
#include <iomanip>
|
||||
|
||||
#include "src/base/bits.h"
|
||||
#include "src/globals.h"
|
||||
#include "src/code-stubs.h"
|
||||
#include "src/frames.h"
|
||||
#include "src/interpreter/bytecode-traits.h"
|
||||
#include "src/interpreter/interpreter.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
@ -101,12 +103,6 @@ const char* Bytecodes::OperandSizeToString(OperandSize operand_size) {
|
||||
return "";
|
||||
}
|
||||
|
||||
// static
|
||||
uint8_t Bytecodes::ToByte(Bytecode bytecode) {
|
||||
DCHECK_LE(bytecode, Bytecode::kLast);
|
||||
return static_cast<uint8_t>(bytecode);
|
||||
}
|
||||
|
||||
// static
|
||||
Bytecode Bytecodes::FromByte(uint8_t value) {
|
||||
Bytecode bytecode = static_cast<Bytecode>(value);
|
||||
@ -384,6 +380,7 @@ bool Bytecodes::IsConditionalJumpImmediate(Bytecode bytecode) {
|
||||
bytecode == Bytecode::kJumpIfUndefined;
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
bool Bytecodes::IsConditionalJumpConstant(Bytecode bytecode) {
|
||||
return bytecode == Bytecode::kJumpIfTrueConstant ||
|
||||
@ -624,6 +621,144 @@ OperandSize Bytecodes::SizeForUnsignedOperand(uint32_t value) {
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
Register Bytecodes::DecodeRegisterOperand(const uint8_t* operand_start,
|
||||
OperandType operand_type,
|
||||
OperandScale operand_scale) {
|
||||
DCHECK(Bytecodes::IsRegisterOperandType(operand_type));
|
||||
int32_t operand =
|
||||
DecodeSignedOperand(operand_start, operand_type, operand_scale);
|
||||
return Register::FromOperand(operand);
|
||||
}
|
||||
|
||||
// static
|
||||
int32_t Bytecodes::DecodeSignedOperand(const uint8_t* operand_start,
|
||||
OperandType operand_type,
|
||||
OperandScale operand_scale) {
|
||||
DCHECK(!Bytecodes::IsUnsignedOperandType(operand_type));
|
||||
switch (Bytecodes::SizeOfOperand(operand_type, operand_scale)) {
|
||||
case OperandSize::kByte:
|
||||
return static_cast<int8_t>(*operand_start);
|
||||
case OperandSize::kShort:
|
||||
return static_cast<int16_t>(ReadUnalignedUInt16(operand_start));
|
||||
case OperandSize::kQuad:
|
||||
return static_cast<int32_t>(ReadUnalignedUInt32(operand_start));
|
||||
case OperandSize::kNone:
|
||||
UNREACHABLE();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// static
|
||||
uint32_t Bytecodes::DecodeUnsignedOperand(const uint8_t* operand_start,
|
||||
OperandType operand_type,
|
||||
OperandScale operand_scale) {
|
||||
DCHECK(Bytecodes::IsUnsignedOperandType(operand_type));
|
||||
switch (Bytecodes::SizeOfOperand(operand_type, operand_scale)) {
|
||||
case OperandSize::kByte:
|
||||
return *operand_start;
|
||||
case OperandSize::kShort:
|
||||
return ReadUnalignedUInt16(operand_start);
|
||||
case OperandSize::kQuad:
|
||||
return ReadUnalignedUInt32(operand_start);
|
||||
case OperandSize::kNone:
|
||||
UNREACHABLE();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// static
|
||||
std::ostream& Bytecodes::Decode(std::ostream& os, const uint8_t* bytecode_start,
|
||||
int parameter_count) {
|
||||
Bytecode bytecode = Bytecodes::FromByte(bytecode_start[0]);
|
||||
int prefix_offset = 0;
|
||||
OperandScale operand_scale = OperandScale::kSingle;
|
||||
if (IsPrefixScalingBytecode(bytecode)) {
|
||||
prefix_offset = 1;
|
||||
operand_scale = Bytecodes::PrefixBytecodeToOperandScale(bytecode);
|
||||
bytecode = Bytecodes::FromByte(bytecode_start[1]);
|
||||
}
|
||||
|
||||
// Prepare to print bytecode and operands as hex digits.
|
||||
std::ios saved_format(nullptr);
|
||||
saved_format.copyfmt(saved_format);
|
||||
os.fill('0');
|
||||
os.flags(std::ios::hex);
|
||||
|
||||
int bytecode_size = Bytecodes::Size(bytecode, operand_scale);
|
||||
for (int i = 0; i < prefix_offset + bytecode_size; i++) {
|
||||
os << std::setw(2) << static_cast<uint32_t>(bytecode_start[i]) << ' ';
|
||||
}
|
||||
os.copyfmt(saved_format);
|
||||
|
||||
const int kBytecodeColumnSize = 6;
|
||||
for (int i = prefix_offset + bytecode_size; i < kBytecodeColumnSize; i++) {
|
||||
os << " ";
|
||||
}
|
||||
|
||||
os << Bytecodes::ToString(bytecode, operand_scale) << " ";
|
||||
|
||||
// Operands for the debug break are from the original instruction.
|
||||
if (IsDebugBreak(bytecode)) return os;
|
||||
|
||||
int number_of_operands = NumberOfOperands(bytecode);
|
||||
int range = 0;
|
||||
for (int i = 0; i < number_of_operands; i++) {
|
||||
OperandType op_type = GetOperandType(bytecode, i);
|
||||
const uint8_t* operand_start =
|
||||
&bytecode_start[prefix_offset +
|
||||
GetOperandOffset(bytecode, i, operand_scale)];
|
||||
switch (op_type) {
|
||||
case interpreter::OperandType::kRegCount:
|
||||
os << "#"
|
||||
<< DecodeUnsignedOperand(operand_start, op_type, operand_scale);
|
||||
break;
|
||||
case interpreter::OperandType::kIdx:
|
||||
case interpreter::OperandType::kRuntimeId:
|
||||
case interpreter::OperandType::kIntrinsicId:
|
||||
os << "["
|
||||
<< DecodeUnsignedOperand(operand_start, op_type, operand_scale)
|
||||
<< "]";
|
||||
break;
|
||||
case interpreter::OperandType::kImm:
|
||||
os << "[" << DecodeSignedOperand(operand_start, op_type, operand_scale)
|
||||
<< "]";
|
||||
break;
|
||||
case interpreter::OperandType::kFlag8:
|
||||
os << "#"
|
||||
<< DecodeUnsignedOperand(operand_start, op_type, operand_scale);
|
||||
break;
|
||||
case interpreter::OperandType::kMaybeReg:
|
||||
case interpreter::OperandType::kReg:
|
||||
case interpreter::OperandType::kRegOut: {
|
||||
Register reg =
|
||||
DecodeRegisterOperand(operand_start, op_type, operand_scale);
|
||||
os << reg.ToString(parameter_count);
|
||||
break;
|
||||
}
|
||||
case interpreter::OperandType::kRegOutTriple:
|
||||
range += 1;
|
||||
case interpreter::OperandType::kRegOutPair:
|
||||
case interpreter::OperandType::kRegPair: {
|
||||
range += 1;
|
||||
Register first_reg =
|
||||
DecodeRegisterOperand(operand_start, op_type, operand_scale);
|
||||
Register last_reg = Register(first_reg.index() + range);
|
||||
os << first_reg.ToString(parameter_count) << "-"
|
||||
<< last_reg.ToString(parameter_count);
|
||||
break;
|
||||
}
|
||||
case interpreter::OperandType::kNone:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
if (i != number_of_operands - 1) {
|
||||
os << ", ";
|
||||
}
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
// static
|
||||
bool Bytecodes::BytecodeHasHandler(Bytecode bytecode,
|
||||
OperandScale operand_scale) {
|
||||
@ -651,6 +786,169 @@ std::ostream& operator<<(std::ostream& os, const OperandType& operand_type) {
|
||||
return os << Bytecodes::OperandTypeToString(operand_type);
|
||||
}
|
||||
|
||||
static const int kLastParamRegisterIndex =
|
||||
(InterpreterFrameConstants::kRegisterFileFromFp -
|
||||
InterpreterFrameConstants::kLastParamFromFp) /
|
||||
kPointerSize;
|
||||
static const int kFunctionClosureRegisterIndex =
|
||||
(InterpreterFrameConstants::kRegisterFileFromFp -
|
||||
StandardFrameConstants::kFunctionOffset) /
|
||||
kPointerSize;
|
||||
static const int kCurrentContextRegisterIndex =
|
||||
(InterpreterFrameConstants::kRegisterFileFromFp -
|
||||
StandardFrameConstants::kContextOffset) /
|
||||
kPointerSize;
|
||||
static const int kNewTargetRegisterIndex =
|
||||
(InterpreterFrameConstants::kRegisterFileFromFp -
|
||||
InterpreterFrameConstants::kNewTargetFromFp) /
|
||||
kPointerSize;
|
||||
static const int kBytecodeArrayRegisterIndex =
|
||||
(InterpreterFrameConstants::kRegisterFileFromFp -
|
||||
InterpreterFrameConstants::kBytecodeArrayFromFp) /
|
||||
kPointerSize;
|
||||
static const int kBytecodeOffsetRegisterIndex =
|
||||
(InterpreterFrameConstants::kRegisterFileFromFp -
|
||||
InterpreterFrameConstants::kBytecodeOffsetFromFp) /
|
||||
kPointerSize;
|
||||
static const int kCallerPCOffsetRegisterIndex =
|
||||
(InterpreterFrameConstants::kRegisterFileFromFp -
|
||||
InterpreterFrameConstants::kCallerPCOffsetFromFp) /
|
||||
kPointerSize;
|
||||
|
||||
Register Register::FromParameterIndex(int index, int parameter_count) {
|
||||
DCHECK_GE(index, 0);
|
||||
DCHECK_LT(index, parameter_count);
|
||||
int register_index = kLastParamRegisterIndex - parameter_count + index + 1;
|
||||
DCHECK_LT(register_index, 0);
|
||||
return Register(register_index);
|
||||
}
|
||||
|
||||
int Register::ToParameterIndex(int parameter_count) const {
|
||||
DCHECK(is_parameter());
|
||||
return index() - kLastParamRegisterIndex + parameter_count - 1;
|
||||
}
|
||||
|
||||
Register Register::function_closure() {
|
||||
return Register(kFunctionClosureRegisterIndex);
|
||||
}
|
||||
|
||||
bool Register::is_function_closure() const {
|
||||
return index() == kFunctionClosureRegisterIndex;
|
||||
}
|
||||
|
||||
Register Register::current_context() {
|
||||
return Register(kCurrentContextRegisterIndex);
|
||||
}
|
||||
|
||||
bool Register::is_current_context() const {
|
||||
return index() == kCurrentContextRegisterIndex;
|
||||
}
|
||||
|
||||
Register Register::new_target() { return Register(kNewTargetRegisterIndex); }
|
||||
|
||||
bool Register::is_new_target() const {
|
||||
return index() == kNewTargetRegisterIndex;
|
||||
}
|
||||
|
||||
Register Register::bytecode_array() {
|
||||
return Register(kBytecodeArrayRegisterIndex);
|
||||
}
|
||||
|
||||
bool Register::is_bytecode_array() const {
|
||||
return index() == kBytecodeArrayRegisterIndex;
|
||||
}
|
||||
|
||||
Register Register::bytecode_offset() {
|
||||
return Register(kBytecodeOffsetRegisterIndex);
|
||||
}
|
||||
|
||||
bool Register::is_bytecode_offset() const {
|
||||
return index() == kBytecodeOffsetRegisterIndex;
|
||||
}
|
||||
|
||||
// static
|
||||
Register Register::virtual_accumulator() {
|
||||
return Register(kCallerPCOffsetRegisterIndex);
|
||||
}
|
||||
|
||||
OperandSize Register::SizeOfOperand() const {
|
||||
int32_t operand = ToOperand();
|
||||
if (operand >= kMinInt8 && operand <= kMaxInt8) {
|
||||
return OperandSize::kByte;
|
||||
} else if (operand >= kMinInt16 && operand <= kMaxInt16) {
|
||||
return OperandSize::kShort;
|
||||
} else {
|
||||
return OperandSize::kQuad;
|
||||
}
|
||||
}
|
||||
|
||||
bool Register::AreContiguous(Register reg1, Register reg2, Register reg3,
|
||||
Register reg4, Register reg5) {
|
||||
if (reg1.index() + 1 != reg2.index()) {
|
||||
return false;
|
||||
}
|
||||
if (reg3.is_valid() && reg2.index() + 1 != reg3.index()) {
|
||||
return false;
|
||||
}
|
||||
if (reg4.is_valid() && reg3.index() + 1 != reg4.index()) {
|
||||
return false;
|
||||
}
|
||||
if (reg5.is_valid() && reg4.index() + 1 != reg5.index()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string Register::ToString(int parameter_count) {
|
||||
if (is_current_context()) {
|
||||
return std::string("<context>");
|
||||
} else if (is_function_closure()) {
|
||||
return std::string("<closure>");
|
||||
} else if (is_new_target()) {
|
||||
return std::string("<new.target>");
|
||||
} else if (is_parameter()) {
|
||||
int parameter_index = ToParameterIndex(parameter_count);
|
||||
if (parameter_index == 0) {
|
||||
return std::string("<this>");
|
||||
} else {
|
||||
std::ostringstream s;
|
||||
s << "a" << parameter_index - 1;
|
||||
return s.str();
|
||||
}
|
||||
} else {
|
||||
std::ostringstream s;
|
||||
s << "r" << index();
|
||||
return s.str();
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
uint8_t CreateObjectLiteralFlags::Encode(bool fast_clone_supported,
|
||||
int properties_count,
|
||||
int runtime_flags) {
|
||||
uint8_t result = FlagsBits::encode(runtime_flags);
|
||||
if (fast_clone_supported) {
|
||||
STATIC_ASSERT(
|
||||
FastCloneShallowObjectStub::kMaximumClonedProperties <=
|
||||
1 << CreateObjectLiteralFlags::FastClonePropertiesCountBits::kShift);
|
||||
DCHECK_LE(properties_count,
|
||||
FastCloneShallowObjectStub::kMaximumClonedProperties);
|
||||
result |= CreateObjectLiteralFlags::FastClonePropertiesCountBits::encode(
|
||||
properties_count);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// static
|
||||
uint8_t CreateClosureFlags::Encode(bool pretenure, bool is_function_scope) {
|
||||
uint8_t result = PretenuredBit::encode(pretenure);
|
||||
if (!FLAG_always_opt && !FLAG_prepare_always_opt &&
|
||||
pretenure == NOT_TENURED && is_function_scope) {
|
||||
result |= FastNewClosureBit::encode(true);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace interpreter
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -5,13 +5,12 @@
|
||||
#ifndef V8_INTERPRETER_BYTECODES_H_
|
||||
#define V8_INTERPRETER_BYTECODES_H_
|
||||
|
||||
#include <cstdint>
|
||||
#include <iosfwd>
|
||||
#include <string>
|
||||
|
||||
// This interface and it's implementation are independent of the
|
||||
// libv8_base library as they are used by the interpreter and the
|
||||
// standalone mkpeephole table generator program.
|
||||
// Clients of this interface shouldn't depend on lots of interpreter internals.
|
||||
// Do not include anything from src/interpreter here!
|
||||
#include "src/frames.h"
|
||||
#include "src/utils.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
@ -287,12 +286,12 @@ enum class AccumulatorUse : uint8_t {
|
||||
kReadWrite = kRead | kWrite
|
||||
};
|
||||
|
||||
inline AccumulatorUse operator&(AccumulatorUse lhs, AccumulatorUse rhs) {
|
||||
V8_INLINE AccumulatorUse operator&(AccumulatorUse lhs, AccumulatorUse rhs) {
|
||||
int result = static_cast<int>(lhs) & static_cast<int>(rhs);
|
||||
return static_cast<AccumulatorUse>(result);
|
||||
}
|
||||
|
||||
inline AccumulatorUse operator|(AccumulatorUse lhs, AccumulatorUse rhs) {
|
||||
V8_INLINE AccumulatorUse operator|(AccumulatorUse lhs, AccumulatorUse rhs) {
|
||||
int result = static_cast<int>(lhs) | static_cast<int>(rhs);
|
||||
return static_cast<AccumulatorUse>(result);
|
||||
}
|
||||
@ -349,6 +348,7 @@ enum class OperandType : uint8_t {
|
||||
#undef COUNT_OPERAND_TYPES
|
||||
};
|
||||
|
||||
|
||||
// Enumeration of interpreter bytecodes.
|
||||
enum class Bytecode : uint8_t {
|
||||
#define DECLARE_BYTECODE(Name, ...) k##Name,
|
||||
@ -361,7 +361,94 @@ enum class Bytecode : uint8_t {
|
||||
#undef COUNT_BYTECODE
|
||||
};
|
||||
|
||||
class Bytecodes final {
|
||||
|
||||
// An interpreter Register which is located in the function's Register file
|
||||
// in its stack-frame. Register hold parameters, this, and expression values.
|
||||
class Register final {
|
||||
public:
|
||||
explicit Register(int index = kInvalidIndex) : index_(index) {}
|
||||
|
||||
int index() const { return index_; }
|
||||
bool is_parameter() const { return index() < 0; }
|
||||
bool is_valid() const { return index_ != kInvalidIndex; }
|
||||
|
||||
static Register FromParameterIndex(int index, int parameter_count);
|
||||
int ToParameterIndex(int parameter_count) const;
|
||||
|
||||
// Returns an invalid register.
|
||||
static Register invalid_value() { return Register(); }
|
||||
|
||||
// Returns the register for the function's closure object.
|
||||
static Register function_closure();
|
||||
bool is_function_closure() const;
|
||||
|
||||
// Returns the register which holds the current context object.
|
||||
static Register current_context();
|
||||
bool is_current_context() const;
|
||||
|
||||
// Returns the register for the incoming new target value.
|
||||
static Register new_target();
|
||||
bool is_new_target() const;
|
||||
|
||||
// Returns the register for the bytecode array.
|
||||
static Register bytecode_array();
|
||||
bool is_bytecode_array() const;
|
||||
|
||||
// Returns the register for the saved bytecode offset.
|
||||
static Register bytecode_offset();
|
||||
bool is_bytecode_offset() const;
|
||||
|
||||
// Returns a register that can be used to represent the accumulator
|
||||
// within code in the interpreter, but should never be emitted in
|
||||
// bytecode.
|
||||
static Register virtual_accumulator();
|
||||
|
||||
OperandSize SizeOfOperand() const;
|
||||
|
||||
int32_t ToOperand() const { return kRegisterFileStartOffset - index_; }
|
||||
static Register FromOperand(int32_t operand) {
|
||||
return Register(kRegisterFileStartOffset - operand);
|
||||
}
|
||||
|
||||
static bool AreContiguous(Register reg1, Register reg2,
|
||||
Register reg3 = Register(),
|
||||
Register reg4 = Register(),
|
||||
Register reg5 = Register());
|
||||
|
||||
std::string ToString(int parameter_count);
|
||||
|
||||
bool operator==(const Register& other) const {
|
||||
return index() == other.index();
|
||||
}
|
||||
bool operator!=(const Register& other) const {
|
||||
return index() != other.index();
|
||||
}
|
||||
bool operator<(const Register& other) const {
|
||||
return index() < other.index();
|
||||
}
|
||||
bool operator<=(const Register& other) const {
|
||||
return index() <= other.index();
|
||||
}
|
||||
bool operator>(const Register& other) const {
|
||||
return index() > other.index();
|
||||
}
|
||||
bool operator>=(const Register& other) const {
|
||||
return index() >= other.index();
|
||||
}
|
||||
|
||||
private:
|
||||
static const int kInvalidIndex = kMaxInt;
|
||||
static const int kRegisterFileStartOffset =
|
||||
InterpreterFrameConstants::kRegisterFileFromFp / kPointerSize;
|
||||
|
||||
void* operator new(size_t size);
|
||||
void operator delete(void* p);
|
||||
|
||||
int index_;
|
||||
};
|
||||
|
||||
|
||||
class Bytecodes {
|
||||
public:
|
||||
// The maximum number of operands a bytecode may have.
|
||||
static const int kMaxOperands = 4;
|
||||
@ -385,7 +472,10 @@ class Bytecodes final {
|
||||
static const char* OperandSizeToString(OperandSize operand_size);
|
||||
|
||||
// Returns byte value of bytecode.
|
||||
static uint8_t ToByte(Bytecode bytecode);
|
||||
static uint8_t ToByte(Bytecode bytecode) {
|
||||
DCHECK_LE(bytecode, Bytecode::kLast);
|
||||
return static_cast<uint8_t>(bytecode);
|
||||
}
|
||||
|
||||
// Returns bytecode for |value|.
|
||||
static Bytecode FromByte(uint8_t value);
|
||||
@ -546,6 +636,25 @@ class Bytecodes final {
|
||||
// Returns true if |operand_type| is unsigned, false if signed.
|
||||
static bool IsUnsignedOperandType(OperandType operand_type);
|
||||
|
||||
// Decodes a register operand in a byte array.
|
||||
static Register DecodeRegisterOperand(const uint8_t* operand_start,
|
||||
OperandType operand_type,
|
||||
OperandScale operand_scale);
|
||||
|
||||
// Decodes a signed operand in a byte array.
|
||||
static int32_t DecodeSignedOperand(const uint8_t* operand_start,
|
||||
OperandType operand_type,
|
||||
OperandScale operand_scale);
|
||||
|
||||
// Decodes an unsigned operand in a byte array.
|
||||
static uint32_t DecodeUnsignedOperand(const uint8_t* operand_start,
|
||||
OperandType operand_type,
|
||||
OperandScale operand_scale);
|
||||
|
||||
// Decode a single bytecode and operands to |os|.
|
||||
static std::ostream& Decode(std::ostream& os, const uint8_t* bytecode_start,
|
||||
int number_of_parameters);
|
||||
|
||||
// Returns true if a handler is generated for a bytecode at a given
|
||||
// operand scale. All bytecodes have handlers at OperandScale::kSingle,
|
||||
// but only bytecodes with scalable operands have handlers with larger
|
||||
@ -557,6 +666,33 @@ class Bytecodes final {
|
||||
|
||||
// Return the operand size required to hold an unsigned operand.
|
||||
static OperandSize SizeForUnsignedOperand(uint32_t value);
|
||||
|
||||
private:
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(Bytecodes);
|
||||
};
|
||||
|
||||
class CreateObjectLiteralFlags {
|
||||
public:
|
||||
class FlagsBits : public BitField8<int, 0, 3> {};
|
||||
class FastClonePropertiesCountBits
|
||||
: public BitField8<int, FlagsBits::kNext, 3> {};
|
||||
|
||||
static uint8_t Encode(bool fast_clone_supported, int properties_count,
|
||||
int runtime_flags);
|
||||
|
||||
private:
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(CreateObjectLiteralFlags);
|
||||
};
|
||||
|
||||
class CreateClosureFlags {
|
||||
public:
|
||||
class PretenuredBit : public BitField8<bool, 0, 1> {};
|
||||
class FastNewClosureBit : public BitField8<bool, PretenuredBit::kNext, 1> {};
|
||||
|
||||
static uint8_t Encode(bool pretenure, bool is_function_scope);
|
||||
|
||||
private:
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(CreateClosureFlags);
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const Bytecode& bytecode);
|
||||
|
@ -5,7 +5,6 @@
|
||||
#include "src/interpreter/handler-table-builder.h"
|
||||
|
||||
#include "src/factory.h"
|
||||
#include "src/interpreter/bytecode-register.h"
|
||||
#include "src/isolate.h"
|
||||
#include "src/objects-inl.h"
|
||||
|
||||
|
@ -6,7 +6,6 @@
|
||||
#define V8_INTERPRETER_HANDLER_TABLE_BUILDER_H_
|
||||
|
||||
#include "src/handles.h"
|
||||
#include "src/interpreter/bytecode-register.h"
|
||||
#include "src/interpreter/bytecodes.h"
|
||||
#include "src/zone-containers.h"
|
||||
|
||||
|
@ -10,7 +10,6 @@
|
||||
#include "src/builtins/builtins.h"
|
||||
#include "src/code-stub-assembler.h"
|
||||
#include "src/frames.h"
|
||||
#include "src/interpreter/bytecode-register.h"
|
||||
#include "src/interpreter/bytecodes.h"
|
||||
#include "src/runtime/runtime.h"
|
||||
|
||||
|
@ -10,7 +10,6 @@
|
||||
#include "src/code-factory.h"
|
||||
#include "src/compiler.h"
|
||||
#include "src/factory.h"
|
||||
#include "src/interpreter/bytecode-flags.h"
|
||||
#include "src/interpreter/bytecode-generator.h"
|
||||
#include "src/interpreter/bytecodes.h"
|
||||
#include "src/interpreter/interpreter-assembler.h"
|
||||
|
@ -38,7 +38,6 @@
|
||||
#include "src/ic/ic.h"
|
||||
#include "src/identity-map.h"
|
||||
#include "src/interpreter/bytecode-array-iterator.h"
|
||||
#include "src/interpreter/bytecode-decoder.h"
|
||||
#include "src/interpreter/interpreter.h"
|
||||
#include "src/isolate-inl.h"
|
||||
#include "src/keys.h"
|
||||
@ -14397,8 +14396,7 @@ void BytecodeArray::Disassemble(std::ostream& os) {
|
||||
const uint8_t* current_address = base_address + iterator.current_offset();
|
||||
os << reinterpret_cast<const void*>(current_address) << " @ "
|
||||
<< std::setw(4) << iterator.current_offset() << " : ";
|
||||
interpreter::BytecodeDecoder::Decode(os, current_address,
|
||||
parameter_count());
|
||||
interpreter::Bytecodes::Decode(os, current_address, parameter_count());
|
||||
if (interpreter::Bytecodes::IsJump(iterator.current_bytecode())) {
|
||||
const void* jump_target = base_address + iterator.GetJumpTargetOffset();
|
||||
os << " (" << jump_target << " @ " << iterator.GetJumpTargetOffset()
|
||||
|
@ -9,9 +9,6 @@
|
||||
#include "src/arguments.h"
|
||||
#include "src/frames-inl.h"
|
||||
#include "src/interpreter/bytecode-array-iterator.h"
|
||||
#include "src/interpreter/bytecode-decoder.h"
|
||||
#include "src/interpreter/bytecode-flags.h"
|
||||
#include "src/interpreter/bytecode-register.h"
|
||||
#include "src/interpreter/bytecodes.h"
|
||||
#include "src/isolate-inl.h"
|
||||
#include "src/ostreams.h"
|
||||
@ -120,8 +117,8 @@ RUNTIME_FUNCTION(Runtime_InterpreterTraceBytecodeEntry) {
|
||||
const uint8_t* bytecode_address = base_address + offset;
|
||||
os << " -> " << static_cast<const void*>(bytecode_address) << " @ "
|
||||
<< std::setw(4) << offset << " : ";
|
||||
interpreter::BytecodeDecoder::Decode(os, bytecode_address,
|
||||
bytecode_array->parameter_count());
|
||||
interpreter::Bytecodes::Decode(os, bytecode_address,
|
||||
bytecode_array->parameter_count());
|
||||
os << std::endl;
|
||||
// Print all input registers and accumulator.
|
||||
PrintRegisters(os, true, bytecode_iterator, accumulator);
|
||||
|
@ -917,19 +917,13 @@
|
||||
'interpreter/bytecode-array-writer.h',
|
||||
'interpreter/bytecode-dead-code-optimizer.cc',
|
||||
'interpreter/bytecode-dead-code-optimizer.h',
|
||||
'interpreter/bytecode-decoder.cc',
|
||||
'interpreter/bytecode-decoder.h',
|
||||
'interpreter/bytecode-flags.cc',
|
||||
'interpreter/bytecode-flags.h',
|
||||
'interpreter/bytecode-label.h',
|
||||
'interpreter/bytecode-generator.cc',
|
||||
'interpreter/bytecode-generator.h',
|
||||
'interpreter/bytecode-label.h',
|
||||
'interpreter/bytecode-peephole-optimizer.cc',
|
||||
'interpreter/bytecode-peephole-optimizer.h',
|
||||
'interpreter/bytecode-pipeline.cc',
|
||||
'interpreter/bytecode-pipeline.h',
|
||||
'interpreter/bytecode-register.cc',
|
||||
'interpreter/bytecode-register.h',
|
||||
'interpreter/bytecode-register-allocator.cc',
|
||||
'interpreter/bytecode-register-allocator.h',
|
||||
'interpreter/bytecode-register-optimizer.cc',
|
||||
|
@ -1,86 +0,0 @@
|
||||
// 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.
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "src/v8.h"
|
||||
|
||||
#include "src/interpreter/bytecode-decoder.h"
|
||||
#include "test/unittests/interpreter/bytecode-utils.h"
|
||||
#include "test/unittests/test-utils.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
namespace interpreter {
|
||||
|
||||
TEST(BytecodeDecoder, DecodeBytecodeAndOperands) {
|
||||
struct BytecodesAndResult {
|
||||
const uint8_t bytecode[32];
|
||||
const size_t length;
|
||||
int parameter_count;
|
||||
const char* output;
|
||||
};
|
||||
|
||||
const BytecodesAndResult cases[] = {
|
||||
{{B(LdaSmi), U8(1)}, 2, 0, " LdaSmi [1]"},
|
||||
{{B(Wide), B(LdaSmi), U16(1000)}, 4, 0, " LdaSmi.Wide [1000]"},
|
||||
{{B(ExtraWide), B(LdaSmi), U32(100000)},
|
||||
6,
|
||||
0,
|
||||
"LdaSmi.ExtraWide [100000]"},
|
||||
{{B(LdaSmi), U8(-1)}, 2, 0, " LdaSmi [-1]"},
|
||||
{{B(Wide), B(LdaSmi), U16(-1000)}, 4, 0, " LdaSmi.Wide [-1000]"},
|
||||
{{B(ExtraWide), B(LdaSmi), U32(-100000)},
|
||||
6,
|
||||
0,
|
||||
"LdaSmi.ExtraWide [-100000]"},
|
||||
{{B(Star), R8(5)}, 2, 0, " Star r5"},
|
||||
{{B(Wide), B(Star), R16(136)}, 4, 0, " Star.Wide r136"},
|
||||
{{B(Wide), B(Call), R16(134), R16(135), U16(2), U16(177)},
|
||||
10,
|
||||
0,
|
||||
"Call.Wide r134, r135, #2, [177]"},
|
||||
{{B(Ldar),
|
||||
static_cast<uint8_t>(Register::FromParameterIndex(2, 3).ToOperand())},
|
||||
2,
|
||||
3,
|
||||
" Ldar a1"},
|
||||
{{B(Wide), B(CreateObjectLiteral), U16(513), U16(1027), U8(165)},
|
||||
7,
|
||||
0,
|
||||
"CreateObjectLiteral.Wide [513], [1027], #165"},
|
||||
{{B(ExtraWide), B(JumpIfNull), U32(123456789)},
|
||||
6,
|
||||
0,
|
||||
"JumpIfNull.ExtraWide [123456789]"},
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < arraysize(cases); ++i) {
|
||||
// Generate reference string by prepending formatted bytes.
|
||||
std::stringstream expected_ss;
|
||||
std::ios default_format(nullptr);
|
||||
default_format.copyfmt(expected_ss);
|
||||
// Match format of BytecodeDecoder::Decode() for byte representations.
|
||||
expected_ss.fill('0');
|
||||
expected_ss.flags(std::ios::right | std::ios::hex);
|
||||
for (size_t b = 0; b < cases[i].length; b++) {
|
||||
expected_ss << std::setw(2) << static_cast<uint32_t>(cases[i].bytecode[b])
|
||||
<< ' ';
|
||||
}
|
||||
expected_ss.copyfmt(default_format);
|
||||
expected_ss << cases[i].output;
|
||||
|
||||
// Generate decoded byte output.
|
||||
std::stringstream actual_ss;
|
||||
BytecodeDecoder::Decode(actual_ss, cases[i].bytecode,
|
||||
cases[i].parameter_count);
|
||||
|
||||
// Compare.
|
||||
CHECK_EQ(actual_ss.str(), expected_ss.str());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace interpreter
|
||||
} // namespace internal
|
||||
} // namespace v8
|
@ -6,8 +6,8 @@
|
||||
|
||||
#include "src/v8.h"
|
||||
|
||||
#include "src/interpreter/bytecode-register.h"
|
||||
#include "src/interpreter/bytecodes.h"
|
||||
#include "test/unittests/interpreter/bytecode-utils.h"
|
||||
#include "test/unittests/test-utils.h"
|
||||
|
||||
namespace v8 {
|
||||
@ -146,6 +146,72 @@ TEST(Bytecodes, DebugBreakExistForEachBytecode) {
|
||||
#undef CHECK_DEBUG_BREAK_SIZE
|
||||
}
|
||||
|
||||
TEST(Bytecodes, DecodeBytecodeAndOperands) {
|
||||
struct BytecodesAndResult {
|
||||
const uint8_t bytecode[32];
|
||||
const size_t length;
|
||||
int parameter_count;
|
||||
const char* output;
|
||||
};
|
||||
|
||||
const BytecodesAndResult cases[] = {
|
||||
{{B(LdaSmi), U8(1)}, 2, 0, " LdaSmi [1]"},
|
||||
{{B(Wide), B(LdaSmi), U16(1000)}, 4, 0, " LdaSmi.Wide [1000]"},
|
||||
{{B(ExtraWide), B(LdaSmi), U32(100000)},
|
||||
6,
|
||||
0,
|
||||
"LdaSmi.ExtraWide [100000]"},
|
||||
{{B(LdaSmi), U8(-1)}, 2, 0, " LdaSmi [-1]"},
|
||||
{{B(Wide), B(LdaSmi), U16(-1000)}, 4, 0, " LdaSmi.Wide [-1000]"},
|
||||
{{B(ExtraWide), B(LdaSmi), U32(-100000)},
|
||||
6,
|
||||
0,
|
||||
"LdaSmi.ExtraWide [-100000]"},
|
||||
{{B(Star), R8(5)}, 2, 0, " Star r5"},
|
||||
{{B(Wide), B(Star), R16(136)}, 4, 0, " Star.Wide r136"},
|
||||
{{B(Wide), B(Call), R16(134), R16(135), U16(2), U16(177)},
|
||||
10,
|
||||
0,
|
||||
"Call.Wide r134, r135, #2, [177]"},
|
||||
{{B(Ldar),
|
||||
static_cast<uint8_t>(Register::FromParameterIndex(2, 3).ToOperand())},
|
||||
2,
|
||||
3,
|
||||
" Ldar a1"},
|
||||
{{B(Wide), B(CreateObjectLiteral), U16(513), U16(1027), U8(165)},
|
||||
7,
|
||||
0,
|
||||
"CreateObjectLiteral.Wide [513], [1027], #165"},
|
||||
{{B(ExtraWide), B(JumpIfNull), U32(123456789)},
|
||||
6,
|
||||
0,
|
||||
"JumpIfNull.ExtraWide [123456789]"},
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < arraysize(cases); ++i) {
|
||||
// Generate reference string by prepending formatted bytes.
|
||||
std::stringstream expected_ss;
|
||||
std::ios default_format(nullptr);
|
||||
default_format.copyfmt(expected_ss);
|
||||
// Match format of Bytecodes::Decode() for byte representations.
|
||||
expected_ss.fill('0');
|
||||
expected_ss.flags(std::ios::right | std::ios::hex);
|
||||
for (size_t b = 0; b < cases[i].length; b++) {
|
||||
expected_ss << std::setw(2) << static_cast<uint32_t>(cases[i].bytecode[b])
|
||||
<< ' ';
|
||||
}
|
||||
expected_ss.copyfmt(default_format);
|
||||
expected_ss << cases[i].output;
|
||||
|
||||
// Generate decoded byte output.
|
||||
std::stringstream actual_ss;
|
||||
Bytecodes::Decode(actual_ss, cases[i].bytecode, cases[i].parameter_count);
|
||||
|
||||
// Compare.
|
||||
CHECK_EQ(actual_ss.str(), expected_ss.str());
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Bytecodes, DebugBreakForPrefixBytecodes) {
|
||||
CHECK_EQ(Bytecode::kDebugBreakWide,
|
||||
Bytecodes::GetDebugBreak(Bytecode::kWide));
|
||||
|
@ -84,7 +84,6 @@
|
||||
'interpreter/bytecode-array-iterator-unittest.cc',
|
||||
'interpreter/bytecode-array-writer-unittest.cc',
|
||||
'interpreter/bytecode-dead-code-optimizer-unittest.cc',
|
||||
'interpreter/bytecode-decoder-unittest.cc',
|
||||
'interpreter/bytecode-peephole-optimizer-unittest.cc',
|
||||
'interpreter/bytecode-pipeline-unittest.cc',
|
||||
'interpreter/bytecode-register-allocator-unittest.cc',
|
||||
|
Loading…
Reference in New Issue
Block a user