summaryrefslogtreecommitdiff
path: root/deps/v8/src/interpreter/bytecode-array-writer.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/interpreter/bytecode-array-writer.cc')
-rw-r--r--deps/v8/src/interpreter/bytecode-array-writer.cc181
1 files changed, 109 insertions, 72 deletions
diff --git a/deps/v8/src/interpreter/bytecode-array-writer.cc b/deps/v8/src/interpreter/bytecode-array-writer.cc
index a563ff4fc3..05f655b71a 100644
--- a/deps/v8/src/interpreter/bytecode-array-writer.cc
+++ b/deps/v8/src/interpreter/bytecode-array-writer.cc
@@ -11,6 +11,7 @@
#include "src/interpreter/bytecode-register.h"
#include "src/interpreter/bytecode-source-info.h"
#include "src/interpreter/constant-array-builder.h"
+#include "src/interpreter/handler-table-builder.h"
#include "src/log.h"
#include "src/objects-inl.h"
@@ -45,16 +46,20 @@ Handle<BytecodeArray> BytecodeArrayWriter::ToBytecodeArray(
int frame_size = register_count * kSystemPointerSize;
Handle<FixedArray> constant_pool =
constant_array_builder()->ToFixedArray(isolate);
- Handle<ByteArray> source_position_table =
- source_position_table_builder()->ToSourcePositionTable(isolate);
Handle<BytecodeArray> bytecode_array = isolate->factory()->NewBytecodeArray(
bytecode_size, &bytecodes()->front(), frame_size, parameter_count,
constant_pool);
bytecode_array->set_handler_table(*handler_table);
- bytecode_array->set_source_position_table(*source_position_table);
- LOG_CODE_EVENT(isolate, CodeLinePosInfoRecordEvent(
- bytecode_array->GetFirstBytecodeAddress(),
- *source_position_table));
+ // TODO(v8:8510): Need to support native functions that should always have
+ // source positions suppressed and should write empty_byte_array here.
+ if (!source_position_table_builder_.Omit()) {
+ Handle<ByteArray> source_position_table =
+ source_position_table_builder()->ToSourcePositionTable(isolate);
+ bytecode_array->set_source_position_table(*source_position_table);
+ LOG_CODE_EVENT(isolate, CodeLinePosInfoRecordEvent(
+ bytecode_array->GetFirstBytecodeAddress(),
+ *source_position_table));
+ }
return bytecode_array;
}
@@ -70,10 +75,8 @@ void BytecodeArrayWriter::Write(BytecodeNode* node) {
}
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.
UpdateExitSeenInBlock(node->bytecode());
MaybeElideLastBytecode(node->bytecode(), node->source_info().is_valid());
@@ -82,12 +85,22 @@ void BytecodeArrayWriter::WriteJump(BytecodeNode* node, BytecodeLabel* 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,
BytecodeJumpTable* jump_table) {
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.
UpdateExitSeenInBlock(node->bytecode());
MaybeElideLastBytecode(node->bytecode(), node->source_info().is_valid());
@@ -97,30 +110,18 @@ void BytecodeArrayWriter::WriteSwitch(BytecodeNode* node,
}
void BytecodeArrayWriter::BindLabel(BytecodeLabel* label) {
+ DCHECK(label->has_referrer_jump());
size_t current_offset = bytecodes()->size();
- if (label->is_forward_target()) {
- // An earlier jump instruction refers to this label. Update it's location.
- PatchJump(current_offset, label->offset());
- // Now treat as if the label will only be back referred to.
- }
- label->bind_to(current_offset);
- InvalidateLastBytecode();
- exit_seen_in_block_ = false; // Starting a new basic block.
+ // Update the jump instruction's location.
+ PatchJump(current_offset, label->jump_offset());
+ label->bind();
+ StartBasicBlock();
}
-void BytecodeArrayWriter::BindLabel(const BytecodeLabel& target,
- BytecodeLabel* label) {
- DCHECK(!label->is_bound());
- DCHECK(target.is_bound());
- 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::BindLoopHeader(BytecodeLoopHeader* loop_header) {
+ size_t current_offset = bytecodes()->size();
+ loop_header->bind_to(current_offset);
+ StartBasicBlock();
}
void BytecodeArrayWriter::BindJumpTableEntry(BytecodeJumpTable* jump_table,
@@ -135,8 +136,37 @@ void BytecodeArrayWriter::BindJumpTableEntry(BytecodeJumpTable* jump_table,
Smi::FromInt(static_cast<int>(relative_jump)));
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();
+ 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; // Starting a new basic block.
+ exit_seen_in_block_ = false;
}
void BytecodeArrayWriter::UpdateSourcePositionTable(
@@ -374,50 +404,57 @@ void BytecodeArrayWriter::PatchJump(size_t jump_target, size_t jump_location) {
unbound_jumps_--;
}
+void BytecodeArrayWriter::EmitJumpLoop(BytecodeNode* node,
+ BytecodeLoopHeader* loop_header) {
+ DCHECK_EQ(node->bytecode(), Bytecode::kJumpLoop);
+ DCHECK_EQ(0u, node->operand(0));
+
+ size_t current_offset = bytecodes()->size();
+
+ CHECK_GE(current_offset, loop_header->offset());
+ CHECK_LE(current_offset, static_cast<size_t>(kMaxUInt32));
+ // Label has been bound already so this is a backwards jump.
+ uint32_t delta =
+ static_cast<uint32_t>(current_offset - loop_header->offset());
+ OperandScale operand_scale = Bytecodes::ScaleForUnsignedOperand(delta);
+ if (operand_scale > OperandScale::kSingle) {
+ // Adjust for scaling byte prefix for wide jump offset.
+ delta += 1;
+ }
+ node->update_operand0(delta);
+ EmitBytecode(node);
+}
+
void BytecodeArrayWriter::EmitJump(BytecodeNode* node, BytecodeLabel* label) {
- DCHECK(Bytecodes::IsJump(node->bytecode()));
+ DCHECK(Bytecodes::IsForwardJump(node->bytecode()));
DCHECK_EQ(0u, node->operand(0));
size_t current_offset = bytecodes()->size();
- if (label->is_bound()) {
- CHECK_GE(current_offset, label->offset());
- CHECK_LE(current_offset, static_cast<size_t>(kMaxUInt32));
- // Label has been bound already so this is a backwards jump.
- uint32_t delta = static_cast<uint32_t>(current_offset - label->offset());
- OperandScale operand_scale = Bytecodes::ScaleForUnsignedOperand(delta);
- if (operand_scale > OperandScale::kSingle) {
- // Adjust for scaling byte prefix for wide jump offset.
- delta += 1;
- }
- DCHECK_EQ(Bytecode::kJumpLoop, node->bytecode());
- node->update_operand0(delta);
- } else {
- // 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
- // reservation in the constant pool so the jump can be patched
- // when the label is bound. The reservation means the maximum size
- // of the operand for the constant is known and the jump can
- // be emitted into the bytecode stream with space for the operand.
- unbound_jumps_++;
- label->set_referrer(current_offset);
- OperandSize reserved_operand_size =
- constant_array_builder()->CreateReservedEntry();
- DCHECK_NE(Bytecode::kJumpLoop, node->bytecode());
- switch (reserved_operand_size) {
- case OperandSize::kNone:
- UNREACHABLE();
- break;
- case OperandSize::kByte:
- node->update_operand0(k8BitJumpPlaceholder);
- break;
- case OperandSize::kShort:
- node->update_operand0(k16BitJumpPlaceholder);
- break;
- case OperandSize::kQuad:
- node->update_operand0(k32BitJumpPlaceholder);
- break;
- }
+ // 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
+ // reservation in the constant pool so the jump can be patched
+ // when the label is bound. The reservation means the maximum size
+ // of the operand for the constant is known and the jump can
+ // be emitted into the bytecode stream with space for the operand.
+ unbound_jumps_++;
+ label->set_referrer(current_offset);
+ OperandSize reserved_operand_size =
+ constant_array_builder()->CreateReservedEntry();
+ DCHECK_NE(Bytecode::kJumpLoop, node->bytecode());
+ switch (reserved_operand_size) {
+ case OperandSize::kNone:
+ UNREACHABLE();
+ break;
+ case OperandSize::kByte:
+ node->update_operand0(k8BitJumpPlaceholder);
+ break;
+ case OperandSize::kShort:
+ node->update_operand0(k16BitJumpPlaceholder);
+ break;
+ case OperandSize::kQuad:
+ node->update_operand0(k32BitJumpPlaceholder);
+ break;
}
EmitBytecode(node);
}