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 */
163320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom
173320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom#include "compiled_method.h"
1835831e8bfa1c0944d4c978d99c4c5b9577945170Vladimir Marko
1935831e8bfa1c0944d4c978d99c4c5b9577945170Vladimir Marko#include "driver/compiled_method_storage.h"
20193bad9b9cfd10642043fa2ebbfc68bd5f9ede4bMathieu Chartier#include "driver/compiler_driver.h"
2135831e8bfa1c0944d4c978d99c4c5b9577945170Vladimir Marko#include "utils/swap_space.h"
223320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom
233320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstromnamespace art {
243320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom
25d8dbc8da0e5cc6b5c2176ce2d3877e6194d72c0cVladimir MarkoCompiledCode::CompiledCode(CompilerDriver* compiler_driver,
26d8dbc8da0e5cc6b5c2176ce2d3877e6194d72c0cVladimir Marko                           InstructionSet instruction_set,
2735831e8bfa1c0944d4c978d99c4c5b9577945170Vladimir Marko                           const ArrayRef<const uint8_t>& quick_code)
2835831e8bfa1c0944d4c978d99c4c5b9577945170Vladimir Marko    : compiler_driver_(compiler_driver),
2992f7f3ce3b01f7c7df1c15b81c900e087248093fVladimir Marko      quick_code_(compiler_driver_->GetCompiledMethodStorage()->DeduplicateCode(quick_code)),
3092f7f3ce3b01f7c7df1c15b81c900e087248093fVladimir Marko      packed_fields_(InstructionSetField::Encode(instruction_set)) {
31e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier}
32e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier
33e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu ChartierCompiledCode::~CompiledCode() {
3435831e8bfa1c0944d4c978d99c4c5b9577945170Vladimir Marko  compiler_driver_->GetCompiledMethodStorage()->ReleaseCode(quick_code_);
35ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers}
36ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers
37ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogersbool CompiledCode::operator==(const CompiledCode& rhs) const {
38ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  if (quick_code_ != nullptr) {
39ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (rhs.quick_code_ == nullptr) {
40ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      return false;
41ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    } else if (quick_code_->size() != rhs.quick_code_->size()) {
42ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      return false;
43ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    } else {
44ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      return std::equal(quick_code_->begin(), quick_code_->end(), rhs.quick_code_->begin());
45ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    }
46ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  }
47956af0f0cb05422e38c1d22cbef309d16b8a1a12Elliott Hughes  return (rhs.quick_code_ == nullptr);
48265091e581c9f643b37e7966890911f09e223269Brian Carlstrom}
49265091e581c9f643b37e7966890911f09e223269Brian Carlstrom
50e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartiersize_t CompiledCode::AlignCode(size_t offset) const {
5192f7f3ce3b01f7c7df1c15b81c900e087248093fVladimir Marko  return AlignCode(offset, GetInstructionSet());
52598c513a2737d872e22ea8bcedec61b92deff357Logan Chien}
53598c513a2737d872e22ea8bcedec61b92deff357Logan Chien
54e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartiersize_t CompiledCode::AlignCode(size_t offset, InstructionSet instruction_set) {
55af13ad9fd18b6f75fe82e7995224c55654594f93Andreas Gampe  return RoundUp(offset, GetInstructionSetAlignment(instruction_set));
56598c513a2737d872e22ea8bcedec61b92deff357Logan Chien}
57598c513a2737d872e22ea8bcedec61b92deff357Logan Chien
58598c513a2737d872e22ea8bcedec61b92deff357Logan Chiensize_t CompiledCode::CodeDelta() const {
5992f7f3ce3b01f7c7df1c15b81c900e087248093fVladimir Marko  return CodeDelta(GetInstructionSet());
6050abf0ad03c2cad0fa7969fc1b0bfadb0ca3bf3aDave Allison}
6150abf0ad03c2cad0fa7969fc1b0bfadb0ca3bf3aDave Allison
6250abf0ad03c2cad0fa7969fc1b0bfadb0ca3bf3aDave Allisonsize_t CompiledCode::CodeDelta(InstructionSet instruction_set) {
6350abf0ad03c2cad0fa7969fc1b0bfadb0ca3bf3aDave Allison  switch (instruction_set) {
6433bff25bcd7a02d35c54f63740eadb1a4833fc92Vladimir Marko    case InstructionSet::kArm:
6533bff25bcd7a02d35c54f63740eadb1a4833fc92Vladimir Marko    case InstructionSet::kArm64:
6633bff25bcd7a02d35c54f63740eadb1a4833fc92Vladimir Marko    case InstructionSet::kMips:
6733bff25bcd7a02d35c54f63740eadb1a4833fc92Vladimir Marko    case InstructionSet::kMips64:
6833bff25bcd7a02d35c54f63740eadb1a4833fc92Vladimir Marko    case InstructionSet::kX86:
6933bff25bcd7a02d35c54f63740eadb1a4833fc92Vladimir Marko    case InstructionSet::kX86_64:
70598c513a2737d872e22ea8bcedec61b92deff357Logan Chien      return 0;
7133bff25bcd7a02d35c54f63740eadb1a4833fc92Vladimir Marko    case InstructionSet::kThumb2: {
72598c513a2737d872e22ea8bcedec61b92deff357Logan Chien      // +1 to set the low-order bit so a BLX will switch to Thumb mode
73598c513a2737d872e22ea8bcedec61b92deff357Logan Chien      return 1;
74598c513a2737d872e22ea8bcedec61b92deff357Logan Chien    }
75598c513a2737d872e22ea8bcedec61b92deff357Logan Chien    default:
7650abf0ad03c2cad0fa7969fc1b0bfadb0ca3bf3aDave Allison      LOG(FATAL) << "Unknown InstructionSet: " << instruction_set;
77598c513a2737d872e22ea8bcedec61b92deff357Logan Chien      return 0;
78598c513a2737d872e22ea8bcedec61b92deff357Logan Chien  }
79598c513a2737d872e22ea8bcedec61b92deff357Logan Chien}
80598c513a2737d872e22ea8bcedec61b92deff357Logan Chien
81d8dbc8da0e5cc6b5c2176ce2d3877e6194d72c0cVladimir Markoconst void* CompiledCode::CodePointer(const void* code_pointer, InstructionSet instruction_set) {
82598c513a2737d872e22ea8bcedec61b92deff357Logan Chien  switch (instruction_set) {
8333bff25bcd7a02d35c54f63740eadb1a4833fc92Vladimir Marko    case InstructionSet::kArm:
8433bff25bcd7a02d35c54f63740eadb1a4833fc92Vladimir Marko    case InstructionSet::kArm64:
8533bff25bcd7a02d35c54f63740eadb1a4833fc92Vladimir Marko    case InstructionSet::kMips:
8633bff25bcd7a02d35c54f63740eadb1a4833fc92Vladimir Marko    case InstructionSet::kMips64:
8733bff25bcd7a02d35c54f63740eadb1a4833fc92Vladimir Marko    case InstructionSet::kX86:
8833bff25bcd7a02d35c54f63740eadb1a4833fc92Vladimir Marko    case InstructionSet::kX86_64:
89598c513a2737d872e22ea8bcedec61b92deff357Logan Chien      return code_pointer;
9033bff25bcd7a02d35c54f63740eadb1a4833fc92Vladimir Marko    case InstructionSet::kThumb2: {
91598c513a2737d872e22ea8bcedec61b92deff357Logan Chien      uintptr_t address = reinterpret_cast<uintptr_t>(code_pointer);
92598c513a2737d872e22ea8bcedec61b92deff357Logan Chien      // Set the low-order bit so a BLX will switch to Thumb mode
93598c513a2737d872e22ea8bcedec61b92deff357Logan Chien      address |= 0x1;
94598c513a2737d872e22ea8bcedec61b92deff357Logan Chien      return reinterpret_cast<const void*>(address);
95598c513a2737d872e22ea8bcedec61b92deff357Logan Chien    }
96598c513a2737d872e22ea8bcedec61b92deff357Logan Chien    default:
97598c513a2737d872e22ea8bcedec61b92deff357Logan Chien      LOG(FATAL) << "Unknown InstructionSet: " << instruction_set;
982cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier      return nullptr;
99598c513a2737d872e22ea8bcedec61b92deff357Logan Chien  }
100598c513a2737d872e22ea8bcedec61b92deff357Logan Chien}
101598c513a2737d872e22ea8bcedec61b92deff357Logan Chien
10272d32629303f8f39362a4099481f48646aed042fIan RogersCompiledMethod::CompiledMethod(CompilerDriver* driver,
103193bad9b9cfd10642043fa2ebbfc68bd5f9ede4bMathieu Chartier                               InstructionSet instruction_set,
104e21dc3db191df04c100620965bee4617b3b24397Andreas Gampe                               const ArrayRef<const uint8_t>& quick_code,
1053320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom                               const size_t frame_size_in_bytes,
1063320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom                               const uint32_t core_spill_mask,
1073320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom                               const uint32_t fp_spill_mask,
108cbcedbf9382bc773713cd3552ed96f417bf1daebMathieu Chartier                               const ArrayRef<const uint8_t>& method_info,
109e21dc3db191df04c100620965bee4617b3b24397Andreas Gampe                               const ArrayRef<const uint8_t>& vmap_table,
110e21dc3db191df04c100620965bee4617b3b24397Andreas Gampe                               const ArrayRef<const uint8_t>& cfi_info,
111d8dbc8da0e5cc6b5c2176ce2d3877e6194d72c0cVladimir Marko                               const ArrayRef<const linker::LinkerPatch>& patches)
11235831e8bfa1c0944d4c978d99c4c5b9577945170Vladimir Marko    : CompiledCode(driver, instruction_set, quick_code),
113cbcedbf9382bc773713cd3552ed96f417bf1daebMathieu Chartier      frame_size_in_bytes_(frame_size_in_bytes),
114cbcedbf9382bc773713cd3552ed96f417bf1daebMathieu Chartier      core_spill_mask_(core_spill_mask),
115e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier      fp_spill_mask_(fp_spill_mask),
116cbcedbf9382bc773713cd3552ed96f417bf1daebMathieu Chartier      method_info_(driver->GetCompiledMethodStorage()->DeduplicateMethodInfo(method_info)),
11735831e8bfa1c0944d4c978d99c4c5b9577945170Vladimir Marko      vmap_table_(driver->GetCompiledMethodStorage()->DeduplicateVMapTable(vmap_table)),
11835831e8bfa1c0944d4c978d99c4c5b9577945170Vladimir Marko      cfi_info_(driver->GetCompiledMethodStorage()->DeduplicateCFIInfo(cfi_info)),
11935831e8bfa1c0944d4c978d99c4c5b9577945170Vladimir Marko      patches_(driver->GetCompiledMethodStorage()->DeduplicateLinkerPatches(patches)) {
1203320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom}
1213320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom
122e21dc3db191df04c100620965bee4617b3b24397Andreas GampeCompiledMethod* CompiledMethod::SwapAllocCompiledMethod(
123e21dc3db191df04c100620965bee4617b3b24397Andreas Gampe    CompilerDriver* driver,
124e21dc3db191df04c100620965bee4617b3b24397Andreas Gampe    InstructionSet instruction_set,
125e21dc3db191df04c100620965bee4617b3b24397Andreas Gampe    const ArrayRef<const uint8_t>& quick_code,
126e21dc3db191df04c100620965bee4617b3b24397Andreas Gampe    const size_t frame_size_in_bytes,
127e21dc3db191df04c100620965bee4617b3b24397Andreas Gampe    const uint32_t core_spill_mask,
128e21dc3db191df04c100620965bee4617b3b24397Andreas Gampe    const uint32_t fp_spill_mask,
129cbcedbf9382bc773713cd3552ed96f417bf1daebMathieu Chartier    const ArrayRef<const uint8_t>& method_info,
130e21dc3db191df04c100620965bee4617b3b24397Andreas Gampe    const ArrayRef<const uint8_t>& vmap_table,
131e21dc3db191df04c100620965bee4617b3b24397Andreas Gampe    const ArrayRef<const uint8_t>& cfi_info,
132d8dbc8da0e5cc6b5c2176ce2d3877e6194d72c0cVladimir Marko    const ArrayRef<const linker::LinkerPatch>& patches) {
13335831e8bfa1c0944d4c978d99c4c5b9577945170Vladimir Marko  SwapAllocator<CompiledMethod> alloc(driver->GetCompiledMethodStorage()->GetSwapSpaceAllocator());
134e21dc3db191df04c100620965bee4617b3b24397Andreas Gampe  CompiledMethod* ret = alloc.allocate(1);
1359d07e3d128ccfa0ef7670feadd424a825e447d1dVladimir Marko  alloc.construct(ret,
1369d07e3d128ccfa0ef7670feadd424a825e447d1dVladimir Marko                  driver,
1379d07e3d128ccfa0ef7670feadd424a825e447d1dVladimir Marko                  instruction_set,
1389d07e3d128ccfa0ef7670feadd424a825e447d1dVladimir Marko                  quick_code,
1399d07e3d128ccfa0ef7670feadd424a825e447d1dVladimir Marko                  frame_size_in_bytes,
1409d07e3d128ccfa0ef7670feadd424a825e447d1dVladimir Marko                  core_spill_mask,
1419d07e3d128ccfa0ef7670feadd424a825e447d1dVladimir Marko                  fp_spill_mask,
142cbcedbf9382bc773713cd3552ed96f417bf1daebMathieu Chartier                  method_info,
1439d07e3d128ccfa0ef7670feadd424a825e447d1dVladimir Marko                  vmap_table,
144e21dc3db191df04c100620965bee4617b3b24397Andreas Gampe                  cfi_info, patches);
145e21dc3db191df04c100620965bee4617b3b24397Andreas Gampe  return ret;
1463946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray}
1473946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray
148e21dc3db191df04c100620965bee4617b3b24397Andreas Gampevoid CompiledMethod::ReleaseSwapAllocatedCompiledMethod(CompilerDriver* driver, CompiledMethod* m) {
14935831e8bfa1c0944d4c978d99c4c5b9577945170Vladimir Marko  SwapAllocator<CompiledMethod> alloc(driver->GetCompiledMethodStorage()->GetSwapSpaceAllocator());
150e21dc3db191df04c100620965bee4617b3b24397Andreas Gampe  alloc.destroy(m);
151e21dc3db191df04c100620965bee4617b3b24397Andreas Gampe  alloc.deallocate(m, 1);
152193bad9b9cfd10642043fa2ebbfc68bd5f9ede4bMathieu Chartier}
153193bad9b9cfd10642043fa2ebbfc68bd5f9ede4bMathieu Chartier
154e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu ChartierCompiledMethod::~CompiledMethod() {
15535831e8bfa1c0944d4c978d99c4c5b9577945170Vladimir Marko  CompiledMethodStorage* storage = GetCompilerDriver()->GetCompiledMethodStorage();
15635831e8bfa1c0944d4c978d99c4c5b9577945170Vladimir Marko  storage->ReleaseLinkerPatches(patches_);
15735831e8bfa1c0944d4c978d99c4c5b9577945170Vladimir Marko  storage->ReleaseCFIInfo(cfi_info_);
15835831e8bfa1c0944d4c978d99c4c5b9577945170Vladimir Marko  storage->ReleaseVMapTable(vmap_table_);
159cbcedbf9382bc773713cd3552ed96f417bf1daebMathieu Chartier  storage->ReleaseMethodInfo(method_info_);
160e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier}
161e5f13e57ff8fa36342beb33830b3ec5942a61ccaMathieu Chartier
1623320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom}  // namespace art
163