OLD | NEW |
---|---|
(Empty) | |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "src/v8.h" | |
6 | |
7 #include "src/interpreter/bytecode-array-writer.h" | |
8 #include "src/interpreter/source-position-table.h" | |
9 #include "src/isolate.h" | |
10 #include "src/utils.h" | |
11 #include "test/unittests/interpreter/bytecode-utils.h" | |
12 #include "test/unittests/test-utils.h" | |
13 | |
14 namespace v8 { | |
15 namespace internal { | |
16 namespace interpreter { | |
17 | |
18 class BytecodeArrayWriterUnittest : public TestWithIsolateAndZone { | |
19 public: | |
20 BytecodeArrayWriterUnittest() | |
21 : source_position_builder_(isolate(), zone()), | |
22 bytecode_array_writer_(zone(), &source_position_builder_) {} | |
23 ~BytecodeArrayWriterUnittest() override {} | |
24 | |
25 SourcePositionTableBuilder* source_position_builder() { | |
26 return &source_position_builder_; | |
27 } | |
28 BytecodeArrayWriter* writer() { return &bytecode_array_writer_; } | |
29 | |
30 private: | |
31 SourcePositionTableBuilder source_position_builder_; | |
32 BytecodeArrayWriter bytecode_array_writer_; | |
33 }; | |
34 | |
35 TEST_F(BytecodeArrayWriterUnittest, SimpleExample) { | |
36 CHECK_EQ(writer()->bytecodes()->size(), 0); | |
37 | |
38 BytecodeNode node0(Bytecode::kStackCheck); | |
39 node0.source_info().Update({10, false}); | |
40 writer()->Write(&node0); | |
41 CHECK_EQ(writer()->bytecodes()->size(), 1); | |
42 CHECK_EQ(writer()->GetMeasuredFrameSize(), 0); | |
43 | |
44 BytecodeNode node1(Bytecode::kLdaSmi, 0xff, OperandScale::kSingle); | |
45 node1.source_info().Update({55, true}); | |
46 writer()->Write(&node1); | |
47 CHECK_EQ(writer()->bytecodes()->size(), 3); | |
48 CHECK_EQ(writer()->GetMeasuredFrameSize(), 0); | |
49 | |
50 BytecodeNode node2(Bytecode::kLdar, Register(1).ToOperand(), | |
51 OperandScale::kDouble); | |
52 writer()->Write(&node2); | |
53 CHECK_EQ(writer()->bytecodes()->size(), 7); | |
54 CHECK_EQ(writer()->GetMeasuredFrameSize(), 2 * kPointerSize); | |
55 | |
56 BytecodeNode node3(Bytecode::kReturn); | |
57 node3.source_info().Update({70, true}); | |
58 writer()->Write(&node3); | |
59 CHECK_EQ(writer()->bytecodes()->size(), 8); | |
60 CHECK_EQ(writer()->GetMeasuredFrameSize(), 2 * kPointerSize); | |
61 | |
62 static const uint8_t bytes[] = {B(StackCheck), B(LdaSmi), U8(0xff), B(Wide), | |
63 B(Ldar), R16(1), B(Return)}; | |
64 CHECK_EQ(writer()->bytecodes()->size(), arraysize(bytes)); | |
65 for (size_t i = 0; i < arraysize(bytes); ++i) { | |
66 CHECK_EQ(writer()->bytecodes()->at(i), bytes[i]); | |
67 } | |
68 | |
69 CHECK_EQ(writer()->FlushForOffset(), arraysize(bytes)); | |
70 writer()->FlushBasicBlock(); | |
71 CHECK_EQ(writer()->bytecodes()->size(), arraysize(bytes)); | |
72 | |
73 PositionTableEntry expected_positions[] = { | |
74 {0, 10, false}, {1, 55, true}, {7, 70, true}}; | |
75 Handle<ByteArray> source_positions = | |
76 source_position_builder()->ToSourcePositionTable(); | |
77 SourcePositionTableIterator source_iterator(*source_positions); | |
78 for (size_t i = 0; i < arraysize(expected_positions); ++i) { | |
79 const PositionTableEntry& expected = expected_positions[i]; | |
80 CHECK_EQ(source_iterator.bytecode_offset(), expected.bytecode_offset); | |
81 CHECK_EQ(source_iterator.source_position(), expected.source_position); | |
82 CHECK_EQ(source_iterator.is_statement(), expected.is_statement); | |
83 source_iterator.Advance(); | |
84 } | |
85 CHECK(source_iterator.done()); | |
86 } | |
87 | |
88 | |
89 TEST_F(BytecodeArrayWriterUnittest, ComplexExample) { | |
90 static const uint8_t expected_bytes[] = { | |
91 // clang-format off | |
rmcilroy
2016/05/12 12:15:14
nit - indent
oth
2016/05/12 14:59:53
Done.
| |
92 /* 0 30 E> */ B(StackCheck), | |
93 /* 1 42 S> */ B(LdaConstant), U8(0), | |
94 /* 3 42 E> */ B(Star), R8(1), | |
95 /* 5 68 S> */ B(JumpIfUndefined), U8(38), | |
96 /* 7 */ B(JumpIfNull), U8(36), | |
97 /* 9 */ B(ToObject), | |
98 /* 10 */ B(Star), R8(3), | |
99 /* 12 */ B(ForInPrepare), R8(4), | |
100 /* 14 */ B(LdaZero), | |
101 /* 15 */ B(Star), R8(7), | |
102 /* 17 63 S> */ B(ForInDone), R8(7), R8(6), | |
103 /* 20 */ B(JumpIfTrue), U8(23), | |
104 /* 22 */ B(ForInNext), R8(3), R8(7), R8(4), U8(1), | |
105 /* 27 */ B(JumpIfUndefined), U8(10), | |
106 /* 29 */ B(Star), R8(0), | |
107 /* 31 54 E> */ B(StackCheck), | |
108 /* 32 */ B(Ldar), R8(0), | |
109 /* 34 */ B(Star), R8(2), | |
110 /* 36 85 S> */ B(Return), | |
111 /* 37 */ B(ForInStep), R8(7), | |
112 /* 39 */ B(Star), R8(7), | |
113 /* 41 */ B(Jump), U8(-24), | |
114 /* 43 */ B(LdaUndefined), | |
115 /* 44 85 S> */ B(Return), | |
116 // clang-format on | |
rmcilroy
2016/05/12 12:15:14
nit - indent
oth
2016/05/12 14:59:53
Done.
| |
117 }; | |
118 | |
119 static const PositionTableEntry expected_positions[] = { | |
120 {0, 30, false}, {1, 42, true}, {3, 42, false}, {5, 68, true}, | |
121 {17, 63, true}, {31, 54, false}, {36, 85, true}, {44, 85, true}}; | |
122 | |
123 #define NODE(node_args) \ | |
rmcilroy
2016/05/12 12:15:14
Nit - these could be helper functions instead of m
oth
2016/05/12 14:59:53
Done.
| |
124 { \ | |
125 BytecodeNode node node_args; \ | |
126 writer()->Write(&node); \ | |
127 } | |
128 | |
129 #define NODE_SP(node_args, source_position, statement) \ | |
130 { \ | |
131 BytecodeNode node node_args; \ | |
132 node.source_info().Update({source_position, statement}); \ | |
133 writer()->Write(&node); \ | |
134 } | |
135 | |
136 #define R(i) static_cast<uint32_t>(Register(i).ToOperand()) | |
137 | |
138 NODE_SP((Bytecode::kStackCheck), 30, false); | |
139 NODE_SP((Bytecode::kLdaConstant, U8(0), OperandScale::kSingle), 42, true); | |
140 CHECK_EQ(writer()->GetMeasuredFrameSize(), 0 * kPointerSize); | |
141 NODE_SP((Bytecode::kStar, R(1), OperandScale::kSingle), 42, false); | |
142 CHECK_EQ(writer()->GetMeasuredFrameSize(), 2 * kPointerSize); | |
143 NODE_SP((Bytecode::kJumpIfUndefined, U8(38), OperandScale::kSingle), 68, | |
144 true); | |
145 NODE((Bytecode::kJumpIfNull, U8(36), OperandScale::kSingle)); | |
146 NODE((Bytecode::kToObject)); | |
147 CHECK_EQ(writer()->GetMeasuredFrameSize(), 2 * kPointerSize); | |
148 NODE((Bytecode::kStar, R(3), OperandScale::kSingle)); | |
149 CHECK_EQ(writer()->GetMeasuredFrameSize(), 4 * kPointerSize); | |
150 NODE((Bytecode::kForInPrepare, R(4), OperandScale::kSingle)); | |
151 CHECK_EQ(writer()->GetMeasuredFrameSize(), 7 * kPointerSize); | |
152 NODE((Bytecode::kLdaZero)); | |
153 CHECK_EQ(writer()->GetMeasuredFrameSize(), 7 * kPointerSize); | |
154 NODE((Bytecode::kStar, R(7), OperandScale::kSingle)); | |
155 CHECK_EQ(writer()->GetMeasuredFrameSize(), 8 * kPointerSize); | |
156 NODE_SP((Bytecode::kForInDone, R(7), R(6), OperandScale::kSingle), 63, true); | |
157 CHECK_EQ(writer()->GetMeasuredFrameSize(), 8 * kPointerSize); | |
158 NODE((Bytecode::kJumpIfTrue, U8(23), OperandScale::kSingle)); | |
159 NODE((Bytecode::kForInNext, R(3), R(7), R(4), U8(1), OperandScale::kSingle)); | |
160 NODE((Bytecode::kJumpIfUndefined, U8(10), OperandScale::kSingle)); | |
161 NODE((Bytecode::kStar, R(0), OperandScale::kSingle)); | |
162 NODE_SP((Bytecode::kStackCheck), 54, false); | |
163 NODE((Bytecode::kLdar, R(0), OperandScale::kSingle)); | |
164 NODE((Bytecode::kStar, R(2), OperandScale::kSingle)); | |
165 NODE_SP((Bytecode::kReturn), 85, true); | |
166 NODE((Bytecode::kForInStep, R(7), OperandScale::kSingle)); | |
167 NODE((Bytecode::kStar, R(7), OperandScale::kSingle)); | |
168 NODE((Bytecode::kJump, U8(-24), OperandScale::kSingle)); | |
169 NODE((Bytecode::kLdaUndefined)); | |
170 NODE_SP((Bytecode::kReturn), 85, true); | |
171 CHECK_EQ(writer()->GetMeasuredFrameSize(), 8 * kPointerSize); | |
172 | |
173 #undef NODE | |
174 #undef NODE_SP | |
175 #undef R | |
176 | |
177 CHECK_EQ(writer()->bytecodes()->size(), arraysize(expected_bytes)); | |
178 for (size_t i = 0; i < arraysize(expected_bytes); ++i) { | |
179 CHECK_EQ(static_cast<int>(writer()->bytecodes()->at(i)), | |
180 static_cast<int>(expected_bytes[i])); | |
181 } | |
182 | |
183 Handle<ByteArray> source_positions = | |
184 source_position_builder()->ToSourcePositionTable(); | |
185 SourcePositionTableIterator source_iterator(*source_positions); | |
186 for (size_t i = 0; i < arraysize(expected_positions); ++i) { | |
187 const PositionTableEntry& expected = expected_positions[i]; | |
188 CHECK_EQ(source_iterator.bytecode_offset(), expected.bytecode_offset); | |
189 CHECK_EQ(source_iterator.source_position(), expected.source_position); | |
190 CHECK_EQ(source_iterator.is_statement(), expected.is_statement); | |
191 source_iterator.Advance(); | |
192 } | |
193 CHECK(source_iterator.done()); | |
194 } | |
195 | |
196 } // namespace interpreter | |
197 } // namespace internal | |
198 } // namespace v8 | |
OLD | NEW |