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

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

Issue 24744002: Pattern match on generated code to find edge counters. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Incorporated review comments. Created 7 years, 2 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 | Annotate | Revision Log
« no previous file with comments | « runtime/vm/instructions_arm.h ('k') | runtime/vm/instructions_mips.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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_ARM. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM.
6 #if defined(TARGET_ARCH_ARM) 6 #if defined(TARGET_ARCH_ARM)
7 7
8 #include "vm/constants_arm.h" 8 #include "vm/constants_arm.h"
9 #include "vm/cpu.h" 9 #include "vm/cpu.h"
10 #include "vm/instructions.h" 10 #include "vm/instructions.h"
11 #include "vm/object.h" 11 #include "vm/object.h"
12 12
13 namespace dart { 13 namespace dart {
14 14
15 CallPattern::CallPattern(uword pc, const Code& code) 15 CallPattern::CallPattern(uword pc, const Code& code)
16 : end_(reinterpret_cast<uword*>(pc)), 16 : object_pool_(Array::Handle(code.ObjectPool())),
17 end_(pc),
18 args_desc_load_end_(0),
19 ic_data_load_end_(0),
17 target_address_pool_index_(-1), 20 target_address_pool_index_(-1),
18 args_desc_load_end_(-1),
19 args_desc_(Array::Handle()), 21 args_desc_(Array::Handle()),
20 ic_data_load_end_(-1), 22 ic_data_(ICData::Handle()) {
21 ic_data_(ICData::Handle()),
22 object_pool_(Array::Handle(code.ObjectPool())) {
23 ASSERT(code.ContainsInstructionAt(pc)); 23 ASSERT(code.ContainsInstructionAt(pc));
24 ASSERT(Back(1) == 0xe12fff3e); // Last instruction: blx lr 24 // Last instruction: blx lr.
25 ASSERT(*(reinterpret_cast<uword*>(end_) - 1) == 0xe12fff3e);
26
25 Register reg; 27 Register reg;
26 ic_data_load_end_ = 28 ic_data_load_end_ =
27 DecodeLoadWordFromPool(1, &reg, &target_address_pool_index_); 29 InstructionPattern::DecodeLoadWordFromPool(end_ - Instr::kInstrSize,
30 &reg,
31 &target_address_pool_index_);
28 ASSERT(reg == LR); 32 ASSERT(reg == LR);
29 } 33 }
30 34
31 35
32 uword CallPattern::Back(int n) const { 36 // Decodes a load sequence ending at 'end' (the last instruction of the load
33 ASSERT(n > 0); 37 // sequence is the instruction before the one at end). Returns a pointer to
34 return *(end_ - n); 38 // the first instruction in the sequence. Returns the register being loaded
39 // and the loaded object in the output parameters 'reg' and 'obj'
40 // respectively.
41 uword InstructionPattern::DecodeLoadObject(uword end,
42 const Array& object_pool,
43 Register* reg,
44 Object* obj) {
45 uword start = 0;
46 Instr* instr = Instr::At(end - Instr::kInstrSize);
47 if ((instr->InstructionBits() & 0xfff00000) == 0xe5900000) {
48 // ldr reg, [reg, #+offset]
49 intptr_t index = 0;
50 start = DecodeLoadWordFromPool(end, reg, &index);
51 *obj = object_pool.At(index);
52 } else {
53 intptr_t value = 0;
54 start = DecodeLoadWordImmediate(end, reg, &value);
55 *obj = reinterpret_cast<RawObject*>(value);
56 }
57 return start;
35 } 58 }
36 59
37 60
38 // Decodes a load sequence ending at end. Returns the register being loaded and 61 // Decodes a load sequence ending at 'end' (the last instruction of the load
39 // the loaded object. 62 // sequence is the instruction before the one at end). Returns a pointer to
40 // Returns the location of the load sequence, counting the number of 63 // the first instruction in the sequence. Returns the register being loaded
41 // instructions back from the end of the call pattern. 64 // and the loaded immediate value in the output parameters 'reg' and 'value'
42 int CallPattern::DecodeLoadObject(int end, Register* reg, Object* obj) { 65 // respectively.
43 ASSERT(end > 0); 66 uword InstructionPattern::DecodeLoadWordImmediate(uword end,
44 uword instr = Back(end + 1); 67 Register* reg,
45 if ((instr & 0xfff00000) == 0xe5900000) { // ldr reg, [reg, #+offset] 68 intptr_t* value) {
46 int index = 0; 69 uword start = end - Instr::kInstrSize;
47 end = DecodeLoadWordFromPool(end, reg, &index); 70 int32_t instr = Instr::At(start)->InstructionBits();
48 *obj = object_pool_.At(index); 71 intptr_t imm = 0;
49 } else {
50 int value = 0;
51 end = DecodeLoadWordImmediate(end, reg, &value);
52 *obj = reinterpret_cast<RawObject*>(value);
53 }
54 return end;
55 }
56
57
58 // Decodes a load sequence ending at end. Returns the register being loaded and
59 // the loaded immediate value.
60 // Returns the location of the load sequence, counting the number of
61 // instructions back from the end of the call pattern.
62 int CallPattern::DecodeLoadWordImmediate(int end, Register* reg, int* value) {
63 ASSERT(end > 0);
64 uword instr = Back(++end);
65 int imm = 0;
66 if ((instr & 0xfff00000) == 0xe3400000) { // movt reg, #imm_hi 72 if ((instr & 0xfff00000) == 0xe3400000) { // movt reg, #imm_hi
67 imm |= (instr & 0xf0000) << 12; 73 imm |= (instr & 0xf0000) << 12;
68 imm |= (instr & 0xfff) << 16; 74 imm |= (instr & 0xfff) << 16;
69 instr = Back(++end); 75 start -= Instr::kInstrSize;
76 instr = Instr::At(start)->InstructionBits();
70 } 77 }
71 ASSERT((instr & 0xfff00000) == 0xe3000000); // movw reg, #imm_lo 78 ASSERT((instr & 0xfff00000) == 0xe3000000); // movw reg, #imm_lo
72 imm |= (instr & 0xf0000) >> 4; 79 imm |= (instr & 0xf0000) >> 4;
73 imm |= instr & 0xfff; 80 imm |= instr & 0xfff;
74 *reg = static_cast<Register>((instr & 0xf000) >> 12); 81 *reg = static_cast<Register>((instr & 0xf000) >> 12);
75 *value = imm; 82 *value = imm;
76 return end; 83 return start;
77 } 84 }
78 85
79 86
80 // Decodes a load sequence ending at end. Returns the register being loaded and 87 // Decodes a load sequence ending at 'end' (the last instruction of the load
81 // the index in the pool being read from. 88 // sequence is the instruction before the one at end). Returns a pointer to
82 // Returns the location of the load sequence, counting the number of 89 // the first instruction in the sequence. Returns the register being loaded
83 // instructions back from the end of the call pattern. 90 // and the index in the pool being read from in the output parameters 'reg'
84 int CallPattern::DecodeLoadWordFromPool(int end, Register* reg, int* index) { 91 // and 'index' respectively.
85 ASSERT(end > 0); 92 uword InstructionPattern::DecodeLoadWordFromPool(uword end,
86 uword instr = Back(++end); 93 Register* reg,
87 int offset = 0; 94 intptr_t* index) {
95 uword start = end - Instr::kInstrSize;
96 int32_t instr = Instr::At(start)->InstructionBits();
97 intptr_t offset = 0;
88 if ((instr & 0xffff0000) == 0xe59a0000) { // ldr reg, [pp, #+offset] 98 if ((instr & 0xffff0000) == 0xe59a0000) { // ldr reg, [pp, #+offset]
89 offset = instr & 0xfff; 99 offset = instr & 0xfff;
90 *reg = static_cast<Register>((instr & 0xf000) >> 12); 100 *reg = static_cast<Register>((instr & 0xf000) >> 12);
91 } else { 101 } else {
92 ASSERT((instr & 0xfff00000) == 0xe5900000); // ldr reg, [reg, #+offset] 102 ASSERT((instr & 0xfff00000) == 0xe5900000); // ldr reg, [reg, #+offset]
93 offset = instr & 0xfff; 103 offset = instr & 0xfff;
94 instr = Back(++end); 104 start -= Instr::kInstrSize;
105 instr = Instr::At(start)->InstructionBits();
95 if ((instr & 0xffff0000) == 0xe28a0000) { // add reg, pp, shifter_op 106 if ((instr & 0xffff0000) == 0xe28a0000) { // add reg, pp, shifter_op
96 const int rot = (instr & 0xf00) >> 7; 107 const intptr_t rot = (instr & 0xf00) >> 7;
97 const int imm8 = instr & 0xff; 108 const intptr_t imm8 = instr & 0xff;
98 offset += (imm8 >> rot) | (imm8 << (32 - rot)); 109 offset += (imm8 >> rot) | (imm8 << (32 - rot));
99 *reg = static_cast<Register>((instr & 0xf000) >> 12); 110 *reg = static_cast<Register>((instr & 0xf000) >> 12);
100 } else { 111 } else {
101 ASSERT((instr & 0xffff0000) == 0xe08a0000); // add reg, pp, reg 112 ASSERT((instr & 0xffff0000) == 0xe08a0000); // add reg, pp, reg
102 end = DecodeLoadWordImmediate(end, reg, &offset); 113 end = DecodeLoadWordImmediate(end, reg, &offset);
103 } 114 }
104 } 115 }
105 offset += kHeapObjectTag; 116 offset += kHeapObjectTag;
106 ASSERT(Utils::IsAligned(offset, 4)); 117 ASSERT(Utils::IsAligned(offset, 4));
107 *index = (offset - Array::data_offset())/4; 118 *index = (offset - Array::data_offset()) / 4;
108 return end; 119 return start;
109 } 120 }
110 121
111 122
112 RawICData* CallPattern::IcData() { 123 RawICData* CallPattern::IcData() {
113 if (ic_data_.IsNull()) { 124 if (ic_data_.IsNull()) {
114 Register reg; 125 Register reg;
115 args_desc_load_end_ = DecodeLoadObject(ic_data_load_end_, &reg, &ic_data_); 126 args_desc_load_end_ =
127 InstructionPattern::DecodeLoadObject(ic_data_load_end_,
128 object_pool_,
129 &reg,
130 &ic_data_);
116 ASSERT(reg == R5); 131 ASSERT(reg == R5);
117 } 132 }
118 return ic_data_.raw(); 133 return ic_data_.raw();
119 } 134 }
120 135
121 136
122 RawArray* CallPattern::ClosureArgumentsDescriptor() { 137 RawArray* CallPattern::ClosureArgumentsDescriptor() {
123 if (args_desc_.IsNull()) { 138 if (args_desc_.IsNull()) {
124 IcData(); // Loading of the ic_data must be decoded first, if not already. 139 IcData(); // Loading of the ic_data must be decoded first, if not already.
125 Register reg; 140 Register reg;
126 DecodeLoadObject(args_desc_load_end_, &reg, &args_desc_); 141 InstructionPattern::DecodeLoadObject(args_desc_load_end_,
142 object_pool_,
143 &reg,
144 &args_desc_);
127 ASSERT(reg == R4); 145 ASSERT(reg == R4);
128 } 146 }
129 return args_desc_.raw(); 147 return args_desc_.raw();
130 } 148 }
131 149
132 150
133 uword CallPattern::TargetAddress() const { 151 uword CallPattern::TargetAddress() const {
134 ASSERT(target_address_pool_index_ >= 0); 152 ASSERT(target_address_pool_index_ >= 0);
135 const Object& target_address = 153 const Object& target_address =
136 Object::Handle(object_pool_.At(target_address_pool_index_)); 154 Object::Handle(object_pool_.At(target_address_pool_index_));
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
191 uword movw_ip = 0xe300c000 | ((target_lo >> 12) << 16) | (target_lo & 0xfff); 209 uword movw_ip = 0xe300c000 | ((target_lo >> 12) << 16) | (target_lo & 0xfff);
192 uword movt_ip = 0xe340c000 | ((target_hi >> 12) << 16) | (target_hi & 0xfff); 210 uword movt_ip = 0xe340c000 | ((target_hi >> 12) << 16) | (target_hi & 0xfff);
193 *reinterpret_cast<uword*>(pc_ + (0 * Instr::kInstrSize)) = movw_ip; 211 *reinterpret_cast<uword*>(pc_ + (0 * Instr::kInstrSize)) = movw_ip;
194 *reinterpret_cast<uword*>(pc_ + (1 * Instr::kInstrSize)) = movt_ip; 212 *reinterpret_cast<uword*>(pc_ + (1 * Instr::kInstrSize)) = movt_ip;
195 CPU::FlushICache(pc_, 2 * Instr::kInstrSize); 213 CPU::FlushICache(pc_, 2 * Instr::kInstrSize);
196 } 214 }
197 215
198 } // namespace dart 216 } // namespace dart
199 217
200 #endif // defined TARGET_ARCH_ARM 218 #endif // defined TARGET_ARCH_ARM
201
OLDNEW
« no previous file with comments | « runtime/vm/instructions_arm.h ('k') | runtime/vm/instructions_mips.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698