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

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

Issue 829133006: VM: Small generated code size improvements on x64. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: addressed comments Created 5 years, 11 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_mips.cc ('k') | runtime/vm/flow_graph_compiler_x64.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/flow_graph_compiler.h" 12 #include "vm/flow_graph_compiler.h"
13 #include "vm/instructions.h" 13 #include "vm/instructions.h"
14 #include "vm/object.h" 14 #include "vm/object.h"
15 #include "vm/raw_object.h" 15 #include "vm/raw_object.h"
16 16
17 namespace dart { 17 namespace dart {
18 18
19 // The expected pattern of a Dart unoptimized call (static and instance): 19 // The expected pattern of a Dart unoptimized call (static and instance):
20 // 00: 49 8b 9f imm32 mov RBX, [PP + off] 20 // 0: 49 8b 9f imm32 mov RBX, [PP + off]
21 // 07: 4d 8b 9f imm32 mov R11, [PP + off] 21 // 7: 41 ff 97 imm32 call [PP + off]
22 // 14: 41 ff d3 call R11 22 // 14 <- return address
23 // 17 <- return address
24 class UnoptimizedCall : public ValueObject { 23 class UnoptimizedCall : public ValueObject {
25 public: 24 public:
26 UnoptimizedCall(uword return_address, const Code& code) 25 UnoptimizedCall(uword return_address, const Code& code)
27 : start_(return_address - kCallPatternSize), 26 : start_(return_address - kCallPatternSize),
28 object_pool_(Array::Handle(code.ObjectPool())) { 27 object_pool_(Array::Handle(code.ObjectPool())) {
29 ASSERT(IsValid(return_address)); 28 ASSERT(IsValid(return_address));
30 ASSERT((kCallPatternSize - 7) == Assembler::kCallExternalLabelSize); 29 ASSERT((kCallPatternSize - 7) == Assembler::kCallExternalLabelSize);
31 } 30 }
32 31
33 static const int kCallPatternSize = 17; 32 static const int kCallPatternSize = 14;
34 33
35 static bool IsValid(uword return_address) { 34 static bool IsValid(uword return_address) {
36 uint8_t* code_bytes = 35 uint8_t* code_bytes =
37 reinterpret_cast<uint8_t*>(return_address - kCallPatternSize); 36 reinterpret_cast<uint8_t*>(return_address - kCallPatternSize);
38 return (code_bytes[0] == 0x49) && (code_bytes[1] == 0x8B) && 37 return (code_bytes[0] == 0x49) && (code_bytes[1] == 0x8B) &&
39 (code_bytes[2] == 0x9F) && 38 (code_bytes[2] == 0x9F) &&
40 (code_bytes[7] == 0x4D) && (code_bytes[8] == 0x8B) && 39 (code_bytes[7] == 0x41) && (code_bytes[8] == 0xFF) &&
41 (code_bytes[9] == 0x9F) && 40 (code_bytes[9] == 0x97);
42 (code_bytes[14] == 0x41) && (code_bytes[15] == 0xFF) &&
43 (code_bytes[16] == 0xD3);
44 } 41 }
45 42
46 RawObject* ic_data() const { 43 RawObject* ic_data() const {
47 intptr_t index = InstructionPattern::IndexFromPPLoad(start_ + 3); 44 intptr_t index = InstructionPattern::IndexFromPPLoad(start_ + 3);
48 return object_pool_.At(index); 45 return object_pool_.At(index);
49 } 46 }
50 47
51 uword target() const { 48 uword target() const {
52 intptr_t index = InstructionPattern::IndexFromPPLoad(start_ + 10); 49 intptr_t index = InstructionPattern::IndexFromPPLoad(start_ + 10);
53 return reinterpret_cast<uword>(object_pool_.At(index)); 50 return reinterpret_cast<uword>(object_pool_.At(index));
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
92 test_ic_data ^= ic_data(); 89 test_ic_data ^= ic_data();
93 ASSERT(test_ic_data.NumArgsTested() >= 0); 90 ASSERT(test_ic_data.NumArgsTested() >= 0);
94 #endif // DEBUG 91 #endif // DEBUG
95 } 92 }
96 93
97 private: 94 private:
98 DISALLOW_IMPLICIT_CONSTRUCTORS(UnoptimizedStaticCall); 95 DISALLOW_IMPLICIT_CONSTRUCTORS(UnoptimizedStaticCall);
99 }; 96 };
100 97
101 98
102 // The expected pattern of a dart static call:
103 // 00 mov R10, arguments_descriptor_array (10 bytes) (optional in polym. calls)
104 // 11: 4d 8b 9f imm32 mov R11, [PP + off]
105 // 16: call R11 (3 bytes)
106 // <- return address
107 class StaticCall : public ValueObject {
108 public:
109 explicit StaticCall(uword return_address, const Code& code)
110 : start_(return_address - kCallPatternSize),
111 object_pool_(Array::Handle(code.ObjectPool())) {
112 ASSERT(IsValid(return_address));
113 ASSERT(kCallPatternSize == Assembler::kCallExternalLabelSize);
114 }
115
116 static const int kCallPatternSize = 10;
117
118 static bool IsValid(uword return_address) {
119 uint8_t* code_bytes =
120 reinterpret_cast<uint8_t*>(return_address - kCallPatternSize);
121 return (code_bytes[0] == 0x4D) && (code_bytes[1] == 0x8B) &&
122 (code_bytes[2] == 0x9F) &&
123 (code_bytes[7] == 0x41) && (code_bytes[8] == 0xFF) &&
124 (code_bytes[9] == 0xD3);
125 }
126
127 uword target() const {
128 intptr_t index = InstructionPattern::IndexFromPPLoad(start_ + 3);
129 return reinterpret_cast<uword>(object_pool_.At(index));
130 }
131
132 void set_target(uword target) const {
133 intptr_t index = InstructionPattern::IndexFromPPLoad(start_ + 3);
134 const Smi& smi = Smi::Handle(reinterpret_cast<RawSmi*>(target));
135 object_pool_.SetAt(index, smi);
136 // No need to flush the instruction cache, since the code is not modified.
137 }
138
139 private:
140 uword start_;
141 const Array& object_pool_;
142 DISALLOW_IMPLICIT_CONSTRUCTORS(StaticCall);
143 };
144
145
146 // The expected pattern of a call where the target is loaded from 99 // The expected pattern of a call where the target is loaded from
147 // the object pool: 100 // the object pool:
148 // 00: 4d 8b 9f imm32 mov R11, [PP + off] 101 // 0: 41 ff 97 imm32 call [PP + off]
149 // 07: 41 ff d3 call R11 102 // 7: <- return address
150 // 10 <- return address
151 class PoolPointerCall : public ValueObject { 103 class PoolPointerCall : public ValueObject {
152 public: 104 public:
153 explicit PoolPointerCall(uword return_address) 105 explicit PoolPointerCall(uword return_address)
154 : start_(return_address - kCallPatternSize) { 106 : start_(return_address - kCallPatternSize) {
155 ASSERT(IsValid(return_address)); 107 ASSERT(IsValid(return_address));
156 } 108 }
157 109
110 static const int kCallPatternSize = 7;
111
158 static bool IsValid(uword return_address) { 112 static bool IsValid(uword return_address) {
159 uint8_t* code_bytes = 113 uint8_t* code_bytes =
160 reinterpret_cast<uint8_t*>(return_address - kCallPatternSize); 114 reinterpret_cast<uint8_t*>(return_address - kCallPatternSize);
161 return (code_bytes[0] == 0x4D) && (code_bytes[1] == 0x8B) && 115 return (code_bytes[0] == 0x41) && (code_bytes[1] == 0xFF) &&
162 (code_bytes[2] == 0x9F) && 116 (code_bytes[2] == 0x97);
163 (code_bytes[7] == 0x41) && (code_bytes[8] == 0xFF) &&
164 (code_bytes[9] == 0xD3);
165 } 117 }
166 118
167 int32_t pp_offset() const { 119 int32_t pp_offset() const {
168 return *reinterpret_cast<int32_t*>(start_ + 3); 120 return *reinterpret_cast<int32_t*>(start_ + 3);
169 } 121 }
170 122
171 void set_pp_offset(int32_t offset) const { 123 void set_pp_offset(int32_t offset) const {
172 *reinterpret_cast<int32_t*>(start_ + 3) = offset; 124 *reinterpret_cast<int32_t*>(start_ + 3) = offset;
173 CPU::FlushICache(start_, kCallPatternSize); 125 CPU::FlushICache(start_, kCallPatternSize);
174 } 126 }
175 127
128 protected:
129 uword start_;
130
176 private: 131 private:
177 static const int kCallPatternSize = 7 + 3;
178 uword start_;
179 DISALLOW_IMPLICIT_CONSTRUCTORS(PoolPointerCall); 132 DISALLOW_IMPLICIT_CONSTRUCTORS(PoolPointerCall);
180 }; 133 };
181 134
182 135
183 // The expected code pattern of a Dart closure call: 136 // The expected pattern of a dart static call:
184 // 00: 49 ba imm64 mov R10, immediate 2 ; 10 bytes 137 // 0: 41 ff 97 imm32 call [PP + off]
185 // 10: 4d 8b 9f imm32 mov R11, [PP + off] 138 // 7: <- return address
186 // 17: 41 ff d3 call R11 ; 3 bytes 139 class StaticCall : public PoolPointerCall {
187 // 20: <- return_address
188 class ClosureCall : public ValueObject {
189 public: 140 public:
190 explicit ClosureCall(uword return_address) 141 StaticCall(uword return_address, const Code& code)
191 : start_(return_address - kCallPatternSize) { 142 : PoolPointerCall(return_address),
143 object_pool_(Array::Handle(code.ObjectPool())) {
192 ASSERT(IsValid(return_address)); 144 ASSERT(IsValid(return_address));
145 ASSERT(kCallPatternSize == Assembler::kCallExternalLabelSize);
193 } 146 }
194 147
195 static bool IsValid(uword return_address) { 148 uword target() const {
196 uint8_t* code_bytes = 149 intptr_t index = InstructionPattern::IndexFromPPLoad(start_ + 3);
197 reinterpret_cast<uint8_t*>(return_address - kCallPatternSize); 150 return reinterpret_cast<uword>(object_pool_.At(index));
198 return (code_bytes[00] == 0x49) && (code_bytes[01] == 0xBA) &&
199 (code_bytes[10] == 0x4D) && (code_bytes[11] == 0x8B) &&
200 (code_bytes[12] == 0x9F) &&
201 (code_bytes[17] == 0x41) && (code_bytes[18] == 0xFF) &&
202 (code_bytes[19] == 0xD3);
203 } 151 }
204 152
205 RawArray* arguments_descriptor() const { 153 void set_target(uword target) const {
206 return *reinterpret_cast<RawArray**>(start_ + 2); 154 intptr_t index = InstructionPattern::IndexFromPPLoad(start_ + 3);
155 const Smi& smi = Smi::Handle(reinterpret_cast<RawSmi*>(target));
156 object_pool_.SetAt(index, smi);
157 // No need to flush the instruction cache, since the code is not modified.
207 } 158 }
208 159
209 private: 160 private:
210 static const int kCallPatternSize = 10 + 7 + 3; 161 const Array& object_pool_;
211 uword start_; 162 DISALLOW_IMPLICIT_CONSTRUCTORS(StaticCall);
212 DISALLOW_IMPLICIT_CONSTRUCTORS(ClosureCall);
213 }; 163 };
214 164
215 165
216 RawArray* CodePatcher::GetClosureArgDescAt(uword return_address,
217 const Code& code) {
218 ASSERT(code.ContainsInstructionAt(return_address));
219 ClosureCall call(return_address);
220 return call.arguments_descriptor();
221 }
222
223
224 uword CodePatcher::GetStaticCallTargetAt(uword return_address, 166 uword CodePatcher::GetStaticCallTargetAt(uword return_address,
225 const Code& code) { 167 const Code& code) {
226 ASSERT(code.ContainsInstructionAt(return_address)); 168 ASSERT(code.ContainsInstructionAt(return_address));
227 StaticCall call(return_address, code); 169 StaticCall call(return_address, code);
228 return call.target(); 170 return call.target();
229 } 171 }
230 172
231 173
232 void CodePatcher::PatchStaticCallAt(uword return_address, 174 void CodePatcher::PatchStaticCallAt(uword return_address,
233 const Code& code, 175 const Code& code,
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
326 268
327 RawObject* CodePatcher::GetEdgeCounterAt(uword pc, const Code& code) { 269 RawObject* CodePatcher::GetEdgeCounterAt(uword pc, const Code& code) {
328 ASSERT(code.ContainsInstructionAt(pc)); 270 ASSERT(code.ContainsInstructionAt(pc));
329 EdgeCounter counter(pc, code); 271 EdgeCounter counter(pc, code);
330 return counter.edge_counter(); 272 return counter.edge_counter();
331 } 273 }
332 274
333 } // namespace dart 275 } // namespace dart
334 276
335 #endif // defined TARGET_ARCH_X64 277 #endif // defined TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « runtime/vm/code_patcher_mips.cc ('k') | runtime/vm/flow_graph_compiler_x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698