diff options
Diffstat (limited to 'deps/v8/src/interpreter/bytecode-array-writer.cc')
-rw-r--r-- | deps/v8/src/interpreter/bytecode-array-writer.cc | 181 |
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); } |