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 "base/arena_allocator.h" 18#include "nodes.h" 19#include "optimizing_unit_test.h" 20 21#include "gtest/gtest.h" 22 23namespace art { 24 25/** 26 * Test that removing instruction from the graph removes itself from user lists 27 * and environment lists. 28 */ 29TEST(Node, RemoveInstruction) { 30 ArenaPool pool; 31 ArenaAllocator allocator(&pool); 32 33 HGraph* graph = CreateGraph(&allocator); 34 HBasicBlock* entry = new (&allocator) HBasicBlock(graph); 35 graph->AddBlock(entry); 36 graph->SetEntryBlock(entry); 37 HInstruction* parameter = new (&allocator) HParameterValue( 38 graph->GetDexFile(), 0, 0, Primitive::kPrimNot); 39 entry->AddInstruction(parameter); 40 entry->AddInstruction(new (&allocator) HGoto()); 41 42 HBasicBlock* first_block = new (&allocator) HBasicBlock(graph); 43 graph->AddBlock(first_block); 44 entry->AddSuccessor(first_block); 45 HInstruction* null_check = new (&allocator) HNullCheck(parameter, 0); 46 first_block->AddInstruction(null_check); 47 first_block->AddInstruction(new (&allocator) HReturnVoid()); 48 49 HBasicBlock* exit_block = new (&allocator) HBasicBlock(graph); 50 graph->AddBlock(exit_block); 51 first_block->AddSuccessor(exit_block); 52 exit_block->AddInstruction(new (&allocator) HExit()); 53 54 HEnvironment* environment = new (&allocator) HEnvironment( 55 &allocator, 1, graph->GetDexFile(), graph->GetMethodIdx(), 0, kStatic, 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 */ 72TEST(Node, InsertInstruction) { 73 ArenaPool pool; 74 ArenaAllocator allocator(&pool); 75 76 HGraph* graph = CreateGraph(&allocator); 77 HBasicBlock* entry = new (&allocator) HBasicBlock(graph); 78 graph->AddBlock(entry); 79 graph->SetEntryBlock(entry); 80 HInstruction* parameter1 = new (&allocator) HParameterValue( 81 graph->GetDexFile(), 0, 0, Primitive::kPrimNot); 82 HInstruction* parameter2 = new (&allocator) HParameterValue( 83 graph->GetDexFile(), 0, 0, Primitive::kPrimNot); 84 entry->AddInstruction(parameter1); 85 entry->AddInstruction(parameter2); 86 entry->AddInstruction(new (&allocator) HExit()); 87 88 ASSERT_FALSE(parameter1->HasUses()); 89 90 HInstruction* to_insert = new (&allocator) HNullCheck(parameter1, 0); 91 entry->InsertInstructionBefore(to_insert, parameter2); 92 93 ASSERT_TRUE(parameter1->HasUses()); 94 ASSERT_TRUE(parameter1->GetUses().HasExactlyOneElement()); 95} 96 97/** 98 * Test that adding an instruction in the graph updates user lists. 99 */ 100TEST(Node, AddInstruction) { 101 ArenaPool pool; 102 ArenaAllocator allocator(&pool); 103 104 HGraph* graph = CreateGraph(&allocator); 105 HBasicBlock* entry = new (&allocator) HBasicBlock(graph); 106 graph->AddBlock(entry); 107 graph->SetEntryBlock(entry); 108 HInstruction* parameter = new (&allocator) HParameterValue( 109 graph->GetDexFile(), 0, 0, Primitive::kPrimNot); 110 entry->AddInstruction(parameter); 111 112 ASSERT_FALSE(parameter->HasUses()); 113 114 HInstruction* to_add = new (&allocator) HNullCheck(parameter, 0); 115 entry->AddInstruction(to_add); 116 117 ASSERT_TRUE(parameter->HasUses()); 118 ASSERT_TRUE(parameter->GetUses().HasExactlyOneElement()); 119} 120 121TEST(Node, ParentEnvironment) { 122 ArenaPool pool; 123 ArenaAllocator allocator(&pool); 124 125 HGraph* graph = CreateGraph(&allocator); 126 HBasicBlock* entry = new (&allocator) HBasicBlock(graph); 127 graph->AddBlock(entry); 128 graph->SetEntryBlock(entry); 129 HInstruction* parameter1 = new (&allocator) HParameterValue( 130 graph->GetDexFile(), 0, 0, Primitive::kPrimNot); 131 HInstruction* with_environment = new (&allocator) HNullCheck(parameter1, 0); 132 entry->AddInstruction(parameter1); 133 entry->AddInstruction(with_environment); 134 entry->AddInstruction(new (&allocator) HExit()); 135 136 ASSERT_TRUE(parameter1->HasUses()); 137 ASSERT_TRUE(parameter1->GetUses().HasExactlyOneElement()); 138 139 HEnvironment* environment = new (&allocator) HEnvironment( 140 &allocator, 1, graph->GetDexFile(), graph->GetMethodIdx(), 0, kStatic, with_environment); 141 ArenaVector<HInstruction*> array(allocator.Adapter()); 142 array.push_back(parameter1); 143 144 environment->CopyFrom(array); 145 with_environment->SetRawEnvironment(environment); 146 147 ASSERT_TRUE(parameter1->HasEnvironmentUses()); 148 ASSERT_TRUE(parameter1->GetEnvUses().HasExactlyOneElement()); 149 150 HEnvironment* parent1 = new (&allocator) HEnvironment( 151 &allocator, 1, graph->GetDexFile(), graph->GetMethodIdx(), 0, kStatic, nullptr); 152 parent1->CopyFrom(array); 153 154 ASSERT_EQ(parameter1->GetEnvUses().SizeSlow(), 2u); 155 156 HEnvironment* parent2 = new (&allocator) HEnvironment( 157 &allocator, 1, graph->GetDexFile(), graph->GetMethodIdx(), 0, kStatic, nullptr); 158 parent2->CopyFrom(array); 159 parent1->SetAndCopyParentChain(&allocator, parent2); 160 161 // One use for parent2, and one other use for the new parent of parent1. 162 ASSERT_EQ(parameter1->GetEnvUses().SizeSlow(), 4u); 163 164 // We have copied the parent chain. So we now have two more uses. 165 environment->SetAndCopyParentChain(&allocator, parent1); 166 ASSERT_EQ(parameter1->GetEnvUses().SizeSlow(), 6u); 167} 168 169} // namespace art 170