Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(570)

Side by Side Diff: runtime/vm/code_patcher_x64.cc

Issue 8984003: Port code generator to x64. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: '' Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/code_index_table_test.cc ('k') | runtime/vm/code_patcher_x64_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 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. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64.
6 #if defined(TARGET_ARCH_X64) 6 #if defined(TARGET_ARCH_X64)
7 7
8 #include "vm/assembler.h"
8 #include "vm/code_patcher.h" 9 #include "vm/code_patcher.h"
10 #include "vm/cpu.h"
11 #include "vm/ic_data.h"
12 #include "vm/instructions.h"
13 #include "vm/object.h"
14 #include "vm/raw_object.h"
9 15
10 namespace dart { 16 namespace dart {
11 17
18 // The pattern of a Dart call is:
19 // 00: 48 bb imm64 mov RBX, immediate 1
20 // 10: 49 ba imm64 mov R10, immediate 2
21 // 20: 49 bb imm64 mov R11, target_address
22 // 30: 41 ff d3 call R11
23 // 33: <- return_address
24 class DartCallPattern : public ValueObject {
25 public:
26 explicit DartCallPattern(uword return_address)
27 : start_(return_address - kCallPatternSize) {
28 ASSERT(IsValid(return_address));
29 ASSERT((kCallPatternSize - 20) == Assembler::kCallExternalLabelSize);
30 }
31
32 static const int kCallPatternSize = 33;
33
34 static bool IsValid(uword return_address) {
35 uint8_t* code_bytes =
36 reinterpret_cast<uint8_t*>(return_address - kCallPatternSize);
37 return (code_bytes[00] == 0x48) && (code_bytes[01] == 0xBB) &&
38 (code_bytes[10] == 0x49) && (code_bytes[11] == 0xBA) &&
39 (code_bytes[20] == 0x49) && (code_bytes[21] == 0xBB) &&
40 (code_bytes[30] == 0x41) && (code_bytes[31] == 0xFF) &&
41 (code_bytes[32] == 0xD3);
42 }
43
44 uword target() const {
45 return *reinterpret_cast<uword*>(start_ + 20 + 2);
46 }
47
48 void set_target(uword target) const {
49 uword* target_addr = reinterpret_cast<uword*>(start_ + 20 + 2);
50 *target_addr = target;
51 CPU::FlushICache(start_ + 20, 2 + 8);
52 }
53
54 uint64_t immediate_one() const {
55 return *reinterpret_cast<uint64_t*>(start_ + 0 + 2);
56 }
57
58 void set_immediate_one(uint64_t value) {
59 uint64_t* target_addr = reinterpret_cast<uint64_t*>(start_ + 0 + 2);
60 *target_addr = value;
61 CPU::FlushICache(start_ + 0, 2 + 8);
62 }
63
64 uint64_t immediate_two() const {
65 return *reinterpret_cast<uint64_t*>(start_ + 10 + 2);
66 }
67
68 int argument_count() const {
69 Array& args_desc = Array::Handle();
70 args_desc ^= reinterpret_cast<RawObject*>(immediate_two());
71 Smi& num_args = Smi::Handle();
72 num_args ^= args_desc.At(0);
73 return num_args.Value();
74 }
75
76 int named_argument_count() const {
77 Array& args_desc = Array::Handle();
78 args_desc ^= reinterpret_cast<RawObject*>(immediate_two());
79 Smi& num_args = Smi::Handle();
80 num_args ^= args_desc.At(0);
81 Smi& num_pos_args = Smi::Handle();
82 num_pos_args ^= args_desc.At(1);
83 return num_args.Value() - num_pos_args.Value();
84 }
85
86 uword start_;
87 DISALLOW_IMPLICIT_CONSTRUCTORS(DartCallPattern);
88 };
89
90
91 // A Dart static call passes the function object in RBX.
92 class StaticCall : public DartCallPattern {
93 public:
94 explicit StaticCall(uword return_address)
95 : DartCallPattern(return_address) {}
96
97 RawFunction* function() const {
98 Function& f = Function::Handle();
99 f ^= reinterpret_cast<RawObject*>(immediate_one());
100 return f.raw();
101 }
102
103 private:
104 DISALLOW_IMPLICIT_CONSTRUCTORS(StaticCall);
105 };
106
107
108 // A Dart instance call passes the ic-data array in RBX.
109 class InstanceCall : public DartCallPattern {
110 public:
111 explicit InstanceCall(uword return_address)
112 : DartCallPattern(return_address) {}
113
114 RawArray* ic_data() const {
115 Array& array = Array::Handle();
116 array ^= reinterpret_cast<RawObject*>(immediate_one());
117 return array.raw();
118 }
119
120 void SetIcData(const Array& value) {
121 set_immediate_one(reinterpret_cast<int64_t>(value.raw()));
122 }
123
124 private:
125 DISALLOW_IMPLICIT_CONSTRUCTORS(InstanceCall);
126 };
127
128
12 void CodePatcher::GetStaticCallAt(uword return_address, 129 void CodePatcher::GetStaticCallAt(uword return_address,
13 Function* function, 130 Function* function,
14 uword* target) { 131 uword* target) {
15 UNIMPLEMENTED(); 132 ASSERT(function != NULL);
133 ASSERT(target != NULL);
134 StaticCall call(return_address);
135 *target = call.target();
136 *function = call.function();
16 } 137 }
17 138
18 139
19 void CodePatcher::PatchStaticCallAt(uword return_address, uword new_target) { 140 void CodePatcher::PatchStaticCallAt(uword return_address, uword new_target) {
20 UNIMPLEMENTED(); 141 StaticCall call(return_address);
142 call.set_target(new_target);
21 } 143 }
22 144
23 145
24 void CodePatcher::PatchInstanceCallAt(uword return_address, uword new_target) { 146 void CodePatcher::PatchInstanceCallAt(uword return_address, uword new_target) {
25 UNIMPLEMENTED(); 147 InstanceCall call(return_address);
148 call.set_target(new_target);
149 }
150
151
152 static void SwapCode(intptr_t num_bytes, char* a, char* b) {
153 for (intptr_t i = 0; i < num_bytes; i++) {
154 char tmp = *a;
155 *a = *b;
156 *b = tmp;
157 a++;
158 b++;
159 }
160 }
161
162
163 // The patch code buffer contains the jump code sequence which will be inserted
164 // at entry point.
165 void CodePatcher::PatchEntry(const Code& code) {
166 Jump jmp_entry(code.EntryPoint());
167 ASSERT(!jmp_entry.IsValid());
168 const uword patch_buffer = code.GetPatchCodePc();
169 ASSERT(patch_buffer != 0);
170 Jump jmp_patch(patch_buffer);
171 ASSERT(jmp_patch.IsValid());
172 const uword jump_target = jmp_patch.TargetAddress();
173 SwapCode(jmp_patch.pattern_length_in_bytes(),
174 reinterpret_cast<char*>(code.EntryPoint()),
175 reinterpret_cast<char*>(patch_buffer));
176 jmp_entry.SetTargetAddress(jump_target);
177 }
178
179
180 // The entry point is a jump code sequence, the patch code buffer contains
181 // original code, the entry point contains the jump code sequence.
182 void CodePatcher::RestoreEntry(const Code& code) {
183 Jump jmp_entry(code.EntryPoint());
184 ASSERT(jmp_entry.IsValid());
185 const uword jump_target = jmp_entry.TargetAddress();
186 const uword patch_buffer = code.GetPatchCodePc();
187 ASSERT(patch_buffer != 0);
188 // 'patch_buffer' contains original entry code.
189 Jump jmp_patch(patch_buffer);
190 ASSERT(!jmp_patch.IsValid());
191 SwapCode(jmp_patch.pattern_length_in_bytes(),
192 reinterpret_cast<char*>(code.EntryPoint()),
193 reinterpret_cast<char*>(patch_buffer));
194 ASSERT(jmp_patch.IsValid());
195 jmp_patch.SetTargetAddress(jump_target);
196 }
197
198
199 bool CodePatcher::CodeIsPatchable(const Code& code) {
200 Jump jmp_entry(code.EntryPoint());
201 if (code.Size() < (jmp_entry.pattern_length_in_bytes() * 2)) {
202 return false;
203 }
204 uword limit = code.EntryPoint() + jmp_entry.pattern_length_in_bytes();
205 for (intptr_t i = 0; i < code.pointer_offsets_length(); i++) {
206 const uword addr = code.GetPointerOffsetAt(i) + code.EntryPoint();
207 if (addr < limit) {
208 return false;
209 }
210 }
211 return true;
26 } 212 }
27 213
28 214
29 bool CodePatcher::IsDartCall(uword return_address) { 215 bool CodePatcher::IsDartCall(uword return_address) {
30 UNIMPLEMENTED(); 216 return DartCallPattern::IsValid(return_address);
31 return false;
32 } 217 }
33 218
34 219
35 void CodePatcher::GetInstanceCallAt(uword return_address, 220 void CodePatcher::GetInstanceCallAt(uword return_address,
36 String* function_name, 221 String* function_name,
37 int* num_arguments, 222 int* num_arguments,
38 int* num_named_arguments, 223 int* num_named_arguments,
39 uword* target) { 224 uword* target) {
40 UNIMPLEMENTED(); 225 ASSERT(function_name != NULL);
41 } 226 ASSERT(num_arguments != NULL);
42 227 ASSERT(num_named_arguments != NULL);
43 228 ASSERT(target != NULL);
44 void CodePatcher::PatchEntry(const Code& code) { 229 InstanceCall call(return_address);
45 UNIMPLEMENTED(); 230 *num_arguments = call.argument_count();
46 } 231 *num_named_arguments = call.named_argument_count();
47 232 *target = call.target();
48 233 ICData ic_data(Array::ZoneHandle(call.ic_data()));
49 void CodePatcher::RestoreEntry(const Code& code) { 234 *function_name = ic_data.FunctionName();
50 UNIMPLEMENTED();
51 }
52
53
54 bool CodePatcher::CodeIsPatchable(const Code& code) {
55 UNIMPLEMENTED();
56 return false;
57 } 235 }
58 236
59 237
60 RawArray* CodePatcher::GetInstanceCallIcDataAt(uword return_address) { 238 RawArray* CodePatcher::GetInstanceCallIcDataAt(uword return_address) {
61 UNIMPLEMENTED(); 239 InstanceCall call(return_address);
62 return NULL; 240 return call.ic_data();
63 } 241 }
64 242
65 243
66 void CodePatcher::SetInstanceCallIcDataAt(uword return_address, 244 void CodePatcher::SetInstanceCallIcDataAt(uword return_address,
67 const Array& ic_data) { 245 const Array& ic_data) {
68 UNIMPLEMENTED(); 246 InstanceCall call(return_address);
247 call.SetIcData(ic_data);
248 }
249
250
251 intptr_t CodePatcher::InstanceCallSizeInBytes() {
252 return DartCallPattern::kCallPatternSize;
69 } 253 }
70 254
71 } // namespace dart 255 } // namespace dart
72 256
73 #endif // defined TARGET_ARCH_X64 257 #endif // defined TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « runtime/vm/code_index_table_test.cc ('k') | runtime/vm/code_patcher_x64_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698