blob: def43e2bd264938d56822541502a0a27a67ddb92 [file] [log] [blame]
Brian Carlstrom7940e442013-07-12 13:46:57 -07001/*
2 * Copyright (C) 2011 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#include "stubs/stubs.h"
18
Ian Rogers166db042013-07-26 12:05:57 -070019#include "entrypoints/quick/quick_entrypoints.h"
Brian Carlstrom7940e442013-07-12 13:46:57 -070020#include "jni_internal.h"
Ian Rogers166db042013-07-26 12:05:57 -070021#include "utils/arm/assembler_arm.h"
22#include "utils/mips/assembler_mips.h"
23#include "utils/x86/assembler_x86.h"
Brian Carlstrom7940e442013-07-12 13:46:57 -070024#include "stack_indirect_reference_table.h"
25#include "sirt_ref.h"
26
27#define __ assembler->
28
29namespace art {
30
31namespace arm {
32const std::vector<uint8_t>* CreatePortableResolutionTrampoline() {
33 UniquePtr<ArmAssembler> assembler(static_cast<ArmAssembler*>(Assembler::Create(kArm)));
34 RegList save = (1 << R0) | (1 << R1) | (1 << R2) | (1 << R3) | (1 << LR);
35
36 __ PushList(save);
Ian Rogers7655f292013-07-29 11:07:13 -070037 __ LoadFromOffset(kLoadWord, R12, TR,
38 PORTABLE_ENTRYPOINT_OFFSET(pPortableResolutionTrampolineFromCode));
Brian Carlstrom7940e442013-07-12 13:46:57 -070039 __ mov(R3, ShifterOperand(TR)); // Pass Thread::Current() in R3
40 __ mov(R2, ShifterOperand(SP)); // Pass sp for Method** callee_addr
41 __ IncreaseFrameSize(12); // 3 words of space for alignment
42 // Call to resolution trampoline (callee, receiver, callee_addr, Thread*)
43 __ blx(R12);
44 __ mov(R12, ShifterOperand(R0)); // Save code address returned into R12
45 __ DecreaseFrameSize(12);
46 __ PopList(save);
47 __ cmp(R12, ShifterOperand(0));
48 __ bx(R12, NE); // If R12 != 0 tail call method's code
49 __ bx(LR); // Return to caller to handle exception
50
51 assembler->EmitSlowPaths();
52 size_t cs = assembler->CodeSize();
53 UniquePtr<std::vector<uint8_t> > resolution_trampoline(new std::vector<uint8_t>(cs));
54 MemoryRegion code(&(*resolution_trampoline)[0], resolution_trampoline->size());
55 assembler->FinalizeInstructions(code);
56
57 return resolution_trampoline.release();
58}
Brian Carlstrom7934ac22013-07-26 10:54:15 -070059} // namespace arm
Brian Carlstrom7940e442013-07-12 13:46:57 -070060
61namespace mips {
62const std::vector<uint8_t>* CreatePortableResolutionTrampoline() {
63 UniquePtr<MipsAssembler> assembler(static_cast<MipsAssembler*>(Assembler::Create(kMips)));
64 // Build frame and save argument registers and RA.
65 __ AddConstant(SP, SP, -32);
66 __ StoreToOffset(kStoreWord, RA, SP, 28);
67 __ StoreToOffset(kStoreWord, A3, SP, 12);
68 __ StoreToOffset(kStoreWord, A2, SP, 8);
69 __ StoreToOffset(kStoreWord, A1, SP, 4);
70 __ StoreToOffset(kStoreWord, A0, SP, 0);
71
72 __ LoadFromOffset(kLoadWord, T9, S1,
Ian Rogers7655f292013-07-29 11:07:13 -070073 PORTABLE_ENTRYPOINT_OFFSET(pPortableResolutionTrampolineFromCode));
Brian Carlstrom7940e442013-07-12 13:46:57 -070074 __ Move(A3, S1); // Pass Thread::Current() in A3
75 __ Move(A2, SP); // Pass SP for Method** callee_addr
Brian Carlstrom7934ac22013-07-26 10:54:15 -070076 __ Jalr(T9); // Call to resolution trampoline (callee, receiver, callee_addr, Thread*)
Brian Carlstrom7940e442013-07-12 13:46:57 -070077
78 // Restore frame, argument registers, and RA.
79 __ LoadFromOffset(kLoadWord, A0, SP, 0);
80 __ LoadFromOffset(kLoadWord, A1, SP, 4);
81 __ LoadFromOffset(kLoadWord, A2, SP, 8);
82 __ LoadFromOffset(kLoadWord, A3, SP, 12);
83 __ LoadFromOffset(kLoadWord, RA, SP, 28);
84 __ AddConstant(SP, SP, 32);
85
86 Label resolve_fail;
87 __ EmitBranch(V0, ZERO, &resolve_fail, true);
Brian Carlstrom7934ac22013-07-26 10:54:15 -070088 __ Jr(V0); // If V0 != 0 tail call method's code
Brian Carlstrom7940e442013-07-12 13:46:57 -070089 __ Bind(&resolve_fail, false);
Brian Carlstrom7934ac22013-07-26 10:54:15 -070090 __ Jr(RA); // Return to caller to handle exception
Brian Carlstrom7940e442013-07-12 13:46:57 -070091
92 assembler->EmitSlowPaths();
93 size_t cs = assembler->CodeSize();
94 UniquePtr<std::vector<uint8_t> > resolution_trampoline(new std::vector<uint8_t>(cs));
95 MemoryRegion code(&(*resolution_trampoline)[0], resolution_trampoline->size());
96 assembler->FinalizeInstructions(code);
97
98 return resolution_trampoline.release();
99}
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700100} // namespace mips
Brian Carlstrom7940e442013-07-12 13:46:57 -0700101
102namespace x86 {
103const std::vector<uint8_t>* CreatePortableResolutionTrampoline() {
104 UniquePtr<X86Assembler> assembler(static_cast<X86Assembler*>(Assembler::Create(kX86)));
105
106 __ pushl(EBP);
107 __ movl(EBP, ESP); // save ESP
108 __ subl(ESP, Immediate(8)); // Align stack
109 __ movl(EAX, Address(EBP, 8)); // Method* called
110 __ leal(EDX, Address(EBP, 8)); // Method** called_addr
111 __ fs()->pushl(Address::Absolute(Thread::SelfOffset())); // pass thread
112 __ pushl(EDX); // pass called_addr
113 __ pushl(ECX); // pass receiver
114 __ pushl(EAX); // pass called
115 // Call to resolve method.
Ian Rogers7655f292013-07-29 11:07:13 -0700116 __ Call(ThreadOffset(PORTABLE_ENTRYPOINT_OFFSET(pPortableResolutionTrampolineFromCode)),
Brian Carlstrom7940e442013-07-12 13:46:57 -0700117 X86ManagedRegister::FromCpuRegister(ECX));
118 __ leave();
119
120 Label resolve_fail; // forward declaration
121 __ cmpl(EAX, Immediate(0));
122 __ j(kEqual, &resolve_fail);
123 __ jmp(EAX);
124 // Tail call to intended method.
125 __ Bind(&resolve_fail);
126 __ ret();
127
128 assembler->EmitSlowPaths();
129 size_t cs = assembler->CodeSize();
130 UniquePtr<std::vector<uint8_t> > resolution_trampoline(new std::vector<uint8_t>(cs));
131 MemoryRegion code(&(*resolution_trampoline)[0], resolution_trampoline->size());
132 assembler->FinalizeInstructions(code);
133
134 return resolution_trampoline.release();
135}
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700136} // namespace x86
Brian Carlstrom7940e442013-07-12 13:46:57 -0700137
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700138} // namespace art