1d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray/* 2d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * Copyright (C) 2014 The Android Open Source Project 3d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * 4d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * Licensed under the Apache License, Version 2.0 (the "License"); 5d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * you may not use this file except in compliance with the License. 6d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * You may obtain a copy of the License at 7d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * 8d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * http://www.apache.org/licenses/LICENSE-2.0 9d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * 10d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * Unless required by applicable law or agreed to in writing, software 11d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * distributed under the License is distributed on an "AS IS" BASIS, 12d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * See the License for the specific language governing permissions and 14d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray * limitations under the License. 15d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray */ 16d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 17d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray#ifndef ART_COMPILER_OPTIMIZING_CODE_GENERATOR_H_ 18d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray#define ART_COMPILER_OPTIMIZING_CODE_GENERATOR_H_ 19d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 20d582fa4ea62083a7598dded5b82dc2198b3daac7Ian Rogers#include "arch/instruction_set.h" 213416601a9e9be81bb7494864287fd3602d18ef13Calin Juravle#include "arch/instruction_set_features.h" 22f9f6441c665b5ff9004d3ed55014f46d416fb1bbVladimir Marko#include "base/arena_containers.h" 23f9f6441c665b5ff9004d3ed55014f46d416fb1bbVladimir Marko#include "base/arena_object.h" 2401bc96d007b67fdb7fe349232a83e4b354ce3d08Nicolas Geoffray#include "base/bit_field.h" 25d28b969c273ab777ca9b147b87fcef671b4f695fNicolas Geoffray#include "compiled_method.h" 26cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle#include "driver/compiler_options.h" 27bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray#include "globals.h" 28eb7b7399dbdb5e471b8ae00a567bf4f19edd3907Alexandre Rames#include "graph_visualizer.h" 294e3d23aa1523718ea1fdf3a32516d2f9d81e84feNicolas Geoffray#include "locations.h" 30d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray#include "memory_region.h" 31d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray#include "nodes.h" 32ecc4366670e12b4812ef1653f7c8d52234ca1b1fSerban Constantinescu#include "optimizing_compiler_stats.h" 333946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray#include "stack_map_stream.h" 3485b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe#include "utils/label.h" 35d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 36d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffraynamespace art { 37d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 386d0e483dd2e0b63e952de060738c10e2abd12ff7Roland Levillain// Binary encoding of 2^32 for type double. 396d0e483dd2e0b63e952de060738c10e2abd12ff7Roland Levillainstatic int64_t constexpr k2Pow32EncodingForDouble = INT64_C(0x41F0000000000000); 406d0e483dd2e0b63e952de060738c10e2abd12ff7Roland Levillain// Binary encoding of 2^31 for type double. 416d0e483dd2e0b63e952de060738c10e2abd12ff7Roland Levillainstatic int64_t constexpr k2Pow31EncodingForDouble = INT64_C(0x41E0000000000000); 426d0e483dd2e0b63e952de060738c10e2abd12ff7Roland Levillain 43e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell// Minimum value for a primitive integer. 44e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendellstatic int32_t constexpr kPrimIntMin = 0x80000000; 45e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell// Minimum value for a primitive long. 46e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendellstatic int64_t constexpr kPrimLongMin = INT64_C(0x8000000000000000); 47e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendell 483f8f936aff35f29d86183d31c20597ea17e9789dRoland Levillain// Maximum value for a primitive integer. 493f8f936aff35f29d86183d31c20597ea17e9789dRoland Levillainstatic int32_t constexpr kPrimIntMax = 0x7fffffff; 50624279f3c70f9904cbaf428078981b05d3b324c0Roland Levillain// Maximum value for a primitive long. 51e82549b14c7def0a45461183964f7e6a34cbb70cMark Mendellstatic int64_t constexpr kPrimLongMax = INT64_C(0x7fffffffffffffff); 523f8f936aff35f29d86183d31c20597ea17e9789dRoland Levillain 5392a73aef279be78e3c2b04db1713076183933436Nicolas Geoffrayclass Assembler; 54e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffrayclass CodeGenerator; 55d28b969c273ab777ca9b147b87fcef671b4f695fNicolas Geoffrayclass CompilerDriver; 56581550137ee3a068a14224870e71aeee924a0646Vladimir Markoclass LinkerPatch; 57f0e3937b87453234d0d7970b8712082062709b8dNicolas Geoffrayclass ParallelMoveResolver; 5892cf83e001357329cbf41fa15a6e053fab6f4933Nicolas Geoffray 59d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffrayclass CodeAllocator { 60d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray public: 61e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray CodeAllocator() {} 62e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray virtual ~CodeAllocator() {} 63d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 64d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray virtual uint8_t* Allocate(size_t size) = 0; 65d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 66d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray private: 67d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray DISALLOW_COPY_AND_ASSIGN(CodeAllocator); 68d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray}; 69d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 70c393d63aa2b8f6984672fdd4de631bbeff14b6a2Alexandre Ramesclass SlowPathCode : public DeletableArenaObject<kArenaAllocSlowPaths> { 71e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray public: 729cd6d378bd573cdc14d049d32bdd22a97fa4d84aDavid Srbecky explicit SlowPathCode(HInstruction* instruction) : instruction_(instruction) { 73eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray for (size_t i = 0; i < kMaximumNumberOfExpectedRegisters; ++i) { 74eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray saved_core_stack_offsets_[i] = kRegisterNotSaved; 75eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray saved_fpu_stack_offsets_[i] = kRegisterNotSaved; 76eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray } 77eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray } 78eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray 79e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray virtual ~SlowPathCode() {} 80e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray 81e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray virtual void EmitNativeCode(CodeGenerator* codegen) = 0; 82e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray 83da40309f61f98c16d7d58e4c34cc0f5eef626f93Zheng Xu virtual void SaveLiveRegisters(CodeGenerator* codegen, LocationSummary* locations); 84da40309f61f98c16d7d58e4c34cc0f5eef626f93Zheng Xu virtual void RestoreLiveRegisters(CodeGenerator* codegen, LocationSummary* locations); 85a8ac9130b872c080299afacf5dcaab513d13ea87Nicolas Geoffray 86eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray bool IsCoreRegisterSaved(int reg) const { 87eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray return saved_core_stack_offsets_[reg] != kRegisterNotSaved; 88eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray } 89eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray 90eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray bool IsFpuRegisterSaved(int reg) const { 91eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray return saved_fpu_stack_offsets_[reg] != kRegisterNotSaved; 92eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray } 93eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray 94eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray uint32_t GetStackOffsetOfCoreRegister(int reg) const { 95eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray return saved_core_stack_offsets_[reg]; 96eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray } 97eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray 98eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray uint32_t GetStackOffsetOfFpuRegister(int reg) const { 99eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray return saved_fpu_stack_offsets_[reg]; 100eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray } 101eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray 1028158f28b6689314213eb4dbbe14166073be71f7eAlexandre Rames virtual bool IsFatal() const { return false; } 1038158f28b6689314213eb4dbbe14166073be71f7eAlexandre Rames 1049931f319cf86c56c2855d800339a3410697633a6Alexandre Rames virtual const char* GetDescription() const = 0; 1059931f319cf86c56c2855d800339a3410697633a6Alexandre Rames 10685b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe Label* GetEntryLabel() { return &entry_label_; } 10785b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe Label* GetExitLabel() { return &exit_label_; } 10885b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe 109d28f4a00933a4a3b8d5e9db73b8532924d0f989dDavid Srbecky HInstruction* GetInstruction() const { 110d28f4a00933a4a3b8d5e9db73b8532924d0f989dDavid Srbecky return instruction_; 111d28f4a00933a4a3b8d5e9db73b8532924d0f989dDavid Srbecky } 112d28f4a00933a4a3b8d5e9db73b8532924d0f989dDavid Srbecky 1139cd6d378bd573cdc14d049d32bdd22a97fa4d84aDavid Srbecky uint32_t GetDexPc() const { 1149cd6d378bd573cdc14d049d32bdd22a97fa4d84aDavid Srbecky return instruction_ != nullptr ? instruction_->GetDexPc() : kNoDexPc; 1159cd6d378bd573cdc14d049d32bdd22a97fa4d84aDavid Srbecky } 1169cd6d378bd573cdc14d049d32bdd22a97fa4d84aDavid Srbecky 117da40309f61f98c16d7d58e4c34cc0f5eef626f93Zheng Xu protected: 118eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray static constexpr size_t kMaximumNumberOfExpectedRegisters = 32; 119eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray static constexpr uint32_t kRegisterNotSaved = -1; 1209cd6d378bd573cdc14d049d32bdd22a97fa4d84aDavid Srbecky // The instruction where this slow path is happening. 1219cd6d378bd573cdc14d049d32bdd22a97fa4d84aDavid Srbecky HInstruction* instruction_; 122eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray uint32_t saved_core_stack_offsets_[kMaximumNumberOfExpectedRegisters]; 123eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray uint32_t saved_fpu_stack_offsets_[kMaximumNumberOfExpectedRegisters]; 124da40309f61f98c16d7d58e4c34cc0f5eef626f93Zheng Xu 125da40309f61f98c16d7d58e4c34cc0f5eef626f93Zheng Xu private: 12685b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe Label entry_label_; 12785b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe Label exit_label_; 12885b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe 129e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray DISALLOW_COPY_AND_ASSIGN(SlowPathCode); 130e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray}; 131e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray 1322d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillainclass InvokeDexCallingConventionVisitor { 1332d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain public: 1342d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain virtual Location GetNextLocation(Primitive::Type type) = 0; 135fd88f16100cceafbfde1b4f095f17e89444d6fa8Nicolas Geoffray virtual Location GetReturnLocation(Primitive::Type type) const = 0; 136fd88f16100cceafbfde1b4f095f17e89444d6fa8Nicolas Geoffray virtual Location GetMethodLocation() const = 0; 1372d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain 1382d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain protected: 1392d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain InvokeDexCallingConventionVisitor() {} 1402d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain virtual ~InvokeDexCallingConventionVisitor() {} 1412d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain 1422d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain // The current index for core registers. 1432d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain uint32_t gp_index_ = 0u; 1442d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain // The current index for floating-point registers. 1452d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain uint32_t float_index_ = 0u; 1462d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain // The current stack index. 1472d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain uint32_t stack_index_ = 0u; 1482d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain 1492d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain private: 1502d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain DISALLOW_COPY_AND_ASSIGN(InvokeDexCallingConventionVisitor); 1512d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain}; 1522d27c8e338af7262dbd4aaa66127bb8fa1758b86Roland Levillain 153e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravleclass FieldAccessCallingConvention { 154e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle public: 155e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle virtual Location GetObjectLocation() const = 0; 156e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle virtual Location GetFieldIndexLocation() const = 0; 157e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle virtual Location GetReturnLocation(Primitive::Type type) const = 0; 158e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle virtual Location GetSetValueLocation(Primitive::Type type, bool is_instance) const = 0; 159e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle virtual Location GetFpuLocation(Primitive::Type type) const = 0; 160e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle virtual ~FieldAccessCallingConvention() {} 161e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle 162e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle protected: 163e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle FieldAccessCallingConvention() {} 164e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle 165e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle private: 166e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle DISALLOW_COPY_AND_ASSIGN(FieldAccessCallingConvention); 167e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle}; 168e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle 169d58b837ae41c6d8ce010c362e8f85bd938715900Vladimir Markoclass CodeGenerator : public DeletableArenaObject<kArenaAllocCodeGenerator> { 170d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray public: 17158282f4510961317b8d5a364a6f740a78926716fDavid Brazdil // Compiles the graph to executable instructions. 17258282f4510961317b8d5a364a6f740a78926716fDavid Brazdil void Compile(CodeAllocator* allocator); 173d58b837ae41c6d8ce010c362e8f85bd938715900Vladimir Marko static std::unique_ptr<CodeGenerator> Create(HGraph* graph, 174d58b837ae41c6d8ce010c362e8f85bd938715900Vladimir Marko InstructionSet instruction_set, 175d58b837ae41c6d8ce010c362e8f85bd938715900Vladimir Marko const InstructionSetFeatures& isa_features, 176d58b837ae41c6d8ce010c362e8f85bd938715900Vladimir Marko const CompilerOptions& compiler_options, 177d58b837ae41c6d8ce010c362e8f85bd938715900Vladimir Marko OptimizingCompilerStats* stats = nullptr); 17812df9ebf72255544b0147c81b1dca6644a29764eNicolas Geoffray virtual ~CodeGenerator() {} 179d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 180dc151b2346bb8a4fdeed0c06e54c2fca21d59b5dVladimir Marko // Get the graph. This is the outermost graph, never the graph of a method being inlined. 181787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray HGraph* GetGraph() const { return graph_; } 182d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 183dc23d8318db08cb42e20f1d16dbc416798951a8bNicolas Geoffray HBasicBlock* GetNextBlockToEmit() const; 184dc23d8318db08cb42e20f1d16dbc416798951a8bNicolas Geoffray HBasicBlock* FirstNonEmptyBlock(HBasicBlock* block) const; 185bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray bool GoesToNextBlock(HBasicBlock* current, HBasicBlock* next) const; 186bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray 18786dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray size_t GetStackSlotOfParameter(HParameterValue* parameter) const { 18886dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray // Note that this follows the current calling convention. 18986dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray return GetFrameSize() 190e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier + InstructionSetPointerSize(GetInstructionSet()) // Art method 191e27f31a81636ad74bd3376ee39cf215941b85c0eNicolas Geoffray + parameter->GetIndex() * kVRegSize; 19286dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray } 19386dbb9a12119273039ce272b41c809fa548b37b6Nicolas Geoffray 19492a73aef279be78e3c2b04db1713076183933436Nicolas Geoffray virtual void Initialize() = 0; 19532f5b4d2c8c9b52e9522941c159577b21752d0faSerban Constantinescu virtual void Finalize(CodeAllocator* allocator); 196581550137ee3a068a14224870e71aeee924a0646Vladimir Marko virtual void EmitLinkerPatches(ArenaVector<LinkerPatch>* linker_patches); 197d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray virtual void GenerateFrameEntry() = 0; 198d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray virtual void GenerateFrameExit() = 0; 19992a73aef279be78e3c2b04db1713076183933436Nicolas Geoffray virtual void Bind(HBasicBlock* block) = 0; 200175dc732c80e6f2afd83209348124df349290ba8Calin Juravle virtual void MoveConstant(Location destination, int32_t value) = 0; 201e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle virtual void MoveLocation(Location dst, Location src, Primitive::Type dst_type) = 0; 202e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle virtual void AddLocationAsTemp(Location location, LocationSummary* locations) = 0; 203e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle 204787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray virtual Assembler* GetAssembler() = 0; 205eb7b7399dbdb5e471b8ae00a567bf4f19edd3907Alexandre Rames virtual const Assembler& GetAssembler() const = 0; 206707c809f661554713edfacf338365adca8dfd3a3Nicolas Geoffray virtual size_t GetWordSize() const = 0; 207f85a9ca9859ad843dc03d3a2b600afbaf2e9bbddMark Mendell virtual size_t GetFloatingPointSpillSlotSize() const = 0; 208c393d63aa2b8f6984672fdd4de631bbeff14b6a2Alexandre Rames virtual uintptr_t GetAddressOf(HBasicBlock* block) = 0; 2094c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray void InitializeCodeGeneration(size_t number_of_spill_slots, 2104c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray size_t maximum_number_of_live_core_registers, 2110d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain size_t maximum_number_of_live_fpu_registers, 2124c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray size_t number_of_out_slots, 213fa6b93c4b69e6d7ddfa2a4ed0aff01b0608c5a3aVladimir Marko const ArenaVector<HBasicBlock*>& block_order); 214787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray 215787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray uint32_t GetFrameSize() const { return frame_size_; } 216787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray void SetFrameSize(uint32_t size) { frame_size_ = size; } 2178ccc3f5d06fd217cdaabd37e743adab2031d3720Nicolas Geoffray uint32_t GetCoreSpillMask() const { return core_spill_mask_; } 218d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray uint32_t GetFpuSpillMask() const { return fpu_spill_mask_; } 2198ccc3f5d06fd217cdaabd37e743adab2031d3720Nicolas Geoffray 22071175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray size_t GetNumberOfCoreRegisters() const { return number_of_core_registers_; } 22171175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray size_t GetNumberOfFloatingPointRegisters() const { return number_of_fpu_registers_; } 22258282f4510961317b8d5a364a6f740a78926716fDavid Brazdil virtual void SetupBlockedRegisters() const = 0; 22371175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray 2244dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray virtual void ComputeSpillMask() { 2254dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray core_spill_mask_ = allocated_registers_.GetCoreRegisters() & core_callee_save_mask_; 2264dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray DCHECK_NE(core_spill_mask_, 0u) << "At least the return address register must be saved"; 2274dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray fpu_spill_mask_ = allocated_registers_.GetFloatingPointRegisters() & fpu_callee_save_mask_; 2284dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray } 2294dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray 2304dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray static uint32_t ComputeRegisterMask(const int* registers, size_t length) { 2314dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray uint32_t mask = 0; 2324dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray for (size_t i = 0, e = length; i < e; ++i) { 2334dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray mask |= (1 << registers[i]); 2344dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray } 2354dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray return mask; 2364dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray } 2374dee636d21d9ce54386cdfbb824e5eb2a9c1af0dNicolas Geoffray 238a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray virtual void DumpCoreRegister(std::ostream& stream, int reg) const = 0; 239a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray virtual void DumpFloatingPointRegister(std::ostream& stream, int reg) const = 0; 240412f10cfed002ab617c78f2621d68446ca4dd8bdNicolas Geoffray virtual InstructionSet GetInstructionSet() const = 0; 241cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle 242cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle const CompilerOptions& GetCompilerOptions() const { return compiler_options_; } 243cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle 244ecc4366670e12b4812ef1653f7c8d52234ca1b1fSerban Constantinescu void MaybeRecordStat(MethodCompilationStat compilation_stat, size_t count = 1) const; 245ecc4366670e12b4812ef1653f7c8d52234ca1b1fSerban Constantinescu 246102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray // Saves the register in the stack. Returns the size taken on stack. 247102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray virtual size_t SaveCoreRegister(size_t stack_index, uint32_t reg_id) = 0; 248102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray // Restores the register from the stack. Returns the size taken on stack. 249102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray virtual size_t RestoreCoreRegister(size_t stack_index, uint32_t reg_id) = 0; 250234d69d075d1608f80adb647f7935077b62b6376Nicolas Geoffray 251234d69d075d1608f80adb647f7935077b62b6376Nicolas Geoffray virtual size_t SaveFloatingPointRegister(size_t stack_index, uint32_t reg_id) = 0; 252234d69d075d1608f80adb647f7935077b62b6376Nicolas Geoffray virtual size_t RestoreFloatingPointRegister(size_t stack_index, uint32_t reg_id) = 0; 253234d69d075d1608f80adb647f7935077b62b6376Nicolas Geoffray 254840e5461a85f8908f51e7f6cd562a9129ff0e7ceNicolas Geoffray virtual bool NeedsTwoRegisters(Primitive::Type type) const = 0; 255234d69d075d1608f80adb647f7935077b62b6376Nicolas Geoffray // Returns whether we should split long moves in parallel moves. 256234d69d075d1608f80adb647f7935077b62b6376Nicolas Geoffray virtual bool ShouldSplitLongMoves() const { return false; } 257a7062e05e6048c7f817d784a5b94e3122e25b1ecNicolas Geoffray 2580d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain size_t GetNumberOfCoreCalleeSaveRegisters() const { 2590d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain return POPCOUNT(core_callee_save_mask_); 2600d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain } 2610d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain 2620d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain size_t GetNumberOfCoreCallerSaveRegisters() const { 2630d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain DCHECK_GE(GetNumberOfCoreRegisters(), GetNumberOfCoreCalleeSaveRegisters()); 2640d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain return GetNumberOfCoreRegisters() - GetNumberOfCoreCalleeSaveRegisters(); 2650d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain } 2660d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain 267988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray bool IsCoreCalleeSaveRegister(int reg) const { 268988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray return (core_callee_save_mask_ & (1 << reg)) != 0; 269988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray } 270988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray 271988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray bool IsFloatingPointCalleeSaveRegister(int reg) const { 272988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray return (fpu_callee_save_mask_ & (1 << reg)) != 0; 273988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray } 274988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray 2752a7c1ef95c850abae915b3a59fbafa87e6833967Yevgeny Rouban // Record native to dex mapping for a suspend point. Required by runtime. 276eeefa1276e83776f08704a3db4237423b0627e20Nicolas Geoffray void RecordPcInfo(HInstruction* instruction, uint32_t dex_pc, SlowPathCode* slow_path = nullptr); 277b7070a2db8b0b7eca14f01f932be305be64ded57David Srbecky // Check whether we have already recorded mapping at this PC. 278b7070a2db8b0b7eca14f01f932be305be64ded57David Srbecky bool HasStackMapAtCurrentPc(); 279c7098ff991bb4e00a800d315d1c36f52a9cb0149David Srbecky // Record extra stack maps if we support native debugging. 280d28f4a00933a4a3b8d5e9db73b8532924d0f989dDavid Srbecky void MaybeRecordNativeDebugInfo(HInstruction* instruction, 281d28f4a00933a4a3b8d5e9db73b8532924d0f989dDavid Srbecky uint32_t dex_pc, 282d28f4a00933a4a3b8d5e9db73b8532924d0f989dDavid Srbecky SlowPathCode* slow_path = nullptr); 2832a7c1ef95c850abae915b3a59fbafa87e6833967Yevgeny Rouban 28477520bca97ec44e3758510cebd0f20e3bb4584eaCalin Juravle bool CanMoveNullCheckToUser(HNullCheck* null_check); 28577520bca97ec44e3758510cebd0f20e3bb4584eaCalin Juravle void MaybeRecordImplicitNullCheck(HInstruction* instruction); 2862ae48182573da7087bffc2873730bc758ec29696Calin Juravle void GenerateNullCheck(HNullCheck* null_check); 2872ae48182573da7087bffc2873730bc758ec29696Calin Juravle virtual void GenerateImplicitNullCheck(HNullCheck* null_check) = 0; 2882ae48182573da7087bffc2873730bc758ec29696Calin Juravle virtual void GenerateExplicitNullCheck(HNullCheck* null_check) = 0; 289787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray 29077a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil // Records a stack map which the runtime might use to set catch phi values 29177a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil // during exception delivery. 29277a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil // TODO: Replace with a catch-entering instruction that records the environment. 29377a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil void RecordCatchBlockInfo(); 29477a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil 29577a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil // Returns true if implicit null checks are allowed in the compiler options 29677a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil // and if the null check is not inside a try block. We currently cannot do 29777a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil // implicit null checks in that case because we need the NullCheckSlowPath to 29877a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil // save live registers, which may be needed by the runtime to set catch phis. 29977a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil bool IsImplicitNullCheckAllowed(HNullCheck* null_check) const; 30077a48ae01bbc5b05ca009cf09e2fcb53e4c8ff23David Brazdil 301c393d63aa2b8f6984672fdd4de631bbeff14b6a2Alexandre Rames // TODO: Avoid creating the `std::unique_ptr` here. 302e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray void AddSlowPath(SlowPathCode* slow_path) { 303c393d63aa2b8f6984672fdd4de631bbeff14b6a2Alexandre Rames slow_paths_.push_back(std::unique_ptr<SlowPathCode>(slow_path)); 304e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray } 305e50383288a75244255d3ecedcc79ffe9caf774cbNicolas Geoffray 306b331febbab8e916680faba722cc84b66b84218a3Nicolas Geoffray void BuildStackMaps(MemoryRegion region, const DexFile::CodeItem& code_item); 307d28b969c273ab777ca9b147b87fcef671b4f695fNicolas Geoffray size_t ComputeStackMapsSize(); 308787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray 309f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray bool IsLeafMethod() const { 310f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray return is_leaf_; 311f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray } 312f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray 313f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray void MarkNotLeaf() { 314f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray is_leaf_ = false; 315c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray requires_current_method_ = true; 316c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray } 317c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray 318c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray void SetRequiresCurrentMethod() { 319c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray requires_current_method_ = true; 320c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray } 321c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray 322c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray bool RequiresCurrentMethod() const { 323c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray return requires_current_method_; 324f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray } 325f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray 3263c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray // Clears the spill slots taken by loop phis in the `LocationSummary` of the 3273c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray // suspend check. This is called when the code generator generates code 3283c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray // for the suspend check at the back edge (instead of where the suspend check 3293c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray // is, which is the loop entry). At this point, the spill slots for the phis 3303c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray // have not been written to. 3313c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray void ClearSpillSlotsFromLoopPhisInStackMap(HSuspendCheck* suspend_check) const; 3323c04974a90b0e03f4b509010bff49f0b2a3da57fNicolas Geoffray 33371175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray bool* GetBlockedCoreRegisters() const { return blocked_core_registers_; } 334102cbed1e52b7c5f09458b44903fe97bb3e14d5fNicolas Geoffray bool* GetBlockedFloatingPointRegisters() const { return blocked_fpu_registers_; } 33571175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray 33619a19cffd197a28ae4c9c3e59eff6352fd392241Nicolas Geoffray // Helper that returns the pointer offset of an index in an object array. 33719a19cffd197a28ae4c9c3e59eff6352fd392241Nicolas Geoffray // Note: this method assumes we always have the same pointer size, regardless 33819a19cffd197a28ae4c9c3e59eff6352fd392241Nicolas Geoffray // of the architecture. 33919a19cffd197a28ae4c9c3e59eff6352fd392241Nicolas Geoffray static size_t GetCacheOffset(uint32_t index); 340e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier // Pointer variant for ArtMethod and ArtField arrays. 341e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier size_t GetCachePointerOffset(uint32_t index); 34219a19cffd197a28ae4c9c3e59eff6352fd392241Nicolas Geoffray 3439021825d1e73998b99c81e89c73796f6f2845471Nicolas Geoffray void EmitParallelMoves(Location from1, 3449021825d1e73998b99c81e89c73796f6f2845471Nicolas Geoffray Location to1, 3459021825d1e73998b99c81e89c73796f6f2845471Nicolas Geoffray Primitive::Type type1, 3469021825d1e73998b99c81e89c73796f6f2845471Nicolas Geoffray Location from2, 3479021825d1e73998b99c81e89c73796f6f2845471Nicolas Geoffray Location to2, 3489021825d1e73998b99c81e89c73796f6f2845471Nicolas Geoffray Primitive::Type type2); 349f0e3937b87453234d0d7970b8712082062709b8dNicolas Geoffray 350af07bc121121d7bd7e8329c55dfe24782207b561Nicolas Geoffray static bool StoreNeedsWriteBarrier(Primitive::Type type, HInstruction* value) { 351522e2241f5b5f331d0aa2f8508f4c97973f7f012David Brazdil // Check that null value is not represented as an integer constant. 352522e2241f5b5f331d0aa2f8508f4c97973f7f012David Brazdil DCHECK(type != Primitive::kPrimNot || !value->IsIntConstant()); 353522e2241f5b5f331d0aa2f8508f4c97973f7f012David Brazdil return type == Primitive::kPrimNot && !value->IsNullConstant(); 354af07bc121121d7bd7e8329c55dfe24782207b561Nicolas Geoffray } 355af07bc121121d7bd7e8329c55dfe24782207b561Nicolas Geoffray 35678e3ef6bc5f8aa149f2f8bf0c78ce854c2f910faAlexandre Rames void ValidateInvokeRuntime(HInstruction* instruction, SlowPathCode* slow_path); 35778e3ef6bc5f8aa149f2f8bf0c78ce854c2f910faAlexandre Rames 358988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray void AddAllocatedRegister(Location location) { 359988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray allocated_registers_.Add(location); 360988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray } 361988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray 36245b83aff85a8a8dfcae0da90d010fa2d7eb299a7Nicolas Geoffray bool HasAllocatedRegister(bool is_core, int reg) const { 36345b83aff85a8a8dfcae0da90d010fa2d7eb299a7Nicolas Geoffray return is_core 36445b83aff85a8a8dfcae0da90d010fa2d7eb299a7Nicolas Geoffray ? allocated_registers_.ContainsCoreRegister(reg) 36545b83aff85a8a8dfcae0da90d010fa2d7eb299a7Nicolas Geoffray : allocated_registers_.ContainsFloatingPointRegister(reg); 36645b83aff85a8a8dfcae0da90d010fa2d7eb299a7Nicolas Geoffray } 36745b83aff85a8a8dfcae0da90d010fa2d7eb299a7Nicolas Geoffray 368c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray void AllocateLocations(HInstruction* instruction); 369c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray 370aa9b7c48069699e2aabedc6c0f62cb131fee0c73Roland Levillain // Tells whether the stack frame of the compiled method is 371aa9b7c48069699e2aabedc6c0f62cb131fee0c73Roland Levillain // considered "empty", that is either actually having a size of zero, 372aa9b7c48069699e2aabedc6c0f62cb131fee0c73Roland Levillain // or just containing the saved return address register. 373aa9b7c48069699e2aabedc6c0f62cb131fee0c73Roland Levillain bool HasEmptyFrame() const { 374aa9b7c48069699e2aabedc6c0f62cb131fee0c73Roland Levillain return GetFrameSize() == (CallPushesPC() ? GetWordSize() : 0); 375aa9b7c48069699e2aabedc6c0f62cb131fee0c73Roland Levillain } 376aa9b7c48069699e2aabedc6c0f62cb131fee0c73Roland Levillain 377d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray static int32_t GetInt32ValueOf(HConstant* constant) { 378d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray if (constant->IsIntConstant()) { 379d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray return constant->AsIntConstant()->GetValue(); 380d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray } else if (constant->IsNullConstant()) { 381d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray return 0; 382d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray } else { 383d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray DCHECK(constant->IsFloatConstant()); 384da4d79bc9a4aeb9da7c6259ce4c9c1c3bf545eb8Roland Levillain return bit_cast<int32_t, float>(constant->AsFloatConstant()->GetValue()); 385d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray } 386d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray } 387d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray 388d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray static int64_t GetInt64ValueOf(HConstant* constant) { 389d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray if (constant->IsIntConstant()) { 390d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray return constant->AsIntConstant()->GetValue(); 391d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray } else if (constant->IsNullConstant()) { 392d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray return 0; 393d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray } else if (constant->IsFloatConstant()) { 394da4d79bc9a4aeb9da7c6259ce4c9c1c3bf545eb8Roland Levillain return bit_cast<int32_t, float>(constant->AsFloatConstant()->GetValue()); 395d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray } else if (constant->IsLongConstant()) { 396d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray return constant->AsLongConstant()->GetValue(); 397d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray } else { 398d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray DCHECK(constant->IsDoubleConstant()); 399da4d79bc9a4aeb9da7c6259ce4c9c1c3bf545eb8Roland Levillain return bit_cast<int64_t, double>(constant->AsDoubleConstant()->GetValue()); 400d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray } 401d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray } 402d6138ef1ea13d07ae555542f8898b30d89e9ac9aNicolas Geoffray 403a8ac9130b872c080299afacf5dcaab513d13ea87Nicolas Geoffray size_t GetFirstRegisterSlotInSlowPath() const { 404a8ac9130b872c080299afacf5dcaab513d13ea87Nicolas Geoffray return first_register_slot_in_slow_path_; 405a8ac9130b872c080299afacf5dcaab513d13ea87Nicolas Geoffray } 406a8ac9130b872c080299afacf5dcaab513d13ea87Nicolas Geoffray 407a8ac9130b872c080299afacf5dcaab513d13ea87Nicolas Geoffray uint32_t FrameEntrySpillSize() const { 408a8ac9130b872c080299afacf5dcaab513d13ea87Nicolas Geoffray return GetFpuSpillSize() + GetCoreSpillSize(); 409a8ac9130b872c080299afacf5dcaab513d13ea87Nicolas Geoffray } 410a8ac9130b872c080299afacf5dcaab513d13ea87Nicolas Geoffray 411ec525fc30848189051b888da53ba051bc0878b78Roland Levillain virtual ParallelMoveResolver* GetMoveResolver() = 0; 412a8ac9130b872c080299afacf5dcaab513d13ea87Nicolas Geoffray 413fd88f16100cceafbfde1b4f095f17e89444d6fa8Nicolas Geoffray static void CreateCommonInvokeLocationSummary( 414fd88f16100cceafbfde1b4f095f17e89444d6fa8Nicolas Geoffray HInvoke* invoke, InvokeDexCallingConventionVisitor* visitor); 415fd88f16100cceafbfde1b4f095f17e89444d6fa8Nicolas Geoffray 416175dc732c80e6f2afd83209348124df349290ba8Calin Juravle void GenerateInvokeUnresolvedRuntimeCall(HInvokeUnresolved* invoke); 417175dc732c80e6f2afd83209348124df349290ba8Calin Juravle 418e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle void CreateUnresolvedFieldLocationSummary( 419e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle HInstruction* field_access, 420e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle Primitive::Type field_type, 421e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle const FieldAccessCallingConvention& calling_convention); 422e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle 423e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle void GenerateUnresolvedFieldAccess( 424e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle HInstruction* field_access, 425e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle Primitive::Type field_type, 426e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle uint32_t field_index, 427e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle uint32_t dex_pc, 428e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle const FieldAccessCallingConvention& calling_convention); 429e460d1df1f789c7c8bb97024a8efbd713ac175e9Calin Juravle 43098893e146b0ff0e1fd1d7c29252f1d1e75a163f2Calin Juravle // TODO: This overlaps a bit with MoveFromReturnRegister. Refactor for a better design. 43198893e146b0ff0e1fd1d7c29252f1d1e75a163f2Calin Juravle static void CreateLoadClassLocationSummary(HLoadClass* cls, 43298893e146b0ff0e1fd1d7c29252f1d1e75a163f2Calin Juravle Location runtime_type_index_location, 4330d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain Location runtime_return_location, 4340d5a281c671444bfa75d63caf1427a8c0e6e1177Roland Levillain bool code_generator_supports_read_barrier = false); 43598893e146b0ff0e1fd1d7c29252f1d1e75a163f2Calin Juravle 4365bd05a5c9492189ec28edaf6396d6a39ddf03367Nicolas Geoffray static void CreateSystemArrayCopyLocationSummary(HInvoke* invoke); 4375bd05a5c9492189ec28edaf6396d6a39ddf03367Nicolas Geoffray 438eb7b7399dbdb5e471b8ae00a567bf4f19edd3907Alexandre Rames void SetDisassemblyInformation(DisassemblyInformation* info) { disasm_info_ = info; } 439eb7b7399dbdb5e471b8ae00a567bf4f19edd3907Alexandre Rames DisassemblyInformation* GetDisassemblyInformation() const { return disasm_info_; } 440eb7b7399dbdb5e471b8ae00a567bf4f19edd3907Alexandre Rames 441175dc732c80e6f2afd83209348124df349290ba8Calin Juravle virtual void InvokeRuntime(QuickEntrypointEnum entrypoint, 442175dc732c80e6f2afd83209348124df349290ba8Calin Juravle HInstruction* instruction, 443175dc732c80e6f2afd83209348124df349290ba8Calin Juravle uint32_t dex_pc, 444175dc732c80e6f2afd83209348124df349290ba8Calin Juravle SlowPathCode* slow_path) = 0; 445175dc732c80e6f2afd83209348124df349290ba8Calin Juravle 446cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko // Check if the desired_string_load_kind is supported. If it is, return it, 447cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko // otherwise return a fall-back info that should be used instead. 448cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko virtual HLoadString::LoadKind GetSupportedLoadStringKind( 449cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko HLoadString::LoadKind desired_string_load_kind) = 0; 450cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko 451dc151b2346bb8a4fdeed0c06e54c2fca21d59b5dVladimir Marko // Check if the desired_dispatch_info is supported. If it is, return it, 452dc151b2346bb8a4fdeed0c06e54c2fca21d59b5dVladimir Marko // otherwise return a fall-back info that should be used instead. 453dc151b2346bb8a4fdeed0c06e54c2fca21d59b5dVladimir Marko virtual HInvokeStaticOrDirect::DispatchInfo GetSupportedInvokeStaticOrDirectDispatch( 454dc151b2346bb8a4fdeed0c06e54c2fca21d59b5dVladimir Marko const HInvokeStaticOrDirect::DispatchInfo& desired_dispatch_info, 455dc151b2346bb8a4fdeed0c06e54c2fca21d59b5dVladimir Marko MethodReference target_method) = 0; 456dc151b2346bb8a4fdeed0c06e54c2fca21d59b5dVladimir Marko 45785b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe // Generate a call to a static or direct method. 45885b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe virtual void GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, Location temp) = 0; 45985b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe // Generate a call to a virtual method. 46085b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe virtual void GenerateVirtualCall(HInvokeVirtual* invoke, Location temp) = 0; 46185b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe 46285b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe // Copy the result of a call into the given target. 46385b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe virtual void MoveFromReturnRegister(Location trg, Primitive::Type type) = 0; 46485b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe 465c7098ff991bb4e00a800d315d1c36f52a9cb0149David Srbecky virtual void GenerateNop() = 0; 466c7098ff991bb4e00a800d315d1c36f52a9cb0149David Srbecky 467787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray protected: 468581550137ee3a068a14224870e71aeee924a0646Vladimir Marko // Method patch info used for recording locations of required linker patches and 469581550137ee3a068a14224870e71aeee924a0646Vladimir Marko // target methods. The target method can be used for various purposes, whether for 470581550137ee3a068a14224870e71aeee924a0646Vladimir Marko // patching the address of the method or the code pointer or a PC-relative call. 471581550137ee3a068a14224870e71aeee924a0646Vladimir Marko template <typename LabelType> 472581550137ee3a068a14224870e71aeee924a0646Vladimir Marko struct MethodPatchInfo { 473581550137ee3a068a14224870e71aeee924a0646Vladimir Marko explicit MethodPatchInfo(MethodReference m) : target_method(m), label() { } 474581550137ee3a068a14224870e71aeee924a0646Vladimir Marko 475581550137ee3a068a14224870e71aeee924a0646Vladimir Marko MethodReference target_method; 476581550137ee3a068a14224870e71aeee924a0646Vladimir Marko LabelType label; 477581550137ee3a068a14224870e71aeee924a0646Vladimir Marko }; 478581550137ee3a068a14224870e71aeee924a0646Vladimir Marko 479cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko // String patch info used for recording locations of required linker patches and 480cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko // target strings. The actual string address can be absolute or PC-relative. 481cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko template <typename LabelType> 482cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko struct StringPatchInfo { 483cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko StringPatchInfo(const DexFile& df, uint32_t index) 484cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko : dex_file(df), string_index(index), label() { } 485cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko 486cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko const DexFile& dex_file; 487cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko uint32_t string_index; 488cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko LabelType label; 489cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko }; 490cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko 49171175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray CodeGenerator(HGraph* graph, 49271175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray size_t number_of_core_registers, 49371175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray size_t number_of_fpu_registers, 494cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle size_t number_of_register_pairs, 495988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray uint32_t core_callee_save_mask, 496988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray uint32_t fpu_callee_save_mask, 497ecc4366670e12b4812ef1653f7c8d52234ca1b1fSerban Constantinescu const CompilerOptions& compiler_options, 498ecc4366670e12b4812ef1653f7c8d52234ca1b1fSerban Constantinescu OptimizingCompilerStats* stats) 499c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray : frame_size_(0), 5004361beff5bc540c43ab7c072c99994adc4ed78f9Nicolas Geoffray core_spill_mask_(0), 501d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray fpu_spill_mask_(0), 5023bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray first_register_slot_in_slow_path_(0), 5035233f93ee336b3581ccdb993ff6342c52fec34b0Vladimir Marko blocked_core_registers_(graph->GetArena()->AllocArray<bool>(number_of_core_registers, 5045233f93ee336b3581ccdb993ff6342c52fec34b0Vladimir Marko kArenaAllocCodeGenerator)), 5055233f93ee336b3581ccdb993ff6342c52fec34b0Vladimir Marko blocked_fpu_registers_(graph->GetArena()->AllocArray<bool>(number_of_fpu_registers, 5065233f93ee336b3581ccdb993ff6342c52fec34b0Vladimir Marko kArenaAllocCodeGenerator)), 5075233f93ee336b3581ccdb993ff6342c52fec34b0Vladimir Marko blocked_register_pairs_(graph->GetArena()->AllocArray<bool>(number_of_register_pairs, 5085233f93ee336b3581ccdb993ff6342c52fec34b0Vladimir Marko kArenaAllocCodeGenerator)), 50971175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray number_of_core_registers_(number_of_core_registers), 51071175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray number_of_fpu_registers_(number_of_fpu_registers), 51171175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray number_of_register_pairs_(number_of_register_pairs), 512988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray core_callee_save_mask_(core_callee_save_mask), 513988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray fpu_callee_save_mask_(fpu_callee_save_mask), 514cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko stack_map_stream_(graph->GetArena()), 515cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko block_order_(nullptr), 516eb7b7399dbdb5e471b8ae00a567bf4f19edd3907Alexandre Rames disasm_info_(nullptr), 517ecc4366670e12b4812ef1653f7c8d52234ca1b1fSerban Constantinescu stats_(stats), 518787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray graph_(graph), 519cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle compiler_options_(compiler_options), 520225b6464a58ebe11c156144653f11a1c6607f4ebVladimir Marko slow_paths_(graph->GetArena()->Adapter(kArenaAllocCodeGenerator)), 5210f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko current_slow_path_(nullptr), 5224c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray current_block_index_(0), 5233946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray is_leaf_(true), 524225b6464a58ebe11c156144653f11a1c6607f4ebVladimir Marko requires_current_method_(false) { 525225b6464a58ebe11c156144653f11a1c6607f4ebVladimir Marko slow_paths_.reserve(8); 526225b6464a58ebe11c156144653f11a1c6607f4ebVladimir Marko } 527d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 528c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray virtual HGraphVisitor* GetLocationBuilder() = 0; 529c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray virtual HGraphVisitor* GetInstructionVisitor() = 0; 530f0e3937b87453234d0d7970b8712082062709b8dNicolas Geoffray 531d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray // Returns the location of the first spilled entry for floating point registers, 532d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray // relative to the stack pointer. 533d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray uint32_t GetFpuSpillStart() const { 534d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray return GetFrameSize() - FrameEntrySpillSize(); 535d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray } 536d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray 537d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray uint32_t GetFpuSpillSize() const { 538d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray return POPCOUNT(fpu_spill_mask_) * GetFloatingPointSpillSlotSize(); 539d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray } 540d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray 541d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray uint32_t GetCoreSpillSize() const { 542d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray return POPCOUNT(core_spill_mask_) * GetWordSize(); 543d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray } 544d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray 545c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray bool HasAllocatedCalleeSaveRegisters() const { 546c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray // We check the core registers against 1 because it always comprises the return PC. 547c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray return (POPCOUNT(allocated_registers_.GetCoreRegisters() & core_callee_save_mask_) != 1) 548c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray || (POPCOUNT(allocated_registers_.GetFloatingPointRegisters() & fpu_callee_save_mask_) != 0); 549c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray } 550c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray 551c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray bool CallPushesPC() const { 552c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray InstructionSet instruction_set = GetInstructionSet(); 553c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray return instruction_set == kX86 || instruction_set == kX86_64; 554c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray } 555c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray 556225b6464a58ebe11c156144653f11a1c6607f4ebVladimir Marko // Arm64 has its own type for a label, so we need to templatize these methods 557dc23d8318db08cb42e20f1d16dbc416798951a8bNicolas Geoffray // to share the logic. 558225b6464a58ebe11c156144653f11a1c6607f4ebVladimir Marko 559225b6464a58ebe11c156144653f11a1c6607f4ebVladimir Marko template <typename LabelType> 560225b6464a58ebe11c156144653f11a1c6607f4ebVladimir Marko LabelType* CommonInitializeLabels() { 561b95fb775cc4c08349d0d905adbc96ad85e50601dVladimir Marko // We use raw array allocations instead of ArenaVector<> because Labels are 562b95fb775cc4c08349d0d905adbc96ad85e50601dVladimir Marko // non-constructible and non-movable and as such cannot be held in a vector. 563225b6464a58ebe11c156144653f11a1c6607f4ebVladimir Marko size_t size = GetGraph()->GetBlocks().size(); 564225b6464a58ebe11c156144653f11a1c6607f4ebVladimir Marko LabelType* labels = GetGraph()->GetArena()->AllocArray<LabelType>(size, 565225b6464a58ebe11c156144653f11a1c6607f4ebVladimir Marko kArenaAllocCodeGenerator); 566225b6464a58ebe11c156144653f11a1c6607f4ebVladimir Marko for (size_t i = 0; i != size; ++i) { 567225b6464a58ebe11c156144653f11a1c6607f4ebVladimir Marko new(labels + i) LabelType(); 568225b6464a58ebe11c156144653f11a1c6607f4ebVladimir Marko } 569225b6464a58ebe11c156144653f11a1c6607f4ebVladimir Marko return labels; 570225b6464a58ebe11c156144653f11a1c6607f4ebVladimir Marko } 571225b6464a58ebe11c156144653f11a1c6607f4ebVladimir Marko 572581550137ee3a068a14224870e71aeee924a0646Vladimir Marko template <typename LabelType> 573581550137ee3a068a14224870e71aeee924a0646Vladimir Marko LabelType* CommonGetLabelOf(LabelType* raw_pointer_to_labels_array, HBasicBlock* block) const { 574dc23d8318db08cb42e20f1d16dbc416798951a8bNicolas Geoffray block = FirstNonEmptyBlock(block); 575dc23d8318db08cb42e20f1d16dbc416798951a8bNicolas Geoffray return raw_pointer_to_labels_array + block->GetBlockId(); 576dc23d8318db08cb42e20f1d16dbc416798951a8bNicolas Geoffray } 577dc23d8318db08cb42e20f1d16dbc416798951a8bNicolas Geoffray 5780f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko SlowPathCode* GetCurrentSlowPath() { 5790f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko return current_slow_path_; 5800f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko } 5810f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko 5828ccc3f5d06fd217cdaabd37e743adab2031d3720Nicolas Geoffray // Frame size required for this method. 5838ccc3f5d06fd217cdaabd37e743adab2031d3720Nicolas Geoffray uint32_t frame_size_; 5848ccc3f5d06fd217cdaabd37e743adab2031d3720Nicolas Geoffray uint32_t core_spill_mask_; 585d97dc40d186aec46bfd318b6a2026a98241d7e9cNicolas Geoffray uint32_t fpu_spill_mask_; 5863bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray uint32_t first_register_slot_in_slow_path_; 5878ccc3f5d06fd217cdaabd37e743adab2031d3720Nicolas Geoffray 588988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray // Registers that were allocated during linear scan. 589988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray RegisterSet allocated_registers_; 590988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray 59171175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray // Arrays used when doing register allocation to know which 59271175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray // registers we can allocate. `SetupBlockedRegisters` updates the 59371175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray // arrays. 59471175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray bool* const blocked_core_registers_; 59571175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray bool* const blocked_fpu_registers_; 59671175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray bool* const blocked_register_pairs_; 59771175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray size_t number_of_core_registers_; 59871175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray size_t number_of_fpu_registers_; 59971175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray size_t number_of_register_pairs_; 600988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray const uint32_t core_callee_save_mask_; 601988939683c26c0b1c8808fc206add6337319509aNicolas Geoffray const uint32_t fpu_callee_save_mask_; 60271175b7f19a4f6cf9cc264feafd820dbafa371fbNicolas Geoffray 603cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko StackMapStream stack_map_stream_; 604cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 605cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko // The order to use for code generation. 606fa6b93c4b69e6d7ddfa2a4ed0aff01b0608c5a3aVladimir Marko const ArenaVector<HBasicBlock*>* block_order_; 607cf93a5cd9c978f59113d42f9f642fab5e2cc8877Vladimir Marko 608eb7b7399dbdb5e471b8ae00a567bf4f19edd3907Alexandre Rames DisassemblyInformation* disasm_info_; 609eb7b7399dbdb5e471b8ae00a567bf4f19edd3907Alexandre Rames 610bab4ed7057799a4fadc6283108ab56f389d117d4Nicolas Geoffray private: 6113bca0df855f0e575c6ee020ed016999fc8f14122Nicolas Geoffray size_t GetStackOffsetOfSavedRegister(size_t index); 612eb7b7399dbdb5e471b8ae00a567bf4f19edd3907Alexandre Rames void GenerateSlowPaths(); 6135f8741860d465410bfed495dbb5f794590d338daMark Mendell void BlockIfInRegister(Location location, bool is_out = false) const; 614b1d0f3f7e92fdcc92fe2d4c48cbb1262c005583fNicolas Geoffray void EmitEnvironment(HEnvironment* environment, SlowPathCode* slow_path); 615d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 616ecc4366670e12b4812ef1653f7c8d52234ca1b1fSerban Constantinescu OptimizingCompilerStats* stats_; 617ecc4366670e12b4812ef1653f7c8d52234ca1b1fSerban Constantinescu 618787c3076635cf117eb646c5a89a9014b2072fb44Nicolas Geoffray HGraph* const graph_; 619cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle const CompilerOptions& compiler_options_; 620d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 621c393d63aa2b8f6984672fdd4de631bbeff14b6a2Alexandre Rames ArenaVector<std::unique_ptr<SlowPathCode>> slow_paths_; 622d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 62342249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik // The current slow-path that we're generating code for. 6240f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko SlowPathCode* current_slow_path_; 6250f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko 6264c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray // The current block index in `block_order_` of the block 6274c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray // we are generating code for. 6284c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray size_t current_block_index_; 6294c204bafbc8d596894f8cb8ec696f5be1c6f12d8Nicolas Geoffray 630c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray // Whether the method is a leaf method. 631f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray bool is_leaf_; 632f12feb8e0e857f2832545b3f28d31bad5a9d3903Nicolas Geoffray 633c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray // Whether an instruction in the graph accesses the current method. 634c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray bool requires_current_method_; 635c0572a451944f78397619dec34a38c36c11e9d2aNicolas Geoffray 636c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky friend class OptimizingCFITest; 637c6b4dd8980350aaf250f0185f73e9c42ec17cd57David Srbecky 638d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray DISALLOW_COPY_AND_ASSIGN(CodeGenerator); 639d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray}; 640d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 6417fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffraytemplate <typename C, typename F> 6424a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffrayclass CallingConvention { 6434a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray public: 6447fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray CallingConvention(const C* registers, 6457fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray size_t number_of_registers, 6467fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray const F* fpu_registers, 647e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier size_t number_of_fpu_registers, 648e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier size_t pointer_size) 6497fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray : registers_(registers), 6507fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray number_of_registers_(number_of_registers), 6517fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray fpu_registers_(fpu_registers), 652e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier number_of_fpu_registers_(number_of_fpu_registers), 653e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier pointer_size_(pointer_size) {} 6544a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray 6554a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray size_t GetNumberOfRegisters() const { return number_of_registers_; } 6567fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray size_t GetNumberOfFpuRegisters() const { return number_of_fpu_registers_; } 6574a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray 6587fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray C GetRegisterAt(size_t index) const { 6594a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray DCHECK_LT(index, number_of_registers_); 6604a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray return registers_[index]; 6614a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray } 6624a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray 6637fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray F GetFpuRegisterAt(size_t index) const { 6647fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray DCHECK_LT(index, number_of_fpu_registers_); 6657fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray return fpu_registers_[index]; 6667fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray } 6677fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray 6687fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray size_t GetStackOffsetOf(size_t index) const { 6694a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray // We still reserve the space for parameters passed by registers. 670e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier // Add space for the method pointer. 671e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier return pointer_size_ + index * kVRegSize; 6724a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray } 6734a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray 6744a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray private: 6757fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray const C* registers_; 6764a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray const size_t number_of_registers_; 6777fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray const F* fpu_registers_; 6787fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray const size_t number_of_fpu_registers_; 679e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier const size_t pointer_size_; 6804a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray 6814a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray DISALLOW_COPY_AND_ASSIGN(CallingConvention); 6824a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray}; 6834a34a428c6a2588e0857ef6baf88f1b73ce65958Nicolas Geoffray 68442249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik/** 68542249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik * A templated class SlowPathGenerator with a templated method NewSlowPath() 68642249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik * that can be used by any code generator to share equivalent slow-paths with 68742249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik * the objective of reducing generated code size. 68842249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik * 68942249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik * InstructionType: instruction that requires SlowPathCodeType 69042249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik * SlowPathCodeType: subclass of SlowPathCode, with constructor SlowPathCodeType(InstructionType *) 69142249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik */ 69242249c3602c3d0243396ee3627ffb5906aa77c1eAart Biktemplate <typename InstructionType> 69342249c3602c3d0243396ee3627ffb5906aa77c1eAart Bikclass SlowPathGenerator { 69442249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik static_assert(std::is_base_of<HInstruction, InstructionType>::value, 69542249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik "InstructionType is not a subclass of art::HInstruction"); 69642249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik 69742249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik public: 69842249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik SlowPathGenerator(HGraph* graph, CodeGenerator* codegen) 69942249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik : graph_(graph), 70042249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik codegen_(codegen), 70142249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik slow_path_map_(std::less<uint32_t>(), graph->GetArena()->Adapter(kArenaAllocSlowPaths)) {} 70242249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik 70342249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik // Creates and adds a new slow-path, if needed, or returns existing one otherwise. 70442249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik // Templating the method (rather than the whole class) on the slow-path type enables 70542249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik // keeping this code at a generic, non architecture-specific place. 70642249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik // 70742249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik // NOTE: This approach assumes each InstructionType only generates one SlowPathCodeType. 70842249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik // To relax this requirement, we would need some RTTI on the stored slow-paths, 70942249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik // or template the class as a whole on SlowPathType. 71042249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik template <typename SlowPathCodeType> 71142249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik SlowPathCodeType* NewSlowPath(InstructionType* instruction) { 71242249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik static_assert(std::is_base_of<SlowPathCode, SlowPathCodeType>::value, 71342249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik "SlowPathCodeType is not a subclass of art::SlowPathCode"); 71442249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik static_assert(std::is_constructible<SlowPathCodeType, InstructionType*>::value, 71542249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik "SlowPathCodeType is not constructible from InstructionType*"); 71642249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik // Iterate over potential candidates for sharing. Currently, only same-typed 71742249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik // slow-paths with exactly the same dex-pc are viable candidates. 71842249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik // TODO: pass dex-pc/slow-path-type to run-time to allow even more sharing? 71942249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik const uint32_t dex_pc = instruction->GetDexPc(); 72042249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik auto iter = slow_path_map_.find(dex_pc); 72142249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik if (iter != slow_path_map_.end()) { 72242249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik auto candidates = iter->second; 72342249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik for (const auto& it : candidates) { 72442249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik InstructionType* other_instruction = it.first; 72542249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik SlowPathCodeType* other_slow_path = down_cast<SlowPathCodeType*>(it.second); 72642249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik // Determine if the instructions allow for slow-path sharing. 72742249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik if (HaveSameLiveRegisters(instruction, other_instruction) && 72842249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik HaveSameStackMap(instruction, other_instruction)) { 72942249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik // Can share: reuse existing one. 73042249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik return other_slow_path; 73142249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik } 73242249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik } 73342249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik } else { 73442249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik // First time this dex-pc is seen. 73542249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik iter = slow_path_map_.Put(dex_pc, {{}, {graph_->GetArena()->Adapter(kArenaAllocSlowPaths)}}); 73642249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik } 73742249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik // Cannot share: create and add new slow-path for this particular dex-pc. 73842249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik SlowPathCodeType* slow_path = new (graph_->GetArena()) SlowPathCodeType(instruction); 73942249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik iter->second.emplace_back(std::make_pair(instruction, slow_path)); 74042249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik codegen_->AddSlowPath(slow_path); 74142249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik return slow_path; 74242249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik } 74342249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik 74442249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik private: 74542249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik // Tests if both instructions have same set of live physical registers. This ensures 74642249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik // the slow-path has exactly the same preamble on saving these registers to stack. 74742249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik bool HaveSameLiveRegisters(const InstructionType* i1, const InstructionType* i2) const { 74842249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik const uint32_t core_spill = ~codegen_->GetCoreSpillMask(); 74942249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik const uint32_t fpu_spill = ~codegen_->GetFpuSpillMask(); 75042249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik RegisterSet* live1 = i1->GetLocations()->GetLiveRegisters(); 75142249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik RegisterSet* live2 = i2->GetLocations()->GetLiveRegisters(); 75242249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik return (((live1->GetCoreRegisters() & core_spill) == 75342249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik (live2->GetCoreRegisters() & core_spill)) && 75442249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik ((live1->GetFloatingPointRegisters() & fpu_spill) == 75542249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik (live2->GetFloatingPointRegisters() & fpu_spill))); 75642249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik } 75742249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik 75842249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik // Tests if both instructions have the same stack map. This ensures the interpreter 75942249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik // will find exactly the same dex-registers at the same entries. 76042249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik bool HaveSameStackMap(const InstructionType* i1, const InstructionType* i2) const { 76142249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik DCHECK(i1->HasEnvironment()); 76242249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik DCHECK(i2->HasEnvironment()); 76342249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik // We conservatively test if the two instructions find exactly the same instructions 76442249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik // and location in each dex-register. This guarantees they will have the same stack map. 76542249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik HEnvironment* e1 = i1->GetEnvironment(); 76642249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik HEnvironment* e2 = i2->GetEnvironment(); 76742249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik if (e1->GetParent() != e2->GetParent() || e1->Size() != e2->Size()) { 76842249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik return false; 76942249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik } 77042249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik for (size_t i = 0, sz = e1->Size(); i < sz; ++i) { 77142249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik if (e1->GetInstructionAt(i) != e2->GetInstructionAt(i) || 77242249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik !e1->GetLocationAt(i).Equals(e2->GetLocationAt(i))) { 77342249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik return false; 77442249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik } 77542249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik } 77642249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik return true; 77742249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik } 77842249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik 77942249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik HGraph* const graph_; 78042249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik CodeGenerator* const codegen_; 78142249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik 78242249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik // Map from dex-pc to vector of already existing instruction/slow-path pairs. 78342249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik ArenaSafeMap<uint32_t, ArenaVector<std::pair<InstructionType*, SlowPathCode*>>> slow_path_map_; 78442249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik 78542249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik DISALLOW_COPY_AND_ASSIGN(SlowPathGenerator); 78642249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik}; 78742249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik 78842249c3602c3d0243396ee3627ffb5906aa77c1eAart Bikclass InstructionCodeGenerator : public HGraphVisitor { 78942249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik public: 79042249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik InstructionCodeGenerator(HGraph* graph, CodeGenerator* codegen) 79142249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik : HGraphVisitor(graph), 79242249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik deopt_slow_paths_(graph, codegen) {} 79342249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik 79442249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik protected: 79542249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik // Add slow-path generator for each instruction/slow-path combination that desires sharing. 79642249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik // TODO: under current regime, only deopt sharing make sense; extend later. 79742249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik SlowPathGenerator<HDeoptimize> deopt_slow_paths_; 79842249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik}; 79942249c3602c3d0243396ee3627ffb5906aa77c1eAart Bik 800d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray} // namespace art 801d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray 802d4dd255db1d110ceb5551f6d95ff31fb57420994Nicolas Geoffray#endif // ART_COMPILER_OPTIMIZING_CODE_GENERATOR_H_ 803