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 #ifndef ART_COMPILER_OPTIMIZING_INTRINSICS_UTILS_H_ 18 #define ART_COMPILER_OPTIMIZING_INTRINSICS_UTILS_H_ 19 20 #include "base/casts.h" 21 #include "base/macros.h" 22 #include "code_generator.h" 23 #include "locations.h" 24 #include "nodes.h" 25 #include "utils/assembler.h" 26 #include "utils/label.h" 27 28 namespace art { 29 30 // Default slow-path for fallback (calling the managed code to handle the intrinsic) in an 31 // intrinsified call. This will copy the arguments into the positions for a regular call. 32 // 33 // Note: The actual parameters are required to be in the locations given by the invoke's location 34 // summary. If an intrinsic modifies those locations before a slowpath call, they must be 35 // restored! 36 // 37 // Note: If an invoke wasn't sharpened, we will put down an invoke-virtual here. That's potentially 38 // sub-optimal (compared to a direct pointer call), but this is a slow-path. 39 40 template <typename TDexCallingConvention, 41 typename TSlowPathCode = SlowPathCode, 42 typename TAssembler = Assembler> 43 class IntrinsicSlowPath : public TSlowPathCode { 44 public: IntrinsicSlowPath(HInvoke * invoke)45 explicit IntrinsicSlowPath(HInvoke* invoke) : TSlowPathCode(invoke), invoke_(invoke) { } 46 MoveArguments(CodeGenerator * codegen)47 Location MoveArguments(CodeGenerator* codegen) { 48 TDexCallingConvention calling_convention_visitor; 49 IntrinsicVisitor::MoveArguments(invoke_, codegen, &calling_convention_visitor); 50 return calling_convention_visitor.GetMethodLocation(); 51 } 52 EmitNativeCode(CodeGenerator * codegen)53 void EmitNativeCode(CodeGenerator* codegen) override { 54 TAssembler* assembler = down_cast<TAssembler*>(codegen->GetAssembler()); 55 assembler->Bind(this->GetEntryLabel()); 56 57 this->SaveLiveRegisters(codegen, invoke_->GetLocations()); 58 59 Location method_loc = MoveArguments(codegen); 60 61 if (invoke_->IsInvokeStaticOrDirect()) { 62 HInvokeStaticOrDirect* invoke_static_or_direct = invoke_->AsInvokeStaticOrDirect(); 63 DCHECK_NE(invoke_static_or_direct->GetMethodLoadKind(), 64 HInvokeStaticOrDirect::MethodLoadKind::kRecursive); 65 DCHECK_NE(invoke_static_or_direct->GetCodePtrLocation(), 66 HInvokeStaticOrDirect::CodePtrLocation::kCallCriticalNative); 67 codegen->GenerateStaticOrDirectCall(invoke_static_or_direct, method_loc, this); 68 } else { 69 codegen->GenerateVirtualCall(invoke_->AsInvokeVirtual(), method_loc, this); 70 } 71 72 // Copy the result back to the expected output. 73 Location out = invoke_->GetLocations()->Out(); 74 if (out.IsValid()) { 75 DCHECK(out.IsRegister()); // TODO: Replace this when we support output in memory. 76 DCHECK(!invoke_->GetLocations()->GetLiveRegisters()->ContainsCoreRegister(out.reg())); 77 codegen->MoveFromReturnRegister(out, invoke_->GetType()); 78 } 79 80 this->RestoreLiveRegisters(codegen, invoke_->GetLocations()); 81 assembler->Jump(this->GetExitLabel()); 82 } 83 GetDescription()84 const char* GetDescription() const override { return "IntrinsicSlowPath"; } 85 86 private: 87 // The instruction where this slow path is happening. 88 HInvoke* const invoke_; 89 90 DISALLOW_COPY_AND_ASSIGN(IntrinsicSlowPath); 91 }; 92 93 } // namespace art 94 95 #endif // ART_COMPILER_OPTIMIZING_INTRINSICS_UTILS_H_ 96