1 /* 2 * Copyright (C) 2015 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 <memory> 18 #include <vector> 19 20 #include "arch/instruction_set.h" 21 #include "base/arena_allocator.h" 22 #include "base/enums.h" 23 #include "base/malloc_arena_pool.h" 24 #include "cfi_test.h" 25 #include "gtest/gtest.h" 26 #include "jni/quick/calling_convention.h" 27 #include "read_barrier_config.h" 28 #include "utils/assembler.h" 29 #include "utils/jni_macro_assembler.h" 30 31 #include "jni/jni_cfi_test_expected.inc" 32 33 namespace art { 34 35 // Run the tests only on host. 36 #ifndef ART_TARGET_ANDROID 37 38 class JNICFITest : public CFITest { 39 public: 40 // Enable this flag to generate the expected outputs. 41 static constexpr bool kGenerateExpected = false; 42 TestImpl(InstructionSet isa,const char * isa_str,const std::vector<uint8_t> & expected_asm,const std::vector<uint8_t> & expected_cfi)43 void TestImpl(InstructionSet isa, 44 const char* isa_str, 45 const std::vector<uint8_t>& expected_asm, 46 const std::vector<uint8_t>& expected_cfi) { 47 if (Is64BitInstructionSet(isa)) { 48 TestImplSized<PointerSize::k64>(isa, isa_str, expected_asm, expected_cfi); 49 } else { 50 TestImplSized<PointerSize::k32>(isa, isa_str, expected_asm, expected_cfi); 51 } 52 } 53 54 private: 55 template <PointerSize kPointerSize> TestImplSized(InstructionSet isa,const char * isa_str,const std::vector<uint8_t> & expected_asm,const std::vector<uint8_t> & expected_cfi)56 void TestImplSized(InstructionSet isa, 57 const char* isa_str, 58 const std::vector<uint8_t>& expected_asm, 59 const std::vector<uint8_t>& expected_cfi) { 60 // Description of simple method. 61 const bool is_static = true; 62 const bool is_synchronized = false; 63 const char* shorty = "IIFII"; 64 65 MallocArenaPool pool; 66 ArenaAllocator allocator(&pool); 67 68 std::unique_ptr<JniCallingConvention> jni_conv( 69 JniCallingConvention::Create(&allocator, 70 is_static, 71 is_synchronized, 72 /*is_critical_native*/false, 73 shorty, 74 isa)); 75 std::unique_ptr<ManagedRuntimeCallingConvention> mr_conv( 76 ManagedRuntimeCallingConvention::Create( 77 &allocator, is_static, is_synchronized, shorty, isa)); 78 const int frame_size(jni_conv->FrameSize()); 79 ArrayRef<const ManagedRegister> callee_save_regs = jni_conv->CalleeSaveRegisters(); 80 81 // Assemble the method. 82 std::unique_ptr<JNIMacroAssembler<kPointerSize>> jni_asm( 83 JNIMacroAssembler<kPointerSize>::Create(&allocator, isa)); 84 jni_asm->cfi().SetEnabled(true); 85 jni_asm->BuildFrame(frame_size, mr_conv->MethodRegister(), 86 callee_save_regs, mr_conv->EntrySpills()); 87 jni_asm->IncreaseFrameSize(32); 88 jni_asm->DecreaseFrameSize(32); 89 jni_asm->RemoveFrame(frame_size, callee_save_regs, /* may_suspend= */ true); 90 jni_asm->FinalizeCode(); 91 std::vector<uint8_t> actual_asm(jni_asm->CodeSize()); 92 MemoryRegion code(&actual_asm[0], actual_asm.size()); 93 jni_asm->FinalizeInstructions(code); 94 ASSERT_EQ(jni_asm->cfi().GetCurrentCFAOffset(), frame_size); 95 const std::vector<uint8_t>& actual_cfi = *(jni_asm->cfi().data()); 96 97 if (kGenerateExpected) { 98 GenerateExpected(stdout, 99 isa, 100 isa_str, 101 ArrayRef<const uint8_t>(actual_asm), 102 ArrayRef<const uint8_t>(actual_cfi)); 103 } else { 104 EXPECT_EQ(expected_asm, actual_asm); 105 EXPECT_EQ(expected_cfi, actual_cfi); 106 } 107 } 108 }; 109 110 #define TEST_ISA(isa) \ 111 TEST_F(JNICFITest, isa) { \ 112 std::vector<uint8_t> expected_asm(expected_asm_##isa, \ 113 expected_asm_##isa + arraysize(expected_asm_##isa)); \ 114 std::vector<uint8_t> expected_cfi(expected_cfi_##isa, \ 115 expected_cfi_##isa + arraysize(expected_cfi_##isa)); \ 116 TestImpl(InstructionSet::isa, #isa, expected_asm, expected_cfi); \ 117 } 118 119 #ifdef ART_ENABLE_CODEGEN_arm 120 // Run the tests for ARM only with Baker read barriers, as the 121 // expected generated code contains a Marking Register refresh 122 // instruction. 123 #if defined(USE_READ_BARRIER) && defined(USE_BAKER_READ_BARRIER) 124 TEST_ISA(kThumb2) 125 #endif 126 #endif 127 128 #ifdef ART_ENABLE_CODEGEN_arm64 129 // Run the tests for ARM64 only with Baker read barriers, as the 130 // expected generated code contains a Marking Register refresh 131 // instruction. 132 #if defined(USE_READ_BARRIER) && defined(USE_BAKER_READ_BARRIER) 133 TEST_ISA(kArm64) 134 #endif 135 #endif 136 137 #ifdef ART_ENABLE_CODEGEN_x86 138 TEST_ISA(kX86) 139 #endif 140 141 #ifdef ART_ENABLE_CODEGEN_x86_64 142 TEST_ISA(kX86_64) 143 #endif 144 145 #endif // ART_TARGET_ANDROID 146 147 } // namespace art 148