• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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