1 /* 2 * Copyright (C) 2014 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 "nodes.h" 18 19 #include "base/arena_allocator.h" 20 #include "optimizing_unit_test.h" 21 22 #include "gtest/gtest.h" 23 24 namespace art { 25 26 class NodeTest : public OptimizingUnitTest {}; 27 28 /** 29 * Test that removing instruction from the graph removes itself from user lists 30 * and environment lists. 31 */ 32 TEST_F(NodeTest, RemoveInstruction) { 33 HGraph* graph = CreateGraph(); 34 HBasicBlock* entry = new (GetAllocator()) HBasicBlock(graph); 35 graph->AddBlock(entry); 36 graph->SetEntryBlock(entry); 37 HInstruction* parameter = new (GetAllocator()) HParameterValue( 38 graph->GetDexFile(), dex::TypeIndex(0), 0, DataType::Type::kReference); 39 entry->AddInstruction(parameter); 40 entry->AddInstruction(new (GetAllocator()) HGoto()); 41 42 HBasicBlock* first_block = new (GetAllocator()) HBasicBlock(graph); 43 graph->AddBlock(first_block); 44 entry->AddSuccessor(first_block); 45 HInstruction* null_check = new (GetAllocator()) HNullCheck(parameter, 0); 46 first_block->AddInstruction(null_check); 47 first_block->AddInstruction(new (GetAllocator()) HReturnVoid()); 48 49 HBasicBlock* exit_block = new (GetAllocator()) HBasicBlock(graph); 50 graph->AddBlock(exit_block); 51 first_block->AddSuccessor(exit_block); 52 exit_block->AddInstruction(new (GetAllocator()) HExit()); 53 54 HEnvironment* environment = new (GetAllocator()) HEnvironment( 55 GetAllocator(), 1, graph->GetArtMethod(), 0, null_check); 56 null_check->SetRawEnvironment(environment); 57 environment->SetRawEnvAt(0, parameter); 58 parameter->AddEnvUseAt(null_check->GetEnvironment(), 0); 59 60 ASSERT_TRUE(parameter->HasEnvironmentUses()); 61 ASSERT_TRUE(parameter->HasUses()); 62 63 first_block->RemoveInstruction(null_check); 64 65 ASSERT_FALSE(parameter->HasEnvironmentUses()); 66 ASSERT_FALSE(parameter->HasUses()); 67 } 68 69 /** 70 * Test that inserting an instruction in the graph updates user lists. 71 */ 72 TEST_F(NodeTest, InsertInstruction) { 73 HGraph* graph = CreateGraph(); 74 HBasicBlock* entry = new (GetAllocator()) HBasicBlock(graph); 75 graph->AddBlock(entry); 76 graph->SetEntryBlock(entry); 77 HInstruction* parameter1 = new (GetAllocator()) HParameterValue( 78 graph->GetDexFile(), dex::TypeIndex(0), 0, DataType::Type::kReference); 79 HInstruction* parameter2 = new (GetAllocator()) HParameterValue( 80 graph->GetDexFile(), dex::TypeIndex(0), 0, DataType::Type::kReference); 81 entry->AddInstruction(parameter1); 82 entry->AddInstruction(parameter2); 83 entry->AddInstruction(new (GetAllocator()) HExit()); 84 85 ASSERT_FALSE(parameter1->HasUses()); 86 87 HInstruction* to_insert = new (GetAllocator()) HNullCheck(parameter1, 0); 88 entry->InsertInstructionBefore(to_insert, parameter2); 89 90 ASSERT_TRUE(parameter1->HasUses()); 91 ASSERT_TRUE(parameter1->GetUses().HasExactlyOneElement()); 92 } 93 94 /** 95 * Test that adding an instruction in the graph updates user lists. 96 */ 97 TEST_F(NodeTest, AddInstruction) { 98 HGraph* graph = CreateGraph(); 99 HBasicBlock* entry = new (GetAllocator()) HBasicBlock(graph); 100 graph->AddBlock(entry); 101 graph->SetEntryBlock(entry); 102 HInstruction* parameter = new (GetAllocator()) HParameterValue( 103 graph->GetDexFile(), dex::TypeIndex(0), 0, DataType::Type::kReference); 104 entry->AddInstruction(parameter); 105 106 ASSERT_FALSE(parameter->HasUses()); 107 108 HInstruction* to_add = new (GetAllocator()) HNullCheck(parameter, 0); 109 entry->AddInstruction(to_add); 110 111 ASSERT_TRUE(parameter->HasUses()); 112 ASSERT_TRUE(parameter->GetUses().HasExactlyOneElement()); 113 } 114 115 TEST_F(NodeTest, ParentEnvironment) { 116 HGraph* graph = CreateGraph(); 117 HBasicBlock* entry = new (GetAllocator()) HBasicBlock(graph); 118 graph->AddBlock(entry); 119 graph->SetEntryBlock(entry); 120 HInstruction* parameter1 = new (GetAllocator()) HParameterValue( 121 graph->GetDexFile(), dex::TypeIndex(0), 0, DataType::Type::kReference); 122 HInstruction* with_environment = new (GetAllocator()) HNullCheck(parameter1, 0); 123 entry->AddInstruction(parameter1); 124 entry->AddInstruction(with_environment); 125 entry->AddInstruction(new (GetAllocator()) HExit()); 126 127 ASSERT_TRUE(parameter1->HasUses()); 128 ASSERT_TRUE(parameter1->GetUses().HasExactlyOneElement()); 129 130 HEnvironment* environment = new (GetAllocator()) HEnvironment( 131 GetAllocator(), 1, graph->GetArtMethod(), 0, with_environment); 132 HInstruction* const array[] = { parameter1 }; 133 134 environment->CopyFrom(ArrayRef<HInstruction* const>(array)); 135 with_environment->SetRawEnvironment(environment); 136 137 ASSERT_TRUE(parameter1->HasEnvironmentUses()); 138 ASSERT_TRUE(parameter1->GetEnvUses().HasExactlyOneElement()); 139 140 HEnvironment* parent1 = new (GetAllocator()) HEnvironment( 141 GetAllocator(), 1, graph->GetArtMethod(), 0, nullptr); 142 parent1->CopyFrom(ArrayRef<HInstruction* const>(array)); 143 144 ASSERT_EQ(parameter1->GetEnvUses().SizeSlow(), 2u); 145 146 HEnvironment* parent2 = new (GetAllocator()) HEnvironment( 147 GetAllocator(), 1, graph->GetArtMethod(), 0, nullptr); 148 parent2->CopyFrom(ArrayRef<HInstruction* const>(array)); 149 parent1->SetAndCopyParentChain(GetAllocator(), parent2); 150 151 // One use for parent2, and one other use for the new parent of parent1. 152 ASSERT_EQ(parameter1->GetEnvUses().SizeSlow(), 4u); 153 154 // We have copied the parent chain. So we now have two more uses. 155 environment->SetAndCopyParentChain(GetAllocator(), parent1); 156 ASSERT_EQ(parameter1->GetEnvUses().SizeSlow(), 6u); 157 } 158 159 } // namespace art 160