Commit e4c67d3f authored by klaasb's avatar klaasb Committed by Commit bot

[interpreter] Use VisitForTest for loop conditions

Changes the control flow builder classes to make use of the
BytecodeLabels helper class.

BUG=v8:4280
LOG=n

Review-Url: https://codereview.chromium.org/2254493002
Cr-Commit-Position: refs/heads/master@{#38744}
parent a3057266
......@@ -18,11 +18,14 @@ BytecodeLoopAnalysis::BytecodeLoopAnalysis(
: bytecode_array_(bytecode_array),
branch_analysis_(branch_analysis),
zone_(zone),
current_loop_offset_(-1),
found_current_backedge_(false),
backedge_to_header_(zone),
loop_header_to_parent_(zone) {}
void BytecodeLoopAnalysis::Analyze() {
current_loop_offset_ = -1;
found_current_backedge_ = false;
interpreter::BytecodeArrayIterator iterator(bytecode_array());
while (!iterator.done()) {
interpreter::Bytecode bytecode = iterator.current_bytecode();
......@@ -37,18 +40,36 @@ void BytecodeLoopAnalysis::Analyze() {
}
void BytecodeLoopAnalysis::AddLoopEntry(int entry_offset) {
if (found_current_backedge_) {
// We assume that all backedges of a loop must occur together and before
// another loop entry or an outer loop backedge.
// This is guaranteed by the invariants from AddBranch, such that every
// backedge must either go to the current loop or be the first of the
// backedges to the parent loop.
// Thus here, the current loop actually ended before and we have a loop
// with the same parent.
current_loop_offset_ = loop_header_to_parent_[current_loop_offset_];
found_current_backedge_ = false;
}
loop_header_to_parent_[entry_offset] = current_loop_offset_;
current_loop_offset_ = entry_offset;
}
void BytecodeLoopAnalysis::AddBranch(int origin_offset, int target_offset) {
// If this is a backedge, record it and update the current loop to the parent.
// If this is a backedge, record it.
if (target_offset < origin_offset) {
backedge_to_header_[origin_offset] = target_offset;
// Check that we are finishing the current loop. This assumes that
// there is one backedge for each loop.
DCHECK_EQ(target_offset, current_loop_offset_);
current_loop_offset_ = loop_header_to_parent_[target_offset];
// Check whether this is actually a backedge of the outer loop and we have
// already finished the current loop.
if (target_offset < current_loop_offset_) {
DCHECK(found_current_backedge_);
int parent_offset = loop_header_to_parent_[current_loop_offset_];
DCHECK_EQ(target_offset, parent_offset);
current_loop_offset_ = parent_offset;
} else {
DCHECK_EQ(target_offset, current_loop_offset_);
found_current_backedge_ = true;
}
}
}
......
......@@ -47,10 +47,10 @@ class BytecodeLoopAnalysis BASE_EMBEDDED {
Zone* zone_;
int current_loop_offset_;
bool found_current_backedge_;
// Map from the offset of a backedge jump to the offset of the corresponding
// loop header. Since we assume exactly one backedge per loop, the map will
// have as many entries as there are loops.
// loop header. There might be multiple backedges for do-while loops.
ZoneMap<int, int> backedge_to_header_;
// Map from the offset of a loop header to the offset of its parent's loop
// header. This map will have as many entries as there are loops in the
......
......@@ -1119,7 +1119,6 @@ void BytecodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
Register tag = VisitForRegisterValue(stmt->tag());
// Iterate over all cases and create nodes for label comparison.
BytecodeLabel done_label;
for (int i = 0; i < clauses->length(); i++) {
CaseClause* clause = clauses->at(i);
......@@ -1140,8 +1139,8 @@ void BytecodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
switch_builder.DefaultAt(default_index);
} else {
// Otherwise if we have reached here none of the cases matched, so jump to
// done.
builder()->Jump(&done_label);
// the end.
switch_builder.Break();
}
// Iterate over all cases and create the case bodies.
......@@ -1150,9 +1149,7 @@ void BytecodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
switch_builder.SetCaseTarget(i);
VisitStatements(clause->statements());
}
builder()->Bind(&done_label);
switch_builder.SetBreakTarget(done_label);
switch_builder.BindBreakTarget();
}
void BytecodeGenerator::VisitCaseClause(CaseClause* clause) {
......@@ -1165,7 +1162,7 @@ void BytecodeGenerator::VisitIterationBody(IterationStatement* stmt,
ControlScopeForIteration execution_control(this, stmt, loop_builder);
builder()->StackCheck(stmt->position());
Visit(stmt->body());
loop_builder->SetContinueTarget();
loop_builder->BindContinueTarget();
}
void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
......@@ -1180,9 +1177,8 @@ void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
VisitIterationHeader(stmt, &loop_builder);
VisitIterationBody(stmt, &loop_builder);
builder()->SetExpressionAsStatementPosition(stmt->cond());
// TODO(klaasb) VisitForTest for loop conditions
VisitForAccumulatorValue(stmt->cond());
loop_builder.JumpToHeaderIfTrue();
VisitForTest(stmt->cond(), loop_builder.header_labels(),
loop_builder.break_labels(), TestFallthrough::kElse);
}
loop_builder.EndLoop();
}
......@@ -1197,9 +1193,10 @@ void BytecodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
VisitIterationHeader(stmt, &loop_builder);
if (!stmt->cond()->ToBooleanIsTrue()) {
builder()->SetExpressionAsStatementPosition(stmt->cond());
// TODO(klaasb) VisitForTest for loop conditions
VisitForAccumulatorValue(stmt->cond());
loop_builder.BreakIfFalse();
BytecodeLabels loop_body(zone());
VisitForTest(stmt->cond(), &loop_body, loop_builder.break_labels(),
TestFallthrough::kThen);
loop_body.Bind(builder());
}
VisitIterationBody(stmt, &loop_builder);
loop_builder.JumpToHeader();
......@@ -1220,9 +1217,10 @@ void BytecodeGenerator::VisitForStatement(ForStatement* stmt) {
VisitIterationHeader(stmt, &loop_builder);
if (stmt->cond() && !stmt->cond()->ToBooleanIsTrue()) {
builder()->SetExpressionAsStatementPosition(stmt->cond());
// TODO(klaasb) VisitForTest for loop conditions
VisitForAccumulatorValue(stmt->cond());
loop_builder.BreakIfFalse();
BytecodeLabels loop_body(zone());
VisitForTest(stmt->cond(), &loop_body, loop_builder.break_labels(),
TestFallthrough::kThen);
loop_body.Bind(builder());
}
VisitIterationBody(stmt, &loop_builder);
if (stmt->next() != nullptr) {
......
......@@ -11,16 +11,24 @@ namespace internal {
namespace interpreter {
BytecodeLabel* BytecodeLabels::New() {
DCHECK(!is_bound());
labels_.push_back(BytecodeLabel());
return &labels_.back();
}
void BytecodeLabels::Bind(BytecodeArrayBuilder* builder) {
for (auto label : labels_) {
for (auto& label : labels_) {
builder->Bind(&label);
}
}
void BytecodeLabels::BindToLabel(BytecodeArrayBuilder* builder,
const BytecodeLabel& target) {
for (auto& label : labels_) {
builder->Bind(target, &label);
}
}
} // namespace interpreter
} // namespace internal
} // namespace v8
......@@ -62,6 +62,18 @@ class BytecodeLabels {
void Bind(BytecodeArrayBuilder* builder);
void BindToLabel(BytecodeArrayBuilder* builder, const BytecodeLabel& target);
bool is_bound() const {
bool is_bound = !labels_.empty() && labels_.at(0).is_bound();
DCHECK(!is_bound ||
std::all_of(labels_.begin(), labels_.end(),
[](const BytecodeLabel& l) { return l.is_bound(); }));
return is_bound;
}
bool empty() const { return labels_.empty(); }
private:
ZoneVector<BytecodeLabel> labels_;
......
......@@ -10,95 +10,53 @@ namespace interpreter {
BreakableControlFlowBuilder::~BreakableControlFlowBuilder() {
DCHECK(break_sites_.empty());
DCHECK(break_labels_.empty() || break_labels_.is_bound());
}
void BreakableControlFlowBuilder::SetBreakTarget(const BytecodeLabel& target) {
BindLabels(target, &break_sites_);
}
void BreakableControlFlowBuilder::EmitJump(ZoneVector<BytecodeLabel>* sites) {
sites->push_back(BytecodeLabel());
builder()->Jump(&sites->back());
}
void BreakableControlFlowBuilder::EmitJumpIfTrue(
ZoneVector<BytecodeLabel>* sites) {
sites->push_back(BytecodeLabel());
builder()->JumpIfTrue(&sites->back());
void BreakableControlFlowBuilder::BindBreakTarget() {
break_labels_.Bind(builder());
}
void BreakableControlFlowBuilder::EmitJumpIfFalse(
ZoneVector<BytecodeLabel>* sites) {
sites->push_back(BytecodeLabel());
builder()->JumpIfFalse(&sites->back());
}
void BreakableControlFlowBuilder::EmitJumpIfUndefined(
ZoneVector<BytecodeLabel>* sites) {
sites->push_back(BytecodeLabel());
builder()->JumpIfUndefined(&sites->back());
}
void BreakableControlFlowBuilder::EmitJumpIfNull(
ZoneVector<BytecodeLabel>* sites) {
sites->push_back(BytecodeLabel());
builder()->JumpIfNull(&sites->back());
void BreakableControlFlowBuilder::EmitJump(BytecodeLabels* sites) {
builder()->Jump(sites->New());
}
void BreakableControlFlowBuilder::EmitJump(ZoneVector<BytecodeLabel>* sites,
int index) {
builder()->Jump(&sites->at(index));
void BreakableControlFlowBuilder::EmitJumpIfTrue(BytecodeLabels* sites) {
builder()->JumpIfTrue(sites->New());
}
void BreakableControlFlowBuilder::EmitJumpIfTrue(
ZoneVector<BytecodeLabel>* sites, int index) {
builder()->JumpIfTrue(&sites->at(index));
void BreakableControlFlowBuilder::EmitJumpIfFalse(BytecodeLabels* sites) {
builder()->JumpIfFalse(sites->New());
}
void BreakableControlFlowBuilder::EmitJumpIfFalse(
ZoneVector<BytecodeLabel>* sites, int index) {
builder()->JumpIfFalse(&sites->at(index));
void BreakableControlFlowBuilder::EmitJumpIfUndefined(BytecodeLabels* sites) {
builder()->JumpIfUndefined(sites->New());
}
void BreakableControlFlowBuilder::BindLabels(const BytecodeLabel& target,
ZoneVector<BytecodeLabel>* sites) {
for (size_t i = 0; i < sites->size(); i++) {
BytecodeLabel& site = sites->at(i);
builder()->Bind(target, &site);
}
sites->clear();
void BreakableControlFlowBuilder::EmitJumpIfNull(BytecodeLabels* sites) {
builder()->JumpIfNull(sites->New());
}
void BlockBuilder::EndBlock() {
builder()->Bind(&block_end_);
SetBreakTarget(block_end_);
BindBreakTarget();
}
LoopBuilder::~LoopBuilder() { DCHECK(continue_sites_.empty()); }
LoopBuilder::~LoopBuilder() {
DCHECK(continue_labels_.empty() || continue_labels_.is_bound());
DCHECK(header_labels_.empty() || header_labels_.is_bound());
}
void LoopBuilder::LoopHeader(ZoneVector<BytecodeLabel>* additional_labels) {
// Jumps from before the loop header into the loop violate ordering
// requirements of bytecode basic blocks. The only entry into a loop
// must be the loop header. Surely breaks is okay? Not if nested
// and misplaced between the headers.
DCHECK(break_sites_.empty() && continue_sites_.empty());
DCHECK(break_labels_.empty() && continue_labels_.empty());
builder()->Bind(&loop_header_);
for (auto& label : *additional_labels) {
builder()->Bind(loop_header_, &label);
builder()->Bind(&label);
}
}
......@@ -117,16 +75,11 @@ void LoopBuilder::JumpToHeaderIfTrue() {
}
void LoopBuilder::EndLoop() {
builder()->Bind(&loop_end_);
SetBreakTarget(loop_end_);
}
void LoopBuilder::SetContinueTarget() {
BytecodeLabel target;
builder()->Bind(&target);
BindLabels(target, &continue_sites_);
BindBreakTarget();
header_labels_.BindToLabel(builder(), loop_header_);
}
void LoopBuilder::BindContinueTarget() { continue_labels_.Bind(builder()); }
SwitchBuilder::~SwitchBuilder() {
#ifdef DEBUG
......@@ -165,8 +118,7 @@ void TryFinallyBuilder::BeginTry(Register context) {
void TryFinallyBuilder::LeaveTry() {
finalization_sites_.push_back(BytecodeLabel());
builder()->Jump(&finalization_sites_.back());
builder()->Jump(finalization_sites_.New());
}
......@@ -180,14 +132,7 @@ void TryFinallyBuilder::BeginHandler() {
builder()->MarkHandler(handler_id_, catch_prediction_);
}
void TryFinallyBuilder::BeginFinally() {
for (size_t i = 0; i < finalization_sites_.size(); i++) {
BytecodeLabel& site = finalization_sites_.at(i);
builder()->Bind(&site);
}
}
void TryFinallyBuilder::BeginFinally() { finalization_sites_.Bind(builder()); }
void TryFinallyBuilder::EndFinally() {
// Nothing to be done here.
......
......@@ -32,37 +32,33 @@ class ControlFlowBuilder BASE_EMBEDDED {
class BreakableControlFlowBuilder : public ControlFlowBuilder {
public:
explicit BreakableControlFlowBuilder(BytecodeArrayBuilder* builder)
: ControlFlowBuilder(builder),
break_sites_(builder->zone()) {}
: ControlFlowBuilder(builder), break_labels_(builder->zone()) {}
virtual ~BreakableControlFlowBuilder();
// This method should be called by the control flow owner before
// destruction to update sites that emit jumps for break.
void SetBreakTarget(const BytecodeLabel& break_target);
void BindBreakTarget();
// This method is called when visiting break statements in the AST.
// Inserts a jump to a unbound label that is patched when the corresponding
// SetBreakTarget is called.
void Break() { EmitJump(&break_sites_); }
void BreakIfTrue() { EmitJumpIfTrue(&break_sites_); }
void BreakIfFalse() { EmitJumpIfFalse(&break_sites_); }
void BreakIfUndefined() { EmitJumpIfUndefined(&break_sites_); }
void BreakIfNull() { EmitJumpIfNull(&break_sites_); }
// Inserts a jump to an unbound label that is patched when the corresponding
// BindBreakTarget is called.
void Break() { EmitJump(&break_labels_); }
void BreakIfTrue() { EmitJumpIfTrue(&break_labels_); }
void BreakIfFalse() { EmitJumpIfFalse(&break_labels_); }
void BreakIfUndefined() { EmitJumpIfUndefined(&break_labels_); }
void BreakIfNull() { EmitJumpIfNull(&break_labels_); }
protected:
void EmitJump(ZoneVector<BytecodeLabel>* labels);
void EmitJump(ZoneVector<BytecodeLabel>* labels, int index);
void EmitJumpIfTrue(ZoneVector<BytecodeLabel>* labels);
void EmitJumpIfTrue(ZoneVector<BytecodeLabel>* labels, int index);
void EmitJumpIfFalse(ZoneVector<BytecodeLabel>* labels);
void EmitJumpIfFalse(ZoneVector<BytecodeLabel>* labels, int index);
void EmitJumpIfUndefined(ZoneVector<BytecodeLabel>* labels);
void EmitJumpIfNull(ZoneVector<BytecodeLabel>* labels);
BytecodeLabels* break_labels() { return &break_labels_; }
void BindLabels(const BytecodeLabel& target, ZoneVector<BytecodeLabel>* site);
protected:
void EmitJump(BytecodeLabels* labels);
void EmitJumpIfTrue(BytecodeLabels* labels);
void EmitJumpIfFalse(BytecodeLabels* labels);
void EmitJumpIfUndefined(BytecodeLabels* labels);
void EmitJumpIfNull(BytecodeLabels* labels);
// Unbound labels that identify jumps for break statements in the code.
ZoneVector<BytecodeLabel> break_sites_;
BytecodeLabels break_labels_;
};
......@@ -85,29 +81,34 @@ class LoopBuilder final : public BreakableControlFlowBuilder {
public:
explicit LoopBuilder(BytecodeArrayBuilder* builder)
: BreakableControlFlowBuilder(builder),
continue_sites_(builder->zone()) {}
continue_labels_(builder->zone()),
header_labels_(builder->zone()) {}
~LoopBuilder();
void LoopHeader(ZoneVector<BytecodeLabel>* additional_labels);
void JumpToHeader();
void JumpToHeaderIfTrue();
void SetContinueTarget();
void BindContinueTarget();
void EndLoop();
// This method is called when visiting continue statements in the AST.
// Inserts a jump to an unbound label that is patched when SetContinueTarget
// Inserts a jump to an unbound label that is patched when BindContinueTarget
// is called.
void Continue() { EmitJump(&continue_sites_); }
void ContinueIfTrue() { EmitJumpIfTrue(&continue_sites_); }
void ContinueIfUndefined() { EmitJumpIfUndefined(&continue_sites_); }
void ContinueIfNull() { EmitJumpIfNull(&continue_sites_); }
void Continue() { EmitJump(&continue_labels_); }
void ContinueIfTrue() { EmitJumpIfTrue(&continue_labels_); }
void ContinueIfUndefined() { EmitJumpIfUndefined(&continue_labels_); }
void ContinueIfNull() { EmitJumpIfNull(&continue_labels_); }
BytecodeLabels* header_labels() { return &header_labels_; }
BytecodeLabels* continue_labels() { return &continue_labels_; }
private:
BytecodeLabel loop_header_;
BytecodeLabel loop_end_;
// Unbound labels that identify jumps for continue statements in the code.
ZoneVector<BytecodeLabel> continue_sites_;
// Unbound labels that identify jumps for continue statements in the code and
// jumps from checking the loop condition to the header for do-while loops.
BytecodeLabels continue_labels_;
BytecodeLabels header_labels_;
};
......@@ -128,12 +129,12 @@ class SwitchBuilder final : public BreakableControlFlowBuilder {
// This method is called when visiting case comparison operation for |index|.
// Inserts a JumpIfTrue to a unbound label that is patched when the
// corresponding SetCaseTarget is called.
void Case(int index) { EmitJumpIfTrue(&case_sites_, index); }
void Case(int index) { builder()->JumpIfTrue(&case_sites_.at(index)); }
// This method is called when all cases comparisons have been emitted if there
// is a default case statement. Inserts a Jump to a unbound label that is
// patched when the corresponding SetCaseTarget is called.
void DefaultAt(int index) { EmitJump(&case_sites_, index); }
void DefaultAt(int index) { builder()->Jump(&case_sites_.at(index)); }
private:
// Unbound labels that identify jumps for case statements in the code.
......@@ -185,7 +186,7 @@ class TryFinallyBuilder final : public ControlFlowBuilder {
BytecodeLabel handler_;
// Unbound labels that identify jumps to the finally block in the code.
ZoneVector<BytecodeLabel> finalization_sites_;
BytecodeLabels finalization_sites_;
};
} // namespace interpreter
......
......@@ -2332,7 +2332,19 @@ TEST(BytecodeGraphBuilderDo) {
" if (x == 4) break;\n"
"} while (x < 7);\n"
"return y;",
{factory->NewNumberFromInt(16)}}};
{factory->NewNumberFromInt(16)}},
{"var x = 0, sum = 0;\n"
"do {\n"
" do {\n"
" ++sum;\n"
" ++x;\n"
" } while (sum < 1 || x < 2)\n"
" do {\n"
" ++x;\n"
" } while (x < 1)\n"
"} while (sum < 3)\n"
"return sum;",
{factory->NewNumber(3)}}};
for (size_t i = 0; i < arraysize(snippets); i++) {
ScopedVector<char> script(1024);
......@@ -2413,6 +2425,19 @@ TEST(BytecodeGraphBuilderFor) {
"}\n"
"return sum;",
{factory->NewNumberFromInt(385)}},
{"var sum = 0;\n"
"for (var x = 0; x < 5; x++) {\n"
" for (var y = 0; y < 5; y++) {\n"
" ++sum;\n"
" }\n"
"}\n"
"for (var x = 0; x < 5; x++) {\n"
" for (var y = 0; y < 5; y++) {\n"
" ++sum;\n"
" }\n"
"}\n"
"return sum;",
{factory->NewNumberFromInt(50)}},
};
for (size_t i = 0; i < arraysize(snippets); i++) {
......
......@@ -165,7 +165,7 @@ snippet: "
"
frame size: 1
parameter count: 1
bytecode array length: 39
bytecode array length: 37
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaZero),
......@@ -184,8 +184,7 @@ bytecodes: [
B(Jump), U8(-20),
/* 122 S> */ B(AddSmi), U8(1), R(0),
B(Star), R(0),
/* 135 S> */ B(Jump), U8(4),
B(Jump), U8(-30),
/* 135 S> */ B(Jump), U8(2),
/* 144 S> */ B(Ldar), R(0),
/* 154 S> */ B(Return),
]
......@@ -287,7 +286,7 @@ snippet: "
"
frame size: 2
parameter count: 1
bytecode array length: 29
bytecode array length: 27
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaSmi), U8(10),
......@@ -300,8 +299,7 @@ bytecodes: [
B(Star), R(1),
/* 78 S> */ B(SubSmi), U8(1), R(0),
B(Star), R(0),
/* 98 S> */ B(Ldar), R(0),
B(JumpIfToBooleanTrue), U8(-15),
/* 98 S> */ B(JumpIfToBooleanTrue), U8(-13),
/* 102 S> */ B(Ldar), R(1),
/* 112 S> */ B(Return),
]
......
......@@ -54,7 +54,7 @@ snippet: "
"
frame size: 2
parameter count: 1
bytecode array length: 18
bytecode array length: 16
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 34 E> */ B(StackCheck),
......@@ -63,8 +63,7 @@ bytecodes: [
/* 69 S> */ B(Inc), U8(1),
B(Star), R(1),
B(Star), R(0),
/* 74 S> */ B(Jump), U8(4),
B(Jump), U8(-13),
/* 74 S> */ B(Jump), U8(2),
B(LdaUndefined),
/* 94 S> */ B(Return),
]
......
......@@ -149,7 +149,7 @@ snippet: "
"
frame size: 16
parameter count: 1
bytecode array length: 281
bytecode array length: 279
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaConstant), U8(0),
......@@ -170,7 +170,7 @@ bytecodes: [
B(JumpIfFalse), U8(7),
B(CallRuntime), U16(Runtime::kThrowIteratorResultNotAnObject), R(2), U8(1),
B(LdaNamedProperty), R(2), U8(3), U8(9),
B(JumpIfToBooleanTrue), U8(28),
B(JumpIfToBooleanTrue), U8(26),
B(LdrNamedProperty), R(2), U8(4), U8(11), R(4),
B(LdaSmi), U8(2),
B(Star), R(3),
......@@ -180,8 +180,7 @@ bytecodes: [
/* 73 S> */ B(LdaZero),
B(Star), R(10),
B(Mov), R(0), R(11),
B(Jump), U8(50),
B(Jump), U8(-54),
B(Jump), U8(48),
B(Jump), U8(34),
B(Star), R(14),
B(Ldar), R(closure),
......@@ -280,9 +279,9 @@ constant pool: [
InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
]
handlers: [
[11, 117, 123],
[14, 83, 85],
[196, 206, 208],
[11, 115, 121],
[14, 81, 83],
[194, 204, 206],
]
---
......@@ -438,7 +437,7 @@ snippet: "
"
frame size: 14
parameter count: 1
bytecode array length: 294
bytecode array length: 292
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(CreateObjectLiteral), U8(0), U8(0), U8(1), R(8),
......@@ -461,7 +460,7 @@ bytecodes: [
B(JumpIfFalse), U8(7),
B(CallRuntime), U16(Runtime::kThrowIteratorResultNotAnObject), R(1), U8(1),
B(LdaNamedProperty), R(1), U8(4), U8(9),
B(JumpIfToBooleanTrue), U8(31),
B(JumpIfToBooleanTrue), U8(29),
/* 67 E> */ B(LdrNamedProperty), R(1), U8(5), U8(11), R(3),
B(LdaSmi), U8(2),
B(Star), R(2),
......@@ -472,8 +471,7 @@ bytecodes: [
/* 96 E> */ B(LdrNamedProperty), R(6), U8(6), U8(15), R(9),
B(LdaZero),
B(Star), R(8),
B(Jump), U8(50),
B(Jump), U8(-57),
B(Jump), U8(48),
B(Jump), U8(34),
B(Star), R(12),
B(Ldar), R(closure),
......@@ -574,8 +572,8 @@ constant pool: [
InstanceType::ONE_BYTE_INTERNALIZED_STRING_TYPE,
]
handlers: [
[15, 130, 136],
[18, 96, 98],
[209, 219, 221],
[15, 128, 134],
[18, 94, 96],
[207, 217, 219],
]
......@@ -17,19 +17,18 @@ snippet: "
"
frame size: 1
parameter count: 1
bytecode array length: 22
bytecode array length: 21
bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaZero),
B(Star), R(0),
/* 54 S> */ B(LdaSmi), U8(10),
/* 54 E> */ B(TestEqual), R(0),
B(LogicalNot),
B(JumpIfFalse), U8(10),
B(JumpIfTrue), U8(10),
/* 45 E> */ B(StackCheck),
/* 65 S> */ B(AddSmi), U8(10), R(0),
B(Star), R(0),
B(Jump), U8(-13),
B(Jump), U8(-12),
/* 79 S> */ B(Ldar), R(0),
/* 89 S> */ B(Return),
]
......
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