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/deopt_instructions.h" | 5 #include "vm/deopt_instructions.h" |
6 | 6 |
| 7 #include "vm/assembler_macros.h" |
7 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
8 #include "vm/locations.h" | 9 #include "vm/locations.h" |
9 #include "vm/parser.h" | 10 #include "vm/parser.h" |
10 | 11 |
11 namespace dart { | 12 namespace dart { |
12 | 13 |
| 14 DeoptimizationContext::DeoptimizationContext(intptr_t* to_frame_start, |
| 15 intptr_t to_frame_size, |
| 16 const Array& object_table, |
| 17 intptr_t num_args) |
| 18 : object_table_(object_table), |
| 19 to_frame_(to_frame_start), |
| 20 to_frame_size_(to_frame_size), |
| 21 from_frame_(NULL), |
| 22 from_frame_size_(0), |
| 23 registers_copy_(NULL), |
| 24 num_args_(num_args), |
| 25 isolate_(Isolate::Current()) { |
| 26 from_frame_ = isolate_->deopt_frame_copy(); |
| 27 from_frame_size_ = isolate_->deopt_frame_copy_size(); |
| 28 registers_copy_ = isolate_->deopt_registers_copy(); |
| 29 } |
| 30 |
| 31 |
| 32 intptr_t* DeoptimizationContext::GetFromFpAddress() const { |
| 33 return &from_frame_[from_frame_size_ - 1 - num_args_ - 1]; |
| 34 } |
| 35 |
| 36 |
| 37 intptr_t* DeoptimizationContext::GetFromPcAddress() const { |
| 38 return &from_frame_[from_frame_size_ - 1 - num_args_]; |
| 39 } |
| 40 |
13 // Deoptimization instruction moving value from optimized frame at | 41 // Deoptimization instruction moving value from optimized frame at |
14 // 'from_index' to specified slots in the unoptimized frame. | 42 // 'from_index' to specified slots in the unoptimized frame. |
15 // 'from_index' represents the local count >= 0, first | 43 // 'from_index' represents the slot index of the frame (0 being first argument) |
16 // argument being 0. | 44 // and accounts for saved return address, frame pointer and pc marker. |
17 class DeoptStackSlotInstr : public DeoptInstr { | 45 class DeoptStackSlotInstr : public DeoptInstr { |
18 public: | 46 public: |
19 explicit DeoptStackSlotInstr(intptr_t from_index) | 47 explicit DeoptStackSlotInstr(intptr_t from_index) |
20 : stack_slot_index_(from_index) { | 48 : stack_slot_index_(from_index) { |
21 ASSERT(stack_slot_index_ >= 0); | 49 ASSERT(stack_slot_index_ >= 0); |
22 } | 50 } |
23 | 51 |
24 virtual intptr_t from_index() const { return stack_slot_index_; } | 52 virtual intptr_t from_index() const { return stack_slot_index_; } |
25 virtual DeoptInstr::Kind kind() const { return kCopyStackSlot; } | 53 virtual DeoptInstr::Kind kind() const { return kCopyStackSlot; } |
26 | 54 |
27 virtual const char* ToCString() const { | 55 virtual const char* ToCString() const { |
28 intptr_t len = OS::SNPrint(NULL, 0, "s%d", stack_slot_index_); | 56 intptr_t len = OS::SNPrint(NULL, 0, "s%d", stack_slot_index_); |
29 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); | 57 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); |
30 OS::SNPrint(chars, len + 1, "s%d", stack_slot_index_); | 58 OS::SNPrint(chars, len + 1, "s%d", stack_slot_index_); |
31 return chars; | 59 return chars; |
32 } | 60 } |
33 | 61 |
| 62 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { |
| 63 intptr_t from_index = |
| 64 deopt_context->from_frame_size() - stack_slot_index_ - 1; |
| 65 intptr_t* from_addr = deopt_context->GetFromFrameAddressAt(from_index); |
| 66 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index); |
| 67 *to_addr = *from_addr; |
| 68 } |
| 69 |
34 private: | 70 private: |
35 const intptr_t stack_slot_index_; // First argument is 0, always >= 0. | 71 const intptr_t stack_slot_index_; // First argument is 0, always >= 0. |
36 | 72 |
37 DISALLOW_COPY_AND_ASSIGN(DeoptStackSlotInstr); | 73 DISALLOW_COPY_AND_ASSIGN(DeoptStackSlotInstr); |
38 }; | 74 }; |
39 | 75 |
40 | 76 |
41 // Deoptimization instruction creating return address using function and | 77 // Deoptimization instruction creating return address using function and |
42 // deopt-id stored at 'object_table_index'. | 78 // deopt-id stored at 'object_table_index'. |
43 class DeoptRetAddrInstr : public DeoptInstr { | 79 class DeoptRetAddrInstr : public DeoptInstr { |
44 public: | 80 public: |
45 explicit DeoptRetAddrInstr(intptr_t object_table_index) | 81 explicit DeoptRetAddrInstr(intptr_t object_table_index) |
46 : object_table_index_(object_table_index) { | 82 : object_table_index_(object_table_index) { |
47 ASSERT(object_table_index >= 0); | 83 ASSERT(object_table_index >= 0); |
48 } | 84 } |
49 | 85 |
50 virtual intptr_t from_index() const { return object_table_index_; } | 86 virtual intptr_t from_index() const { return object_table_index_; } |
51 virtual DeoptInstr::Kind kind() const { return kSetRetAddress; } | 87 virtual DeoptInstr::Kind kind() const { return kSetRetAddress; } |
52 | 88 |
53 virtual const char* ToCString() const { | 89 virtual const char* ToCString() const { |
54 intptr_t len = OS::SNPrint(NULL, 0, "ret oti:%d", object_table_index_); | 90 intptr_t len = OS::SNPrint(NULL, 0, "ret oti:%d", object_table_index_); |
55 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); | 91 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); |
56 OS::SNPrint(chars, len + 1, "ret oti:%d", object_table_index_); | 92 OS::SNPrint(chars, len + 1, "ret oti:%d", object_table_index_); |
57 return chars; | 93 return chars; |
58 } | 94 } |
59 | 95 |
| 96 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { |
| 97 Function& function = Function::Handle(deopt_context->isolate()); |
| 98 function ^= deopt_context->ObjectAt(object_table_index_); |
| 99 Smi& deopt_id_as_smi = Smi::Handle(deopt_context->isolate()); |
| 100 deopt_id_as_smi ^= deopt_context->ObjectAt(object_table_index_ + 1); |
| 101 const Code& code = |
| 102 Code::Handle(deopt_context->isolate(), function.unoptimized_code()); |
| 103 uword continue_at_pc = code.GetDeoptPcAtDeoptId(deopt_id_as_smi.Value()); |
| 104 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index); |
| 105 *to_addr = continue_at_pc; |
| 106 } |
| 107 |
60 private: | 108 private: |
61 const intptr_t object_table_index_; | 109 const intptr_t object_table_index_; |
62 | 110 |
63 DISALLOW_COPY_AND_ASSIGN(DeoptRetAddrInstr); | 111 DISALLOW_COPY_AND_ASSIGN(DeoptRetAddrInstr); |
64 }; | 112 }; |
65 | 113 |
66 | 114 |
67 // Deoptimization instruction moving a constant stored at 'object_table_index'. | 115 // Deoptimization instruction moving a constant stored at 'object_table_index'. |
68 class DeoptConstantInstr : public DeoptInstr { | 116 class DeoptConstantInstr : public DeoptInstr { |
69 public: | 117 public: |
70 explicit DeoptConstantInstr(intptr_t object_table_index) | 118 explicit DeoptConstantInstr(intptr_t object_table_index) |
71 : object_table_index_(object_table_index) { | 119 : object_table_index_(object_table_index) { |
72 ASSERT(object_table_index >= 0); | 120 ASSERT(object_table_index >= 0); |
73 } | 121 } |
74 | 122 |
75 virtual intptr_t from_index() const { return object_table_index_; } | 123 virtual intptr_t from_index() const { return object_table_index_; } |
76 virtual DeoptInstr::Kind kind() const { return kCopyConstant; } | 124 virtual DeoptInstr::Kind kind() const { return kCopyConstant; } |
77 | 125 |
78 virtual const char* ToCString() const { | 126 virtual const char* ToCString() const { |
79 intptr_t len = OS::SNPrint(NULL, 0, "const oti:%d", object_table_index_); | 127 intptr_t len = OS::SNPrint(NULL, 0, "const oti:%d", object_table_index_); |
80 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); | 128 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); |
81 OS::SNPrint(chars, len + 1, "const oti:%d", object_table_index_); | 129 OS::SNPrint(chars, len + 1, "const oti:%d", object_table_index_); |
82 return chars; | 130 return chars; |
83 } | 131 } |
84 | 132 |
| 133 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { |
| 134 const Object& obj = Object::Handle( |
| 135 deopt_context->isolate(), deopt_context->ObjectAt(object_table_index_)); |
| 136 RawObject** to_addr = reinterpret_cast<RawObject**>( |
| 137 deopt_context->GetToFrameAddressAt(to_index)); |
| 138 *to_addr = obj.raw(); |
| 139 } |
| 140 |
85 private: | 141 private: |
86 const intptr_t object_table_index_; | 142 const intptr_t object_table_index_; |
87 | 143 |
88 DISALLOW_COPY_AND_ASSIGN(DeoptConstantInstr); | 144 DISALLOW_COPY_AND_ASSIGN(DeoptConstantInstr); |
89 }; | 145 }; |
90 | 146 |
91 | 147 |
92 // Deoptimization instruction moving a register. | 148 // Deoptimization instruction moving a register. |
93 class DeoptRegisterInstr: public DeoptInstr { | 149 class DeoptRegisterInstr: public DeoptInstr { |
94 public: | 150 public: |
95 explicit DeoptRegisterInstr(intptr_t reg_as_int) | 151 explicit DeoptRegisterInstr(intptr_t reg_as_int) |
96 : reg_(static_cast<Register>(reg_as_int)) {} | 152 : reg_(static_cast<Register>(reg_as_int)) {} |
97 | 153 |
98 virtual intptr_t from_index() const { return static_cast<intptr_t>(reg_); } | 154 virtual intptr_t from_index() const { return static_cast<intptr_t>(reg_); } |
99 virtual DeoptInstr::Kind kind() const { return kCopyRegister; } | 155 virtual DeoptInstr::Kind kind() const { return kCopyRegister; } |
100 | 156 |
101 virtual const char* ToCString() const { | 157 virtual const char* ToCString() const { |
102 return Assembler::RegisterName(reg_); | 158 return Assembler::RegisterName(reg_); |
103 } | 159 } |
104 | 160 |
| 161 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { |
| 162 intptr_t value = deopt_context->RegisterValue(reg_); |
| 163 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index); |
| 164 *to_addr = value; |
| 165 } |
| 166 |
105 private: | 167 private: |
106 const Register reg_; | 168 const Register reg_; |
107 | 169 |
108 DISALLOW_COPY_AND_ASSIGN(DeoptRegisterInstr); | 170 DISALLOW_COPY_AND_ASSIGN(DeoptRegisterInstr); |
109 }; | 171 }; |
110 | 172 |
111 | 173 |
112 // Deoptimization instruction creating a PC marker for the code of | 174 // Deoptimization instruction creating a PC marker for the code of |
113 // function at 'object_table_index'. | 175 // function at 'object_table_index'. |
114 class DeoptPcMarkerInstr : public DeoptInstr { | 176 class DeoptPcMarkerInstr : public DeoptInstr { |
115 public: | 177 public: |
116 explicit DeoptPcMarkerInstr(intptr_t object_table_index) | 178 explicit DeoptPcMarkerInstr(intptr_t object_table_index) |
117 : object_table_index_(object_table_index) { | 179 : object_table_index_(object_table_index) { |
118 ASSERT(object_table_index >= 0); | 180 ASSERT(object_table_index >= 0); |
119 } | 181 } |
120 | 182 |
121 virtual intptr_t from_index() const { return object_table_index_; } | 183 virtual intptr_t from_index() const { return object_table_index_; } |
122 virtual DeoptInstr::Kind kind() const { return kSetPcMarker; } | 184 virtual DeoptInstr::Kind kind() const { return kSetPcMarker; } |
123 | 185 |
124 virtual const char* ToCString() const { | 186 virtual const char* ToCString() const { |
125 intptr_t len = OS::SNPrint(NULL, 0, "pcmark oti:%d", object_table_index_); | 187 intptr_t len = OS::SNPrint(NULL, 0, "pcmark oti:%d", object_table_index_); |
126 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); | 188 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len + 1); |
127 OS::SNPrint(chars, len + 1, "pcmark oti:%d", object_table_index_); | 189 OS::SNPrint(chars, len + 1, "pcmark oti:%d", object_table_index_); |
128 return chars; | 190 return chars; |
129 } | 191 } |
130 | 192 |
| 193 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { |
| 194 Function& function = Function::Handle(deopt_context->isolate()); |
| 195 function ^= deopt_context->ObjectAt(object_table_index_); |
| 196 const Code& code = |
| 197 Code::Handle(deopt_context->isolate(), function.unoptimized_code()); |
| 198 intptr_t pc_marker = code.EntryPoint() + |
| 199 AssemblerMacros::kOffsetOfSavedPCfromEntrypoint; |
| 200 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index); |
| 201 *to_addr = pc_marker; |
| 202 } |
| 203 |
131 private: | 204 private: |
132 intptr_t object_table_index_; | 205 intptr_t object_table_index_; |
133 | 206 |
134 DISALLOW_COPY_AND_ASSIGN(DeoptPcMarkerInstr); | 207 DISALLOW_COPY_AND_ASSIGN(DeoptPcMarkerInstr); |
135 }; | 208 }; |
136 | 209 |
137 | 210 |
138 // Deoptimization instruction copying the caller saved FP from optimized frame. | 211 // Deoptimization instruction copying the caller saved FP from optimized frame. |
139 class DeoptCallerFpInstr : public DeoptInstr { | 212 class DeoptCallerFpInstr : public DeoptInstr { |
140 public: | 213 public: |
141 DeoptCallerFpInstr() {} | 214 DeoptCallerFpInstr() {} |
142 | 215 |
143 virtual intptr_t from_index() const { return 0; } | 216 virtual intptr_t from_index() const { return 0; } |
144 virtual DeoptInstr::Kind kind() const { return kSetCallerFp; } | 217 virtual DeoptInstr::Kind kind() const { return kSetCallerFp; } |
145 | 218 |
146 virtual const char* ToCString() const { return "callerfp"; } | 219 virtual const char* ToCString() const { |
| 220 return "callerfp"; |
| 221 } |
| 222 |
| 223 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { |
| 224 intptr_t* from_addr = deopt_context->GetFromFpAddress(); |
| 225 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index); |
| 226 *to_addr = *from_addr; |
| 227 } |
147 | 228 |
148 private: | 229 private: |
149 DISALLOW_COPY_AND_ASSIGN(DeoptCallerFpInstr); | 230 DISALLOW_COPY_AND_ASSIGN(DeoptCallerFpInstr); |
150 }; | 231 }; |
151 | 232 |
152 | 233 |
153 // Deoptimization instruction copying the caller return address from optimzied | 234 // Deoptimization instruction copying the caller return address from optimized |
154 // frame. | 235 // frame. |
155 class DeoptCallerPcInstr : public DeoptInstr { | 236 class DeoptCallerPcInstr : public DeoptInstr { |
156 public: | 237 public: |
157 DeoptCallerPcInstr() {} | 238 DeoptCallerPcInstr() {} |
158 | 239 |
159 virtual intptr_t from_index() const { return 0; } | 240 virtual intptr_t from_index() const { return 0; } |
160 virtual DeoptInstr::Kind kind() const { return kSetCallerPc; } | 241 virtual DeoptInstr::Kind kind() const { return kSetCallerPc; } |
161 | 242 |
162 virtual const char* ToCString() const { return "callerpc"; } | 243 virtual const char* ToCString() const { |
| 244 return "callerpc"; |
| 245 } |
| 246 |
| 247 void Execute(DeoptimizationContext* deopt_context, intptr_t to_index) { |
| 248 intptr_t* from_addr = deopt_context->GetFromPcAddress(); |
| 249 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index); |
| 250 *to_addr = *from_addr; |
| 251 } |
163 | 252 |
164 private: | 253 private: |
165 DISALLOW_COPY_AND_ASSIGN(DeoptCallerPcInstr); | 254 DISALLOW_COPY_AND_ASSIGN(DeoptCallerPcInstr); |
166 }; | 255 }; |
167 | 256 |
168 | 257 |
169 DeoptInstr* DeoptInstr::Create(intptr_t kind_as_int, intptr_t from_index) { | 258 DeoptInstr* DeoptInstr::Create(intptr_t kind_as_int, intptr_t from_index) { |
170 Kind kind = static_cast<Kind>(kind_as_int); | 259 Kind kind = static_cast<Kind>(kind_as_int); |
171 switch (kind) { | 260 switch (kind) { |
172 case kCopyStackSlot: return new DeoptStackSlotInstr(from_index); | 261 case kCopyStackSlot: return new DeoptStackSlotInstr(from_index); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
219 void DeoptInfoBuilder::AddCopy(const Location& from_loc, | 308 void DeoptInfoBuilder::AddCopy(const Location& from_loc, |
220 const Value& from_value, | 309 const Value& from_value, |
221 const intptr_t to_index) { | 310 const intptr_t to_index) { |
222 DeoptInstr* deopt_instr = NULL; | 311 DeoptInstr* deopt_instr = NULL; |
223 if (from_loc.IsConstant()) { | 312 if (from_loc.IsConstant()) { |
224 intptr_t object_table_index = FindOrAddObjectInTable(from_loc.constant()); | 313 intptr_t object_table_index = FindOrAddObjectInTable(from_loc.constant()); |
225 deopt_instr = new DeoptConstantInstr(object_table_index); | 314 deopt_instr = new DeoptConstantInstr(object_table_index); |
226 } else if (from_loc.IsRegister()) { | 315 } else if (from_loc.IsRegister()) { |
227 deopt_instr = new DeoptRegisterInstr(from_loc.reg()); | 316 deopt_instr = new DeoptRegisterInstr(from_loc.reg()); |
228 } else if (from_loc.IsStackSlot()) { | 317 } else if (from_loc.IsStackSlot()) { |
229 deopt_instr = new DeoptStackSlotInstr(from_loc.stack_index() + num_args_); | 318 intptr_t from_index = (from_loc.stack_index() < 0) ? |
| 319 from_loc.stack_index() + num_args_ : |
| 320 from_loc.stack_index() + num_args_ - |
| 321 ParsedFunction::kFirstLocalSlotIndex + 1; |
| 322 deopt_instr = new DeoptStackSlotInstr(from_index); |
230 } else if (from_loc.IsInvalid()) { | 323 } else if (from_loc.IsInvalid()) { |
231 ASSERT(from_value.IsConstant()); | 324 ASSERT(from_value.IsConstant()); |
232 const Object& obj = from_value.AsConstant()->value(); | 325 const Object& obj = from_value.AsConstant()->value(); |
233 intptr_t object_table_index = FindOrAddObjectInTable(obj); | 326 intptr_t object_table_index = FindOrAddObjectInTable(obj); |
234 deopt_instr = new DeoptConstantInstr(object_table_index); | 327 deopt_instr = new DeoptConstantInstr(object_table_index); |
235 } else { | 328 } else { |
236 UNREACHABLE(); | 329 UNREACHABLE(); |
237 } | 330 } |
238 ASSERT(to_index == instructions_.length()); | 331 ASSERT(to_index == instructions_.length()); |
239 instructions_.Add(deopt_instr); | 332 instructions_.Add(deopt_instr); |
(...skipping 16 matching lines...) Expand all Loading... |
256 const intptr_t len = instructions_.length(); | 349 const intptr_t len = instructions_.length(); |
257 const DeoptInfo& deopt_info = DeoptInfo::Handle(DeoptInfo::New(len)); | 350 const DeoptInfo& deopt_info = DeoptInfo::Handle(DeoptInfo::New(len)); |
258 for (intptr_t i = 0; i < len; i++) { | 351 for (intptr_t i = 0; i < len; i++) { |
259 DeoptInstr* instr = instructions_[i]; | 352 DeoptInstr* instr = instructions_[i]; |
260 deopt_info.SetAt(i, instr->kind(), instr->from_index()); | 353 deopt_info.SetAt(i, instr->kind(), instr->from_index()); |
261 } | 354 } |
262 return deopt_info.raw(); | 355 return deopt_info.raw(); |
263 } | 356 } |
264 | 357 |
265 } // namespace dart | 358 } // namespace dart |
OLD | NEW |