Commit 5d693348 authored by hablich's avatar hablich Committed by Commit bot

Revert of [Interpreter] Optimize BytecodeArrayBuilder and BytecodeArrayWriter....

Revert of [Interpreter] Optimize BytecodeArrayBuilder and BytecodeArrayWriter. (patchset #6 id:200001 of https://codereview.chromium.org/2351763002/ )

Reason for revert:
Prime suspect for roll blocker: https://codereview.chromium.org/2362503002/

Original issue's description:
> [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
> Cr-Commit-Position: refs/heads/master@{#39599}

TBR=mythria@chromium.org,leszeks@chromium.org,rmcilroy@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/2360193003
Cr-Commit-Position: refs/heads/master@{#39612}
parent a041367e
...@@ -1413,8 +1413,6 @@ v8_source_set("v8_base") { ...@@ -1413,8 +1413,6 @@ v8_source_set("v8_base") {
"src/interpreter/bytecode-generator.h", "src/interpreter/bytecode-generator.h",
"src/interpreter/bytecode-label.cc", "src/interpreter/bytecode-label.cc",
"src/interpreter/bytecode-label.h", "src/interpreter/bytecode-label.h",
"src/interpreter/bytecode-operands.cc",
"src/interpreter/bytecode-operands.h",
"src/interpreter/bytecode-peephole-optimizer.cc", "src/interpreter/bytecode-peephole-optimizer.cc",
"src/interpreter/bytecode-peephole-optimizer.h", "src/interpreter/bytecode-peephole-optimizer.h",
"src/interpreter/bytecode-peephole-table.h", "src/interpreter/bytecode-peephole-table.h",
...@@ -2382,10 +2380,7 @@ v8_executable("mkpeephole") { ...@@ -2382,10 +2380,7 @@ v8_executable("mkpeephole") {
visibility = [ ":*" ] # Only targets in this file can depend on this. visibility = [ ":*" ] # Only targets in this file can depend on this.
sources = [ sources = [
"src/interpreter/bytecode-operands.cc",
"src/interpreter/bytecode-operands.h",
"src/interpreter/bytecode-peephole-optimizer.h", "src/interpreter/bytecode-peephole-optimizer.h",
"src/interpreter/bytecode-traits.h",
"src/interpreter/bytecodes.cc", "src/interpreter/bytecodes.cc",
"src/interpreter/bytecodes.h", "src/interpreter/bytecodes.h",
"src/interpreter/mkpeephole.cc", "src/interpreter/mkpeephole.cc",
......
This diff is collapsed.
...@@ -309,24 +309,9 @@ class BytecodeArrayBuilder final : public ZoneObject { ...@@ -309,24 +309,9 @@ class BytecodeArrayBuilder final : public ZoneObject {
void InitializeReturnPosition(FunctionLiteral* literal); void InitializeReturnPosition(FunctionLiteral* literal);
void SetStatementPosition(Statement* stmt) { void SetStatementPosition(Statement* stmt);
if (stmt->position() == kNoSourcePosition) return; void SetExpressionPosition(Expression* expr);
latest_source_info_.MakeStatementPosition(stmt->position()); void SetExpressionAsStatementPosition(Expression* expr);
}
void SetExpressionPosition(Expression* expr) {
if (expr->position() == kNoSourcePosition) return;
if (!latest_source_info_.is_statement()) {
// Ensure the current expression position is overwritten with the
// latest value.
latest_source_info_.MakeExpressionPosition(expr->position());
}
}
void SetExpressionAsStatementPosition(Expression* expr) {
if (expr->position() == kNoSourcePosition) return;
latest_source_info_.MakeStatementPosition(expr->position());
}
// Accessors // Accessors
TemporaryRegisterAllocator* temporary_register_allocator() { TemporaryRegisterAllocator* temporary_register_allocator() {
...@@ -360,23 +345,36 @@ class BytecodeArrayBuilder final : public ZoneObject { ...@@ -360,23 +345,36 @@ class BytecodeArrayBuilder final : public ZoneObject {
private: private:
friend class BytecodeRegisterAllocator; friend class BytecodeRegisterAllocator;
INLINE(void Output(Bytecode bytecode, uint32_t operand0, uint32_t operand1, static Bytecode BytecodeForBinaryOperation(Token::Value op);
uint32_t operand2, uint32_t operand3)); static Bytecode BytecodeForCountOperation(Token::Value op);
INLINE(void Output(Bytecode bytecode, uint32_t operand0, uint32_t operand1, static Bytecode BytecodeForCompareOperation(Token::Value op);
uint32_t operand2)); static Bytecode BytecodeForStoreNamedProperty(LanguageMode language_mode);
INLINE(void Output(Bytecode bytecode, uint32_t operand0, uint32_t operand1)); static Bytecode BytecodeForStoreKeyedProperty(LanguageMode language_mode);
INLINE(void Output(Bytecode bytecode, uint32_t operand0)); static Bytecode BytecodeForLoadGlobal(TypeofMode typeof_mode);
INLINE(void Output(Bytecode bytecode)); static Bytecode BytecodeForStoreGlobal(LanguageMode language_mode);
static Bytecode BytecodeForStoreLookupSlot(LanguageMode language_mode);
INLINE(void OutputJump(Bytecode bytecode, BytecodeLabel* label)); static Bytecode BytecodeForCreateArguments(CreateArgumentsType type);
INLINE(void OutputJump(Bytecode bytecode, uint32_t operand0, static Bytecode BytecodeForDelete(LanguageMode language_mode);
BytecodeLabel* label)); static Bytecode BytecodeForCall(TailCallMode tail_call_mode);
void Output(Bytecode bytecode, uint32_t operand0, uint32_t operand1,
uint32_t operand2, uint32_t operand3);
void Output(Bytecode bytecode, uint32_t operand0, uint32_t operand1,
uint32_t operand2);
void Output(Bytecode bytecode, uint32_t operand0, uint32_t operand1);
void Output(Bytecode bytecode, uint32_t operand0);
void Output(Bytecode bytecode);
BytecodeArrayBuilder& OutputJump(BytecodeNode* node, BytecodeLabel* label);
bool RegisterIsValid(Register reg) const; bool RegisterIsValid(Register reg) const;
bool OperandsAreValid(Bytecode bytecode, int operand_count, bool OperandsAreValid(Bytecode bytecode, int operand_count,
uint32_t operand0 = 0, uint32_t operand1 = 0, uint32_t operand0 = 0, uint32_t operand1 = 0,
uint32_t operand2 = 0, uint32_t operand3 = 0) const; uint32_t operand2 = 0, uint32_t operand3 = 0) const;
// Attach latest source position to |node|.
void AttachSourceInfo(BytecodeNode* node);
// Set position for return. // Set position for return.
void SetReturnPosition(); void SetReturnPosition();
......
...@@ -21,23 +21,27 @@ BytecodeArrayWriter::BytecodeArrayWriter( ...@@ -21,23 +21,27 @@ BytecodeArrayWriter::BytecodeArrayWriter(
Zone* zone, ConstantArrayBuilder* constant_array_builder, Zone* zone, ConstantArrayBuilder* constant_array_builder,
SourcePositionTableBuilder::RecordingMode source_position_mode) SourcePositionTableBuilder::RecordingMode source_position_mode)
: bytecodes_(zone), : bytecodes_(zone),
max_register_count_(0),
unbound_jumps_(0), unbound_jumps_(0),
source_position_table_builder_(zone, source_position_mode), source_position_table_builder_(zone, source_position_mode),
constant_array_builder_(constant_array_builder) { constant_array_builder_(constant_array_builder) {}
bytecodes_.reserve(512); // Derived via experimentation.
}
// override // override
BytecodeArrayWriter::~BytecodeArrayWriter() {} BytecodeArrayWriter::~BytecodeArrayWriter() {}
// override // override
Handle<BytecodeArray> BytecodeArrayWriter::ToBytecodeArray( Handle<BytecodeArray> BytecodeArrayWriter::ToBytecodeArray(
Isolate* isolate, int register_count, int parameter_count, Isolate* isolate, int fixed_register_count, int parameter_count,
Handle<FixedArray> handler_table) { Handle<FixedArray> handler_table) {
DCHECK_EQ(0, unbound_jumps_); DCHECK_EQ(0, unbound_jumps_);
int bytecode_size = static_cast<int>(bytecodes()->size()); int bytecode_size = static_cast<int>(bytecodes()->size());
int frame_size = register_count * kPointerSize;
// All locals need a frame slot for the debugger, but may not be
// present in generated code.
int frame_size_for_locals = fixed_register_count * kPointerSize;
int frame_size_used = max_register_count() * kPointerSize;
int frame_size = std::max(frame_size_for_locals, frame_size_used);
Handle<FixedArray> constant_pool = Handle<FixedArray> constant_pool =
constant_array_builder()->ToFixedArray(isolate); constant_array_builder()->ToFixedArray(isolate);
Handle<BytecodeArray> bytecode_array = isolate->factory()->NewBytecodeArray( Handle<BytecodeArray> bytecode_array = isolate->factory()->NewBytecodeArray(
...@@ -100,48 +104,116 @@ void BytecodeArrayWriter::UpdateSourcePositionTable( ...@@ -100,48 +104,116 @@ void BytecodeArrayWriter::UpdateSourcePositionTable(
} }
} }
namespace {
OperandScale ScaleForScalableByteOperand(OperandSize operand_size) {
STATIC_ASSERT(static_cast<int>(OperandSize::kByte) ==
static_cast<int>(OperandScale::kSingle));
STATIC_ASSERT(static_cast<int>(OperandSize::kShort) ==
static_cast<int>(OperandScale::kDouble));
STATIC_ASSERT(static_cast<int>(OperandSize::kQuad) ==
static_cast<int>(OperandScale::kQuadruple));
return static_cast<OperandScale>(operand_size);
}
OperandScale OperandScaleForScalableSignedByte(uint32_t operand_value) {
int32_t signed_operand = static_cast<int32_t>(operand_value);
OperandSize bytes_required = Bytecodes::SizeForSignedOperand(signed_operand);
return ScaleForScalableByteOperand(bytes_required);
}
OperandScale OperandScaleForScalableUnsignedByte(uint32_t operand_value) {
OperandSize bytes_required = Bytecodes::SizeForUnsignedOperand(operand_value);
return ScaleForScalableByteOperand(bytes_required);
}
OperandScale GetOperandScale(const BytecodeNode* const node) {
const OperandTypeInfo* operand_type_infos =
Bytecodes::GetOperandTypeInfos(node->bytecode());
OperandScale operand_scale = OperandScale::kSingle;
int operand_count = node->operand_count();
for (int i = 0; i < operand_count; ++i) {
switch (operand_type_infos[i]) {
case OperandTypeInfo::kScalableSignedByte: {
uint32_t operand = node->operand(i);
operand_scale =
std::max(operand_scale, OperandScaleForScalableSignedByte(operand));
break;
}
case OperandTypeInfo::kScalableUnsignedByte: {
uint32_t operand = node->operand(i);
operand_scale = std::max(operand_scale,
OperandScaleForScalableUnsignedByte(operand));
break;
}
case OperandTypeInfo::kFixedUnsignedByte:
case OperandTypeInfo::kFixedUnsignedShort:
break;
case OperandTypeInfo::kNone:
UNREACHABLE();
break;
}
}
return operand_scale;
}
} // namespace
void BytecodeArrayWriter::EmitBytecode(const BytecodeNode* const node) { void BytecodeArrayWriter::EmitBytecode(const BytecodeNode* const node) {
DCHECK_NE(node->bytecode(), Bytecode::kIllegal); DCHECK_NE(node->bytecode(), Bytecode::kIllegal);
Bytecode bytecode = node->bytecode(); uint8_t buffer[kMaxSizeOfPackedBytecode];
OperandScale operand_scale = node->operand_scale(); uint8_t* buffer_limit = buffer;
OperandScale operand_scale = GetOperandScale(node);
if (operand_scale != OperandScale::kSingle) { if (operand_scale != OperandScale::kSingle) {
Bytecode prefix = Bytecodes::OperandScaleToPrefixBytecode(operand_scale); Bytecode prefix = Bytecodes::OperandScaleToPrefixBytecode(operand_scale);
bytecodes()->push_back(Bytecodes::ToByte(prefix)); *buffer_limit++ = Bytecodes::ToByte(prefix);
} }
bytecodes()->push_back(Bytecodes::ToByte(bytecode));
Bytecode bytecode = node->bytecode();
*buffer_limit++ = Bytecodes::ToByte(bytecode);
const uint32_t* const operands = node->operands(); const uint32_t* const operands = node->operands();
const int operand_count = node->operand_count(); const OperandType* operand_types = Bytecodes::GetOperandTypes(bytecode);
const OperandSize* operand_sizes = const int operand_count = Bytecodes::NumberOfOperands(bytecode);
Bytecodes::GetOperandSizes(bytecode, operand_scale);
for (int i = 0; i < operand_count; ++i) { for (int i = 0; i < operand_count; ++i) {
switch (operand_sizes[i]) { OperandSize operand_size =
Bytecodes::SizeOfOperand(operand_types[i], operand_scale);
switch (operand_size) {
case OperandSize::kNone: case OperandSize::kNone:
UNREACHABLE(); UNREACHABLE();
break; break;
case OperandSize::kByte: case OperandSize::kByte:
bytecodes()->push_back(static_cast<uint8_t>(operands[i])); *buffer_limit++ = static_cast<uint8_t>(operands[i]);
break; break;
case OperandSize::kShort: { case OperandSize::kShort: {
const uint8_t* raw_operand = WriteUnalignedUInt16(buffer_limit, operands[i]);
reinterpret_cast<const uint8_t*>(&operands[i]); buffer_limit += 2;
bytecodes()->push_back(raw_operand[0]);
bytecodes()->push_back(raw_operand[1]);
break; break;
} }
case OperandSize::kQuad: { case OperandSize::kQuad: {
const uint8_t* raw_operand = WriteUnalignedUInt32(buffer_limit, operands[i]);
reinterpret_cast<const uint8_t*>(&operands[i]); buffer_limit += 4;
bytecodes()->push_back(raw_operand[0]);
bytecodes()->push_back(raw_operand[1]);
bytecodes()->push_back(raw_operand[2]);
bytecodes()->push_back(raw_operand[3]);
break; break;
} }
} }
int count = Bytecodes::GetNumberOfRegistersRepresentedBy(operand_types[i]);
if (count == 0) {
continue;
}
// NB operand_types is terminated by OperandType::kNone so
// operand_types[i + 1] is valid whilst i < operand_count.
if (operand_types[i + 1] == OperandType::kRegCount) {
count = static_cast<int>(operands[i]);
}
Register reg = Register::FromOperand(static_cast<int32_t>(operands[i]));
max_register_count_ = std::max(max_register_count_, reg.index() + count);
} }
DCHECK_LE(buffer_limit, buffer + sizeof(buffer));
bytecodes()->insert(bytecodes()->end(), buffer, buffer_limit);
} }
// static // static
...@@ -175,17 +247,18 @@ void BytecodeArrayWriter::PatchJumpWith8BitOperand(size_t jump_location, ...@@ -175,17 +247,18 @@ void BytecodeArrayWriter::PatchJumpWith8BitOperand(size_t jump_location,
DCHECK(Bytecodes::IsJumpImmediate(jump_bytecode)); DCHECK(Bytecodes::IsJumpImmediate(jump_bytecode));
size_t operand_location = jump_location + 1; size_t operand_location = jump_location + 1;
DCHECK_EQ(bytecodes()->at(operand_location), k8BitJumpPlaceholder); DCHECK_EQ(bytecodes()->at(operand_location), k8BitJumpPlaceholder);
if (Bytecodes::ScaleForSignedOperand(delta) == OperandScale::kSingle) { if (Bytecodes::SizeForSignedOperand(delta) == OperandSize::kByte) {
// The jump fits within the range of an Imm8 operand, so cancel // The jump fits within the range of an Imm operand, so cancel
// the reservation and jump directly. // the reservation and jump directly.
constant_array_builder()->DiscardReservedEntry(OperandSize::kByte); constant_array_builder()->DiscardReservedEntry(OperandSize::kByte);
bytecodes()->at(operand_location) = static_cast<uint8_t>(delta); bytecodes()->at(operand_location) = static_cast<uint8_t>(delta);
} else { } else {
// The jump does not fit within the range of an Imm8 operand, so // The jump does not fit within the range of an Imm operand, so
// commit reservation putting the offset into the constant pool, // commit reservation putting the offset into the constant pool,
// and update the jump instruction and operand. // and update the jump instruction and operand.
size_t entry = constant_array_builder()->CommitReservedEntry( size_t entry = constant_array_builder()->CommitReservedEntry(
OperandSize::kByte, Smi::FromInt(delta)); OperandSize::kByte, Smi::FromInt(delta));
DCHECK_LE(entry, kMaxUInt32);
DCHECK_EQ(Bytecodes::SizeForUnsignedOperand(static_cast<uint32_t>(entry)), DCHECK_EQ(Bytecodes::SizeForUnsignedOperand(static_cast<uint32_t>(entry)),
OperandSize::kByte); OperandSize::kByte);
jump_bytecode = GetJumpWithConstantOperand(jump_bytecode); jump_bytecode = GetJumpWithConstantOperand(jump_bytecode);
...@@ -200,21 +273,14 @@ void BytecodeArrayWriter::PatchJumpWith16BitOperand(size_t jump_location, ...@@ -200,21 +273,14 @@ void BytecodeArrayWriter::PatchJumpWith16BitOperand(size_t jump_location,
DCHECK(Bytecodes::IsJumpImmediate(jump_bytecode)); DCHECK(Bytecodes::IsJumpImmediate(jump_bytecode));
size_t operand_location = jump_location + 1; size_t operand_location = jump_location + 1;
uint8_t operand_bytes[2]; uint8_t operand_bytes[2];
if (Bytecodes::ScaleForSignedOperand(delta) <= OperandScale::kDouble) { if (Bytecodes::SizeForSignedOperand(delta) <= OperandSize::kShort) {
// The jump fits within the range of an Imm16 operand, so cancel
// the reservation and jump directly.
constant_array_builder()->DiscardReservedEntry(OperandSize::kShort); constant_array_builder()->DiscardReservedEntry(OperandSize::kShort);
WriteUnalignedUInt16(operand_bytes, static_cast<uint16_t>(delta)); WriteUnalignedUInt16(operand_bytes, static_cast<uint16_t>(delta));
} else { } else {
// The jump does not fit within the range of an Imm16 operand, so
// commit reservation putting the offset into the constant pool,
// and update the jump instruction and operand.
size_t entry = constant_array_builder()->CommitReservedEntry(
OperandSize::kShort, Smi::FromInt(delta));
DCHECK_EQ(Bytecodes::SizeForUnsignedOperand(static_cast<uint32_t>(entry)),
OperandSize::kShort);
jump_bytecode = GetJumpWithConstantOperand(jump_bytecode); jump_bytecode = GetJumpWithConstantOperand(jump_bytecode);
bytecodes()->at(jump_location) = Bytecodes::ToByte(jump_bytecode); bytecodes()->at(jump_location) = Bytecodes::ToByte(jump_bytecode);
size_t entry = constant_array_builder()->CommitReservedEntry(
OperandSize::kShort, Smi::FromInt(delta));
WriteUnalignedUInt16(operand_bytes, static_cast<uint16_t>(entry)); WriteUnalignedUInt16(operand_bytes, static_cast<uint16_t>(entry));
} }
DCHECK(bytecodes()->at(operand_location) == k8BitJumpPlaceholder && DCHECK(bytecodes()->at(operand_location) == k8BitJumpPlaceholder &&
...@@ -285,8 +351,8 @@ void BytecodeArrayWriter::EmitJump(BytecodeNode* node, BytecodeLabel* label) { ...@@ -285,8 +351,8 @@ void BytecodeArrayWriter::EmitJump(BytecodeNode* node, BytecodeLabel* label) {
// Label has been bound already so this is a backwards jump. // Label has been bound already so this is a backwards jump.
size_t abs_delta = current_offset - label->offset(); size_t abs_delta = current_offset - label->offset();
int delta = -static_cast<int>(abs_delta); int delta = -static_cast<int>(abs_delta);
OperandScale operand_scale = Bytecodes::ScaleForSignedOperand(delta); OperandSize operand_size = Bytecodes::SizeForSignedOperand(delta);
if (operand_scale > OperandScale::kSingle) { if (operand_size > OperandSize::kByte) {
// Adjust for scaling byte prefix for wide jump offset. // Adjust for scaling byte prefix for wide jump offset.
DCHECK_LE(delta, 0); DCHECK_LE(delta, 0);
delta -= 1; delta -= 1;
......
...@@ -33,7 +33,7 @@ class BytecodeArrayWriter final : public BytecodePipelineStage { ...@@ -33,7 +33,7 @@ class BytecodeArrayWriter final : public BytecodePipelineStage {
void BindLabel(BytecodeLabel* label) override; void BindLabel(BytecodeLabel* label) override;
void BindLabel(const BytecodeLabel& target, BytecodeLabel* label) override; void BindLabel(const BytecodeLabel& target, BytecodeLabel* label) override;
Handle<BytecodeArray> ToBytecodeArray( Handle<BytecodeArray> ToBytecodeArray(
Isolate* isolate, int register_count, int parameter_count, Isolate* isolate, int fixed_register_count, int parameter_count,
Handle<FixedArray> handler_table) override; Handle<FixedArray> handler_table) override;
private: private:
...@@ -69,8 +69,10 @@ class BytecodeArrayWriter final : public BytecodePipelineStage { ...@@ -69,8 +69,10 @@ class BytecodeArrayWriter final : public BytecodePipelineStage {
ConstantArrayBuilder* constant_array_builder() { ConstantArrayBuilder* constant_array_builder() {
return constant_array_builder_; return constant_array_builder_;
} }
int max_register_count() { return max_register_count_; }
ZoneVector<uint8_t> bytecodes_; ZoneVector<uint8_t> bytecodes_;
int max_register_count_;
int unbound_jumps_; int unbound_jumps_;
SourcePositionTableBuilder source_position_table_builder_; SourcePositionTableBuilder source_position_table_builder_;
ConstantArrayBuilder* constant_array_builder_; ConstantArrayBuilder* constant_array_builder_;
......
...@@ -14,10 +14,10 @@ BytecodeDeadCodeOptimizer::BytecodeDeadCodeOptimizer( ...@@ -14,10 +14,10 @@ BytecodeDeadCodeOptimizer::BytecodeDeadCodeOptimizer(
// override // override
Handle<BytecodeArray> BytecodeDeadCodeOptimizer::ToBytecodeArray( Handle<BytecodeArray> BytecodeDeadCodeOptimizer::ToBytecodeArray(
Isolate* isolate, int register_count, int parameter_count, Isolate* isolate, int fixed_register_count, int parameter_count,
Handle<FixedArray> handler_table) { Handle<FixedArray> handler_table) {
return next_stage_->ToBytecodeArray(isolate, register_count, parameter_count, return next_stage_->ToBytecodeArray(isolate, fixed_register_count,
handler_table); parameter_count, handler_table);
} }
// override // override
......
...@@ -24,7 +24,7 @@ class BytecodeDeadCodeOptimizer final : public BytecodePipelineStage, ...@@ -24,7 +24,7 @@ class BytecodeDeadCodeOptimizer final : public BytecodePipelineStage,
void BindLabel(BytecodeLabel* label) override; void BindLabel(BytecodeLabel* label) override;
void BindLabel(const BytecodeLabel& target, BytecodeLabel* label) override; void BindLabel(const BytecodeLabel& target, BytecodeLabel* label) override;
Handle<BytecodeArray> ToBytecodeArray( Handle<BytecodeArray> ToBytecodeArray(
Isolate* isolate, int register_count, int parameter_count, Isolate* isolate, int fixed_register_count, int parameter_count,
Handle<FixedArray> handler_table) override; Handle<FixedArray> handler_table) override;
private: private:
......
// 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-operands.h"
#include <iomanip>
namespace v8 {
namespace internal {
namespace interpreter {
namespace {
const char* AccumulatorUseToString(AccumulatorUse accumulator_use) {
switch (accumulator_use) {
case AccumulatorUse::kNone:
return "None";
case AccumulatorUse::kRead:
return "Read";
case AccumulatorUse::kWrite:
return "Write";
case AccumulatorUse::kReadWrite:
return "ReadWrite";
}
UNREACHABLE();
return "";
}
const char* OperandTypeToString(OperandType operand_type) {
switch (operand_type) {
#define CASE(Name, _) \
case OperandType::k##Name: \
return #Name;
OPERAND_TYPE_LIST(CASE)
#undef CASE
}
UNREACHABLE();
return "";
}
const char* OperandScaleToString(OperandScale operand_scale) {
switch (operand_scale) {
#define CASE(Name, _) \
case OperandScale::k##Name: \
return #Name;
OPERAND_SCALE_LIST(CASE)
#undef CASE
}
UNREACHABLE();
return "";
}
const char* OperandSizeToString(OperandSize operand_size) {
switch (operand_size) {
case OperandSize::kNone:
return "None";
case OperandSize::kByte:
return "Byte";
case OperandSize::kShort:
return "Short";
case OperandSize::kQuad:
return "Quad";
}
UNREACHABLE();
return "";
}
} // namespace
std::ostream& operator<<(std::ostream& os, const AccumulatorUse& use) {
return os << AccumulatorUseToString(use);
}
std::ostream& operator<<(std::ostream& os, const OperandSize& operand_size) {
return os << OperandSizeToString(operand_size);
}
std::ostream& operator<<(std::ostream& os, const OperandScale& operand_scale) {
return os << OperandScaleToString(operand_scale);
}
std::ostream& operator<<(std::ostream& os, const OperandType& operand_type) {
return os << OperandTypeToString(operand_type);
}
} // namespace interpreter
} // namespace internal
} // namespace v8
// 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_OPERANDS_H_
#define V8_INTERPRETER_BYTECODE_OPERANDS_H_
#include "src/globals.h"
namespace v8 {
namespace internal {
namespace interpreter {
#define INVALID_OPERAND_TYPE_LIST(V) V(None, OperandTypeInfo::kNone)
#define REGISTER_INPUT_OPERAND_TYPE_LIST(V) \
V(MaybeReg, OperandTypeInfo::kScalableSignedByte) \
V(Reg, OperandTypeInfo::kScalableSignedByte) \
V(RegPair, OperandTypeInfo::kScalableSignedByte)
#define REGISTER_OUTPUT_OPERAND_TYPE_LIST(V) \
V(RegOut, OperandTypeInfo::kScalableSignedByte) \
V(RegOutPair, OperandTypeInfo::kScalableSignedByte) \
V(RegOutTriple, OperandTypeInfo::kScalableSignedByte)
#define SCALAR_OPERAND_TYPE_LIST(V) \
V(Flag8, OperandTypeInfo::kFixedUnsignedByte) \
V(IntrinsicId, OperandTypeInfo::kFixedUnsignedByte) \
V(Idx, OperandTypeInfo::kScalableUnsignedByte) \
V(UImm, OperandTypeInfo::kScalableUnsignedByte) \
V(Imm, OperandTypeInfo::kScalableSignedByte) \
V(RegCount, OperandTypeInfo::kScalableUnsignedByte) \
V(RuntimeId, OperandTypeInfo::kFixedUnsignedShort)
#define REGISTER_OPERAND_TYPE_LIST(V) \
REGISTER_INPUT_OPERAND_TYPE_LIST(V) \
REGISTER_OUTPUT_OPERAND_TYPE_LIST(V)
#define NON_REGISTER_OPERAND_TYPE_LIST(V) \
INVALID_OPERAND_TYPE_LIST(V) \
SCALAR_OPERAND_TYPE_LIST(V)
// The list of operand types used by bytecodes.
#define OPERAND_TYPE_LIST(V) \
NON_REGISTER_OPERAND_TYPE_LIST(V) \
REGISTER_OPERAND_TYPE_LIST(V)
// Enumeration of scaling factors applicable to scalable operands. Code
// relies on being able to cast values to integer scaling values.
#define OPERAND_SCALE_LIST(V) \
V(Single, 1) \
V(Double, 2) \
V(Quadruple, 4)
enum class OperandScale : uint8_t {
#define DECLARE_OPERAND_SCALE(Name, Scale) k##Name = Scale,
OPERAND_SCALE_LIST(DECLARE_OPERAND_SCALE)
#undef DECLARE_OPERAND_SCALE
kLast = kQuadruple
};
// Enumeration of the size classes of operand types used by
// bytecodes. Code relies on being able to cast values to integer
// types to get the size in bytes.
enum class OperandSize : uint8_t {
kNone = 0,
kByte = 1,
kShort = 2,
kQuad = 4,
kLast = kQuad
};
// Primitive operand info used that summarize properties of operands.
// Columns are Name, IsScalable, IsUnsigned, UnscaledSize.
#define OPERAND_TYPE_INFO_LIST(V) \
V(None, false, false, OperandSize::kNone) \
V(ScalableSignedByte, true, false, OperandSize::kByte) \
V(ScalableUnsignedByte, true, true, OperandSize::kByte) \
V(FixedUnsignedByte, false, true, OperandSize::kByte) \
V(FixedUnsignedShort, false, true, OperandSize::kShort)
enum class OperandTypeInfo : uint8_t {
#define DECLARE_OPERAND_TYPE_INFO(Name, ...) k##Name,
OPERAND_TYPE_INFO_LIST(DECLARE_OPERAND_TYPE_INFO)
#undef DECLARE_OPERAND_TYPE_INFO
};
// Enumeration of operand types used by bytecodes.
enum class OperandType : uint8_t {
#define DECLARE_OPERAND_TYPE(Name, _) k##Name,
OPERAND_TYPE_LIST(DECLARE_OPERAND_TYPE)
#undef DECLARE_OPERAND_TYPE
#define COUNT_OPERAND_TYPES(x, _) +1
// The COUNT_OPERAND macro will turn this into kLast = -1 +1 +1... which will
// evaluate to the same value as the last operand.
kLast = -1 OPERAND_TYPE_LIST(COUNT_OPERAND_TYPES)
#undef COUNT_OPERAND_TYPES
};
enum class AccumulatorUse : uint8_t {
kNone = 0,
kRead = 1 << 0,
kWrite = 1 << 1,
kReadWrite = kRead | kWrite
};
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) {
int result = static_cast<int>(lhs) | static_cast<int>(rhs);
return static_cast<AccumulatorUse>(result);
}
std::ostream& operator<<(std::ostream& os, const AccumulatorUse& use);
std::ostream& operator<<(std::ostream& os, const OperandScale& operand_scale);
std::ostream& operator<<(std::ostream& os, const OperandSize& operand_size);
std::ostream& operator<<(std::ostream& os, const OperandType& operand_type);
} // namespace interpreter
} // namespace internal
} // namespace v8
#endif // V8_INTERPRETER_BYTECODE_OPERANDS_H_
...@@ -13,17 +13,17 @@ namespace interpreter { ...@@ -13,17 +13,17 @@ namespace interpreter {
BytecodePeepholeOptimizer::BytecodePeepholeOptimizer( BytecodePeepholeOptimizer::BytecodePeepholeOptimizer(
BytecodePipelineStage* next_stage) BytecodePipelineStage* next_stage)
: next_stage_(next_stage), last_(Bytecode::kIllegal) { : next_stage_(next_stage) {
InvalidateLast(); InvalidateLast();
} }
// override // override
Handle<BytecodeArray> BytecodePeepholeOptimizer::ToBytecodeArray( Handle<BytecodeArray> BytecodePeepholeOptimizer::ToBytecodeArray(
Isolate* isolate, int register_count, int parameter_count, Isolate* isolate, int fixed_register_count, int parameter_count,
Handle<FixedArray> handler_table) { Handle<FixedArray> handler_table) {
Flush(); Flush();
return next_stage_->ToBytecodeArray(isolate, register_count, parameter_count, return next_stage_->ToBytecodeArray(isolate, fixed_register_count,
handler_table); parameter_count, handler_table);
} }
// override // override
...@@ -142,7 +142,7 @@ void TransformLdaSmiBinaryOpToBinaryOpWithSmi(Bytecode new_bytecode, ...@@ -142,7 +142,7 @@ void TransformLdaSmiBinaryOpToBinaryOpWithSmi(Bytecode new_bytecode,
current->set_bytecode(new_bytecode, last->operand(0), current->operand(0), current->set_bytecode(new_bytecode, last->operand(0), current->operand(0),
current->operand(1)); current->operand(1));
if (last->source_info().is_valid()) { if (last->source_info().is_valid()) {
current->source_info_ptr()->Clone(last->source_info()); current->source_info().Clone(last->source_info());
} }
} }
...@@ -153,7 +153,7 @@ void TransformLdaZeroBinaryOpToBinaryOpWithZero(Bytecode new_bytecode, ...@@ -153,7 +153,7 @@ void TransformLdaZeroBinaryOpToBinaryOpWithZero(Bytecode new_bytecode,
current->set_bytecode(new_bytecode, 0, current->operand(0), current->set_bytecode(new_bytecode, 0, current->operand(0),
current->operand(1)); current->operand(1));
if (last->source_info().is_valid()) { if (last->source_info().is_valid()) {
current->source_info_ptr()->Clone(last->source_info()); current->source_info().Clone(last->source_info());
} }
} }
...@@ -223,7 +223,7 @@ void BytecodePeepholeOptimizer::ElideLastAction( ...@@ -223,7 +223,7 @@ void BytecodePeepholeOptimizer::ElideLastAction(
// |node| can not have a valid source position if the source // |node| can not have a valid source position if the source
// position of last() is valid (per rules in // position of last() is valid (per rules in
// CanElideLastBasedOnSourcePosition()). // CanElideLastBasedOnSourcePosition()).
node->source_info_ptr()->Clone(last()->source_info()); node->source_info().Clone(last()->source_info());
} }
SetLast(node); SetLast(node);
} else { } else {
...@@ -314,7 +314,7 @@ void BytecodePeepholeOptimizer::ElideLastBeforeJumpAction( ...@@ -314,7 +314,7 @@ void BytecodePeepholeOptimizer::ElideLastBeforeJumpAction(
if (!CanElideLastBasedOnSourcePosition(node)) { if (!CanElideLastBasedOnSourcePosition(node)) {
next_stage()->Write(last()); next_stage()->Write(last());
} else if (!node->source_info().is_valid()) { } else if (!node->source_info().is_valid()) {
node->source_info_ptr()->Clone(last()->source_info()); node->source_info().Clone(last()->source_info());
} }
InvalidateLast(); InvalidateLast();
} }
......
...@@ -28,7 +28,7 @@ class BytecodePeepholeOptimizer final : public BytecodePipelineStage, ...@@ -28,7 +28,7 @@ class BytecodePeepholeOptimizer final : public BytecodePipelineStage,
void BindLabel(BytecodeLabel* label) override; void BindLabel(BytecodeLabel* label) override;
void BindLabel(const BytecodeLabel& target, BytecodeLabel* label) override; void BindLabel(const BytecodeLabel& target, BytecodeLabel* label) override;
Handle<BytecodeArray> ToBytecodeArray( Handle<BytecodeArray> ToBytecodeArray(
Isolate* isolate, int register_count, int parameter_count, Isolate* isolate, int fixed_register_count, int parameter_count,
Handle<FixedArray> handler_table) override; Handle<FixedArray> handler_table) override;
private: private:
......
...@@ -11,6 +11,45 @@ namespace v8 { ...@@ -11,6 +11,45 @@ namespace v8 {
namespace internal { namespace internal {
namespace interpreter { namespace interpreter {
BytecodeNode::BytecodeNode(Bytecode bytecode) {
DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 0);
bytecode_ = bytecode;
}
BytecodeNode::BytecodeNode(Bytecode bytecode, uint32_t operand0) {
DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 1);
bytecode_ = bytecode;
operands_[0] = operand0;
}
BytecodeNode::BytecodeNode(Bytecode bytecode, uint32_t operand0,
uint32_t operand1) {
DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 2);
bytecode_ = bytecode;
operands_[0] = operand0;
operands_[1] = operand1;
}
BytecodeNode::BytecodeNode(Bytecode bytecode, uint32_t operand0,
uint32_t operand1, uint32_t operand2) {
DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 3);
bytecode_ = bytecode;
operands_[0] = operand0;
operands_[1] = operand1;
operands_[2] = operand2;
}
BytecodeNode::BytecodeNode(Bytecode bytecode, uint32_t operand0,
uint32_t operand1, uint32_t operand2,
uint32_t operand3) {
DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 4);
bytecode_ = bytecode;
operands_[0] = operand0;
operands_[1] = operand1;
operands_[2] = operand2;
operands_[3] = operand3;
}
BytecodeNode::BytecodeNode(const BytecodeNode& other) { BytecodeNode::BytecodeNode(const BytecodeNode& other) {
memcpy(this, &other, sizeof(other)); memcpy(this, &other, sizeof(other));
} }
...@@ -44,6 +83,23 @@ void BytecodeNode::Print(std::ostream& os) const { ...@@ -44,6 +83,23 @@ void BytecodeNode::Print(std::ostream& os) const {
#endif // DEBUG #endif // DEBUG
} }
void BytecodeNode::Transform(Bytecode new_bytecode, uint32_t extra_operand) {
DCHECK_EQ(Bytecodes::NumberOfOperands(new_bytecode),
Bytecodes::NumberOfOperands(bytecode()) + 1);
DCHECK(Bytecodes::NumberOfOperands(bytecode()) < 1 ||
Bytecodes::GetOperandType(new_bytecode, 0) ==
Bytecodes::GetOperandType(bytecode(), 0));
DCHECK(Bytecodes::NumberOfOperands(bytecode()) < 2 ||
Bytecodes::GetOperandType(new_bytecode, 1) ==
Bytecodes::GetOperandType(bytecode(), 1));
DCHECK(Bytecodes::NumberOfOperands(bytecode()) < 3 ||
Bytecodes::GetOperandType(new_bytecode, 2) ==
Bytecodes::GetOperandType(bytecode(), 2));
DCHECK(Bytecodes::NumberOfOperands(bytecode()) < 4);
operands_[operand_count()] = extra_operand;
bytecode_ = new_bytecode;
}
bool BytecodeNode::operator==(const BytecodeNode& other) const { bool BytecodeNode::operator==(const BytecodeNode& other) const {
if (this == &other) { if (this == &other) {
return true; return true;
......
...@@ -47,7 +47,7 @@ class BytecodePipelineStage { ...@@ -47,7 +47,7 @@ class BytecodePipelineStage {
// Flush the pipeline and generate a bytecode array. // Flush the pipeline and generate a bytecode array.
virtual Handle<BytecodeArray> ToBytecodeArray( virtual Handle<BytecodeArray> ToBytecodeArray(
Isolate* isolate, int register_count, int parameter_count, Isolate* isolate, int fixed_register_count, int parameter_count,
Handle<FixedArray> handler_table) = 0; Handle<FixedArray> handler_table) = 0;
}; };
...@@ -134,69 +134,21 @@ class BytecodeSourceInfo final { ...@@ -134,69 +134,21 @@ class BytecodeSourceInfo final {
PositionType position_type_; PositionType position_type_;
int source_position_; int source_position_;
DISALLOW_COPY_AND_ASSIGN(BytecodeSourceInfo);
}; };
// A container for a generated bytecode, it's operands, and source information. // A container for a generated bytecode, it's operands, and source information.
// These must be allocated by a BytecodeNodeAllocator instance. // These must be allocated by a BytecodeNodeAllocator instance.
class BytecodeNode final : ZoneObject { class BytecodeNode final : ZoneObject {
public: public:
INLINE(BytecodeNode(const Bytecode bytecode, explicit BytecodeNode(Bytecode bytecode = Bytecode::kIllegal);
BytecodeSourceInfo* source_info = nullptr)) BytecodeNode(Bytecode bytecode, uint32_t operand0);
: bytecode_(bytecode), BytecodeNode(Bytecode bytecode, uint32_t operand0, uint32_t operand1);
operand_count_(0), BytecodeNode(Bytecode bytecode, uint32_t operand0, uint32_t operand1,
operand_scale_(OperandScale::kSingle) { uint32_t operand2);
DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), operand_count()); BytecodeNode(Bytecode bytecode, uint32_t operand0, uint32_t operand1,
AttachSourceInfo(source_info); uint32_t operand2, uint32_t operand3);
}
INLINE(BytecodeNode(const Bytecode bytecode, uint32_t operand0,
BytecodeSourceInfo* source_info = nullptr))
: bytecode_(bytecode),
operand_count_(1),
operand_scale_(OperandScale::kSingle) {
DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), operand_count());
SetOperand(0, operand0);
AttachSourceInfo(source_info);
}
INLINE(BytecodeNode(const Bytecode bytecode, uint32_t operand0,
uint32_t operand1,
BytecodeSourceInfo* source_info = nullptr))
: bytecode_(bytecode),
operand_count_(2),
operand_scale_(OperandScale::kSingle) {
DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), operand_count());
SetOperand(0, operand0);
SetOperand(1, operand1);
AttachSourceInfo(source_info);
}
INLINE(BytecodeNode(const Bytecode bytecode, uint32_t operand0,
uint32_t operand1, uint32_t operand2,
BytecodeSourceInfo* source_info = nullptr))
: bytecode_(bytecode),
operand_count_(3),
operand_scale_(OperandScale::kSingle) {
DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), operand_count());
SetOperand(0, operand0);
SetOperand(1, operand1);
SetOperand(2, operand2);
AttachSourceInfo(source_info);
}
INLINE(BytecodeNode(const Bytecode bytecode, uint32_t operand0,
uint32_t operand1, uint32_t operand2, uint32_t operand3,
BytecodeSourceInfo* source_info = nullptr))
: bytecode_(bytecode),
operand_count_(4),
operand_scale_(OperandScale::kSingle) {
DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), operand_count());
SetOperand(0, operand0);
SetOperand(1, operand1);
SetOperand(2, operand2);
SetOperand(3, operand3);
AttachSourceInfo(source_info);
}
BytecodeNode(const BytecodeNode& other); BytecodeNode(const BytecodeNode& other);
BytecodeNode& operator=(const BytecodeNode& other); BytecodeNode& operator=(const BytecodeNode& other);
...@@ -210,33 +162,25 @@ class BytecodeNode final : ZoneObject { ...@@ -210,33 +162,25 @@ class BytecodeNode final : ZoneObject {
void set_bytecode(Bytecode bytecode) { void set_bytecode(Bytecode bytecode) {
DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 0); DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 0);
bytecode_ = bytecode; bytecode_ = bytecode;
operand_count_ = 0;
operand_scale_ = OperandScale::kSingle;
} }
void set_bytecode(Bytecode bytecode, uint32_t operand0) { void set_bytecode(Bytecode bytecode, uint32_t operand0) {
DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 1); DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 1);
bytecode_ = bytecode; bytecode_ = bytecode;
operand_count_ = 1; operands_[0] = operand0;
operand_scale_ = OperandScale::kSingle;
SetOperand(0, operand0);
} }
void set_bytecode(Bytecode bytecode, uint32_t operand0, uint32_t operand1) { void set_bytecode(Bytecode bytecode, uint32_t operand0, uint32_t operand1) {
DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 2); DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 2);
bytecode_ = bytecode; bytecode_ = bytecode;
operand_count_ = 2; operands_[0] = operand0;
operand_scale_ = OperandScale::kSingle; operands_[1] = operand1;
SetOperand(0, operand0);
SetOperand(1, operand1);
} }
void set_bytecode(Bytecode bytecode, uint32_t operand0, uint32_t operand1, void set_bytecode(Bytecode bytecode, uint32_t operand0, uint32_t operand1,
uint32_t operand2) { uint32_t operand2) {
DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 3); DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 3);
bytecode_ = bytecode; bytecode_ = bytecode;
operand_count_ = 3; operands_[0] = operand0;
operand_scale_ = OperandScale::kSingle; operands_[1] = operand1;
SetOperand(0, operand0); operands_[2] = operand2;
SetOperand(1, operand1);
SetOperand(2, operand2);
} }
// Clone |other|. // Clone |other|.
...@@ -247,36 +191,7 @@ class BytecodeNode final : ZoneObject { ...@@ -247,36 +191,7 @@ class BytecodeNode final : ZoneObject {
// Transform to a node representing |new_bytecode| which has one // Transform to a node representing |new_bytecode| which has one
// operand more than the current bytecode. // operand more than the current bytecode.
void Transform(Bytecode new_bytecode, uint32_t extra_operand) { void Transform(Bytecode new_bytecode, uint32_t extra_operand);
DCHECK_EQ(Bytecodes::NumberOfOperands(new_bytecode),
Bytecodes::NumberOfOperands(bytecode()) + 1);
DCHECK(Bytecodes::NumberOfOperands(bytecode()) < 1 ||
Bytecodes::GetOperandType(new_bytecode, 0) ==
Bytecodes::GetOperandType(bytecode(), 0));
DCHECK(Bytecodes::NumberOfOperands(bytecode()) < 2 ||
Bytecodes::GetOperandType(new_bytecode, 1) ==
Bytecodes::GetOperandType(bytecode(), 1));
DCHECK(Bytecodes::NumberOfOperands(bytecode()) < 3 ||
Bytecodes::GetOperandType(new_bytecode, 2) ==
Bytecodes::GetOperandType(bytecode(), 2));
DCHECK(Bytecodes::NumberOfOperands(bytecode()) < 4);
bytecode_ = new_bytecode;
operand_count_++;
SetOperand(operand_count() - 1, extra_operand);
}
// Updates the operand at |operand_index| to |operand|.
void UpdateOperand(int operand_index, uint32_t operand) {
DCHECK_LE(operand_index, Bytecodes::NumberOfOperands(bytecode()));
operands_[operand_index] = operand;
if ((Bytecodes::OperandIsScalableSignedByte(bytecode(), operand_index) &&
Bytecodes::ScaleForSignedOperand(operand) != operand_scale_) ||
(Bytecodes::OperandIsScalableUnsignedByte(bytecode(), operand_index) &&
Bytecodes::ScaleForUnsignedOperand(operand) != operand_scale_)) {
UpdateScale();
}
}
Bytecode bytecode() const { return bytecode_; } Bytecode bytecode() const { return bytecode_; }
...@@ -284,60 +199,22 @@ class BytecodeNode final : ZoneObject { ...@@ -284,60 +199,22 @@ class BytecodeNode final : ZoneObject {
DCHECK_LT(i, operand_count()); DCHECK_LT(i, operand_count());
return operands_[i]; return operands_[i];
} }
uint32_t* operands() { return operands_; }
const uint32_t* operands() const { return operands_; } const uint32_t* operands() const { return operands_; }
int operand_count() const { return operand_count_; } int operand_count() const { return Bytecodes::NumberOfOperands(bytecode_); }
OperandScale operand_scale() const { return operand_scale_; }
const BytecodeSourceInfo& source_info() const { return source_info_; } const BytecodeSourceInfo& source_info() const { return source_info_; }
BytecodeSourceInfo* source_info_ptr() { return &source_info_; } BytecodeSourceInfo& source_info() { return source_info_; }
bool operator==(const BytecodeNode& other) const; bool operator==(const BytecodeNode& other) const;
bool operator!=(const BytecodeNode& other) const { return !(*this == other); } bool operator!=(const BytecodeNode& other) const { return !(*this == other); }
private: private:
INLINE(void AttachSourceInfo(BytecodeSourceInfo* source_info)) { static const int kInvalidPosition = kMinInt;
if (source_info && source_info->is_valid()) {
// Statement positions need to be emitted immediately. Expression
// positions can be pushed back until a bytecode is found that can
// throw (if expression position filtering is turned on). We only
// invalidate the existing source position information if it is used.
if (source_info->is_statement() ||
!FLAG_ignition_filter_expression_positions ||
!Bytecodes::IsWithoutExternalSideEffects(bytecode())) {
source_info_.Clone(*source_info);
source_info->set_invalid();
}
}
}
INLINE(void UpdateScaleForOperand(int operand_index, uint32_t operand)) {
if (Bytecodes::OperandIsScalableSignedByte(bytecode(), operand_index)) {
operand_scale_ =
std::max(operand_scale_, Bytecodes::ScaleForSignedOperand(operand));
} else if (Bytecodes::OperandIsScalableUnsignedByte(bytecode(),
operand_index)) {
operand_scale_ =
std::max(operand_scale_, Bytecodes::ScaleForUnsignedOperand(operand));
}
}
INLINE(void SetOperand(int operand_index, uint32_t operand)) {
operands_[operand_index] = operand;
UpdateScaleForOperand(operand_index, operand);
}
void UpdateScale() {
operand_scale_ = OperandScale::kSingle;
for (int i = 0; i < operand_count(); i++) {
UpdateScaleForOperand(i, operands_[i]);
}
}
Bytecode bytecode_; Bytecode bytecode_;
uint32_t operands_[Bytecodes::kMaxOperands]; uint32_t operands_[Bytecodes::kMaxOperands];
int operand_count_;
OperandScale operand_scale_;
BytecodeSourceInfo source_info_; BytecodeSourceInfo source_info_;
}; };
......
...@@ -174,7 +174,6 @@ BytecodeRegisterOptimizer::BytecodeRegisterOptimizer( ...@@ -174,7 +174,6 @@ BytecodeRegisterOptimizer::BytecodeRegisterOptimizer(
int parameter_count, BytecodePipelineStage* next_stage) int parameter_count, BytecodePipelineStage* next_stage)
: accumulator_(Register::virtual_accumulator()), : accumulator_(Register::virtual_accumulator()),
temporary_base_(register_allocator->allocation_base()), temporary_base_(register_allocator->allocation_base()),
max_register_index_(register_allocator->allocation_base() - 1),
register_info_table_(zone), register_info_table_(zone),
equivalence_id_(0), equivalence_id_(0),
next_stage_(next_stage), next_stage_(next_stage),
...@@ -209,17 +208,15 @@ BytecodeRegisterOptimizer::BytecodeRegisterOptimizer( ...@@ -209,17 +208,15 @@ BytecodeRegisterOptimizer::BytecodeRegisterOptimizer(
// override // override
Handle<BytecodeArray> BytecodeRegisterOptimizer::ToBytecodeArray( Handle<BytecodeArray> BytecodeRegisterOptimizer::ToBytecodeArray(
Isolate* isolate, int register_count, int parameter_count, Isolate* isolate, int fixed_register_count, int parameter_count,
Handle<FixedArray> handler_table) { Handle<FixedArray> handler_table) {
FlushState(); FlushState();
return next_stage_->ToBytecodeArray(isolate, max_register_index_ + 1, return next_stage_->ToBytecodeArray(isolate, fixed_register_count,
parameter_count, handler_table); parameter_count, handler_table);
} }
// override // override
void BytecodeRegisterOptimizer::Write(BytecodeNode* node) { void BytecodeRegisterOptimizer::Write(BytecodeNode* node) {
// Jumps are handled by WriteJump.
DCHECK(!Bytecodes::IsJump(node->bytecode()));
// //
// Transfers with observable registers as the destination will be // Transfers with observable registers as the destination will be
// immediately materialized so the source position information will // immediately materialized so the source position information will
...@@ -248,16 +245,18 @@ void BytecodeRegisterOptimizer::Write(BytecodeNode* node) { ...@@ -248,16 +245,18 @@ void BytecodeRegisterOptimizer::Write(BytecodeNode* node) {
break; break;
} }
if (node->bytecode() == Bytecode::kDebugger || if (Bytecodes::IsJump(node->bytecode()) ||
node->bytecode() == Bytecode::kDebugger ||
node->bytecode() == Bytecode::kSuspendGenerator) { node->bytecode() == Bytecode::kSuspendGenerator) {
// All state must be flushed before emitting // All state must be flushed before emitting
// - a jump (due to how bytecode offsets for jumps are evaluated),
// - a call to the debugger (as it can manipulate locals and parameters), // - a call to the debugger (as it can manipulate locals and parameters),
// - a generator suspend (as this involves saving all registers). // - a generator suspend (as this involves saving all registers).
FlushState(); FlushState();
} }
PrepareOperands(node); PrepareOperands(node);
next_stage_->Write(node); WriteToNextStage(node);
} }
// override // override
...@@ -307,29 +306,38 @@ void BytecodeRegisterOptimizer::FlushState() { ...@@ -307,29 +306,38 @@ void BytecodeRegisterOptimizer::FlushState() {
flush_required_ = false; flush_required_ = false;
} }
void BytecodeRegisterOptimizer::WriteToNextStage(BytecodeNode* node) const {
next_stage_->Write(node);
}
void BytecodeRegisterOptimizer::WriteToNextStage(
BytecodeNode* node, const BytecodeSourceInfo& source_info) const {
if (source_info.is_valid()) {
node->source_info().Clone(source_info);
}
next_stage_->Write(node);
}
void BytecodeRegisterOptimizer::OutputRegisterTransfer( void BytecodeRegisterOptimizer::OutputRegisterTransfer(
RegisterInfo* input_info, RegisterInfo* output_info, RegisterInfo* input_info, RegisterInfo* output_info,
BytecodeSourceInfo* source_info) { const BytecodeSourceInfo& source_info) {
Register input = input_info->register_value(); Register input = input_info->register_value();
Register output = output_info->register_value(); Register output = output_info->register_value();
DCHECK_NE(input.index(), output.index()); DCHECK_NE(input.index(), output.index());
if (input == accumulator_) { if (input == accumulator_) {
uint32_t operand = static_cast<uint32_t>(output.ToOperand()); uint32_t operand = static_cast<uint32_t>(output.ToOperand());
BytecodeNode node(Bytecode::kStar, operand, source_info); BytecodeNode node(Bytecode::kStar, operand);
next_stage_->Write(&node); WriteToNextStage(&node, source_info);
} else if (output == accumulator_) { } else if (output == accumulator_) {
uint32_t operand = static_cast<uint32_t>(input.ToOperand()); uint32_t operand = static_cast<uint32_t>(input.ToOperand());
BytecodeNode node(Bytecode::kLdar, operand, source_info); BytecodeNode node(Bytecode::kLdar, operand);
next_stage_->Write(&node); WriteToNextStage(&node, source_info);
} else { } else {
uint32_t operand0 = static_cast<uint32_t>(input.ToOperand()); uint32_t operand0 = static_cast<uint32_t>(input.ToOperand());
uint32_t operand1 = static_cast<uint32_t>(output.ToOperand()); uint32_t operand1 = static_cast<uint32_t>(output.ToOperand());
BytecodeNode node(Bytecode::kMov, operand0, operand1, source_info); BytecodeNode node(Bytecode::kMov, operand0, operand1);
next_stage_->Write(&node); WriteToNextStage(&node, source_info);
}
if (output != accumulator_) {
max_register_index_ = std::max(max_register_index_, output.index());
} }
output_info->set_materialized(true); output_info->set_materialized(true);
} }
...@@ -381,7 +389,7 @@ void BytecodeRegisterOptimizer::AddToEquivalenceSet( ...@@ -381,7 +389,7 @@ void BytecodeRegisterOptimizer::AddToEquivalenceSet(
void BytecodeRegisterOptimizer::RegisterTransfer( void BytecodeRegisterOptimizer::RegisterTransfer(
RegisterInfo* input_info, RegisterInfo* output_info, RegisterInfo* input_info, RegisterInfo* output_info,
BytecodeSourceInfo* source_info) { const BytecodeSourceInfo& source_info) {
// Materialize an alternate in the equivalence set that // Materialize an alternate in the equivalence set that
// |output_info| is leaving. // |output_info| is leaving.
if (output_info->materialized()) { if (output_info->materialized()) {
...@@ -400,41 +408,42 @@ void BytecodeRegisterOptimizer::RegisterTransfer( ...@@ -400,41 +408,42 @@ void BytecodeRegisterOptimizer::RegisterTransfer(
output_info->set_materialized(false); output_info->set_materialized(false);
RegisterInfo* materialized_info = input_info->GetMaterializedEquivalent(); RegisterInfo* materialized_info = input_info->GetMaterializedEquivalent();
OutputRegisterTransfer(materialized_info, output_info, source_info); OutputRegisterTransfer(materialized_info, output_info, source_info);
} else if (source_info->is_valid()) { } else if (source_info.is_valid()) {
// Emit a placeholder nop to maintain source position info. // Emit a placeholder nop to maintain source position info.
EmitNopForSourceInfo(source_info); EmitNopForSourceInfo(source_info);
} }
} }
void BytecodeRegisterOptimizer::EmitNopForSourceInfo( void BytecodeRegisterOptimizer::EmitNopForSourceInfo(
BytecodeSourceInfo* source_info) const { const BytecodeSourceInfo& source_info) const {
DCHECK(source_info->is_valid()); DCHECK(source_info.is_valid());
BytecodeNode nop(Bytecode::kNop, source_info); BytecodeNode nop(Bytecode::kNop);
next_stage_->Write(&nop); nop.source_info().Clone(source_info);
WriteToNextStage(&nop);
} }
void BytecodeRegisterOptimizer::DoLdar(BytecodeNode* node) { void BytecodeRegisterOptimizer::DoLdar(const BytecodeNode* const node) {
Register input = GetRegisterInputOperand( Register input = GetRegisterInputOperand(
0, node->bytecode(), node->operands(), node->operand_count()); 0, node->bytecode(), node->operands(), node->operand_count());
RegisterInfo* input_info = GetRegisterInfo(input); RegisterInfo* input_info = GetRegisterInfo(input);
RegisterTransfer(input_info, accumulator_info_, node->source_info_ptr()); RegisterTransfer(input_info, accumulator_info_, node->source_info());
} }
void BytecodeRegisterOptimizer::DoMov(BytecodeNode* node) { void BytecodeRegisterOptimizer::DoMov(const BytecodeNode* const node) {
Register input = GetRegisterInputOperand( Register input = GetRegisterInputOperand(
0, node->bytecode(), node->operands(), node->operand_count()); 0, node->bytecode(), node->operands(), node->operand_count());
RegisterInfo* input_info = GetRegisterInfo(input); RegisterInfo* input_info = GetRegisterInfo(input);
Register output = GetRegisterOutputOperand( Register output = GetRegisterOutputOperand(
1, node->bytecode(), node->operands(), node->operand_count()); 1, node->bytecode(), node->operands(), node->operand_count());
RegisterInfo* output_info = GetOrCreateRegisterInfo(output); RegisterInfo* output_info = GetOrCreateRegisterInfo(output);
RegisterTransfer(input_info, output_info, node->source_info_ptr()); RegisterTransfer(input_info, output_info, node->source_info());
} }
void BytecodeRegisterOptimizer::DoStar(BytecodeNode* node) { void BytecodeRegisterOptimizer::DoStar(const BytecodeNode* const node) {
Register output = GetRegisterOutputOperand( Register output = GetRegisterOutputOperand(
0, node->bytecode(), node->operands(), node->operand_count()); 0, node->bytecode(), node->operands(), node->operand_count());
RegisterInfo* output_info = GetOrCreateRegisterInfo(output); RegisterInfo* output_info = GetOrCreateRegisterInfo(output);
RegisterTransfer(accumulator_info_, output_info, node->source_info_ptr()); RegisterTransfer(accumulator_info_, output_info, node->source_info());
} }
void BytecodeRegisterOptimizer::PrepareRegisterOutputOperand( void BytecodeRegisterOptimizer::PrepareRegisterOutputOperand(
...@@ -442,8 +451,6 @@ void BytecodeRegisterOptimizer::PrepareRegisterOutputOperand( ...@@ -442,8 +451,6 @@ void BytecodeRegisterOptimizer::PrepareRegisterOutputOperand(
if (reg_info->materialized()) { if (reg_info->materialized()) {
CreateMaterializedEquivalent(reg_info); CreateMaterializedEquivalent(reg_info);
} }
max_register_index_ =
std::max(max_register_index_, reg_info->register_value().index());
reg_info->MoveToNewEquivalenceSet(NextEquivalenceId(), true); reg_info->MoveToNewEquivalenceSet(NextEquivalenceId(), true);
} }
...@@ -474,8 +481,8 @@ Register BytecodeRegisterOptimizer::GetEquivalentRegisterForInputOperand( ...@@ -474,8 +481,8 @@ Register BytecodeRegisterOptimizer::GetEquivalentRegisterForInputOperand(
void BytecodeRegisterOptimizer::PrepareRegisterInputOperand( void BytecodeRegisterOptimizer::PrepareRegisterInputOperand(
BytecodeNode* const node, Register reg, int operand_index) { BytecodeNode* const node, Register reg, int operand_index) {
Register equivalent = GetEquivalentRegisterForInputOperand(reg); Register equivalent = GetEquivalentRegisterForInputOperand(reg);
node->UpdateOperand(operand_index, node->operands()[operand_index] =
static_cast<uint32_t>(equivalent.ToOperand())); static_cast<uint32_t>(equivalent.ToOperand());
} }
void BytecodeRegisterOptimizer::PrepareRegisterRangeInputOperand(Register start, void BytecodeRegisterOptimizer::PrepareRegisterRangeInputOperand(Register start,
......
...@@ -31,7 +31,7 @@ class BytecodeRegisterOptimizer final : public BytecodePipelineStage, ...@@ -31,7 +31,7 @@ class BytecodeRegisterOptimizer final : public BytecodePipelineStage,
void BindLabel(BytecodeLabel* label) override; void BindLabel(BytecodeLabel* label) override;
void BindLabel(const BytecodeLabel& target, BytecodeLabel* label) override; void BindLabel(const BytecodeLabel& target, BytecodeLabel* label) override;
Handle<BytecodeArray> ToBytecodeArray( Handle<BytecodeArray> ToBytecodeArray(
Isolate* isolate, int register_count, int parameter_count, Isolate* isolate, int fixed_register_count, int parameter_count,
Handle<FixedArray> handler_table) override; Handle<FixedArray> handler_table) override;
private: private:
...@@ -44,25 +44,29 @@ class BytecodeRegisterOptimizer final : public BytecodePipelineStage, ...@@ -44,25 +44,29 @@ class BytecodeRegisterOptimizer final : public BytecodePipelineStage,
// Helpers for BytecodePipelineStage interface. // Helpers for BytecodePipelineStage interface.
void FlushState(); void FlushState();
void WriteToNextStage(BytecodeNode* node) const;
void WriteToNextStage(BytecodeNode* node,
const BytecodeSourceInfo& output_info) const;
// Update internal state for register transfer from |input| to // Update internal state for register transfer from |input| to
// |output| using |source_info| as source position information if // |output| using |source_info| as source position information if
// any bytecodes are emitted due to transfer. // any bytecodes are emitted due to transfer.
void RegisterTransfer(RegisterInfo* input, RegisterInfo* output, void RegisterTransfer(RegisterInfo* input, RegisterInfo* output,
BytecodeSourceInfo* source_info); const BytecodeSourceInfo& source_info);
// Emit a register transfer bytecode from |input| to |output|. // Emit a register transfer bytecode from |input| to |output|.
void OutputRegisterTransfer(RegisterInfo* input, RegisterInfo* output, void OutputRegisterTransfer(
BytecodeSourceInfo* source_info = nullptr); RegisterInfo* input, RegisterInfo* output,
const BytecodeSourceInfo& source_info = BytecodeSourceInfo());
// Emits a Nop to preserve source position information in the // Emits a Nop to preserve source position information in the
// bytecode pipeline. // bytecode pipeline.
void EmitNopForSourceInfo(BytecodeSourceInfo* source_info) const; void EmitNopForSourceInfo(const BytecodeSourceInfo& source_info) const;
// Handlers for bytecode nodes for register to register transfers. // Handlers for bytecode nodes for register to register transfers.
void DoLdar(BytecodeNode* node); void DoLdar(const BytecodeNode* const node);
void DoMov(BytecodeNode* node); void DoMov(const BytecodeNode* const node);
void DoStar(BytecodeNode* node); void DoStar(const BytecodeNode* const node);
// Operand processing methods for bytecodes other than those // Operand processing methods for bytecodes other than those
// performing register to register transfers. // performing register to register transfers.
...@@ -129,7 +133,6 @@ class BytecodeRegisterOptimizer final : public BytecodePipelineStage, ...@@ -129,7 +133,6 @@ class BytecodeRegisterOptimizer final : public BytecodePipelineStage,
const Register accumulator_; const Register accumulator_;
RegisterInfo* accumulator_info_; RegisterInfo* accumulator_info_;
const Register temporary_base_; const Register temporary_base_;
int max_register_index_;
// Direct mapping to register info. // Direct mapping to register info.
ZoneVector<RegisterInfo*> register_info_table_; ZoneVector<RegisterInfo*> register_info_table_;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -983,8 +983,6 @@ ...@@ -983,8 +983,6 @@
'interpreter/bytecode-generator.h', 'interpreter/bytecode-generator.h',
'interpreter/bytecode-label.cc', 'interpreter/bytecode-label.cc',
'interpreter/bytecode-label.h', 'interpreter/bytecode-label.h',
'interpreter/bytecode-operands.cc',
'interpreter/bytecode-operands.h',
'interpreter/bytecode-peephole-optimizer.cc', 'interpreter/bytecode-peephole-optimizer.cc',
'interpreter/bytecode-peephole-optimizer.h', 'interpreter/bytecode-peephole-optimizer.h',
'interpreter/bytecode-peephole-table.h', 'interpreter/bytecode-peephole-table.h',
...@@ -2434,10 +2432,7 @@ ...@@ -2434,10 +2432,7 @@
'..', '..',
], ],
'sources': [ 'sources': [
'interpreter/bytecode-operands.h',
'interpreter/bytecode-operands.cc',
'interpreter/bytecode-peephole-table.h', 'interpreter/bytecode-peephole-table.h',
'interpreter/bytecode-traits.h',
'interpreter/bytecodes.h', 'interpreter/bytecodes.h',
'interpreter/bytecodes.cc', 'interpreter/bytecodes.cc',
'interpreter/mkpeephole.cc' 'interpreter/mkpeephole.cc'
......
...@@ -28,78 +28,93 @@ class BytecodeArrayWriterUnittest : public TestWithIsolateAndZone { ...@@ -28,78 +28,93 @@ class BytecodeArrayWriterUnittest : public TestWithIsolateAndZone {
SourcePositionTableBuilder::RECORD_SOURCE_POSITIONS) {} SourcePositionTableBuilder::RECORD_SOURCE_POSITIONS) {}
~BytecodeArrayWriterUnittest() override {} ~BytecodeArrayWriterUnittest() override {}
void Write(Bytecode bytecode, BytecodeSourceInfo info = BytecodeSourceInfo()); void Write(BytecodeNode* node, const BytecodeSourceInfo& info);
void Write(Bytecode bytecode,
const BytecodeSourceInfo& info = BytecodeSourceInfo());
void Write(Bytecode bytecode, uint32_t operand0, void Write(Bytecode bytecode, uint32_t operand0,
BytecodeSourceInfo info = BytecodeSourceInfo()); const BytecodeSourceInfo& info = BytecodeSourceInfo());
void Write(Bytecode bytecode, uint32_t operand0, uint32_t operand1, void Write(Bytecode bytecode, uint32_t operand0, uint32_t operand1,
BytecodeSourceInfo info = BytecodeSourceInfo());
const BytecodeSourceInfo& info = BytecodeSourceInfo());
void Write(Bytecode bytecode, uint32_t operand0, uint32_t operand1, void Write(Bytecode bytecode, uint32_t operand0, uint32_t operand1,
uint32_t operand2, BytecodeSourceInfo info = BytecodeSourceInfo()); uint32_t operand2,
const BytecodeSourceInfo& info = BytecodeSourceInfo());
void Write(Bytecode bytecode, uint32_t operand0, uint32_t operand1, void Write(Bytecode bytecode, uint32_t operand0, uint32_t operand1,
uint32_t operand2, uint32_t operand3, uint32_t operand2, uint32_t operand3,
BytecodeSourceInfo info = BytecodeSourceInfo()); const BytecodeSourceInfo& info = BytecodeSourceInfo());
void WriteJump(Bytecode bytecode, BytecodeLabel* label, void WriteJump(Bytecode bytecode, BytecodeLabel* label,
BytecodeSourceInfo info = BytecodeSourceInfo()); const BytecodeSourceInfo& info = BytecodeSourceInfo());
void WriteJumpLoop(Bytecode bytecode, BytecodeLabel* label, int depth, void WriteJumpLoop(Bytecode bytecode, BytecodeLabel* label, int depth);
BytecodeSourceInfo info = BytecodeSourceInfo());
BytecodeArrayWriter* writer() { return &bytecode_array_writer_; } BytecodeArrayWriter* writer() { return &bytecode_array_writer_; }
ZoneVector<unsigned char>* bytecodes() { return writer()->bytecodes(); } ZoneVector<unsigned char>* bytecodes() { return writer()->bytecodes(); }
SourcePositionTableBuilder* source_position_table_builder() { SourcePositionTableBuilder* source_position_table_builder() {
return writer()->source_position_table_builder(); return writer()->source_position_table_builder();
} }
int max_register_count() { return writer()->max_register_count(); }
private: private:
ConstantArrayBuilder constant_array_builder_; ConstantArrayBuilder constant_array_builder_;
BytecodeArrayWriter bytecode_array_writer_; BytecodeArrayWriter bytecode_array_writer_;
}; };
void BytecodeArrayWriterUnittest::Write(BytecodeNode* node,
const BytecodeSourceInfo& info) {
if (info.is_valid()) {
node->source_info().Clone(info);
}
writer()->Write(node);
}
void BytecodeArrayWriterUnittest::Write(Bytecode bytecode, void BytecodeArrayWriterUnittest::Write(Bytecode bytecode,
BytecodeSourceInfo info) { const BytecodeSourceInfo& info) {
BytecodeNode node(bytecode, &info); BytecodeNode node(bytecode);
writer()->Write(&node); Write(&node, info);
} }
void BytecodeArrayWriterUnittest::Write(Bytecode bytecode, uint32_t operand0, void BytecodeArrayWriterUnittest::Write(Bytecode bytecode, uint32_t operand0,
BytecodeSourceInfo info) { const BytecodeSourceInfo& info) {
BytecodeNode node(bytecode, operand0, &info); BytecodeNode node(bytecode, operand0);
writer()->Write(&node); Write(&node, info);
} }
void BytecodeArrayWriterUnittest::Write(Bytecode bytecode, uint32_t operand0, void BytecodeArrayWriterUnittest::Write(Bytecode bytecode, uint32_t operand0,
uint32_t operand1, uint32_t operand1,
BytecodeSourceInfo info) { const BytecodeSourceInfo& info) {
BytecodeNode node(bytecode, operand0, operand1, &info); BytecodeNode node(bytecode, operand0, operand1);
writer()->Write(&node); Write(&node, info);
} }
void BytecodeArrayWriterUnittest::Write(Bytecode bytecode, uint32_t operand0, void BytecodeArrayWriterUnittest::Write(Bytecode bytecode, uint32_t operand0,
uint32_t operand1, uint32_t operand2, uint32_t operand1, uint32_t operand2,
BytecodeSourceInfo info) { const BytecodeSourceInfo& info) {
BytecodeNode node(bytecode, operand0, operand1, operand2, &info); BytecodeNode node(bytecode, operand0, operand1, operand2);
writer()->Write(&node); Write(&node, info);
} }
void BytecodeArrayWriterUnittest::Write(Bytecode bytecode, uint32_t operand0, void BytecodeArrayWriterUnittest::Write(Bytecode bytecode, uint32_t operand0,
uint32_t operand1, uint32_t operand2, uint32_t operand1, uint32_t operand2,
uint32_t operand3, uint32_t operand3,
BytecodeSourceInfo info) { const BytecodeSourceInfo& info) {
BytecodeNode node(bytecode, operand0, operand1, operand2, operand3, &info); BytecodeNode node(bytecode, operand0, operand1, operand2, operand3);
writer()->Write(&node); Write(&node, info);
} }
void BytecodeArrayWriterUnittest::WriteJump(Bytecode bytecode, void BytecodeArrayWriterUnittest::WriteJump(Bytecode bytecode,
BytecodeLabel* label, BytecodeLabel* label,
BytecodeSourceInfo info) { const BytecodeSourceInfo& info) {
BytecodeNode node(bytecode, 0, &info); BytecodeNode node(bytecode, 0);
if (info.is_valid()) {
node.source_info().Clone(info);
}
writer()->WriteJump(&node, label); writer()->WriteJump(&node, label);
} }
void BytecodeArrayWriterUnittest::WriteJumpLoop(Bytecode bytecode, void BytecodeArrayWriterUnittest::WriteJumpLoop(Bytecode bytecode,
BytecodeLabel* label, int depth, BytecodeLabel* label,
BytecodeSourceInfo info) { int depth) {
BytecodeNode node(bytecode, 0, depth, &info); BytecodeNode node(bytecode, 0, depth);
writer()->WriteJump(&node, label); writer()->WriteJump(&node, label);
} }
...@@ -108,15 +123,19 @@ TEST_F(BytecodeArrayWriterUnittest, SimpleExample) { ...@@ -108,15 +123,19 @@ TEST_F(BytecodeArrayWriterUnittest, SimpleExample) {
Write(Bytecode::kStackCheck, {10, false}); Write(Bytecode::kStackCheck, {10, false});
CHECK_EQ(bytecodes()->size(), 1); CHECK_EQ(bytecodes()->size(), 1);
CHECK_EQ(max_register_count(), 0);
Write(Bytecode::kLdaSmi, 127, {55, true}); Write(Bytecode::kLdaSmi, 127, {55, true});
CHECK_EQ(bytecodes()->size(), 3); CHECK_EQ(bytecodes()->size(), 3);
CHECK_EQ(max_register_count(), 0);
Write(Bytecode::kLdar, Register(200).ToOperand()); Write(Bytecode::kLdar, Register(200).ToOperand());
CHECK_EQ(bytecodes()->size(), 7); CHECK_EQ(bytecodes()->size(), 7);
CHECK_EQ(max_register_count(), 201);
Write(Bytecode::kReturn, {70, true}); Write(Bytecode::kReturn, {70, true});
CHECK_EQ(bytecodes()->size(), 8); CHECK_EQ(bytecodes()->size(), 8);
CHECK_EQ(max_register_count(), 201);
static const uint8_t bytes[] = {B(StackCheck), B(LdaSmi), U8(127), B(Wide), static const uint8_t bytes[] = {B(StackCheck), B(LdaSmi), U8(127), B(Wide),
B(Ldar), R16(200), B(Return)}; B(Ldar), R16(200), B(Return)};
...@@ -148,7 +167,7 @@ TEST_F(BytecodeArrayWriterUnittest, ComplexExample) { ...@@ -148,7 +167,7 @@ TEST_F(BytecodeArrayWriterUnittest, ComplexExample) {
// clang-format off // clang-format off
/* 0 30 E> */ B(StackCheck), /* 0 30 E> */ B(StackCheck),
/* 1 42 S> */ B(LdaConstant), U8(0), /* 1 42 S> */ B(LdaConstant), U8(0),
/* 3 42 E> */ B(Add), R8(1), U8(1), /* 3 42 E> */ B(Star), R8(1),
/* 5 68 S> */ B(JumpIfUndefined), U8(39), /* 5 68 S> */ B(JumpIfUndefined), U8(39),
/* 7 */ B(JumpIfNull), U8(37), /* 7 */ B(JumpIfNull), U8(37),
/* 9 */ B(ToObject), R8(3), /* 9 */ B(ToObject), R8(3),
...@@ -173,23 +192,30 @@ TEST_F(BytecodeArrayWriterUnittest, ComplexExample) { ...@@ -173,23 +192,30 @@ TEST_F(BytecodeArrayWriterUnittest, ComplexExample) {
}; };
static const PositionTableEntry expected_positions[] = { static const PositionTableEntry expected_positions[] = {
{0, 30, false}, {1, 42, true}, {3, 42, false}, {6, 68, true}, {0, 30, false}, {1, 42, true}, {3, 42, false}, {5, 68, true},
{18, 63, true}, {32, 54, false}, {37, 85, true}, {46, 85, true}}; {17, 63, true}, {31, 54, false}, {36, 85, true}, {45, 85, true}};
BytecodeLabel back_jump, jump_for_in, jump_end_1, jump_end_2, jump_end_3; BytecodeLabel back_jump, jump_for_in, jump_end_1, jump_end_2, jump_end_3;
#define R(i) static_cast<uint32_t>(Register(i).ToOperand()) #define R(i) static_cast<uint32_t>(Register(i).ToOperand())
Write(Bytecode::kStackCheck, {30, false}); Write(Bytecode::kStackCheck, {30, false});
Write(Bytecode::kLdaConstant, U8(0), {42, true}); Write(Bytecode::kLdaConstant, U8(0), {42, true});
Write(Bytecode::kAdd, R(1), U8(1), {42, false}); CHECK_EQ(max_register_count(), 0);
Write(Bytecode::kStar, R(1), {42, false});
CHECK_EQ(max_register_count(), 2);
WriteJump(Bytecode::kJumpIfUndefined, &jump_end_1, {68, true}); WriteJump(Bytecode::kJumpIfUndefined, &jump_end_1, {68, true});
WriteJump(Bytecode::kJumpIfNull, &jump_end_2); WriteJump(Bytecode::kJumpIfNull, &jump_end_2);
Write(Bytecode::kToObject, R(3)); Write(Bytecode::kToObject, R(3));
CHECK_EQ(max_register_count(), 4);
Write(Bytecode::kForInPrepare, R(3), R(4)); Write(Bytecode::kForInPrepare, R(3), R(4));
CHECK_EQ(max_register_count(), 7);
Write(Bytecode::kLdaZero); Write(Bytecode::kLdaZero);
CHECK_EQ(max_register_count(), 7);
Write(Bytecode::kStar, R(7)); Write(Bytecode::kStar, R(7));
CHECK_EQ(max_register_count(), 8);
writer()->BindLabel(&back_jump); writer()->BindLabel(&back_jump);
Write(Bytecode::kForInContinue, R(7), R(6), {63, true}); Write(Bytecode::kForInContinue, R(7), R(6), {63, true});
CHECK_EQ(max_register_count(), 8);
WriteJump(Bytecode::kJumpIfFalse, &jump_end_3); WriteJump(Bytecode::kJumpIfFalse, &jump_end_3);
Write(Bytecode::kForInNext, R(3), R(7), R(4), U8(1)); Write(Bytecode::kForInNext, R(3), R(7), R(4), U8(1));
WriteJump(Bytecode::kJumpIfUndefined, &jump_for_in); WriteJump(Bytecode::kJumpIfUndefined, &jump_for_in);
...@@ -207,6 +233,7 @@ TEST_F(BytecodeArrayWriterUnittest, ComplexExample) { ...@@ -207,6 +233,7 @@ TEST_F(BytecodeArrayWriterUnittest, ComplexExample) {
writer()->BindLabel(&jump_end_3); writer()->BindLabel(&jump_end_3);
Write(Bytecode::kLdaUndefined); Write(Bytecode::kLdaUndefined);
Write(Bytecode::kReturn, {85, true}); Write(Bytecode::kReturn, {85, true});
CHECK_EQ(max_register_count(), 8);
#undef R #undef R
CHECK_EQ(bytecodes()->size(), arraysize(expected_bytes)); CHECK_EQ(bytecodes()->size(), arraysize(expected_bytes));
......
...@@ -16,8 +16,7 @@ namespace interpreter { ...@@ -16,8 +16,7 @@ namespace interpreter {
class BytecodeDeadCodeOptimizerTest : public BytecodePipelineStage, class BytecodeDeadCodeOptimizerTest : public BytecodePipelineStage,
public TestWithIsolateAndZone { public TestWithIsolateAndZone {
public: public:
BytecodeDeadCodeOptimizerTest() BytecodeDeadCodeOptimizerTest() : dead_code_optimizer_(this) {}
: dead_code_optimizer_(this), last_written_(Bytecode::kIllegal) {}
~BytecodeDeadCodeOptimizerTest() override {} ~BytecodeDeadCodeOptimizerTest() override {}
void Write(BytecodeNode* node) override { void Write(BytecodeNode* node) override {
...@@ -57,7 +56,7 @@ TEST_F(BytecodeDeadCodeOptimizerTest, LiveCodeKept) { ...@@ -57,7 +56,7 @@ TEST_F(BytecodeDeadCodeOptimizerTest, LiveCodeKept) {
CHECK_EQ(add, last_written()); CHECK_EQ(add, last_written());
BytecodeLabel target; BytecodeLabel target;
BytecodeNode jump(Bytecode::kJump, 0, nullptr); BytecodeNode jump(Bytecode::kJump, 0);
optimizer()->WriteJump(&jump, &target); optimizer()->WriteJump(&jump, &target);
CHECK_EQ(write_count(), 2); CHECK_EQ(write_count(), 2);
CHECK_EQ(jump, last_written()); CHECK_EQ(jump, last_written());
...@@ -101,7 +100,7 @@ TEST_F(BytecodeDeadCodeOptimizerTest, DeadCodeAfterReThrowEliminated) { ...@@ -101,7 +100,7 @@ TEST_F(BytecodeDeadCodeOptimizerTest, DeadCodeAfterReThrowEliminated) {
TEST_F(BytecodeDeadCodeOptimizerTest, DeadCodeAfterJumpEliminated) { TEST_F(BytecodeDeadCodeOptimizerTest, DeadCodeAfterJumpEliminated) {
BytecodeLabel target; BytecodeLabel target;
BytecodeNode jump(Bytecode::kJump, 0, nullptr); BytecodeNode jump(Bytecode::kJump, 0);
optimizer()->WriteJump(&jump, &target); optimizer()->WriteJump(&jump, &target);
CHECK_EQ(write_count(), 1); CHECK_EQ(write_count(), 1);
CHECK_EQ(jump, last_written()); CHECK_EQ(jump, last_written());
...@@ -119,7 +118,7 @@ TEST_F(BytecodeDeadCodeOptimizerTest, DeadCodeStillDeadAfterConditinalJump) { ...@@ -119,7 +118,7 @@ TEST_F(BytecodeDeadCodeOptimizerTest, DeadCodeStillDeadAfterConditinalJump) {
CHECK_EQ(ret, last_written()); CHECK_EQ(ret, last_written());
BytecodeLabel target; BytecodeLabel target;
BytecodeNode jump(Bytecode::kJumpIfTrue, 0, nullptr); BytecodeNode jump(Bytecode::kJumpIfTrue, 0);
optimizer()->WriteJump(&jump, &target); optimizer()->WriteJump(&jump, &target);
CHECK_EQ(write_count(), 1); CHECK_EQ(write_count(), 1);
CHECK_EQ(ret, last_written()); CHECK_EQ(ret, last_written());
......
...@@ -18,8 +18,7 @@ namespace interpreter { ...@@ -18,8 +18,7 @@ namespace interpreter {
class BytecodePeepholeOptimizerTest : public BytecodePipelineStage, class BytecodePeepholeOptimizerTest : public BytecodePipelineStage,
public TestWithIsolateAndZone { public TestWithIsolateAndZone {
public: public:
BytecodePeepholeOptimizerTest() BytecodePeepholeOptimizerTest() : peephole_optimizer_(this) {}
: peephole_optimizer_(this), last_written_(Bytecode::kIllegal) {}
~BytecodePeepholeOptimizerTest() override {} ~BytecodePeepholeOptimizerTest() override {}
void Reset() { void Reset() {
...@@ -72,7 +71,7 @@ TEST_F(BytecodePeepholeOptimizerTest, FlushOnJump) { ...@@ -72,7 +71,7 @@ TEST_F(BytecodePeepholeOptimizerTest, FlushOnJump) {
CHECK_EQ(write_count(), 0); CHECK_EQ(write_count(), 0);
BytecodeLabel target; BytecodeLabel target;
BytecodeNode jump(Bytecode::kJump, 0, nullptr); BytecodeNode jump(Bytecode::kJump, 0);
optimizer()->WriteJump(&jump, &target); optimizer()->WriteJump(&jump, &target);
CHECK_EQ(write_count(), 2); CHECK_EQ(write_count(), 2);
CHECK_EQ(jump, last_written()); CHECK_EQ(jump, last_written());
...@@ -104,8 +103,8 @@ TEST_F(BytecodePeepholeOptimizerTest, ElideEmptyNop) { ...@@ -104,8 +103,8 @@ TEST_F(BytecodePeepholeOptimizerTest, ElideEmptyNop) {
} }
TEST_F(BytecodePeepholeOptimizerTest, ElideExpressionNop) { TEST_F(BytecodePeepholeOptimizerTest, ElideExpressionNop) {
BytecodeSourceInfo source_info(3, false); BytecodeNode nop(Bytecode::kNop);
BytecodeNode nop(Bytecode::kNop, &source_info); nop.source_info().MakeExpressionPosition(3);
optimizer()->Write(&nop); optimizer()->Write(&nop);
BytecodeNode add(Bytecode::kAdd, Register(0).ToOperand(), 1); BytecodeNode add(Bytecode::kAdd, Register(0).ToOperand(), 1);
optimizer()->Write(&add); optimizer()->Write(&add);
...@@ -115,11 +114,11 @@ TEST_F(BytecodePeepholeOptimizerTest, ElideExpressionNop) { ...@@ -115,11 +114,11 @@ TEST_F(BytecodePeepholeOptimizerTest, ElideExpressionNop) {
} }
TEST_F(BytecodePeepholeOptimizerTest, KeepStatementNop) { TEST_F(BytecodePeepholeOptimizerTest, KeepStatementNop) {
BytecodeSourceInfo source_info(3, true); BytecodeNode nop(Bytecode::kNop);
BytecodeNode nop(Bytecode::kNop, &source_info); nop.source_info().MakeStatementPosition(3);
optimizer()->Write(&nop); optimizer()->Write(&nop);
source_info.MakeExpressionPosition(3); BytecodeNode add(Bytecode::kAdd, Register(0).ToOperand(), 1);
BytecodeNode add(Bytecode::kAdd, Register(0).ToOperand(), 1, &source_info); add.source_info().MakeExpressionPosition(3);
optimizer()->Write(&add); optimizer()->Write(&add);
Flush(); Flush();
CHECK_EQ(write_count(), 2); CHECK_EQ(write_count(), 2);
...@@ -205,8 +204,8 @@ TEST_F(BytecodePeepholeOptimizerTest, StarRxLdarRx) { ...@@ -205,8 +204,8 @@ TEST_F(BytecodePeepholeOptimizerTest, StarRxLdarRx) {
TEST_F(BytecodePeepholeOptimizerTest, StarRxLdarRxStatement) { TEST_F(BytecodePeepholeOptimizerTest, StarRxLdarRxStatement) {
BytecodeNode first(Bytecode::kStar, Register(0).ToOperand()); BytecodeNode first(Bytecode::kStar, Register(0).ToOperand());
BytecodeSourceInfo source_info(3, true); BytecodeNode second(Bytecode::kLdar, Register(0).ToOperand());
BytecodeNode second(Bytecode::kLdar, Register(0).ToOperand(), &source_info); second.source_info().MakeStatementPosition(0);
optimizer()->Write(&first); optimizer()->Write(&first);
CHECK_EQ(write_count(), 0); CHECK_EQ(write_count(), 0);
optimizer()->Write(&second); optimizer()->Write(&second);
...@@ -221,9 +220,9 @@ TEST_F(BytecodePeepholeOptimizerTest, StarRxLdarRxStatement) { ...@@ -221,9 +220,9 @@ TEST_F(BytecodePeepholeOptimizerTest, StarRxLdarRxStatement) {
TEST_F(BytecodePeepholeOptimizerTest, StarRxLdarRxStatementStarRy) { TEST_F(BytecodePeepholeOptimizerTest, StarRxLdarRxStatementStarRy) {
BytecodeLabel label; BytecodeLabel label;
BytecodeNode first(Bytecode::kStar, Register(0).ToOperand()); BytecodeNode first(Bytecode::kStar, Register(0).ToOperand());
BytecodeSourceInfo source_info(0, true); BytecodeNode second(Bytecode::kLdar, Register(0).ToOperand());
BytecodeNode second(Bytecode::kLdar, Register(0).ToOperand(), &source_info);
BytecodeNode third(Bytecode::kStar, Register(3).ToOperand()); BytecodeNode third(Bytecode::kStar, Register(3).ToOperand());
second.source_info().MakeStatementPosition(0);
optimizer()->Write(&first); optimizer()->Write(&first);
CHECK_EQ(write_count(), 0); CHECK_EQ(write_count(), 0);
optimizer()->Write(&second); optimizer()->Write(&second);
...@@ -278,8 +277,8 @@ TEST_F(BytecodePeepholeOptimizerTest, LdaTrueLdaFalse) { ...@@ -278,8 +277,8 @@ TEST_F(BytecodePeepholeOptimizerTest, LdaTrueLdaFalse) {
} }
TEST_F(BytecodePeepholeOptimizerTest, LdaTrueStatementLdaFalse) { TEST_F(BytecodePeepholeOptimizerTest, LdaTrueStatementLdaFalse) {
BytecodeSourceInfo source_info(3, true); BytecodeNode first(Bytecode::kLdaTrue);
BytecodeNode first(Bytecode::kLdaTrue, &source_info); first.source_info().MakeExpressionPosition(3);
BytecodeNode second(Bytecode::kLdaFalse); BytecodeNode second(Bytecode::kLdaFalse);
optimizer()->Write(&first); optimizer()->Write(&first);
CHECK_EQ(write_count(), 0); CHECK_EQ(write_count(), 0);
...@@ -288,13 +287,13 @@ TEST_F(BytecodePeepholeOptimizerTest, LdaTrueStatementLdaFalse) { ...@@ -288,13 +287,13 @@ TEST_F(BytecodePeepholeOptimizerTest, LdaTrueStatementLdaFalse) {
Flush(); Flush();
CHECK_EQ(write_count(), 1); CHECK_EQ(write_count(), 1);
CHECK_EQ(last_written(), second); CHECK_EQ(last_written(), second);
CHECK(second.source_info().is_statement()); CHECK(second.source_info().is_expression());
CHECK_EQ(second.source_info().source_position(), 3); CHECK_EQ(second.source_info().source_position(), 3);
} }
TEST_F(BytecodePeepholeOptimizerTest, NopStackCheck) { TEST_F(BytecodePeepholeOptimizerTest, NopStackCheck) {
BytecodeNode first(Bytecode::kNop); BytecodeNode first(Bytecode::kNop);
BytecodeNode second(Bytecode::kStackCheck, nullptr); BytecodeNode second(Bytecode::kStackCheck);
optimizer()->Write(&first); optimizer()->Write(&first);
CHECK_EQ(write_count(), 0); CHECK_EQ(write_count(), 0);
optimizer()->Write(&second); optimizer()->Write(&second);
...@@ -305,8 +304,8 @@ TEST_F(BytecodePeepholeOptimizerTest, NopStackCheck) { ...@@ -305,8 +304,8 @@ TEST_F(BytecodePeepholeOptimizerTest, NopStackCheck) {
} }
TEST_F(BytecodePeepholeOptimizerTest, NopStatementStackCheck) { TEST_F(BytecodePeepholeOptimizerTest, NopStatementStackCheck) {
BytecodeSourceInfo source_info(3, true); BytecodeNode first(Bytecode::kNop);
BytecodeNode first(Bytecode::kNop, &source_info); first.source_info().MakeExpressionPosition(3);
BytecodeNode second(Bytecode::kStackCheck); BytecodeNode second(Bytecode::kStackCheck);
optimizer()->Write(&first); optimizer()->Write(&first);
CHECK_EQ(write_count(), 0); CHECK_EQ(write_count(), 0);
...@@ -314,9 +313,9 @@ TEST_F(BytecodePeepholeOptimizerTest, NopStatementStackCheck) { ...@@ -314,9 +313,9 @@ TEST_F(BytecodePeepholeOptimizerTest, NopStatementStackCheck) {
CHECK_EQ(write_count(), 0); CHECK_EQ(write_count(), 0);
Flush(); Flush();
CHECK_EQ(write_count(), 1); CHECK_EQ(write_count(), 1);
BytecodeSourceInfo expected_source_info(3, true); second.source_info().MakeExpressionPosition(
BytecodeNode expected(Bytecode::kStackCheck, &expected_source_info); first.source_info().source_position());
CHECK_EQ(last_written(), expected); CHECK_EQ(last_written(), second);
} }
// Tests covering BytecodePeepholeOptimizer::UpdateLastAndCurrentBytecodes(). // Tests covering BytecodePeepholeOptimizer::UpdateLastAndCurrentBytecodes().
...@@ -353,8 +352,7 @@ TEST_F(BytecodePeepholeOptimizerTest, MergeLdaKeyedPropertyStar) { ...@@ -353,8 +352,7 @@ TEST_F(BytecodePeepholeOptimizerTest, MergeLdaKeyedPropertyStar) {
static_cast<uint32_t>(Register(1).ToOperand())}; static_cast<uint32_t>(Register(1).ToOperand())};
const int expected_operand_count = static_cast<int>(arraysize(operands)); const int expected_operand_count = static_cast<int>(arraysize(operands));
BytecodeNode first(Bytecode::kLdaKeyedProperty, operands[0], operands[1], BytecodeNode first(Bytecode::kLdaKeyedProperty, operands[0], operands[1]);
nullptr);
BytecodeNode second(Bytecode::kStar, operands[2]); BytecodeNode second(Bytecode::kStar, operands[2]);
BytecodeNode third(Bytecode::kReturn); BytecodeNode third(Bytecode::kReturn);
optimizer()->Write(&first); optimizer()->Write(&first);
...@@ -459,8 +457,8 @@ TEST_F(BytecodePeepholeOptimizerTest, MergeLdaSmiWithBinaryOp) { ...@@ -459,8 +457,8 @@ TEST_F(BytecodePeepholeOptimizerTest, MergeLdaSmiWithBinaryOp) {
for (auto operator_replacement : operator_replacement_pairs) { for (auto operator_replacement : operator_replacement_pairs) {
uint32_t imm_operand = 17; uint32_t imm_operand = 17;
BytecodeSourceInfo source_info(3, true); BytecodeNode first(Bytecode::kLdaSmi, imm_operand);
BytecodeNode first(Bytecode::kLdaSmi, imm_operand, &source_info); first.source_info().Clone({3, true});
uint32_t reg_operand = Register(0).ToOperand(); uint32_t reg_operand = Register(0).ToOperand();
uint32_t idx_operand = 1; uint32_t idx_operand = 1;
BytecodeNode second(operator_replacement[0], reg_operand, idx_operand); BytecodeNode second(operator_replacement[0], reg_operand, idx_operand);
...@@ -489,11 +487,11 @@ TEST_F(BytecodePeepholeOptimizerTest, NotMergingLdaSmiWithBinaryOp) { ...@@ -489,11 +487,11 @@ TEST_F(BytecodePeepholeOptimizerTest, NotMergingLdaSmiWithBinaryOp) {
for (auto operator_replacement : operator_replacement_pairs) { for (auto operator_replacement : operator_replacement_pairs) {
uint32_t imm_operand = 17; uint32_t imm_operand = 17;
BytecodeSourceInfo source_info(3, true); BytecodeNode first(Bytecode::kLdaSmi, imm_operand);
BytecodeNode first(Bytecode::kLdaSmi, imm_operand, &source_info); first.source_info().Clone({3, true});
uint32_t reg_operand = Register(0).ToOperand(); uint32_t reg_operand = Register(0).ToOperand();
source_info.MakeStatementPosition(4); BytecodeNode second(operator_replacement[0], reg_operand, 1);
BytecodeNode second(operator_replacement[0], reg_operand, 1, &source_info); second.source_info().Clone({4, true});
optimizer()->Write(&first); optimizer()->Write(&first);
optimizer()->Write(&second); optimizer()->Write(&second);
CHECK_EQ(last_written(), first); CHECK_EQ(last_written(), first);
......
...@@ -51,6 +51,12 @@ TEST(BytecodeSourceInfo, Operations) { ...@@ -51,6 +51,12 @@ TEST(BytecodeSourceInfo, Operations) {
CHECK_EQ(y.is_statement(), true); CHECK_EQ(y.is_statement(), true);
} }
TEST_F(BytecodeNodeTest, Constructor0) {
BytecodeNode node;
CHECK_EQ(node.bytecode(), Bytecode::kIllegal);
CHECK(!node.source_info().is_valid());
}
TEST_F(BytecodeNodeTest, Constructor1) { TEST_F(BytecodeNodeTest, Constructor1) {
BytecodeNode node(Bytecode::kLdaZero); BytecodeNode node(Bytecode::kLdaZero);
CHECK_EQ(node.bytecode(), Bytecode::kLdaZero); CHECK_EQ(node.bytecode(), Bytecode::kLdaZero);
...@@ -113,21 +119,21 @@ TEST_F(BytecodeNodeTest, Equality) { ...@@ -113,21 +119,21 @@ TEST_F(BytecodeNodeTest, Equality) {
TEST_F(BytecodeNodeTest, EqualityWithSourceInfo) { TEST_F(BytecodeNodeTest, EqualityWithSourceInfo) {
uint32_t operands[] = {0x71, 0xa5, 0x5a, 0xfc}; uint32_t operands[] = {0x71, 0xa5, 0x5a, 0xfc};
BytecodeSourceInfo first_source_info(3, true);
BytecodeNode node(Bytecode::kForInNext, operands[0], operands[1], operands[2], BytecodeNode node(Bytecode::kForInNext, operands[0], operands[1], operands[2],
operands[3], &first_source_info); operands[3]);
node.source_info().MakeStatementPosition(3);
CHECK_EQ(node, node); CHECK_EQ(node, node);
BytecodeSourceInfo second_source_info(3, true);
BytecodeNode other(Bytecode::kForInNext, operands[0], operands[1], BytecodeNode other(Bytecode::kForInNext, operands[0], operands[1],
operands[2], operands[3], &second_source_info); operands[2], operands[3]);
other.source_info().MakeStatementPosition(3);
CHECK_EQ(node, other); CHECK_EQ(node, other);
} }
TEST_F(BytecodeNodeTest, NoEqualityWithDifferentSourceInfo) { TEST_F(BytecodeNodeTest, NoEqualityWithDifferentSourceInfo) {
uint32_t operands[] = {0x71, 0xa5, 0x5a, 0xfc}; uint32_t operands[] = {0x71, 0xa5, 0x5a, 0xfc};
BytecodeSourceInfo source_info(77, true);
BytecodeNode node(Bytecode::kForInNext, operands[0], operands[1], operands[2], BytecodeNode node(Bytecode::kForInNext, operands[0], operands[1], operands[2],
operands[3], &source_info); operands[3]);
node.source_info().MakeStatementPosition(3);
BytecodeNode other(Bytecode::kForInNext, operands[0], operands[1], BytecodeNode other(Bytecode::kForInNext, operands[0], operands[1],
operands[2], operands[3]); operands[2], operands[3]);
CHECK_NE(node, other); CHECK_NE(node, other);
...@@ -137,39 +143,41 @@ TEST_F(BytecodeNodeTest, Clone) { ...@@ -137,39 +143,41 @@ TEST_F(BytecodeNodeTest, Clone) {
uint32_t operands[] = {0x71, 0xa5, 0x5a, 0xfc}; uint32_t operands[] = {0x71, 0xa5, 0x5a, 0xfc};
BytecodeNode node(Bytecode::kForInNext, operands[0], operands[1], operands[2], BytecodeNode node(Bytecode::kForInNext, operands[0], operands[1], operands[2],
operands[3]); operands[3]);
BytecodeNode clone(Bytecode::kIllegal); BytecodeNode clone;
clone.Clone(&node); clone.Clone(&node);
CHECK_EQ(clone, node); CHECK_EQ(clone, node);
} }
TEST_F(BytecodeNodeTest, SetBytecode0) { TEST_F(BytecodeNodeTest, SetBytecode0) {
uint32_t operands[] = {0x71, 0xa5, 0x5a, 0xfc}; uint32_t operands[] = {0x71, 0xa5, 0x5a, 0xfc};
BytecodeSourceInfo source_info(77, false);
BytecodeNode node(Bytecode::kForInNext, operands[0], operands[1], operands[2], BytecodeNode node(Bytecode::kForInNext, operands[0], operands[1], operands[2],
operands[3], &source_info); operands[3]);
CHECK_EQ(node.source_info(), BytecodeSourceInfo(77, false)); BytecodeSourceInfo source_info(77, false);
node.source_info().Clone(source_info);
CHECK_EQ(node.source_info(), source_info);
BytecodeNode clone(Bytecode::kIllegal); BytecodeNode clone;
clone.Clone(&node); clone.Clone(&node);
clone.set_bytecode(Bytecode::kNop); clone.set_bytecode(Bytecode::kNop);
CHECK_EQ(clone.bytecode(), Bytecode::kNop); CHECK_EQ(clone.bytecode(), Bytecode::kNop);
CHECK_EQ(clone.operand_count(), 0); CHECK_EQ(clone.operand_count(), 0);
CHECK_EQ(clone.source_info(), BytecodeSourceInfo(77, false)); CHECK_EQ(clone.source_info(), source_info);
} }
TEST_F(BytecodeNodeTest, SetBytecode1) { TEST_F(BytecodeNodeTest, SetBytecode1) {
uint32_t operands[] = {0x71, 0xa5, 0x5a, 0xfc}; uint32_t operands[] = {0x71, 0xa5, 0x5a, 0xfc};
BytecodeSourceInfo source_info(77, false);
BytecodeNode node(Bytecode::kForInNext, operands[0], operands[1], operands[2], BytecodeNode node(Bytecode::kForInNext, operands[0], operands[1], operands[2],
operands[3], &source_info); operands[3]);
BytecodeSourceInfo source_info(77, false);
node.source_info().Clone(source_info);
BytecodeNode clone(Bytecode::kIllegal); BytecodeNode clone;
clone.Clone(&node); clone.Clone(&node);
clone.set_bytecode(Bytecode::kJump, 0x01aabbcc); clone.set_bytecode(Bytecode::kJump, 0x01aabbcc);
CHECK_EQ(clone.bytecode(), Bytecode::kJump); CHECK_EQ(clone.bytecode(), Bytecode::kJump);
CHECK_EQ(clone.operand_count(), 1); CHECK_EQ(clone.operand_count(), 1);
CHECK_EQ(clone.operand(0), 0x01aabbcc); CHECK_EQ(clone.operand(0), 0x01aabbcc);
CHECK_EQ(clone.source_info(), BytecodeSourceInfo(77, false)); CHECK_EQ(clone.source_info(), source_info);
} }
} // namespace interpreter } // namespace interpreter
......
...@@ -74,8 +74,8 @@ TEST_F(BytecodeRegisterOptimizerTest, WriteNop) { ...@@ -74,8 +74,8 @@ TEST_F(BytecodeRegisterOptimizerTest, WriteNop) {
TEST_F(BytecodeRegisterOptimizerTest, WriteNopExpression) { TEST_F(BytecodeRegisterOptimizerTest, WriteNopExpression) {
Initialize(1, 1); Initialize(1, 1);
BytecodeSourceInfo source_info(3, false); BytecodeNode node(Bytecode::kNop);
BytecodeNode node(Bytecode::kNop, &source_info); node.source_info().MakeExpressionPosition(3);
optimizer()->Write(&node); optimizer()->Write(&node);
CHECK_EQ(write_count(), 1); CHECK_EQ(write_count(), 1);
CHECK_EQ(node, last_written()); CHECK_EQ(node, last_written());
...@@ -83,8 +83,8 @@ TEST_F(BytecodeRegisterOptimizerTest, WriteNopExpression) { ...@@ -83,8 +83,8 @@ TEST_F(BytecodeRegisterOptimizerTest, WriteNopExpression) {
TEST_F(BytecodeRegisterOptimizerTest, WriteNopStatement) { TEST_F(BytecodeRegisterOptimizerTest, WriteNopStatement) {
Initialize(1, 1); Initialize(1, 1);
BytecodeSourceInfo source_info(3, true);
BytecodeNode node(Bytecode::kNop); BytecodeNode node(Bytecode::kNop);
node.source_info().MakeStatementPosition(3);
optimizer()->Write(&node); optimizer()->Write(&node);
CHECK_EQ(write_count(), 1); CHECK_EQ(write_count(), 1);
CHECK_EQ(node, last_written()); CHECK_EQ(node, last_written());
...@@ -97,7 +97,7 @@ TEST_F(BytecodeRegisterOptimizerTest, TemporaryMaterializedForJump) { ...@@ -97,7 +97,7 @@ TEST_F(BytecodeRegisterOptimizerTest, TemporaryMaterializedForJump) {
optimizer()->Write(&node); optimizer()->Write(&node);
CHECK_EQ(write_count(), 0); CHECK_EQ(write_count(), 0);
BytecodeLabel label; BytecodeLabel label;
BytecodeNode jump(Bytecode::kJump, 0, nullptr); BytecodeNode jump(Bytecode::kJump, 0);
optimizer()->WriteJump(&jump, &label); optimizer()->WriteJump(&jump, &label);
CHECK_EQ(write_count(), 2); CHECK_EQ(write_count(), 2);
CHECK_EQ(output()->at(0).bytecode(), Bytecode::kStar); CHECK_EQ(output()->at(0).bytecode(), Bytecode::kStar);
......
...@@ -161,47 +161,18 @@ TEST(Bytecodes, PrefixMappings) { ...@@ -161,47 +161,18 @@ TEST(Bytecodes, PrefixMappings) {
} }
} }
TEST(Bytecodes, ScaleForSignedOperand) { TEST(Bytecodes, SizesForSignedOperands) {
CHECK(Bytecodes::ScaleForSignedOperand(0) == OperandScale::kSingle); CHECK(Bytecodes::SizeForSignedOperand(0) == OperandSize::kByte);
CHECK(Bytecodes::ScaleForSignedOperand(kMaxInt8) == OperandScale::kSingle); CHECK(Bytecodes::SizeForSignedOperand(kMaxInt8) == OperandSize::kByte);
CHECK(Bytecodes::ScaleForSignedOperand(kMinInt8) == OperandScale::kSingle); CHECK(Bytecodes::SizeForSignedOperand(kMinInt8) == OperandSize::kByte);
CHECK(Bytecodes::ScaleForSignedOperand(kMaxInt8 + 1) == CHECK(Bytecodes::SizeForSignedOperand(kMaxInt8 + 1) == OperandSize::kShort);
OperandScale::kDouble); CHECK(Bytecodes::SizeForSignedOperand(kMinInt8 - 1) == OperandSize::kShort);
CHECK(Bytecodes::ScaleForSignedOperand(kMinInt8 - 1) == CHECK(Bytecodes::SizeForSignedOperand(kMaxInt16) == OperandSize::kShort);
OperandScale::kDouble); CHECK(Bytecodes::SizeForSignedOperand(kMinInt16) == OperandSize::kShort);
CHECK(Bytecodes::ScaleForSignedOperand(kMaxInt16) == OperandScale::kDouble); CHECK(Bytecodes::SizeForSignedOperand(kMaxInt16 + 1) == OperandSize::kQuad);
CHECK(Bytecodes::ScaleForSignedOperand(kMinInt16) == OperandScale::kDouble); CHECK(Bytecodes::SizeForSignedOperand(kMinInt16 - 1) == OperandSize::kQuad);
CHECK(Bytecodes::ScaleForSignedOperand(kMaxInt16 + 1) == CHECK(Bytecodes::SizeForSignedOperand(kMaxInt) == OperandSize::kQuad);
OperandScale::kQuadruple); CHECK(Bytecodes::SizeForSignedOperand(kMinInt) == OperandSize::kQuad);
CHECK(Bytecodes::ScaleForSignedOperand(kMinInt16 - 1) ==
OperandScale::kQuadruple);
CHECK(Bytecodes::ScaleForSignedOperand(kMaxInt) == OperandScale::kQuadruple);
CHECK(Bytecodes::ScaleForSignedOperand(kMinInt) == OperandScale::kQuadruple);
}
TEST(Bytecodes, ScaleForUnsignedOperands) {
// int overloads
CHECK(Bytecodes::ScaleForUnsignedOperand(0) == OperandScale::kSingle);
CHECK(Bytecodes::ScaleForUnsignedOperand(kMaxUInt8) == OperandScale::kSingle);
CHECK(Bytecodes::ScaleForUnsignedOperand(kMaxUInt8 + 1) ==
OperandScale::kDouble);
CHECK(Bytecodes::ScaleForUnsignedOperand(kMaxUInt16) ==
OperandScale::kDouble);
CHECK(Bytecodes::ScaleForUnsignedOperand(kMaxUInt16 + 1) ==
OperandScale::kQuadruple);
// size_t overloads
CHECK(Bytecodes::ScaleForUnsignedOperand(static_cast<size_t>(0)) ==
OperandScale::kSingle);
CHECK(Bytecodes::ScaleForUnsignedOperand(static_cast<size_t>(kMaxUInt8)) ==
OperandScale::kSingle);
CHECK(Bytecodes::ScaleForUnsignedOperand(
static_cast<size_t>(kMaxUInt8 + 1)) == OperandScale::kDouble);
CHECK(Bytecodes::ScaleForUnsignedOperand(static_cast<size_t>(kMaxUInt16)) ==
OperandScale::kDouble);
CHECK(Bytecodes::ScaleForUnsignedOperand(
static_cast<size_t>(kMaxUInt16 + 1)) == OperandScale::kQuadruple);
CHECK(Bytecodes::ScaleForUnsignedOperand(static_cast<size_t>(kMaxUInt32)) ==
OperandScale::kQuadruple);
} }
TEST(Bytecodes, SizesForUnsignedOperands) { TEST(Bytecodes, SizesForUnsignedOperands) {
...@@ -265,6 +236,14 @@ TEST(AccumulatorUse, SampleBytecodes) { ...@@ -265,6 +236,14 @@ TEST(AccumulatorUse, SampleBytecodes) {
AccumulatorUse::kReadWrite); AccumulatorUse::kReadWrite);
} }
TEST(AccumulatorUse, AccumulatorUseToString) {
std::set<std::string> names;
names.insert(Bytecodes::AccumulatorUseToString(AccumulatorUse::kNone));
names.insert(Bytecodes::AccumulatorUseToString(AccumulatorUse::kRead));
names.insert(Bytecodes::AccumulatorUseToString(AccumulatorUse::kWrite));
names.insert(Bytecodes::AccumulatorUseToString(AccumulatorUse::kReadWrite));
CHECK_EQ(names.size(), 4);
}
} // namespace interpreter } // namespace interpreter
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
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