Line data Source code
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 : #include "src/v8.h"
6 :
7 : #include "src/interpreter/bytecode-array-builder.h"
8 : #include "src/interpreter/bytecode-array-iterator.h"
9 : #include "src/objects-inl.h"
10 : #include "src/objects/smi.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 BytecodeArrayIteratorTest : public TestWithIsolateAndZone {
19 : public:
20 1 : BytecodeArrayIteratorTest() = default;
21 1 : ~BytecodeArrayIteratorTest() override = default;
22 : };
23 :
24 15129 : TEST_F(BytecodeArrayIteratorTest, IteratesBytecodeArray) {
25 : // Use a builder to create an array with containing multiple bytecodes
26 : // with 0, 1 and 2 operands.
27 1 : FeedbackVectorSpec feedback_spec(zone());
28 2 : BytecodeArrayBuilder builder(zone(), 3, 3, &feedback_spec);
29 : AstValueFactory ast_factory(zone(), isolate()->ast_string_constants(),
30 2 : isolate()->heap()->HashSeed());
31 1 : double heap_num_0 = 2.718;
32 1 : double heap_num_1 = 2.0 * Smi::kMaxValue;
33 1 : Smi zero = Smi::zero();
34 1 : Smi smi_0 = Smi::FromInt(64);
35 1 : Smi smi_1 = Smi::FromInt(-65536);
36 : Register reg_0(0);
37 : Register reg_1(1);
38 1 : RegisterList pair = BytecodeUtils::NewRegisterList(0, 2);
39 1 : RegisterList triple = BytecodeUtils::NewRegisterList(0, 3);
40 1 : Register param = Register::FromParameterIndex(2, builder.parameter_count());
41 1 : const AstRawString* name = ast_factory.GetOneByteString("abc");
42 1 : uint32_t name_index = 2;
43 1 : uint32_t load_feedback_slot = feedback_spec.AddLoadICSlot().ToInt();
44 1 : uint32_t forin_feedback_slot = feedback_spec.AddForInSlot().ToInt();
45 : uint32_t load_global_feedback_slot =
46 1 : feedback_spec.AddLoadGlobalICSlot(TypeofMode::NOT_INSIDE_TYPEOF).ToInt();
47 :
48 1 : builder.LoadLiteral(heap_num_0)
49 2 : .StoreAccumulatorInRegister(reg_0)
50 1 : .LoadLiteral(heap_num_1)
51 2 : .StoreAccumulatorInRegister(reg_0)
52 1 : .LoadLiteral(zero)
53 1 : .StoreAccumulatorInRegister(reg_0)
54 1 : .LoadLiteral(smi_0)
55 1 : .StackCheck(0)
56 1 : .StoreAccumulatorInRegister(reg_0)
57 1 : .LoadLiteral(smi_1)
58 1 : .StackCheck(1)
59 1 : .StoreAccumulatorInRegister(reg_1)
60 1 : .LoadAccumulatorWithRegister(reg_0)
61 1 : .BinaryOperation(Token::Value::ADD, reg_0, 2)
62 1 : .StoreAccumulatorInRegister(reg_1)
63 2 : .LoadNamedProperty(reg_1, name, load_feedback_slot)
64 1 : .BinaryOperation(Token::Value::ADD, reg_0, 3)
65 1 : .StoreAccumulatorInRegister(param)
66 1 : .CallRuntimeForPair(Runtime::kLoadLookupSlotForCall, param, pair)
67 2 : .ForInPrepare(triple, forin_feedback_slot)
68 1 : .CallRuntime(Runtime::kLoadIC_Miss, reg_0)
69 1 : .Debugger()
70 : .LoadGlobal(name, load_global_feedback_slot,
71 1 : TypeofMode::NOT_INSIDE_TYPEOF)
72 1 : .Return();
73 :
74 : // Test iterator sees the expected output from the builder.
75 1 : ast_factory.Internalize(isolate());
76 1 : BytecodeArrayIterator iterator(builder.ToBytecodeArray(isolate()));
77 : const int kPrefixByteSize = 1;
78 1 : int offset = 0;
79 :
80 2 : EXPECT_EQ(iterator.current_bytecode(), Bytecode::kLdaConstant);
81 2 : EXPECT_EQ(iterator.current_offset(), offset);
82 2 : EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
83 2 : EXPECT_EQ(iterator.GetConstantForIndexOperand(0)->Number(), heap_num_0);
84 1 : CHECK(!iterator.done());
85 1 : offset += Bytecodes::Size(Bytecode::kLdaConstant, OperandScale::kSingle);
86 1 : iterator.Advance();
87 :
88 2 : EXPECT_EQ(iterator.current_bytecode(), Bytecode::kStar);
89 2 : EXPECT_EQ(iterator.current_offset(), offset);
90 2 : EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
91 3 : EXPECT_EQ(iterator.GetRegisterOperand(0).index(), reg_0.index());
92 2 : EXPECT_EQ(iterator.GetRegisterOperandRange(0), 1);
93 1 : CHECK(!iterator.done());
94 1 : offset += Bytecodes::Size(Bytecode::kStar, OperandScale::kSingle);
95 1 : iterator.Advance();
96 :
97 2 : EXPECT_EQ(iterator.current_bytecode(), Bytecode::kLdaConstant);
98 2 : EXPECT_EQ(iterator.current_offset(), offset);
99 2 : EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
100 2 : EXPECT_EQ(iterator.GetConstantForIndexOperand(0)->Number(), heap_num_1);
101 1 : CHECK(!iterator.done());
102 1 : offset += Bytecodes::Size(Bytecode::kLdaConstant, OperandScale::kSingle);
103 1 : iterator.Advance();
104 :
105 2 : EXPECT_EQ(iterator.current_bytecode(), Bytecode::kStar);
106 2 : EXPECT_EQ(iterator.current_offset(), offset);
107 2 : EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
108 3 : EXPECT_EQ(iterator.GetRegisterOperand(0).index(), reg_0.index());
109 2 : EXPECT_EQ(iterator.GetRegisterOperandRange(0), 1);
110 1 : CHECK(!iterator.done());
111 1 : offset += Bytecodes::Size(Bytecode::kStar, OperandScale::kSingle);
112 1 : iterator.Advance();
113 :
114 2 : EXPECT_EQ(iterator.current_bytecode(), Bytecode::kLdaZero);
115 2 : EXPECT_EQ(iterator.current_offset(), offset);
116 2 : EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
117 1 : CHECK(!iterator.done());
118 1 : offset += Bytecodes::Size(Bytecode::kLdaZero, OperandScale::kSingle);
119 1 : iterator.Advance();
120 :
121 2 : EXPECT_EQ(iterator.current_bytecode(), Bytecode::kStar);
122 2 : EXPECT_EQ(iterator.current_offset(), offset);
123 2 : EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
124 3 : EXPECT_EQ(iterator.GetRegisterOperand(0).index(), reg_0.index());
125 2 : EXPECT_EQ(iterator.GetRegisterOperandRange(0), 1);
126 1 : CHECK(!iterator.done());
127 1 : offset += Bytecodes::Size(Bytecode::kStar, OperandScale::kSingle);
128 1 : iterator.Advance();
129 :
130 2 : EXPECT_EQ(iterator.current_bytecode(), Bytecode::kLdaSmi);
131 2 : EXPECT_EQ(iterator.current_offset(), offset);
132 2 : EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
133 3 : EXPECT_EQ(Smi::FromInt(iterator.GetImmediateOperand(0)), smi_0);
134 1 : CHECK(!iterator.done());
135 1 : offset += Bytecodes::Size(Bytecode::kLdaSmi, OperandScale::kSingle);
136 1 : iterator.Advance();
137 :
138 2 : EXPECT_EQ(iterator.current_bytecode(), Bytecode::kStackCheck);
139 2 : EXPECT_EQ(iterator.current_offset(), offset);
140 2 : EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
141 3 : EXPECT_EQ(Bytecodes::NumberOfOperands(iterator.current_bytecode()), 0);
142 1 : CHECK(!iterator.done());
143 1 : offset += Bytecodes::Size(Bytecode::kStackCheck, OperandScale::kSingle);
144 1 : iterator.Advance();
145 :
146 2 : EXPECT_EQ(iterator.current_bytecode(), Bytecode::kStar);
147 2 : EXPECT_EQ(iterator.current_offset(), offset);
148 2 : EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
149 3 : EXPECT_EQ(iterator.GetRegisterOperand(0).index(), reg_0.index());
150 2 : EXPECT_EQ(iterator.GetRegisterOperandRange(0), 1);
151 1 : CHECK(!iterator.done());
152 1 : offset += Bytecodes::Size(Bytecode::kStar, OperandScale::kSingle);
153 1 : iterator.Advance();
154 :
155 2 : EXPECT_EQ(iterator.current_bytecode(), Bytecode::kLdaSmi);
156 2 : EXPECT_EQ(iterator.current_offset(), offset);
157 2 : EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kQuadruple);
158 3 : EXPECT_EQ(Smi::FromInt(iterator.GetImmediateOperand(0)), smi_1);
159 1 : CHECK(!iterator.done());
160 : offset += Bytecodes::Size(Bytecode::kLdaSmi, OperandScale::kQuadruple) +
161 1 : kPrefixByteSize;
162 1 : iterator.Advance();
163 :
164 2 : EXPECT_EQ(iterator.current_bytecode(), Bytecode::kStackCheck);
165 2 : EXPECT_EQ(iterator.current_offset(), offset);
166 2 : EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
167 3 : EXPECT_EQ(Bytecodes::NumberOfOperands(iterator.current_bytecode()), 0);
168 1 : CHECK(!iterator.done());
169 1 : offset += Bytecodes::Size(Bytecode::kStackCheck, OperandScale::kSingle);
170 1 : iterator.Advance();
171 :
172 2 : EXPECT_EQ(iterator.current_bytecode(), Bytecode::kStar);
173 2 : EXPECT_EQ(iterator.current_offset(), offset);
174 2 : EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
175 3 : EXPECT_EQ(iterator.GetRegisterOperand(0).index(), reg_1.index());
176 2 : EXPECT_EQ(iterator.GetRegisterOperandRange(0), 1);
177 1 : CHECK(!iterator.done());
178 1 : offset += Bytecodes::Size(Bytecode::kStar, OperandScale::kSingle);
179 1 : iterator.Advance();
180 :
181 2 : EXPECT_EQ(iterator.current_bytecode(), Bytecode::kLdar);
182 2 : EXPECT_EQ(iterator.current_offset(), offset);
183 2 : EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
184 3 : EXPECT_EQ(iterator.GetRegisterOperand(0).index(), reg_0.index());
185 : CHECK(!iterator.done());
186 1 : offset += Bytecodes::Size(Bytecode::kLdar, OperandScale::kSingle);
187 1 : iterator.Advance();
188 :
189 2 : EXPECT_EQ(iterator.current_bytecode(), Bytecode::kAdd);
190 2 : EXPECT_EQ(iterator.current_offset(), offset);
191 2 : EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
192 3 : EXPECT_EQ(iterator.GetRegisterOperand(0).index(), reg_0.index());
193 2 : EXPECT_EQ(iterator.GetRegisterOperandRange(0), 1);
194 1 : CHECK(!iterator.done());
195 1 : offset += Bytecodes::Size(Bytecode::kAdd, OperandScale::kSingle);
196 1 : iterator.Advance();
197 :
198 2 : EXPECT_EQ(iterator.current_bytecode(), Bytecode::kStar);
199 2 : EXPECT_EQ(iterator.current_offset(), offset);
200 2 : EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
201 3 : EXPECT_EQ(iterator.GetRegisterOperand(0).index(), reg_1.index());
202 2 : EXPECT_EQ(iterator.GetRegisterOperandRange(0), 1);
203 1 : CHECK(!iterator.done());
204 1 : offset += Bytecodes::Size(Bytecode::kStar, OperandScale::kSingle);
205 1 : iterator.Advance();
206 :
207 2 : EXPECT_EQ(iterator.current_bytecode(), Bytecode::kLdaNamedProperty);
208 2 : EXPECT_EQ(iterator.current_offset(), offset);
209 2 : EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
210 3 : EXPECT_EQ(iterator.GetRegisterOperand(0).index(), reg_1.index());
211 2 : EXPECT_EQ(iterator.GetIndexOperand(1), name_index);
212 2 : EXPECT_EQ(iterator.GetIndexOperand(2), load_feedback_slot);
213 1 : CHECK(!iterator.done());
214 1 : offset += Bytecodes::Size(Bytecode::kLdaNamedProperty, OperandScale::kSingle);
215 1 : iterator.Advance();
216 :
217 2 : EXPECT_EQ(iterator.current_bytecode(), Bytecode::kAdd);
218 2 : EXPECT_EQ(iterator.current_offset(), offset);
219 2 : EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
220 3 : EXPECT_EQ(iterator.GetRegisterOperand(0).index(), reg_0.index());
221 2 : EXPECT_EQ(iterator.GetRegisterOperandRange(0), 1);
222 1 : CHECK(!iterator.done());
223 1 : offset += Bytecodes::Size(Bytecode::kAdd, OperandScale::kSingle);
224 1 : iterator.Advance();
225 :
226 2 : EXPECT_EQ(iterator.current_bytecode(), Bytecode::kStar);
227 2 : EXPECT_EQ(iterator.current_offset(), offset);
228 2 : EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
229 3 : EXPECT_EQ(iterator.GetRegisterOperand(0).index(), param.index());
230 2 : EXPECT_EQ(iterator.GetRegisterOperandRange(0), 1);
231 1 : CHECK(!iterator.done());
232 1 : offset += Bytecodes::Size(Bytecode::kStar, OperandScale::kSingle);
233 1 : iterator.Advance();
234 :
235 2 : EXPECT_EQ(iterator.current_bytecode(), Bytecode::kCallRuntimeForPair);
236 2 : EXPECT_EQ(iterator.current_offset(), offset);
237 2 : EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
238 2 : EXPECT_EQ(iterator.GetRuntimeIdOperand(0), Runtime::kLoadLookupSlotForCall);
239 3 : EXPECT_EQ(iterator.GetRegisterOperand(1).index(), param.index());
240 2 : EXPECT_EQ(iterator.GetRegisterOperandRange(1), 1);
241 2 : EXPECT_EQ(iterator.GetRegisterCountOperand(2), 1u);
242 3 : EXPECT_EQ(iterator.GetRegisterOperand(3).index(), reg_0.index());
243 2 : EXPECT_EQ(iterator.GetRegisterOperandRange(3), 2);
244 1 : CHECK(!iterator.done());
245 : offset +=
246 1 : Bytecodes::Size(Bytecode::kCallRuntimeForPair, OperandScale::kSingle);
247 1 : iterator.Advance();
248 :
249 2 : EXPECT_EQ(iterator.current_bytecode(), Bytecode::kForInPrepare);
250 2 : EXPECT_EQ(iterator.current_offset(), offset);
251 2 : EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
252 3 : EXPECT_EQ(iterator.GetRegisterOperand(0).index(), reg_0.index());
253 2 : EXPECT_EQ(iterator.GetRegisterOperandRange(0), 3);
254 2 : EXPECT_EQ(iterator.GetIndexOperand(1), forin_feedback_slot);
255 1 : CHECK(!iterator.done());
256 1 : offset += Bytecodes::Size(Bytecode::kForInPrepare, OperandScale::kSingle);
257 1 : iterator.Advance();
258 :
259 2 : EXPECT_EQ(iterator.current_bytecode(), Bytecode::kCallRuntime);
260 2 : EXPECT_EQ(iterator.current_offset(), offset);
261 2 : EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
262 2 : EXPECT_EQ(iterator.GetRuntimeIdOperand(0), Runtime::kLoadIC_Miss);
263 3 : EXPECT_EQ(iterator.GetRegisterOperand(1).index(), reg_0.index());
264 2 : EXPECT_EQ(iterator.GetRegisterCountOperand(2), 1u);
265 1 : CHECK(!iterator.done());
266 1 : offset += Bytecodes::Size(Bytecode::kCallRuntime, OperandScale::kSingle);
267 1 : iterator.Advance();
268 :
269 2 : EXPECT_EQ(iterator.current_bytecode(), Bytecode::kDebugger);
270 2 : EXPECT_EQ(iterator.current_offset(), offset);
271 2 : EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
272 1 : CHECK(!iterator.done());
273 1 : offset += Bytecodes::Size(Bytecode::kDebugger, OperandScale::kSingle);
274 1 : iterator.Advance();
275 :
276 2 : EXPECT_EQ(iterator.current_bytecode(), Bytecode::kLdaGlobal);
277 2 : EXPECT_EQ(iterator.current_offset(), offset);
278 2 : EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
279 2 : EXPECT_EQ(iterator.current_bytecode_size(), 3);
280 2 : EXPECT_EQ(iterator.GetIndexOperand(1), load_global_feedback_slot);
281 1 : offset += Bytecodes::Size(Bytecode::kLdaGlobal, OperandScale::kSingle);
282 1 : iterator.Advance();
283 :
284 2 : EXPECT_EQ(iterator.current_bytecode(), Bytecode::kReturn);
285 2 : EXPECT_EQ(iterator.current_offset(), offset);
286 2 : EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
287 1 : CHECK(!iterator.done());
288 1 : iterator.Advance();
289 1 : CHECK(iterator.done());
290 1 : }
291 :
292 : } // namespace interpreter
293 : } // namespace internal
294 9075 : } // namespace v8
|