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