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