Commit 35269f77 authored by Leszek Swirski's avatar Leszek Swirski Committed by Commit Bot

[ignition] Skip binding dead labels

BytecodeLabels for forward jumps may create a dead basic block if their
corresponding jump was elided (due to it dead code elimination). We can
avoid generating such dead basic blocks by skipping the label bind when
no corresponding jump has been observed. This works because all jumps
except JumpLoop are forward jumps, so we only have to special case one
Bind for loop headers to bind unconditionally.

Since Binds are now conditional on a jump existing, we can no longer rely
on using Bind to get the current offset (e.g. at the beginning of a try
block). Instead, we now expose the current offset in the bytecode array
writer. Conveniently, this means that we can be a bit smarter about basic
blocks around these statements.

As a drive-by, remove the unused Bind(target,label) function.

Bug: chromium:934166
Change-Id: I532aa452fb083560d07b90da99caca0b1d082aa3
Reviewed-on: https://chromium-review.googlesource.com/c/1488763
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Reviewed-by: 's avatarRoss McIlroy <rmcilroy@chromium.org>
Cr-Commit-Position: refs/heads/master@{#59942}
parent 3f057d44
...@@ -146,6 +146,12 @@ void BytecodeArrayBuilder::WriteJump(BytecodeNode* node, BytecodeLabel* label) { ...@@ -146,6 +146,12 @@ void BytecodeArrayBuilder::WriteJump(BytecodeNode* node, BytecodeLabel* label) {
bytecode_array_writer_.WriteJump(node, label); bytecode_array_writer_.WriteJump(node, label);
} }
void BytecodeArrayBuilder::WriteJumpLoop(BytecodeNode* node,
BytecodeLoopHeader* loop_header) {
AttachOrEmitDeferredSourceInfo(node);
bytecode_array_writer_.WriteJumpLoop(node, loop_header);
}
void BytecodeArrayBuilder::WriteSwitch(BytecodeNode* node, void BytecodeArrayBuilder::WriteSwitch(BytecodeNode* node,
BytecodeJumpTable* jump_table) { BytecodeJumpTable* jump_table) {
AttachOrEmitDeferredSourceInfo(node); AttachOrEmitDeferredSourceInfo(node);
...@@ -330,7 +336,7 @@ class BytecodeNodeBuilder { ...@@ -330,7 +336,7 @@ class BytecodeNodeBuilder {
template <typename... Operands> \ template <typename... Operands> \
void BytecodeArrayBuilder::Output##name(BytecodeLabel* label, \ void BytecodeArrayBuilder::Output##name(BytecodeLabel* label, \
Operands... operands) { \ Operands... operands) { \
DCHECK(Bytecodes::IsJump(Bytecode::k##name)); \ DCHECK(Bytecodes::IsForwardJump(Bytecode::k##name)); \
BytecodeNode node(Create##name##Node(operands...)); \ BytecodeNode node(Create##name##Node(operands...)); \
WriteJump(&node, label); \ WriteJump(&node, label); \
LeaveBasicBlock(); \ LeaveBasicBlock(); \
...@@ -338,6 +344,12 @@ class BytecodeNodeBuilder { ...@@ -338,6 +344,12 @@ class BytecodeNodeBuilder {
BYTECODE_LIST(DEFINE_BYTECODE_OUTPUT) BYTECODE_LIST(DEFINE_BYTECODE_OUTPUT)
#undef DEFINE_BYTECODE_OUTPUT #undef DEFINE_BYTECODE_OUTPUT
void BytecodeArrayBuilder::OutputJumpLoop(BytecodeLoopHeader* loop_header,
int loop_depth) {
BytecodeNode node(CreateJumpLoopNode(0, loop_depth));
WriteJumpLoop(&node, loop_header);
}
void BytecodeArrayBuilder::OutputSwitchOnSmiNoFeedback( void BytecodeArrayBuilder::OutputSwitchOnSmiNoFeedback(
BytecodeJumpTable* jump_table) { BytecodeJumpTable* jump_table) {
BytecodeNode node(CreateSwitchOnSmiNoFeedbackNode( BytecodeNode node(CreateSwitchOnSmiNoFeedbackNode(
...@@ -1053,6 +1065,10 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::ToNumeric(int feedback_slot) { ...@@ -1053,6 +1065,10 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::ToNumeric(int feedback_slot) {
} }
BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(BytecodeLabel* label) { BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(BytecodeLabel* label) {
// Don't generate code for a label which hasn't had a corresponding forward
// jump generated already. For backwards jumps, use BindLoopHeader.
if (!label->has_referrer_jump()) return *this;
// Flush the register optimizer when binding a label to ensure all // Flush the register optimizer when binding a label to ensure all
// expected registers are valid when jumping to this label. // expected registers are valid when jumping to this label.
if (register_optimizer_) register_optimizer_->Flush(); if (register_optimizer_) register_optimizer_->Flush();
...@@ -1061,9 +1077,12 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(BytecodeLabel* label) { ...@@ -1061,9 +1077,12 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(BytecodeLabel* label) {
return *this; return *this;
} }
BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(const BytecodeLabel& target, BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(
BytecodeLabel* label) { BytecodeLoopHeader* loop_header) {
bytecode_array_writer_.BindLabel(target, label); // Flush the register optimizer when starting a loop to ensure all expected
// registers are valid when jumping to the loop header.
if (register_optimizer_) register_optimizer_->Flush();
bytecode_array_writer_.BindLoopHeader(loop_header);
LeaveBasicBlock(); LeaveBasicBlock();
return *this; return *this;
} }
...@@ -1078,6 +1097,33 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(BytecodeJumpTable* jump_table, ...@@ -1078,6 +1097,33 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(BytecodeJumpTable* jump_table,
return *this; return *this;
} }
BytecodeArrayBuilder& BytecodeArrayBuilder::MarkHandler(
int handler_id, HandlerTable::CatchPrediction catch_prediction) {
// The handler starts a new basic block, and any reasonable try block won't
// let control fall through into it.
DCHECK_IMPLIES(register_optimizer_,
register_optimizer_->EnsureAllRegistersAreFlushed());
bytecode_array_writer_.BindHandlerTarget(handler_table_builder(), handler_id);
handler_table_builder()->SetPrediction(handler_id, catch_prediction);
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::MarkTryBegin(int handler_id,
Register context) {
// Flush registers to make sure everything visible to the handler is
// materialized.
if (register_optimizer_) register_optimizer_->Flush();
bytecode_array_writer_.BindTryRegionStart(handler_table_builder(),
handler_id);
handler_table_builder()->SetContextRegister(handler_id, context);
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::MarkTryEnd(int handler_id) {
bytecode_array_writer_.BindTryRegionEnd(handler_table_builder(), handler_id);
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::Jump(BytecodeLabel* label) { BytecodeArrayBuilder& BytecodeArrayBuilder::Jump(BytecodeLabel* label) {
DCHECK(!label->is_bound()); DCHECK(!label->is_bound());
OutputJump(label, 0); OutputJump(label, 0);
...@@ -1178,10 +1224,9 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfJSReceiver( ...@@ -1178,10 +1224,9 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfJSReceiver(
return *this; return *this;
} }
BytecodeArrayBuilder& BytecodeArrayBuilder::JumpLoop(BytecodeLabel* label, BytecodeArrayBuilder& BytecodeArrayBuilder::JumpLoop(
int loop_depth) { BytecodeLoopHeader* loop_header, int loop_depth) {
DCHECK(label->is_bound()); OutputJumpLoop(loop_header, loop_depth);
OutputJumpLoop(label, 0, loop_depth);
return *this; return *this;
} }
...@@ -1321,7 +1366,6 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::SwitchOnGeneratorState( ...@@ -1321,7 +1366,6 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::SwitchOnGeneratorState(
BytecodeNode node(CreateSwitchOnGeneratorStateNode( BytecodeNode node(CreateSwitchOnGeneratorStateNode(
generator, jump_table->constant_pool_index(), jump_table->size())); generator, jump_table->constant_pool_index(), jump_table->size()));
WriteSwitch(&node, jump_table); WriteSwitch(&node, jump_table);
LeaveBasicBlock();
return *this; return *this;
} }
...@@ -1331,33 +1375,6 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::ResumeGenerator( ...@@ -1331,33 +1375,6 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::ResumeGenerator(
return *this; return *this;
} }
BytecodeArrayBuilder& BytecodeArrayBuilder::MarkHandler(
int handler_id, HandlerTable::CatchPrediction catch_prediction) {
BytecodeLabel handler;
Bind(&handler);
handler_table_builder()->SetHandlerTarget(handler_id, handler.offset());
handler_table_builder()->SetPrediction(handler_id, catch_prediction);
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::MarkTryBegin(int handler_id,
Register context) {
// TODO(leszeks): Do we need to start a new basic block here? Could we simply
// get the current bytecode offset from the array writer instead?
BytecodeLabel try_begin;
Bind(&try_begin);
handler_table_builder()->SetTryRegionStart(handler_id, try_begin.offset());
handler_table_builder()->SetContextRegister(handler_id, context);
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::MarkTryEnd(int handler_id) {
BytecodeLabel try_end;
Bind(&try_end);
handler_table_builder()->SetTryRegionEnd(handler_id, try_end.offset());
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::CallProperty(Register callable, BytecodeArrayBuilder& BytecodeArrayBuilder::CallProperty(Register callable,
RegisterList args, RegisterList args,
int feedback_slot) { int feedback_slot) {
......
...@@ -27,6 +27,7 @@ class Isolate; ...@@ -27,6 +27,7 @@ class Isolate;
namespace interpreter { namespace interpreter {
class BytecodeLabel; class BytecodeLabel;
class BytecodeLoopHeader;
class BytecodeNode; class BytecodeNode;
class BytecodeRegisterOptimizer; class BytecodeRegisterOptimizer;
class BytecodeJumpTable; class BytecodeJumpTable;
...@@ -397,13 +398,20 @@ class V8_EXPORT_PRIVATE BytecodeArrayBuilder final { ...@@ -397,13 +398,20 @@ class V8_EXPORT_PRIVATE BytecodeArrayBuilder final {
BytecodeArrayBuilder& ToNumber(int feedback_slot); BytecodeArrayBuilder& ToNumber(int feedback_slot);
BytecodeArrayBuilder& ToNumeric(int feedback_slot); BytecodeArrayBuilder& ToNumeric(int feedback_slot);
// Exception handling.
BytecodeArrayBuilder& MarkHandler(int handler_id,
HandlerTable::CatchPrediction will_catch);
BytecodeArrayBuilder& MarkTryBegin(int handler_id, Register context);
BytecodeArrayBuilder& MarkTryEnd(int handler_id);
// Flow Control. // Flow Control.
BytecodeArrayBuilder& Bind(BytecodeLabel* label); BytecodeArrayBuilder& Bind(BytecodeLabel* label);
BytecodeArrayBuilder& Bind(const BytecodeLabel& target, BytecodeLabel* label); BytecodeArrayBuilder& Bind(BytecodeLoopHeader* label);
BytecodeArrayBuilder& Bind(BytecodeJumpTable* jump_table, int case_value); BytecodeArrayBuilder& Bind(BytecodeJumpTable* jump_table, int case_value);
BytecodeArrayBuilder& Jump(BytecodeLabel* label); BytecodeArrayBuilder& Jump(BytecodeLabel* label);
BytecodeArrayBuilder& JumpLoop(BytecodeLabel* label, int loop_depth); BytecodeArrayBuilder& JumpLoop(BytecodeLoopHeader* loop_header,
int loop_depth);
BytecodeArrayBuilder& JumpIfTrue(ToBooleanMode mode, BytecodeLabel* label); BytecodeArrayBuilder& JumpIfTrue(ToBooleanMode mode, BytecodeLabel* label);
BytecodeArrayBuilder& JumpIfFalse(ToBooleanMode mode, BytecodeLabel* label); BytecodeArrayBuilder& JumpIfFalse(ToBooleanMode mode, BytecodeLabel* label);
...@@ -458,12 +466,6 @@ class V8_EXPORT_PRIVATE BytecodeArrayBuilder final { ...@@ -458,12 +466,6 @@ class V8_EXPORT_PRIVATE BytecodeArrayBuilder final {
BytecodeArrayBuilder& ResumeGenerator(Register generator, BytecodeArrayBuilder& ResumeGenerator(Register generator,
RegisterList registers); RegisterList registers);
// Exception handling.
BytecodeArrayBuilder& MarkHandler(int handler_id,
HandlerTable::CatchPrediction will_catch);
BytecodeArrayBuilder& MarkTryBegin(int handler_id, Register context);
BytecodeArrayBuilder& MarkTryEnd(int handler_id);
// Creates a new handler table entry and returns a {hander_id} identifying the // Creates a new handler table entry and returns a {hander_id} identifying the
// entry, so that it can be referenced by above exception handling support. // entry, so that it can be referenced by above exception handling support.
int NewHandlerEntry() { return handler_table_builder()->NewHandlerEntry(); } int NewHandlerEntry() { return handler_table_builder()->NewHandlerEntry(); }
...@@ -568,6 +570,8 @@ class V8_EXPORT_PRIVATE BytecodeArrayBuilder final { ...@@ -568,6 +570,8 @@ class V8_EXPORT_PRIVATE BytecodeArrayBuilder final {
BYTECODE_LIST(DECLARE_BYTECODE_OUTPUT) BYTECODE_LIST(DECLARE_BYTECODE_OUTPUT)
#undef DECLARE_OPERAND_TYPE_INFO #undef DECLARE_OPERAND_TYPE_INFO
V8_INLINE void OutputJumpLoop(BytecodeLoopHeader* loop_header,
int loop_depth);
V8_INLINE void OutputSwitchOnSmiNoFeedback(BytecodeJumpTable* jump_table); V8_INLINE void OutputSwitchOnSmiNoFeedback(BytecodeJumpTable* jump_table);
bool RegisterIsValid(Register reg) const; bool RegisterIsValid(Register reg) const;
...@@ -583,6 +587,7 @@ class V8_EXPORT_PRIVATE BytecodeArrayBuilder final { ...@@ -583,6 +587,7 @@ class V8_EXPORT_PRIVATE BytecodeArrayBuilder final {
// Write bytecode to bytecode array. // Write bytecode to bytecode array.
void Write(BytecodeNode* node); void Write(BytecodeNode* node);
void WriteJump(BytecodeNode* node, BytecodeLabel* label); void WriteJump(BytecodeNode* node, BytecodeLabel* label);
void WriteJumpLoop(BytecodeNode* node, BytecodeLoopHeader* loop_header);
void WriteSwitch(BytecodeNode* node, BytecodeJumpTable* label); void WriteSwitch(BytecodeNode* node, BytecodeJumpTable* label);
// Not implemented as the illegal bytecode is used inside internally // Not implemented as the illegal bytecode is used inside internally
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "src/interpreter/bytecode-register.h" #include "src/interpreter/bytecode-register.h"
#include "src/interpreter/bytecode-source-info.h" #include "src/interpreter/bytecode-source-info.h"
#include "src/interpreter/constant-array-builder.h" #include "src/interpreter/constant-array-builder.h"
#include "src/interpreter/handler-table-builder.h"
#include "src/log.h" #include "src/log.h"
#include "src/objects-inl.h" #include "src/objects-inl.h"
...@@ -74,10 +75,8 @@ void BytecodeArrayWriter::Write(BytecodeNode* node) { ...@@ -74,10 +75,8 @@ void BytecodeArrayWriter::Write(BytecodeNode* node) {
} }
void BytecodeArrayWriter::WriteJump(BytecodeNode* node, BytecodeLabel* label) { void BytecodeArrayWriter::WriteJump(BytecodeNode* node, BytecodeLabel* label) {
DCHECK(Bytecodes::IsJump(node->bytecode())); DCHECK(Bytecodes::IsForwardJump(node->bytecode()));
// TODO(rmcilroy): For forward jumps we could also mark the label as dead,
// thereby avoiding emitting dead code when we bind the label.
if (exit_seen_in_block_) return; // Don't emit dead code. if (exit_seen_in_block_) return; // Don't emit dead code.
UpdateExitSeenInBlock(node->bytecode()); UpdateExitSeenInBlock(node->bytecode());
MaybeElideLastBytecode(node->bytecode(), node->source_info().is_valid()); MaybeElideLastBytecode(node->bytecode(), node->source_info().is_valid());
...@@ -86,12 +85,22 @@ void BytecodeArrayWriter::WriteJump(BytecodeNode* node, BytecodeLabel* label) { ...@@ -86,12 +85,22 @@ void BytecodeArrayWriter::WriteJump(BytecodeNode* node, BytecodeLabel* label) {
EmitJump(node, label); EmitJump(node, label);
} }
void BytecodeArrayWriter::WriteJumpLoop(BytecodeNode* node,
BytecodeLoopHeader* loop_header) {
DCHECK_EQ(node->bytecode(), Bytecode::kJumpLoop);
if (exit_seen_in_block_) return; // Don't emit dead code.
UpdateExitSeenInBlock(node->bytecode());
MaybeElideLastBytecode(node->bytecode(), node->source_info().is_valid());
UpdateSourcePositionTable(node);
EmitJumpLoop(node, loop_header);
}
void BytecodeArrayWriter::WriteSwitch(BytecodeNode* node, void BytecodeArrayWriter::WriteSwitch(BytecodeNode* node,
BytecodeJumpTable* jump_table) { BytecodeJumpTable* jump_table) {
DCHECK(Bytecodes::IsSwitch(node->bytecode())); DCHECK(Bytecodes::IsSwitch(node->bytecode()));
// TODO(rmcilroy): For jump tables we could also mark the table as dead,
// thereby avoiding emitting dead code when we bind the entries.
if (exit_seen_in_block_) return; // Don't emit dead code. if (exit_seen_in_block_) return; // Don't emit dead code.
UpdateExitSeenInBlock(node->bytecode()); UpdateExitSeenInBlock(node->bytecode());
MaybeElideLastBytecode(node->bytecode(), node->source_info().is_valid()); MaybeElideLastBytecode(node->bytecode(), node->source_info().is_valid());
...@@ -101,30 +110,18 @@ void BytecodeArrayWriter::WriteSwitch(BytecodeNode* node, ...@@ -101,30 +110,18 @@ void BytecodeArrayWriter::WriteSwitch(BytecodeNode* node,
} }
void BytecodeArrayWriter::BindLabel(BytecodeLabel* label) { void BytecodeArrayWriter::BindLabel(BytecodeLabel* label) {
DCHECK(label->has_referrer_jump());
size_t current_offset = bytecodes()->size(); size_t current_offset = bytecodes()->size();
if (label->is_forward_target()) { // Update the jump instruction's location.
// An earlier jump instruction refers to this label. Update it's location. PatchJump(current_offset, label->jump_offset());
PatchJump(current_offset, label->offset()); label->bind();
// Now treat as if the label will only be back referred to. StartBasicBlock();
}
label->bind_to(current_offset);
InvalidateLastBytecode();
exit_seen_in_block_ = false; // Starting a new basic block.
} }
void BytecodeArrayWriter::BindLabel(const BytecodeLabel& target, void BytecodeArrayWriter::BindLoopHeader(BytecodeLoopHeader* loop_header) {
BytecodeLabel* label) { size_t current_offset = bytecodes()->size();
DCHECK(!label->is_bound()); loop_header->bind_to(current_offset);
DCHECK(target.is_bound()); StartBasicBlock();
if (label->is_forward_target()) {
// An earlier jump instruction refers to this label. Update it's location.
PatchJump(target.offset(), label->offset());
// Now treat as if the label will only be back referred to.
}
label->bind_to(target.offset());
InvalidateLastBytecode();
// exit_seen_in_block_ was reset when target was bound, so shouldn't be
// changed here.
} }
void BytecodeArrayWriter::BindJumpTableEntry(BytecodeJumpTable* jump_table, void BytecodeArrayWriter::BindJumpTableEntry(BytecodeJumpTable* jump_table,
...@@ -139,8 +136,37 @@ void BytecodeArrayWriter::BindJumpTableEntry(BytecodeJumpTable* jump_table, ...@@ -139,8 +136,37 @@ void BytecodeArrayWriter::BindJumpTableEntry(BytecodeJumpTable* jump_table,
Smi::FromInt(static_cast<int>(relative_jump))); Smi::FromInt(static_cast<int>(relative_jump)));
jump_table->mark_bound(case_value); jump_table->mark_bound(case_value);
StartBasicBlock();
}
void BytecodeArrayWriter::BindHandlerTarget(
HandlerTableBuilder* handler_table_builder, int handler_id) {
size_t current_offset = bytecodes()->size();
StartBasicBlock();
handler_table_builder->SetHandlerTarget(handler_id, current_offset);
}
void BytecodeArrayWriter::BindTryRegionStart(
HandlerTableBuilder* handler_table_builder, int handler_id) {
size_t current_offset = bytecodes()->size();
// Try blocks don't have to be in a separate basic block, but we do have to
// invalidate the bytecode to avoid eliding it and changing the offset.
InvalidateLastBytecode(); InvalidateLastBytecode();
exit_seen_in_block_ = false; // Starting a new basic block. handler_table_builder->SetTryRegionStart(handler_id, current_offset);
}
void BytecodeArrayWriter::BindTryRegionEnd(
HandlerTableBuilder* handler_table_builder, int handler_id) {
// Try blocks don't have to be in a separate basic block, but we do have to
// invalidate the bytecode to avoid eliding it and changing the offset.
InvalidateLastBytecode();
size_t current_offset = bytecodes()->size();
handler_table_builder->SetTryRegionEnd(handler_id, current_offset);
}
void BytecodeArrayWriter::StartBasicBlock() {
InvalidateLastBytecode();
exit_seen_in_block_ = false;
} }
void BytecodeArrayWriter::UpdateSourcePositionTable( void BytecodeArrayWriter::UpdateSourcePositionTable(
...@@ -378,25 +404,33 @@ void BytecodeArrayWriter::PatchJump(size_t jump_target, size_t jump_location) { ...@@ -378,25 +404,33 @@ void BytecodeArrayWriter::PatchJump(size_t jump_target, size_t jump_location) {
unbound_jumps_--; unbound_jumps_--;
} }
void BytecodeArrayWriter::EmitJump(BytecodeNode* node, BytecodeLabel* label) { void BytecodeArrayWriter::EmitJumpLoop(BytecodeNode* node,
DCHECK(Bytecodes::IsJump(node->bytecode())); BytecodeLoopHeader* loop_header) {
DCHECK_EQ(node->bytecode(), Bytecode::kJumpLoop);
DCHECK_EQ(0u, node->operand(0)); DCHECK_EQ(0u, node->operand(0));
size_t current_offset = bytecodes()->size(); size_t current_offset = bytecodes()->size();
if (label->is_bound()) { CHECK_GE(current_offset, loop_header->offset());
CHECK_GE(current_offset, label->offset());
CHECK_LE(current_offset, static_cast<size_t>(kMaxUInt32)); CHECK_LE(current_offset, static_cast<size_t>(kMaxUInt32));
// Label has been bound already so this is a backwards jump. // Label has been bound already so this is a backwards jump.
uint32_t delta = static_cast<uint32_t>(current_offset - label->offset()); uint32_t delta =
static_cast<uint32_t>(current_offset - loop_header->offset());
OperandScale operand_scale = Bytecodes::ScaleForUnsignedOperand(delta); OperandScale operand_scale = Bytecodes::ScaleForUnsignedOperand(delta);
if (operand_scale > OperandScale::kSingle) { if (operand_scale > OperandScale::kSingle) {
// Adjust for scaling byte prefix for wide jump offset. // Adjust for scaling byte prefix for wide jump offset.
delta += 1; delta += 1;
} }
DCHECK_EQ(Bytecode::kJumpLoop, node->bytecode());
node->update_operand0(delta); node->update_operand0(delta);
} else { EmitBytecode(node);
}
void BytecodeArrayWriter::EmitJump(BytecodeNode* node, BytecodeLabel* label) {
DCHECK(Bytecodes::IsForwardJump(node->bytecode()));
DCHECK_EQ(0u, node->operand(0));
size_t current_offset = bytecodes()->size();
// The label has not yet been bound so this is a forward reference // The label has not yet been bound so this is a forward reference
// that will be patched when the label is bound. We create a // that will be patched when the label is bound. We create a
// reservation in the constant pool so the jump can be patched // reservation in the constant pool so the jump can be patched
...@@ -422,7 +456,6 @@ void BytecodeArrayWriter::EmitJump(BytecodeNode* node, BytecodeLabel* label) { ...@@ -422,7 +456,6 @@ void BytecodeArrayWriter::EmitJump(BytecodeNode* node, BytecodeLabel* label) {
node->update_operand0(k32BitJumpPlaceholder); node->update_operand0(k32BitJumpPlaceholder);
break; break;
} }
}
EmitBytecode(node); EmitBytecode(node);
} }
......
...@@ -19,9 +19,11 @@ class SourcePositionTableBuilder; ...@@ -19,9 +19,11 @@ class SourcePositionTableBuilder;
namespace interpreter { namespace interpreter {
class BytecodeLabel; class BytecodeLabel;
class BytecodeLoopHeader;
class BytecodeNode; class BytecodeNode;
class BytecodeJumpTable; class BytecodeJumpTable;
class ConstantArrayBuilder; class ConstantArrayBuilder;
class HandlerTableBuilder;
namespace bytecode_array_writer_unittest { namespace bytecode_array_writer_unittest {
class BytecodeArrayWriterUnittest; class BytecodeArrayWriterUnittest;
...@@ -37,10 +39,18 @@ class V8_EXPORT_PRIVATE BytecodeArrayWriter final { ...@@ -37,10 +39,18 @@ class V8_EXPORT_PRIVATE BytecodeArrayWriter final {
void Write(BytecodeNode* node); void Write(BytecodeNode* node);
void WriteJump(BytecodeNode* node, BytecodeLabel* label); void WriteJump(BytecodeNode* node, BytecodeLabel* label);
void WriteJumpLoop(BytecodeNode* node, BytecodeLoopHeader* loop_header);
void WriteSwitch(BytecodeNode* node, BytecodeJumpTable* jump_table); void WriteSwitch(BytecodeNode* node, BytecodeJumpTable* jump_table);
void BindLabel(BytecodeLabel* label); void BindLabel(BytecodeLabel* label);
void BindLabel(const BytecodeLabel& target, BytecodeLabel* label); void BindLoopHeader(BytecodeLoopHeader* loop_header);
void BindJumpTableEntry(BytecodeJumpTable* jump_table, int case_value); void BindJumpTableEntry(BytecodeJumpTable* jump_table, int case_value);
void BindHandlerTarget(HandlerTableBuilder* handler_table_builder,
int handler_id);
void BindTryRegionStart(HandlerTableBuilder* handler_table_builder,
int handler_id);
void BindTryRegionEnd(HandlerTableBuilder* handler_table_builder,
int handler_id);
Handle<BytecodeArray> ToBytecodeArray(Isolate* isolate, int register_count, Handle<BytecodeArray> ToBytecodeArray(Isolate* isolate, int register_count,
int parameter_count, int parameter_count,
Handle<ByteArray> handler_table); Handle<ByteArray> handler_table);
...@@ -71,6 +81,7 @@ class V8_EXPORT_PRIVATE BytecodeArrayWriter final { ...@@ -71,6 +81,7 @@ class V8_EXPORT_PRIVATE BytecodeArrayWriter final {
void EmitBytecode(const BytecodeNode* const node); void EmitBytecode(const BytecodeNode* const node);
void EmitJump(BytecodeNode* node, BytecodeLabel* label); void EmitJump(BytecodeNode* node, BytecodeLabel* label);
void EmitJumpLoop(BytecodeNode* node, BytecodeLoopHeader* loop_header);
void EmitSwitch(BytecodeNode* node, BytecodeJumpTable* jump_table); void EmitSwitch(BytecodeNode* node, BytecodeJumpTable* jump_table);
void UpdateSourcePositionTable(const BytecodeNode* const node); void UpdateSourcePositionTable(const BytecodeNode* const node);
...@@ -79,6 +90,8 @@ class V8_EXPORT_PRIVATE BytecodeArrayWriter final { ...@@ -79,6 +90,8 @@ class V8_EXPORT_PRIVATE BytecodeArrayWriter final {
void MaybeElideLastBytecode(Bytecode next_bytecode, bool has_source_info); void MaybeElideLastBytecode(Bytecode next_bytecode, bool has_source_info);
void InvalidateLastBytecode(); void InvalidateLastBytecode();
void StartBasicBlock();
ZoneVector<uint8_t>* bytecodes() { return &bytecodes_; } ZoneVector<uint8_t>* bytecodes() { return &bytecodes_; }
SourcePositionTableBuilder* source_position_table_builder() { SourcePositionTableBuilder* source_position_table_builder() {
return &source_position_table_builder_; return &source_position_table_builder_;
......
...@@ -18,18 +18,13 @@ BytecodeLabel* BytecodeLabels::New() { ...@@ -18,18 +18,13 @@ BytecodeLabel* BytecodeLabels::New() {
} }
void BytecodeLabels::Bind(BytecodeArrayBuilder* builder) { void BytecodeLabels::Bind(BytecodeArrayBuilder* builder) {
DCHECK(!is_bound_);
is_bound_ = true;
for (auto& label : labels_) { for (auto& label : labels_) {
builder->Bind(&label); builder->Bind(&label);
} }
} }
void BytecodeLabels::BindToLabel(BytecodeArrayBuilder* builder,
const BytecodeLabel& target) {
for (auto& label : labels_) {
builder->Bind(target, &label);
}
}
} // namespace interpreter } // namespace interpreter
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
...@@ -15,42 +15,67 @@ namespace interpreter { ...@@ -15,42 +15,67 @@ namespace interpreter {
class BytecodeArrayBuilder; class BytecodeArrayBuilder;
// A label representing a branch target in a bytecode array. When a // A label representing a loop header in a bytecode array. It is bound before
// label is bound, it represents a known position in the bytecode // the jump is seen, so its position is always known by the time the jump is
// array. For labels that are forward references there can be at most // reached.
// one reference whilst it is unbound. class V8_EXPORT_PRIVATE BytecodeLoopHeader final {
class V8_EXPORT_PRIVATE BytecodeLabel final {
public: public:
BytecodeLabel() : bound_(false), offset_(kInvalidOffset) {} BytecodeLoopHeader() : offset_(kInvalidOffset) {}
bool is_bound() const { return bound_; } size_t offset() const {
size_t offset() const { return offset_; } DCHECK_NE(offset_, kInvalidOffset);
return offset_;
}
private: private:
static const size_t kInvalidOffset = static_cast<size_t>(-1); static const size_t kInvalidOffset = static_cast<size_t>(-1);
void bind_to(size_t offset) { void bind_to(size_t offset) {
DCHECK(!bound_ && offset != kInvalidOffset); DCHECK_NE(offset, kInvalidOffset);
DCHECK_EQ(offset_, kInvalidOffset);
offset_ = offset; offset_ = offset;
bound_ = true;
} }
void set_referrer(size_t offset) { // The bytecode offset of the loop header.
DCHECK(!bound_ && offset != kInvalidOffset && offset_ == kInvalidOffset); size_t offset_;
offset_ = offset;
friend class BytecodeArrayWriter;
};
// A label representing a forward branch target in a bytecode array. When a
// label is bound, it represents a known position in the bytecode array. A label
// can only have at most one referrer jump.
class V8_EXPORT_PRIVATE BytecodeLabel final {
public:
BytecodeLabel() : bound_(false), jump_offset_(kInvalidOffset) {}
bool is_bound() const { return bound_; }
size_t jump_offset() const {
DCHECK_NE(jump_offset_, kInvalidOffset);
return jump_offset_;
}
bool has_referrer_jump() const { return jump_offset_ != kInvalidOffset; }
private:
static const size_t kInvalidOffset = static_cast<size_t>(-1);
void bind() {
DCHECK(!bound_);
bound_ = true;
} }
bool is_forward_target() const { void set_referrer(size_t offset) {
return offset() != kInvalidOffset && !is_bound(); DCHECK(!bound_);
DCHECK_NE(offset, kInvalidOffset);
DCHECK_EQ(jump_offset_, kInvalidOffset);
jump_offset_ = offset;
} }
// There are three states for a label: // Set when the label is bound (i.e. the start of the target basic block).
// bound_ offset_
// UNSET false kInvalidOffset
// FORWARD_TARGET false Offset of referring jump
// BACKWARD_TARGET true Offset of label in bytecode array when bound
bool bound_; bool bound_;
size_t offset_; // Set when the jump referrer is set (i.e. the location of the jump).
size_t jump_offset_;
friend class BytecodeArrayWriter; friend class BytecodeArrayWriter;
}; };
...@@ -58,26 +83,26 @@ class V8_EXPORT_PRIVATE BytecodeLabel final { ...@@ -58,26 +83,26 @@ class V8_EXPORT_PRIVATE BytecodeLabel final {
// Class representing a branch target of multiple jumps. // Class representing a branch target of multiple jumps.
class V8_EXPORT_PRIVATE BytecodeLabels { class V8_EXPORT_PRIVATE BytecodeLabels {
public: public:
explicit BytecodeLabels(Zone* zone) : labels_(zone) {} explicit BytecodeLabels(Zone* zone) : labels_(zone), is_bound_(false) {}
BytecodeLabel* New(); BytecodeLabel* New();
void Bind(BytecodeArrayBuilder* builder); void Bind(BytecodeArrayBuilder* builder);
void BindToLabel(BytecodeArrayBuilder* builder, const BytecodeLabel& target);
bool is_bound() const { bool is_bound() const {
bool is_bound = !labels_.empty() && labels_.front().is_bound(); DCHECK_IMPLIES(
DCHECK(!is_bound || is_bound_,
std::all_of(labels_.begin(), labels_.end(), std::all_of(labels_.begin(), labels_.end(), [](const BytecodeLabel& l) {
[](const BytecodeLabel& l) { return l.is_bound(); })); return !l.has_referrer_jump() || l.is_bound();
return is_bound; }));
return is_bound_;
} }
bool empty() const { return labels_.empty(); } bool empty() const { return labels_.empty(); }
private: private:
ZoneLinkedList<BytecodeLabel> labels_; ZoneLinkedList<BytecodeLabel> labels_;
bool is_bound_;
DISALLOW_COPY_AND_ASSIGN(BytecodeLabels); DISALLOW_COPY_AND_ASSIGN(BytecodeLabels);
}; };
......
...@@ -60,6 +60,7 @@ class V8_EXPORT_PRIVATE BytecodeRegisterOptimizer final ...@@ -60,6 +60,7 @@ class V8_EXPORT_PRIVATE BytecodeRegisterOptimizer final
// Materialize all live registers and flush equivalence sets. // Materialize all live registers and flush equivalence sets.
void Flush(); void Flush();
bool EnsureAllRegistersAreFlushed() const;
// Prepares for |bytecode|. // Prepares for |bytecode|.
template <Bytecode bytecode, AccumulatorUse accumulator_use> template <Bytecode bytecode, AccumulatorUse accumulator_use>
...@@ -132,8 +133,6 @@ class V8_EXPORT_PRIVATE BytecodeRegisterOptimizer final ...@@ -132,8 +133,6 @@ class V8_EXPORT_PRIVATE BytecodeRegisterOptimizer final
RegisterInfo* non_set_member); RegisterInfo* non_set_member);
void PushToRegistersNeedingFlush(RegisterInfo* reg); void PushToRegistersNeedingFlush(RegisterInfo* reg);
bool EnsureAllRegistersAreFlushed() const;
// Methods for finding and creating metadata for each register. // Methods for finding and creating metadata for each register.
RegisterInfo* GetRegisterInfo(Register reg) { RegisterInfo* GetRegisterInfo(Register reg) {
size_t index = GetRegisterInfoTableIndex(reg); size_t index = GetRegisterInfoTableIndex(reg);
......
...@@ -70,7 +70,6 @@ void LoopBuilder::JumpToHeader(int loop_depth) { ...@@ -70,7 +70,6 @@ void LoopBuilder::JumpToHeader(int loop_depth) {
int level = Min(loop_depth, AbstractCode::kMaxLoopNestingMarker - 1); int level = Min(loop_depth, AbstractCode::kMaxLoopNestingMarker - 1);
// Loop must have closed form, i.e. all loop elements are within the loop, // Loop must have closed form, i.e. all loop elements are within the loop,
// the loop header precedes the body and next elements in the loop. // the loop header precedes the body and next elements in the loop.
DCHECK(loop_header_.is_bound());
builder()->JumpLoop(&loop_header_, level); builder()->JumpLoop(&loop_header_, level);
} }
...@@ -108,7 +107,6 @@ void TryCatchBuilder::BeginTry(Register context) { ...@@ -108,7 +107,6 @@ void TryCatchBuilder::BeginTry(Register context) {
void TryCatchBuilder::EndTry() { void TryCatchBuilder::EndTry() {
builder()->MarkTryEnd(handler_id_); builder()->MarkTryEnd(handler_id_);
builder()->Jump(&exit_); builder()->Jump(&exit_);
builder()->Bind(&handler_);
builder()->MarkHandler(handler_id_, catch_prediction_); builder()->MarkHandler(handler_id_, catch_prediction_);
if (block_coverage_builder_ != nullptr) { if (block_coverage_builder_ != nullptr) {
......
...@@ -121,7 +121,7 @@ class V8_EXPORT_PRIVATE LoopBuilder final : public BreakableControlFlowBuilder { ...@@ -121,7 +121,7 @@ class V8_EXPORT_PRIVATE LoopBuilder final : public BreakableControlFlowBuilder {
void ContinueIfNull() { EmitJumpIfNull(&continue_labels_); } void ContinueIfNull() { EmitJumpIfNull(&continue_labels_); }
private: private:
BytecodeLabel loop_header_; BytecodeLoopHeader loop_header_;
// Unbound labels that identify jumps for continue statements in the code and // 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. // jumps from checking the loop condition to the header for do-while loops.
...@@ -188,7 +188,6 @@ class V8_EXPORT_PRIVATE TryCatchBuilder final : public ControlFlowBuilder { ...@@ -188,7 +188,6 @@ class V8_EXPORT_PRIVATE TryCatchBuilder final : public ControlFlowBuilder {
private: private:
int handler_id_; int handler_id_;
HandlerTable::CatchPrediction catch_prediction_; HandlerTable::CatchPrediction catch_prediction_;
BytecodeLabel handler_;
BytecodeLabel exit_; BytecodeLabel exit_;
BlockCoverageBuilder* block_coverage_builder_; BlockCoverageBuilder* block_coverage_builder_;
......
...@@ -14,7 +14,7 @@ snippet: " ...@@ -14,7 +14,7 @@ snippet: "
" "
frame size: 8 frame size: 8
parameter count: 1 parameter count: 1
bytecode array length: 190 bytecode array length: 180
bytecodes: [ bytecodes: [
B(SwitchOnGeneratorState), R(0), U8(0), U8(2), B(SwitchOnGeneratorState), R(0), U8(0), U8(2),
B(Mov), R(closure), R(1), B(Mov), R(closure), R(1),
...@@ -35,7 +35,7 @@ bytecodes: [ ...@@ -35,7 +35,7 @@ bytecodes: [
B(LdaSmi), I8(1), B(LdaSmi), I8(1),
B(Star), R(1), B(Star), R(1),
B(Mov), R(5), R(2), B(Mov), R(5), R(2),
B(Jump), U8(95), B(Jump), U8(85),
B(LdaUndefined), B(LdaUndefined),
B(Star), R(6), B(Star), R(6),
B(Mov), R(0), R(5), B(Mov), R(0), R(5),
...@@ -53,8 +53,7 @@ bytecodes: [ ...@@ -53,8 +53,7 @@ bytecodes: [
B(LdaSmi), I8(1), B(LdaSmi), I8(1),
B(Star), R(1), B(Star), R(1),
B(Mov), R(5), R(2), B(Mov), R(5), R(2),
B(Jump), U8(51), B(Jump), U8(41),
B(Jump), U8(36),
B(Star), R(5), B(Star), R(5),
B(CreateCatchContext), R(5), U8(4), B(CreateCatchContext), R(5), U8(4),
B(Star), R(4), B(Star), R(4),
...@@ -70,10 +69,6 @@ bytecodes: [ ...@@ -70,10 +69,6 @@ bytecodes: [
B(Star), R(2), B(Star), R(2),
B(LdaSmi), I8(2), B(LdaSmi), I8(2),
B(Star), R(1), B(Star), R(1),
B(Jump), U8(15),
B(LdaSmi), I8(-1),
B(Star), R(2),
B(Star), R(1),
B(Jump), U8(7), B(Jump), U8(7),
B(Star), R(2), B(Star), R(2),
B(LdaZero), B(LdaZero),
...@@ -111,8 +106,8 @@ constant pool: [ ...@@ -111,8 +106,8 @@ constant pool: [
Smi [23], Smi [23],
] ]
handlers: [ handlers: [
[20, 136, 144], [20, 134, 134],
[23, 100, 102], [23, 100, 100],
] ]
--- ---
...@@ -122,7 +117,7 @@ snippet: " ...@@ -122,7 +117,7 @@ snippet: "
" "
frame size: 8 frame size: 8
parameter count: 1 parameter count: 1
bytecode array length: 235 bytecode array length: 225
bytecodes: [ bytecodes: [
B(SwitchOnGeneratorState), R(0), U8(0), U8(3), B(SwitchOnGeneratorState), R(0), U8(0), U8(3),
B(Mov), R(closure), R(1), B(Mov), R(closure), R(1),
...@@ -143,7 +138,7 @@ bytecodes: [ ...@@ -143,7 +138,7 @@ bytecodes: [
B(LdaSmi), I8(1), B(LdaSmi), I8(1),
B(Star), R(1), B(Star), R(1),
B(Mov), R(5), R(2), B(Mov), R(5), R(2),
B(Jump), U8(140), B(Jump), U8(130),
/* 22 S> */ B(LdaSmi), I8(42), /* 22 S> */ B(LdaSmi), I8(42),
B(Star), R(6), B(Star), R(6),
B(LdaFalse), B(LdaFalse),
...@@ -160,7 +155,7 @@ bytecodes: [ ...@@ -160,7 +155,7 @@ bytecodes: [
B(LdaSmi), I8(1), B(LdaSmi), I8(1),
B(Star), R(1), B(Star), R(1),
B(Mov), R(5), R(2), B(Mov), R(5), R(2),
B(Jump), U8(95), B(Jump), U8(85),
B(LdaUndefined), B(LdaUndefined),
B(Star), R(6), B(Star), R(6),
B(Mov), R(0), R(5), B(Mov), R(0), R(5),
...@@ -178,8 +173,7 @@ bytecodes: [ ...@@ -178,8 +173,7 @@ bytecodes: [
B(LdaSmi), I8(1), B(LdaSmi), I8(1),
B(Star), R(1), B(Star), R(1),
B(Mov), R(5), R(2), B(Mov), R(5), R(2),
B(Jump), U8(51), B(Jump), U8(41),
B(Jump), U8(36),
B(Star), R(5), B(Star), R(5),
B(CreateCatchContext), R(5), U8(7), B(CreateCatchContext), R(5), U8(7),
B(Star), R(4), B(Star), R(4),
...@@ -195,10 +189,6 @@ bytecodes: [ ...@@ -195,10 +189,6 @@ bytecodes: [
B(Star), R(2), B(Star), R(2),
B(LdaSmi), I8(2), B(LdaSmi), I8(2),
B(Star), R(1), B(Star), R(1),
B(Jump), U8(15),
B(LdaSmi), I8(-1),
B(Star), R(2),
B(Star), R(1),
B(Jump), U8(7), B(Jump), U8(7),
B(Star), R(2), B(Star), R(2),
B(LdaZero), B(LdaZero),
...@@ -239,8 +229,8 @@ constant pool: [ ...@@ -239,8 +229,8 @@ constant pool: [
Smi [23], Smi [23],
] ]
handlers: [ handlers: [
[20, 181, 189], [20, 179, 179],
[23, 145, 147], [23, 145, 145],
] ]
--- ---
...@@ -250,7 +240,7 @@ snippet: " ...@@ -250,7 +240,7 @@ snippet: "
" "
frame size: 20 frame size: 20
parameter count: 1 parameter count: 1
bytecode array length: 416 bytecode array length: 406
bytecodes: [ bytecodes: [
B(SwitchOnGeneratorState), R(0), U8(0), U8(3), B(SwitchOnGeneratorState), R(0), U8(0), U8(3),
B(Mov), R(closure), R(4), B(Mov), R(closure), R(4),
...@@ -364,7 +354,7 @@ bytecodes: [ ...@@ -364,7 +354,7 @@ bytecodes: [
B(LdaSmi), I8(1), B(LdaSmi), I8(1),
B(Star), R(4), B(Star), R(4),
B(Mov), R(14), R(5), B(Mov), R(14), R(5),
B(Jump), U8(95), B(Jump), U8(85),
B(LdaUndefined), B(LdaUndefined),
B(Star), R(9), B(Star), R(9),
B(Mov), R(0), R(8), B(Mov), R(0), R(8),
...@@ -382,8 +372,7 @@ bytecodes: [ ...@@ -382,8 +372,7 @@ bytecodes: [
B(LdaSmi), I8(1), B(LdaSmi), I8(1),
B(Star), R(4), B(Star), R(4),
B(Mov), R(8), R(5), B(Mov), R(8), R(5),
B(Jump), U8(51), B(Jump), U8(41),
B(Jump), U8(36),
B(Star), R(8), B(Star), R(8),
B(CreateCatchContext), R(8), U8(16), B(CreateCatchContext), R(8), U8(16),
B(Star), R(7), B(Star), R(7),
...@@ -399,10 +388,6 @@ bytecodes: [ ...@@ -399,10 +388,6 @@ bytecodes: [
B(Star), R(5), B(Star), R(5),
B(LdaSmi), I8(2), B(LdaSmi), I8(2),
B(Star), R(4), B(Star), R(4),
B(Jump), U8(15),
B(LdaSmi), I8(-1),
B(Star), R(5),
B(Star), R(4),
B(Jump), U8(7), B(Jump), U8(7),
B(Star), R(5), B(Star), R(5),
B(LdaZero), B(LdaZero),
...@@ -447,14 +432,14 @@ constant pool: [ ...@@ -447,14 +432,14 @@ constant pool: [
Smi [6], Smi [6],
Smi [9], Smi [9],
SCOPE_INFO_TYPE, SCOPE_INFO_TYPE,
Smi [321], Smi [311],
Smi [6], Smi [6],
Smi [9], Smi [9],
Smi [23], Smi [23],
] ]
handlers: [ handlers: [
[20, 362, 370], [20, 360, 360],
[23, 326, 328], [23, 326, 326],
[93, 180, 188], [93, 180, 188],
[234, 247, 249], [234, 247, 249],
] ]
...@@ -467,7 +452,7 @@ snippet: " ...@@ -467,7 +452,7 @@ snippet: "
" "
frame size: 17 frame size: 17
parameter count: 1 parameter count: 1
bytecode array length: 482 bytecode array length: 472
bytecodes: [ bytecodes: [
B(SwitchOnGeneratorState), R(0), U8(0), U8(5), B(SwitchOnGeneratorState), R(0), U8(0), U8(5),
B(Mov), R(closure), R(1), B(Mov), R(closure), R(1),
...@@ -595,7 +580,7 @@ bytecodes: [ ...@@ -595,7 +580,7 @@ bytecodes: [
B(LdaSmi), I8(1), B(LdaSmi), I8(1),
B(Star), R(1), B(Star), R(1),
B(Mov), R(7), R(2), B(Mov), R(7), R(2),
B(Jump), U8(95), B(Jump), U8(85),
B(LdaUndefined), B(LdaUndefined),
B(Star), R(6), B(Star), R(6),
B(Mov), R(0), R(5), B(Mov), R(0), R(5),
...@@ -613,8 +598,7 @@ bytecodes: [ ...@@ -613,8 +598,7 @@ bytecodes: [
B(LdaSmi), I8(1), B(LdaSmi), I8(1),
B(Star), R(1), B(Star), R(1),
B(Mov), R(5), R(2), B(Mov), R(5), R(2),
B(Jump), U8(51), B(Jump), U8(41),
B(Jump), U8(36),
B(Star), R(5), B(Star), R(5),
B(CreateCatchContext), R(5), U8(17), B(CreateCatchContext), R(5), U8(17),
B(Star), R(4), B(Star), R(4),
...@@ -630,10 +614,6 @@ bytecodes: [ ...@@ -630,10 +614,6 @@ bytecodes: [
B(Star), R(2), B(Star), R(2),
B(LdaSmi), I8(2), B(LdaSmi), I8(2),
B(Star), R(1), B(Star), R(1),
B(Jump), U8(15),
B(LdaSmi), I8(-1),
B(Star), R(2),
B(Star), R(1),
B(Jump), U8(7), B(Jump), U8(7),
B(Star), R(2), B(Star), R(2),
B(LdaZero), B(LdaZero),
...@@ -679,14 +659,14 @@ constant pool: [ ...@@ -679,14 +659,14 @@ constant pool: [
ONE_BYTE_INTERNALIZED_STRING_TYPE ["done"], ONE_BYTE_INTERNALIZED_STRING_TYPE ["done"],
ONE_BYTE_INTERNALIZED_STRING_TYPE ["value"], ONE_BYTE_INTERNALIZED_STRING_TYPE ["value"],
SCOPE_INFO_TYPE, SCOPE_INFO_TYPE,
Smi [387], Smi [377],
Smi [287], Smi [277],
Smi [6], Smi [6],
Smi [9], Smi [9],
Smi [23], Smi [23],
] ]
handlers: [ handlers: [
[20, 428, 436], [20, 426, 426],
[23, 392, 394], [23, 392, 392],
] ]
...@@ -211,7 +211,7 @@ snippet: " ...@@ -211,7 +211,7 @@ snippet: "
" "
frame size: 1 frame size: 1
parameter count: 1 parameter count: 1
bytecode array length: 14 bytecode array length: 12
bytecodes: [ bytecodes: [
/* 30 E> */ B(StackCheck), /* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaZero), /* 42 S> */ B(LdaZero),
...@@ -221,8 +221,6 @@ bytecodes: [ ...@@ -221,8 +221,6 @@ bytecodes: [
/* 74 S> */ B(Return), /* 74 S> */ B(Return),
/* 86 S> */ B(LdaSmi), I8(2), /* 86 S> */ B(LdaSmi), I8(2),
/* 95 S> */ B(Return), /* 95 S> */ B(Return),
B(LdaUndefined),
/* 98 S> */ B(Return),
] ]
constant pool: [ constant pool: [
] ]
......
...@@ -115,7 +115,7 @@ snippet: " ...@@ -115,7 +115,7 @@ snippet: "
" "
frame size: 16 frame size: 16
parameter count: 1 parameter count: 1
bytecode array length: 266 bytecode array length: 264
bytecodes: [ bytecodes: [
/* 30 E> */ B(StackCheck), /* 30 E> */ B(StackCheck),
/* 48 S> */ B(CreateArrayLiteral), U8(0), U8(0), U8(37), /* 48 S> */ B(CreateArrayLiteral), U8(0), U8(0), U8(37),
...@@ -185,7 +185,6 @@ bytecodes: [ ...@@ -185,7 +185,6 @@ bytecodes: [
B(Star), R(14), B(Star), R(14),
B(JumpLoop), U8(33), I8(0), B(JumpLoop), U8(33), I8(0),
B(Mov), R(13), R(1), B(Mov), R(13), R(1),
B(Ldar), R(1),
B(LdaSmi), I8(-1), B(LdaSmi), I8(-1),
B(Star), R(10), B(Star), R(10),
B(Star), R(9), B(Star), R(9),
...@@ -242,8 +241,8 @@ constant pool: [ ...@@ -242,8 +241,8 @@ constant pool: [
ONE_BYTE_INTERNALIZED_STRING_TYPE [""], ONE_BYTE_INTERNALIZED_STRING_TYPE [""],
] ]
handlers: [ handlers: [
[44, 174, 182], [44, 172, 180],
[228, 241, 243], [226, 239, 241],
] ]
--- ---
......
...@@ -16,7 +16,7 @@ snippet: " ...@@ -16,7 +16,7 @@ snippet: "
" "
frame size: 21 frame size: 21
parameter count: 1 parameter count: 1
bytecode array length: 329 bytecode array length: 325
bytecodes: [ bytecodes: [
B(SwitchOnGeneratorState), R(0), U8(0), U8(2), B(SwitchOnGeneratorState), R(0), U8(0), U8(2),
B(Mov), R(closure), R(4), B(Mov), R(closure), R(4),
...@@ -140,7 +140,6 @@ bytecodes: [ ...@@ -140,7 +140,6 @@ bytecodes: [
B(Mov), R(0), R(5), B(Mov), R(0), R(5),
B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionResolve), R(5), U8(3), B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionResolve), R(5), U8(3),
/* 57 S> */ B(Return), /* 57 S> */ B(Return),
B(Jump), U8(30),
B(Star), R(5), B(Star), R(5),
B(CreateCatchContext), R(5), U8(10), B(CreateCatchContext), R(5), U8(10),
B(Star), R(4), B(Star), R(4),
...@@ -154,8 +153,6 @@ bytecodes: [ ...@@ -154,8 +153,6 @@ bytecodes: [
B(Star), R(8), B(Star), R(8),
B(Mov), R(0), R(6), B(Mov), R(0), R(6),
B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionReject), R(6), U8(3), B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionReject), R(6), U8(3),
/* 57 S> */ B(Return),
B(LdaUndefined),
/* 57 S> */ B(Return), /* 57 S> */ B(Return),
] ]
constant pool: [ constant pool: [
...@@ -172,7 +169,7 @@ constant pool: [ ...@@ -172,7 +169,7 @@ constant pool: [
SCOPE_INFO_TYPE, SCOPE_INFO_TYPE,
] ]
handlers: [ handlers: [
[20, 297, 299], [20, 297, 297],
[77, 157, 165], [77, 157, 165],
[211, 260, 262], [211, 260, 262],
] ]
...@@ -186,7 +183,7 @@ snippet: " ...@@ -186,7 +183,7 @@ snippet: "
" "
frame size: 21 frame size: 21
parameter count: 1 parameter count: 1
bytecode array length: 350 bytecode array length: 346
bytecodes: [ bytecodes: [
B(SwitchOnGeneratorState), R(0), U8(0), U8(2), B(SwitchOnGeneratorState), R(0), U8(0), U8(2),
B(Mov), R(closure), R(4), B(Mov), R(closure), R(4),
...@@ -318,7 +315,6 @@ bytecodes: [ ...@@ -318,7 +315,6 @@ bytecodes: [
B(Mov), R(0), R(5), B(Mov), R(0), R(5),
B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionResolve), R(5), U8(3), B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionResolve), R(5), U8(3),
/* 68 S> */ B(Return), /* 68 S> */ B(Return),
B(Jump), U8(30),
B(Star), R(5), B(Star), R(5),
B(CreateCatchContext), R(5), U8(12), B(CreateCatchContext), R(5), U8(12),
B(Star), R(4), B(Star), R(4),
...@@ -332,8 +328,6 @@ bytecodes: [ ...@@ -332,8 +328,6 @@ bytecodes: [
B(Star), R(8), B(Star), R(8),
B(Mov), R(0), R(6), B(Mov), R(0), R(6),
B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionReject), R(6), U8(3), B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionReject), R(6), U8(3),
/* 68 S> */ B(Return),
B(LdaUndefined),
/* 68 S> */ B(Return), /* 68 S> */ B(Return),
] ]
constant pool: [ constant pool: [
...@@ -352,7 +346,7 @@ constant pool: [ ...@@ -352,7 +346,7 @@ constant pool: [
SCOPE_INFO_TYPE, SCOPE_INFO_TYPE,
] ]
handlers: [ handlers: [
[20, 318, 320], [20, 318, 318],
[77, 161, 169], [77, 161, 169],
[215, 264, 266], [215, 264, 266],
] ]
...@@ -369,7 +363,7 @@ snippet: " ...@@ -369,7 +363,7 @@ snippet: "
" "
frame size: 21 frame size: 21
parameter count: 1 parameter count: 1
bytecode array length: 345 bytecode array length: 341
bytecodes: [ bytecodes: [
B(SwitchOnGeneratorState), R(0), U8(0), U8(2), B(SwitchOnGeneratorState), R(0), U8(0), U8(2),
B(Mov), R(closure), R(4), B(Mov), R(closure), R(4),
...@@ -500,7 +494,6 @@ bytecodes: [ ...@@ -500,7 +494,6 @@ bytecodes: [
B(Mov), R(0), R(5), B(Mov), R(0), R(5),
B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionResolve), R(5), U8(3), B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionResolve), R(5), U8(3),
/* 114 S> */ B(Return), /* 114 S> */ B(Return),
B(Jump), U8(30),
B(Star), R(5), B(Star), R(5),
B(CreateCatchContext), R(5), U8(10), B(CreateCatchContext), R(5), U8(10),
B(Star), R(4), B(Star), R(4),
...@@ -514,8 +507,6 @@ bytecodes: [ ...@@ -514,8 +507,6 @@ bytecodes: [
B(Star), R(8), B(Star), R(8),
B(Mov), R(0), R(6), B(Mov), R(0), R(6),
B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionReject), R(6), U8(3), B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionReject), R(6), U8(3),
/* 114 S> */ B(Return),
B(LdaUndefined),
/* 114 S> */ B(Return), /* 114 S> */ B(Return),
] ]
constant pool: [ constant pool: [
...@@ -532,7 +523,7 @@ constant pool: [ ...@@ -532,7 +523,7 @@ constant pool: [
SCOPE_INFO_TYPE, SCOPE_INFO_TYPE,
] ]
handlers: [ handlers: [
[20, 313, 315], [20, 313, 313],
[77, 173, 181], [77, 173, 181],
[227, 276, 278], [227, 276, 278],
] ]
...@@ -547,7 +538,7 @@ snippet: " ...@@ -547,7 +538,7 @@ snippet: "
" "
frame size: 16 frame size: 16
parameter count: 1 parameter count: 1
bytecode array length: 265 bytecode array length: 261
bytecodes: [ bytecodes: [
B(Mov), R(closure), R(2), B(Mov), R(closure), R(2),
B(Mov), R(this), R(3), B(Mov), R(this), R(3),
...@@ -647,7 +638,6 @@ bytecodes: [ ...@@ -647,7 +638,6 @@ bytecodes: [
B(Mov), R(0), R(3), B(Mov), R(0), R(3),
B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionResolve), R(3), U8(3), B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionResolve), R(3), U8(3),
/* 96 S> */ B(Return), /* 96 S> */ B(Return),
B(Jump), U8(30),
B(Star), R(3), B(Star), R(3),
B(CreateCatchContext), R(3), U8(11), B(CreateCatchContext), R(3), U8(11),
B(Star), R(2), B(Star), R(2),
...@@ -661,8 +651,6 @@ bytecodes: [ ...@@ -661,8 +651,6 @@ bytecodes: [
B(Star), R(6), B(Star), R(6),
B(Mov), R(0), R(4), B(Mov), R(0), R(4),
B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionReject), R(4), U8(3), B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionReject), R(4), U8(3),
/* 96 S> */ B(Return),
B(LdaUndefined),
/* 96 S> */ B(Return), /* 96 S> */ B(Return),
] ]
constant pool: [ constant pool: [
...@@ -680,7 +668,7 @@ constant pool: [ ...@@ -680,7 +668,7 @@ constant pool: [
SCOPE_INFO_TYPE, SCOPE_INFO_TYPE,
] ]
handlers: [ handlers: [
[16, 233, 235], [16, 233, 233],
[59, 112, 120], [59, 112, 120],
[166, 179, 181], [166, 179, 181],
] ]
......
...@@ -739,7 +739,7 @@ snippet: " ...@@ -739,7 +739,7 @@ snippet: "
" "
frame size: 18 frame size: 18
parameter count: 2 parameter count: 2
bytecode array length: 232 bytecode array length: 228
bytecodes: [ bytecodes: [
B(Mov), R(closure), R(5), B(Mov), R(closure), R(5),
B(Mov), R(this), R(6), B(Mov), R(this), R(6),
...@@ -827,7 +827,6 @@ bytecodes: [ ...@@ -827,7 +827,6 @@ bytecodes: [
B(Mov), R(0), R(6), B(Mov), R(0), R(6),
B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionResolve), R(6), U8(3), B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionResolve), R(6), U8(3),
/* 60 S> */ B(Return), /* 60 S> */ B(Return),
B(Jump), U8(30),
B(Star), R(6), B(Star), R(6),
B(CreateCatchContext), R(6), U8(6), B(CreateCatchContext), R(6), U8(6),
B(Star), R(5), B(Star), R(5),
...@@ -841,8 +840,6 @@ bytecodes: [ ...@@ -841,8 +840,6 @@ bytecodes: [
B(Star), R(9), B(Star), R(9),
B(Mov), R(0), R(7), B(Mov), R(0), R(7),
B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionReject), R(7), U8(3), B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionReject), R(7), U8(3),
/* 60 S> */ B(Return),
B(LdaUndefined),
/* 60 S> */ B(Return), /* 60 S> */ B(Return),
] ]
constant pool: [ constant pool: [
...@@ -855,7 +852,7 @@ constant pool: [ ...@@ -855,7 +852,7 @@ constant pool: [
SCOPE_INFO_TYPE, SCOPE_INFO_TYPE,
] ]
handlers: [ handlers: [
[16, 200, 202], [16, 200, 200],
[50, 96, 104], [50, 96, 104],
[150, 163, 165], [150, 163, 165],
] ]
...@@ -869,7 +866,7 @@ snippet: " ...@@ -869,7 +866,7 @@ snippet: "
" "
frame size: 17 frame size: 17
parameter count: 2 parameter count: 2
bytecode array length: 268 bytecode array length: 264
bytecodes: [ bytecodes: [
B(SwitchOnGeneratorState), R(0), U8(0), U8(1), B(SwitchOnGeneratorState), R(0), U8(0), U8(1),
B(Mov), R(closure), R(4), B(Mov), R(closure), R(4),
...@@ -970,7 +967,6 @@ bytecodes: [ ...@@ -970,7 +967,6 @@ bytecodes: [
B(Mov), R(0), R(5), B(Mov), R(0), R(5),
B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionResolve), R(5), U8(3), B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionResolve), R(5), U8(3),
/* 54 S> */ B(Return), /* 54 S> */ B(Return),
B(Jump), U8(30),
B(Star), R(5), B(Star), R(5),
B(CreateCatchContext), R(5), U8(7), B(CreateCatchContext), R(5), U8(7),
B(Star), R(4), B(Star), R(4),
...@@ -984,8 +980,6 @@ bytecodes: [ ...@@ -984,8 +980,6 @@ bytecodes: [
B(Star), R(8), B(Star), R(8),
B(Mov), R(0), R(6), B(Mov), R(0), R(6),
B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionReject), R(6), U8(3), B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionReject), R(6), U8(3),
/* 54 S> */ B(Return),
B(LdaUndefined),
/* 54 S> */ B(Return), /* 54 S> */ B(Return),
] ]
constant pool: [ constant pool: [
...@@ -999,7 +993,7 @@ constant pool: [ ...@@ -999,7 +993,7 @@ constant pool: [
SCOPE_INFO_TYPE, SCOPE_INFO_TYPE,
] ]
handlers: [ handlers: [
[20, 236, 238], [20, 236, 236],
[54, 132, 140], [54, 132, 140],
[186, 199, 201], [186, 199, 201],
] ]
......
...@@ -147,7 +147,7 @@ snippet: " ...@@ -147,7 +147,7 @@ snippet: "
" "
frame size: 0 frame size: 0
parameter count: 2 parameter count: 2
bytecode array length: 19 bytecode array length: 17
bytecodes: [ bytecodes: [
/* 10 E> */ B(StackCheck), /* 10 E> */ B(StackCheck),
/* 18 S> */ B(LdaZero), /* 18 S> */ B(LdaZero),
...@@ -157,8 +157,6 @@ bytecodes: [ ...@@ -157,8 +157,6 @@ bytecodes: [
/* 47 S> */ B(Return), /* 47 S> */ B(Return),
/* 63 S> */ B(Wide), B(LdaSmi), I16(-200), /* 63 S> */ B(Wide), B(LdaSmi), I16(-200),
/* 75 S> */ B(Return), /* 75 S> */ B(Return),
B(LdaUndefined),
/* 80 S> */ B(Return),
] ]
constant pool: [ constant pool: [
] ]
...@@ -258,7 +256,7 @@ snippet: " ...@@ -258,7 +256,7 @@ snippet: "
" "
frame size: 2 frame size: 2
parameter count: 2 parameter count: 2
bytecode array length: 29 bytecode array length: 27
bytecodes: [ bytecodes: [
/* 10 E> */ B(StackCheck), /* 10 E> */ B(StackCheck),
/* 24 S> */ B(LdaZero), /* 24 S> */ B(LdaZero),
...@@ -273,8 +271,6 @@ bytecodes: [ ...@@ -273,8 +271,6 @@ bytecodes: [
/* 1092 S> */ B(Return), /* 1092 S> */ B(Return),
/* 1102 S> */ B(Wide), B(LdaSmi), I16(-200), /* 1102 S> */ B(Wide), B(LdaSmi), I16(-200),
/* 1114 S> */ B(Return), /* 1114 S> */ B(Return),
B(LdaUndefined),
/* 1117 S> */ B(Return),
] ]
constant pool: [ constant pool: [
HEAP_NUMBER_TYPE [0.01], HEAP_NUMBER_TYPE [0.01],
...@@ -357,7 +353,7 @@ snippet: " ...@@ -357,7 +353,7 @@ snippet: "
" "
frame size: 2 frame size: 2
parameter count: 1 parameter count: 1
bytecode array length: 26 bytecode array length: 24
bytecodes: [ bytecodes: [
/* 10 E> */ B(StackCheck), /* 10 E> */ B(StackCheck),
/* 25 S> */ B(LdaZero), /* 25 S> */ B(LdaZero),
...@@ -371,8 +367,6 @@ bytecodes: [ ...@@ -371,8 +367,6 @@ bytecodes: [
/* 1087 S> */ B(Return), /* 1087 S> */ B(Return),
/* 1097 S> */ B(Wide), B(LdaSmi), I16(-200), /* 1097 S> */ B(Wide), B(LdaSmi), I16(-200),
/* 1109 S> */ B(Return), /* 1109 S> */ B(Return),
B(LdaUndefined),
/* 1112 S> */ B(Return),
] ]
constant pool: [ constant pool: [
] ]
...@@ -461,7 +455,7 @@ snippet: " ...@@ -461,7 +455,7 @@ snippet: "
" "
frame size: 1 frame size: 1
parameter count: 1 parameter count: 1
bytecode array length: 14 bytecode array length: 12
bytecodes: [ bytecodes: [
/* 10 E> */ B(StackCheck), /* 10 E> */ B(StackCheck),
/* 25 S> */ B(LdaZero), /* 25 S> */ B(LdaZero),
...@@ -471,8 +465,6 @@ bytecodes: [ ...@@ -471,8 +465,6 @@ bytecodes: [
/* 53 S> */ B(Return), /* 53 S> */ B(Return),
/* 69 S> */ B(LdaSmi), I8(-20), /* 69 S> */ B(LdaSmi), I8(-20),
/* 80 S> */ B(Return), /* 80 S> */ B(Return),
B(LdaUndefined),
/* 85 S> */ B(Return),
] ]
constant pool: [ constant pool: [
] ]
...@@ -494,7 +486,7 @@ snippet: " ...@@ -494,7 +486,7 @@ snippet: "
" "
frame size: 0 frame size: 0
parameter count: 3 parameter count: 3
bytecode array length: 36 bytecode array length: 34
bytecodes: [ bytecodes: [
/* 10 E> */ B(StackCheck), /* 10 E> */ B(StackCheck),
/* 21 S> */ B(Ldar), R(arg1), /* 21 S> */ B(Ldar), R(arg1),
...@@ -515,8 +507,6 @@ bytecodes: [ ...@@ -515,8 +507,6 @@ bytecodes: [
/* 102 S> */ B(Return), /* 102 S> */ B(Return),
/* 118 S> */ B(LdaSmi), I8(-1), /* 118 S> */ B(LdaSmi), I8(-1),
/* 128 S> */ B(Return), /* 128 S> */ B(Return),
B(LdaUndefined),
/* 133 S> */ B(Return),
] ]
constant pool: [ constant pool: [
] ]
......
...@@ -374,7 +374,7 @@ snippet: " ...@@ -374,7 +374,7 @@ snippet: "
" "
frame size: 8 frame size: 8
parameter count: 1 parameter count: 1
bytecode array length: 85 bytecode array length: 81
bytecodes: [ bytecodes: [
B(Mov), R(closure), R(3), B(Mov), R(closure), R(3),
B(Mov), R(this), R(4), B(Mov), R(this), R(4),
...@@ -400,7 +400,6 @@ bytecodes: [ ...@@ -400,7 +400,6 @@ bytecodes: [
B(Mov), R(0), R(4), B(Mov), R(0), R(4),
/* 49 E> */ B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionResolve), R(4), U8(3), /* 49 E> */ B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionResolve), R(4), U8(3),
/* 67 S> */ B(Return), /* 67 S> */ B(Return),
B(Jump), U8(30),
B(Star), R(4), B(Star), R(4),
B(CreateCatchContext), R(4), U8(0), B(CreateCatchContext), R(4), U8(0),
B(Star), R(3), B(Star), R(3),
...@@ -414,15 +413,13 @@ bytecodes: [ ...@@ -414,15 +413,13 @@ bytecodes: [
B(Star), R(7), B(Star), R(7),
B(Mov), R(0), R(5), B(Mov), R(0), R(5),
B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionReject), R(5), U8(3), B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionReject), R(5), U8(3),
/* 67 S> */ B(Return),
B(LdaUndefined),
/* 67 S> */ B(Return), /* 67 S> */ B(Return),
] ]
constant pool: [ constant pool: [
SCOPE_INFO_TYPE, SCOPE_INFO_TYPE,
] ]
handlers: [ handlers: [
[16, 53, 55], [16, 53, 53],
] ]
--- ---
...@@ -434,7 +431,7 @@ snippet: " ...@@ -434,7 +431,7 @@ snippet: "
" "
frame size: 7 frame size: 7
parameter count: 1 parameter count: 1
bytecode array length: 121 bytecode array length: 117
bytecodes: [ bytecodes: [
B(SwitchOnGeneratorState), R(0), U8(0), U8(1), B(SwitchOnGeneratorState), R(0), U8(0), U8(1),
B(Mov), R(closure), R(2), B(Mov), R(closure), R(2),
...@@ -473,7 +470,6 @@ bytecodes: [ ...@@ -473,7 +470,6 @@ bytecodes: [
B(Mov), R(0), R(3), B(Mov), R(0), R(3),
/* 49 E> */ B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionResolve), R(3), U8(3), /* 49 E> */ B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionResolve), R(3), U8(3),
/* 61 S> */ B(Return), /* 61 S> */ B(Return),
B(Jump), U8(30),
B(Star), R(3), B(Star), R(3),
B(CreateCatchContext), R(3), U8(1), B(CreateCatchContext), R(3), U8(1),
B(Star), R(2), B(Star), R(2),
...@@ -487,8 +483,6 @@ bytecodes: [ ...@@ -487,8 +483,6 @@ bytecodes: [
B(Star), R(6), B(Star), R(6),
B(Mov), R(0), R(4), B(Mov), R(0), R(4),
B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionReject), R(4), U8(3), B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionReject), R(4), U8(3),
/* 61 S> */ B(Return),
B(LdaUndefined),
/* 61 S> */ B(Return), /* 61 S> */ B(Return),
] ]
constant pool: [ constant pool: [
...@@ -496,6 +490,6 @@ constant pool: [ ...@@ -496,6 +490,6 @@ constant pool: [
SCOPE_INFO_TYPE, SCOPE_INFO_TYPE,
] ]
handlers: [ handlers: [
[20, 89, 91], [20, 89, 89],
] ]
...@@ -11,13 +11,12 @@ snippet: " ...@@ -11,13 +11,12 @@ snippet: "
" "
frame size: 2 frame size: 2
parameter count: 1 parameter count: 1
bytecode array length: 27 bytecode array length: 23
bytecodes: [ bytecodes: [
/* 30 E> */ B(StackCheck), /* 30 E> */ B(StackCheck),
B(Mov), R(context), R(0), B(Mov), R(context), R(0),
/* 40 S> */ B(LdaSmi), I8(1), /* 40 S> */ B(LdaSmi), I8(1),
/* 49 S> */ B(Return), /* 49 S> */ B(Return),
B(Jump), U8(18),
B(Star), R(1), B(Star), R(1),
B(CreateCatchContext), R(1), U8(0), B(CreateCatchContext), R(1), U8(0),
B(Star), R(0), B(Star), R(0),
...@@ -27,14 +26,12 @@ bytecodes: [ ...@@ -27,14 +26,12 @@ bytecodes: [
B(PushContext), R(1), B(PushContext), R(1),
/* 63 S> */ B(LdaSmi), I8(2), /* 63 S> */ B(LdaSmi), I8(2),
/* 72 S> */ B(Return), /* 72 S> */ B(Return),
B(LdaUndefined),
/* 75 S> */ B(Return),
] ]
constant pool: [ constant pool: [
SCOPE_INFO_TYPE, SCOPE_INFO_TYPE,
] ]
handlers: [ handlers: [
[4, 7, 9], [4, 7, 7],
] ]
--- ---
......
...@@ -1528,17 +1528,18 @@ TEST(InterpreterJumps) { ...@@ -1528,17 +1528,18 @@ TEST(InterpreterJumps) {
NewFeedbackMetadata(isolate, &feedback_spec); NewFeedbackMetadata(isolate, &feedback_spec);
Register reg(0), scratch(1); Register reg(0), scratch(1);
BytecodeLabel label[3]; BytecodeLoopHeader loop_header;
BytecodeLabel label[2];
builder.LoadLiteral(Smi::zero()) builder.LoadLiteral(Smi::zero())
.StoreAccumulatorInRegister(reg) .StoreAccumulatorInRegister(reg)
.Jump(&label[1]); .Jump(&label[0]);
SetRegister(builder, reg, 1024, scratch).Bind(&label[0]); SetRegister(builder, reg, 1024, scratch).Bind(&loop_header);
IncrementRegister(builder, reg, 1, scratch, GetIndex(slot)).Jump(&label[2]); IncrementRegister(builder, reg, 1, scratch, GetIndex(slot)).Jump(&label[1]);
SetRegister(builder, reg, 2048, scratch).Bind(&label[1]); SetRegister(builder, reg, 2048, scratch).Bind(&label[0]);
IncrementRegister(builder, reg, 2, scratch, GetIndex(slot1)) IncrementRegister(builder, reg, 2, scratch, GetIndex(slot1))
.JumpLoop(&label[0], 0); .JumpLoop(&loop_header, 0);
SetRegister(builder, reg, 4096, scratch).Bind(&label[2]); SetRegister(builder, reg, 4096, scratch).Bind(&label[1]);
IncrementRegister(builder, reg, 4, scratch, GetIndex(slot2)) IncrementRegister(builder, reg, 4, scratch, GetIndex(slot2))
.LoadAccumulatorWithRegister(reg) .LoadAccumulatorWithRegister(reg)
.Return(); .Return();
...@@ -1667,6 +1668,8 @@ TEST(InterpreterJumpConstantWith16BitOperand) { ...@@ -1667,6 +1668,8 @@ TEST(InterpreterJumpConstantWith16BitOperand) {
builder.LoadLiteral(Smi::zero()); builder.LoadLiteral(Smi::zero());
builder.StoreAccumulatorInRegister(reg); builder.StoreAccumulatorInRegister(reg);
// Conditional jump to the fake label, to force both basic blocks to be live.
builder.JumpIfTrue(ToBooleanMode::kConvertToBoolean, &fake);
// Consume all 8-bit operands // Consume all 8-bit operands
for (int i = 1; i <= 256; i++) { for (int i = 1; i <= 256; i++) {
builder.LoadLiteral(i + 0.5); builder.LoadLiteral(i + 0.5);
......
// Copyright 2019 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.
// Flags: --allow-natives-syntax
{
for(let i = 0; i < 10; ++i){
try{
// Carefully constructed by a fuzzer to use a new register for s(), whose
// write is dead due to the unconditional throw after s()=N, but which is
// read in the ({...g}) call, which therefore must also be marked dead and
// elided.
with(f&&g&&(s()=N)({...g})){}
} catch {}
%OptimizeOsr();
}
}
...@@ -280,10 +280,12 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) { ...@@ -280,10 +280,12 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
// Short jumps with Imm8 operands // Short jumps with Imm8 operands
{ {
BytecodeLabel start, after_jump1, after_jump2, after_jump3, after_jump4, BytecodeLoopHeader loop_header;
BytecodeLabel after_jump1, after_jump2, after_jump3, after_jump4,
after_jump5, after_jump6, after_jump7, after_jump8, after_jump9, after_jump5, after_jump6, after_jump7, after_jump8, after_jump9,
after_jump10; after_jump10, after_loop;
builder.Bind(&start) builder.JumpIfNull(&after_loop)
.Bind(&loop_header)
.Jump(&after_jump1) .Jump(&after_jump1)
.Bind(&after_jump1) .Bind(&after_jump1)
.JumpIfNull(&after_jump2) .JumpIfNull(&after_jump2)
...@@ -304,14 +306,16 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) { ...@@ -304,14 +306,16 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
.Bind(&after_jump9) .Bind(&after_jump9)
.JumpIfFalse(ToBooleanMode::kAlreadyBoolean, &after_jump10) .JumpIfFalse(ToBooleanMode::kAlreadyBoolean, &after_jump10)
.Bind(&after_jump10) .Bind(&after_jump10)
.JumpLoop(&start, 0); .JumpLoop(&loop_header, 0)
.Bind(&after_loop);
} }
// Longer jumps with constant operands
BytecodeLabel end[10]; BytecodeLabel end[10];
{ {
// Longer jumps with constant operands
BytecodeLabel after_jump; BytecodeLabel after_jump;
builder.Jump(&end[0]) builder.JumpIfNull(&after_jump)
.Jump(&end[0])
.Bind(&after_jump) .Bind(&after_jump)
.JumpIfTrue(ToBooleanMode::kConvertToBoolean, &end[1]) .JumpIfTrue(ToBooleanMode::kConvertToBoolean, &end[1])
.JumpIfTrue(ToBooleanMode::kAlreadyBoolean, &end[2]) .JumpIfTrue(ToBooleanMode::kAlreadyBoolean, &end[2])
...@@ -337,10 +341,9 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) { ...@@ -337,10 +341,9 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
// Emit throw and re-throw in it's own basic block so that the rest of the // Emit throw and re-throw in it's own basic block so that the rest of the
// code isn't omitted due to being dead. // code isn't omitted due to being dead.
BytecodeLabel after_throw; BytecodeLabel after_throw, after_rethrow;
builder.Throw().Bind(&after_throw); builder.JumpIfNull(&after_throw).Throw().Bind(&after_throw);
BytecodeLabel after_rethrow; builder.JumpIfNull(&after_rethrow).ReThrow().Bind(&after_rethrow);
builder.ReThrow().Bind(&after_rethrow);
builder.ForInEnumerate(reg) builder.ForInEnumerate(reg)
.ForInPrepare(triple, 1) .ForInPrepare(triple, 1)
...@@ -414,10 +417,10 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) { ...@@ -414,10 +417,10 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
builder.Debugger(); builder.Debugger();
// Emit abort bytecode. // Emit abort bytecode.
{ BytecodeLabel after_abort;
BytecodeLabel after; builder.JumpIfNull(&after_abort)
builder.Abort(AbortReason::kOperandIsASmi).Bind(&after); .Abort(AbortReason::kOperandIsASmi)
} .Bind(&after_abort);
// Insert dummy ops to force longer jumps. // Insert dummy ops to force longer jumps.
for (int i = 0; i < 256; i++) { for (int i = 0; i < 256; i++) {
...@@ -568,10 +571,11 @@ TEST_F(BytecodeArrayBuilderTest, ForwardJumps) { ...@@ -568,10 +571,11 @@ TEST_F(BytecodeArrayBuilderTest, ForwardJumps) {
Register reg(0); Register reg(0);
BytecodeLabel far0, far1, far2, far3, far4; BytecodeLabel far0, far1, far2, far3, far4;
BytecodeLabel near0, near1, near2, near3, near4; BytecodeLabel near0, near1, near2, near3, near4;
BytecodeLabel after_jump0, after_jump1; BytecodeLabel after_jump_near0, after_jump_far0;
builder.Jump(&near0) builder.JumpIfNull(&after_jump_near0)
.Bind(&after_jump0) .Jump(&near0)
.Bind(&after_jump_near0)
.CompareOperation(Token::Value::EQ, reg, 1) .CompareOperation(Token::Value::EQ, reg, 1)
.JumpIfTrue(ToBooleanMode::kAlreadyBoolean, &near1) .JumpIfTrue(ToBooleanMode::kAlreadyBoolean, &near1)
.CompareOperation(Token::Value::EQ, reg, 2) .CompareOperation(Token::Value::EQ, reg, 2)
...@@ -585,8 +589,9 @@ TEST_F(BytecodeArrayBuilderTest, ForwardJumps) { ...@@ -585,8 +589,9 @@ TEST_F(BytecodeArrayBuilderTest, ForwardJumps) {
.Bind(&near2) .Bind(&near2)
.Bind(&near3) .Bind(&near3)
.Bind(&near4) .Bind(&near4)
.JumpIfNull(&after_jump_far0)
.Jump(&far0) .Jump(&far0)
.Bind(&after_jump1) .Bind(&after_jump_far0)
.CompareOperation(Token::Value::EQ, reg, 3) .CompareOperation(Token::Value::EQ, reg, 3)
.JumpIfTrue(ToBooleanMode::kAlreadyBoolean, &far1) .JumpIfTrue(ToBooleanMode::kAlreadyBoolean, &far1)
.CompareOperation(Token::Value::EQ, reg, 4) .CompareOperation(Token::Value::EQ, reg, 4)
...@@ -602,9 +607,13 @@ TEST_F(BytecodeArrayBuilderTest, ForwardJumps) { ...@@ -602,9 +607,13 @@ TEST_F(BytecodeArrayBuilderTest, ForwardJumps) {
builder.Return(); builder.Return();
Handle<BytecodeArray> array = builder.ToBytecodeArray(isolate()); Handle<BytecodeArray> array = builder.ToBytecodeArray(isolate());
DCHECK_EQ(array->length(), 44 + kFarJumpDistance - 22 + 1); DCHECK_EQ(array->length(), 48 + kFarJumpDistance - 22 + 1);
BytecodeArrayIterator iterator(array); BytecodeArrayIterator iterator(array);
// Ignore JumpIfNull operation.
iterator.Advance();
CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump);
CHECK_EQ(iterator.GetUnsignedImmediateOperand(0), 22); CHECK_EQ(iterator.GetUnsignedImmediateOperand(0), 22);
iterator.Advance(); iterator.Advance();
...@@ -637,6 +646,9 @@ TEST_F(BytecodeArrayBuilderTest, ForwardJumps) { ...@@ -637,6 +646,9 @@ TEST_F(BytecodeArrayBuilderTest, ForwardJumps) {
CHECK_EQ(iterator.GetUnsignedImmediateOperand(0), 2); CHECK_EQ(iterator.GetUnsignedImmediateOperand(0), 2);
iterator.Advance(); iterator.Advance();
// Ignore JumpIfNull operation.
iterator.Advance();
CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpConstant); CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpConstant);
CHECK_EQ(iterator.GetConstantForIndexOperand(0), CHECK_EQ(iterator.GetConstantForIndexOperand(0),
Smi::FromInt(kFarJumpDistance)); Smi::FromInt(kFarJumpDistance));
...@@ -682,11 +694,22 @@ TEST_F(BytecodeArrayBuilderTest, BackwardJumps) { ...@@ -682,11 +694,22 @@ TEST_F(BytecodeArrayBuilderTest, BackwardJumps) {
Register reg(0); Register reg(0);
BytecodeLabel label0; BytecodeLabel end;
builder.Bind(&label0).JumpLoop(&label0, 0); builder.JumpIfNull(&end);
BytecodeLabel after_loop;
// Conditional jump to force the code after the JumpLoop to be live.
// Technically this jump is illegal because it's jumping into the middle of
// the subsequent loops, but that's ok for this unit test.
BytecodeLoopHeader loop_header;
builder.JumpIfNull(&after_loop)
.Bind(&loop_header)
.JumpLoop(&loop_header, 0)
.Bind(&after_loop);
for (int i = 0; i < 42; i++) { for (int i = 0; i < 42; i++) {
BytecodeLabel after_jump; BytecodeLabel after_loop;
builder.JumpLoop(&label0, 0).Bind(&after_jump); // Conditional jump to force the code after the JumpLoop to be live.
builder.JumpIfNull(&after_loop).JumpLoop(&loop_header, 0).Bind(&after_loop);
} }
// Add padding to force wide backwards jumps. // Add padding to force wide backwards jumps.
...@@ -694,21 +717,28 @@ TEST_F(BytecodeArrayBuilderTest, BackwardJumps) { ...@@ -694,21 +717,28 @@ TEST_F(BytecodeArrayBuilderTest, BackwardJumps) {
builder.Debugger(); builder.Debugger();
} }
builder.JumpLoop(&label0, 0); builder.JumpLoop(&loop_header, 0);
BytecodeLabel end;
builder.Bind(&end); builder.Bind(&end);
builder.Return(); builder.Return();
Handle<BytecodeArray> array = builder.ToBytecodeArray(isolate()); Handle<BytecodeArray> array = builder.ToBytecodeArray(isolate());
BytecodeArrayIterator iterator(array); BytecodeArrayIterator iterator(array);
// Ignore the JumpIfNull to the end
iterator.Advance();
// Ignore the JumpIfNull to after the first JumpLoop
iterator.Advance();
CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpLoop); CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpLoop);
CHECK_EQ(iterator.GetUnsignedImmediateOperand(0), 0); CHECK_EQ(iterator.GetUnsignedImmediateOperand(0), 0);
iterator.Advance(); iterator.Advance();
for (unsigned i = 0; i < 42; i++) { for (unsigned i = 0; i < 42; i++) {
// Ignore the JumpIfNull to after the JumpLoop
iterator.Advance();
CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpLoop); CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpLoop);
CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle); CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
// offset of 3 (because kJumpLoop takes two immediate operands) // offset of 5 (because kJumpLoop takes two immediate operands and
CHECK_EQ(iterator.GetUnsignedImmediateOperand(0), i * 3 + 3); // JumpIfNull takes 1)
CHECK_EQ(iterator.GetUnsignedImmediateOperand(0), i * 5 + 5);
iterator.Advance(); iterator.Advance();
} }
// Check padding to force wide backwards jumps. // Check padding to force wide backwards jumps.
...@@ -718,7 +748,7 @@ TEST_F(BytecodeArrayBuilderTest, BackwardJumps) { ...@@ -718,7 +748,7 @@ TEST_F(BytecodeArrayBuilderTest, BackwardJumps) {
} }
CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpLoop); CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpLoop);
CHECK_EQ(iterator.current_operand_scale(), OperandScale::kDouble); CHECK_EQ(iterator.current_operand_scale(), OperandScale::kDouble);
CHECK_EQ(iterator.GetUnsignedImmediateOperand(0), 386); CHECK_EQ(iterator.GetUnsignedImmediateOperand(0), 42 * 5 + 256 + 4);
iterator.Advance(); iterator.Advance();
CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn); CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn);
iterator.Advance(); iterator.Advance();
...@@ -821,71 +851,6 @@ TEST_F(BytecodeArrayBuilderTest, WideSwitch) { ...@@ -821,71 +851,6 @@ TEST_F(BytecodeArrayBuilderTest, WideSwitch) {
CHECK(iterator.done()); CHECK(iterator.done());
} }
TEST_F(BytecodeArrayBuilderTest, LabelReuse) {
BytecodeArrayBuilder builder(zone(), 1, 0);
// Labels can only have 1 forward reference, but
// can be referred to mulitple times once bound.
BytecodeLabel label, after_jump0, after_jump1;
builder.Jump(&label)
.Bind(&label)
.JumpLoop(&label, 0)
.Bind(&after_jump0)
.JumpLoop(&label, 0)
.Bind(&after_jump1)
.Return();
Handle<BytecodeArray> array = builder.ToBytecodeArray(isolate());
BytecodeArrayIterator iterator(array);
CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump);
CHECK_EQ(iterator.GetUnsignedImmediateOperand(0), 2);
iterator.Advance();
CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpLoop);
CHECK_EQ(iterator.GetUnsignedImmediateOperand(0), 0);
iterator.Advance();
CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpLoop);
CHECK_EQ(iterator.GetUnsignedImmediateOperand(0), 3);
iterator.Advance();
CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn);
iterator.Advance();
CHECK(iterator.done());
}
TEST_F(BytecodeArrayBuilderTest, LabelAddressReuse) {
static const int kRepeats = 3;
BytecodeArrayBuilder builder(zone(), 1, 0);
for (int i = 0; i < kRepeats; i++) {
BytecodeLabel label, after_jump0, after_jump1;
builder.Jump(&label)
.Bind(&label)
.JumpLoop(&label, 0)
.Bind(&after_jump0)
.JumpLoop(&label, 0)
.Bind(&after_jump1);
}
builder.Return();
Handle<BytecodeArray> array = builder.ToBytecodeArray(isolate());
BytecodeArrayIterator iterator(array);
for (int i = 0; i < kRepeats; i++) {
CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump);
CHECK_EQ(iterator.GetUnsignedImmediateOperand(0), 2);
iterator.Advance();
CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpLoop);
CHECK_EQ(iterator.GetUnsignedImmediateOperand(0), 0);
iterator.Advance();
CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpLoop);
CHECK_EQ(iterator.GetUnsignedImmediateOperand(0), 3);
iterator.Advance();
}
CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn);
iterator.Advance();
CHECK(iterator.done());
}
} // namespace interpreter } // namespace interpreter
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
...@@ -49,8 +49,8 @@ class BytecodeArrayWriterUnittest : public TestWithIsolateAndZone { ...@@ -49,8 +49,8 @@ class BytecodeArrayWriterUnittest : public TestWithIsolateAndZone {
void WriteJump(Bytecode bytecode, BytecodeLabel* label, void WriteJump(Bytecode bytecode, BytecodeLabel* label,
BytecodeSourceInfo info = BytecodeSourceInfo()); BytecodeSourceInfo info = BytecodeSourceInfo());
void WriteJumpLoop(Bytecode bytecode, BytecodeLabel* label, int depth, void WriteJumpLoop(Bytecode bytecode, BytecodeLoopHeader* loop_header,
BytecodeSourceInfo info = BytecodeSourceInfo()); 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(); }
...@@ -105,10 +105,11 @@ void BytecodeArrayWriterUnittest::WriteJump(Bytecode bytecode, ...@@ -105,10 +105,11 @@ void BytecodeArrayWriterUnittest::WriteJump(Bytecode bytecode,
} }
void BytecodeArrayWriterUnittest::WriteJumpLoop(Bytecode bytecode, void BytecodeArrayWriterUnittest::WriteJumpLoop(Bytecode bytecode,
BytecodeLabel* label, int depth, BytecodeLoopHeader* loop_header,
int depth,
BytecodeSourceInfo info) { BytecodeSourceInfo info) {
BytecodeNode node(bytecode, 0, depth, info); BytecodeNode node(bytecode, 0, depth, info);
writer()->WriteJump(&node, label); writer()->WriteJumpLoop(&node, loop_header);
} }
TEST_F(BytecodeArrayWriterUnittest, SimpleExample) { TEST_F(BytecodeArrayWriterUnittest, SimpleExample) {
...@@ -195,7 +196,8 @@ TEST_F(BytecodeArrayWriterUnittest, ComplexExample) { ...@@ -195,7 +196,8 @@ TEST_F(BytecodeArrayWriterUnittest, ComplexExample) {
{0, 30, false}, {1, 42, true}, {3, 42, false}, {6, 68, true}, {0, 30, false}, {1, 42, true}, {3, 42, false}, {6, 68, true},
{18, 63, true}, {32, 54, false}, {37, 85, true}, {46, 85, true}}; {18, 63, true}, {32, 54, false}, {37, 85, true}, {46, 85, true}};
BytecodeLabel back_jump, jump_for_in, jump_end_1, jump_end_2, jump_end_3; BytecodeLoopHeader loop_header;
BytecodeLabel jump_for_in, jump_end_1, jump_end_2, jump_end_3;
Write(Bytecode::kStackCheck, {30, false}); Write(Bytecode::kStackCheck, {30, false});
Write(Bytecode::kLdaConstant, U8(0), {42, true}); Write(Bytecode::kLdaConstant, U8(0), {42, true});
...@@ -206,7 +208,7 @@ TEST_F(BytecodeArrayWriterUnittest, ComplexExample) { ...@@ -206,7 +208,7 @@ TEST_F(BytecodeArrayWriterUnittest, ComplexExample) {
Write(Bytecode::kForInPrepare, R(3), U8(4)); Write(Bytecode::kForInPrepare, R(3), U8(4));
Write(Bytecode::kLdaZero); Write(Bytecode::kLdaZero);
Write(Bytecode::kStar, R(7)); Write(Bytecode::kStar, R(7));
writer()->BindLabel(&back_jump); writer()->BindLoopHeader(&loop_header);
Write(Bytecode::kForInContinue, R(7), R(6), {63, true}); Write(Bytecode::kForInContinue, R(7), R(6), {63, true});
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));
...@@ -219,7 +221,7 @@ TEST_F(BytecodeArrayWriterUnittest, ComplexExample) { ...@@ -219,7 +221,7 @@ TEST_F(BytecodeArrayWriterUnittest, ComplexExample) {
writer()->BindLabel(&jump_for_in); writer()->BindLabel(&jump_for_in);
Write(Bytecode::kForInStep, R(7)); Write(Bytecode::kForInStep, R(7));
Write(Bytecode::kStar, R(7)); Write(Bytecode::kStar, R(7));
WriteJumpLoop(Bytecode::kJumpLoop, &back_jump, 0); WriteJumpLoop(Bytecode::kJumpLoop, &loop_header, 0);
writer()->BindLabel(&jump_end_1); writer()->BindLabel(&jump_end_1);
writer()->BindLabel(&jump_end_2); writer()->BindLabel(&jump_end_2);
writer()->BindLabel(&jump_end_3); writer()->BindLabel(&jump_end_3);
...@@ -328,7 +330,9 @@ TEST_F(BytecodeArrayWriterUnittest, DeadcodeElimination) { ...@@ -328,7 +330,9 @@ TEST_F(BytecodeArrayWriterUnittest, DeadcodeElimination) {
Write(Bytecode::kLdaSmi, 127); // Dead code. Write(Bytecode::kLdaSmi, 127); // Dead code.
WriteJump(Bytecode::kJumpIfFalse, &after_conditional_jump); // Dead code. WriteJump(Bytecode::kJumpIfFalse, &after_conditional_jump); // Dead code.
writer()->BindLabel(&after_jump); writer()->BindLabel(&after_jump);
writer()->BindLabel(&after_conditional_jump); // We would bind the after_conditional_jump label here, but the jump to it is
// dead.
CHECK(!after_conditional_jump.has_referrer_jump());
Write(Bytecode::kLdaSmi, 127, {65, true}); Write(Bytecode::kLdaSmi, 127, {65, true});
WriteJump(Bytecode::kJumpIfFalse, &after_return); WriteJump(Bytecode::kJumpIfFalse, &after_return);
Write(Bytecode::kReturn, {75, true}); Write(Bytecode::kReturn, {75, true});
......
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