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