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

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

Powered by Google App Engine
This is Rietveld 408576698