1// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5#include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM.
6#if defined(TARGET_ARCH_ARM)
7
8#include "vm/code_patcher.h"
9
10#include "vm/instructions.h"
11#include "vm/object.h"
12
13namespace dart {
14
15CodePtr CodePatcher::GetStaticCallTargetAt(uword return_address,
16 const Code& code) {
17 ASSERT(code.ContainsInstructionAt(return_address));
18 CallPattern call(return_address, code);
19 return call.TargetCode();
20}
21
22void CodePatcher::PatchStaticCallAt(uword return_address,
23 const Code& code,
24 const Code& new_target) {
25 ASSERT(code.ContainsInstructionAt(return_address));
26 CallPattern call(return_address, code);
27 call.SetTargetCode(new_target);
28}
29
30void CodePatcher::InsertDeoptimizationCallAt(uword start) {
31 UNREACHABLE();
32}
33
34CodePtr CodePatcher::GetInstanceCallAt(uword return_address,
35 const Code& caller_code,
36 Object* data) {
37 ASSERT(caller_code.ContainsInstructionAt(return_address));
38 ICCallPattern call(return_address, caller_code);
39 if (data != NULL) {
40 *data = call.Data();
41 }
42 return call.TargetCode();
43}
44
45void CodePatcher::PatchInstanceCallAt(uword return_address,
46 const Code& caller_code,
47 const Object& data,
48 const Code& target) {
49 auto thread = Thread::Current();
50 thread->isolate_group()->RunWithStoppedMutators([&]() {
51 PatchInstanceCallAtWithMutatorsStopped(thread, return_address, caller_code,
52 data, target);
53 });
54}
55
56void CodePatcher::PatchInstanceCallAtWithMutatorsStopped(
57 Thread* thread,
58 uword return_address,
59 const Code& caller_code,
60 const Object& data,
61 const Code& target) {
62 ASSERT(caller_code.ContainsInstructionAt(return_address));
63 ICCallPattern call(return_address, caller_code);
64 call.SetData(data);
65 call.SetTargetCode(target);
66}
67
68FunctionPtr CodePatcher::GetUnoptimizedStaticCallAt(uword return_address,
69 const Code& caller_code,
70 ICData* ic_data_result) {
71 ASSERT(caller_code.ContainsInstructionAt(return_address));
72 ICCallPattern static_call(return_address, caller_code);
73 ICData& ic_data = ICData::Handle();
74 ic_data ^= static_call.Data();
75 if (ic_data_result != NULL) {
76 *ic_data_result = ic_data.raw();
77 }
78 return ic_data.GetTargetAt(0);
79}
80
81void CodePatcher::PatchSwitchableCallAt(uword return_address,
82 const Code& caller_code,
83 const Object& data,
84 const Code& target) {
85 auto thread = Thread::Current();
86 // Ensure all threads are suspended as we update data and target pair.
87 thread->isolate_group()->RunWithStoppedMutators([&]() {
88 PatchSwitchableCallAtWithMutatorsStopped(thread, return_address,
89 caller_code, data, target);
90 });
91}
92
93void CodePatcher::PatchSwitchableCallAtWithMutatorsStopped(
94 Thread* thread,
95 uword return_address,
96 const Code& caller_code,
97 const Object& data,
98 const Code& target) {
99 ASSERT(caller_code.ContainsInstructionAt(return_address));
100 if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
101 BareSwitchableCallPattern call(return_address, caller_code);
102 call.SetData(data);
103 call.SetTarget(target);
104 } else {
105 SwitchableCallPattern call(return_address, caller_code);
106 call.SetData(data);
107 call.SetTarget(target);
108 }
109}
110
111CodePtr CodePatcher::GetSwitchableCallTargetAt(uword return_address,
112 const Code& caller_code) {
113 ASSERT(caller_code.ContainsInstructionAt(return_address));
114 if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
115 BareSwitchableCallPattern call(return_address, caller_code);
116 return call.target();
117 } else {
118 SwitchableCallPattern call(return_address, caller_code);
119 return call.target();
120 }
121}
122
123ObjectPtr CodePatcher::GetSwitchableCallDataAt(uword return_address,
124 const Code& caller_code) {
125 ASSERT(caller_code.ContainsInstructionAt(return_address));
126 if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
127 BareSwitchableCallPattern call(return_address, caller_code);
128 return call.data();
129 } else {
130 SwitchableCallPattern call(return_address, caller_code);
131 return call.data();
132 }
133}
134
135void CodePatcher::PatchNativeCallAt(uword return_address,
136 const Code& code,
137 NativeFunction target,
138 const Code& trampoline) {
139 Thread::Current()->isolate_group()->RunWithStoppedMutators([&]() {
140 ASSERT(code.ContainsInstructionAt(return_address));
141 NativeCallPattern call(return_address, code);
142 call.set_target(trampoline);
143 call.set_native_function(target);
144 });
145}
146
147CodePtr CodePatcher::GetNativeCallAt(uword return_address,
148 const Code& code,
149 NativeFunction* target) {
150 ASSERT(code.ContainsInstructionAt(return_address));
151 NativeCallPattern call(return_address, code);
152 *target = call.native_function();
153 return call.target();
154}
155
156} // namespace dart
157
158#endif // defined TARGET_ARCH_ARM
159