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