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

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

Issue 22825023: Uses an object pool on x64 (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 3 months 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
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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/assembler.h"
9 #include "vm/code_patcher.h" 9 #include "vm/code_patcher.h"
10 #include "vm/cpu.h" 10 #include "vm/cpu.h"
11 #include "vm/dart_entry.h" 11 #include "vm/dart_entry.h"
12 #include "vm/instructions.h" 12 #include "vm/instructions.h"
13 #include "vm/object.h" 13 #include "vm/object.h"
14 #include "vm/raw_object.h" 14 #include "vm/raw_object.h"
15 15
16 namespace dart { 16 namespace dart {
17 17
18 // The expected pattern of a Dart unoptimized call (static and instance): 18 // The expected pattern of a Dart unoptimized call (static and instance):
19 // 00: 48 bb imm64 mov RBX, ic-data 19 // 00: 49 8b 9f imm32 mov RBX, [PP + off]
20 // 10: 49 bb imm64 mov R11, target_address 20 // OR:
21 // 20: 41 ff d3 call R11 21 // 00: 49 8b 5f imm8 mov RBX, [PP + off]
22 // 23 <- return address 22 // 04: 0f 1f 00 nop
23 // Then:
24 // 07: 4d 8b 9f imm32 mov R11, [PP + off]
25 // OR:
26 // 07: 4d 8b 5f imm8 mov R11, [PP + off]
27 // 11: 0f 1f 00 nop
28 // Then:
29 // 14: 41 ff d3 call R11
30 // 17 <- return address
23 class UnoptimizedCall : public ValueObject { 31 class UnoptimizedCall : public ValueObject {
24 public: 32 public:
25 explicit UnoptimizedCall(uword return_address) 33 UnoptimizedCall(uword return_address, const Code& code)
26 : start_(return_address - kCallPatternSize) { 34 : start_(return_address - kCallPatternSize),
35 object_pool_(Array::Handle(code.ObjectPool())) {
27 ASSERT(IsValid(return_address)); 36 ASSERT(IsValid(return_address));
28 ASSERT((kCallPatternSize - 10) == Assembler::kCallExternalLabelSize); 37 ASSERT((kCallPatternSize - 7) == Assembler::kCallExternalLabelSize);
29 } 38 }
30 39
31 static const int kCallPatternSize = 23; 40 static const int kCallPatternSize = 17;
32 41
33 static bool IsValid(uword return_address) { 42 static bool IsValid(uword return_address) {
34 uint8_t* code_bytes = 43 uint8_t* code_bytes =
35 reinterpret_cast<uint8_t*>(return_address - kCallPatternSize); 44 reinterpret_cast<uint8_t*>(return_address - kCallPatternSize);
36 return (code_bytes[00] == 0x48) && (code_bytes[01] == 0xBB) && 45 return (code_bytes[0] == 0x49) && (code_bytes[1] == 0x8B) &&
37 (code_bytes[10] == 0x49) && (code_bytes[11] == 0xBB) && 46 ((code_bytes[2] == 0x5F) || (code_bytes[2] == 0x9F)) &&
38 (code_bytes[20] == 0x41) && (code_bytes[21] == 0xFF) && 47 (code_bytes[7] == 0x4D) && (code_bytes[8] == 0x8B) &&
39 (code_bytes[22] == 0xD3); 48 ((code_bytes[9] == 0x5F) || (code_bytes[9] == 0x9F)) &&
49 (code_bytes[14] == 0x41) && (code_bytes[15] == 0xFF) &&
50 (code_bytes[16] == 0xD3);
40 } 51 }
41 52
42 RawObject* ic_data() const { 53 RawObject* ic_data() const {
43 return *reinterpret_cast<RawObject**>(start_ + 0 + 2); 54 int index = InstructionPattern::IndexFromPPLoad(start_ + 2);
55 return object_pool_.At(index);
44 } 56 }
45 57
46 uword target() const { 58 uword target() const {
47 return *reinterpret_cast<uword*>(start_ + 10 + 2); 59 int index = InstructionPattern::IndexFromPPLoad(start_ + 9);
60 return reinterpret_cast<uword>(object_pool_.At(index));
48 } 61 }
49 62
50 void set_target(uword target) const { 63 void set_target(uword target) const {
51 uword* target_addr = reinterpret_cast<uword*>(start_ + 10 + 2); 64 int index = InstructionPattern::IndexFromPPLoad(start_ + 9);
52 *target_addr = target; 65 const Smi& smi = Smi::Handle(reinterpret_cast<RawSmi*>(target));
53 CPU::FlushICache(start_ + 10, 2 + 8); 66 object_pool_.SetAt(index, smi);
67 // No need to flush the instruction cache, since the code is not modified.
54 } 68 }
55 69
56 private: 70 private:
57 uword start_; 71 uword start_;
72 const Array& object_pool_;
58 DISALLOW_IMPLICIT_CONSTRUCTORS(UnoptimizedCall); 73 DISALLOW_IMPLICIT_CONSTRUCTORS(UnoptimizedCall);
59 }; 74 };
60 75
61 76
62 class InstanceCall : public UnoptimizedCall { 77 class InstanceCall : public UnoptimizedCall {
63 public: 78 public:
64 explicit InstanceCall(uword return_address) 79 InstanceCall(uword return_address, const Code& code)
65 : UnoptimizedCall(return_address) { 80 : UnoptimizedCall(return_address, code) {
66 #if defined(DEBUG) 81 #if defined(DEBUG)
67 ICData& test_ic_data = ICData::Handle(); 82 ICData& test_ic_data = ICData::Handle();
68 test_ic_data ^= ic_data(); 83 test_ic_data ^= ic_data();
69 ASSERT(test_ic_data.num_args_tested() > 0); 84 ASSERT(test_ic_data.num_args_tested() > 0);
70 #endif // DEBUG 85 #endif // DEBUG
71 } 86 }
72 87
73 private: 88 private:
74 DISALLOW_IMPLICIT_CONSTRUCTORS(InstanceCall); 89 DISALLOW_IMPLICIT_CONSTRUCTORS(InstanceCall);
75 }; 90 };
76 91
77 92
78 class UnoptimizedStaticCall : public UnoptimizedCall { 93 class UnoptimizedStaticCall : public UnoptimizedCall {
79 public: 94 public:
80 explicit UnoptimizedStaticCall(uword return_address) 95 UnoptimizedStaticCall(uword return_address, const Code& code)
81 : UnoptimizedCall(return_address) { 96 : UnoptimizedCall(return_address, code) {
82 #if defined(DEBUG) 97 #if defined(DEBUG)
83 ICData& test_ic_data = ICData::Handle(); 98 ICData& test_ic_data = ICData::Handle();
84 test_ic_data ^= ic_data(); 99 test_ic_data ^= ic_data();
85 ASSERT(test_ic_data.num_args_tested() >= 0); 100 ASSERT(test_ic_data.num_args_tested() >= 0);
86 #endif // DEBUG 101 #endif // DEBUG
87 } 102 }
88 103
89 private: 104 private:
90 DISALLOW_IMPLICIT_CONSTRUCTORS(UnoptimizedStaticCall); 105 DISALLOW_IMPLICIT_CONSTRUCTORS(UnoptimizedStaticCall);
91 }; 106 };
92 107
93 108
94 // The expected pattern of a dart static call: 109 // The expected pattern of a dart static call:
95 // mov R10, arguments_descriptor_array (10 bytes) (optional in polym. calls) 110 // 00 mov R10, arguments_descriptor_array (10 bytes) (optional in polym. calls)
96 // mov R11, target_address (10 bytes) 111 // 11: 4d 8b 9f imm32 mov R11, [PP + off]
97 // call R11 (3 bytes) 112 // OR:
113 // 11: 4d 8b 5f imm8 mov R11, [PP + off]
114 // 15: 0f 1f 00 nop
115 // Then:
116 // 16: call R11 (3 bytes)
98 // <- return address 117 // <- return address
99 class StaticCall : public ValueObject { 118 class StaticCall : public ValueObject {
100 public: 119 public:
101 explicit StaticCall(uword return_address) 120 explicit StaticCall(uword return_address, const Code& code)
102 : start_(return_address - kCallPatternSize) { 121 : start_(return_address - kCallPatternSize),
122 object_pool_(Array::Handle(code.ObjectPool())) {
103 ASSERT(IsValid(return_address)); 123 ASSERT(IsValid(return_address));
104 ASSERT(kCallPatternSize == Assembler::kCallExternalLabelSize); 124 ASSERT(kCallPatternSize == Assembler::kCallExternalLabelSize);
105 } 125 }
106 126
107 static const int kCallPatternSize = 13; 127 static const int kCallPatternSize = 10;
108 128
109 static bool IsValid(uword return_address) { 129 static bool IsValid(uword return_address) {
110 uint8_t* code_bytes = 130 uint8_t* code_bytes =
111 reinterpret_cast<uint8_t*>(return_address - kCallPatternSize); 131 reinterpret_cast<uint8_t*>(return_address - kCallPatternSize);
112 return (code_bytes[00] == 0x49) && (code_bytes[01] == 0xBB) && 132 return (code_bytes[0] == 0x4D) && (code_bytes[1] == 0x8B) &&
113 (code_bytes[10] == 0x41) && (code_bytes[11] == 0xFF) && 133 ((code_bytes[2] == 0x5F) || (code_bytes[2] == 0x9F)) &&
114 (code_bytes[12] == 0xD3); 134 (code_bytes[7] == 0x41) && (code_bytes[8] == 0xFF) &&
135 (code_bytes[9] == 0xD3);
115 } 136 }
116 137
117 uword target() const { 138 uword target() const {
118 return *reinterpret_cast<uword*>(start_ + 2); 139 int index = InstructionPattern::IndexFromPPLoad(start_ + 2);
140 return reinterpret_cast<uword>(object_pool_.At(index));
119 } 141 }
120 142
121 void set_target(uword target) const { 143 void set_target(uword target) const {
122 uword* target_addr = reinterpret_cast<uword*>(start_ + 2); 144 int index = InstructionPattern::IndexFromPPLoad(start_ + 2);
123 *target_addr = target; 145 const Smi& smi = Smi::Handle(reinterpret_cast<RawSmi*>(target));
124 CPU::FlushICache(start_, 2 + 8); 146 object_pool_.SetAt(index, smi);
147 // No need to flush the instruction cache, since the code is not modified.
125 } 148 }
126 149
127 private: 150 private:
128 uword start_; 151 uword start_;
129 152 const Array& object_pool_;
130 DISALLOW_IMPLICIT_CONSTRUCTORS(StaticCall); 153 DISALLOW_IMPLICIT_CONSTRUCTORS(StaticCall);
131 }; 154 };
132 155
133 156
134 // The expected code pattern of a dart closure call: 157 // The expected code pattern of a dart closure call:
135 // 00: 49 ba imm64 mov R10, immediate 2 ; 10 bytes 158 // 00: 49 ba imm64 mov R10, immediate 2 ; 10 bytes
136 // 10: 49 bb imm64 mov R11, target_address ; 10 bytes 159 // 10: 4d 8b 9f imm32 mov R11, [PP + off]
137 // 20: 41 ff d3 call R11 ; 3 bytes 160 // OR:
138 // 23: <- return_address 161 // 10: 4d 8b 5f imm8 mov R11, [PP + off]
162 // 14: 0f 1f 00 nop
163 // Then:
164 // 17: 41 ff d3 call R11 ; 3 bytes
165 // 20: <- return_address
139 class ClosureCall : public ValueObject { 166 class ClosureCall : public ValueObject {
140 public: 167 public:
141 explicit ClosureCall(uword return_address) 168 explicit ClosureCall(uword return_address)
142 : start_(return_address - kCallPatternSize) { 169 : start_(return_address - kCallPatternSize) {
143 ASSERT(IsValid(return_address)); 170 ASSERT(IsValid(return_address));
144 } 171 }
145 172
146 static bool IsValid(uword return_address) { 173 static bool IsValid(uword return_address) {
147 uint8_t* code_bytes = 174 uint8_t* code_bytes =
148 reinterpret_cast<uint8_t*>(return_address - kCallPatternSize); 175 reinterpret_cast<uint8_t*>(return_address - kCallPatternSize);
149 return (code_bytes[00] == 0x49) && (code_bytes[01] == 0xBA) && 176 return (code_bytes[00] == 0x49) && (code_bytes[01] == 0xBA) &&
150 (code_bytes[10] == 0x49) && (code_bytes[11] == 0xBB) && 177 (code_bytes[10] == 0x4D) && (code_bytes[11] == 0x8B) &&
151 (code_bytes[20] == 0x41) && (code_bytes[21] == 0xFF) && 178 ((code_bytes[12] == 0x5F) || (code_bytes[12] == 0x9F)) &&
152 (code_bytes[22] == 0xD3); 179 (code_bytes[17] == 0x41) && (code_bytes[18] == 0xFF) &&
180 (code_bytes[19] == 0xD3);
153 } 181 }
154 182
155 RawArray* arguments_descriptor() const { 183 RawArray* arguments_descriptor() const {
156 return *reinterpret_cast<RawArray**>(start_ + 2); 184 return *reinterpret_cast<RawArray**>(start_ + 2);
157 } 185 }
158 186
159 private: 187 private:
160 static const int kCallPatternSize = 10 + 10 + 3; 188 static const int kCallPatternSize = 10 + 7 + 3;
161 uword start_; 189 uword start_;
162 DISALLOW_IMPLICIT_CONSTRUCTORS(ClosureCall); 190 DISALLOW_IMPLICIT_CONSTRUCTORS(ClosureCall);
163 }; 191 };
164 192
165 193
166 RawArray* CodePatcher::GetClosureArgDescAt(uword return_address, 194 RawArray* CodePatcher::GetClosureArgDescAt(uword return_address,
167 const Code& code) { 195 const Code& code) {
168 ASSERT(code.ContainsInstructionAt(return_address)); 196 ASSERT(code.ContainsInstructionAt(return_address));
169 ClosureCall call(return_address); 197 ClosureCall call(return_address);
170 return call.arguments_descriptor(); 198 return call.arguments_descriptor();
171 } 199 }
172 200
173 201
174 uword CodePatcher::GetStaticCallTargetAt(uword return_address, 202 uword CodePatcher::GetStaticCallTargetAt(uword return_address,
175 const Code& code) { 203 const Code& code) {
176 ASSERT(code.ContainsInstructionAt(return_address)); 204 ASSERT(code.ContainsInstructionAt(return_address));
177 StaticCall call(return_address); 205 StaticCall call(return_address, code);
178 return call.target(); 206 return call.target();
179 } 207 }
180 208
181 209
182 void CodePatcher::PatchStaticCallAt(uword return_address, 210 void CodePatcher::PatchStaticCallAt(uword return_address,
183 const Code& code, 211 const Code& code,
184 uword new_target) { 212 uword new_target) {
185 ASSERT(code.ContainsInstructionAt(return_address)); 213 ASSERT(code.ContainsInstructionAt(return_address));
186 StaticCall call(return_address); 214 StaticCall call(return_address, code);
187 call.set_target(new_target); 215 call.set_target(new_target);
188 } 216 }
189 217
190 218
191 void CodePatcher::PatchInstanceCallAt(uword return_address, 219 void CodePatcher::PatchInstanceCallAt(uword return_address,
192 const Code& code, 220 const Code& code,
193 uword new_target) { 221 uword new_target) {
194 ASSERT(code.ContainsInstructionAt(return_address)); 222 ASSERT(code.ContainsInstructionAt(return_address));
195 InstanceCall call(return_address); 223 InstanceCall call(return_address, code);
196 call.set_target(new_target); 224 call.set_target(new_target);
197 } 225 }
198 226
199 227
200 uword CodePatcher::GetInstanceCallAt(uword return_address, 228 uword CodePatcher::GetInstanceCallAt(uword return_address,
201 const Code& code, 229 const Code& code,
202 ICData* ic_data) { 230 ICData* ic_data) {
203 ASSERT(code.ContainsInstructionAt(return_address)); 231 ASSERT(code.ContainsInstructionAt(return_address));
204 InstanceCall call(return_address); 232 InstanceCall call(return_address, code);
205 if (ic_data != NULL) { 233 if (ic_data != NULL) {
206 *ic_data ^= call.ic_data(); 234 *ic_data ^= call.ic_data();
207 } 235 }
208 return call.target(); 236 return call.target();
209 } 237 }
210 238
211 239
212 intptr_t CodePatcher::InstanceCallSizeInBytes() { 240 intptr_t CodePatcher::InstanceCallSizeInBytes() {
213 return InstanceCall::kCallPatternSize; 241 return InstanceCall::kCallPatternSize;
214 } 242 }
215 243
216 244
217 void CodePatcher::InsertCallAt(uword start, uword target) { 245 void CodePatcher::InsertCallAt(uword start, uword target) {
218 // The inserted call should not overlap the lazy deopt jump code. 246 // The inserted call should not overlap the lazy deopt jump code.
219 ASSERT(start + ShortCallPattern::InstructionLength() <= target); 247 ASSERT(start + ShortCallPattern::InstructionLength() <= target);
220 *reinterpret_cast<uint8_t*>(start) = 0xE8; 248 *reinterpret_cast<uint8_t*>(start) = 0xE8;
221 ShortCallPattern call(start); 249 ShortCallPattern call(start);
222 call.SetTargetAddress(target); 250 call.SetTargetAddress(target);
223 CPU::FlushICache(start, ShortCallPattern::InstructionLength()); 251 CPU::FlushICache(start, ShortCallPattern::InstructionLength());
224 } 252 }
225 253
226 254
227 RawFunction* CodePatcher::GetUnoptimizedStaticCallAt( 255 RawFunction* CodePatcher::GetUnoptimizedStaticCallAt(
228 uword return_address, const Code& code, ICData* ic_data_result) { 256 uword return_address, const Code& code, ICData* ic_data_result) {
229 ASSERT(code.ContainsInstructionAt(return_address)); 257 ASSERT(code.ContainsInstructionAt(return_address));
230 UnoptimizedStaticCall static_call(return_address); 258 UnoptimizedStaticCall static_call(return_address, code);
231 ICData& ic_data = ICData::Handle(); 259 ICData& ic_data = ICData::Handle();
232 ic_data ^= static_call.ic_data(); 260 ic_data ^= static_call.ic_data();
233 if (ic_data_result != NULL) { 261 if (ic_data_result != NULL) {
234 *ic_data_result = ic_data.raw(); 262 *ic_data_result = ic_data.raw();
235 } 263 }
236 return ic_data.GetTargetAt(0); 264 return ic_data.GetTargetAt(0);
237 } 265 }
238 266
239 } // namespace dart 267 } // namespace dart
240 268
241 #endif // defined TARGET_ARCH_X64 269 #endif // defined TARGET_ARCH_X64
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698