OLD | NEW |
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 // 0: 49 8b 9f imm32 mov RBX, [PP + off] | 20 // 0: 49 8b 9f imm32 mov RBX, [PP + off] |
21 // 7: 41 ff 97 imm32 call [PP + off] | 21 // 7: 41 ff 97 imm32 call [PP + off] |
22 // 14 <- return address | 22 // 14 <- return address |
23 class UnoptimizedCall : public ValueObject { | 23 class UnoptimizedCall : public ValueObject { |
24 public: | 24 public: |
25 UnoptimizedCall(uword return_address, const Code& code) | 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 object_pool_(ObjectPool::Handle(code.GetObjectPool())) { |
28 ASSERT(IsValid(return_address)); | 28 ASSERT(IsValid(return_address)); |
29 ASSERT((kCallPatternSize - 7) == Assembler::kCallExternalLabelSize); | 29 ASSERT((kCallPatternSize - 7) == Assembler::kCallExternalLabelSize); |
30 } | 30 } |
31 | 31 |
32 static const int kCallPatternSize = 14; | 32 static const int kCallPatternSize = 14; |
33 | 33 |
34 static bool IsValid(uword return_address) { | 34 static bool IsValid(uword return_address) { |
35 uint8_t* code_bytes = | 35 uint8_t* code_bytes = |
36 reinterpret_cast<uint8_t*>(return_address - kCallPatternSize); | 36 reinterpret_cast<uint8_t*>(return_address - kCallPatternSize); |
37 return (code_bytes[0] == 0x49) && (code_bytes[1] == 0x8B) && | 37 return (code_bytes[0] == 0x49) && (code_bytes[1] == 0x8B) && |
38 (code_bytes[2] == 0x9F) && | 38 (code_bytes[2] == 0x9F) && |
39 (code_bytes[7] == 0x41) && (code_bytes[8] == 0xFF) && | 39 (code_bytes[7] == 0x41) && (code_bytes[8] == 0xFF) && |
40 (code_bytes[9] == 0x97); | 40 (code_bytes[9] == 0x97); |
41 } | 41 } |
42 | 42 |
43 RawObject* ic_data() const { | 43 RawObject* ic_data() const { |
44 intptr_t index = InstructionPattern::IndexFromPPLoad(start_ + 3); | 44 intptr_t index = InstructionPattern::IndexFromPPLoad(start_ + 3); |
45 return object_pool_.At(index); | 45 return object_pool_.ObjectAt(index); |
46 } | 46 } |
47 | 47 |
48 uword target() const { | 48 uword target() const { |
49 intptr_t index = InstructionPattern::IndexFromPPLoad(start_ + 10); | 49 intptr_t index = InstructionPattern::IndexFromPPLoad(start_ + 10); |
50 return reinterpret_cast<uword>(object_pool_.At(index)); | 50 return object_pool_.RawValueAt(index); |
51 } | 51 } |
52 | 52 |
53 void set_target(uword target) const { | 53 void set_target(uword target) const { |
54 intptr_t index = InstructionPattern::IndexFromPPLoad(start_ + 10); | 54 intptr_t index = InstructionPattern::IndexFromPPLoad(start_ + 10); |
55 const Smi& smi = Smi::Handle(reinterpret_cast<RawSmi*>(target)); | 55 object_pool_.SetRawValueAt(index, target); |
56 object_pool_.SetAt(index, smi); | |
57 // No need to flush the instruction cache, since the code is not modified. | 56 // No need to flush the instruction cache, since the code is not modified. |
58 } | 57 } |
59 | 58 |
60 private: | 59 private: |
61 uword start_; | 60 uword start_; |
62 const Array& object_pool_; | 61 const ObjectPool& object_pool_; |
63 DISALLOW_IMPLICIT_CONSTRUCTORS(UnoptimizedCall); | 62 DISALLOW_IMPLICIT_CONSTRUCTORS(UnoptimizedCall); |
64 }; | 63 }; |
65 | 64 |
66 | 65 |
67 class InstanceCall : public UnoptimizedCall { | 66 class InstanceCall : public UnoptimizedCall { |
68 public: | 67 public: |
69 InstanceCall(uword return_address, const Code& code) | 68 InstanceCall(uword return_address, const Code& code) |
70 : UnoptimizedCall(return_address, code) { | 69 : UnoptimizedCall(return_address, code) { |
71 #if defined(DEBUG) | 70 #if defined(DEBUG) |
72 ICData& test_ic_data = ICData::Handle(); | 71 ICData& test_ic_data = ICData::Handle(); |
(...skipping 24 matching lines...) Expand all Loading... |
97 | 96 |
98 | 97 |
99 // The expected pattern of a call where the target is loaded from | 98 // The expected pattern of a call where the target is loaded from |
100 // the object pool: | 99 // the object pool: |
101 // 0: 41 ff 97 imm32 call [PP + off] | 100 // 0: 41 ff 97 imm32 call [PP + off] |
102 // 7: <- return address | 101 // 7: <- return address |
103 class PoolPointerCall : public ValueObject { | 102 class PoolPointerCall : public ValueObject { |
104 public: | 103 public: |
105 explicit PoolPointerCall(uword return_address, const Code& code) | 104 explicit PoolPointerCall(uword return_address, const Code& code) |
106 : start_(return_address - kCallPatternSize), | 105 : start_(return_address - kCallPatternSize), |
107 object_pool_(Array::Handle(code.ObjectPool())) { | 106 object_pool_(ObjectPool::Handle(code.GetObjectPool())) { |
108 ASSERT(IsValid(return_address)); | 107 ASSERT(IsValid(return_address)); |
109 } | 108 } |
110 | 109 |
111 static const int kCallPatternSize = 7; | 110 static const int kCallPatternSize = 7; |
112 | 111 |
113 static bool IsValid(uword return_address) { | 112 static bool IsValid(uword return_address) { |
114 uint8_t* code_bytes = | 113 uint8_t* code_bytes = |
115 reinterpret_cast<uint8_t*>(return_address - kCallPatternSize); | 114 reinterpret_cast<uint8_t*>(return_address - kCallPatternSize); |
116 return (code_bytes[0] == 0x41) && (code_bytes[1] == 0xFF) && | 115 return (code_bytes[0] == 0x41) && (code_bytes[1] == 0xFF) && |
117 (code_bytes[2] == 0x97); | 116 (code_bytes[2] == 0x97); |
118 } | 117 } |
119 | 118 |
120 intptr_t pp_index() const { | 119 intptr_t pp_index() const { |
121 return InstructionPattern::IndexFromPPLoad(start_ + 3); | 120 return InstructionPattern::IndexFromPPLoad(start_ + 3); |
122 } | 121 } |
123 | 122 |
124 uword Target() const { | 123 uword Target() const { |
125 return reinterpret_cast<uword>(object_pool_.At(pp_index())); | 124 return reinterpret_cast<uword>(object_pool_.RawValueAt(pp_index())); |
126 } | 125 } |
127 | 126 |
128 void SetTarget(uword target) const { | 127 void SetTarget(uword target) const { |
129 const Smi& smi = Smi::Handle(reinterpret_cast<RawSmi*>(target)); | 128 object_pool_.SetRawValueAt(pp_index(), target); |
130 object_pool_.SetAt(pp_index(), smi); | |
131 // No need to flush the instruction cache, since the code is not modified. | 129 // No need to flush the instruction cache, since the code is not modified. |
132 } | 130 } |
133 | 131 |
134 protected: | 132 protected: |
135 uword start_; | 133 uword start_; |
136 const Array& object_pool_; | 134 const ObjectPool& object_pool_; |
137 | 135 |
138 private: | 136 private: |
139 DISALLOW_IMPLICIT_CONSTRUCTORS(PoolPointerCall); | 137 DISALLOW_IMPLICIT_CONSTRUCTORS(PoolPointerCall); |
140 }; | 138 }; |
141 | 139 |
142 | 140 |
143 uword CodePatcher::GetStaticCallTargetAt(uword return_address, | 141 uword CodePatcher::GetStaticCallTargetAt(uword return_address, |
144 const Code& code) { | 142 const Code& code) { |
145 ASSERT(code.ContainsInstructionAt(return_address)); | 143 ASSERT(code.ContainsInstructionAt(return_address)); |
146 PoolPointerCall call(return_address, code); | 144 PoolPointerCall call(return_address, code); |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
212 return ic_data.GetTargetAt(0); | 210 return ic_data.GetTargetAt(0); |
213 } | 211 } |
214 | 212 |
215 | 213 |
216 // The expected code pattern of an edge counter in unoptimized code: | 214 // The expected code pattern of an edge counter in unoptimized code: |
217 // 49 8b 87 imm32 mov RAX, [PP + offset] | 215 // 49 8b 87 imm32 mov RAX, [PP + offset] |
218 class EdgeCounter : public ValueObject { | 216 class EdgeCounter : public ValueObject { |
219 public: | 217 public: |
220 EdgeCounter(uword pc, const Code& code) | 218 EdgeCounter(uword pc, const Code& code) |
221 : end_(pc - FlowGraphCompiler::EdgeCounterIncrementSizeInBytes()), | 219 : end_(pc - FlowGraphCompiler::EdgeCounterIncrementSizeInBytes()), |
222 object_pool_(Array::Handle(code.ObjectPool())) { | 220 object_pool_(ObjectPool::Handle(code.GetObjectPool())) { |
223 ASSERT(IsValid(end_)); | 221 ASSERT(IsValid(end_)); |
224 } | 222 } |
225 | 223 |
226 static bool IsValid(uword end) { | 224 static bool IsValid(uword end) { |
227 uint8_t* bytes = reinterpret_cast<uint8_t*>(end - 7); | 225 uint8_t* bytes = reinterpret_cast<uint8_t*>(end - 7); |
228 return (bytes[0] == 0x49) && (bytes[1] == 0x8b) && (bytes[2] == 0x87); | 226 return (bytes[0] == 0x49) && (bytes[1] == 0x8b) && (bytes[2] == 0x87); |
229 } | 227 } |
230 | 228 |
231 RawObject* edge_counter() const { | 229 RawObject* edge_counter() const { |
232 return object_pool_.At(InstructionPattern::IndexFromPPLoad(end_ - 4)); | 230 return object_pool_.ObjectAt(InstructionPattern::IndexFromPPLoad(end_ - 4)); |
233 } | 231 } |
234 | 232 |
235 private: | 233 private: |
236 uword end_; | 234 uword end_; |
237 const Array& object_pool_; | 235 const ObjectPool& object_pool_; |
238 }; | 236 }; |
239 | 237 |
240 | 238 |
241 RawObject* CodePatcher::GetEdgeCounterAt(uword pc, const Code& code) { | 239 RawObject* CodePatcher::GetEdgeCounterAt(uword pc, const Code& code) { |
242 ASSERT(code.ContainsInstructionAt(pc)); | 240 ASSERT(code.ContainsInstructionAt(pc)); |
243 EdgeCounter counter(pc, code); | 241 EdgeCounter counter(pc, code); |
244 return counter.edge_counter(); | 242 return counter.edge_counter(); |
245 } | 243 } |
246 | 244 |
247 } // namespace dart | 245 } // namespace dart |
248 | 246 |
249 #endif // defined TARGET_ARCH_X64 | 247 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |