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