OLD | NEW |
1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/api.h" | 7 #include "src/api.h" |
8 #include "src/factory.h" | 8 #include "src/factory.h" |
9 #include "src/interpreter/bytecode-array-writer.h" | 9 #include "src/interpreter/bytecode-array-writer.h" |
10 #include "src/interpreter/bytecode-label.h" | 10 #include "src/interpreter/bytecode-label.h" |
(...skipping 10 matching lines...) Expand all Loading... |
21 | 21 |
22 class BytecodeArrayWriterUnittest : public TestWithIsolateAndZone { | 22 class BytecodeArrayWriterUnittest : public TestWithIsolateAndZone { |
23 public: | 23 public: |
24 BytecodeArrayWriterUnittest() | 24 BytecodeArrayWriterUnittest() |
25 : constant_array_builder_(zone(), isolate()->factory()->the_hole_value()), | 25 : constant_array_builder_(zone(), isolate()->factory()->the_hole_value()), |
26 bytecode_array_writer_( | 26 bytecode_array_writer_( |
27 zone(), &constant_array_builder_, | 27 zone(), &constant_array_builder_, |
28 SourcePositionTableBuilder::RECORD_SOURCE_POSITIONS) {} | 28 SourcePositionTableBuilder::RECORD_SOURCE_POSITIONS) {} |
29 ~BytecodeArrayWriterUnittest() override {} | 29 ~BytecodeArrayWriterUnittest() override {} |
30 | 30 |
31 void Write(Bytecode bytecode, BytecodeSourceInfo info = BytecodeSourceInfo()); | 31 void Write(BytecodeNode* node, const BytecodeSourceInfo& info); |
| 32 void Write(Bytecode bytecode, |
| 33 const BytecodeSourceInfo& info = BytecodeSourceInfo()); |
32 void Write(Bytecode bytecode, uint32_t operand0, | 34 void Write(Bytecode bytecode, uint32_t operand0, |
33 BytecodeSourceInfo info = BytecodeSourceInfo()); | 35 const BytecodeSourceInfo& info = BytecodeSourceInfo()); |
34 void Write(Bytecode bytecode, uint32_t operand0, uint32_t operand1, | 36 void Write(Bytecode bytecode, uint32_t operand0, uint32_t operand1, |
35 BytecodeSourceInfo info = BytecodeSourceInfo()); | 37 |
| 38 const BytecodeSourceInfo& info = BytecodeSourceInfo()); |
36 void Write(Bytecode bytecode, uint32_t operand0, uint32_t operand1, | 39 void Write(Bytecode bytecode, uint32_t operand0, uint32_t operand1, |
37 uint32_t operand2, BytecodeSourceInfo info = BytecodeSourceInfo()); | 40 uint32_t operand2, |
| 41 const BytecodeSourceInfo& info = BytecodeSourceInfo()); |
38 void Write(Bytecode bytecode, uint32_t operand0, uint32_t operand1, | 42 void Write(Bytecode bytecode, uint32_t operand0, uint32_t operand1, |
39 uint32_t operand2, uint32_t operand3, | 43 uint32_t operand2, uint32_t operand3, |
40 BytecodeSourceInfo info = BytecodeSourceInfo()); | 44 const BytecodeSourceInfo& info = BytecodeSourceInfo()); |
41 | 45 |
42 void WriteJump(Bytecode bytecode, BytecodeLabel* label, | 46 void WriteJump(Bytecode bytecode, BytecodeLabel* label, |
43 BytecodeSourceInfo info = BytecodeSourceInfo()); | 47 const BytecodeSourceInfo& info = BytecodeSourceInfo()); |
44 void WriteJumpLoop(Bytecode bytecode, BytecodeLabel* label, int depth, | 48 void WriteJumpLoop(Bytecode bytecode, BytecodeLabel* label, int depth); |
45 BytecodeSourceInfo info = BytecodeSourceInfo()); | |
46 | 49 |
47 BytecodeArrayWriter* writer() { return &bytecode_array_writer_; } | 50 BytecodeArrayWriter* writer() { return &bytecode_array_writer_; } |
48 ZoneVector<unsigned char>* bytecodes() { return writer()->bytecodes(); } | 51 ZoneVector<unsigned char>* bytecodes() { return writer()->bytecodes(); } |
49 SourcePositionTableBuilder* source_position_table_builder() { | 52 SourcePositionTableBuilder* source_position_table_builder() { |
50 return writer()->source_position_table_builder(); | 53 return writer()->source_position_table_builder(); |
51 } | 54 } |
| 55 int max_register_count() { return writer()->max_register_count(); } |
52 | 56 |
53 private: | 57 private: |
54 ConstantArrayBuilder constant_array_builder_; | 58 ConstantArrayBuilder constant_array_builder_; |
55 BytecodeArrayWriter bytecode_array_writer_; | 59 BytecodeArrayWriter bytecode_array_writer_; |
56 }; | 60 }; |
57 | 61 |
| 62 void BytecodeArrayWriterUnittest::Write(BytecodeNode* node, |
| 63 const BytecodeSourceInfo& info) { |
| 64 if (info.is_valid()) { |
| 65 node->source_info().Clone(info); |
| 66 } |
| 67 writer()->Write(node); |
| 68 } |
| 69 |
58 void BytecodeArrayWriterUnittest::Write(Bytecode bytecode, | 70 void BytecodeArrayWriterUnittest::Write(Bytecode bytecode, |
59 BytecodeSourceInfo info) { | 71 const BytecodeSourceInfo& info) { |
60 BytecodeNode node(bytecode, &info); | 72 BytecodeNode node(bytecode); |
61 writer()->Write(&node); | 73 Write(&node, info); |
62 } | 74 } |
63 | 75 |
64 void BytecodeArrayWriterUnittest::Write(Bytecode bytecode, uint32_t operand0, | 76 void BytecodeArrayWriterUnittest::Write(Bytecode bytecode, uint32_t operand0, |
65 BytecodeSourceInfo info) { | 77 const BytecodeSourceInfo& info) { |
66 BytecodeNode node(bytecode, operand0, &info); | 78 BytecodeNode node(bytecode, operand0); |
67 writer()->Write(&node); | 79 Write(&node, info); |
68 } | 80 } |
69 | 81 |
70 void BytecodeArrayWriterUnittest::Write(Bytecode bytecode, uint32_t operand0, | 82 void BytecodeArrayWriterUnittest::Write(Bytecode bytecode, uint32_t operand0, |
71 uint32_t operand1, | 83 uint32_t operand1, |
72 BytecodeSourceInfo info) { | 84 const BytecodeSourceInfo& info) { |
73 BytecodeNode node(bytecode, operand0, operand1, &info); | 85 BytecodeNode node(bytecode, operand0, operand1); |
74 writer()->Write(&node); | 86 Write(&node, info); |
75 } | 87 } |
76 | 88 |
77 void BytecodeArrayWriterUnittest::Write(Bytecode bytecode, uint32_t operand0, | 89 void BytecodeArrayWriterUnittest::Write(Bytecode bytecode, uint32_t operand0, |
78 uint32_t operand1, uint32_t operand2, | 90 uint32_t operand1, uint32_t operand2, |
79 BytecodeSourceInfo info) { | 91 const BytecodeSourceInfo& info) { |
80 BytecodeNode node(bytecode, operand0, operand1, operand2, &info); | 92 BytecodeNode node(bytecode, operand0, operand1, operand2); |
81 writer()->Write(&node); | 93 Write(&node, info); |
82 } | 94 } |
83 | 95 |
84 void BytecodeArrayWriterUnittest::Write(Bytecode bytecode, uint32_t operand0, | 96 void BytecodeArrayWriterUnittest::Write(Bytecode bytecode, uint32_t operand0, |
85 uint32_t operand1, uint32_t operand2, | 97 uint32_t operand1, uint32_t operand2, |
86 uint32_t operand3, | 98 uint32_t operand3, |
87 BytecodeSourceInfo info) { | 99 const BytecodeSourceInfo& info) { |
88 BytecodeNode node(bytecode, operand0, operand1, operand2, operand3, &info); | 100 BytecodeNode node(bytecode, operand0, operand1, operand2, operand3); |
89 writer()->Write(&node); | 101 Write(&node, info); |
90 } | 102 } |
91 | 103 |
92 void BytecodeArrayWriterUnittest::WriteJump(Bytecode bytecode, | 104 void BytecodeArrayWriterUnittest::WriteJump(Bytecode bytecode, |
93 BytecodeLabel* label, | 105 BytecodeLabel* label, |
94 BytecodeSourceInfo info) { | 106 const BytecodeSourceInfo& info) { |
95 BytecodeNode node(bytecode, 0, &info); | 107 BytecodeNode node(bytecode, 0); |
| 108 if (info.is_valid()) { |
| 109 node.source_info().Clone(info); |
| 110 } |
96 writer()->WriteJump(&node, label); | 111 writer()->WriteJump(&node, label); |
97 } | 112 } |
98 | 113 |
99 void BytecodeArrayWriterUnittest::WriteJumpLoop(Bytecode bytecode, | 114 void BytecodeArrayWriterUnittest::WriteJumpLoop(Bytecode bytecode, |
100 BytecodeLabel* label, int depth, | 115 BytecodeLabel* label, |
101 BytecodeSourceInfo info) { | 116 int depth) { |
102 BytecodeNode node(bytecode, 0, depth, &info); | 117 BytecodeNode node(bytecode, 0, depth); |
103 writer()->WriteJump(&node, label); | 118 writer()->WriteJump(&node, label); |
104 } | 119 } |
105 | 120 |
106 TEST_F(BytecodeArrayWriterUnittest, SimpleExample) { | 121 TEST_F(BytecodeArrayWriterUnittest, SimpleExample) { |
107 CHECK_EQ(bytecodes()->size(), 0); | 122 CHECK_EQ(bytecodes()->size(), 0); |
108 | 123 |
109 Write(Bytecode::kStackCheck, {10, false}); | 124 Write(Bytecode::kStackCheck, {10, false}); |
110 CHECK_EQ(bytecodes()->size(), 1); | 125 CHECK_EQ(bytecodes()->size(), 1); |
| 126 CHECK_EQ(max_register_count(), 0); |
111 | 127 |
112 Write(Bytecode::kLdaSmi, 127, {55, true}); | 128 Write(Bytecode::kLdaSmi, 127, {55, true}); |
113 CHECK_EQ(bytecodes()->size(), 3); | 129 CHECK_EQ(bytecodes()->size(), 3); |
| 130 CHECK_EQ(max_register_count(), 0); |
114 | 131 |
115 Write(Bytecode::kLdar, Register(200).ToOperand()); | 132 Write(Bytecode::kLdar, Register(200).ToOperand()); |
116 CHECK_EQ(bytecodes()->size(), 7); | 133 CHECK_EQ(bytecodes()->size(), 7); |
| 134 CHECK_EQ(max_register_count(), 201); |
117 | 135 |
118 Write(Bytecode::kReturn, {70, true}); | 136 Write(Bytecode::kReturn, {70, true}); |
119 CHECK_EQ(bytecodes()->size(), 8); | 137 CHECK_EQ(bytecodes()->size(), 8); |
| 138 CHECK_EQ(max_register_count(), 201); |
120 | 139 |
121 static const uint8_t bytes[] = {B(StackCheck), B(LdaSmi), U8(127), B(Wide), | 140 static const uint8_t bytes[] = {B(StackCheck), B(LdaSmi), U8(127), B(Wide), |
122 B(Ldar), R16(200), B(Return)}; | 141 B(Ldar), R16(200), B(Return)}; |
123 CHECK_EQ(bytecodes()->size(), arraysize(bytes)); | 142 CHECK_EQ(bytecodes()->size(), arraysize(bytes)); |
124 for (size_t i = 0; i < arraysize(bytes); ++i) { | 143 for (size_t i = 0; i < arraysize(bytes); ++i) { |
125 CHECK_EQ(bytecodes()->at(i), bytes[i]); | 144 CHECK_EQ(bytecodes()->at(i), bytes[i]); |
126 } | 145 } |
127 | 146 |
128 Handle<BytecodeArray> bytecode_array = writer()->ToBytecodeArray( | 147 Handle<BytecodeArray> bytecode_array = writer()->ToBytecodeArray( |
129 isolate(), 0, 0, factory()->empty_fixed_array()); | 148 isolate(), 0, 0, factory()->empty_fixed_array()); |
(...skipping 11 matching lines...) Expand all Loading... |
141 source_iterator.Advance(); | 160 source_iterator.Advance(); |
142 } | 161 } |
143 CHECK(source_iterator.done()); | 162 CHECK(source_iterator.done()); |
144 } | 163 } |
145 | 164 |
146 TEST_F(BytecodeArrayWriterUnittest, ComplexExample) { | 165 TEST_F(BytecodeArrayWriterUnittest, ComplexExample) { |
147 static const uint8_t expected_bytes[] = { | 166 static const uint8_t expected_bytes[] = { |
148 // clang-format off | 167 // clang-format off |
149 /* 0 30 E> */ B(StackCheck), | 168 /* 0 30 E> */ B(StackCheck), |
150 /* 1 42 S> */ B(LdaConstant), U8(0), | 169 /* 1 42 S> */ B(LdaConstant), U8(0), |
151 /* 3 42 E> */ B(Add), R8(1), U8(1), | 170 /* 3 42 E> */ B(Star), R8(1), |
152 /* 5 68 S> */ B(JumpIfUndefined), U8(39), | 171 /* 5 68 S> */ B(JumpIfUndefined), U8(39), |
153 /* 7 */ B(JumpIfNull), U8(37), | 172 /* 7 */ B(JumpIfNull), U8(37), |
154 /* 9 */ B(ToObject), R8(3), | 173 /* 9 */ B(ToObject), R8(3), |
155 /* 11 */ B(ForInPrepare), R8(3), R8(4), | 174 /* 11 */ B(ForInPrepare), R8(3), R8(4), |
156 /* 14 */ B(LdaZero), | 175 /* 14 */ B(LdaZero), |
157 /* 15 */ B(Star), R8(7), | 176 /* 15 */ B(Star), R8(7), |
158 /* 17 63 S> */ B(ForInContinue), R8(7), R8(6), | 177 /* 17 63 S> */ B(ForInContinue), R8(7), R8(6), |
159 /* 20 */ B(JumpIfFalse), U8(24), | 178 /* 20 */ B(JumpIfFalse), U8(24), |
160 /* 22 */ B(ForInNext), R8(3), R8(7), R8(4), U8(1), | 179 /* 22 */ B(ForInNext), R8(3), R8(7), R8(4), U8(1), |
161 /* 27 */ B(JumpIfUndefined), U8(10), | 180 /* 27 */ B(JumpIfUndefined), U8(10), |
162 /* 29 */ B(Star), R8(0), | 181 /* 29 */ B(Star), R8(0), |
163 /* 31 54 E> */ B(StackCheck), | 182 /* 31 54 E> */ B(StackCheck), |
164 /* 32 */ B(Ldar), R8(0), | 183 /* 32 */ B(Ldar), R8(0), |
165 /* 34 */ B(Star), R8(2), | 184 /* 34 */ B(Star), R8(2), |
166 /* 36 85 S> */ B(Return), | 185 /* 36 85 S> */ B(Return), |
167 /* 37 */ B(ForInStep), R8(7), | 186 /* 37 */ B(ForInStep), R8(7), |
168 /* 39 */ B(Star), R8(7), | 187 /* 39 */ B(Star), R8(7), |
169 /* 41 */ B(JumpLoop), U8(-24), U8(0), | 188 /* 41 */ B(JumpLoop), U8(-24), U8(0), |
170 /* 44 */ B(LdaUndefined), | 189 /* 44 */ B(LdaUndefined), |
171 /* 45 85 S> */ B(Return), | 190 /* 45 85 S> */ B(Return), |
172 // clang-format on | 191 // clang-format on |
173 }; | 192 }; |
174 | 193 |
175 static const PositionTableEntry expected_positions[] = { | 194 static const PositionTableEntry expected_positions[] = { |
176 {0, 30, false}, {1, 42, true}, {3, 42, false}, {6, 68, true}, | 195 {0, 30, false}, {1, 42, true}, {3, 42, false}, {5, 68, true}, |
177 {18, 63, true}, {32, 54, false}, {37, 85, true}, {46, 85, true}}; | 196 {17, 63, true}, {31, 54, false}, {36, 85, true}, {45, 85, true}}; |
178 | 197 |
179 BytecodeLabel back_jump, jump_for_in, jump_end_1, jump_end_2, jump_end_3; | 198 BytecodeLabel back_jump, jump_for_in, jump_end_1, jump_end_2, jump_end_3; |
180 | 199 |
181 #define R(i) static_cast<uint32_t>(Register(i).ToOperand()) | 200 #define R(i) static_cast<uint32_t>(Register(i).ToOperand()) |
182 Write(Bytecode::kStackCheck, {30, false}); | 201 Write(Bytecode::kStackCheck, {30, false}); |
183 Write(Bytecode::kLdaConstant, U8(0), {42, true}); | 202 Write(Bytecode::kLdaConstant, U8(0), {42, true}); |
184 Write(Bytecode::kAdd, R(1), U8(1), {42, false}); | 203 CHECK_EQ(max_register_count(), 0); |
| 204 Write(Bytecode::kStar, R(1), {42, false}); |
| 205 CHECK_EQ(max_register_count(), 2); |
185 WriteJump(Bytecode::kJumpIfUndefined, &jump_end_1, {68, true}); | 206 WriteJump(Bytecode::kJumpIfUndefined, &jump_end_1, {68, true}); |
186 WriteJump(Bytecode::kJumpIfNull, &jump_end_2); | 207 WriteJump(Bytecode::kJumpIfNull, &jump_end_2); |
187 Write(Bytecode::kToObject, R(3)); | 208 Write(Bytecode::kToObject, R(3)); |
| 209 CHECK_EQ(max_register_count(), 4); |
188 Write(Bytecode::kForInPrepare, R(3), R(4)); | 210 Write(Bytecode::kForInPrepare, R(3), R(4)); |
| 211 CHECK_EQ(max_register_count(), 7); |
189 Write(Bytecode::kLdaZero); | 212 Write(Bytecode::kLdaZero); |
| 213 CHECK_EQ(max_register_count(), 7); |
190 Write(Bytecode::kStar, R(7)); | 214 Write(Bytecode::kStar, R(7)); |
| 215 CHECK_EQ(max_register_count(), 8); |
191 writer()->BindLabel(&back_jump); | 216 writer()->BindLabel(&back_jump); |
192 Write(Bytecode::kForInContinue, R(7), R(6), {63, true}); | 217 Write(Bytecode::kForInContinue, R(7), R(6), {63, true}); |
| 218 CHECK_EQ(max_register_count(), 8); |
193 WriteJump(Bytecode::kJumpIfFalse, &jump_end_3); | 219 WriteJump(Bytecode::kJumpIfFalse, &jump_end_3); |
194 Write(Bytecode::kForInNext, R(3), R(7), R(4), U8(1)); | 220 Write(Bytecode::kForInNext, R(3), R(7), R(4), U8(1)); |
195 WriteJump(Bytecode::kJumpIfUndefined, &jump_for_in); | 221 WriteJump(Bytecode::kJumpIfUndefined, &jump_for_in); |
196 Write(Bytecode::kStar, R(0)); | 222 Write(Bytecode::kStar, R(0)); |
197 Write(Bytecode::kStackCheck, {54, false}); | 223 Write(Bytecode::kStackCheck, {54, false}); |
198 Write(Bytecode::kLdar, R(0)); | 224 Write(Bytecode::kLdar, R(0)); |
199 Write(Bytecode::kStar, R(2)); | 225 Write(Bytecode::kStar, R(2)); |
200 Write(Bytecode::kReturn, {85, true}); | 226 Write(Bytecode::kReturn, {85, true}); |
201 writer()->BindLabel(&jump_for_in); | 227 writer()->BindLabel(&jump_for_in); |
202 Write(Bytecode::kForInStep, R(7)); | 228 Write(Bytecode::kForInStep, R(7)); |
203 Write(Bytecode::kStar, R(7)); | 229 Write(Bytecode::kStar, R(7)); |
204 WriteJumpLoop(Bytecode::kJumpLoop, &back_jump, 0); | 230 WriteJumpLoop(Bytecode::kJumpLoop, &back_jump, 0); |
205 writer()->BindLabel(&jump_end_1); | 231 writer()->BindLabel(&jump_end_1); |
206 writer()->BindLabel(&jump_end_2); | 232 writer()->BindLabel(&jump_end_2); |
207 writer()->BindLabel(&jump_end_3); | 233 writer()->BindLabel(&jump_end_3); |
208 Write(Bytecode::kLdaUndefined); | 234 Write(Bytecode::kLdaUndefined); |
209 Write(Bytecode::kReturn, {85, true}); | 235 Write(Bytecode::kReturn, {85, true}); |
| 236 CHECK_EQ(max_register_count(), 8); |
210 #undef R | 237 #undef R |
211 | 238 |
212 CHECK_EQ(bytecodes()->size(), arraysize(expected_bytes)); | 239 CHECK_EQ(bytecodes()->size(), arraysize(expected_bytes)); |
213 for (size_t i = 0; i < arraysize(expected_bytes); ++i) { | 240 for (size_t i = 0; i < arraysize(expected_bytes); ++i) { |
214 CHECK_EQ(static_cast<int>(bytecodes()->at(i)), | 241 CHECK_EQ(static_cast<int>(bytecodes()->at(i)), |
215 static_cast<int>(expected_bytes[i])); | 242 static_cast<int>(expected_bytes[i])); |
216 } | 243 } |
217 | 244 |
218 Handle<BytecodeArray> bytecode_array = writer()->ToBytecodeArray( | 245 Handle<BytecodeArray> bytecode_array = writer()->ToBytecodeArray( |
219 isolate(), 0, 0, factory()->empty_fixed_array()); | 246 isolate(), 0, 0, factory()->empty_fixed_array()); |
220 SourcePositionTableIterator source_iterator( | 247 SourcePositionTableIterator source_iterator( |
221 bytecode_array->source_position_table()); | 248 bytecode_array->source_position_table()); |
222 for (size_t i = 0; i < arraysize(expected_positions); ++i) { | 249 for (size_t i = 0; i < arraysize(expected_positions); ++i) { |
223 const PositionTableEntry& expected = expected_positions[i]; | 250 const PositionTableEntry& expected = expected_positions[i]; |
224 CHECK_EQ(source_iterator.code_offset(), expected.code_offset); | 251 CHECK_EQ(source_iterator.code_offset(), expected.code_offset); |
225 CHECK_EQ(source_iterator.source_position(), expected.source_position); | 252 CHECK_EQ(source_iterator.source_position(), expected.source_position); |
226 CHECK_EQ(source_iterator.is_statement(), expected.is_statement); | 253 CHECK_EQ(source_iterator.is_statement(), expected.is_statement); |
227 source_iterator.Advance(); | 254 source_iterator.Advance(); |
228 } | 255 } |
229 CHECK(source_iterator.done()); | 256 CHECK(source_iterator.done()); |
230 } | 257 } |
231 | 258 |
232 } // namespace interpreter | 259 } // namespace interpreter |
233 } // namespace internal | 260 } // namespace internal |
234 } // namespace v8 | 261 } // namespace v8 |
OLD | NEW |