1 // Copyright 2015 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef V8_INTERPRETER_BYTECODE_ARRAY_WRITER_H_ 6 #define V8_INTERPRETER_BYTECODE_ARRAY_WRITER_H_ 7 8 #include "src/base/compiler-specific.h" 9 #include "src/codegen/source-position-table.h" 10 #include "src/common/globals.h" 11 #include "src/interpreter/bytecodes.h" 12 13 namespace v8 { 14 namespace internal { 15 16 class BytecodeArray; 17 class SourcePositionTableBuilder; 18 19 namespace interpreter { 20 21 class BytecodeLabel; 22 class BytecodeLoopHeader; 23 class BytecodeNode; 24 class BytecodeJumpTable; 25 class ConstantArrayBuilder; 26 class HandlerTableBuilder; 27 28 namespace bytecode_array_writer_unittest { 29 class BytecodeArrayWriterUnittest; 30 } // namespace bytecode_array_writer_unittest 31 32 // Class for emitting bytecode as the final stage of the bytecode 33 // generation pipeline. 34 class V8_EXPORT_PRIVATE BytecodeArrayWriter final { 35 public: 36 BytecodeArrayWriter( 37 Zone* zone, ConstantArrayBuilder* constant_array_builder, 38 SourcePositionTableBuilder::RecordingMode source_position_mode); 39 BytecodeArrayWriter(const BytecodeArrayWriter&) = delete; 40 BytecodeArrayWriter& operator=(const BytecodeArrayWriter&) = delete; 41 42 void Write(BytecodeNode* node); 43 void WriteJump(BytecodeNode* node, BytecodeLabel* label); 44 void WriteJumpLoop(BytecodeNode* node, BytecodeLoopHeader* loop_header); 45 void WriteSwitch(BytecodeNode* node, BytecodeJumpTable* jump_table); 46 void BindLabel(BytecodeLabel* label); 47 void BindLoopHeader(BytecodeLoopHeader* loop_header); 48 void BindJumpTableEntry(BytecodeJumpTable* jump_table, int case_value); 49 void BindHandlerTarget(HandlerTableBuilder* handler_table_builder, 50 int handler_id); 51 void BindTryRegionStart(HandlerTableBuilder* handler_table_builder, 52 int handler_id); 53 void BindTryRegionEnd(HandlerTableBuilder* handler_table_builder, 54 int handler_id); 55 56 void SetFunctionEntrySourcePosition(int position); 57 58 template <typename LocalIsolate> 59 EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE) 60 Handle<BytecodeArray> ToBytecodeArray(LocalIsolate* isolate, 61 int register_count, int parameter_count, 62 Handle<ByteArray> handler_table); 63 64 template <typename LocalIsolate> 65 EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE) 66 Handle<ByteArray> ToSourcePositionTable(LocalIsolate* isolate); 67 68 #ifdef DEBUG 69 // Returns -1 if they match or the offset of the first mismatching byte. 70 int CheckBytecodeMatches(BytecodeArray bytecode); 71 #endif 72 RemainderOfBlockIsDead()73 bool RemainderOfBlockIsDead() const { return exit_seen_in_block_; } 74 75 private: 76 // Maximum sized packed bytecode is comprised of a prefix bytecode, 77 // plus the actual bytecode, plus the maximum number of operands times 78 // the maximum operand size. 79 static const size_t kMaxSizeOfPackedBytecode = 80 2 * sizeof(Bytecode) + 81 Bytecodes::kMaxOperands * static_cast<size_t>(OperandSize::kLast); 82 83 // Constants that act as placeholders for jump operands to be 84 // patched. These have operand sizes that match the sizes of 85 // reserved constant pool entries. 86 const uint32_t k8BitJumpPlaceholder = 0x7f; 87 const uint32_t k16BitJumpPlaceholder = 88 k8BitJumpPlaceholder | (k8BitJumpPlaceholder << 8); 89 const uint32_t k32BitJumpPlaceholder = 90 k16BitJumpPlaceholder | (k16BitJumpPlaceholder << 16); 91 92 void PatchJump(size_t jump_target, size_t jump_location); 93 void PatchJumpWith8BitOperand(size_t jump_location, int delta); 94 void PatchJumpWith16BitOperand(size_t jump_location, int delta); 95 void PatchJumpWith32BitOperand(size_t jump_location, int delta); 96 97 void EmitBytecode(const BytecodeNode* const node); 98 void EmitJump(BytecodeNode* node, BytecodeLabel* label); 99 void EmitJumpLoop(BytecodeNode* node, BytecodeLoopHeader* loop_header); 100 void EmitSwitch(BytecodeNode* node, BytecodeJumpTable* jump_table); 101 void UpdateSourcePositionTable(const BytecodeNode* const node); 102 103 void UpdateExitSeenInBlock(Bytecode bytecode); 104 105 void MaybeElideLastBytecode(Bytecode next_bytecode, bool has_source_info); 106 void InvalidateLastBytecode(); 107 108 void StartBasicBlock(); 109 bytecodes()110 ZoneVector<uint8_t>* bytecodes() { return &bytecodes_; } source_position_table_builder()111 SourcePositionTableBuilder* source_position_table_builder() { 112 return &source_position_table_builder_; 113 } constant_array_builder()114 ConstantArrayBuilder* constant_array_builder() { 115 return constant_array_builder_; 116 } 117 118 ZoneVector<uint8_t> bytecodes_; 119 int unbound_jumps_; 120 SourcePositionTableBuilder source_position_table_builder_; 121 ConstantArrayBuilder* constant_array_builder_; 122 123 Bytecode last_bytecode_; 124 size_t last_bytecode_offset_; 125 bool last_bytecode_had_source_info_; 126 bool elide_noneffectful_bytecodes_; 127 128 bool exit_seen_in_block_; 129 130 friend class bytecode_array_writer_unittest::BytecodeArrayWriterUnittest; 131 }; 132 133 } // namespace interpreter 134 } // namespace internal 135 } // namespace v8 136 137 #endif // V8_INTERPRETER_BYTECODE_ARRAY_WRITER_H_ 138