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

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

Issue 1192103004: VM: New calling convention for generated code. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 6 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
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
20 static bool MatchesPattern(uword addr, int16_t* pattern, intptr_t size) {
21 uint8_t* bytes = reinterpret_cast<uint8_t*>(addr);
22 for (intptr_t i = 0; i < size; i++) {
23 int16_t val = pattern[i];
24 if ((val >= 0) && (val != bytes[i])) {
25 return false;
26 }
27 }
28 return true;
29 }
30
31
19 // The expected pattern of a Dart unoptimized call (static and instance): 32 // The expected pattern of a Dart unoptimized call (static and instance):
20 // 0: 49 8b 9f imm32 mov RBX, [PP + off] 33 // 0: 49 8b 9f imm32 mov RBX, [PP + off]
21 // 7: 41 ff 97 imm32 call [PP + off] 34 // 7: 41 ff 97 imm32 call [PP + off]
srdjan 2015/06/18 21:29:47 You may need to update this comment.
Florian Schneider 2015/06/29 14:50:24 Done.
22 // 14 <- return address 35 // 14 <- return address
23 class UnoptimizedCall : public ValueObject { 36 class UnoptimizedCall : public ValueObject {
24 public: 37 public:
25 UnoptimizedCall(uword return_address, const Code& code) 38 UnoptimizedCall(uword return_address, const Code& code)
26 : start_(return_address - kCallPatternSize), 39 : start_(return_address - kCallPatternSize),
27 object_pool_(ObjectPool::Handle(code.GetObjectPool())) { 40 object_pool_(ObjectPool::Handle(code.GetObjectPool())) {
28 ASSERT(IsValid(return_address));
29 ASSERT((kCallPatternSize - 7) == Assembler::kCallExternalLabelSize); 41 ASSERT((kCallPatternSize - 7) == Assembler::kCallExternalLabelSize);
42 ASSERT(IsValid());
30 } 43 }
31 44
32 static const int kCallPatternSize = 14; 45 static const int kCallPatternSize = 26;
33 46
34 static bool IsValid(uword return_address) { 47 bool IsValid() const {
35 uint8_t* code_bytes = 48 static int16_t pattern[kCallPatternSize] = {
36 reinterpret_cast<uint8_t*>(return_address - kCallPatternSize); 49 0x49, 0x8b, 0x9f, -1, -1, -1, -1, // movq RBX, [PP + offs]
37 return (code_bytes[0] == 0x49) && (code_bytes[1] == 0x8B) && 50 0x4d, 0x8b, 0xa7, -1, -1, -1, -1, // movq CR, [PP + offs]
38 (code_bytes[2] == 0x9F) && 51 0x4d, 0x8b, 0x5c, 0x24, 0x07, // movq TMP, [CR + insns_offs]
39 (code_bytes[7] == 0x41) && (code_bytes[8] == 0xFF) && 52 0x49, 0x83, 0xc3, 0x1f, // addq TMP, entry_offs
40 (code_bytes[9] == 0x97); 53 0x41, 0xff, 0xd3 // callq TMP
54 };
55 return MatchesPattern(start_, pattern, kCallPatternSize);
41 } 56 }
42 57
43 RawObject* ic_data() const { 58 RawObject* ic_data() const {
44 intptr_t index = InstructionPattern::IndexFromPPLoad(start_ + 3); 59 intptr_t index = InstructionPattern::IndexFromPPLoad(start_ + 3);
45 return object_pool_.ObjectAt(index); 60 return object_pool_.ObjectAt(index);
46 } 61 }
47 62
48 uword target() const { 63 RawCode* target() const {
49 intptr_t index = InstructionPattern::IndexFromPPLoad(start_ + 10); 64 intptr_t index = InstructionPattern::IndexFromPPLoad(start_ + 10);
50 return object_pool_.RawValueAt(index); 65 Code& code = Code::Handle();
66 code ^= object_pool_.ObjectAt(index);
67 return code.raw();
51 } 68 }
52 69
53 void set_target(uword target) const { 70 void set_target(const Code& target) const {
54 intptr_t index = InstructionPattern::IndexFromPPLoad(start_ + 10); 71 intptr_t index = InstructionPattern::IndexFromPPLoad(start_ + 10);
55 object_pool_.SetRawValueAt(index, target); 72 object_pool_.SetObjectAt(index, target);
56 // No need to flush the instruction cache, since the code is not modified. 73 // No need to flush the instruction cache, since the code is not modified.
57 } 74 }
58 75
59 private: 76 private:
60 uword start_; 77 uword start_;
61 const ObjectPool& object_pool_; 78 const ObjectPool& object_pool_;
62 DISALLOW_IMPLICIT_CONSTRUCTORS(UnoptimizedCall); 79 DISALLOW_IMPLICIT_CONSTRUCTORS(UnoptimizedCall);
63 }; 80 };
64 81
65 82
(...skipping 24 matching lines...) Expand all
90 #endif // DEBUG 107 #endif // DEBUG
91 } 108 }
92 109
93 private: 110 private:
94 DISALLOW_IMPLICIT_CONSTRUCTORS(UnoptimizedStaticCall); 111 DISALLOW_IMPLICIT_CONSTRUCTORS(UnoptimizedStaticCall);
95 }; 112 };
96 113
97 114
98 // The expected pattern of a call where the target is loaded from 115 // The expected pattern of a call where the target is loaded from
99 // the object pool: 116 // the object pool:
100 // 0: 41 ff 97 imm32 call [PP + off] 117 // 0: 4d 8b a7 imm32 movq CR, [PP + offs]
101 // 7: <- return address 118 // 7: 4d 8b 5c 24 07 movq TMP, [CR + insns_offs]
119 // 12: 49 83 c3 1f addq TMP, entry_offs
120 // 16: 41 ff d3 callq TMP
121 // 19: <- return address
102 class PoolPointerCall : public ValueObject { 122 class PoolPointerCall : public ValueObject {
103 public: 123 public:
104 explicit PoolPointerCall(uword return_address, const Code& code) 124 explicit PoolPointerCall(uword return_address, const Code& code)
105 : start_(return_address - kCallPatternSize), 125 : start_(return_address - kCallPatternSize),
106 object_pool_(ObjectPool::Handle(code.GetObjectPool())) { 126 object_pool_(ObjectPool::Handle(code.GetObjectPool())) {
107 ASSERT(IsValid(return_address)); 127 ASSERT(IsValid());
108 } 128 }
109 129
110 static const int kCallPatternSize = 7; 130 static const int kCallPatternSize = 19;
111 131
112 static bool IsValid(uword return_address) { 132 bool IsValid() const {
113 uint8_t* code_bytes = 133 static int16_t pattern[kCallPatternSize] = {
114 reinterpret_cast<uint8_t*>(return_address - kCallPatternSize); 134 0x4d, 0x8b, 0xa7, -1, -1, -1, -1, // movq CR, [PP + offs]
115 return (code_bytes[0] == 0x41) && (code_bytes[1] == 0xFF) && 135 0x4d, 0x8b, 0x5c, 0x24, 0x07, // movq TMP, [CR + insns_offs]
116 (code_bytes[2] == 0x97); 136 0x49, 0x83, 0xc3, 0x1f, // addq TMP, entry_offs
137 0x41, 0xff, 0xd3 // callq TMP
138 };
139 return MatchesPattern(start_, pattern, kCallPatternSize);
117 } 140 }
118 141
119 intptr_t pp_index() const { 142 intptr_t pp_index() const {
120 return InstructionPattern::IndexFromPPLoad(start_ + 3); 143 return InstructionPattern::IndexFromPPLoad(start_ + 3);
121 } 144 }
122 145
123 uword Target() const { 146 RawCode* Target() const {
124 return object_pool_.RawValueAt(pp_index()); 147 Code& code = Code::Handle();
148 code ^= object_pool_.ObjectAt(pp_index());
149 return code.raw();
125 } 150 }
126 151
127 void SetTarget(uword target) const { 152 void SetTarget(const Code& target) const {
128 object_pool_.SetRawValueAt(pp_index(), target); 153 object_pool_.SetObjectAt(pp_index(), target);
129 // No need to flush the instruction cache, since the code is not modified. 154 // No need to flush the instruction cache, since the code is not modified.
130 } 155 }
131 156
132 protected: 157 protected:
133 uword start_; 158 uword start_;
134 const ObjectPool& object_pool_; 159 const ObjectPool& object_pool_;
135 160
136 private: 161 private:
137 DISALLOW_IMPLICIT_CONSTRUCTORS(PoolPointerCall); 162 DISALLOW_IMPLICIT_CONSTRUCTORS(PoolPointerCall);
138 }; 163 };
139 164
140 165
141 uword CodePatcher::GetStaticCallTargetAt(uword return_address, 166 RawCode* CodePatcher::GetStaticCallTargetAt(uword return_address,
142 const Code& code) { 167 const Code& code) {
143 ASSERT(code.ContainsInstructionAt(return_address)); 168 ASSERT(code.ContainsInstructionAt(return_address));
144 PoolPointerCall call(return_address, code); 169 PoolPointerCall call(return_address, code);
145 return call.Target(); 170 return call.Target();
146 } 171 }
147 172
148 173
149 void CodePatcher::PatchStaticCallAt(uword return_address, 174 void CodePatcher::PatchStaticCallAt(uword return_address,
150 const Code& code, 175 const Code& code,
151 uword new_target) { 176 const Code& new_target) {
152 PatchPoolPointerCallAt(return_address, code, new_target); 177 PatchPoolPointerCallAt(return_address, code, new_target);
153 } 178 }
154 179
155 180
156 void CodePatcher::PatchPoolPointerCallAt(uword return_address, 181 void CodePatcher::PatchPoolPointerCallAt(uword return_address,
157 const Code& code, 182 const Code& code,
158 uword new_target) { 183 const Code& new_target) {
159 ASSERT(code.ContainsInstructionAt(return_address)); 184 ASSERT(code.ContainsInstructionAt(return_address));
160 PoolPointerCall call(return_address, code); 185 PoolPointerCall call(return_address, code);
161 call.SetTarget(new_target); 186 call.SetTarget(new_target);
162 } 187 }
163 188
164 189
165 void CodePatcher::PatchInstanceCallAt(uword return_address, 190 void CodePatcher::PatchInstanceCallAt(uword return_address,
166 const Code& code, 191 const Code& code,
167 uword new_target) { 192 const Code& new_target) {
168 ASSERT(code.ContainsInstructionAt(return_address)); 193 ASSERT(code.ContainsInstructionAt(return_address));
169 InstanceCall call(return_address, code); 194 InstanceCall call(return_address, code);
170 call.set_target(new_target); 195 call.set_target(new_target);
171 } 196 }
172 197
173 198
174 uword CodePatcher::GetInstanceCallAt(uword return_address, 199 RawCode* CodePatcher::GetInstanceCallAt(uword return_address,
175 const Code& code, 200 const Code& code,
176 ICData* ic_data) { 201 ICData* ic_data) {
177 ASSERT(code.ContainsInstructionAt(return_address)); 202 ASSERT(code.ContainsInstructionAt(return_address));
178 InstanceCall call(return_address, code); 203 InstanceCall call(return_address, code);
179 if (ic_data != NULL) { 204 if (ic_data != NULL) {
180 *ic_data ^= call.ic_data(); 205 *ic_data ^= call.ic_data();
181 } 206 }
182 return call.target(); 207 return call.target();
183 } 208 }
184 209
185 210
186 intptr_t CodePatcher::InstanceCallSizeInBytes() { 211 intptr_t CodePatcher::InstanceCallSizeInBytes() {
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
238 263
239 RawObject* CodePatcher::GetEdgeCounterAt(uword pc, const Code& code) { 264 RawObject* CodePatcher::GetEdgeCounterAt(uword pc, const Code& code) {
240 ASSERT(code.ContainsInstructionAt(pc)); 265 ASSERT(code.ContainsInstructionAt(pc));
241 EdgeCounter counter(pc, code); 266 EdgeCounter counter(pc, code);
242 return counter.edge_counter(); 267 return counter.edge_counter();
243 } 268 }
244 269
245 } // namespace dart 270 } // namespace dart
246 271
247 #endif // defined TARGET_ARCH_X64 272 #endif // defined TARGET_ARCH_X64
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698