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
3// BSD-style license that can be found in the LICENSE file.
4
5#include "vm/globals.h" // Needed here to get TARGET_ARCH_X64.
6#if defined(TARGET_ARCH_X64)
7
8#include "platform/unaligned.h"
9
10#include "vm/code_patcher.h"
11#include "vm/instructions.h"
12#include "vm/instructions_x64.h"
13
14#include "vm/constants.h"
15#include "vm/cpu.h"
16#include "vm/object.h"
17
18namespace dart {
19
20// [start] is the address of a displacement inside a load instruction
21intptr_t IndexFromPPLoadDisp8(uword start) {
22 int8_t offset = *reinterpret_cast<int8_t*>(start);
23 return ObjectPool::IndexFromOffset(offset);
24}
25
26intptr_t IndexFromPPLoadDisp32(uword start) {
27 int32_t offset = LoadUnaligned(reinterpret_cast<int32_t*>(start));
28 return ObjectPool::IndexFromOffset(offset);
29}
30
31bool DecodeLoadObjectFromPoolOrThread(uword pc, const Code& code, Object* obj) {
32 ASSERT(code.ContainsInstructionAt(pc));
33
34 uint8_t* bytes = reinterpret_cast<uint8_t*>(pc);
35
36 COMPILE_ASSERT(THR == R14);
37 if ((bytes[0] == 0x49) || (bytes[0] == 0x4d)) {
38 if ((bytes[1] == 0x8b) || (bytes[1] == 0x3b)) { // movq, cmpq
39 if ((bytes[2] & 0xc7) == (0x80 | (THR & 7))) { // [r14+disp32]
40 int32_t offset = LoadUnaligned(reinterpret_cast<int32_t*>(pc + 3));
41 return Thread::ObjectAtOffset(offset, obj);
42 }
43 if ((bytes[2] & 0xc7) == (0x40 | (THR & 7))) { // [r14+disp8]
44 uint8_t offset = *reinterpret_cast<uint8_t*>(pc + 3);
45 return Thread::ObjectAtOffset(offset, obj);
46 }
47 }
48 }
49
50 if (((bytes[0] == 0x41) && (bytes[1] == 0xff) && (bytes[2] == 0x76))) {
51 // push [r14+disp8]
52 uint8_t offset = *reinterpret_cast<uint8_t*>(pc + 3);
53 return Thread::ObjectAtOffset(offset, obj);
54 }
55
56 // A code object may have an object pool attached in bare instructions mode
57 // if the v8 snapshot profile writer is active, but this pool cannot be used
58 // for object loading.
59 if (FLAG_use_bare_instructions) return false;
60
61 COMPILE_ASSERT(PP == R15);
62 if ((bytes[0] == 0x49) || (bytes[0] == 0x4d)) {
63 if ((bytes[1] == 0x8b) || (bytes[1] == 0x3b)) { // movq, cmpq
64 if ((bytes[2] & 0xc7) == (0x80 | (PP & 7))) { // [r15+disp32]
65 intptr_t index = IndexFromPPLoadDisp32(pc + 3);
66 const ObjectPool& pool = ObjectPool::Handle(code.object_pool());
67 if (!pool.IsNull()) {
68 if (pool.TypeAt(index) == ObjectPool::EntryType::kTaggedObject) {
69 *obj = pool.ObjectAt(index);
70 return true;
71 }
72 }
73 }
74 if ((bytes[2] & 0xc7) == (0x40 | (PP & 7))) { // [r15+disp8]
75 intptr_t index = IndexFromPPLoadDisp8(pc + 3);
76 const ObjectPool& pool = ObjectPool::Handle(code.object_pool());
77 if (!pool.IsNull()) {
78 if (pool.TypeAt(index) == ObjectPool::EntryType::kTaggedObject) {
79 *obj = pool.ObjectAt(index);
80 return true;
81 }
82 }
83 }
84 }
85 }
86
87 return false;
88}
89
90intptr_t TypeTestingStubCallPattern::GetSubtypeTestCachePoolIndex() {
91 static int16_t indirect_call_pattern[] = {
92 0xff, -1 /* 0x53 or 0x56 */, 0x07, // callq [RBX/RSI + 0x7]
93 };
94 static int16_t direct_call_pattern[] = {
95 0xe8, -1, -1, -1, -1, // callq [PC + <offset>]
96 };
97 static int16_t pattern_disp8[] = {
98 0x4d, 0x8b, 0x4f, -1, // movq R9, [PP + offset]
99 };
100 static int16_t pattern_disp32[] = {
101 0x4d, 0x8b, 0x8f, -1, -1, -1, -1, // movq R9, [PP + offset]
102 };
103
104 uword pc = pc_;
105 if (MatchesPattern(pc, direct_call_pattern,
106 ARRAY_SIZE(direct_call_pattern))) {
107 pc -= ARRAY_SIZE(direct_call_pattern);
108 } else if (MatchesPattern(pc, indirect_call_pattern,
109 ARRAY_SIZE(indirect_call_pattern))) {
110 pc -= ARRAY_SIZE(indirect_call_pattern);
111 } else {
112 FATAL1("Failed to decode at %" Px, pc_);
113 }
114
115 if (MatchesPattern(pc, pattern_disp8, ARRAY_SIZE(pattern_disp8))) {
116 return IndexFromPPLoadDisp8(pc - 1);
117 } else if (MatchesPattern(pc, pattern_disp32, ARRAY_SIZE(pattern_disp32))) {
118 return IndexFromPPLoadDisp32(pc - 4);
119 } else {
120 FATAL1("Failed to decode at %" Px, pc);
121 }
122}
123
124} // namespace dart
125
126#endif // defined TARGET_ARCH_X64
127