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