1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "base/logging.h" 18 #include "compiler_ir.h" 19 #include "dataflow_iterator-inl.h" 20 #include "dex_flags.h" 21 #include "dex/mir_field_info.h" 22 #include "dex/mir_graph.h" 23 #include "driver/dex_compilation_unit.h" 24 #include "gtest/gtest.h" 25 #include "type_inference.h" 26 #include "utils/test_dex_file_builder.h" 27 28 namespace art { 29 30 class TypeInferenceTest : public testing::Test { 31 protected: 32 struct TypeDef { 33 const char* descriptor; 34 }; 35 36 struct FieldDef { 37 const char* class_descriptor; 38 const char* type; 39 const char* name; 40 }; 41 42 struct MethodDef { 43 const char* class_descriptor; 44 const char* signature; 45 const char* name; 46 InvokeType type; 47 }; 48 49 struct BBDef { 50 static constexpr size_t kMaxSuccessors = 4; 51 static constexpr size_t kMaxPredecessors = 4; 52 53 BBType type; 54 size_t num_successors; 55 BasicBlockId successors[kMaxPredecessors]; 56 size_t num_predecessors; 57 BasicBlockId predecessors[kMaxPredecessors]; 58 }; 59 60 struct MIRDef { 61 static constexpr size_t kMaxSsaDefs = 2; 62 static constexpr size_t kMaxSsaUses = 4; 63 64 BasicBlockId bbid; 65 Instruction::Code opcode; 66 int64_t value; 67 uint32_t metadata; 68 size_t num_uses; 69 int32_t uses[kMaxSsaUses]; 70 size_t num_defs; 71 int32_t defs[kMaxSsaDefs]; 72 }; 73 74 #define DEF_SUCC0() \ 75 0u, { } 76 #define DEF_SUCC1(s1) \ 77 1u, { s1 } 78 #define DEF_SUCC2(s1, s2) \ 79 2u, { s1, s2 } 80 #define DEF_SUCC3(s1, s2, s3) \ 81 3u, { s1, s2, s3 } 82 #define DEF_SUCC4(s1, s2, s3, s4) \ 83 4u, { s1, s2, s3, s4 } 84 #define DEF_PRED0() \ 85 0u, { } 86 #define DEF_PRED1(p1) \ 87 1u, { p1 } 88 #define DEF_PRED2(p1, p2) \ 89 2u, { p1, p2 } 90 #define DEF_PRED3(p1, p2, p3) \ 91 3u, { p1, p2, p3 } 92 #define DEF_PRED4(p1, p2, p3, p4) \ 93 4u, { p1, p2, p3, p4 } 94 #define DEF_BB(type, succ, pred) \ 95 { type, succ, pred } 96 97 #define DEF_CONST(bb, opcode, reg, value) \ 98 { bb, opcode, value, 0u, 0, { }, 1, { reg } } 99 #define DEF_CONST_WIDE(bb, opcode, reg, value) \ 100 { bb, opcode, value, 0u, 0, { }, 2, { reg, reg + 1 } } 101 #define DEF_CONST_STRING(bb, opcode, reg, index) \ 102 { bb, opcode, index, 0u, 0, { }, 1, { reg } } 103 #define DEF_IGET(bb, opcode, reg, obj, field_info) \ 104 { bb, opcode, 0u, field_info, 1, { obj }, 1, { reg } } 105 #define DEF_IGET_WIDE(bb, opcode, reg, obj, field_info) \ 106 { bb, opcode, 0u, field_info, 1, { obj }, 2, { reg, reg + 1 } } 107 #define DEF_IPUT(bb, opcode, reg, obj, field_info) \ 108 { bb, opcode, 0u, field_info, 2, { reg, obj }, 0, { } } 109 #define DEF_IPUT_WIDE(bb, opcode, reg, obj, field_info) \ 110 { bb, opcode, 0u, field_info, 3, { reg, reg + 1, obj }, 0, { } } 111 #define DEF_SGET(bb, opcode, reg, field_info) \ 112 { bb, opcode, 0u, field_info, 0, { }, 1, { reg } } 113 #define DEF_SGET_WIDE(bb, opcode, reg, field_info) \ 114 { bb, opcode, 0u, field_info, 0, { }, 2, { reg, reg + 1 } } 115 #define DEF_SPUT(bb, opcode, reg, field_info) \ 116 { bb, opcode, 0u, field_info, 1, { reg }, 0, { } } 117 #define DEF_SPUT_WIDE(bb, opcode, reg, field_info) \ 118 { bb, opcode, 0u, field_info, 2, { reg, reg + 1 }, 0, { } } 119 #define DEF_AGET(bb, opcode, reg, obj, idx) \ 120 { bb, opcode, 0u, 0u, 2, { obj, idx }, 1, { reg } } 121 #define DEF_AGET_WIDE(bb, opcode, reg, obj, idx) \ 122 { bb, opcode, 0u, 0u, 2, { obj, idx }, 2, { reg, reg + 1 } } 123 #define DEF_APUT(bb, opcode, reg, obj, idx) \ 124 { bb, opcode, 0u, 0u, 3, { reg, obj, idx }, 0, { } } 125 #define DEF_APUT_WIDE(bb, opcode, reg, obj, idx) \ 126 { bb, opcode, 0u, 0u, 4, { reg, reg + 1, obj, idx }, 0, { } } 127 #define DEF_INVOKE0(bb, opcode, method_idx) \ 128 { bb, opcode, 0u, method_idx, 0, { }, 0, { } } 129 #define DEF_INVOKE1(bb, opcode, reg, method_idx) \ 130 { bb, opcode, 0u, method_idx, 1, { reg }, 0, { } } 131 #define DEF_INVOKE2(bb, opcode, reg1, reg2, method_idx) \ 132 { bb, opcode, 0u, method_idx, 2, { reg1, reg2 }, 0, { } } 133 #define DEF_IFZ(bb, opcode, reg) \ 134 { bb, opcode, 0u, 0u, 1, { reg }, 0, { } } 135 #define DEF_MOVE(bb, opcode, reg, src) \ 136 { bb, opcode, 0u, 0u, 1, { src }, 1, { reg } } 137 #define DEF_MOVE_WIDE(bb, opcode, reg, src) \ 138 { bb, opcode, 0u, 0u, 2, { src, src + 1 }, 2, { reg, reg + 1 } } 139 #define DEF_PHI2(bb, reg, src1, src2) \ 140 { bb, static_cast<Instruction::Code>(kMirOpPhi), 0, 0u, 2u, { src1, src2 }, 1, { reg } } 141 #define DEF_BINOP(bb, opcode, result, src1, src2) \ 142 { bb, opcode, 0u, 0u, 2, { src1, src2 }, 1, { result } } 143 #define DEF_UNOP(bb, opcode, result, src) DEF_MOVE(bb, opcode, result, src) 144 #define DEF_NULOP(bb, opcode, result) DEF_CONST(bb, opcode, result, 0) 145 #define DEF_NULOP_WIDE(bb, opcode, result) DEF_CONST_WIDE(bb, opcode, result, 0) 146 #define DEF_CHECK_CAST(bb, opcode, reg, type) \ 147 { bb, opcode, 0, type, 1, { reg }, 0, { } } 148 #define DEF_NEW_ARRAY(bb, opcode, reg, length, type) \ 149 { bb, opcode, 0, type, 1, { length }, 1, { reg } } 150 151 void AddTypes(const TypeDef* defs, size_t count) { 152 for (size_t i = 0; i != count; ++i) { 153 const TypeDef* def = &defs[i]; 154 dex_file_builder_.AddType(def->descriptor); 155 } 156 } 157 158 template <size_t count> 159 void PrepareTypes(const TypeDef (&defs)[count]) { 160 type_defs_ = defs; 161 type_count_ = count; 162 AddTypes(defs, count); 163 } 164 165 void AddFields(const FieldDef* defs, size_t count) { 166 for (size_t i = 0; i != count; ++i) { 167 const FieldDef* def = &defs[i]; 168 dex_file_builder_.AddField(def->class_descriptor, def->type, def->name); 169 } 170 } 171 172 template <size_t count> 173 void PrepareIFields(const FieldDef (&defs)[count]) { 174 ifield_defs_ = defs; 175 ifield_count_ = count; 176 AddFields(defs, count); 177 } 178 179 template <size_t count> 180 void PrepareSFields(const FieldDef (&defs)[count]) { 181 sfield_defs_ = defs; 182 sfield_count_ = count; 183 AddFields(defs, count); 184 } 185 186 void AddMethods(const MethodDef* defs, size_t count) { 187 for (size_t i = 0; i != count; ++i) { 188 const MethodDef* def = &defs[i]; 189 dex_file_builder_.AddMethod(def->class_descriptor, def->signature, def->name); 190 } 191 } 192 193 template <size_t count> 194 void PrepareMethods(const MethodDef (&defs)[count]) { 195 method_defs_ = defs; 196 method_count_ = count; 197 AddMethods(defs, count); 198 } 199 200 DexMemAccessType AccessTypeForDescriptor(const char* descriptor) { 201 switch (descriptor[0]) { 202 case 'I': 203 case 'F': 204 return kDexMemAccessWord; 205 case 'J': 206 case 'D': 207 return kDexMemAccessWide; 208 case '[': 209 case 'L': 210 return kDexMemAccessObject; 211 case 'Z': 212 return kDexMemAccessBoolean; 213 case 'B': 214 return kDexMemAccessByte; 215 case 'C': 216 return kDexMemAccessChar; 217 case 'S': 218 return kDexMemAccessShort; 219 default: 220 LOG(FATAL) << "Bad descriptor: " << descriptor; 221 UNREACHABLE(); 222 } 223 } 224 225 size_t CountIns(const std::string& test_method_signature, bool is_static) { 226 const char* sig = test_method_signature.c_str(); 227 CHECK_EQ(sig[0], '('); 228 ++sig; 229 size_t result = is_static ? 0u : 1u; 230 while (*sig != ')') { 231 result += (AccessTypeForDescriptor(sig) == kDexMemAccessWide) ? 2u : 1u; 232 while (*sig == '[') { 233 ++sig; 234 } 235 if (*sig == 'L') { 236 do { 237 ++sig; 238 CHECK(*sig != '\0' && *sig != ')'); 239 } while (*sig != ';'); 240 } 241 ++sig; 242 } 243 return result; 244 } 245 246 void BuildDexFile(const std::string& test_method_signature, bool is_static) { 247 dex_file_builder_.AddMethod(kClassName, test_method_signature, kMethodName); 248 dex_file_ = dex_file_builder_.Build(kDexLocation); 249 cu_.dex_file = dex_file_.get(); 250 cu_.method_idx = dex_file_builder_.GetMethodIdx(kClassName, test_method_signature, kMethodName); 251 cu_.access_flags = is_static ? kAccStatic : 0u; 252 cu_.mir_graph->m_units_.push_back(new (cu_.mir_graph->arena_) DexCompilationUnit( 253 &cu_, cu_.class_loader, cu_.class_linker, *cu_.dex_file, nullptr /* code_item not used */, 254 0u /* class_def_idx not used */, 0u /* method_index not used */, 255 cu_.access_flags, nullptr /* verified_method not used */)); 256 cu_.mir_graph->current_method_ = 0u; 257 code_item_ = static_cast<DexFile::CodeItem*>( 258 cu_.arena.Alloc(sizeof(DexFile::CodeItem), kArenaAllocMisc)); 259 260 code_item_->ins_size_ = CountIns(test_method_signature, is_static); 261 code_item_->registers_size_ = kLocalVRs + code_item_->ins_size_; 262 cu_.mir_graph->current_code_item_ = code_item_; 263 cu_.mir_graph->num_ssa_regs_ = kMaxSsaRegs; 264 265 cu_.mir_graph->ifield_lowering_infos_.clear(); 266 cu_.mir_graph->ifield_lowering_infos_.reserve(ifield_count_); 267 for (size_t i = 0u; i != ifield_count_; ++i) { 268 const FieldDef* def = &ifield_defs_[i]; 269 uint32_t field_idx = 270 dex_file_builder_.GetFieldIdx(def->class_descriptor, def->type, def->name); 271 MirIFieldLoweringInfo field_info(field_idx, AccessTypeForDescriptor(def->type), false); 272 field_info.declaring_dex_file_ = cu_.dex_file; 273 field_info.declaring_field_idx_ = field_idx; 274 cu_.mir_graph->ifield_lowering_infos_.push_back(field_info); 275 } 276 277 cu_.mir_graph->sfield_lowering_infos_.clear(); 278 cu_.mir_graph->sfield_lowering_infos_.reserve(sfield_count_); 279 for (size_t i = 0u; i != sfield_count_; ++i) { 280 const FieldDef* def = &sfield_defs_[i]; 281 uint32_t field_idx = 282 dex_file_builder_.GetFieldIdx(def->class_descriptor, def->type, def->name); 283 MirSFieldLoweringInfo field_info(field_idx, AccessTypeForDescriptor(def->type)); 284 field_info.declaring_dex_file_ = cu_.dex_file; 285 field_info.declaring_field_idx_ = field_idx; 286 cu_.mir_graph->sfield_lowering_infos_.push_back(field_info); 287 } 288 289 cu_.mir_graph->method_lowering_infos_.clear(); 290 cu_.mir_graph->method_lowering_infos_.reserve(ifield_count_); 291 for (size_t i = 0u; i != method_count_; ++i) { 292 const MethodDef* def = &method_defs_[i]; 293 uint32_t method_idx = 294 dex_file_builder_.GetMethodIdx(def->class_descriptor, def->signature, def->name); 295 MirMethodLoweringInfo method_info(method_idx, def->type, false); 296 method_info.declaring_dex_file_ = cu_.dex_file; 297 method_info.declaring_method_idx_ = method_idx; 298 cu_.mir_graph->method_lowering_infos_.push_back(method_info); 299 } 300 } 301 302 void DoPrepareBasicBlocks(const BBDef* defs, size_t count) { 303 cu_.mir_graph->block_id_map_.clear(); 304 cu_.mir_graph->block_list_.clear(); 305 ASSERT_LT(3u, count); // null, entry, exit and at least one bytecode block. 306 ASSERT_EQ(kNullBlock, defs[0].type); 307 ASSERT_EQ(kEntryBlock, defs[1].type); 308 ASSERT_EQ(kExitBlock, defs[2].type); 309 for (size_t i = 0u; i != count; ++i) { 310 const BBDef* def = &defs[i]; 311 BasicBlock* bb = cu_.mir_graph->CreateNewBB(def->type); 312 if (def->num_successors <= 2) { 313 bb->successor_block_list_type = kNotUsed; 314 bb->fall_through = (def->num_successors >= 1) ? def->successors[0] : 0u; 315 bb->taken = (def->num_successors >= 2) ? def->successors[1] : 0u; 316 } else { 317 bb->successor_block_list_type = kPackedSwitch; 318 bb->fall_through = 0u; 319 bb->taken = 0u; 320 bb->successor_blocks.reserve(def->num_successors); 321 for (size_t j = 0u; j != def->num_successors; ++j) { 322 SuccessorBlockInfo* successor_block_info = 323 static_cast<SuccessorBlockInfo*>(cu_.arena.Alloc(sizeof(SuccessorBlockInfo), 324 kArenaAllocSuccessor)); 325 successor_block_info->block = j; 326 successor_block_info->key = 0u; // Not used by class init check elimination. 327 bb->successor_blocks.push_back(successor_block_info); 328 } 329 } 330 bb->predecessors.assign(def->predecessors, def->predecessors + def->num_predecessors); 331 if (def->type == kDalvikByteCode || def->type == kEntryBlock || def->type == kExitBlock) { 332 bb->data_flow_info = static_cast<BasicBlockDataFlow*>( 333 cu_.arena.Alloc(sizeof(BasicBlockDataFlow), kArenaAllocDFInfo)); 334 bb->data_flow_info->live_in_v = live_in_v_; 335 } 336 } 337 ASSERT_EQ(count, cu_.mir_graph->block_list_.size()); 338 cu_.mir_graph->entry_block_ = cu_.mir_graph->block_list_[1]; 339 ASSERT_EQ(kEntryBlock, cu_.mir_graph->entry_block_->block_type); 340 cu_.mir_graph->exit_block_ = cu_.mir_graph->block_list_[2]; 341 ASSERT_EQ(kExitBlock, cu_.mir_graph->exit_block_->block_type); 342 } 343 344 template <size_t count> 345 void PrepareBasicBlocks(const BBDef (&defs)[count]) { 346 DoPrepareBasicBlocks(defs, count); 347 } 348 349 void PrepareSingleBlock() { 350 static const BBDef bbs[] = { 351 DEF_BB(kNullBlock, DEF_SUCC0(), DEF_PRED0()), 352 DEF_BB(kEntryBlock, DEF_SUCC1(3), DEF_PRED0()), 353 DEF_BB(kExitBlock, DEF_SUCC0(), DEF_PRED1(3)), 354 DEF_BB(kDalvikByteCode, DEF_SUCC1(2), DEF_PRED1(1)), 355 }; 356 PrepareBasicBlocks(bbs); 357 } 358 359 void PrepareDiamond() { 360 static const BBDef bbs[] = { 361 DEF_BB(kNullBlock, DEF_SUCC0(), DEF_PRED0()), 362 DEF_BB(kEntryBlock, DEF_SUCC1(3), DEF_PRED0()), 363 DEF_BB(kExitBlock, DEF_SUCC0(), DEF_PRED1(6)), 364 DEF_BB(kDalvikByteCode, DEF_SUCC2(4, 5), DEF_PRED1(1)), 365 DEF_BB(kDalvikByteCode, DEF_SUCC1(6), DEF_PRED1(3)), 366 DEF_BB(kDalvikByteCode, DEF_SUCC1(6), DEF_PRED1(3)), 367 DEF_BB(kDalvikByteCode, DEF_SUCC1(2), DEF_PRED2(4, 5)), 368 }; 369 PrepareBasicBlocks(bbs); 370 } 371 372 void PrepareLoop() { 373 static const BBDef bbs[] = { 374 DEF_BB(kNullBlock, DEF_SUCC0(), DEF_PRED0()), 375 DEF_BB(kEntryBlock, DEF_SUCC1(3), DEF_PRED0()), 376 DEF_BB(kExitBlock, DEF_SUCC0(), DEF_PRED1(5)), 377 DEF_BB(kDalvikByteCode, DEF_SUCC1(4), DEF_PRED1(1)), 378 DEF_BB(kDalvikByteCode, DEF_SUCC2(5, 4), DEF_PRED2(3, 4)), // "taken" loops to self. 379 DEF_BB(kDalvikByteCode, DEF_SUCC1(2), DEF_PRED1(4)), 380 }; 381 PrepareBasicBlocks(bbs); 382 } 383 384 void DoPrepareMIRs(const MIRDef* defs, size_t count) { 385 mir_count_ = count; 386 mirs_ = cu_.arena.AllocArray<MIR>(count, kArenaAllocMIR); 387 ssa_reps_.resize(count); 388 for (size_t i = 0u; i != count; ++i) { 389 const MIRDef* def = &defs[i]; 390 MIR* mir = &mirs_[i]; 391 ASSERT_LT(def->bbid, cu_.mir_graph->block_list_.size()); 392 BasicBlock* bb = cu_.mir_graph->block_list_[def->bbid]; 393 bb->AppendMIR(mir); 394 mir->dalvikInsn.opcode = def->opcode; 395 mir->dalvikInsn.vB = static_cast<int32_t>(def->value); 396 mir->dalvikInsn.vB_wide = def->value; 397 if (IsInstructionIGetOrIPut(def->opcode)) { 398 ASSERT_LT(def->metadata, cu_.mir_graph->ifield_lowering_infos_.size()); 399 mir->meta.ifield_lowering_info = def->metadata; 400 ASSERT_EQ(cu_.mir_graph->ifield_lowering_infos_[def->metadata].MemAccessType(), 401 IGetOrIPutMemAccessType(def->opcode)); 402 cu_.mir_graph->merged_df_flags_ |= DF_IFIELD; 403 } else if (IsInstructionSGetOrSPut(def->opcode)) { 404 ASSERT_LT(def->metadata, cu_.mir_graph->sfield_lowering_infos_.size()); 405 mir->meta.sfield_lowering_info = def->metadata; 406 ASSERT_EQ(cu_.mir_graph->sfield_lowering_infos_[def->metadata].MemAccessType(), 407 SGetOrSPutMemAccessType(def->opcode)); 408 cu_.mir_graph->merged_df_flags_ |= DF_SFIELD; 409 } else if (IsInstructionInvoke(def->opcode)) { 410 ASSERT_LT(def->metadata, cu_.mir_graph->method_lowering_infos_.size()); 411 mir->meta.method_lowering_info = def->metadata; 412 mir->dalvikInsn.vA = def->num_uses; 413 cu_.mir_graph->merged_df_flags_ |= DF_FORMAT_35C; 414 } else if (def->opcode == static_cast<Instruction::Code>(kMirOpPhi)) { 415 mir->meta.phi_incoming = 416 allocator_->AllocArray<BasicBlockId>(def->num_uses, kArenaAllocDFInfo); 417 ASSERT_EQ(def->num_uses, bb->predecessors.size()); 418 std::copy(bb->predecessors.begin(), bb->predecessors.end(), mir->meta.phi_incoming); 419 } else if (def->opcode == Instruction::CHECK_CAST) { 420 ASSERT_LT(def->metadata, type_count_); 421 mir->dalvikInsn.vB = dex_file_builder_.GetTypeIdx(type_defs_[def->metadata].descriptor); 422 cu_.mir_graph->merged_df_flags_ |= DF_CHK_CAST; 423 } else if (def->opcode == Instruction::NEW_ARRAY) { 424 ASSERT_LT(def->metadata, type_count_); 425 mir->dalvikInsn.vC = dex_file_builder_.GetTypeIdx(type_defs_[def->metadata].descriptor); 426 } 427 mir->ssa_rep = &ssa_reps_[i]; 428 mir->ssa_rep->num_uses = def->num_uses; 429 mir->ssa_rep->uses = const_cast<int32_t*>(def->uses); // Not modified by LVN. 430 mir->ssa_rep->num_defs = def->num_defs; 431 mir->ssa_rep->defs = const_cast<int32_t*>(def->defs); // Not modified by LVN. 432 mir->dalvikInsn.opcode = def->opcode; 433 mir->offset = i; // LVN uses offset only for debug output 434 mir->optimization_flags = 0u; 435 } 436 code_item_->insns_size_in_code_units_ = 2u * count; 437 } 438 439 template <size_t count> 440 void PrepareMIRs(const MIRDef (&defs)[count]) { 441 DoPrepareMIRs(defs, count); 442 } 443 444 // BasicBlockDataFlow::vreg_to_ssa_map_exit is used only for check-casts. 445 void AllocEndingVRegToSRegMaps() { 446 AllNodesIterator iterator(cu_.mir_graph.get()); 447 for (BasicBlock* bb = iterator.Next(); bb != nullptr; bb = iterator.Next()) { 448 if (bb->data_flow_info != nullptr) { 449 if (bb->data_flow_info->vreg_to_ssa_map_exit == nullptr) { 450 size_t num_vregs = code_item_->registers_size_; 451 bb->data_flow_info->vreg_to_ssa_map_exit = static_cast<int32_t*>( 452 cu_.arena.AllocArray<int32_t>(num_vregs, kArenaAllocDFInfo)); 453 std::fill_n(bb->data_flow_info->vreg_to_ssa_map_exit, num_vregs, INVALID_SREG); 454 } 455 } 456 } 457 } 458 459 template <size_t count> 460 void MapVRegToSReg(int vreg, int32_t sreg, const BasicBlockId (&bb_ids)[count]) { 461 AllocEndingVRegToSRegMaps(); 462 for (BasicBlockId bb_id : bb_ids) { 463 BasicBlock* bb = cu_.mir_graph->GetBasicBlock(bb_id); 464 CHECK(bb != nullptr); 465 CHECK(bb->data_flow_info != nullptr); 466 CHECK(bb->data_flow_info->vreg_to_ssa_map_exit != nullptr); 467 bb->data_flow_info->vreg_to_ssa_map_exit[vreg] = sreg; 468 } 469 } 470 471 void PerformTypeInference() { 472 cu_.mir_graph->SSATransformationStart(); 473 cu_.mir_graph->ComputeDFSOrders(); 474 cu_.mir_graph->ComputeDominators(); 475 cu_.mir_graph->ComputeTopologicalSortOrder(); 476 cu_.mir_graph->SSATransformationEnd(); 477 ASSERT_TRUE(type_inference_ == nullptr); 478 type_inference_.reset(new (allocator_.get()) TypeInference(cu_.mir_graph.get(), 479 allocator_.get())); 480 RepeatingPreOrderDfsIterator iter(cu_.mir_graph.get()); 481 bool changed = false; 482 for (BasicBlock* bb = iter.Next(changed); bb != nullptr; bb = iter.Next(changed)) { 483 changed = type_inference_->Apply(bb); 484 } 485 type_inference_->Finish(); 486 } 487 488 TypeInferenceTest() 489 : pool_(), 490 cu_(&pool_, kRuntimeISA, nullptr, nullptr), 491 mir_count_(0u), 492 mirs_(nullptr), 493 code_item_(nullptr), 494 ssa_reps_(), 495 allocator_(), 496 live_in_v_(new (&cu_.arena) ArenaBitVector(&cu_.arena, kMaxSsaRegs, false, kBitMapMisc)), 497 type_defs_(nullptr), 498 type_count_(0u), 499 ifield_defs_(nullptr), 500 ifield_count_(0u), 501 sfield_defs_(nullptr), 502 sfield_count_(0u), 503 method_defs_(nullptr), 504 method_count_(0u), 505 dex_file_builder_(), 506 dex_file_(nullptr) { 507 cu_.mir_graph.reset(new MIRGraph(&cu_, &cu_.arena)); 508 allocator_.reset(ScopedArenaAllocator::Create(&cu_.arena_stack)); 509 // Bind all possible sregs to live vregs for test purposes. 510 live_in_v_->SetInitialBits(kMaxSsaRegs); 511 cu_.mir_graph->reg_location_ = static_cast<RegLocation*>(cu_.arena.Alloc( 512 kMaxSsaRegs * sizeof(cu_.mir_graph->reg_location_[0]), kArenaAllocRegAlloc)); 513 cu_.mir_graph->method_sreg_ = kMaxSsaRegs - 1u; 514 cu_.mir_graph->reg_location_[cu_.mir_graph->GetMethodSReg()].location = kLocCompilerTemp; 515 // Bind all possible sregs to live vregs for test purposes. 516 live_in_v_->SetInitialBits(kMaxSsaRegs); 517 cu_.mir_graph->ssa_base_vregs_.reserve(kMaxSsaRegs); 518 cu_.mir_graph->ssa_subscripts_.reserve(kMaxSsaRegs); 519 for (unsigned int i = 0; i < kMaxSsaRegs; i++) { 520 cu_.mir_graph->ssa_base_vregs_.push_back(i); 521 cu_.mir_graph->ssa_subscripts_.push_back(0); 522 } 523 } 524 525 enum ExpectFlags : uint32_t { 526 kExpectWide = 0x0001u, 527 kExpectNarrow = 0x0002u, 528 kExpectFp = 0x0004u, 529 kExpectCore = 0x0008u, 530 kExpectRef = 0x0010u, 531 kExpectArrayWide = 0x0020u, 532 kExpectArrayNarrow = 0x0040u, 533 kExpectArrayFp = 0x0080u, 534 kExpectArrayCore = 0x0100u, 535 kExpectArrayRef = 0x0200u, 536 kExpectNull = 0x0400u, 537 kExpectHigh = 0x0800u, // Reserved for ExpectSRegType(). 538 }; 539 540 struct SRegExpectation { 541 uint32_t array_depth; 542 uint32_t flags; 543 }; 544 545 void ExpectSRegType(int s_reg, const SRegExpectation& expectation, bool check_loc = true) { 546 uint32_t flags = expectation.flags; 547 uint32_t array_depth = expectation.array_depth; 548 TypeInference::Type type = type_inference_->sregs_[s_reg]; 549 550 if (check_loc) { 551 RegLocation loc = cu_.mir_graph->reg_location_[s_reg]; 552 EXPECT_EQ((flags & kExpectWide) != 0u, loc.wide) << s_reg; 553 EXPECT_EQ((flags & kExpectFp) != 0u, loc.fp) << s_reg; 554 EXPECT_EQ((flags & kExpectCore) != 0u, loc.core) << s_reg; 555 EXPECT_EQ((flags & kExpectRef) != 0u, loc.ref) << s_reg; 556 EXPECT_EQ((flags & kExpectHigh) != 0u, loc.high_word) << s_reg; 557 } 558 559 EXPECT_EQ((flags & kExpectWide) != 0u, type.Wide()) << s_reg; 560 EXPECT_EQ((flags & kExpectNarrow) != 0u, type.Narrow()) << s_reg; 561 EXPECT_EQ((flags & kExpectFp) != 0u, type.Fp()) << s_reg; 562 EXPECT_EQ((flags & kExpectCore) != 0u, type.Core()) << s_reg; 563 EXPECT_EQ((flags & kExpectRef) != 0u, type.Ref()) << s_reg; 564 EXPECT_EQ((flags & kExpectHigh) == 0u, type.LowWord()) << s_reg; 565 EXPECT_EQ((flags & kExpectHigh) != 0u, type.HighWord()) << s_reg; 566 567 if ((flags & kExpectRef) != 0u) { 568 EXPECT_EQ((flags & kExpectNull) != 0u, !type.NonNull()) << s_reg; 569 } else { 570 // Null should be checked only for references. 571 ASSERT_EQ((flags & kExpectNull), 0u); 572 } 573 574 ASSERT_EQ(array_depth, type.ArrayDepth()) << s_reg; 575 if (array_depth != 0u) { 576 ASSERT_NE((flags & kExpectRef), 0u); 577 TypeInference::Type nested_type = type.NestedType(); 578 EXPECT_EQ((flags & kExpectArrayWide) != 0u, nested_type.Wide()) << s_reg; 579 EXPECT_EQ((flags & kExpectArrayNarrow) != 0u, nested_type.Narrow()) << s_reg; 580 EXPECT_EQ((flags & kExpectArrayFp) != 0u, nested_type.Fp()) << s_reg; 581 EXPECT_EQ((flags & kExpectArrayCore) != 0u, nested_type.Core()) << s_reg; 582 EXPECT_EQ((flags & kExpectArrayRef) != 0u, nested_type.Ref()) << s_reg; 583 } 584 if (!type.Narrow() && type.LowWord() && 585 (expectation.flags & (kExpectWide | kExpectNarrow | kExpectHigh)) == kExpectWide) { 586 SRegExpectation high_expectation = { array_depth, flags | kExpectHigh }; 587 ExpectSRegType(s_reg + 1, high_expectation); 588 } 589 } 590 591 void ExpectCore(int s_reg, bool core) { 592 EXPECT_EQ(core, type_inference_->sregs_[s_reg].Core()); 593 } 594 595 void ExpectRef(int s_reg, bool ref) { 596 EXPECT_EQ(ref, type_inference_->sregs_[s_reg].Ref()); 597 } 598 599 void ExpectArrayDepth(int s_reg, uint32_t array_depth) { 600 EXPECT_EQ(array_depth, type_inference_->sregs_[s_reg].ArrayDepth()); 601 } 602 603 static constexpr size_t kMaxSsaRegs = 16384u; 604 static constexpr uint16_t kLocalVRs = 1000u; 605 606 static constexpr const char* kDexLocation = "TypeInferenceDexFile;"; 607 static constexpr const char* kClassName = "LTypeInferenceTest;"; 608 static constexpr const char* kMethodName = "test"; 609 610 ArenaPool pool_; 611 CompilationUnit cu_; 612 size_t mir_count_; 613 MIR* mirs_; 614 DexFile::CodeItem* code_item_; 615 std::vector<SSARepresentation> ssa_reps_; 616 std::unique_ptr<ScopedArenaAllocator> allocator_; 617 std::unique_ptr<TypeInference> type_inference_; 618 ArenaBitVector* live_in_v_; 619 620 const TypeDef* type_defs_; 621 size_t type_count_; 622 const FieldDef* ifield_defs_; 623 size_t ifield_count_; 624 const FieldDef* sfield_defs_; 625 size_t sfield_count_; 626 const MethodDef* method_defs_; 627 size_t method_count_; 628 629 TestDexFileBuilder dex_file_builder_; 630 std::unique_ptr<const DexFile> dex_file_; 631 }; 632 633 TEST_F(TypeInferenceTest, IGet) { 634 static const FieldDef ifields[] = { 635 { kClassName, "B", "byteField" }, 636 { kClassName, "C", "charField" }, 637 { kClassName, "D", "doubleField" }, 638 { kClassName, "F", "floatField" }, 639 { kClassName, "I", "intField" }, 640 { kClassName, "J", "longField" }, 641 { kClassName, "S", "shortField" }, 642 { kClassName, "Z", "booleanField" }, 643 { kClassName, "Ljava/lang/Object;", "objectField" }, 644 { kClassName, "[Ljava/lang/Object;", "objectArrayField" }, 645 }; 646 constexpr uint32_t thiz = kLocalVRs; 647 static const MIRDef mirs[] = { 648 DEF_IGET(3u, Instruction::IGET_BYTE, 0u, thiz, 0u), 649 DEF_IGET(3u, Instruction::IGET_CHAR, 1u, thiz, 1u), 650 DEF_IGET_WIDE(3u, Instruction::IGET_WIDE, 2u, thiz, 2u), 651 DEF_IGET(3u, Instruction::IGET, 4u, thiz, 3u), 652 DEF_IGET(3u, Instruction::IGET, 5u, thiz, 4u), 653 DEF_IGET_WIDE(3u, Instruction::IGET_WIDE, 6u, thiz, 5u), 654 DEF_IGET(3u, Instruction::IGET_SHORT, 8u, thiz, 6u), 655 DEF_IGET(3u, Instruction::IGET_BOOLEAN, 9u, thiz, 7u), 656 DEF_IGET(3u, Instruction::IGET_OBJECT, 10u, thiz, 8u), 657 DEF_IGET(3u, Instruction::IGET_OBJECT, 11u, thiz, 9u), 658 }; 659 660 PrepareIFields(ifields); 661 BuildDexFile("()V", false); 662 PrepareSingleBlock(); 663 PrepareMIRs(mirs); 664 PerformTypeInference(); 665 666 ASSERT_EQ(arraysize(mirs), mir_count_); 667 static const SRegExpectation expectations[] = { 668 { 0u, kExpectCore | kExpectNarrow }, 669 { 0u, kExpectCore | kExpectNarrow }, 670 { 0u, kExpectFp | kExpectWide }, 671 { 0u, kExpectFp | kExpectNarrow }, 672 { 0u, kExpectCore | kExpectNarrow }, 673 { 0u, kExpectCore | kExpectWide }, 674 { 0u, kExpectCore | kExpectNarrow }, 675 { 0u, kExpectCore | kExpectNarrow }, 676 { 0u, kExpectRef | kExpectNarrow }, 677 { 1u, kExpectRef | kExpectNarrow | kExpectArrayRef | kExpectArrayNarrow }, 678 }; 679 static_assert(arraysize(expectations) == arraysize(mirs), "array size mismatch"); 680 for (size_t i = 0; i != arraysize(expectations); ++i) { 681 EXPECT_EQ(mirs[i].opcode, mirs_[i].dalvikInsn.opcode); 682 ASSERT_LE(1u, mirs_[i].ssa_rep->num_defs); 683 ExpectSRegType(mirs_[i].ssa_rep->defs[0], expectations[i]); 684 } 685 EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u); 686 EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter()); 687 } 688 689 TEST_F(TypeInferenceTest, SGet) { 690 static const FieldDef sfields[] = { 691 { kClassName, "B", "staticByteField" }, 692 { kClassName, "C", "staticCharField" }, 693 { kClassName, "D", "staticDoubleField" }, 694 { kClassName, "F", "staticFloatField" }, 695 { kClassName, "I", "staticIntField" }, 696 { kClassName, "J", "staticLongField" }, 697 { kClassName, "S", "staticShortField" }, 698 { kClassName, "Z", "staticBooleanField" }, 699 { kClassName, "Ljava/lang/Object;", "staticObjectField" }, 700 { kClassName, "[Ljava/lang/Object;", "staticObjectArrayField" }, 701 }; 702 static const MIRDef mirs[] = { 703 DEF_SGET(3u, Instruction::SGET_BYTE, 0u, 0u), 704 DEF_SGET(3u, Instruction::SGET_CHAR, 1u, 1u), 705 DEF_SGET_WIDE(3u, Instruction::SGET_WIDE, 2u, 2u), 706 DEF_SGET(3u, Instruction::SGET, 4u, 3u), 707 DEF_SGET(3u, Instruction::SGET, 5u, 4u), 708 DEF_SGET_WIDE(3u, Instruction::SGET_WIDE, 6u, 5u), 709 DEF_SGET(3u, Instruction::SGET_SHORT, 8u, 6u), 710 DEF_SGET(3u, Instruction::SGET_BOOLEAN, 9u, 7u), 711 DEF_SGET(3u, Instruction::SGET_OBJECT, 10u, 8u), 712 DEF_SGET(3u, Instruction::SGET_OBJECT, 11u, 9u), 713 }; 714 715 PrepareSFields(sfields); 716 BuildDexFile("()V", true); 717 PrepareSingleBlock(); 718 PrepareMIRs(mirs); 719 PerformTypeInference(); 720 721 ASSERT_EQ(arraysize(mirs), mir_count_); 722 static const SRegExpectation expectations[] = { 723 { 0u, kExpectCore | kExpectNarrow }, 724 { 0u, kExpectCore | kExpectNarrow }, 725 { 0u, kExpectFp | kExpectWide }, 726 { 0u, kExpectFp | kExpectNarrow }, 727 { 0u, kExpectCore | kExpectNarrow }, 728 { 0u, kExpectCore | kExpectWide }, 729 { 0u, kExpectCore | kExpectNarrow }, 730 { 0u, kExpectCore | kExpectNarrow }, 731 { 0u, kExpectRef | kExpectNarrow }, 732 { 1u, kExpectRef | kExpectNarrow | kExpectArrayRef | kExpectArrayNarrow }, 733 }; 734 static_assert(arraysize(expectations) == arraysize(mirs), "array size mismatch"); 735 for (size_t i = 0; i != arraysize(expectations); ++i) { 736 EXPECT_EQ(mirs[i].opcode, mirs_[i].dalvikInsn.opcode); 737 ASSERT_LE(1u, mirs_[i].ssa_rep->num_defs); 738 ExpectSRegType(mirs_[i].ssa_rep->defs[0], expectations[i]); 739 } 740 EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u); 741 EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter()); 742 } 743 744 TEST_F(TypeInferenceTest, IPut) { 745 static const FieldDef ifields[] = { 746 { kClassName, "B", "byteField" }, 747 { kClassName, "C", "charField" }, 748 { kClassName, "D", "doubleField" }, 749 { kClassName, "F", "floatField" }, 750 { kClassName, "I", "intField" }, 751 { kClassName, "J", "longField" }, 752 { kClassName, "S", "shortField" }, 753 { kClassName, "Z", "booleanField" }, 754 { kClassName, "Ljava/lang/Object;", "objectField" }, 755 { kClassName, "[Ljava/lang/Object;", "objectArrayField" }, 756 }; 757 constexpr uint32_t thiz = kLocalVRs; 758 static const MIRDef mirs[] = { 759 DEF_CONST(3u, Instruction::CONST, 0u, 0), 760 DEF_IPUT(3u, Instruction::IPUT_BYTE, 0u, thiz, 0u), 761 DEF_CONST(3u, Instruction::CONST, 1u, 0), 762 DEF_IPUT(3u, Instruction::IPUT_CHAR, 1u, thiz, 1u), 763 DEF_CONST_WIDE(3u, Instruction::CONST_WIDE, 2u, 0), 764 DEF_IPUT_WIDE(3u, Instruction::IPUT_WIDE, 2u, thiz, 2u), 765 DEF_CONST(3u, Instruction::CONST, 4u, 0), 766 DEF_IPUT(3u, Instruction::IPUT, 4u, thiz, 3u), 767 DEF_CONST(3u, Instruction::CONST, 5u, 0), 768 DEF_IPUT(3u, Instruction::IPUT, 5u, thiz, 4u), 769 DEF_CONST_WIDE(3u, Instruction::CONST_WIDE, 6u, 0), 770 DEF_IPUT_WIDE(3u, Instruction::IPUT_WIDE, 6u, thiz, 5u), 771 DEF_CONST(3u, Instruction::CONST, 8u, 0), 772 DEF_IPUT(3u, Instruction::IPUT_SHORT, 8u, thiz, 6u), 773 DEF_CONST(3u, Instruction::CONST, 9u, 0), 774 DEF_IPUT(3u, Instruction::IPUT_BOOLEAN, 9u, thiz, 7u), 775 DEF_CONST(3u, Instruction::CONST, 10u, 0), 776 DEF_IPUT(3u, Instruction::IPUT_OBJECT, 10u, thiz, 8u), 777 DEF_CONST(3u, Instruction::CONST, 11u, 0), 778 DEF_IPUT(3u, Instruction::IPUT_OBJECT, 11u, thiz, 9u), 779 }; 780 781 PrepareIFields(ifields); 782 BuildDexFile("()V", false); 783 PrepareSingleBlock(); 784 PrepareMIRs(mirs); 785 PerformTypeInference(); 786 787 ASSERT_EQ(arraysize(mirs), mir_count_); 788 static const SRegExpectation expectations[] = { 789 // One expectation for every 2 MIRs. 790 { 0u, kExpectCore | kExpectNarrow }, 791 { 0u, kExpectCore | kExpectNarrow }, 792 { 0u, kExpectFp | kExpectWide }, 793 { 0u, kExpectFp | kExpectNarrow }, 794 { 0u, kExpectCore | kExpectNarrow }, 795 { 0u, kExpectCore | kExpectWide }, 796 { 0u, kExpectCore | kExpectNarrow }, 797 { 0u, kExpectCore | kExpectNarrow }, 798 { 0u, kExpectRef | kExpectNarrow | kExpectNull }, 799 { 1u, kExpectRef | kExpectNarrow | kExpectNull | kExpectArrayRef | kExpectArrayNarrow }, 800 }; 801 static_assert(2 * arraysize(expectations) == arraysize(mirs), "array size mismatch"); 802 for (size_t i = 0; i != arraysize(expectations); ++i) { 803 EXPECT_EQ(mirs[2 * i].opcode, mirs_[2 * i].dalvikInsn.opcode); 804 EXPECT_EQ(mirs[2 * i + 1].opcode, mirs_[2 * i + 1].dalvikInsn.opcode); 805 ASSERT_LE(1u, mirs_[2 * i].ssa_rep->num_defs); 806 ExpectSRegType(mirs_[2 * i].ssa_rep->defs[0], expectations[i]); 807 } 808 EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u); 809 EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter()); 810 } 811 812 TEST_F(TypeInferenceTest, SPut) { 813 static const FieldDef sfields[] = { 814 { kClassName, "B", "staticByteField" }, 815 { kClassName, "C", "staticCharField" }, 816 { kClassName, "D", "staticDoubleField" }, 817 { kClassName, "F", "staticFloatField" }, 818 { kClassName, "I", "staticIntField" }, 819 { kClassName, "J", "staticLongField" }, 820 { kClassName, "S", "staticShortField" }, 821 { kClassName, "Z", "staticBooleanField" }, 822 { kClassName, "Ljava/lang/Object;", "staticObjectField" }, 823 { kClassName, "[Ljava/lang/Object;", "staticObjectArrayField" }, 824 }; 825 static const MIRDef mirs[] = { 826 DEF_CONST(3u, Instruction::CONST, 0u, 0), 827 DEF_SPUT(3u, Instruction::SPUT_BYTE, 0u, 0u), 828 DEF_CONST(3u, Instruction::CONST, 1u, 0), 829 DEF_SPUT(3u, Instruction::SPUT_CHAR, 1u, 1u), 830 DEF_CONST_WIDE(3u, Instruction::CONST_WIDE, 2u, 0), 831 DEF_SPUT_WIDE(3u, Instruction::SPUT_WIDE, 2u, 2u), 832 DEF_CONST(3u, Instruction::CONST, 4u, 0), 833 DEF_SPUT(3u, Instruction::SPUT, 4u, 3u), 834 DEF_CONST(3u, Instruction::CONST, 5u, 0), 835 DEF_SPUT(3u, Instruction::SPUT, 5u, 4u), 836 DEF_CONST_WIDE(3u, Instruction::CONST_WIDE, 6u, 0), 837 DEF_SPUT_WIDE(3u, Instruction::SPUT_WIDE, 6u, 5u), 838 DEF_CONST(3u, Instruction::CONST, 8u, 0), 839 DEF_SPUT(3u, Instruction::SPUT_SHORT, 8u, 6u), 840 DEF_CONST(3u, Instruction::CONST, 9u, 0), 841 DEF_SPUT(3u, Instruction::SPUT_BOOLEAN, 9u, 7u), 842 DEF_CONST(3u, Instruction::CONST, 10u, 0), 843 DEF_SPUT(3u, Instruction::SPUT_OBJECT, 10u, 8u), 844 DEF_CONST(3u, Instruction::CONST, 11u, 0), 845 DEF_SPUT(3u, Instruction::SPUT_OBJECT, 11u, 9u), 846 }; 847 848 PrepareSFields(sfields); 849 BuildDexFile("()V", true); 850 PrepareSingleBlock(); 851 PrepareMIRs(mirs); 852 PerformTypeInference(); 853 854 ASSERT_EQ(arraysize(mirs), mir_count_); 855 static const SRegExpectation expectations[] = { 856 // One expectation for every 2 MIRs. 857 { 0u, kExpectCore | kExpectNarrow }, 858 { 0u, kExpectCore | kExpectNarrow }, 859 { 0u, kExpectFp | kExpectWide }, 860 { 0u, kExpectFp | kExpectNarrow }, 861 { 0u, kExpectCore | kExpectNarrow }, 862 { 0u, kExpectCore | kExpectWide }, 863 { 0u, kExpectCore | kExpectNarrow }, 864 { 0u, kExpectCore | kExpectNarrow }, 865 { 0u, kExpectRef | kExpectNarrow | kExpectNull }, 866 { 1u, kExpectRef | kExpectNarrow | kExpectNull | kExpectArrayRef | kExpectArrayNarrow }, 867 }; 868 static_assert(2 * arraysize(expectations) == arraysize(mirs), "array size mismatch"); 869 for (size_t i = 0; i != arraysize(expectations); ++i) { 870 EXPECT_EQ(mirs[2 * i].opcode, mirs_[2 * i].dalvikInsn.opcode); 871 EXPECT_EQ(mirs[2 * i + 1].opcode, mirs_[2 * i + 1].dalvikInsn.opcode); 872 ASSERT_LE(1u, mirs_[2 * i].ssa_rep->num_defs); 873 ExpectSRegType(mirs_[2 * i].ssa_rep->defs[0], expectations[i]); 874 } 875 EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u); 876 EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter()); 877 } 878 879 TEST_F(TypeInferenceTest, MethodReturnType) { 880 static const MethodDef methods[] = { 881 { kClassName, "()B", "byteFoo", kStatic }, 882 { kClassName, "()C", "charFoo", kStatic }, 883 { kClassName, "()D", "doubleFoo", kStatic }, 884 { kClassName, "()F", "floatFoo", kStatic }, 885 { kClassName, "()I", "intFoo", kStatic }, 886 { kClassName, "()J", "longFoo", kStatic }, 887 { kClassName, "()S", "shortFoo", kStatic }, 888 { kClassName, "()Z", "booleanFoo", kStatic }, 889 { kClassName, "()Ljava/lang/Object;", "objectFoo", kStatic }, 890 { kClassName, "()[Ljava/lang/Object;", "objectArrayFoo", kStatic }, 891 }; 892 static const MIRDef mirs[] = { 893 DEF_INVOKE0(3u, Instruction::INVOKE_STATIC, 0u), 894 DEF_NULOP(3u, Instruction::MOVE_RESULT, 0u), 895 DEF_INVOKE0(3u, Instruction::INVOKE_STATIC, 1u), 896 DEF_NULOP(3u, Instruction::MOVE_RESULT, 1u), 897 DEF_INVOKE0(3u, Instruction::INVOKE_STATIC, 2u), 898 DEF_NULOP_WIDE(3u, Instruction::MOVE_RESULT_WIDE, 2u), 899 DEF_INVOKE0(3u, Instruction::INVOKE_STATIC, 3u), 900 DEF_NULOP(3u, Instruction::MOVE_RESULT, 4u), 901 DEF_INVOKE0(3u, Instruction::INVOKE_STATIC, 4u), 902 DEF_NULOP(3u, Instruction::MOVE_RESULT, 5u), 903 DEF_INVOKE0(3u, Instruction::INVOKE_STATIC, 5u), 904 DEF_NULOP_WIDE(3u, Instruction::MOVE_RESULT_WIDE, 6u), 905 DEF_INVOKE0(3u, Instruction::INVOKE_STATIC, 6u), 906 DEF_NULOP(3u, Instruction::MOVE_RESULT, 8u), 907 DEF_INVOKE0(3u, Instruction::INVOKE_STATIC, 7u), 908 DEF_NULOP(3u, Instruction::MOVE_RESULT, 9u), 909 DEF_INVOKE0(3u, Instruction::INVOKE_STATIC, 8u), 910 DEF_NULOP(3u, Instruction::MOVE_RESULT_OBJECT, 10u), 911 DEF_INVOKE0(3u, Instruction::INVOKE_STATIC, 9u), 912 DEF_NULOP(3u, Instruction::MOVE_RESULT_OBJECT, 11u), 913 }; 914 915 PrepareMethods(methods); 916 BuildDexFile("()V", true); 917 PrepareSingleBlock(); 918 PrepareMIRs(mirs); 919 PerformTypeInference(); 920 921 ASSERT_EQ(arraysize(mirs), mir_count_); 922 static const SRegExpectation expectations[] = { 923 // One expectation for every 2 MIRs. 924 { 0u, kExpectCore | kExpectNarrow }, 925 { 0u, kExpectCore | kExpectNarrow }, 926 { 0u, kExpectFp | kExpectWide }, 927 { 0u, kExpectFp | kExpectNarrow }, 928 { 0u, kExpectCore | kExpectNarrow }, 929 { 0u, kExpectCore | kExpectWide }, 930 { 0u, kExpectCore | kExpectNarrow }, 931 { 0u, kExpectCore | kExpectNarrow }, 932 { 0u, kExpectRef | kExpectNarrow }, 933 { 1u, kExpectRef | kExpectNarrow | kExpectArrayRef | kExpectArrayNarrow }, 934 }; 935 static_assert(2 * arraysize(expectations) == arraysize(mirs), "array size mismatch"); 936 for (size_t i = 0; i != arraysize(expectations); ++i) { 937 EXPECT_EQ(mirs[2 * i].opcode, mirs_[2 * i].dalvikInsn.opcode); 938 EXPECT_EQ(mirs[2 * i + 1].opcode, mirs_[2 * i + 1].dalvikInsn.opcode); 939 ASSERT_LE(1u, mirs_[2 * i + 1].ssa_rep->num_defs); 940 ExpectSRegType(mirs_[2 * i + 1].ssa_rep->defs[0], expectations[i]); 941 } 942 EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u); 943 EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter()); 944 } 945 946 TEST_F(TypeInferenceTest, MethodArgType) { 947 static const MethodDef methods[] = { 948 { kClassName, "(B)V", "fooByte", kStatic }, 949 { kClassName, "(C)V", "fooChar", kStatic }, 950 { kClassName, "(D)V", "fooDouble", kStatic }, 951 { kClassName, "(F)V", "fooFloat", kStatic }, 952 { kClassName, "(I)V", "fooInt", kStatic }, 953 { kClassName, "(J)V", "fooLong", kStatic }, 954 { kClassName, "(S)V", "fooShort", kStatic }, 955 { kClassName, "(Z)V", "fooBoolean", kStatic }, 956 { kClassName, "(Ljava/lang/Object;)V", "fooObject", kStatic }, 957 { kClassName, "([Ljava/lang/Object;)V", "fooObjectArray", kStatic }, 958 }; 959 static const MIRDef mirs[] = { 960 DEF_CONST(3u, Instruction::CONST, 0u, 0), 961 DEF_INVOKE1(3u, Instruction::INVOKE_STATIC, 0u, 0u), 962 DEF_CONST(3u, Instruction::CONST, 1u, 0), 963 DEF_INVOKE1(3u, Instruction::INVOKE_STATIC, 1u, 1u), 964 DEF_CONST_WIDE(3u, Instruction::CONST_WIDE, 2u, 0), 965 DEF_INVOKE2(3u, Instruction::INVOKE_STATIC, 2u, 3u, 2u), 966 DEF_CONST(3u, Instruction::CONST, 4u, 0), 967 DEF_INVOKE1(3u, Instruction::INVOKE_STATIC, 4u, 3u), 968 DEF_CONST(3u, Instruction::CONST, 5u, 0), 969 DEF_INVOKE1(3u, Instruction::INVOKE_STATIC, 5u, 4u), 970 DEF_CONST_WIDE(3u, Instruction::CONST_WIDE, 6u, 0), 971 DEF_INVOKE2(3u, Instruction::INVOKE_STATIC, 6u, 7u, 5u), 972 DEF_CONST(3u, Instruction::CONST, 8u, 0), 973 DEF_INVOKE1(3u, Instruction::INVOKE_STATIC, 8u, 6u), 974 DEF_CONST(3u, Instruction::CONST, 9u, 0), 975 DEF_INVOKE1(3u, Instruction::INVOKE_STATIC, 9u, 7u), 976 DEF_CONST(3u, Instruction::CONST, 10u, 0), 977 DEF_INVOKE1(3u, Instruction::INVOKE_STATIC, 10u, 8u), 978 DEF_CONST(3u, Instruction::CONST, 11u, 0), 979 DEF_INVOKE1(3u, Instruction::INVOKE_STATIC, 11u, 9u), 980 }; 981 982 PrepareMethods(methods); 983 BuildDexFile("()V", true); 984 PrepareSingleBlock(); 985 PrepareMIRs(mirs); 986 PerformTypeInference(); 987 988 ASSERT_EQ(arraysize(mirs), mir_count_); 989 static const SRegExpectation expectations[] = { 990 // One expectation for every 2 MIRs. 991 { 0u, kExpectCore | kExpectNarrow }, 992 { 0u, kExpectCore | kExpectNarrow }, 993 { 0u, kExpectFp | kExpectWide }, 994 { 0u, kExpectFp | kExpectNarrow }, 995 { 0u, kExpectCore | kExpectNarrow }, 996 { 0u, kExpectCore | kExpectWide }, 997 { 0u, kExpectCore | kExpectNarrow }, 998 { 0u, kExpectCore | kExpectNarrow }, 999 { 0u, kExpectRef | kExpectNarrow | kExpectNull }, 1000 { 1u, kExpectRef | kExpectNarrow | kExpectNull | kExpectArrayRef | kExpectArrayNarrow }, 1001 }; 1002 static_assert(2 * arraysize(expectations) == arraysize(mirs), "array size mismatch"); 1003 for (size_t i = 0; i != arraysize(expectations); ++i) { 1004 EXPECT_EQ(mirs[2 * i].opcode, mirs_[2 * i].dalvikInsn.opcode); 1005 EXPECT_EQ(mirs[2 * i + 1].opcode, mirs_[2 * i + 1].dalvikInsn.opcode); 1006 ASSERT_LE(1u, mirs_[2 * i].ssa_rep->num_defs); 1007 ExpectSRegType(mirs_[2 * i].ssa_rep->defs[0], expectations[i]); 1008 } 1009 EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u); 1010 EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter()); 1011 } 1012 1013 TEST_F(TypeInferenceTest, APut1) { 1014 static const MIRDef mirs[] = { 1015 DEF_CONST(3u, Instruction::CONST, 0u, 0), // Object[] array 1016 DEF_CONST(3u, Instruction::CONST, 1u, 0), // value; can't even determine whether core or fp. 1017 DEF_CONST(3u, Instruction::CONST, 2u, 0), // index 1018 DEF_APUT(3u, Instruction::APUT, 1u, 0u, 2u), 1019 }; 1020 1021 BuildDexFile("()V", true); 1022 PrepareSingleBlock(); 1023 PrepareMIRs(mirs); 1024 PerformTypeInference(); 1025 1026 ASSERT_EQ(arraysize(mirs), mir_count_); 1027 static const SRegExpectation expectations[] = { 1028 { 1u, kExpectRef | kExpectNarrow | kExpectNull | kExpectArrayNarrow }, 1029 { 0u, kExpectNarrow }, 1030 { 0u, kExpectCore | kExpectNarrow }, 1031 }; 1032 for (int32_t sreg = 0; sreg != arraysize(expectations); ++sreg) { 1033 ExpectSRegType(sreg, expectations[sreg]); 1034 } 1035 EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u); 1036 EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter()); 1037 } 1038 1039 TEST_F(TypeInferenceTest, APut2) { 1040 static const MIRDef mirs[] = { 1041 DEF_CONST(3u, Instruction::CONST, 0u, 0), // Object[] array 1042 DEF_CONST(3u, Instruction::CONST, 1u, 0), // Object[] value 1043 DEF_CONST(3u, Instruction::CONST, 2u, 0), // index 1044 DEF_APUT(3u, Instruction::APUT_OBJECT, 1u, 0u, 2u), 1045 }; 1046 1047 BuildDexFile("()V", true); 1048 PrepareSingleBlock(); 1049 PrepareMIRs(mirs); 1050 PerformTypeInference(); 1051 1052 ASSERT_EQ(arraysize(mirs), mir_count_); 1053 static const SRegExpectation expectations[] = { 1054 { 1u, kExpectRef | kExpectNarrow | kExpectNull | kExpectArrayRef | kExpectArrayNarrow }, 1055 { 0u, kExpectRef | kExpectNarrow | kExpectNull }, 1056 { 0u, kExpectCore | kExpectNarrow }, 1057 }; 1058 for (int32_t sreg = 0; sreg != arraysize(expectations); ++sreg) { 1059 ExpectSRegType(sreg, expectations[sreg]); 1060 } 1061 EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u); 1062 EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter()); 1063 } 1064 1065 TEST_F(TypeInferenceTest, APut3) { 1066 static const MIRDef mirs[] = { 1067 // Either array1 or array2 could be Object[][] but there is no way to tell from the bytecode. 1068 DEF_CONST(3u, Instruction::CONST, 0u, 0), // Object[] array1 1069 DEF_CONST(3u, Instruction::CONST, 1u, 0), // Object[] array2 1070 DEF_CONST(3u, Instruction::CONST, 2u, 0), // index 1071 DEF_APUT(3u, Instruction::APUT_OBJECT, 0u, 1u, 2u), 1072 DEF_APUT(3u, Instruction::APUT_OBJECT, 1u, 0u, 2u), 1073 }; 1074 1075 BuildDexFile("()V", true); 1076 PrepareSingleBlock(); 1077 PrepareMIRs(mirs); 1078 PerformTypeInference(); 1079 1080 ASSERT_EQ(arraysize(mirs), mir_count_); 1081 static const SRegExpectation expectations[] = { 1082 { 1u, kExpectRef | kExpectNarrow | kExpectNull | kExpectArrayRef | kExpectArrayNarrow }, 1083 { 1u, kExpectRef | kExpectNarrow | kExpectNull | kExpectArrayRef | kExpectArrayNarrow }, 1084 { 0u, kExpectCore | kExpectNarrow }, 1085 }; 1086 for (int32_t sreg = 0; sreg != arraysize(expectations); ++sreg) { 1087 ExpectSRegType(sreg, expectations[sreg]); 1088 } 1089 EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u); 1090 EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter()); 1091 } 1092 1093 TEST_F(TypeInferenceTest, APut4) { 1094 static const MIRDef mirs[] = { 1095 DEF_CONST(3u, Instruction::CONST, 0u, 0), 1096 DEF_CONST(3u, Instruction::CONST, 1u, 0), // index 1097 DEF_AGET(3u, Instruction::AGET_OBJECT, 2u, 0u, 1u), // Object[] array 1098 DEF_CONST(3u, Instruction::CONST, 3u, 0), // value; can't even determine whether core or fp. 1099 DEF_APUT(3u, Instruction::APUT, 3u, 2u, 1u), 1100 }; 1101 1102 BuildDexFile("()V", true); 1103 PrepareSingleBlock(); 1104 PrepareMIRs(mirs); 1105 PerformTypeInference(); 1106 1107 ASSERT_EQ(arraysize(mirs), mir_count_); 1108 static const SRegExpectation expectations[] = { 1109 { 1u, kExpectRef | kExpectNarrow | kExpectNull | kExpectArrayRef | kExpectArrayNarrow }, 1110 { 0u, kExpectCore | kExpectNarrow }, 1111 { 1u, kExpectRef | kExpectNarrow | kExpectArrayNarrow }, 1112 { 0u, kExpectNarrow }, 1113 }; 1114 for (int32_t sreg = 0; sreg != arraysize(expectations); ++sreg) { 1115 ExpectSRegType(sreg, expectations[sreg]); 1116 } 1117 EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u); 1118 EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter()); 1119 } 1120 1121 TEST_F(TypeInferenceTest, APut5) { 1122 static const MIRDef mirs[] = { 1123 DEF_CONST(3u, Instruction::CONST, 0u, 0), 1124 DEF_CONST(3u, Instruction::CONST, 1u, 0), // index 1125 DEF_AGET(3u, Instruction::AGET_OBJECT, 2u, 0u, 1u), // Object[] array 1126 DEF_CONST(3u, Instruction::CONST, 3u, 0), // Object[] value 1127 DEF_APUT(3u, Instruction::APUT_OBJECT, 3u, 2u, 1u), 1128 }; 1129 1130 BuildDexFile("()V", true); 1131 PrepareSingleBlock(); 1132 PrepareMIRs(mirs); 1133 PerformTypeInference(); 1134 1135 ASSERT_EQ(arraysize(mirs), mir_count_); 1136 static const SRegExpectation expectations[] = { 1137 { 1u, kExpectRef | kExpectNarrow | kExpectNull | kExpectArrayRef | kExpectArrayNarrow }, 1138 { 0u, kExpectCore | kExpectNarrow }, 1139 { 1u, kExpectRef | kExpectNarrow | kExpectArrayRef | kExpectArrayNarrow }, 1140 { 0u, kExpectRef | kExpectNarrow | kExpectNull }, 1141 }; 1142 for (int32_t sreg = 0; sreg != arraysize(expectations); ++sreg) { 1143 ExpectSRegType(sreg, expectations[sreg]); 1144 } 1145 EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u); 1146 EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter()); 1147 } 1148 1149 TEST_F(TypeInferenceTest, APut6) { 1150 static const MIRDef mirs[] = { 1151 DEF_CONST(3u, Instruction::CONST, 0u, 0), 1152 DEF_CONST(3u, Instruction::CONST, 1u, 0), // index 1153 // Either array1 or array2 could be Object[][] but there is no way to tell from the bytecode. 1154 DEF_AGET(3u, Instruction::AGET_OBJECT, 2u, 0u, 1u), // Object[] array1 1155 DEF_AGET(3u, Instruction::AGET_OBJECT, 3u, 0u, 1u), // Object[] array2 1156 DEF_APUT(3u, Instruction::APUT_OBJECT, 2u, 3u, 1u), 1157 DEF_APUT(3u, Instruction::APUT_OBJECT, 3u, 2u, 1u), 1158 }; 1159 1160 BuildDexFile("()V", true); 1161 PrepareSingleBlock(); 1162 PrepareMIRs(mirs); 1163 PerformTypeInference(); 1164 1165 ASSERT_EQ(arraysize(mirs), mir_count_); 1166 static const SRegExpectation expectations[] = { 1167 { 1u, kExpectRef | kExpectNarrow | kExpectNull | kExpectArrayRef | kExpectArrayNarrow }, 1168 { 0u, kExpectCore | kExpectNarrow }, 1169 { 1u, kExpectRef | kExpectNarrow | kExpectArrayRef | kExpectArrayNarrow }, 1170 { 1u, kExpectRef | kExpectNarrow | kExpectArrayRef | kExpectArrayNarrow }, 1171 }; 1172 for (int32_t sreg = 0; sreg != arraysize(expectations); ++sreg) { 1173 ExpectSRegType(sreg, expectations[sreg]); 1174 } 1175 EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u); 1176 EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter()); 1177 } 1178 1179 TEST_F(TypeInferenceTest, TwoNullObjectArraysInLoop) { 1180 static const MIRDef mirs[] = { 1181 // void foo() { 1182 // Object[] array1 = ((Object[])null)[0]; 1183 // Object[] array2 = ((Object[])null)[0]; 1184 // for (int i = 0; i != 3; ++i) { 1185 // Object[] a1 = null; // One of these could be Object[][] but not both. 1186 // Object[] a2 = null; // But they will be deduced as Object[]. 1187 // try { a1[0] = a2; } catch (Throwable ignored) { } 1188 // try { a2[0] = a1; } catch (Throwable ignored) { } 1189 // array1 = a1; 1190 // array2 = a2; 1191 // } 1192 // } 1193 // 1194 // Omitting the try-catch: 1195 DEF_CONST(3u, Instruction::CONST, 0u, 0), // null 1196 DEF_CONST(3u, Instruction::CONST, 1u, 0), // index 1197 DEF_AGET(3u, Instruction::AGET_OBJECT, 2u, 0u, 1u), // array1 1198 DEF_AGET(3u, Instruction::AGET_OBJECT, 3u, 0u, 1u), // array2 1199 DEF_PHI2(4u, 4u, 2u, 8u), // ? + [L -> [? gives [L (see array-length below) 1200 DEF_PHI2(4u, 5u, 3u, 9u), // ? + [L -> ? gives ? 1201 DEF_AGET(4u, Instruction::AGET_OBJECT, 6u, 0u, 1u), // a1 1202 DEF_AGET(4u, Instruction::AGET_OBJECT, 7u, 0u, 1u), // a2 1203 DEF_APUT(4u, Instruction::APUT_OBJECT, 6u, 7u, 1u), 1204 DEF_APUT(4u, Instruction::APUT_OBJECT, 7u, 6u, 1u), 1205 DEF_MOVE(4u, Instruction::MOVE_OBJECT, 8u, 6u), 1206 DEF_MOVE(4u, Instruction::MOVE_OBJECT, 9u, 7u), 1207 DEF_UNOP(5u, Instruction::ARRAY_LENGTH, 10u, 4u), 1208 }; 1209 1210 BuildDexFile("()V", true); 1211 PrepareLoop(); 1212 PrepareMIRs(mirs); 1213 PerformTypeInference(); 1214 1215 ASSERT_EQ(arraysize(mirs), mir_count_); 1216 static const SRegExpectation expectations[] = { 1217 { 1u, kExpectRef | kExpectNarrow | kExpectNull | kExpectArrayRef | kExpectArrayNarrow }, 1218 { 0u, kExpectCore | kExpectNarrow }, 1219 { 1u, kExpectRef | kExpectNarrow | kExpectArrayRef | kExpectArrayNarrow }, 1220 { 0u, kExpectRef | kExpectNarrow }, 1221 { 1u, kExpectRef | kExpectNarrow | kExpectArrayRef | kExpectArrayNarrow }, 1222 { 0u, kExpectRef | kExpectNarrow }, 1223 { 1u, kExpectRef | kExpectNarrow | kExpectArrayRef | kExpectArrayNarrow }, 1224 { 1u, kExpectRef | kExpectNarrow | kExpectArrayRef | kExpectArrayNarrow }, 1225 { 1u, kExpectRef | kExpectNarrow | kExpectArrayRef | kExpectArrayNarrow }, 1226 { 1u, kExpectRef | kExpectNarrow | kExpectArrayRef | kExpectArrayNarrow }, 1227 { 0u, kExpectCore | kExpectNarrow }, 1228 }; 1229 for (int32_t sreg = 0; sreg != arraysize(expectations); ++sreg) { 1230 ExpectSRegType(sreg, expectations[sreg]); 1231 } 1232 EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u); 1233 EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter()); 1234 } 1235 1236 TEST_F(TypeInferenceTest, ArrayArrayFloat) { 1237 static const MethodDef methods[] = { 1238 { kClassName, "(F)V", "fooFloat", kStatic }, 1239 }; 1240 static const MIRDef mirs[] = { 1241 // void foo() { 1242 // try { 1243 // float[][][] aaaf = null; 1244 // float[][] array = aaaf[0]; // Make sure array is treated as properly typed. 1245 // array[0][0] = 0.0f; // const + aget-object[1] + aput 1246 // fooFloat(array[0][0]); // aget-object[2] + aget + invoke 1247 // // invoke: signature => input is F. 1248 // // aget: output is F => base is [F (precise) 1249 // // aget-object[2]: output is [F => base is [[F (precise) 1250 // // aput: unknown input type => base is [? 1251 // // aget-object[1]: base is [[F => result is L or [F, merge with [? => result is [F 1252 // // aput (again): base is [F => result is F 1253 // // const: F determined by the aput reprocessing. 1254 // } catch (Throwable ignored) { 1255 // } 1256 // } 1257 // 1258 // Omitting the try-catch: 1259 DEF_CONST(3u, Instruction::CONST, 0u, 0), // 0 1260 DEF_CONST(3u, Instruction::CONST, 1u, 0), // aaaf 1261 DEF_AGET(3u, Instruction::AGET_OBJECT, 2u, 1u, 0u), // array = aaaf[0] 1262 DEF_CONST(3u, Instruction::CONST, 3u, 0), // 0.0f 1263 DEF_AGET(3u, Instruction::AGET_OBJECT, 4u, 2u, 0u), // array[0] 1264 DEF_APUT(3u, Instruction::APUT, 3u, 4u, 0u), // array[0][0] = 0.0f 1265 DEF_AGET(3u, Instruction::AGET_OBJECT, 5u, 2u, 0u), // array[0] 1266 DEF_AGET(3u, Instruction::AGET, 6u, 5u, 0u), // array[0][0] 1267 DEF_INVOKE1(3u, Instruction::INVOKE_STATIC, 6u, 0u), // fooFloat(array[0][0]) 1268 }; 1269 1270 PrepareMethods(methods); 1271 BuildDexFile("()V", true); 1272 PrepareSingleBlock(); 1273 PrepareMIRs(mirs); 1274 PerformTypeInference(); 1275 1276 ASSERT_EQ(arraysize(mirs), mir_count_); 1277 static const SRegExpectation expectations[] = { 1278 { 0u, kExpectCore | kExpectNarrow }, 1279 { 1u, kExpectRef | kExpectNarrow | kExpectNull | kExpectArrayRef | kExpectArrayNarrow }, 1280 { 2u, kExpectRef | kExpectNarrow | kExpectArrayFp | kExpectArrayNarrow }, 1281 { 0u, kExpectFp | kExpectNarrow }, 1282 { 1u, kExpectRef | kExpectNarrow | kExpectArrayFp | kExpectArrayNarrow }, 1283 { 1u, kExpectRef | kExpectNarrow | kExpectArrayFp | kExpectArrayNarrow }, 1284 { 0u, kExpectFp | kExpectNarrow }, 1285 }; 1286 for (int32_t sreg = 0; sreg != arraysize(expectations); ++sreg) { 1287 ExpectSRegType(sreg, expectations[sreg]); 1288 } 1289 EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u); 1290 EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter()); 1291 } 1292 1293 TEST_F(TypeInferenceTest, CheckCast1) { 1294 static const TypeDef types[] = { 1295 { "[I" }, 1296 }; 1297 static const MIRDef mirs[] = { 1298 DEF_CONST(3u, Instruction::CONST, 0u, 0), 1299 DEF_CONST(3u, Instruction::CONST, 1u, 0), 1300 DEF_AGET(3u, Instruction::AGET_OBJECT, 2u, 0u, 1u), 1301 DEF_CHECK_CAST(4u, Instruction::CHECK_CAST, 2u, 0u), 1302 DEF_CHECK_CAST(5u, Instruction::CHECK_CAST, 2u, 0u), 1303 // Pseudo-phi from [I and [I into L infers only L but not [. 1304 DEF_MOVE(6u, Instruction::MOVE_OBJECT, 3u, 2u), 1305 }; 1306 PrepareTypes(types); 1307 BuildDexFile("()V", true); 1308 PrepareDiamond(); 1309 PrepareMIRs(mirs); 1310 static const BasicBlockId v0_def_blocks[] = { 3u, 4u, 5u, 6u }; 1311 MapVRegToSReg(2, 2, v0_def_blocks); 1312 PerformTypeInference(); 1313 1314 ASSERT_EQ(arraysize(mirs), mir_count_); 1315 static const SRegExpectation expectations[] = { 1316 { 1u, kExpectRef | kExpectNarrow | kExpectNull | kExpectArrayRef | kExpectArrayNarrow }, 1317 { 0u, kExpectCore | kExpectNarrow }, 1318 { 0u, kExpectRef | kExpectNarrow }, 1319 { 0u, kExpectRef | kExpectNarrow }, 1320 }; 1321 for (int32_t sreg = 0; sreg != arraysize(expectations); ++sreg) { 1322 ExpectSRegType(sreg, expectations[sreg]); 1323 } 1324 EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u); 1325 EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter()); 1326 } 1327 1328 TEST_F(TypeInferenceTest, CheckCast2) { 1329 static const TypeDef types[] = { 1330 { "[I" }, 1331 }; 1332 static const MIRDef mirs[] = { 1333 DEF_CONST(3u, Instruction::CONST, 0u, 0), 1334 DEF_CONST(3u, Instruction::CONST, 1u, 0), 1335 DEF_AGET(3u, Instruction::AGET_OBJECT, 2u, 0u, 1u), 1336 DEF_CHECK_CAST(4u, Instruction::CHECK_CAST, 2u, 0u), 1337 DEF_CHECK_CAST(5u, Instruction::CHECK_CAST, 2u, 0u), 1338 // Pseudo-phi from [I and [I into [? infers [I. 1339 DEF_MOVE(6u, Instruction::MOVE_OBJECT, 3u, 2u), 1340 DEF_UNOP(6u, Instruction::ARRAY_LENGTH, 4u, 2u), 1341 }; 1342 PrepareTypes(types); 1343 BuildDexFile("()V", true); 1344 PrepareDiamond(); 1345 PrepareMIRs(mirs); 1346 static const BasicBlockId v0_def_blocks[] = { 3u, 4u, 5u, 6u }; 1347 MapVRegToSReg(2, 2, v0_def_blocks); 1348 PerformTypeInference(); 1349 1350 ASSERT_EQ(arraysize(mirs), mir_count_); 1351 static const SRegExpectation expectations[] = { 1352 { 1u, kExpectRef | kExpectNarrow | kExpectNull | kExpectArrayRef | kExpectArrayNarrow }, 1353 { 0u, kExpectCore | kExpectNarrow }, 1354 { 0u, kExpectRef | kExpectNarrow }, 1355 { 1u, kExpectRef | kExpectNarrow | kExpectArrayCore | kExpectArrayNarrow }, 1356 { 0u, kExpectCore | kExpectNarrow }, 1357 }; 1358 for (int32_t sreg = 0; sreg != arraysize(expectations); ++sreg) { 1359 ExpectSRegType(sreg, expectations[sreg]); 1360 } 1361 EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u); 1362 EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter()); 1363 } 1364 1365 TEST_F(TypeInferenceTest, CheckCast3) { 1366 static const TypeDef types[] = { 1367 { "[I" }, 1368 { "[F" }, 1369 }; 1370 static const MIRDef mirs[] = { 1371 DEF_CONST(3u, Instruction::CONST, 0u, 0), 1372 DEF_CONST(3u, Instruction::CONST, 1u, 0), 1373 DEF_AGET(3u, Instruction::AGET_OBJECT, 2u, 0u, 1u), 1374 DEF_CHECK_CAST(4u, Instruction::CHECK_CAST, 2u, 0u), 1375 DEF_CHECK_CAST(5u, Instruction::CHECK_CAST, 2u, 1u), 1376 // Pseudo-phi from [I and [F into L correctly leaves it as L. 1377 DEF_MOVE(6u, Instruction::MOVE_OBJECT, 3u, 2u), 1378 }; 1379 PrepareTypes(types); 1380 BuildDexFile("()V", true); 1381 PrepareDiamond(); 1382 PrepareMIRs(mirs); 1383 static const BasicBlockId v0_def_blocks[] = { 3u, 4u, 5u, 6u }; 1384 MapVRegToSReg(2, 2, v0_def_blocks); 1385 PerformTypeInference(); 1386 1387 ASSERT_EQ(arraysize(mirs), mir_count_); 1388 static const SRegExpectation expectations[] = { 1389 { 1u, kExpectRef | kExpectNarrow | kExpectNull | kExpectArrayRef | kExpectArrayNarrow }, 1390 { 0u, kExpectCore | kExpectNarrow }, 1391 { 0u, kExpectRef | kExpectNarrow }, 1392 { 0u, kExpectRef | kExpectNarrow }, 1393 }; 1394 for (int32_t sreg = 0; sreg != arraysize(expectations); ++sreg) { 1395 ExpectSRegType(sreg, expectations[sreg]); 1396 } 1397 EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u); 1398 EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter()); 1399 } 1400 1401 TEST_F(TypeInferenceTest, CheckCastConflict1) { 1402 static const TypeDef types[] = { 1403 { "[I" }, 1404 { "[F" }, 1405 }; 1406 static const MIRDef mirs[] = { 1407 DEF_CONST(3u, Instruction::CONST, 0u, 0), 1408 DEF_CONST(3u, Instruction::CONST, 1u, 0), 1409 DEF_AGET(3u, Instruction::AGET_OBJECT, 2u, 0u, 1u), 1410 DEF_CHECK_CAST(4u, Instruction::CHECK_CAST, 2u, 0u), 1411 DEF_CHECK_CAST(5u, Instruction::CHECK_CAST, 2u, 1u), 1412 // Pseudo-phi from [I and [F into [? infers conflict [I/[F. 1413 DEF_MOVE(6u, Instruction::MOVE_OBJECT, 3u, 2u), 1414 DEF_UNOP(6u, Instruction::ARRAY_LENGTH, 4u, 2u), 1415 }; 1416 PrepareTypes(types); 1417 BuildDexFile("()V", true); 1418 PrepareDiamond(); 1419 PrepareMIRs(mirs); 1420 static const BasicBlockId v0_def_blocks[] = { 3u, 4u, 5u, 6u }; 1421 MapVRegToSReg(2, 2, v0_def_blocks); 1422 PerformTypeInference(); 1423 1424 ASSERT_EQ(arraysize(mirs), mir_count_); 1425 static const SRegExpectation expectations[] = { 1426 { 1u, kExpectRef | kExpectNarrow | kExpectNull | kExpectArrayRef | kExpectArrayNarrow }, 1427 { 0u, kExpectCore | kExpectNarrow }, 1428 { 0u, kExpectRef | kExpectNarrow }, 1429 { 1u, kExpectRef | kExpectNarrow | kExpectArrayCore | kExpectArrayFp | kExpectArrayNarrow }, 1430 { 0u, kExpectCore | kExpectNarrow }, 1431 }; 1432 for (int32_t sreg = 0; sreg != arraysize(expectations); ++sreg) { 1433 ExpectSRegType(sreg, expectations[sreg], false); 1434 } 1435 // The type conflict in array element wasn't propagated to an SSA reg. 1436 EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u); 1437 EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter()); 1438 } 1439 1440 TEST_F(TypeInferenceTest, CheckCastConflict2) { 1441 static const TypeDef types[] = { 1442 { "[I" }, 1443 { "[F" }, 1444 }; 1445 static const MIRDef mirs[] = { 1446 DEF_CONST(3u, Instruction::CONST, 0u, 0), 1447 DEF_CONST(3u, Instruction::CONST, 1u, 0), 1448 DEF_AGET(3u, Instruction::AGET_OBJECT, 2u, 0u, 1u), 1449 DEF_CHECK_CAST(4u, Instruction::CHECK_CAST, 2u, 0u), 1450 DEF_CHECK_CAST(5u, Instruction::CHECK_CAST, 2u, 1u), 1451 // Pseudo-phi from [I and [F into [? infers conflict [I/[F. 1452 DEF_MOVE(6u, Instruction::MOVE_OBJECT, 3u, 2u), 1453 DEF_AGET(6u, Instruction::AGET, 4u, 2u, 1u), 1454 }; 1455 PrepareTypes(types); 1456 BuildDexFile("()V", true); 1457 PrepareDiamond(); 1458 PrepareMIRs(mirs); 1459 static const BasicBlockId v0_def_blocks[] = { 3u, 4u, 5u, 6u }; 1460 MapVRegToSReg(2, 2, v0_def_blocks); 1461 PerformTypeInference(); 1462 1463 ASSERT_EQ(arraysize(mirs), mir_count_); 1464 static const SRegExpectation expectations[] = { 1465 { 1u, kExpectRef | kExpectNarrow | kExpectNull | kExpectArrayRef | kExpectArrayNarrow }, 1466 { 0u, kExpectCore | kExpectNarrow }, 1467 { 0u, kExpectRef | kExpectNarrow }, 1468 { 1u, kExpectRef | kExpectNarrow | kExpectArrayCore | kExpectArrayFp | kExpectArrayNarrow }, 1469 { 0u, kExpectCore | kExpectFp | kExpectNarrow }, 1470 }; 1471 for (int32_t sreg = 0; sreg != arraysize(expectations); ++sreg) { 1472 ExpectSRegType(sreg, expectations[sreg], false); 1473 } 1474 // Type conflict in an SSA reg, register promotion disabled. 1475 EXPECT_NE(cu_.disable_opt & (1u << kPromoteRegs), 0u); 1476 EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter()); 1477 } 1478 1479 TEST_F(TypeInferenceTest, Phi1) { 1480 static const TypeDef types[] = { 1481 { "[I" }, 1482 }; 1483 static const MIRDef mirs[] = { 1484 DEF_CONST(3u, Instruction::CONST, 0u, 100), 1485 DEF_NEW_ARRAY(4u, Instruction::NEW_ARRAY, 1u, 0u, 0u), 1486 DEF_NEW_ARRAY(5u, Instruction::NEW_ARRAY, 2u, 0u, 0u), 1487 // Phi from [I and [I infers only L but not [. 1488 DEF_PHI2(6u, 3u, 1u, 2u), 1489 }; 1490 PrepareTypes(types); 1491 BuildDexFile("()V", true); 1492 PrepareDiamond(); 1493 PrepareMIRs(mirs); 1494 PerformTypeInference(); 1495 1496 ASSERT_EQ(arraysize(mirs), mir_count_); 1497 static const SRegExpectation expectations[] = { 1498 { 0u, kExpectCore | kExpectNarrow }, 1499 { 1u, kExpectRef | kExpectNarrow | kExpectArrayCore | kExpectArrayNarrow }, 1500 { 1u, kExpectRef | kExpectNarrow | kExpectArrayCore | kExpectArrayNarrow }, 1501 { 0u, kExpectRef | kExpectNarrow }, 1502 }; 1503 for (int32_t sreg = 0; sreg != arraysize(expectations); ++sreg) { 1504 ExpectSRegType(sreg, expectations[sreg]); 1505 } 1506 EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u); 1507 EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter()); 1508 } 1509 1510 TEST_F(TypeInferenceTest, Phi2) { 1511 static const TypeDef types[] = { 1512 { "[F" }, 1513 }; 1514 static const MIRDef mirs[] = { 1515 DEF_CONST(3u, Instruction::CONST, 0u, 100), 1516 DEF_NEW_ARRAY(4u, Instruction::NEW_ARRAY, 1u, 0u, 0u), 1517 DEF_NEW_ARRAY(5u, Instruction::NEW_ARRAY, 2u, 0u, 0u), 1518 // Phi from [F and [F into [? infers [F. 1519 DEF_PHI2(6u, 3u, 1u, 2u), 1520 DEF_UNOP(6u, Instruction::ARRAY_LENGTH, 4u, 3u), 1521 }; 1522 PrepareTypes(types); 1523 BuildDexFile("()V", true); 1524 PrepareDiamond(); 1525 PrepareMIRs(mirs); 1526 PerformTypeInference(); 1527 1528 ASSERT_EQ(arraysize(mirs), mir_count_); 1529 static const SRegExpectation expectations[] = { 1530 { 0u, kExpectCore | kExpectNarrow }, 1531 { 1u, kExpectRef | kExpectNarrow | kExpectArrayFp | kExpectArrayNarrow }, 1532 { 1u, kExpectRef | kExpectNarrow | kExpectArrayFp | kExpectArrayNarrow }, 1533 { 1u, kExpectRef | kExpectNarrow | kExpectArrayFp | kExpectArrayNarrow }, 1534 { 0u, kExpectCore | kExpectNarrow }, 1535 }; 1536 for (int32_t sreg = 0; sreg != arraysize(expectations); ++sreg) { 1537 ExpectSRegType(sreg, expectations[sreg]); 1538 } 1539 EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u); 1540 EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter()); 1541 } 1542 1543 TEST_F(TypeInferenceTest, Phi3) { 1544 static const TypeDef types[] = { 1545 { "[I" }, 1546 { "[F" }, 1547 }; 1548 static const MIRDef mirs[] = { 1549 DEF_CONST(3u, Instruction::CONST, 0u, 100), 1550 DEF_NEW_ARRAY(4u, Instruction::NEW_ARRAY, 1u, 0u, 0u), 1551 DEF_NEW_ARRAY(5u, Instruction::NEW_ARRAY, 2u, 0u, 1u), 1552 // Phi from [I and [F infers L. 1553 DEF_PHI2(6u, 3u, 1u, 2u), 1554 }; 1555 PrepareTypes(types); 1556 BuildDexFile("()V", true); 1557 PrepareDiamond(); 1558 PrepareMIRs(mirs); 1559 PerformTypeInference(); 1560 1561 ASSERT_EQ(arraysize(mirs), mir_count_); 1562 static const SRegExpectation expectations[] = { 1563 { 0u, kExpectCore | kExpectNarrow }, 1564 { 1u, kExpectRef | kExpectNarrow | kExpectArrayCore | kExpectArrayNarrow }, 1565 { 1u, kExpectRef | kExpectNarrow | kExpectArrayFp | kExpectArrayNarrow }, 1566 { 0u, kExpectRef | kExpectNarrow }, 1567 }; 1568 for (int32_t sreg = 0; sreg != arraysize(expectations); ++sreg) { 1569 ExpectSRegType(sreg, expectations[sreg]); 1570 } 1571 EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u); 1572 EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter()); 1573 } 1574 1575 TEST_F(TypeInferenceTest, Phi4) { 1576 static const TypeDef types[] = { 1577 { "[I" }, 1578 }; 1579 static const MIRDef mirs[] = { 1580 DEF_CONST(3u, Instruction::CONST, 0u, 100), 1581 DEF_NEW_ARRAY(4u, Instruction::NEW_ARRAY, 1u, 0u, 0u), 1582 DEF_CONST(5u, Instruction::CONST, 2u, 0), 1583 // Pseudo-phi from [I and null infers L. 1584 DEF_PHI2(6u, 3u, 1u, 2u), 1585 }; 1586 PrepareTypes(types); 1587 BuildDexFile("()V", true); 1588 PrepareDiamond(); 1589 PrepareMIRs(mirs); 1590 PerformTypeInference(); 1591 1592 ASSERT_EQ(arraysize(mirs), mir_count_); 1593 static const SRegExpectation expectations[] = { 1594 { 0u, kExpectCore | kExpectNarrow }, 1595 { 1u, kExpectRef | kExpectNarrow | kExpectArrayCore | kExpectArrayNarrow }, 1596 { 0u, kExpectRef | kExpectNarrow | kExpectNull }, 1597 { 0u, kExpectRef | kExpectNarrow }, 1598 }; 1599 for (int32_t sreg = 0; sreg != arraysize(expectations); ++sreg) { 1600 ExpectSRegType(sreg, expectations[sreg]); 1601 } 1602 EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u); 1603 EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter()); 1604 } 1605 1606 TEST_F(TypeInferenceTest, PhiConflict1) { 1607 static const TypeDef types[] = { 1608 { "[I" }, 1609 { "[F" }, 1610 }; 1611 static const MIRDef mirs[] = { 1612 DEF_CONST(3u, Instruction::CONST, 0u, 100), 1613 DEF_NEW_ARRAY(4u, Instruction::NEW_ARRAY, 1u, 0u, 0u), 1614 DEF_NEW_ARRAY(5u, Instruction::NEW_ARRAY, 2u, 0u, 1u), 1615 // Pseudo-phi from [I and [F into [? infers conflict [I/[F (then propagated upwards). 1616 DEF_PHI2(6u, 3u, 1u, 2u), 1617 DEF_UNOP(6u, Instruction::ARRAY_LENGTH, 4u, 3u), 1618 }; 1619 PrepareTypes(types); 1620 BuildDexFile("()V", true); 1621 PrepareDiamond(); 1622 PrepareMIRs(mirs); 1623 PerformTypeInference(); 1624 1625 ASSERT_EQ(arraysize(mirs), mir_count_); 1626 static const SRegExpectation expectations[] = { 1627 { 0u, kExpectCore | kExpectNarrow }, 1628 { 1u, kExpectRef | kExpectNarrow | kExpectArrayCore | kExpectArrayFp | kExpectArrayNarrow }, 1629 { 1u, kExpectRef | kExpectNarrow | kExpectArrayCore | kExpectArrayFp | kExpectArrayNarrow }, 1630 { 1u, kExpectRef | kExpectNarrow | kExpectArrayCore | kExpectArrayFp | kExpectArrayNarrow }, 1631 { 0u, kExpectCore | kExpectNarrow }, 1632 }; 1633 for (int32_t sreg = 0; sreg != arraysize(expectations); ++sreg) { 1634 ExpectSRegType(sreg, expectations[sreg], false); 1635 } 1636 // The type conflict in array element wasn't propagated to an SSA reg. 1637 EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u); 1638 EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter()); 1639 } 1640 1641 TEST_F(TypeInferenceTest, PhiConflict2) { 1642 static const TypeDef types[] = { 1643 { "[I" }, 1644 { "[F" }, 1645 }; 1646 static const MIRDef mirs[] = { 1647 DEF_CONST(3u, Instruction::CONST, 0u, 100), 1648 DEF_NEW_ARRAY(4u, Instruction::NEW_ARRAY, 1u, 0u, 0u), 1649 DEF_NEW_ARRAY(5u, Instruction::NEW_ARRAY, 2u, 0u, 1u), 1650 // Pseudo-phi from [I and [F into [? infers conflict [I/[F (then propagated upwards). 1651 DEF_PHI2(6u, 3u, 1u, 2u), 1652 DEF_AGET(6u, Instruction::AGET, 4u, 3u, 0u), 1653 }; 1654 PrepareTypes(types); 1655 BuildDexFile("()V", true); 1656 PrepareDiamond(); 1657 PrepareMIRs(mirs); 1658 PerformTypeInference(); 1659 1660 ASSERT_EQ(arraysize(mirs), mir_count_); 1661 static const SRegExpectation expectations[] = { 1662 { 0u, kExpectCore | kExpectNarrow }, 1663 { 1u, kExpectRef | kExpectNarrow | kExpectArrayCore | kExpectArrayFp | kExpectArrayNarrow }, 1664 { 1u, kExpectRef | kExpectNarrow | kExpectArrayCore | kExpectArrayFp | kExpectArrayNarrow }, 1665 { 1u, kExpectRef | kExpectNarrow | kExpectArrayCore | kExpectArrayFp | kExpectArrayNarrow }, 1666 { 0u, kExpectCore | kExpectFp | kExpectNarrow }, 1667 }; 1668 for (int32_t sreg = 0; sreg != arraysize(expectations); ++sreg) { 1669 ExpectSRegType(sreg, expectations[sreg], false); 1670 } 1671 // Type conflict in an SSA reg, register promotion disabled. 1672 EXPECT_NE(cu_.disable_opt & (1u << kPromoteRegs), 0u); 1673 EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter()); 1674 } 1675 1676 TEST_F(TypeInferenceTest, Wide1) { 1677 static const MIRDef mirs[] = { 1678 DEF_CONST(3u, Instruction::CONST, 0u, 0), 1679 DEF_CONST(3u, Instruction::CONST, 1u, 0), // index 1680 DEF_AGET(3u, Instruction::AGET_OBJECT, 2u, 0u, 1u), // long[] 1681 DEF_CONST_WIDE(3u, Instruction::CONST_WIDE, 3u, 0), // long 1682 DEF_APUT_WIDE(3u, Instruction::APUT_WIDE, 3u, 2u, 1u), 1683 { 3u, Instruction::RETURN_OBJECT, 0, 0u, 1u, { 2u }, 0u, { } }, 1684 }; 1685 1686 BuildDexFile("()[J", true); 1687 PrepareSingleBlock(); 1688 PrepareMIRs(mirs); 1689 PerformTypeInference(); 1690 1691 ASSERT_EQ(arraysize(mirs), mir_count_); 1692 static const SRegExpectation expectations[] = { 1693 { 1u, kExpectRef | kExpectNarrow | kExpectNull | kExpectArrayRef | kExpectArrayNarrow }, 1694 { 0u, kExpectCore | kExpectNarrow }, 1695 { 1u, kExpectRef | kExpectNarrow | kExpectArrayCore | kExpectArrayWide }, 1696 { 0u, kExpectCore | kExpectWide }, 1697 // NOTE: High word checked implicitly for sreg = 3. 1698 }; 1699 for (int32_t sreg = 0; sreg != arraysize(expectations); ++sreg) { 1700 ExpectSRegType(sreg, expectations[sreg], false); 1701 } 1702 EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u); 1703 EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter()); 1704 } 1705 1706 TEST_F(TypeInferenceTest, WideSizeConflict1) { 1707 static const MIRDef mirs[] = { 1708 DEF_CONST_WIDE(3u, Instruction::CONST_WIDE, 0u, 0), 1709 DEF_MOVE(3u, Instruction::MOVE, 2u, 0u), 1710 }; 1711 1712 BuildDexFile("()V", true); 1713 PrepareSingleBlock(); 1714 PrepareMIRs(mirs); 1715 PerformTypeInference(); 1716 1717 ASSERT_EQ(arraysize(mirs), mir_count_); 1718 static const SRegExpectation expectations[] = { 1719 { 0u, kExpectNarrow | kExpectWide }, 1720 { 0u, kExpectNarrow | kExpectWide }, 1721 }; 1722 ExpectSRegType(0u, expectations[0], false); 1723 ExpectSRegType(2u, expectations[1], false); 1724 EXPECT_TRUE(cu_.mir_graph->PuntToInterpreter()); 1725 } 1726 1727 TEST_F(TypeInferenceTest, ArrayLongLength) { 1728 static const FieldDef sfields[] = { 1729 { kClassName, "[J", "arrayLongField" }, 1730 }; 1731 static const MIRDef mirs[] = { 1732 DEF_CONST(4u, Instruction::CONST, 0u, 0), 1733 DEF_SGET(5u, Instruction::SGET_OBJECT, 1u, 0u), 1734 DEF_PHI2(6u, 2u, 0u, 1u), 1735 DEF_UNOP(6u, Instruction::ARRAY_LENGTH, 3u, 2u), 1736 DEF_SGET(6u, Instruction::SGET_OBJECT, 4u, 0u), 1737 DEF_UNOP(6u, Instruction::ARRAY_LENGTH, 5u, 4u), 1738 }; 1739 1740 PrepareSFields(sfields); 1741 BuildDexFile("()V", true); 1742 PrepareDiamond(); 1743 PrepareMIRs(mirs); 1744 PerformTypeInference(); 1745 1746 ASSERT_EQ(arraysize(mirs), mir_count_); 1747 static const SRegExpectation expectations[] = { 1748 { 1u, kExpectRef | kExpectNarrow | kExpectNull | kExpectArrayCore | kExpectArrayWide }, 1749 { 1u, kExpectRef | kExpectNarrow | kExpectArrayCore | kExpectArrayWide }, 1750 { 1u, kExpectRef | kExpectNarrow | kExpectArrayCore | kExpectArrayWide }, 1751 { 0u, kExpectCore | kExpectNarrow }, 1752 { 1u, kExpectRef | kExpectNarrow | kExpectArrayCore | kExpectArrayWide }, 1753 { 0u, kExpectCore | kExpectNarrow }, 1754 }; 1755 for (int32_t sreg = 0; sreg != arraysize(expectations); ++sreg) { 1756 ExpectSRegType(sreg, expectations[sreg]); 1757 } 1758 EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u); 1759 EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter()); 1760 } 1761 1762 TEST_F(TypeInferenceTest, ArrayArrayObjectLength) { 1763 static const FieldDef sfields[] = { 1764 { kClassName, "[[Ljava/lang/Object;", "arrayLongField" }, 1765 }; 1766 static const MIRDef mirs[] = { 1767 DEF_CONST(4u, Instruction::CONST, 0u, 0), 1768 DEF_SGET(5u, Instruction::SGET_OBJECT, 1u, 0u), 1769 DEF_PHI2(6u, 2u, 0u, 1u), 1770 DEF_UNOP(6u, Instruction::ARRAY_LENGTH, 3u, 2u), 1771 DEF_SGET(6u, Instruction::SGET_OBJECT, 4u, 0u), 1772 DEF_UNOP(6u, Instruction::ARRAY_LENGTH, 5u, 4u), 1773 }; 1774 1775 PrepareSFields(sfields); 1776 BuildDexFile("()V", true); 1777 PrepareDiamond(); 1778 PrepareMIRs(mirs); 1779 PerformTypeInference(); 1780 1781 ASSERT_EQ(arraysize(mirs), mir_count_); 1782 static const SRegExpectation expectations[] = { 1783 { 1u, kExpectRef | kExpectNarrow | kExpectNull | kExpectArrayRef | kExpectArrayNarrow }, 1784 { 2u, kExpectRef | kExpectNarrow | kExpectArrayRef | kExpectArrayNarrow }, 1785 { 1u, kExpectRef | kExpectNarrow | kExpectArrayRef | kExpectArrayNarrow }, 1786 { 0u, kExpectCore | kExpectNarrow }, 1787 { 2u, kExpectRef | kExpectNarrow | kExpectArrayRef | kExpectArrayNarrow }, 1788 { 0u, kExpectCore | kExpectNarrow }, 1789 }; 1790 for (int32_t sreg = 0; sreg != arraysize(expectations); ++sreg) { 1791 ExpectSRegType(sreg, expectations[sreg]); 1792 } 1793 EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u); 1794 EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter()); 1795 } 1796 1797 TEST_F(TypeInferenceTest, SGetAdd0SPut) { 1798 static const FieldDef sfields[] = { 1799 { kClassName, "I", "staticIntField" }, 1800 }; 1801 static const MIRDef mirs[] = { 1802 DEF_SGET(3u, Instruction::SGET, 0u, 0u), 1803 DEF_UNOP(3u, Instruction::ADD_INT_LIT8, 1u, 0u), // +0 1804 DEF_SPUT(3u, Instruction::SPUT, 1u, 0u), 1805 }; 1806 1807 PrepareSFields(sfields); 1808 BuildDexFile("()V", true); 1809 PrepareSingleBlock(); 1810 PrepareMIRs(mirs); 1811 PerformTypeInference(); 1812 1813 ASSERT_EQ(arraysize(mirs), mir_count_); 1814 static const SRegExpectation expectations[] = { 1815 { 0u, kExpectCore | kExpectNarrow }, 1816 { 0u, kExpectCore | kExpectNarrow }, 1817 }; 1818 for (int32_t sreg = 0; sreg != arraysize(expectations); ++sreg) { 1819 ExpectSRegType(sreg, expectations[sreg]); 1820 } 1821 EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u); 1822 EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter()); 1823 } 1824 1825 TEST_F(TypeInferenceTest, MoveObjectNull) { 1826 static const MethodDef methods[] = { 1827 { kClassName, "([I[D)V", "foo", kStatic }, 1828 }; 1829 static const MIRDef mirs[] = { 1830 DEF_CONST(3u, Instruction::CONST, 0u, 0), 1831 DEF_MOVE(3u, Instruction::MOVE_OBJECT, 1u, 0u), 1832 DEF_INVOKE2(3u, Instruction::INVOKE_STATIC, 0u, 1u, 0u), 1833 }; 1834 1835 PrepareMethods(methods); 1836 BuildDexFile("()V", true); 1837 PrepareSingleBlock(); 1838 PrepareMIRs(mirs); 1839 PerformTypeInference(); 1840 1841 ASSERT_EQ(arraysize(mirs), mir_count_); 1842 static const SRegExpectation expectation = { 1843 1u, 1844 kExpectRef | kExpectNarrow | kExpectNull | 1845 kExpectArrayCore | kExpectArrayFp | kExpectArrayNarrow | kExpectArrayWide 1846 }; 1847 ExpectSRegType(0u, expectation); 1848 ExpectSRegType(1u, expectation); 1849 EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u); 1850 EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter()); 1851 } 1852 1853 TEST_F(TypeInferenceTest, MoveNull1) { 1854 static const MethodDef methods[] = { 1855 { kClassName, "([I[D)V", "foo", kStatic }, 1856 }; 1857 static const MIRDef mirs[] = { 1858 DEF_CONST(3u, Instruction::CONST, 0u, 0), 1859 DEF_MOVE(3u, Instruction::MOVE, 1u, 0u), 1860 DEF_INVOKE2(3u, Instruction::INVOKE_STATIC, 0u, 1u, 0u), 1861 }; 1862 1863 PrepareMethods(methods); 1864 BuildDexFile("()V", true); 1865 PrepareSingleBlock(); 1866 PrepareMIRs(mirs); 1867 PerformTypeInference(); 1868 1869 ASSERT_EQ(arraysize(mirs), mir_count_); 1870 static const SRegExpectation expectation = { 1871 1u, 1872 kExpectCore | kExpectRef | kExpectFp | kExpectNarrow | kExpectNull | 1873 kExpectArrayCore | kExpectArrayFp | kExpectArrayNarrow | kExpectArrayWide 1874 }; 1875 ExpectSRegType(0u, expectation); 1876 ExpectSRegType(1u, expectation); 1877 // Type conflict using move instead of move-object for null, register promotion disabled. 1878 EXPECT_NE(cu_.disable_opt & (1u << kPromoteRegs), 0u); 1879 EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter()); 1880 } 1881 1882 TEST_F(TypeInferenceTest, MoveNull2) { 1883 static const FieldDef sfields[] = { 1884 { kClassName, "[F", "staticArrayArrayFloatField" }, 1885 { kClassName, "[I", "staticArrayIntField" }, 1886 { kClassName, "[[I", "staticArrayArrayIntField" }, 1887 }; 1888 static const MIRDef mirs[] = { 1889 DEF_CONST(4u, Instruction::CONST, 0u, 0), 1890 DEF_MOVE(4u, Instruction::MOVE_OBJECT, 1u, 0u), 1891 DEF_MOVE(4u, Instruction::MOVE_OBJECT, 2u, 1u), 1892 DEF_SGET(5u, Instruction::SGET_OBJECT, 3u, 0u), 1893 DEF_SGET(5u, Instruction::SGET_OBJECT, 4u, 1u), 1894 DEF_SGET(5u, Instruction::SGET_OBJECT, 5u, 2u), 1895 DEF_PHI2(6u, 6u, 0u, 3u), 1896 DEF_PHI2(6u, 7u, 1u, 4u), 1897 DEF_PHI2(6u, 8u, 2u, 5u), 1898 DEF_UNOP(6u, Instruction::ARRAY_LENGTH, 9u, 6u), 1899 DEF_UNOP(6u, Instruction::ARRAY_LENGTH, 10u, 7u), 1900 DEF_UNOP(6u, Instruction::ARRAY_LENGTH, 11u, 8u), 1901 { 6u, Instruction::RETURN_OBJECT, 0, 0u, 1u, { 8u }, 0u, { } }, 1902 }; 1903 1904 PrepareSFields(sfields); 1905 BuildDexFile("()[[I", true); 1906 PrepareDiamond(); 1907 PrepareMIRs(mirs); 1908 PerformTypeInference(); 1909 1910 ASSERT_EQ(arraysize(mirs), mir_count_); 1911 static const SRegExpectation expectations[] = { 1912 { 1u, kExpectRef | kExpectNarrow | kExpectNull | 1913 kExpectArrayCore | kExpectArrayFp | kExpectArrayRef | kExpectArrayNarrow }, 1914 { 1u, kExpectRef | kExpectNarrow | kExpectNull | 1915 kExpectArrayCore | kExpectArrayFp | kExpectArrayRef | kExpectArrayNarrow}, 1916 { 1u, kExpectRef | kExpectNarrow | kExpectNull | 1917 kExpectArrayCore | kExpectArrayFp | kExpectArrayRef | kExpectArrayNarrow}, 1918 { 1u, kExpectRef | kExpectNarrow | kExpectArrayFp | kExpectArrayNarrow }, 1919 { 1u, kExpectRef | kExpectNarrow | kExpectArrayCore | kExpectArrayNarrow }, 1920 { 2u, kExpectRef | kExpectNarrow | kExpectArrayCore | kExpectArrayNarrow }, 1921 { 1u, kExpectRef | kExpectNarrow | kExpectArrayFp | kExpectArrayNarrow }, 1922 { 1u, kExpectRef | kExpectNarrow | kExpectArrayCore | kExpectArrayNarrow }, 1923 { 2u, kExpectRef | kExpectNarrow | kExpectArrayCore | kExpectArrayNarrow }, 1924 { 0u, kExpectCore | kExpectNarrow }, 1925 { 0u, kExpectCore | kExpectNarrow }, 1926 { 0u, kExpectCore | kExpectNarrow }, 1927 }; 1928 for (int32_t sreg = 0; sreg != arraysize(expectations); ++sreg) { 1929 ExpectSRegType(sreg, expectations[sreg]); 1930 } 1931 // Type conflict in array type not propagated to actual register. 1932 EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u); 1933 EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter()); 1934 } 1935 1936 TEST_F(TypeInferenceTest, ReuseNull1) { 1937 static const FieldDef sfields[] = { 1938 { kClassName, "[I", "staticArrayLongField" }, 1939 { kClassName, "[[F", "staticArrayArrayFloatField" }, 1940 }; 1941 static const MIRDef mirs[] = { 1942 DEF_CONST(3u, Instruction::CONST, 0u, 0), 1943 DEF_SPUT(3u, Instruction::SPUT_OBJECT, 0u, 0u), 1944 DEF_SPUT(3u, Instruction::SPUT_OBJECT, 0u, 1u), 1945 }; 1946 1947 PrepareSFields(sfields); 1948 BuildDexFile("()V", true); 1949 PrepareSingleBlock(); 1950 PrepareMIRs(mirs); 1951 PerformTypeInference(); 1952 1953 ASSERT_EQ(arraysize(mirs), mir_count_); 1954 static const SRegExpectation expectation = { 1955 1u, 1956 kExpectRef | kExpectNarrow | kExpectNull | 1957 kExpectArrayCore | kExpectArrayRef | kExpectArrayFp | kExpectArrayNarrow 1958 }; 1959 ExpectSRegType(0u, expectation); 1960 // Type conflict in array type not propagated to actual register. 1961 EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u); 1962 EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter()); 1963 } 1964 1965 TEST_F(TypeInferenceTest, ReuseNull2) { 1966 static const FieldDef sfields[] = { 1967 { kClassName, "[J", "staticArrayLongField" }, 1968 { kClassName, "[[F", "staticArrayArrayFloatField" }, 1969 }; 1970 static const MIRDef mirs[] = { 1971 DEF_CONST(3u, Instruction::CONST, 0u, 0), 1972 DEF_SPUT(3u, Instruction::SPUT_OBJECT, 0u, 0u), 1973 DEF_SPUT(3u, Instruction::SPUT_OBJECT, 0u, 1u), 1974 }; 1975 1976 PrepareSFields(sfields); 1977 BuildDexFile("()V", true); 1978 PrepareSingleBlock(); 1979 PrepareMIRs(mirs); 1980 PerformTypeInference(); 1981 1982 ASSERT_EQ(arraysize(mirs), mir_count_); 1983 static const SRegExpectation expectation = { 1984 1u, 1985 kExpectRef | kExpectNarrow | kExpectNull | 1986 kExpectArrayCore | kExpectArrayRef | kExpectArrayFp | kExpectArrayNarrow | kExpectArrayWide 1987 }; 1988 ExpectSRegType(0u, expectation); 1989 // Type conflict in array type not propagated to actual register. 1990 EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u); 1991 EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter()); 1992 } 1993 1994 TEST_F(TypeInferenceTest, ArgIsNonNull) { 1995 constexpr uint32_t thiz = kLocalVRs; 1996 static const MIRDef mirs[] = { 1997 DEF_MOVE(3u, Instruction::MOVE_OBJECT, 0u, thiz), 1998 }; 1999 2000 BuildDexFile("(Ljava/lang/Object;)V", true); 2001 PrepareSingleBlock(); 2002 PrepareMIRs(mirs); 2003 PerformTypeInference(); 2004 2005 ASSERT_EQ(arraysize(mirs), mir_count_); 2006 static const SRegExpectation expectation = { 2007 0u, 2008 kExpectRef | kExpectNarrow 2009 }; 2010 ExpectSRegType(0u, expectation); 2011 // Type conflict in array type not propagated to actual register. 2012 EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u); 2013 EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter()); 2014 } 2015 2016 TEST_F(TypeInferenceTest, IfCc) { 2017 static const FieldDef sfields[] = { 2018 { kClassName, "I", "intField" }, 2019 }; 2020 static const MIRDef mirs[] = { 2021 DEF_SGET(3u, Instruction::SGET, 0u, 0u), 2022 DEF_CONST(3u, Instruction::CONST, 1u, 0u), 2023 { 3u, Instruction::IF_EQ, 0, 0u, 2, { 0u, 1u }, 0, { } }, 2024 }; 2025 2026 PrepareSFields(sfields); 2027 BuildDexFile("()V", false); 2028 PrepareDiamond(); 2029 PrepareMIRs(mirs); 2030 PerformTypeInference(); 2031 2032 ASSERT_EQ(arraysize(mirs), mir_count_); 2033 static const SRegExpectation expectations[] = { 2034 { 0u, kExpectCore | kExpectNarrow }, 2035 { 0u, kExpectCore | kExpectNarrow }, 2036 }; 2037 for (int32_t sreg = 0; sreg != arraysize(expectations); ++sreg) { 2038 ExpectSRegType(sreg, expectations[sreg]); 2039 } 2040 EXPECT_EQ(cu_.disable_opt & (1u << kPromoteRegs), 0u); 2041 EXPECT_FALSE(cu_.mir_graph->PuntToInterpreter()); 2042 } 2043 2044 } // namespace art 2045