| // Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file | 
 | // for details. All rights reserved. Use of this source code is governed by a | 
 | // BSD-style license that can be found in the LICENSE file. | 
 | // Class for patching compiled code. | 
 |  | 
 | #ifndef RUNTIME_VM_CODE_PATCHER_H_ | 
 | #define RUNTIME_VM_CODE_PATCHER_H_ | 
 |  | 
 | #include "vm/allocation.h" | 
 | #include "vm/native_entry.h" | 
 |  | 
 | namespace dart { | 
 |  | 
 | // Forward declaration. | 
 | class Code; | 
 | class ICData; | 
 |  | 
 | #if defined(TARGET_ARCH_IA32) | 
 | // Stack-allocated class to create a scope where the specified region | 
 | // [address, address + size] has write access enabled. This is used | 
 | // when patching generated code. Access is reset to read-execute in | 
 | // the destructor of this scope. | 
 | // Dual mapping of instructions pages is not supported on these target arch. | 
 | class WritableInstructionsScope : public ValueObject { | 
 |  public: | 
 |   WritableInstructionsScope(uword address, intptr_t size); | 
 |   ~WritableInstructionsScope(); | 
 |  | 
 |  private: | 
 |   const uword address_; | 
 |   const intptr_t size_; | 
 | }; | 
 | #endif  // defined(TARGET_ARCH_IA32) | 
 |  | 
 | class CodePatcher : public AllStatic { | 
 |  public: | 
 |   // Dart static calls have a distinct, machine-dependent code pattern. | 
 |  | 
 |   // Patch static call before return_address in given code to the new target. | 
 |   static void PatchStaticCallAt(uword return_address, | 
 |                                 const Code& code, | 
 |                                 const Code& new_target); | 
 |  | 
 |   // Return the target address of the static call before return_address | 
 |   // in given code. | 
 |   static CodePtr GetStaticCallTargetAt(uword return_address, const Code& code); | 
 |  | 
 |   // Get instance call information. Returns the call target and sets the output | 
 |   // parameter data if non-NULL. | 
 |   static CodePtr GetInstanceCallAt(uword return_address, | 
 |                                    const Code& caller_code, | 
 |                                    Object* data); | 
 |  | 
 |   // Change the state of an instance call by patching the corresponding object | 
 |   // pool entries (non-IA32) or instructions (IA32). | 
 |   static void PatchInstanceCallAt(uword return_address, | 
 |                                   const Code& caller_code, | 
 |                                   const Object& data, | 
 |                                   const Code& target); | 
 |   static void PatchInstanceCallAtWithMutatorsStopped(Thread* thread, | 
 |                                                      uword return_address, | 
 |                                                      const Code& caller_code, | 
 |                                                      const Object& data, | 
 |                                                      const Code& target); | 
 |  | 
 |   // Return target of an unoptimized static call and its ICData object | 
 |   // (calls target via a stub). | 
 |   static FunctionPtr GetUnoptimizedStaticCallAt(uword return_address, | 
 |                                                 const Code& code, | 
 |                                                 ICData* ic_data); | 
 |  | 
 |   static void InsertDeoptimizationCallAt(uword start); | 
 |  | 
 |   static void PatchPoolPointerCallAt(uword return_address, | 
 |                                      const Code& code, | 
 |                                      const Code& new_target); | 
 |  | 
 |   static void PatchSwitchableCallAt(uword return_address, | 
 |                                     const Code& caller_code, | 
 |                                     const Object& data, | 
 |                                     const Code& target); | 
 |   static void PatchSwitchableCallAtWithMutatorsStopped(Thread* thread, | 
 |                                                        uword return_address, | 
 |                                                        const Code& caller_code, | 
 |                                                        const Object& data, | 
 |                                                        const Code& target); | 
 |   static ObjectPtr GetSwitchableCallDataAt(uword return_address, | 
 |                                            const Code& caller_code); | 
 |   static uword GetSwitchableCallTargetEntryAt(uword return_address, | 
 |                                               const Code& caller_code); | 
 |  | 
 |   static CodePtr GetNativeCallAt(uword return_address, | 
 |                                  const Code& caller_code, | 
 |                                  NativeFunction* target); | 
 |  | 
 |   static void PatchNativeCallAt(uword return_address, | 
 |                                 const Code& caller_code, | 
 |                                 NativeFunction target, | 
 |                                 const Code& trampoline); | 
 |  | 
 |   static intptr_t GetSubtypeTestCachePoolIndex(uword return_address); | 
 | }; | 
 |  | 
 | // Beginning from [end - size] we compare [size] bytes with [pattern]. All | 
 | // [0..255] values in [pattern] have to match, negative values are skipped. | 
 | // | 
 | // Example pattern: `[0x3d, 0x8b, -1, -1]`. | 
 | bool MatchesPattern(uword end, const int16_t* pattern, intptr_t size); | 
 |  | 
 | }  // namespace dart | 
 |  | 
 | #endif  // RUNTIME_VM_CODE_PATCHER_H_ |