185b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe/* 285b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe * Copyright (C) 2015 The Android Open Source Project 385b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe * 485b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe * Licensed under the Apache License, Version 2.0 (the "License"); 585b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe * you may not use this file except in compliance with the License. 685b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe * You may obtain a copy of the License at 785b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe * 885b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe * http://www.apache.org/licenses/LICENSE-2.0 985b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe * 1085b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe * Unless required by applicable law or agreed to in writing, software 1185b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe * distributed under the License is distributed on an "AS IS" BASIS, 1285b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1385b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe * See the License for the specific language governing permissions and 1485b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe * limitations under the License. 1585b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe */ 1685b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe 1785b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe#ifndef ART_COMPILER_OPTIMIZING_INTRINSICS_UTILS_H_ 1885b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe#define ART_COMPILER_OPTIMIZING_INTRINSICS_UTILS_H_ 1985b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe 2085b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe#include "base/macros.h" 2185b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe#include "code_generator.h" 2285b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe#include "locations.h" 2385b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe#include "nodes.h" 2485b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe#include "utils/assembler.h" 2585b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe#include "utils/label.h" 2685b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe 2785b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampenamespace art { 2885b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe 2985b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe// Default slow-path for fallback (calling the managed code to handle the intrinsic) in an 3085b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe// intrinsified call. This will copy the arguments into the positions for a regular call. 3185b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe// 3285b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe// Note: The actual parameters are required to be in the locations given by the invoke's location 3385b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe// summary. If an intrinsic modifies those locations before a slowpath call, they must be 3485b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe// restored! 3585b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe// 3685b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe// Note: If an invoke wasn't sharpened, we will put down an invoke-virtual here. That's potentially 3785b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe// sub-optimal (compared to a direct pointer call), but this is a slow-path. 3885b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe 3985b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampetemplate <typename TDexCallingConvention> 4085b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampeclass IntrinsicSlowPath : public SlowPathCode { 4185b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe public: 429cd6d378bd573cdc14d049d32bdd22a97fa4d84aDavid Srbecky explicit IntrinsicSlowPath(HInvoke* invoke) : SlowPathCode(invoke), invoke_(invoke) { } 4385b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe 4485b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe Location MoveArguments(CodeGenerator* codegen) { 4585b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe TDexCallingConvention calling_convention_visitor; 4685b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe IntrinsicVisitor::MoveArguments(invoke_, codegen, &calling_convention_visitor); 4785b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe return calling_convention_visitor.GetMethodLocation(); 4885b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe } 4985b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe 5085b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe void EmitNativeCode(CodeGenerator* codegen) OVERRIDE { 5185b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe Assembler* assembler = codegen->GetAssembler(); 5285b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe assembler->Bind(GetEntryLabel()); 5385b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe 5485b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe SaveLiveRegisters(codegen, invoke_->GetLocations()); 5585b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe 5685b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe Location method_loc = MoveArguments(codegen); 5785b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe 5885b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe if (invoke_->IsInvokeStaticOrDirect()) { 5985b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe codegen->GenerateStaticOrDirectCall(invoke_->AsInvokeStaticOrDirect(), method_loc); 6085b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe } else { 6185b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe codegen->GenerateVirtualCall(invoke_->AsInvokeVirtual(), method_loc); 6285b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe } 6385b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe codegen->RecordPcInfo(invoke_, invoke_->GetDexPc(), this); 6485b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe 6585b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe // Copy the result back to the expected output. 6685b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe Location out = invoke_->GetLocations()->Out(); 6785b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe if (out.IsValid()) { 6885b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe DCHECK(out.IsRegister()); // TODO: Replace this when we support output in memory. 6985b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe DCHECK(!invoke_->GetLocations()->GetLiveRegisters()->ContainsCoreRegister(out.reg())); 7085b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe codegen->MoveFromReturnRegister(out, invoke_->GetType()); 7185b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe } 7285b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe 7385b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe RestoreLiveRegisters(codegen, invoke_->GetLocations()); 7485b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe assembler->Jump(GetExitLabel()); 7585b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe } 7685b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe 7785b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe const char* GetDescription() const OVERRIDE { return "IntrinsicSlowPath"; } 7885b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe 7985b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe private: 8085b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe // The instruction where this slow path is happening. 8185b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe HInvoke* const invoke_; 8285b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe 8385b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe DISALLOW_COPY_AND_ASSIGN(IntrinsicSlowPath); 8485b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe}; 8585b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe 8685b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe} // namespace art 8785b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe 8885b62f23fc6dfffe2ddd3ddfa74611666c9ff41dAndreas Gampe#endif // ART_COMPILER_OPTIMIZING_INTRINSICS_UTILS_H_ 89