| 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_IA32. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32. |
| 6 #if defined(TARGET_ARCH_IA32) | 6 #if defined(TARGET_ARCH_IA32) |
| 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" |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 48 | 48 |
| 49 uword call_address() const { return start_ + 2 * kMovInstructionSize; } | 49 uword call_address() const { return start_ + 2 * kMovInstructionSize; } |
| 50 | 50 |
| 51 protected: | 51 protected: |
| 52 uword start_; | 52 uword start_; |
| 53 | 53 |
| 54 private: | 54 private: |
| 55 DISALLOW_IMPLICIT_CONSTRUCTORS(UnoptimizedCall); | 55 DISALLOW_IMPLICIT_CONSTRUCTORS(UnoptimizedCall); |
| 56 }; | 56 }; |
| 57 | 57 |
| 58 | |
| 59 class NativeCall : public UnoptimizedCall { | 58 class NativeCall : public UnoptimizedCall { |
| 60 public: | 59 public: |
| 61 explicit NativeCall(uword return_address) : UnoptimizedCall(return_address) {} | 60 explicit NativeCall(uword return_address) : UnoptimizedCall(return_address) {} |
| 62 | 61 |
| 63 NativeFunction native_function() const { | 62 NativeFunction native_function() const { |
| 64 return *reinterpret_cast<NativeFunction*>(start_ + 1); | 63 return *reinterpret_cast<NativeFunction*>(start_ + 1); |
| 65 } | 64 } |
| 66 | 65 |
| 67 void set_native_function(NativeFunction func) const { | 66 void set_native_function(NativeFunction func) const { |
| 68 WritableInstructionsScope writable(start_ + 1, sizeof(func)); | 67 WritableInstructionsScope writable(start_ + 1, sizeof(func)); |
| 69 *reinterpret_cast<NativeFunction*>(start_ + 1) = func; | 68 *reinterpret_cast<NativeFunction*>(start_ + 1) = func; |
| 70 } | 69 } |
| 71 | 70 |
| 72 private: | 71 private: |
| 73 DISALLOW_IMPLICIT_CONSTRUCTORS(NativeCall); | 72 DISALLOW_IMPLICIT_CONSTRUCTORS(NativeCall); |
| 74 }; | 73 }; |
| 75 | 74 |
| 76 | |
| 77 class InstanceCall : public UnoptimizedCall { | 75 class InstanceCall : public UnoptimizedCall { |
| 78 public: | 76 public: |
| 79 explicit InstanceCall(uword return_address) | 77 explicit InstanceCall(uword return_address) |
| 80 : UnoptimizedCall(return_address) { | 78 : UnoptimizedCall(return_address) { |
| 81 #if defined(DEBUG) | 79 #if defined(DEBUG) |
| 82 ICData& test_ic_data = ICData::Handle(); | 80 ICData& test_ic_data = ICData::Handle(); |
| 83 test_ic_data ^= ic_data(); | 81 test_ic_data ^= ic_data(); |
| 84 ASSERT(test_ic_data.NumArgsTested() > 0); | 82 ASSERT(test_ic_data.NumArgsTested() > 0); |
| 85 #endif // DEBUG | 83 #endif // DEBUG |
| 86 } | 84 } |
| 87 | 85 |
| 88 private: | 86 private: |
| 89 DISALLOW_IMPLICIT_CONSTRUCTORS(InstanceCall); | 87 DISALLOW_IMPLICIT_CONSTRUCTORS(InstanceCall); |
| 90 }; | 88 }; |
| 91 | 89 |
| 92 | |
| 93 class UnoptimizedStaticCall : public UnoptimizedCall { | 90 class UnoptimizedStaticCall : public UnoptimizedCall { |
| 94 public: | 91 public: |
| 95 explicit UnoptimizedStaticCall(uword return_address) | 92 explicit UnoptimizedStaticCall(uword return_address) |
| 96 : UnoptimizedCall(return_address) { | 93 : UnoptimizedCall(return_address) { |
| 97 #if defined(DEBUG) | 94 #if defined(DEBUG) |
| 98 ICData& test_ic_data = ICData::Handle(); | 95 ICData& test_ic_data = ICData::Handle(); |
| 99 test_ic_data ^= ic_data(); | 96 test_ic_data ^= ic_data(); |
| 100 ASSERT(test_ic_data.NumArgsTested() >= 0); | 97 ASSERT(test_ic_data.NumArgsTested() >= 0); |
| 101 #endif // DEBUG | 98 #endif // DEBUG |
| 102 } | 99 } |
| 103 | 100 |
| 104 private: | 101 private: |
| 105 DISALLOW_IMPLICIT_CONSTRUCTORS(UnoptimizedStaticCall); | 102 DISALLOW_IMPLICIT_CONSTRUCTORS(UnoptimizedStaticCall); |
| 106 }; | 103 }; |
| 107 | 104 |
| 108 | |
| 109 // The expected pattern of a dart static call: | 105 // The expected pattern of a dart static call: |
| 110 // mov EDX, arguments_descriptor_array (optional in polymorphic calls) | 106 // mov EDX, arguments_descriptor_array (optional in polymorphic calls) |
| 111 // mov EDI, Immediate(code_object) | 107 // mov EDI, Immediate(code_object) |
| 112 // call [EDI + entry_point_offset] | 108 // call [EDI + entry_point_offset] |
| 113 // <- return address | 109 // <- return address |
| 114 class StaticCall : public ValueObject { | 110 class StaticCall : public ValueObject { |
| 115 public: | 111 public: |
| 116 explicit StaticCall(uword return_address) | 112 explicit StaticCall(uword return_address) |
| 117 : start_(return_address - (kMovInstructionSize + kCallInstructionSize)) { | 113 : start_(return_address - (kMovInstructionSize + kCallInstructionSize)) { |
| 118 ASSERT(IsValid()); | 114 ASSERT(IsValid()); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 143 return start_ + kMovInstructionSize + kCallInstructionSize; | 139 return start_ + kMovInstructionSize + kCallInstructionSize; |
| 144 } | 140 } |
| 145 | 141 |
| 146 uword call_address() const { return start_ + kMovInstructionSize; } | 142 uword call_address() const { return start_ + kMovInstructionSize; } |
| 147 | 143 |
| 148 uword start_; | 144 uword start_; |
| 149 | 145 |
| 150 DISALLOW_IMPLICIT_CONSTRUCTORS(StaticCall); | 146 DISALLOW_IMPLICIT_CONSTRUCTORS(StaticCall); |
| 151 }; | 147 }; |
| 152 | 148 |
| 153 | |
| 154 RawCode* CodePatcher::GetStaticCallTargetAt(uword return_address, | 149 RawCode* CodePatcher::GetStaticCallTargetAt(uword return_address, |
| 155 const Code& code) { | 150 const Code& code) { |
| 156 ASSERT(code.ContainsInstructionAt(return_address)); | 151 ASSERT(code.ContainsInstructionAt(return_address)); |
| 157 StaticCall call(return_address); | 152 StaticCall call(return_address); |
| 158 return call.target(); | 153 return call.target(); |
| 159 } | 154 } |
| 160 | 155 |
| 161 | |
| 162 void CodePatcher::PatchStaticCallAt(uword return_address, | 156 void CodePatcher::PatchStaticCallAt(uword return_address, |
| 163 const Code& code, | 157 const Code& code, |
| 164 const Code& new_target) { | 158 const Code& new_target) { |
| 165 const Instructions& instrs = Instructions::Handle(code.instructions()); | 159 const Instructions& instrs = Instructions::Handle(code.instructions()); |
| 166 WritableInstructionsScope writable(instrs.PayloadStart(), instrs.Size()); | 160 WritableInstructionsScope writable(instrs.PayloadStart(), instrs.Size()); |
| 167 ASSERT(code.ContainsInstructionAt(return_address)); | 161 ASSERT(code.ContainsInstructionAt(return_address)); |
| 168 StaticCall call(return_address); | 162 StaticCall call(return_address); |
| 169 call.set_target(new_target); | 163 call.set_target(new_target); |
| 170 } | 164 } |
| 171 | 165 |
| 172 | |
| 173 void CodePatcher::InsertDeoptimizationCallAt(uword start) { | 166 void CodePatcher::InsertDeoptimizationCallAt(uword start) { |
| 174 UNREACHABLE(); | 167 UNREACHABLE(); |
| 175 } | 168 } |
| 176 | 169 |
| 177 | |
| 178 RawCode* CodePatcher::GetInstanceCallAt(uword return_address, | 170 RawCode* CodePatcher::GetInstanceCallAt(uword return_address, |
| 179 const Code& code, | 171 const Code& code, |
| 180 ICData* ic_data) { | 172 ICData* ic_data) { |
| 181 ASSERT(code.ContainsInstructionAt(return_address)); | 173 ASSERT(code.ContainsInstructionAt(return_address)); |
| 182 InstanceCall call(return_address); | 174 InstanceCall call(return_address); |
| 183 if (ic_data != NULL) { | 175 if (ic_data != NULL) { |
| 184 *ic_data ^= call.ic_data(); | 176 *ic_data ^= call.ic_data(); |
| 185 } | 177 } |
| 186 return Code::null(); | 178 return Code::null(); |
| 187 } | 179 } |
| 188 | 180 |
| 189 | |
| 190 RawFunction* CodePatcher::GetUnoptimizedStaticCallAt(uword return_address, | 181 RawFunction* CodePatcher::GetUnoptimizedStaticCallAt(uword return_address, |
| 191 const Code& code, | 182 const Code& code, |
| 192 ICData* ic_data_result) { | 183 ICData* ic_data_result) { |
| 193 ASSERT(code.ContainsInstructionAt(return_address)); | 184 ASSERT(code.ContainsInstructionAt(return_address)); |
| 194 UnoptimizedStaticCall static_call(return_address); | 185 UnoptimizedStaticCall static_call(return_address); |
| 195 ICData& ic_data = ICData::Handle(); | 186 ICData& ic_data = ICData::Handle(); |
| 196 ic_data ^= static_call.ic_data(); | 187 ic_data ^= static_call.ic_data(); |
| 197 if (ic_data_result != NULL) { | 188 if (ic_data_result != NULL) { |
| 198 *ic_data_result = ic_data.raw(); | 189 *ic_data_result = ic_data.raw(); |
| 199 } | 190 } |
| 200 return ic_data.GetTargetAt(0); | 191 return ic_data.GetTargetAt(0); |
| 201 } | 192 } |
| 202 | 193 |
| 203 | |
| 204 void CodePatcher::PatchSwitchableCallAt(uword return_address, | 194 void CodePatcher::PatchSwitchableCallAt(uword return_address, |
| 205 const Code& caller_code, | 195 const Code& caller_code, |
| 206 const Object& data, | 196 const Object& data, |
| 207 const Code& target) { | 197 const Code& target) { |
| 208 // Switchable instance calls only generated for precompilation. | 198 // Switchable instance calls only generated for precompilation. |
| 209 UNREACHABLE(); | 199 UNREACHABLE(); |
| 210 } | 200 } |
| 211 | 201 |
| 212 | |
| 213 RawCode* CodePatcher::GetSwitchableCallTargetAt(uword return_address, | 202 RawCode* CodePatcher::GetSwitchableCallTargetAt(uword return_address, |
| 214 const Code& caller_code) { | 203 const Code& caller_code) { |
| 215 // Switchable instance calls only generated for precompilation. | 204 // Switchable instance calls only generated for precompilation. |
| 216 UNREACHABLE(); | 205 UNREACHABLE(); |
| 217 return Code::null(); | 206 return Code::null(); |
| 218 } | 207 } |
| 219 | 208 |
| 220 | |
| 221 RawObject* CodePatcher::GetSwitchableCallDataAt(uword return_address, | 209 RawObject* CodePatcher::GetSwitchableCallDataAt(uword return_address, |
| 222 const Code& caller_code) { | 210 const Code& caller_code) { |
| 223 // Switchable instance calls only generated for precompilation. | 211 // Switchable instance calls only generated for precompilation. |
| 224 UNREACHABLE(); | 212 UNREACHABLE(); |
| 225 return Object::null(); | 213 return Object::null(); |
| 226 } | 214 } |
| 227 | 215 |
| 228 | |
| 229 void CodePatcher::PatchNativeCallAt(uword return_address, | 216 void CodePatcher::PatchNativeCallAt(uword return_address, |
| 230 const Code& code, | 217 const Code& code, |
| 231 NativeFunction target, | 218 NativeFunction target, |
| 232 const Code& trampoline) { | 219 const Code& trampoline) { |
| 233 UNREACHABLE(); | 220 UNREACHABLE(); |
| 234 } | 221 } |
| 235 | 222 |
| 236 | |
| 237 RawCode* CodePatcher::GetNativeCallAt(uword return_address, | 223 RawCode* CodePatcher::GetNativeCallAt(uword return_address, |
| 238 const Code& code, | 224 const Code& code, |
| 239 NativeFunction* target) { | 225 NativeFunction* target) { |
| 240 UNREACHABLE(); | 226 UNREACHABLE(); |
| 241 return NULL; | 227 return NULL; |
| 242 } | 228 } |
| 243 | 229 |
| 244 | |
| 245 intptr_t CodePatcher::InstanceCallSizeInBytes() { | 230 intptr_t CodePatcher::InstanceCallSizeInBytes() { |
| 246 return InstanceCall::kPatternSize; | 231 return InstanceCall::kPatternSize; |
| 247 } | 232 } |
| 248 | 233 |
| 249 } // namespace dart | 234 } // namespace dart |
| 250 | 235 |
| 251 #endif // defined TARGET_ARCH_IA32 | 236 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |