17de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik/*
27de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik * Copyright (C) 2016 The Android Open Source Project
37de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik *
47de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik * Licensed under the Apache License, Version 2.0 (the "License");
57de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik * you may not use this file except in compliance with the License.
67de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik * You may obtain a copy of the License at
77de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik *
87de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik *      http://www.apache.org/licenses/LICENSE-2.0
97de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik *
107de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik * Unless required by applicable law or agreed to in writing, software
117de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik * distributed under the License is distributed on an "AS IS" BASIS,
127de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
137de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik * See the License for the specific language governing permissions and
147de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik * limitations under the License.
157de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik */
167de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik
177de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik#include "base/arena_allocator.h"
187de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik#include "builder.h"
197de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik#include "nodes.h"
207de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik#include "object_lock.h"
217de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik#include "optimizing_unit_test.h"
227de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik#include "reference_type_propagation.h"
237de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik
247de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Biknamespace art {
257de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik
267de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik/**
277de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik * Fixture class for unit testing the ReferenceTypePropagation phase. Used to verify the
287de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik * functionality of methods and situations that are hard to set up with checker tests.
297de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik */
307de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bikclass ReferenceTypePropagationTest : public CommonCompilerTest {
317de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik public:
327de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  ReferenceTypePropagationTest() : pool_(), allocator_(&pool_) {
337de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik    graph_ = CreateGraph(&allocator_);
347de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  }
357de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik
367de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  ~ReferenceTypePropagationTest() { }
377de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik
387de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  void SetupPropagation(StackHandleScopeCollection* handles) {
397de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik    graph_->InitializeInexactObjectRTI(handles);
40a4336d253b88f95c49891a8084579a4599785e90Vladimir Marko    propagation_ = new (&allocator_) ReferenceTypePropagation(graph_,
41a4336d253b88f95c49891a8084579a4599785e90Vladimir Marko                                                              Handle<mirror::DexCache>(),
42a4336d253b88f95c49891a8084579a4599785e90Vladimir Marko                                                              handles,
43a4336d253b88f95c49891a8084579a4599785e90Vladimir Marko                                                              true,
44a4336d253b88f95c49891a8084579a4599785e90Vladimir Marko                                                              "test_prop");
457de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  }
467de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik
477de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  // Relay method to merge type in reference type propagation.
487de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  ReferenceTypeInfo MergeTypes(const ReferenceTypeInfo& a,
497de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik                               const ReferenceTypeInfo& b) SHARED_REQUIRES(Locks::mutator_lock_) {
507de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik    return propagation_->MergeTypes(a, b);
517de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  }
527de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik
537de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  // Helper method to construct an invalid type.
547de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  ReferenceTypeInfo InvalidType() {
557de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik    return ReferenceTypeInfo::CreateInvalid();
567de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  }
577de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik
587de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  // Helper method to construct the Object type.
597de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  ReferenceTypeInfo ObjectType(bool is_exact = true) SHARED_REQUIRES(Locks::mutator_lock_) {
607de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik    return ReferenceTypeInfo::Create(propagation_->handle_cache_.GetObjectClassHandle(), is_exact);
617de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  }
627de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik
637de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  // Helper method to construct the String type.
647de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  ReferenceTypeInfo StringType(bool is_exact = true) SHARED_REQUIRES(Locks::mutator_lock_) {
657de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik    return ReferenceTypeInfo::Create(propagation_->handle_cache_.GetStringClassHandle(), is_exact);
667de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  }
677de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik
687de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  // General building fields.
697de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  ArenaPool pool_;
707de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  ArenaAllocator allocator_;
717de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  HGraph* graph_;
727de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik
737de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  ReferenceTypePropagation* propagation_;
747de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik};
757de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik
767de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik//
777de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik// The actual ReferenceTypePropgation unit tests.
787de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik//
797de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik
807de2439d357710aaf8bfe02b8cf9c196d3c77705Aart BikTEST_F(ReferenceTypePropagationTest, ProperSetup) {
817de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  ScopedObjectAccess soa(Thread::Current());
827de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  StackHandleScopeCollection handles(soa.Self());
837de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  SetupPropagation(&handles);
847de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik
857de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  EXPECT_TRUE(propagation_ != nullptr);
867de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  EXPECT_TRUE(graph_->GetInexactObjectRti().IsEqual(ObjectType(false)));
877de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik}
887de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik
897de2439d357710aaf8bfe02b8cf9c196d3c77705Aart BikTEST_F(ReferenceTypePropagationTest, MergeInvalidTypes) {
907de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  ScopedObjectAccess soa(Thread::Current());
917de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  StackHandleScopeCollection handles(soa.Self());
927de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  SetupPropagation(&handles);
937de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik
947de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  // Two invalid types.
957de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  ReferenceTypeInfo t1(MergeTypes(InvalidType(), InvalidType()));
967de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  EXPECT_FALSE(t1.IsValid());
977de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  EXPECT_FALSE(t1.IsExact());
987de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  EXPECT_TRUE(t1.IsEqual(InvalidType()));
997de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik
1007de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  // Valid type on right.
1017de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  ReferenceTypeInfo t2(MergeTypes(InvalidType(), ObjectType()));
1027de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  EXPECT_TRUE(t2.IsValid());
1037de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  EXPECT_TRUE(t2.IsExact());
1047de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  EXPECT_TRUE(t2.IsEqual(ObjectType()));
1057de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  ReferenceTypeInfo t3(MergeTypes(InvalidType(), StringType()));
1067de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  EXPECT_TRUE(t3.IsValid());
1077de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  EXPECT_TRUE(t3.IsExact());
1087de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  EXPECT_TRUE(t3.IsEqual(StringType()));
1097de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik
1107de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  // Valid type on left.
1117de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  ReferenceTypeInfo t4(MergeTypes(ObjectType(), InvalidType()));
1127de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  EXPECT_TRUE(t4.IsValid());
1137de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  EXPECT_TRUE(t4.IsExact());
1147de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  EXPECT_TRUE(t4.IsEqual(ObjectType()));
1157de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  ReferenceTypeInfo t5(MergeTypes(StringType(), InvalidType()));
1167de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  EXPECT_TRUE(t5.IsValid());
1177de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  EXPECT_TRUE(t5.IsExact());
1187de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  EXPECT_TRUE(t5.IsEqual(StringType()));
1197de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik}
1207de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik
1217de2439d357710aaf8bfe02b8cf9c196d3c77705Aart BikTEST_F(ReferenceTypePropagationTest, MergeValidTypes) {
1227de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  ScopedObjectAccess soa(Thread::Current());
1237de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  StackHandleScopeCollection handles(soa.Self());
1247de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  SetupPropagation(&handles);
1257de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik
1267de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  // Same types.
1277de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  ReferenceTypeInfo t1(MergeTypes(ObjectType(), ObjectType()));
1287de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  EXPECT_TRUE(t1.IsValid());
1297de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  EXPECT_TRUE(t1.IsExact());
1307de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  EXPECT_TRUE(t1.IsEqual(ObjectType()));
1317de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  ReferenceTypeInfo t2(MergeTypes(StringType(), StringType()));
1327de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  EXPECT_TRUE(t2.IsValid());
1337de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  EXPECT_TRUE(t2.IsExact());
1347de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  EXPECT_TRUE(t2.IsEqual(StringType()));
1357de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik
1367de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  // Left is super class of right.
1377de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  ReferenceTypeInfo t3(MergeTypes(ObjectType(), StringType()));
1387de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  EXPECT_TRUE(t3.IsValid());
1397de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  EXPECT_FALSE(t3.IsExact());
1407de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  EXPECT_TRUE(t3.IsEqual(ObjectType(false)));
1417de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik
1427de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  // Right is super class of left.
1437de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  ReferenceTypeInfo t4(MergeTypes(StringType(), ObjectType()));
1447de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  EXPECT_TRUE(t4.IsValid());
1457de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  EXPECT_FALSE(t4.IsExact());
1467de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  EXPECT_TRUE(t4.IsEqual(ObjectType(false)));
1477de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik
1487de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  // Same types, but one or both are inexact.
1497de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  ReferenceTypeInfo t5(MergeTypes(ObjectType(false), ObjectType()));
1507de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  EXPECT_TRUE(t5.IsValid());
1517de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  EXPECT_FALSE(t5.IsExact());
1527de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  EXPECT_TRUE(t5.IsEqual(ObjectType(false)));
1537de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  ReferenceTypeInfo t6(MergeTypes(ObjectType(), ObjectType(false)));
1547de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  EXPECT_TRUE(t6.IsValid());
1557de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  EXPECT_FALSE(t6.IsExact());
1567de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  EXPECT_TRUE(t6.IsEqual(ObjectType(false)));
1577de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  ReferenceTypeInfo t7(MergeTypes(ObjectType(false), ObjectType(false)));
1587de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  EXPECT_TRUE(t7.IsValid());
1597de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  EXPECT_FALSE(t7.IsExact());
1607de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik  EXPECT_TRUE(t7.IsEqual(ObjectType(false)));
1617de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik}
1627de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik
1637de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik}  // namespace art
1647de2439d357710aaf8bfe02b8cf9c196d3c77705Aart Bik
165