bytecode-array-iterator-unittest.cc 12.7 KB
Newer Older
1 2 3 4 5 6
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/v8.h"

7
#include "src/hash-seed-inl.h"
8 9
#include "src/interpreter/bytecode-array-builder.h"
#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 14 15 16 17 18 19 20
#include "test/unittests/test-utils.h"

namespace v8 {
namespace internal {
namespace interpreter {

class BytecodeArrayIteratorTest : public TestWithIsolateAndZone {
 public:
21 22
  BytecodeArrayIteratorTest() = default;
  ~BytecodeArrayIteratorTest() override = default;
23 24 25 26 27
};

TEST_F(BytecodeArrayIteratorTest, IteratesBytecodeArray) {
  // Use a builder to create an array with containing multiple bytecodes
  // with 0, 1 and 2 operands.
28
  FeedbackVectorSpec feedback_spec(zone());
29
  BytecodeArrayBuilder builder(zone(), 3, 3, &feedback_spec);
30
  AstValueFactory ast_factory(zone(), isolate()->ast_string_constants(),
31
                              HashSeed(isolate()));
32 33
  double heap_num_0 = 2.718;
  double heap_num_1 = 2.0 * Smi::kMaxValue;
34 35 36
  Smi zero = Smi::zero();
  Smi smi_0 = Smi::FromInt(64);
  Smi smi_1 = Smi::FromInt(-65536);
37 38
  Register reg_0(0);
  Register reg_1(1);
39 40
  RegisterList pair = BytecodeUtils::NewRegisterList(0, 2);
  RegisterList triple = BytecodeUtils::NewRegisterList(0, 3);
41
  Register param = Register::FromParameterIndex(2, builder.parameter_count());
42
  const AstRawString* name = ast_factory.GetOneByteString("abc");
43
  uint32_t name_index = 2;
44 45 46 47
  uint32_t load_feedback_slot = feedback_spec.AddLoadICSlot().ToInt();
  uint32_t forin_feedback_slot = feedback_spec.AddForInSlot().ToInt();
  uint32_t load_global_feedback_slot =
      feedback_spec.AddLoadGlobalICSlot(TypeofMode::NOT_INSIDE_TYPEOF).ToInt();
48 49

  builder.LoadLiteral(heap_num_0)
50
      .StoreAccumulatorInRegister(reg_0)
51
      .LoadLiteral(heap_num_1)
52
      .StoreAccumulatorInRegister(reg_0)
53
      .LoadLiteral(zero)
54
      .StoreAccumulatorInRegister(reg_0)
55
      .LoadLiteral(smi_0)
56
      .StackCheck(0)
57
      .StoreAccumulatorInRegister(reg_0)
58
      .LoadLiteral(smi_1)
59
      .StackCheck(1)
60
      .StoreAccumulatorInRegister(reg_1)
61
      .LoadAccumulatorWithRegister(reg_0)
62
      .BinaryOperation(Token::Value::ADD, reg_0, 2)
63
      .StoreAccumulatorInRegister(reg_1)
64
      .LoadNamedProperty(reg_1, name, load_feedback_slot)
65
      .BinaryOperation(Token::Value::ADD, reg_0, 3)
66
      .StoreAccumulatorInRegister(param)
67
      .CallRuntimeForPair(Runtime::kLoadLookupSlotForCall, param, pair)
68
      .ForInPrepare(triple, forin_feedback_slot)
69
      .CallRuntime(Runtime::kLoadIC_Miss, reg_0)
70
      .Debugger()
71 72
      .LoadGlobal(name, load_global_feedback_slot,
                  TypeofMode::NOT_INSIDE_TYPEOF)
73 74 75
      .Return();

  // Test iterator sees the expected output from the builder.
76
  ast_factory.Internalize(isolate());
77
  BytecodeArrayIterator iterator(builder.ToBytecodeArray(isolate()));
78 79 80
  const int kPrefixByteSize = 1;
  int offset = 0;

81 82 83
  EXPECT_EQ(iterator.current_bytecode(), Bytecode::kLdaConstant);
  EXPECT_EQ(iterator.current_offset(), offset);
  EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
84
  EXPECT_EQ(iterator.GetConstantForIndexOperand(0)->Number(), heap_num_0);
85
  CHECK(!iterator.done());
86
  offset += Bytecodes::Size(Bytecode::kLdaConstant, OperandScale::kSingle);
87 88
  iterator.Advance();

89 90 91 92 93
  EXPECT_EQ(iterator.current_bytecode(), Bytecode::kStar);
  EXPECT_EQ(iterator.current_offset(), offset);
  EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
  EXPECT_EQ(iterator.GetRegisterOperand(0).index(), reg_0.index());
  EXPECT_EQ(iterator.GetRegisterOperandRange(0), 1);
94 95 96 97
  CHECK(!iterator.done());
  offset += Bytecodes::Size(Bytecode::kStar, OperandScale::kSingle);
  iterator.Advance();

98 99 100
  EXPECT_EQ(iterator.current_bytecode(), Bytecode::kLdaConstant);
  EXPECT_EQ(iterator.current_offset(), offset);
  EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
101
  EXPECT_EQ(iterator.GetConstantForIndexOperand(0)->Number(), heap_num_1);
102
  CHECK(!iterator.done());
103
  offset += Bytecodes::Size(Bytecode::kLdaConstant, OperandScale::kSingle);
104 105
  iterator.Advance();

106 107 108 109 110
  EXPECT_EQ(iterator.current_bytecode(), Bytecode::kStar);
  EXPECT_EQ(iterator.current_offset(), offset);
  EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
  EXPECT_EQ(iterator.GetRegisterOperand(0).index(), reg_0.index());
  EXPECT_EQ(iterator.GetRegisterOperandRange(0), 1);
111 112 113 114
  CHECK(!iterator.done());
  offset += Bytecodes::Size(Bytecode::kStar, OperandScale::kSingle);
  iterator.Advance();

115 116 117
  EXPECT_EQ(iterator.current_bytecode(), Bytecode::kLdaZero);
  EXPECT_EQ(iterator.current_offset(), offset);
  EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
118
  CHECK(!iterator.done());
119
  offset += Bytecodes::Size(Bytecode::kLdaZero, OperandScale::kSingle);
120 121
  iterator.Advance();

122 123 124 125 126
  EXPECT_EQ(iterator.current_bytecode(), Bytecode::kStar);
  EXPECT_EQ(iterator.current_offset(), offset);
  EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
  EXPECT_EQ(iterator.GetRegisterOperand(0).index(), reg_0.index());
  EXPECT_EQ(iterator.GetRegisterOperandRange(0), 1);
127 128 129 130
  CHECK(!iterator.done());
  offset += Bytecodes::Size(Bytecode::kStar, OperandScale::kSingle);
  iterator.Advance();

131 132 133 134
  EXPECT_EQ(iterator.current_bytecode(), Bytecode::kLdaSmi);
  EXPECT_EQ(iterator.current_offset(), offset);
  EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
  EXPECT_EQ(Smi::FromInt(iterator.GetImmediateOperand(0)), smi_0);
135
  CHECK(!iterator.done());
136
  offset += Bytecodes::Size(Bytecode::kLdaSmi, OperandScale::kSingle);
137 138
  iterator.Advance();

139 140 141 142
  EXPECT_EQ(iterator.current_bytecode(), Bytecode::kStackCheck);
  EXPECT_EQ(iterator.current_offset(), offset);
  EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
  EXPECT_EQ(Bytecodes::NumberOfOperands(iterator.current_bytecode()), 0);
143 144 145 146
  CHECK(!iterator.done());
  offset += Bytecodes::Size(Bytecode::kStackCheck, OperandScale::kSingle);
  iterator.Advance();

147 148 149 150 151
  EXPECT_EQ(iterator.current_bytecode(), Bytecode::kStar);
  EXPECT_EQ(iterator.current_offset(), offset);
  EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
  EXPECT_EQ(iterator.GetRegisterOperand(0).index(), reg_0.index());
  EXPECT_EQ(iterator.GetRegisterOperandRange(0), 1);
152 153 154 155
  CHECK(!iterator.done());
  offset += Bytecodes::Size(Bytecode::kStar, OperandScale::kSingle);
  iterator.Advance();

156 157 158 159
  EXPECT_EQ(iterator.current_bytecode(), Bytecode::kLdaSmi);
  EXPECT_EQ(iterator.current_offset(), offset);
  EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kQuadruple);
  EXPECT_EQ(Smi::FromInt(iterator.GetImmediateOperand(0)), smi_1);
160
  CHECK(!iterator.done());
161 162
  offset += Bytecodes::Size(Bytecode::kLdaSmi, OperandScale::kQuadruple) +
            kPrefixByteSize;
163 164
  iterator.Advance();

165 166 167 168
  EXPECT_EQ(iterator.current_bytecode(), Bytecode::kStackCheck);
  EXPECT_EQ(iterator.current_offset(), offset);
  EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
  EXPECT_EQ(Bytecodes::NumberOfOperands(iterator.current_bytecode()), 0);
169 170 171 172
  CHECK(!iterator.done());
  offset += Bytecodes::Size(Bytecode::kStackCheck, OperandScale::kSingle);
  iterator.Advance();

173 174 175 176 177
  EXPECT_EQ(iterator.current_bytecode(), Bytecode::kStar);
  EXPECT_EQ(iterator.current_offset(), offset);
  EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
  EXPECT_EQ(iterator.GetRegisterOperand(0).index(), reg_1.index());
  EXPECT_EQ(iterator.GetRegisterOperandRange(0), 1);
178 179 180 181
  CHECK(!iterator.done());
  offset += Bytecodes::Size(Bytecode::kStar, OperandScale::kSingle);
  iterator.Advance();

182 183 184 185
  EXPECT_EQ(iterator.current_bytecode(), Bytecode::kLdar);
  EXPECT_EQ(iterator.current_offset(), offset);
  EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
  EXPECT_EQ(iterator.GetRegisterOperand(0).index(), reg_0.index());
186
  CHECK(!iterator.done());
187
  offset += Bytecodes::Size(Bytecode::kLdar, OperandScale::kSingle);
188 189
  iterator.Advance();

190 191 192 193 194
  EXPECT_EQ(iterator.current_bytecode(), Bytecode::kAdd);
  EXPECT_EQ(iterator.current_offset(), offset);
  EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
  EXPECT_EQ(iterator.GetRegisterOperand(0).index(), reg_0.index());
  EXPECT_EQ(iterator.GetRegisterOperandRange(0), 1);
195
  CHECK(!iterator.done());
196
  offset += Bytecodes::Size(Bytecode::kAdd, OperandScale::kSingle);
197 198
  iterator.Advance();

199 200 201 202 203
  EXPECT_EQ(iterator.current_bytecode(), Bytecode::kStar);
  EXPECT_EQ(iterator.current_offset(), offset);
  EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
  EXPECT_EQ(iterator.GetRegisterOperand(0).index(), reg_1.index());
  EXPECT_EQ(iterator.GetRegisterOperandRange(0), 1);
204 205 206 207
  CHECK(!iterator.done());
  offset += Bytecodes::Size(Bytecode::kStar, OperandScale::kSingle);
  iterator.Advance();

208 209 210 211 212
  EXPECT_EQ(iterator.current_bytecode(), Bytecode::kLdaNamedProperty);
  EXPECT_EQ(iterator.current_offset(), offset);
  EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
  EXPECT_EQ(iterator.GetRegisterOperand(0).index(), reg_1.index());
  EXPECT_EQ(iterator.GetIndexOperand(1), name_index);
213
  EXPECT_EQ(iterator.GetIndexOperand(2), load_feedback_slot);
214
  CHECK(!iterator.done());
215
  offset += Bytecodes::Size(Bytecode::kLdaNamedProperty, OperandScale::kSingle);
216 217
  iterator.Advance();

218 219 220 221 222
  EXPECT_EQ(iterator.current_bytecode(), Bytecode::kAdd);
  EXPECT_EQ(iterator.current_offset(), offset);
  EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
  EXPECT_EQ(iterator.GetRegisterOperand(0).index(), reg_0.index());
  EXPECT_EQ(iterator.GetRegisterOperandRange(0), 1);
223
  CHECK(!iterator.done());
224
  offset += Bytecodes::Size(Bytecode::kAdd, OperandScale::kSingle);
225 226
  iterator.Advance();

227 228 229 230 231
  EXPECT_EQ(iterator.current_bytecode(), Bytecode::kStar);
  EXPECT_EQ(iterator.current_offset(), offset);
  EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
  EXPECT_EQ(iterator.GetRegisterOperand(0).index(), param.index());
  EXPECT_EQ(iterator.GetRegisterOperandRange(0), 1);
232 233 234 235
  CHECK(!iterator.done());
  offset += Bytecodes::Size(Bytecode::kStar, OperandScale::kSingle);
  iterator.Advance();

236 237 238 239 240 241 242 243 244
  EXPECT_EQ(iterator.current_bytecode(), Bytecode::kCallRuntimeForPair);
  EXPECT_EQ(iterator.current_offset(), offset);
  EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
  EXPECT_EQ(iterator.GetRuntimeIdOperand(0), Runtime::kLoadLookupSlotForCall);
  EXPECT_EQ(iterator.GetRegisterOperand(1).index(), param.index());
  EXPECT_EQ(iterator.GetRegisterOperandRange(1), 1);
  EXPECT_EQ(iterator.GetRegisterCountOperand(2), 1u);
  EXPECT_EQ(iterator.GetRegisterOperand(3).index(), reg_0.index());
  EXPECT_EQ(iterator.GetRegisterOperandRange(3), 2);
245 246 247 248 249
  CHECK(!iterator.done());
  offset +=
      Bytecodes::Size(Bytecode::kCallRuntimeForPair, OperandScale::kSingle);
  iterator.Advance();

250 251 252 253 254
  EXPECT_EQ(iterator.current_bytecode(), Bytecode::kForInPrepare);
  EXPECT_EQ(iterator.current_offset(), offset);
  EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
  EXPECT_EQ(iterator.GetRegisterOperand(0).index(), reg_0.index());
  EXPECT_EQ(iterator.GetRegisterOperandRange(0), 3);
255
  EXPECT_EQ(iterator.GetIndexOperand(1), forin_feedback_slot);
256
  CHECK(!iterator.done());
257
  offset += Bytecodes::Size(Bytecode::kForInPrepare, OperandScale::kSingle);
258 259
  iterator.Advance();

260 261 262 263 264 265
  EXPECT_EQ(iterator.current_bytecode(), Bytecode::kCallRuntime);
  EXPECT_EQ(iterator.current_offset(), offset);
  EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
  EXPECT_EQ(iterator.GetRuntimeIdOperand(0), Runtime::kLoadIC_Miss);
  EXPECT_EQ(iterator.GetRegisterOperand(1).index(), reg_0.index());
  EXPECT_EQ(iterator.GetRegisterCountOperand(2), 1u);
266
  CHECK(!iterator.done());
267
  offset += Bytecodes::Size(Bytecode::kCallRuntime, OperandScale::kSingle);
268 269
  iterator.Advance();

270 271 272
  EXPECT_EQ(iterator.current_bytecode(), Bytecode::kDebugger);
  EXPECT_EQ(iterator.current_offset(), offset);
  EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
273
  CHECK(!iterator.done());
274
  offset += Bytecodes::Size(Bytecode::kDebugger, OperandScale::kSingle);
275 276
  iterator.Advance();

277 278
  EXPECT_EQ(iterator.current_bytecode(), Bytecode::kLdaGlobal);
  EXPECT_EQ(iterator.current_offset(), offset);
279 280 281 282
  EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
  EXPECT_EQ(iterator.current_bytecode_size(), 3);
  EXPECT_EQ(iterator.GetIndexOperand(1), load_global_feedback_slot);
  offset += Bytecodes::Size(Bytecode::kLdaGlobal, OperandScale::kSingle);
283 284
  iterator.Advance();

285 286 287
  EXPECT_EQ(iterator.current_bytecode(), Bytecode::kReturn);
  EXPECT_EQ(iterator.current_offset(), offset);
  EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
288 289 290 291 292 293 294 295
  CHECK(!iterator.done());
  iterator.Advance();
  CHECK(iterator.done());
}

}  // namespace interpreter
}  // namespace internal
}  // namespace v8