12faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes/* 22faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Copyright (C) 2011 The Android Open Source Project 32faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * 42faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License"); 52faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * you may not use this file except in compliance with the License. 62faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * You may obtain a copy of the License at 72faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * 82faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * http://www.apache.org/licenses/LICENSE-2.0 92faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * 102faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Unless required by applicable law or agreed to in writing, software 112faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS, 122faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 132faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * See the License for the specific language governing permissions and 142faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * limitations under the License. 152faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes */ 16db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom 171352f13e76aec57c522f9323cbe04d1368273a94Vladimir Marko#include <string.h> 180cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers#include <vector> 190cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers 201352f13e76aec57c522f9323cbe04d1368273a94Vladimir Marko#include "image_test.h" 2146ee31b67d7ee1bd085fbc240502053caa3cf8faAndreas Gampe 221352f13e76aec57c522f9323cbe04d1368273a94Vladimir Marko#include "image.h" 230795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier#include "scoped_thread_state_change-inl.h" 241352f13e76aec57c522f9323cbe04d1368273a94Vladimir Marko#include "thread.h" 25db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom 26db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstromnamespace art { 277452797678c4345d4a9e65b03e00af703c2c5fe0Vladimir Markonamespace linker { 28db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom 29496577fb4d6d7baea9c093d35d17e208c831bbcaMathieu ChartierTEST_F(ImageTest, TestImageLayout) { 30496577fb4d6d7baea9c093d35d17e208c831bbcaMathieu Chartier std::vector<size_t> image_sizes; 31496577fb4d6d7baea9c093d35d17e208c831bbcaMathieu Chartier std::vector<size_t> image_sizes_extra; 32496577fb4d6d7baea9c093d35d17e208c831bbcaMathieu Chartier // Compile multi-image with ImageLayoutA being the last image. 33496577fb4d6d7baea9c093d35d17e208c831bbcaMathieu Chartier { 34496577fb4d6d7baea9c093d35d17e208c831bbcaMathieu Chartier CompilationHelper helper; 35b3f2b5cfeac75cce1babfc61db46d457fb7c4d70Artem Udovichenko Compile(ImageHeader::kStorageModeUncompressed, helper, "ImageLayoutA", {"LMyClass;"}); 36496577fb4d6d7baea9c093d35d17e208c831bbcaMathieu Chartier image_sizes = helper.GetImageObjectSectionSizes(); 37496577fb4d6d7baea9c093d35d17e208c831bbcaMathieu Chartier } 38496577fb4d6d7baea9c093d35d17e208c831bbcaMathieu Chartier TearDown(); 39496577fb4d6d7baea9c093d35d17e208c831bbcaMathieu Chartier runtime_.reset(); 40496577fb4d6d7baea9c093d35d17e208c831bbcaMathieu Chartier SetUp(); 41496577fb4d6d7baea9c093d35d17e208c831bbcaMathieu Chartier // Compile multi-image with ImageLayoutB being the last image. 42496577fb4d6d7baea9c093d35d17e208c831bbcaMathieu Chartier { 43496577fb4d6d7baea9c093d35d17e208c831bbcaMathieu Chartier CompilationHelper helper; 44b3f2b5cfeac75cce1babfc61db46d457fb7c4d70Artem Udovichenko Compile(ImageHeader::kStorageModeUncompressed, helper, "ImageLayoutB", {"LMyClass;"}); 45496577fb4d6d7baea9c093d35d17e208c831bbcaMathieu Chartier image_sizes_extra = helper.GetImageObjectSectionSizes(); 46496577fb4d6d7baea9c093d35d17e208c831bbcaMathieu Chartier } 47496577fb4d6d7baea9c093d35d17e208c831bbcaMathieu Chartier // Make sure that the new stuff in the clinit in ImageLayoutB is in the last image and not in the 48496577fb4d6d7baea9c093d35d17e208c831bbcaMathieu Chartier // first two images. 49496577fb4d6d7baea9c093d35d17e208c831bbcaMathieu Chartier ASSERT_EQ(image_sizes.size(), image_sizes.size()); 506cfbdbc359ec5414d3e49f70d28f8c0e65b98d63Vladimir Marko // Sizes of the object sections should be the same for all but the last image. 51496577fb4d6d7baea9c093d35d17e208c831bbcaMathieu Chartier for (size_t i = 0; i < image_sizes.size() - 1; ++i) { 52496577fb4d6d7baea9c093d35d17e208c831bbcaMathieu Chartier EXPECT_EQ(image_sizes[i], image_sizes_extra[i]); 53496577fb4d6d7baea9c093d35d17e208c831bbcaMathieu Chartier } 54496577fb4d6d7baea9c093d35d17e208c831bbcaMathieu Chartier // Last image should be larger since it has a hash map and a string. 55496577fb4d6d7baea9c093d35d17e208c831bbcaMathieu Chartier EXPECT_LT(image_sizes.back(), image_sizes_extra.back()); 56496577fb4d6d7baea9c093d35d17e208c831bbcaMathieu Chartier} 57496577fb4d6d7baea9c093d35d17e208c831bbcaMathieu Chartier 58179486aee731f734207873244542993ed4bcff21Brian CarlstromTEST_F(ImageTest, ImageHeaderIsValid) { 59179486aee731f734207873244542993ed4bcff21Brian Carlstrom uint32_t image_begin = ART_BASE_ADDRESS; 60179486aee731f734207873244542993ed4bcff21Brian Carlstrom uint32_t image_size_ = 16 * KB; 61179486aee731f734207873244542993ed4bcff21Brian Carlstrom uint32_t image_roots = ART_BASE_ADDRESS + (1 * KB); 62179486aee731f734207873244542993ed4bcff21Brian Carlstrom uint32_t oat_checksum = 0; 63179486aee731f734207873244542993ed4bcff21Brian Carlstrom uint32_t oat_file_begin = ART_BASE_ADDRESS + (4 * KB); // page aligned 64179486aee731f734207873244542993ed4bcff21Brian Carlstrom uint32_t oat_data_begin = ART_BASE_ADDRESS + (8 * KB); // page aligned 65179486aee731f734207873244542993ed4bcff21Brian Carlstrom uint32_t oat_data_end = ART_BASE_ADDRESS + (9 * KB); 66179486aee731f734207873244542993ed4bcff21Brian Carlstrom uint32_t oat_file_end = ART_BASE_ADDRESS + (10 * KB); 67e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier ImageSection sections[ImageHeader::kSectionCount]; 68179486aee731f734207873244542993ed4bcff21Brian Carlstrom ImageHeader image_header(image_begin, 69179486aee731f734207873244542993ed4bcff21Brian Carlstrom image_size_, 70e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier sections, 71179486aee731f734207873244542993ed4bcff21Brian Carlstrom image_roots, 72179486aee731f734207873244542993ed4bcff21Brian Carlstrom oat_checksum, 73179486aee731f734207873244542993ed4bcff21Brian Carlstrom oat_file_begin, 74179486aee731f734207873244542993ed4bcff21Brian Carlstrom oat_data_begin, 75179486aee731f734207873244542993ed4bcff21Brian Carlstrom oat_data_end, 7646774767fcf7780d1455e755729198648d08742eIgor Murashkin oat_file_end, 77fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier /*boot_image_begin*/0U, 78fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier /*boot_image_size*/0U, 79fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier /*boot_oat_begin*/0U, 80fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier /*boot_oat_size_*/0U, 81e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier sizeof(void*), 82ceb07b3285eaab350a8cd12f7d74be3e40a255ddMathieu Chartier /*compile_pic*/false, 83fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier /*is_pic*/false, 84ceb07b3285eaab350a8cd12f7d74be3e40a255ddMathieu Chartier ImageHeader::kDefaultStorageMode, 85ceb07b3285eaab350a8cd12f7d74be3e40a255ddMathieu Chartier /*data_size*/0u); 86179486aee731f734207873244542993ed4bcff21Brian Carlstrom ASSERT_TRUE(image_header.IsValid()); 87fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier ASSERT_TRUE(!image_header.IsAppImage()); 88179486aee731f734207873244542993ed4bcff21Brian Carlstrom 89179486aee731f734207873244542993ed4bcff21Brian Carlstrom char* magic = const_cast<char*>(image_header.GetMagic()); 90179486aee731f734207873244542993ed4bcff21Brian Carlstrom strcpy(magic, ""); // bad magic 91179486aee731f734207873244542993ed4bcff21Brian Carlstrom ASSERT_FALSE(image_header.IsValid()); 92179486aee731f734207873244542993ed4bcff21Brian Carlstrom strcpy(magic, "art\n000"); // bad version 93179486aee731f734207873244542993ed4bcff21Brian Carlstrom ASSERT_FALSE(image_header.IsValid()); 94179486aee731f734207873244542993ed4bcff21Brian Carlstrom} 95179486aee731f734207873244542993ed4bcff21Brian Carlstrom 96b3f2b5cfeac75cce1babfc61db46d457fb7c4d70Artem Udovichenko// Test that pointer to quick code is the same in 97b3f2b5cfeac75cce1babfc61db46d457fb7c4d70Artem Udovichenko// a default method of an interface and in a copied method 98b3f2b5cfeac75cce1babfc61db46d457fb7c4d70Artem Udovichenko// of a class which implements the interface. This should be true 99b3f2b5cfeac75cce1babfc61db46d457fb7c4d70Artem Udovichenko// only if the copied method and the origin method are located in the 100b3f2b5cfeac75cce1babfc61db46d457fb7c4d70Artem Udovichenko// same oat file. 101b3f2b5cfeac75cce1babfc61db46d457fb7c4d70Artem UdovichenkoTEST_F(ImageTest, TestDefaultMethods) { 102b3f2b5cfeac75cce1babfc61db46d457fb7c4d70Artem Udovichenko CompilationHelper helper; 103b3f2b5cfeac75cce1babfc61db46d457fb7c4d70Artem Udovichenko Compile(ImageHeader::kStorageModeUncompressed, 104b3f2b5cfeac75cce1babfc61db46d457fb7c4d70Artem Udovichenko helper, 105b3f2b5cfeac75cce1babfc61db46d457fb7c4d70Artem Udovichenko "DefaultMethods", 106b3f2b5cfeac75cce1babfc61db46d457fb7c4d70Artem Udovichenko {"LIface;", "LImpl;", "LIterableBase;"}); 107b3f2b5cfeac75cce1babfc61db46d457fb7c4d70Artem Udovichenko 108b3f2b5cfeac75cce1babfc61db46d457fb7c4d70Artem Udovichenko PointerSize pointer_size = class_linker_->GetImagePointerSize(); 109b3f2b5cfeac75cce1babfc61db46d457fb7c4d70Artem Udovichenko Thread* self = Thread::Current(); 110b3f2b5cfeac75cce1babfc61db46d457fb7c4d70Artem Udovichenko ScopedObjectAccess soa(self); 111b3f2b5cfeac75cce1babfc61db46d457fb7c4d70Artem Udovichenko 112b3f2b5cfeac75cce1babfc61db46d457fb7c4d70Artem Udovichenko // Test the pointer to quick code is the same in origin method 113b3f2b5cfeac75cce1babfc61db46d457fb7c4d70Artem Udovichenko // and in the copied method form the same oat file. 114b3f2b5cfeac75cce1babfc61db46d457fb7c4d70Artem Udovichenko mirror::Class* iface_klass = class_linker_->LookupClass( 115b3f2b5cfeac75cce1babfc61db46d457fb7c4d70Artem Udovichenko self, "LIface;", ObjPtr<mirror::ClassLoader>()); 116b3f2b5cfeac75cce1babfc61db46d457fb7c4d70Artem Udovichenko ASSERT_NE(nullptr, iface_klass); 117ba118827465d12177f3996e50133960087b1c916Vladimir Marko ArtMethod* origin = iface_klass->FindInterfaceMethod("defaultMethod", "()V", pointer_size); 118b3f2b5cfeac75cce1babfc61db46d457fb7c4d70Artem Udovichenko ASSERT_NE(nullptr, origin); 119ba118827465d12177f3996e50133960087b1c916Vladimir Marko ASSERT_TRUE(origin->GetDeclaringClass() == iface_klass); 120b3f2b5cfeac75cce1babfc61db46d457fb7c4d70Artem Udovichenko const void* code = origin->GetEntryPointFromQuickCompiledCodePtrSize(pointer_size); 121b3f2b5cfeac75cce1babfc61db46d457fb7c4d70Artem Udovichenko // The origin method should have a pointer to quick code 122b3f2b5cfeac75cce1babfc61db46d457fb7c4d70Artem Udovichenko ASSERT_NE(nullptr, code); 123b3f2b5cfeac75cce1babfc61db46d457fb7c4d70Artem Udovichenko ASSERT_FALSE(class_linker_->IsQuickToInterpreterBridge(code)); 124b3f2b5cfeac75cce1babfc61db46d457fb7c4d70Artem Udovichenko mirror::Class* impl_klass = class_linker_->LookupClass( 125b3f2b5cfeac75cce1babfc61db46d457fb7c4d70Artem Udovichenko self, "LImpl;", ObjPtr<mirror::ClassLoader>()); 126b3f2b5cfeac75cce1babfc61db46d457fb7c4d70Artem Udovichenko ASSERT_NE(nullptr, impl_klass); 127b3f2b5cfeac75cce1babfc61db46d457fb7c4d70Artem Udovichenko ArtMethod* copied = FindCopiedMethod(origin, impl_klass); 128b3f2b5cfeac75cce1babfc61db46d457fb7c4d70Artem Udovichenko ASSERT_NE(nullptr, copied); 129b3f2b5cfeac75cce1babfc61db46d457fb7c4d70Artem Udovichenko // the copied method should have pointer to the same quick code as the origin method 130b3f2b5cfeac75cce1babfc61db46d457fb7c4d70Artem Udovichenko ASSERT_EQ(code, copied->GetEntryPointFromQuickCompiledCodePtrSize(pointer_size)); 131b3f2b5cfeac75cce1babfc61db46d457fb7c4d70Artem Udovichenko 132b3f2b5cfeac75cce1babfc61db46d457fb7c4d70Artem Udovichenko // Test the origin method has pointer to quick code 133b3f2b5cfeac75cce1babfc61db46d457fb7c4d70Artem Udovichenko // but the copied method has pointer to interpreter 134b3f2b5cfeac75cce1babfc61db46d457fb7c4d70Artem Udovichenko // because these methods are in different oat files. 135b3f2b5cfeac75cce1babfc61db46d457fb7c4d70Artem Udovichenko mirror::Class* iterable_klass = class_linker_->LookupClass( 136b3f2b5cfeac75cce1babfc61db46d457fb7c4d70Artem Udovichenko self, "Ljava/lang/Iterable;", ObjPtr<mirror::ClassLoader>()); 137b3f2b5cfeac75cce1babfc61db46d457fb7c4d70Artem Udovichenko ASSERT_NE(nullptr, iterable_klass); 138ba118827465d12177f3996e50133960087b1c916Vladimir Marko origin = iterable_klass->FindClassMethod( 139b3f2b5cfeac75cce1babfc61db46d457fb7c4d70Artem Udovichenko "forEach", "(Ljava/util/function/Consumer;)V", pointer_size); 140b3f2b5cfeac75cce1babfc61db46d457fb7c4d70Artem Udovichenko ASSERT_NE(nullptr, origin); 141ba118827465d12177f3996e50133960087b1c916Vladimir Marko ASSERT_FALSE(origin->IsDirect()); 142ba118827465d12177f3996e50133960087b1c916Vladimir Marko ASSERT_TRUE(origin->GetDeclaringClass() == iterable_klass); 143b3f2b5cfeac75cce1babfc61db46d457fb7c4d70Artem Udovichenko code = origin->GetEntryPointFromQuickCompiledCodePtrSize(pointer_size); 144b3f2b5cfeac75cce1babfc61db46d457fb7c4d70Artem Udovichenko // the origin method should have a pointer to quick code 145b3f2b5cfeac75cce1babfc61db46d457fb7c4d70Artem Udovichenko ASSERT_NE(nullptr, code); 146b3f2b5cfeac75cce1babfc61db46d457fb7c4d70Artem Udovichenko ASSERT_FALSE(class_linker_->IsQuickToInterpreterBridge(code)); 147b3f2b5cfeac75cce1babfc61db46d457fb7c4d70Artem Udovichenko mirror::Class* iterablebase_klass = class_linker_->LookupClass( 148b3f2b5cfeac75cce1babfc61db46d457fb7c4d70Artem Udovichenko self, "LIterableBase;", ObjPtr<mirror::ClassLoader>()); 149b3f2b5cfeac75cce1babfc61db46d457fb7c4d70Artem Udovichenko ASSERT_NE(nullptr, iterablebase_klass); 150b3f2b5cfeac75cce1babfc61db46d457fb7c4d70Artem Udovichenko copied = FindCopiedMethod(origin, iterablebase_klass); 151b3f2b5cfeac75cce1babfc61db46d457fb7c4d70Artem Udovichenko ASSERT_NE(nullptr, copied); 152b3f2b5cfeac75cce1babfc61db46d457fb7c4d70Artem Udovichenko code = copied->GetEntryPointFromQuickCompiledCodePtrSize(pointer_size); 153b3f2b5cfeac75cce1babfc61db46d457fb7c4d70Artem Udovichenko // the copied method should have a pointer to interpreter 154b3f2b5cfeac75cce1babfc61db46d457fb7c4d70Artem Udovichenko ASSERT_TRUE(class_linker_->IsQuickToInterpreterBridge(code)); 155b3f2b5cfeac75cce1babfc61db46d457fb7c4d70Artem Udovichenko} 156b3f2b5cfeac75cce1babfc61db46d457fb7c4d70Artem Udovichenko 1577452797678c4345d4a9e65b03e00af703c2c5fe0Vladimir Marko} // namespace linker 158db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom} // namespace art 159