Commit 25b3fe79 authored by oth's avatar oth Committed by Commit bot

[interpreter] Introduce fused bytecodes for common sequences.

This change introduces five fused bytecodes for common bytecode
sequences on popular websites. These are LdrNamedProperty,
LdrKeyedProperty, LdrGlobal, LdrContextSlot, and LdrUndefined. These
load values into a destination register operand instead of the
accumulator. They are emitted by the peephole optimizer.

BUG=v8:4280
LOG=N

Review-Url: https://codereview.chromium.org/1985753002
Cr-Commit-Position: refs/heads/master@{#36507}
parent 0f777211
......@@ -577,6 +577,11 @@ void BytecodeGraphBuilder::VisitLdaUndefined() {
environment()->BindAccumulator(node);
}
void BytecodeGraphBuilder::VisitLdrUndefined() {
Node* node = jsgraph()->UndefinedConstant();
environment()->BindRegister(bytecode_iterator().GetRegisterOperand(0), node);
}
void BytecodeGraphBuilder::VisitLdaNull() {
Node* node = jsgraph()->NullConstant();
environment()->BindAccumulator(node);
......@@ -614,25 +619,32 @@ void BytecodeGraphBuilder::VisitMov() {
environment()->BindRegister(bytecode_iterator().GetRegisterOperand(1), value);
}
void BytecodeGraphBuilder::BuildLoadGlobal(
TypeofMode typeof_mode) {
FrameStateBeforeAndAfter states(this);
Node* BytecodeGraphBuilder::BuildLoadGlobal(TypeofMode typeof_mode) {
Handle<Name> name =
Handle<Name>::cast(bytecode_iterator().GetConstantForIndexOperand(0));
VectorSlotPair feedback =
CreateVectorSlotPair(bytecode_iterator().GetIndexOperand(1));
const Operator* op = javascript()->LoadGlobal(name, feedback, typeof_mode);
Node* node = NewNode(op, GetFunctionClosure());
environment()->BindAccumulator(node, &states);
return NewNode(op, GetFunctionClosure());
}
void BytecodeGraphBuilder::VisitLdaGlobal() {
BuildLoadGlobal(TypeofMode::NOT_INSIDE_TYPEOF);
FrameStateBeforeAndAfter states(this);
Node* node = BuildLoadGlobal(TypeofMode::NOT_INSIDE_TYPEOF);
environment()->BindAccumulator(node, &states);
}
void BytecodeGraphBuilder::VisitLdrGlobal() {
FrameStateBeforeAndAfter states(this);
Node* node = BuildLoadGlobal(TypeofMode::NOT_INSIDE_TYPEOF);
environment()->BindRegister(bytecode_iterator().GetRegisterOperand(2), node,
&states);
}
void BytecodeGraphBuilder::VisitLdaGlobalInsideTypeof() {
BuildLoadGlobal(TypeofMode::INSIDE_TYPEOF);
FrameStateBeforeAndAfter states(this);
Node* node = BuildLoadGlobal(TypeofMode::INSIDE_TYPEOF);
environment()->BindAccumulator(node, &states);
}
void BytecodeGraphBuilder::BuildStoreGlobal(LanguageMode language_mode) {
......@@ -656,7 +668,7 @@ void BytecodeGraphBuilder::VisitStaGlobalStrict() {
BuildStoreGlobal(LanguageMode::STRICT);
}
void BytecodeGraphBuilder::VisitLdaContextSlot() {
Node* BytecodeGraphBuilder::BuildLoadContextSlot() {
// TODO(mythria): LoadContextSlots are unrolled by the required depth when
// generating bytecode. Hence the value of depth is always 0. Update this
// code, when the implementation changes.
......@@ -667,10 +679,19 @@ void BytecodeGraphBuilder::VisitLdaContextSlot() {
0, bytecode_iterator().GetIndexOperand(1), false);
Node* context =
environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
Node* node = NewNode(op, context);
return NewNode(op, context);
}
void BytecodeGraphBuilder::VisitLdaContextSlot() {
Node* node = BuildLoadContextSlot();
environment()->BindAccumulator(node);
}
void BytecodeGraphBuilder::VisitLdrContextSlot() {
Node* node = BuildLoadContextSlot();
environment()->BindRegister(bytecode_iterator().GetRegisterOperand(2), node);
}
void BytecodeGraphBuilder::VisitStaContextSlot() {
// TODO(mythria): LoadContextSlots are unrolled by the required depth when
// generating bytecode. Hence the value of depth is always 0. Update this
......@@ -723,8 +744,7 @@ void BytecodeGraphBuilder::VisitStaLookupSlotStrict() {
BuildStaLookupSlot(LanguageMode::STRICT);
}
void BytecodeGraphBuilder::BuildNamedLoad() {
FrameStateBeforeAndAfter states(this);
Node* BytecodeGraphBuilder::BuildNamedLoad() {
Node* object =
environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
Handle<Name> name =
......@@ -733,14 +753,23 @@ void BytecodeGraphBuilder::BuildNamedLoad() {
CreateVectorSlotPair(bytecode_iterator().GetIndexOperand(2));
const Operator* op = javascript()->LoadNamed(name, feedback);
Node* node = NewNode(op, object, GetFunctionClosure());
environment()->BindAccumulator(node, &states);
return NewNode(op, object, GetFunctionClosure());
}
void BytecodeGraphBuilder::VisitLoadIC() { BuildNamedLoad(); }
void BytecodeGraphBuilder::VisitLoadIC() {
FrameStateBeforeAndAfter states(this);
Node* node = BuildNamedLoad();
environment()->BindAccumulator(node, &states);
}
void BytecodeGraphBuilder::BuildKeyedLoad() {
void BytecodeGraphBuilder::VisitLdrNamedProperty() {
FrameStateBeforeAndAfter states(this);
Node* node = BuildNamedLoad();
environment()->BindRegister(bytecode_iterator().GetRegisterOperand(3), node,
&states);
}
Node* BytecodeGraphBuilder::BuildKeyedLoad() {
Node* key = environment()->LookupAccumulator();
Node* object =
environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
......@@ -748,11 +777,21 @@ void BytecodeGraphBuilder::BuildKeyedLoad() {
CreateVectorSlotPair(bytecode_iterator().GetIndexOperand(1));
const Operator* op = javascript()->LoadProperty(feedback);
Node* node = NewNode(op, object, key, GetFunctionClosure());
return NewNode(op, object, key, GetFunctionClosure());
}
void BytecodeGraphBuilder::VisitKeyedLoadIC() {
FrameStateBeforeAndAfter states(this);
Node* node = BuildKeyedLoad();
environment()->BindAccumulator(node, &states);
}
void BytecodeGraphBuilder::VisitKeyedLoadIC() { BuildKeyedLoad(); }
void BytecodeGraphBuilder::VisitLdrKeyedProperty() {
FrameStateBeforeAndAfter states(this);
Node* node = BuildKeyedLoad();
environment()->BindRegister(bytecode_iterator().GetRegisterOperand(2), node,
&states);
}
void BytecodeGraphBuilder::BuildNamedStore(LanguageMode language_mode) {
FrameStateBeforeAndAfter states(this);
......
......@@ -112,11 +112,12 @@ class BytecodeGraphBuilder {
void BuildCreateLiteral(const Operator* op);
void BuildCreateArguments(CreateArgumentsType type);
void BuildLoadGlobal(TypeofMode typeof_mode);
Node* BuildLoadContextSlot();
Node* BuildLoadGlobal(TypeofMode typeof_mode);
void BuildStoreGlobal(LanguageMode language_mode);
void BuildNamedLoad();
void BuildKeyedLoad();
Node* BuildNamedLoad();
void BuildNamedStore(LanguageMode language_mode);
Node* BuildKeyedLoad();
void BuildKeyedStore(LanguageMode language_mode);
void BuildLdaLookupSlot(TypeofMode typeof_mode);
void BuildStaLookupSlot(LanguageMode language_mode);
......
......@@ -94,25 +94,8 @@ bool BytecodePeepholeOptimizer::LastBytecodePutsNameInAccumulator() const {
GetConstantForIndexOperand(&last_, 0)->IsName()));
}
void BytecodePeepholeOptimizer::UpdateLastAndCurrentBytecodes(
BytecodeNode* current) {
if (Bytecodes::IsJumpIfToBoolean(current->bytecode()) &&
Bytecodes::WritesBooleanToAccumulator(last_.bytecode())) {
// Conditional jumps with boolean conditions are emitted in
// ToBoolean form by the bytecode array builder,
// i.e. JumpIfToBooleanTrue rather JumpIfTrue. The ToBoolean element
// can be removed if the previous bytecode put a boolean value in
// the accumulator.
Bytecode jump = Bytecodes::GetJumpWithoutToBoolean(current->bytecode());
current->set_bytecode(jump, current->operand(0), current->operand_scale());
} else if (current->bytecode() == Bytecode::kToBooleanLogicalNot &&
Bytecodes::WritesBooleanToAccumulator(last_.bytecode())) {
// Logical-nots are emitted in ToBoolean form by the bytecode array
// builder, The ToBoolean element can be removed if the previous bytecode
// put a boolean value in the accumulator.
current->set_bytecode(Bytecode::kLogicalNot);
}
void BytecodePeepholeOptimizer::TryToRemoveLastExpressionPosition(
const BytecodeNode* const current) {
if (current->source_info().is_statement() &&
last_.source_info().is_expression() &&
Bytecodes::IsWithoutExternalSideEffects(last_.bytecode())) {
......@@ -169,13 +152,13 @@ bool BytecodePeepholeOptimizer::CanElideLastBasedOnSourcePosition(
// source position information is applied to the current node
// updating it if necessary.
//
//
// The last bytecode can be elided for the MAYBE cases if the last
// bytecode is known not to throw. If it throws, the system would
// not have correct stack trace information. The appropriate check
// for this would be Bytecodes::IsWithoutExternalSideEffects(), which
// is checked in BytecodePeepholeOptimizer::UpdateLastAndCurrentBytecodes()
// to keep the check here simple.
// for this would be Bytecodes::IsWithoutExternalSideEffects(),
// which is checked in
// BytecodePeepholeOptimizer::TransformLastAndCurrentBytecodes() to
// keep the check here simple.
//
// In rare cases, bytecode generation produces consecutive bytecodes
// with the same expression positions. In principle, the latter of
......@@ -185,6 +168,96 @@ bool BytecodePeepholeOptimizer::CanElideLastBasedOnSourcePosition(
!current->source_info().is_valid());
}
namespace {
void TransformLdaStarToLdrLdar(Bytecode new_bytecode, BytecodeNode* const last,
BytecodeNode* const current) {
DCHECK_EQ(current->bytecode(), Bytecode::kStar);
//
// An example transformation here would be:
//
// LdaGlobal i0, i1 ____\ LdrGlobal i0, i1, R
// Star R ====/ Ldar R
//
// which loads a global value into both a register and the
// accumulator. However, in the second form the Ldar can often be
// peephole optimized away unlike the Star in the first form.
//
last->Transform(new_bytecode, current->operand(0), current->operand_scale());
current->set_bytecode(Bytecode::kLdar, current->operand(0),
current->operand_scale());
// If there was a source position on |current| transfer it to the
// updated |last| to maintain the debugger's causal view. ie. if an
// expression position LdrGlobal is the bytecode that could throw
// and if a statement position it needs to be placed before the
// store to R occurs.
last->source_info().Update(current->source_info());
current->source_info().set_invalid();
}
} // namespace
bool BytecodePeepholeOptimizer::ChangeLdaToLdr(BytecodeNode* const current) {
if (current->bytecode() == Bytecode::kStar) {
switch (last_.bytecode()) {
case Bytecode::kLoadIC:
TransformLdaStarToLdrLdar(Bytecode::kLdrNamedProperty, &last_, current);
return true;
case Bytecode::kKeyedLoadIC:
TransformLdaStarToLdrLdar(Bytecode::kLdrKeyedProperty, &last_, current);
return true;
case Bytecode::kLdaGlobal:
TransformLdaStarToLdrLdar(Bytecode::kLdrGlobal, &last_, current);
return true;
case Bytecode::kLdaContextSlot:
TransformLdaStarToLdrLdar(Bytecode::kLdrContextSlot, &last_, current);
return true;
case Bytecode::kLdaUndefined:
TransformLdaStarToLdrLdar(Bytecode::kLdrUndefined, &last_, current);
return true;
default:
break;
}
}
return false;
}
bool BytecodePeepholeOptimizer::RemoveToBooleanFromJump(
BytecodeNode* const current) {
bool can_remove = Bytecodes::IsJumpIfToBoolean(current->bytecode()) &&
Bytecodes::WritesBooleanToAccumulator(last_.bytecode());
if (can_remove) {
// Conditional jumps with boolean conditions are emiitted in
// ToBoolean form by the bytecode array builder,
// i.e. JumpIfToBooleanTrue rather JumpIfTrue. The ToBoolean
// element can be removed if the previous bytecode put a boolean
// value in the accumulator.
Bytecode jump = Bytecodes::GetJumpWithoutToBoolean(current->bytecode());
current->set_bytecode(jump, current->operand(0), current->operand_scale());
}
return can_remove;
}
bool BytecodePeepholeOptimizer::RemoveToBooleanFromLogicalNot(
BytecodeNode* const current) {
bool can_remove = current->bytecode() == Bytecode::kToBooleanLogicalNot &&
Bytecodes::WritesBooleanToAccumulator(last_.bytecode());
if (can_remove) {
// Logical-nots are emitted in ToBoolean form by the bytecode array
// builder, The ToBoolean element can be removed if the previous bytecode
// put a boolean value in the accumulator.
current->set_bytecode(Bytecode::kLogicalNot);
}
return can_remove;
}
bool BytecodePeepholeOptimizer::TransformLastAndCurrentBytecodes(
BytecodeNode* const current) {
return RemoveToBooleanFromJump(current) ||
RemoveToBooleanFromLogicalNot(current) || ChangeLdaToLdr(current);
}
bool BytecodePeepholeOptimizer::CanElideLast(
const BytecodeNode* const current) const {
if (!last_is_discardable_) {
......@@ -200,24 +273,41 @@ bool BytecodePeepholeOptimizer::CanElideLast(
// consecutive accumulator loads (that don't have side effects) then only
// the final load is potentially visible.
return true;
} else if (Bytecodes::GetAccumulatorUse(current->bytecode()) ==
AccumulatorUse::kWrite &&
Bytecodes::IsAccumulatorLoadWithoutEffects(last_.bytecode())) {
// The current instruction clobbers the accumulator without reading it. The
// load in the last instruction can be elided as it has no effect.
return true;
} else {
return false;
}
}
BytecodeNode* BytecodePeepholeOptimizer::Optimize(BytecodeNode* current) {
UpdateLastAndCurrentBytecodes(current);
TryToRemoveLastExpressionPosition(current);
if (TransformLastAndCurrentBytecodes(current)) {
return current;
}
if (CanElideCurrent(current)) {
if (current->source_info().is_valid()) {
// Preserve the source information by replacing the current bytecode
// with a no op bytecode.
current->set_bytecode(Bytecode::kNop);
} else {
current = nullptr;
}
} else if (CanElideLast(current) &&
CanElideLastBasedOnSourcePosition(current)) {
return current;
}
if (CanElideLast(current) && CanElideLastBasedOnSourcePosition(current)) {
current->source_info().Update(last_.source_info());
InvalidateLast();
return current;
}
return current;
}
......
......@@ -29,12 +29,18 @@ class BytecodePeepholeOptimizer final : public BytecodePipelineStage,
private:
BytecodeNode* Optimize(BytecodeNode* current);
void UpdateLastAndCurrentBytecodes(BytecodeNode* const current);
void TryToRemoveLastExpressionPosition(const BytecodeNode* const current);
bool TransformLastAndCurrentBytecodes(BytecodeNode* const current);
bool CanElideCurrent(const BytecodeNode* const current) const;
bool CanElideLast(const BytecodeNode* const current) const;
bool CanElideLastBasedOnSourcePosition(
const BytecodeNode* const current) const;
// Simple substitution methods.
bool RemoveToBooleanFromJump(BytecodeNode* const current);
bool RemoveToBooleanFromLogicalNot(BytecodeNode* const current);
bool ChangeLdaToLdr(BytecodeNode* const current);
void InvalidateLast();
bool LastIsValid() const;
void SetLast(const BytecodeNode* const node);
......
......@@ -89,12 +89,8 @@ void BytecodeNode::set_bytecode(Bytecode bytecode, uint32_t operand0,
operand_scale_ = operand_scale;
}
size_t BytecodeNode::Size() const {
size_t size = Bytecodes::Size(bytecode_, operand_scale_);
if (Bytecodes::OperandScaleRequiresPrefixBytecode(operand_scale_)) {
size += 1;
}
return size;
void BytecodeNode::Clone(const BytecodeNode* const other) {
memcpy(this, other, sizeof(*other));
}
void BytecodeNode::Print(std::ostream& os) const {
......@@ -123,8 +119,31 @@ void BytecodeNode::Print(std::ostream& os) const {
#endif // DEBUG
}
void BytecodeNode::Clone(const BytecodeNode* const other) {
memcpy(this, other, sizeof(*other));
size_t BytecodeNode::Size() const {
size_t size = Bytecodes::Size(bytecode_, operand_scale_);
if (Bytecodes::OperandScaleRequiresPrefixBytecode(operand_scale_)) {
size += 1;
}
return size;
}
void BytecodeNode::Transform(Bytecode new_bytecode, uint32_t extra_operand,
OperandScale extra_operand_scale) {
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);
operand_scale_ = std::max(extra_operand_scale, operand_scale());
operands_[operand_count()] = extra_operand;
bytecode_ = new_bytecode;
}
bool BytecodeNode::operator==(const BytecodeNode& other) const {
......
......@@ -101,6 +101,11 @@ class BytecodeNode final : ZoneObject {
// Return the size when this node is serialized to a bytecode array.
size_t Size() const;
// Transform to a node representing |new_bytecode| which has one
// operand more than the current bytecode.
void Transform(Bytecode new_bytecode, uint32_t extra_operand,
OperandScale extra_operand_scale);
Bytecode bytecode() const { return bytecode_; }
uint32_t operand(int i) const {
......
......@@ -100,14 +100,6 @@ const char* Bytecodes::OperandSizeToString(OperandSize operand_size) {
return "";
}
// static
uint8_t Bytecodes::ToByte(Bytecode bytecode) {
DCHECK(bytecode <= Bytecode::kLast);
return static_cast<uint8_t>(bytecode);
}
// static
Bytecode Bytecodes::FromByte(uint8_t value) {
Bytecode bytecode = static_cast<Bytecode>(value);
......
......@@ -88,8 +88,13 @@ namespace interpreter {
V(LdaFalse, AccumulatorUse::kWrite) \
V(LdaConstant, AccumulatorUse::kWrite, OperandType::kIdx) \
\
/* Loading registers */ \
V(LdrUndefined, AccumulatorUse::kNone, OperandType::kRegOut) \
\
/* Globals */ \
V(LdaGlobal, AccumulatorUse::kWrite, OperandType::kIdx, OperandType::kIdx) \
V(LdrGlobal, AccumulatorUse::kNone, OperandType::kIdx, OperandType::kIdx, \
OperandType::kRegOut) \
V(LdaGlobalInsideTypeof, AccumulatorUse::kWrite, OperandType::kIdx, \
OperandType::kIdx) \
V(StaGlobalSloppy, AccumulatorUse::kRead, OperandType::kIdx, \
......@@ -102,6 +107,8 @@ namespace interpreter {
V(PopContext, AccumulatorUse::kNone, OperandType::kReg) \
V(LdaContextSlot, AccumulatorUse::kWrite, OperandType::kReg, \
OperandType::kIdx) \
V(LdrContextSlot, AccumulatorUse::kNone, OperandType::kReg, \
OperandType::kIdx, OperandType::kRegOut) \
V(StaContextSlot, AccumulatorUse::kRead, OperandType::kReg, \
OperandType::kIdx) \
\
......@@ -121,8 +128,12 @@ namespace interpreter {
/* LoadIC operations */ \
V(LoadIC, AccumulatorUse::kWrite, OperandType::kReg, OperandType::kIdx, \
OperandType::kIdx) \
V(LdrNamedProperty, AccumulatorUse::kNone, OperandType::kReg, \
OperandType::kIdx, OperandType::kIdx, OperandType::kRegOut) \
V(KeyedLoadIC, AccumulatorUse::kReadWrite, OperandType::kReg, \
OperandType::kIdx) \
V(LdrKeyedProperty, AccumulatorUse::kRead, OperandType::kReg, \
OperandType::kIdx, OperandType::kRegOut) \
\
/* StoreIC operations */ \
V(StoreICSloppy, AccumulatorUse::kRead, OperandType::kReg, \
......@@ -442,7 +453,10 @@ class Bytecodes {
static const char* OperandSizeToString(OperandSize operand_size);
// Returns byte value of bytecode.
static uint8_t ToByte(Bytecode bytecode);
static uint8_t ToByte(Bytecode bytecode) {
DCHECK_LE(bytecode, Bytecode::kLast);
return static_cast<uint8_t>(bytecode);
}
// Returns bytecode for |value|.
static Bytecode FromByte(uint8_t value);
......
This diff is collapsed.
......@@ -88,22 +88,10 @@ class Interpreter {
// |compare_op|.
void DoCompareOp(Token::Value compare_op, InterpreterAssembler* assembler);
// Generates code to load a constant from the constant pool.
void DoLoadConstant(InterpreterAssembler* assembler);
// Generates code to perform a global load via |ic|.
void DoLoadGlobal(Callable ic, InterpreterAssembler* assembler);
// Generates code to perform a global store via |ic|.
void DoStoreGlobal(Callable ic, InterpreterAssembler* assembler);
// Generates code to perform a named property load via |ic|.
void DoLoadIC(Callable ic, InterpreterAssembler* assembler);
void DoStaGlobal(Callable ic, InterpreterAssembler* assembler);
// Generates code to perform a keyed property load via |ic|.
void DoKeyedLoadIC(Callable ic, InterpreterAssembler* assembler);
// Generates code to perform a namedproperty store via |ic|.
// Generates code to perform a named property store via |ic|.
void DoStoreIC(Callable ic, InterpreterAssembler* assembler);
// Generates code to perform a keyed property store via |ic|.
......@@ -129,12 +117,29 @@ class Interpreter {
InterpreterAssembler* assembler);
// Generates code to perform a lookup slot load via |function_id|.
void DoLoadLookupSlot(Runtime::FunctionId function_id,
InterpreterAssembler* assembler);
void DoLdaLookupSlot(Runtime::FunctionId function_id,
InterpreterAssembler* assembler);
// Generates code to perform a lookup slot store depending on |language_mode|.
void DoStoreLookupSlot(LanguageMode language_mode,
InterpreterAssembler* assembler);
void DoStaLookupSlot(LanguageMode language_mode,
InterpreterAssembler* assembler);
// Generates a node with the undefined constant.
compiler::Node* BuildLoadUndefined(InterpreterAssembler* assembler);
// Generates code to load a context slot.
compiler::Node* BuildLoadContextSlot(InterpreterAssembler* assembler);
// Generates code to load a global.
compiler::Node* BuildLoadGlobal(Callable ic, InterpreterAssembler* assembler);
// Generates code to load a named property.
compiler::Node* BuildLoadNamedProperty(Callable ic,
InterpreterAssembler* assembler);
// Generates code to load a keyed property.
compiler::Node* BuildLoadKeyedProperty(Callable ic,
InterpreterAssembler* assembler);
// Generates code to perform logical-not on boolean |value| and returns the
// result.
......
......@@ -16,13 +16,11 @@ snippet: "
"
frame size: 2
parameter count: 1
bytecode array length: 15
bytecode array length: 13
bytecodes: [
/* 27 E> */ B(StackCheck),
/* 32 S> */ B(LdaUndefined),
B(Star), R(1),
B(LdaGlobal), U8(0), U8(3),
B(Star), R(0),
/* 32 S> */ B(LdrUndefined), R(1),
B(LdrGlobal), U8(0), U8(3), R(0),
/* 39 E> */ B(Call), R(0), R(1), U8(1), U8(1),
/* 44 S> */ B(Return),
]
......@@ -40,13 +38,11 @@ snippet: "
"
frame size: 5
parameter count: 1
bytecode array length: 27
bytecode array length: 25
bytecodes: [
/* 34 E> */ B(StackCheck),
/* 39 S> */ B(LdaUndefined),
B(Star), R(1),
B(LdaGlobal), U8(0), U8(3),
B(Star), R(0),
/* 39 S> */ B(LdrUndefined), R(1),
B(LdrGlobal), U8(0), U8(3), R(0),
B(LdaSmi), U8(1),
B(Star), R(2),
B(LdaSmi), U8(2),
......
......@@ -16,11 +16,11 @@ snippet: "
"
frame size: 1
parameter count: 1
bytecode array length: 11
bytecode array length: 12
bytecodes: [
/* 45 E> */ B(StackCheck),
/* 50 S> */ B(LdaGlobal), U8(0), U8(3),
B(Star), R(0),
/* 50 S> */ B(LdrGlobal), U8(0), U8(3), R(0),
B(Ldar), R(0),
/* 57 E> */ B(New), R(0), R(0), U8(0),
/* 68 S> */ B(Return),
]
......@@ -38,11 +38,10 @@ snippet: "
"
frame size: 2
parameter count: 1
bytecode array length: 17
bytecode array length: 16
bytecodes: [
/* 58 E> */ B(StackCheck),
/* 63 S> */ B(LdaGlobal), U8(0), U8(3),
B(Star), R(0),
/* 63 S> */ B(LdrGlobal), U8(0), U8(3), R(0),
B(LdaSmi), U8(3),
B(Star), R(1),
/* 70 E> */ B(Ldar), R(0),
......@@ -68,11 +67,10 @@ snippet: "
"
frame size: 4
parameter count: 1
bytecode array length: 25
bytecode array length: 24
bytecodes: [
/* 100 E> */ B(StackCheck),
/* 105 S> */ B(LdaGlobal), U8(0), U8(3),
B(Star), R(0),
/* 105 S> */ B(LdrGlobal), U8(0), U8(3), R(0),
B(LdaSmi), U8(3),
B(Star), R(1),
B(LdaSmi), U8(4),
......
......@@ -76,11 +76,10 @@ snippet: "
"
frame size: 2
parameter count: 1
bytecode array length: 15
bytecode array length: 14
bytecodes: [
/* 10 E> */ B(StackCheck),
/* 15 S> */ B(LdaUndefined),
B(Star), R(0),
/* 15 S> */ B(LdrUndefined), R(0),
B(CreateArrayLiteral), U8(0), U8(0), U8(3),
B(Star), R(1),
B(CallJSRuntime), U8(122), R(0), U8(2),
......
......@@ -24,7 +24,7 @@ snippet: "
"
frame size: 7
parameter count: 1
bytecode array length: 57
bytecode array length: 56
bytecodes: [
B(Ldar), R(closure),
B(Star), R(0),
......@@ -38,8 +38,7 @@ bytecodes: [
B(CallRuntime), U16(Runtime::kThrowReferenceError), R(6), U8(1),
B(Star), R(6),
/* 111 E> */ B(LdaConstant), U8(1),
B(KeyedLoadIC), R(6), U8(3),
B(Star), R(4),
B(LdrKeyedProperty), R(6), U8(3), R(4),
B(LdaConstant), U8(2),
B(Star), R(5),
B(CallRuntime), U16(Runtime::kLoadFromSuper), R(3), U8(3),
......@@ -76,7 +75,7 @@ snippet: "
"
frame size: 6
parameter count: 1
bytecode array length: 80
bytecode array length: 78
bytecodes: [
B(Ldar), R(closure),
B(Star), R(0),
......@@ -90,8 +89,7 @@ bytecodes: [
B(CallRuntime), U16(Runtime::kThrowReferenceError), R(5), U8(1),
B(Star), R(5),
/* 130 E> */ B(LdaConstant), U8(1),
B(KeyedLoadIC), R(5), U8(1),
B(Star), R(2),
B(LdrKeyedProperty), R(5), U8(1), R(2),
B(LdaConstant), U8(2),
B(Star), R(3),
B(LdaSmi), U8(2),
......@@ -106,8 +104,7 @@ bytecodes: [
B(CallRuntime), U16(Runtime::kThrowReferenceError), R(4), U8(1),
B(Star), R(4),
/* 150 E> */ B(LdaConstant), U8(1),
B(KeyedLoadIC), R(4), U8(3),
B(Star), R(2),
B(LdrKeyedProperty), R(4), U8(3), R(2),
B(LdaConstant), U8(2),
B(Star), R(3),
B(CallRuntime), U16(Runtime::kLoadFromSuper), R(1), U8(3),
......
......@@ -16,7 +16,7 @@ snippet: "
"
frame size: 9
parameter count: 1
bytecode array length: 73
bytecode array length: 74
bytecodes: [
B(LdaTheHole),
B(Star), R(1),
......@@ -33,8 +33,8 @@ bytecodes: [
B(Star), R(5),
B(CallRuntime), U16(Runtime::kDefineClass), R(2), U8(4),
B(Star), R(2),
B(LoadIC), R(2), U8(1), U8(1),
B(Star), R(3),
B(LdrNamedProperty), R(2), U8(1), U8(1), R(3),
B(Ldar), R(3),
B(Mov), R(3), R(4),
B(LdaConstant), U8(2),
B(Star), R(5),
......@@ -69,7 +69,7 @@ snippet: "
"
frame size: 9
parameter count: 1
bytecode array length: 73
bytecode array length: 74
bytecodes: [
B(LdaTheHole),
B(Star), R(1),
......@@ -86,8 +86,8 @@ bytecodes: [
B(Star), R(5),
B(CallRuntime), U16(Runtime::kDefineClass), R(2), U8(4),
B(Star), R(2),
B(LoadIC), R(2), U8(1), U8(1),
B(Star), R(3),
B(LdrNamedProperty), R(2), U8(1), U8(1), R(3),
B(Ldar), R(3),
B(Mov), R(3), R(4),
B(LdaConstant), U8(2),
B(Star), R(5),
......@@ -124,7 +124,7 @@ snippet: "
"
frame size: 10
parameter count: 1
bytecode array length: 127
bytecode array length: 128
bytecodes: [
B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
B(PushContext), R(2),
......@@ -147,8 +147,8 @@ bytecodes: [
B(Star), R(6),
B(CallRuntime), U16(Runtime::kDefineClass), R(3), U8(4),
B(Star), R(3),
B(LoadIC), R(3), U8(3), U8(1),
B(Star), R(4),
B(LdrNamedProperty), R(3), U8(3), U8(1), R(4),
B(Ldar), R(4),
B(Mov), R(4), R(5),
/* 75 E> */ B(LdaContextSlot), R(context), U8(4),
B(ToName),
......@@ -198,7 +198,7 @@ snippet: "
"
frame size: 7
parameter count: 1
bytecode array length: 74
bytecode array length: 73
bytecodes: [
B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
B(PushContext), R(2),
......@@ -219,8 +219,7 @@ bytecodes: [
B(Star), R(6),
B(CallRuntime), U16(Runtime::kDefineClass), R(3), U8(4),
B(Star), R(3),
B(LoadIC), R(3), U8(1), U8(1),
B(Star), R(4),
B(LdrNamedProperty), R(3), U8(1), U8(1), R(4),
B(CallRuntime), U16(Runtime::kToFastProperties), R(3), U8(1),
B(Star), R(0),
B(Star), R(1),
......
......@@ -59,15 +59,14 @@ snippet: "
"
frame size: 3
parameter count: 1
bytecode array length: 27
bytecode array length: 26
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(CreateObjectLiteral), U8(0), U8(0), U8(1),
B(Star), R(1),
B(Star), R(0),
/* 54 S> */ B(Star), R(1),
B(LoadIC), R(1), U8(1), U8(1),
B(Star), R(2),
B(LdrNamedProperty), R(1), U8(1), U8(1), R(2),
B(LdaSmi), U8(2),
B(Mul), R(2),
/* 61 E> */ B(StoreICSloppy), R(1), U8(1), U8(3),
......@@ -87,7 +86,7 @@ snippet: "
"
frame size: 4
parameter count: 1
bytecode array length: 30
bytecode array length: 29
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(CreateObjectLiteral), U8(0), U8(0), U8(1),
......@@ -96,8 +95,7 @@ bytecodes: [
/* 52 S> */ B(Star), R(1),
B(LdaSmi), U8(1),
B(Star), R(2),
B(KeyedLoadIC), R(1), U8(1),
B(Star), R(3),
B(LdrKeyedProperty), R(1), U8(1), R(3),
B(LdaSmi), U8(2),
B(BitwiseXor), R(3),
/* 57 E> */ B(KeyedStoreICSloppy), R(1), R(2), U8(3),
......@@ -116,7 +114,7 @@ snippet: "
"
frame size: 2
parameter count: 1
bytecode array length: 30
bytecode array length: 29
bytecodes: [
B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
B(PushContext), R(0),
......@@ -124,8 +122,7 @@ bytecodes: [
/* 42 S> */ B(LdaSmi), U8(1),
/* 42 E> */ B(StaContextSlot), R(context), U8(4),
/* 45 S> */ B(CreateClosure), U8(0), U8(0),
/* 75 S> */ B(LdaContextSlot), R(context), U8(4),
B(Star), R(1),
/* 75 S> */ B(LdrContextSlot), R(context), U8(4), R(1),
B(LdaSmi), U8(24),
B(BitwiseOr), R(1),
/* 77 E> */ B(StaContextSlot), R(context), U8(4),
......
......@@ -79,13 +79,12 @@ snippet: "
"
frame size: 3
parameter count: 1
bytecode array length: 25
bytecode array length: 24
bytecodes: [
B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
B(PushContext), R(0),
/* 30 E> */ B(StackCheck),
/* 41 S> */ B(LdaUndefined),
B(Star), R(2),
/* 41 S> */ B(LdrUndefined), R(2),
B(CreateClosure), U8(0), U8(0),
B(Star), R(1),
/* 64 E> */ B(Call), R(1), R(2), U8(1), U8(1),
......@@ -394,7 +393,7 @@ snippet: "
"
frame size: 3
parameter count: 1
bytecode array length: 1046
bytecode array length: 1044
bytecodes: [
B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
B(PushContext), R(0),
......@@ -903,10 +902,8 @@ bytecodes: [
/* 3407 E> */ B(StaContextSlot), R(context), U8(254),
/* 3421 S> */ B(LdaZero),
/* 3421 E> */ B(StaContextSlot), R(context), U8(255),
/* 3424 S> */ B(LdaUndefined),
B(Star), R(2),
/* 3424 E> */ B(LdaGlobal), U8(0), U8(1),
B(Star), R(1),
/* 3424 S> */ B(LdrUndefined), R(2),
/* 3424 E> */ B(LdrGlobal), U8(0), U8(1), R(1),
/* 3424 E> */ B(Call), R(1), R(2), U8(1), U8(0),
/* 3440 S> */ B(LdaSmi), U8(100),
/* 3440 E> */ B(Wide), B(StaContextSlot), R16(context), U16(256),
......
......@@ -86,7 +86,7 @@ snippet: "
"
frame size: 5
parameter count: 2
bytecode array length: 35
bytecode array length: 34
bytecodes: [
B(CreateUnmappedArguments),
B(Star), R(0),
......@@ -100,8 +100,7 @@ bytecodes: [
/* 29 S> */ B(Ldar), R(1),
B(Star), R(3),
/* 44 E> */ B(LdaZero),
B(KeyedLoadIC), R(3), U8(1),
B(Star), R(4),
B(LdrKeyedProperty), R(3), U8(1), R(4),
/* 50 E> */ B(Ldar), R(0),
B(Star), R(3),
/* 59 E> */ B(LdaZero),
......
......@@ -103,7 +103,7 @@ snippet: "
"
frame size: 3
parameter count: 1
bytecode array length: 29
bytecode array length: 27
bytecodes: [
B(LdaConstant), U8(0),
B(Star), R(1),
......@@ -111,10 +111,8 @@ bytecodes: [
B(Star), R(2),
B(CallRuntime), U16(Runtime::kDeclareGlobals), R(1), U8(2),
/* 0 E> */ B(StackCheck),
/* 16 S> */ B(LdaUndefined),
B(Star), R(2),
B(LdaGlobal), U8(1), U8(1),
B(Star), R(1),
/* 16 S> */ B(LdrUndefined), R(2),
B(LdrGlobal), U8(1), U8(1), R(1),
/* 16 E> */ B(Call), R(1), R(2), U8(1), U8(3),
B(Star), R(0),
/* 20 S> */ B(Return),
......
......@@ -106,7 +106,7 @@ snippet: "
"
frame size: 2
parameter count: 1
bytecode array length: 30
bytecode array length: 29
bytecodes: [
B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), U8(1),
B(PushContext), R(0),
......@@ -115,8 +115,7 @@ bytecodes: [
B(Star), R(1),
/* 56 E> */ B(StaContextSlot), R(context), U8(4),
/* 64 S> */ B(CreateClosure), U8(1), U8(0),
/* 93 S> */ B(LdaContextSlot), R(context), U8(4),
B(Star), R(1),
/* 93 S> */ B(LdrContextSlot), R(context), U8(4), R(1),
B(LdaSmi), U8(1),
B(DeletePropertyStrict), R(1),
/* 113 S> */ B(Return),
......
......@@ -33,13 +33,13 @@ snippet: "
"
frame size: 3
parameter count: 1
bytecode array length: 13
bytecode array length: 14
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 55 S> */ B(LdaSmi), U8(100),
B(Star), R(1),
/* 42 S> */ B(LdaUndefined),
B(Star), R(0),
/* 42 S> */ B(LdrUndefined), R(0),
B(Ldar), R(0),
/* 42 E> */ B(Nop),
B(Star), R(2),
/* 63 S> */ B(Nop),
......
......@@ -154,24 +154,24 @@ snippet: "
"
frame size: 8
parameter count: 1
bytecode array length: 94
bytecode array length: 92
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(CreateObjectLiteral), U8(0), U8(0), U8(1),
B(Star), R(1),
B(Star), R(0),
/* 77 S> */ B(CreateArrayLiteral), U8(1), U8(1), U8(3),
B(JumpIfUndefined), U8(79),
B(JumpIfNull), U8(77),
B(JumpIfUndefined), U8(77),
B(JumpIfNull), U8(75),
B(ToObject),
B(Star), R(1),
B(ForInPrepare), R(2),
B(LdaZero),
B(Star), R(5),
/* 68 S> */ B(ForInDone), R(5), R(4),
B(JumpIfTrue), U8(64),
B(JumpIfTrue), U8(62),
B(ForInNext), R(1), R(5), R(2), U8(9),
B(JumpIfUndefined), U8(51),
B(JumpIfUndefined), U8(49),
B(Star), R(6),
/* 67 E> */ B(Ldar), R(0),
B(Star), R(7),
......@@ -180,23 +180,21 @@ bytecodes: [
/* 62 E> */ B(StackCheck),
/* 95 S> */ B(Ldar), R(0),
B(Star), R(6),
/* 100 E> */ B(LoadIC), R(6), U8(2), U8(3),
B(Star), R(7),
/* 100 E> */ B(LdrNamedProperty), R(6), U8(2), U8(3), R(7),
B(LdaSmi), U8(10),
/* 106 E> */ B(TestEqual), R(7),
B(JumpIfFalse), U8(4),
/* 113 S> */ B(Jump), U8(20),
/* 113 S> */ B(Jump), U8(19),
/* 125 S> */ B(Ldar), R(0),
B(Star), R(6),
/* 130 E> */ B(LoadIC), R(6), U8(2), U8(5),
B(Star), R(7),
/* 130 E> */ B(LdrNamedProperty), R(6), U8(2), U8(5), R(7),
B(LdaSmi), U8(20),
/* 136 E> */ B(TestEqual), R(7),
B(JumpIfFalse), U8(4),
/* 143 S> */ B(Jump), U8(8),
B(ForInStep), R(5),
B(Star), R(5),
B(Jump), U8(-65),
B(Jump), U8(-63),
B(LdaUndefined),
/* 152 S> */ B(Return),
]
......
......@@ -31,11 +31,10 @@ snippet: "
"
frame size: 2
parameter count: 1
bytecode array length: 15
bytecode array length: 14
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 34 S> */ B(LdaUndefined),
B(Star), R(1),
/* 34 S> */ B(LdrUndefined), R(1),
B(CreateClosure), U8(0), U8(0),
B(Star), R(0),
/* 56 E> */ B(Call), R(0), R(1), U8(1), U8(1),
......@@ -53,11 +52,10 @@ snippet: "
"
frame size: 3
parameter count: 1
bytecode array length: 19
bytecode array length: 18
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 34 S> */ B(LdaUndefined),
B(Star), R(1),
/* 34 S> */ B(LdrUndefined), R(1),
B(CreateClosure), U8(0), U8(0),
B(Star), R(0),
B(LdaSmi), U8(1),
......
......@@ -16,11 +16,10 @@ snippet: "
"
frame size: 1
parameter count: 1
bytecode array length: 14
bytecode array length: 13
bytecodes: [
/* 26 E> */ B(StackCheck),
/* 31 S> */ B(LdaGlobal), U8(0), U8(1),
B(Star), R(0),
/* 31 S> */ B(LdrGlobal), U8(0), U8(1), R(0),
B(LdaSmi), U8(1),
B(BitwiseAnd), R(0),
/* 45 E> */ B(StaGlobalSloppy), U8(0), U8(3),
......@@ -40,11 +39,10 @@ snippet: "
"
frame size: 1
parameter count: 1
bytecode array length: 14
bytecode array length: 13
bytecodes: [
/* 27 E> */ B(StackCheck),
/* 32 S> */ B(LdaGlobal), U8(0), U8(1),
B(Star), R(0),
/* 32 S> */ B(LdrGlobal), U8(0), U8(1), R(0),
B(LdaSmi), U8(1),
B(Add), R(0),
/* 51 E> */ B(StaGlobalSloppy), U8(0), U8(3),
......
......@@ -18,11 +18,10 @@ snippet: "
"
frame size: 1
parameter count: 1
bytecode array length: 11
bytecode array length: 10
bytecodes: [
/* 32 E> */ B(StackCheck),
/* 39 S> */ B(LdaGlobal), U8(0), U8(1),
B(Star), R(0),
/* 39 S> */ B(LdrGlobal), U8(0), U8(1), R(0),
B(LdaConstant), U8(1),
B(DeletePropertySloppy), R(0),
/* 58 S> */ B(Return),
......@@ -45,11 +44,10 @@ snippet: "
"
frame size: 1
parameter count: 1
bytecode array length: 11
bytecode array length: 10
bytecodes: [
/* 28 E> */ B(StackCheck),
/* 51 S> */ B(LdaGlobal), U8(0), U8(1),
B(Star), R(0),
/* 51 S> */ B(LdrGlobal), U8(0), U8(1), R(0),
B(LdaSmi), U8(1),
B(DeletePropertyStrict), R(0),
/* 71 S> */ B(Return),
......@@ -70,13 +68,11 @@ snippet: "
"
frame size: 2
parameter count: 1
bytecode array length: 16
bytecode array length: 14
bytecodes: [
/* 32 E> */ B(StackCheck),
/* 39 S> */ B(LdaContextSlot), R(context), U8(3),
B(Star), R(0),
B(LdaContextSlot), R(0), U8(2),
B(Star), R(1),
/* 39 S> */ B(LdrContextSlot), R(context), U8(3), R(0),
B(LdrContextSlot), R(0), U8(2), R(1),
B(LdaConstant), U8(0),
B(DeletePropertySloppy), R(1),
/* 56 S> */ B(Return),
......@@ -97,13 +93,11 @@ snippet: "
"
frame size: 2
parameter count: 1
bytecode array length: 16
bytecode array length: 14
bytecodes: [
/* 18 E> */ B(StackCheck),
/* 25 S> */ B(LdaContextSlot), R(context), U8(3),
B(Star), R(0),
B(LdaContextSlot), R(0), U8(2),
B(Star), R(1),
/* 25 S> */ B(LdrContextSlot), R(context), U8(3), R(0),
B(LdrContextSlot), R(0), U8(2), R(1),
B(LdaConstant), U8(0),
B(DeletePropertySloppy), R(1),
/* 42 S> */ B(Return),
......
......@@ -22,15 +22,13 @@ snippet: "
"
frame size: 2
parameter count: 1
bytecode array length: 21
bytecode array length: 19
bytecodes: [
/* 97 E> */ B(StackCheck),
/* 102 S> */ B(Ldar), R(context),
B(Star), R(0),
B(LdaContextSlot), R(0), U8(1),
B(Star), R(0),
B(LdaContextSlot), R(0), U8(4),
B(Star), R(1),
B(LdrContextSlot), R(0), U8(1), R(0),
B(LdrContextSlot), R(0), U8(4), R(1),
/* 120 E> */ B(LdaContextSlot), R(context), U8(4),
B(Mul), R(1),
/* 130 S> */ B(Return),
......@@ -54,15 +52,13 @@ snippet: "
"
frame size: 2
parameter count: 1
bytecode array length: 22
bytecode array length: 20
bytecodes: [
/* 97 E> */ B(StackCheck),
/* 102 S> */ B(LdaContextSlot), R(context), U8(4),
/* 111 E> */ B(Star), R(0),
/* 102 S> */ B(LdrContextSlot), R(context), U8(4), R(0),
B(Ldar), R(context),
B(Star), R(1),
B(LdaContextSlot), R(1), U8(1),
B(Star), R(1),
B(LdrContextSlot), R(1), U8(1), R(1),
B(Ldar), R(0),
B(StaContextSlot), R(1), U8(4),
B(LdaUndefined),
......
......@@ -15,13 +15,12 @@ snippet: "
"
frame size: 2
parameter count: 2
bytecode array length: 17
bytecode array length: 16
bytecodes: [
/* 10 E> */ B(StackCheck),
/* 16 S> */ B(Ldar), R(arg0),
B(Star), R(1),
/* 24 E> */ B(LoadIC), R(1), U8(0), U8(3),
B(Star), R(0),
/* 24 E> */ B(LdrNamedProperty), R(1), U8(0), U8(3), R(0),
/* 25 E> */ B(Call), R(0), R(1), U8(1), U8(1),
/* 33 S> */ B(Return),
]
......@@ -38,13 +37,12 @@ snippet: "
"
frame size: 4
parameter count: 4
bytecode array length: 25
bytecode array length: 24
bytecodes: [
/* 10 E> */ B(StackCheck),
/* 22 S> */ B(Ldar), R(arg0),
B(Star), R(1),
/* 30 E> */ B(LoadIC), R(1), U8(0), U8(3),
B(Star), R(0),
/* 30 E> */ B(LdrNamedProperty), R(1), U8(0), U8(3), R(0),
/* 36 E> */ B(Ldar), R(arg1),
B(Star), R(2),
/* 39 E> */ B(Ldar), R(arg2),
......@@ -65,13 +63,12 @@ snippet: "
"
frame size: 4
parameter count: 3
bytecode array length: 31
bytecode array length: 30
bytecodes: [
/* 10 E> */ B(StackCheck),
/* 19 S> */ B(Ldar), R(arg0),
B(Star), R(1),
/* 27 E> */ B(LoadIC), R(1), U8(0), U8(3),
B(Star), R(0),
/* 27 E> */ B(LdrNamedProperty), R(1), U8(0), U8(3), R(0),
/* 33 E> */ B(Ldar), R(arg1),
B(Star), R(3),
/* 37 E> */ B(Ldar), R(arg1),
......@@ -613,8 +610,7 @@ bytecodes: [
/* 1161 E> */ B(LoadIC), R(0), U8(0), U8(255),
/* 1169 S> */ B(Ldar), R(arg0),
B(Star), R(1),
/* 1177 E> */ B(Wide), B(LoadIC), R16(1), U16(0), U16(259),
B(Star), R(0),
/* 1177 E> */ B(Wide), B(LdrNamedProperty), R16(1), U16(0), U16(259), R16(0),
/* 1178 E> */ B(Wide), B(Call), R16(0), R16(1), U16(1), U16(257),
/* 1186 S> */ B(Return),
]
......
......@@ -49,13 +49,12 @@ snippet: "
"
frame size: 3
parameter count: 1
bytecode array length: 23
bytecode array length: 22
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 34 S> */ B(CreateRegExpLiteral), U8(0), U8(0), U8(0),
B(Star), R(1),
/* 47 E> */ B(LoadIC), R(1), U8(1), U8(3),
B(Star), R(0),
/* 47 E> */ B(LdrNamedProperty), R(1), U8(1), U8(3), R(0),
B(LdaConstant), U8(2),
B(Star), R(2),
/* 48 E> */ B(Call), R(0), R(1), U8(2), U8(1),
......
......@@ -106,7 +106,7 @@ snippet: "
"
frame size: 4
parameter count: 1
bytecode array length: 24
bytecode array length: 25
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(Wide), B(LdaSmi), U16(1234),
......@@ -117,8 +117,8 @@ bytecodes: [
B(Star), R(3),
B(LdaSmi), U8(1),
B(Sub), R(3),
B(LdaUndefined),
B(Star), R(1),
/* 56 E> */ B(LdrUndefined), R(1),
B(Ldar), R(1),
/* 74 S> */ B(Nop),
/* 84 S> */ B(Return),
]
......
......@@ -47,7 +47,7 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
.LoadLiteral(factory->NewStringFromStaticChars("A constant"))
.StoreAccumulatorInRegister(reg)
.LoadUndefined()
.StoreAccumulatorInRegister(reg)
.Debugger() // Prevent peephole optimization LdaNull, Star -> LdrNull.
.LoadNull()
.StoreAccumulatorInRegister(reg)
.LoadTheHole()
......@@ -349,6 +349,13 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
// Insert entry for nop bytecode as this often gets optimized out.
scorecard[Bytecodes::ToByte(Bytecode::kNop)] = 1;
// Insert entries for bytecodes only emiited by peephole optimizer.
scorecard[Bytecodes::ToByte(Bytecode::kLdrNamedProperty)] = 1;
scorecard[Bytecodes::ToByte(Bytecode::kLdrKeyedProperty)] = 1;
scorecard[Bytecodes::ToByte(Bytecode::kLdrGlobal)] = 1;
scorecard[Bytecodes::ToByte(Bytecode::kLdrContextSlot)] = 1;
scorecard[Bytecodes::ToByte(Bytecode::kLdrUndefined)] = 1;
// Check return occurs at the end and only once in the BytecodeArray.
CHECK_EQ(final_bytecode, Bytecode::kReturn);
CHECK_EQ(scorecard[Bytecodes::ToByte(final_bytecode)], 1);
......
......@@ -49,6 +49,7 @@ TEST_F(BytecodeArrayIteratorTest, IteratesBytecodeArray) {
.LoadAccumulatorWithRegister(reg_0)
.StoreAccumulatorInRegister(reg_1)
.LoadNamedProperty(reg_1, name, feedback_slot)
.BinaryOperation(Token::Value::ADD, reg_0)
.StoreAccumulatorInRegister(param)
.CallRuntimeForPair(Runtime::kLoadLookupSlotForCall, param, 1, reg_0)
.ForInPrepare(reg_0)
......@@ -174,6 +175,15 @@ TEST_F(BytecodeArrayIteratorTest, IteratesBytecodeArray) {
offset += Bytecodes::Size(Bytecode::kLoadIC, OperandScale::kSingle);
iterator.Advance();
CHECK_EQ(iterator.current_bytecode(), Bytecode::kAdd);
CHECK_EQ(iterator.current_offset(), offset);
CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
CHECK_EQ(iterator.GetRegisterOperand(0).index(), reg_0.index());
CHECK_EQ(iterator.GetRegisterOperandRange(0), 1);
CHECK(!iterator.done());
offset += Bytecodes::Size(Bytecode::kStar, OperandScale::kSingle);
iterator.Advance();
CHECK_EQ(iterator.current_bytecode(), Bytecode::kStar);
CHECK_EQ(iterator.current_offset(), offset);
CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
......
......@@ -380,6 +380,145 @@ TEST_F(BytecodePeepholeOptimizerTest, NopStatementStackCheck) {
CHECK_EQ(last_written(), second);
}
// Tests covering BytecodePeepholeOptimizer::UpdateLastAndCurrentBytecodes().
TEST_F(BytecodePeepholeOptimizerTest, MergeLoadICStar) {
const uint32_t operands[] = {
static_cast<uint32_t>(Register(31).ToOperand()), 32, 33,
static_cast<uint32_t>(Register(256).ToOperand())};
const int expected_operand_count = static_cast<int>(arraysize(operands));
BytecodeNode first(Bytecode::kLoadIC, operands[0], operands[1], operands[2],
OperandScale::kSingle);
BytecodeNode second(Bytecode::kStar, operands[3], OperandScale::kDouble);
BytecodeNode third(Bytecode::kReturn);
optimizer()->Write(&first);
optimizer()->Write(&second);
CHECK_EQ(write_count(), 1);
CHECK_EQ(last_written().bytecode(), Bytecode::kLdrNamedProperty);
CHECK_EQ(last_written().operand_count(), expected_operand_count);
for (int i = 0; i < expected_operand_count; ++i) {
CHECK_EQ(last_written().operand(i), operands[i]);
}
CHECK_EQ(last_written().operand_scale(),
std::max(first.operand_scale(), second.operand_scale()));
optimizer()->Write(&third);
CHECK_EQ(write_count(), 2);
CHECK_EQ(last_written().bytecode(), Bytecode::kLdar);
CHECK_EQ(last_written().operand(0), operands[expected_operand_count - 1]);
optimizer()->FlushBasicBlock();
CHECK_EQ(last_written().bytecode(), third.bytecode());
}
TEST_F(BytecodePeepholeOptimizerTest, MergeKeyedLoadICStar) {
const uint32_t operands[] = {static_cast<uint32_t>(Register(31).ToOperand()),
9999997,
static_cast<uint32_t>(Register(1).ToOperand())};
const int expected_operand_count = static_cast<int>(arraysize(operands));
BytecodeNode first(Bytecode::kKeyedLoadIC, operands[0], operands[1],
OperandScale::kQuadruple);
BytecodeNode second(Bytecode::kStar, operands[2], OperandScale::kSingle);
BytecodeNode third(Bytecode::kReturn);
optimizer()->Write(&first);
optimizer()->Write(&second);
CHECK_EQ(write_count(), 1);
CHECK_EQ(last_written().bytecode(), Bytecode::kLdrKeyedProperty);
CHECK_EQ(last_written().operand_count(), expected_operand_count);
for (int i = 0; i < expected_operand_count; ++i) {
CHECK_EQ(last_written().operand(i), operands[i]);
}
CHECK_EQ(last_written().operand_scale(),
std::max(first.operand_scale(), second.operand_scale()));
optimizer()->Write(&third);
CHECK_EQ(write_count(), 2);
CHECK_EQ(last_written().bytecode(), Bytecode::kLdar);
CHECK_EQ(last_written().operand(0), operands[expected_operand_count - 1]);
optimizer()->FlushBasicBlock();
CHECK_EQ(last_written().bytecode(), third.bytecode());
}
TEST_F(BytecodePeepholeOptimizerTest, MergeLdaGlobalStar) {
const uint32_t operands[] = {54321, 19191,
static_cast<uint32_t>(Register(1).ToOperand())};
const int expected_operand_count = static_cast<int>(arraysize(operands));
BytecodeNode first(Bytecode::kLdaGlobal, operands[0], operands[1],
OperandScale::kDouble);
BytecodeNode second(Bytecode::kStar, operands[2], OperandScale::kSingle);
BytecodeNode third(Bytecode::kReturn);
optimizer()->Write(&first);
optimizer()->Write(&second);
CHECK_EQ(write_count(), 1);
CHECK_EQ(last_written().bytecode(), Bytecode::kLdrGlobal);
CHECK_EQ(last_written().operand_count(), expected_operand_count);
for (int i = 0; i < expected_operand_count; ++i) {
CHECK_EQ(last_written().operand(i), operands[i]);
}
CHECK_EQ(last_written().operand_scale(),
std::max(first.operand_scale(), second.operand_scale()));
optimizer()->Write(&third);
CHECK_EQ(write_count(), 2);
CHECK_EQ(last_written().bytecode(), Bytecode::kLdar);
CHECK_EQ(last_written().operand(0), operands[expected_operand_count - 1]);
optimizer()->FlushBasicBlock();
CHECK_EQ(last_written().bytecode(), third.bytecode());
}
TEST_F(BytecodePeepholeOptimizerTest, MergeLdaContextSlotStar) {
const uint32_t operands[] = {
static_cast<uint32_t>(Register(200000).ToOperand()), 55005500,
static_cast<uint32_t>(Register(1).ToOperand())};
const int expected_operand_count = static_cast<int>(arraysize(operands));
BytecodeNode first(Bytecode::kLdaContextSlot, operands[0], operands[1],
OperandScale::kQuadruple);
BytecodeNode second(Bytecode::kStar, operands[2], OperandScale::kSingle);
BytecodeNode third(Bytecode::kReturn);
optimizer()->Write(&first);
optimizer()->Write(&second);
CHECK_EQ(write_count(), 1);
CHECK_EQ(last_written().bytecode(), Bytecode::kLdrContextSlot);
CHECK_EQ(last_written().operand_count(), expected_operand_count);
for (int i = 0; i < expected_operand_count; ++i) {
CHECK_EQ(last_written().operand(i), operands[i]);
}
CHECK_EQ(last_written().operand_scale(),
std::max(first.operand_scale(), second.operand_scale()));
optimizer()->Write(&third);
CHECK_EQ(write_count(), 2);
CHECK_EQ(last_written().bytecode(), Bytecode::kLdar);
CHECK_EQ(last_written().operand(0), operands[expected_operand_count - 1]);
optimizer()->FlushBasicBlock();
CHECK_EQ(last_written().bytecode(), third.bytecode());
}
TEST_F(BytecodePeepholeOptimizerTest, MergeLdaUndefinedStar) {
const uint32_t operands[] = {
static_cast<uint32_t>(Register(100000).ToOperand())};
const int expected_operand_count = static_cast<int>(arraysize(operands));
BytecodeNode first(Bytecode::kLdaUndefined);
BytecodeNode second(Bytecode::kStar, operands[0], OperandScale::kQuadruple);
BytecodeNode third(Bytecode::kReturn);
optimizer()->Write(&first);
optimizer()->Write(&second);
CHECK_EQ(write_count(), 1);
CHECK_EQ(last_written().bytecode(), Bytecode::kLdrUndefined);
CHECK_EQ(last_written().operand_count(), expected_operand_count);
for (int i = 0; i < expected_operand_count; ++i) {
CHECK_EQ(last_written().operand(i), operands[i]);
}
CHECK_EQ(last_written().operand_scale(),
std::max(first.operand_scale(), second.operand_scale()));
optimizer()->Write(&third);
CHECK_EQ(write_count(), 2);
CHECK_EQ(last_written().bytecode(), Bytecode::kLdar);
CHECK_EQ(last_written().operand(0), operands[expected_operand_count - 1]);
optimizer()->FlushBasicBlock();
CHECK_EQ(last_written().bytecode(), third.bytecode());
}
} // namespace interpreter
} // namespace internal
} // 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