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/code_descriptors.h" | 5 #include "vm/code_descriptors.h" |
6 | 6 |
| 7 #include "vm/log.h" |
| 8 |
7 namespace dart { | 9 namespace dart { |
8 | 10 |
9 void DescriptorList::AddDescriptor(RawPcDescriptors::Kind kind, | 11 void DescriptorList::AddDescriptor(RawPcDescriptors::Kind kind, |
10 intptr_t pc_offset, | 12 intptr_t pc_offset, |
11 intptr_t deopt_id, | 13 intptr_t deopt_id, |
12 TokenPosition token_pos, | 14 TokenPosition token_pos, |
13 intptr_t try_index) { | 15 intptr_t try_index) { |
14 ASSERT((kind == RawPcDescriptors::kRuntimeCall) || | 16 ASSERT((kind == RawPcDescriptors::kRuntimeCall) || |
15 (kind == RawPcDescriptors::kOther) || | 17 (kind == RawPcDescriptors::kOther) || |
16 (deopt_id != Thread::kNoDeoptId)); | 18 (deopt_id != Thread::kNoDeoptId)); |
(...skipping 17 matching lines...) Expand all Loading... |
34 | 36 |
35 | 37 |
36 RawPcDescriptors* DescriptorList::FinalizePcDescriptors(uword entry_point) { | 38 RawPcDescriptors* DescriptorList::FinalizePcDescriptors(uword entry_point) { |
37 if (encoded_data_.length() == 0) { | 39 if (encoded_data_.length() == 0) { |
38 return Object::empty_descriptors().raw(); | 40 return Object::empty_descriptors().raw(); |
39 } | 41 } |
40 return PcDescriptors::New(&encoded_data_); | 42 return PcDescriptors::New(&encoded_data_); |
41 } | 43 } |
42 | 44 |
43 | 45 |
44 void CodeSourceMapBuilder::AddEntry(intptr_t pc_offset, | |
45 TokenPosition token_pos) { | |
46 // Require pc offset to monotonically increase. | |
47 ASSERT((prev_pc_offset < pc_offset) || | |
48 ((prev_pc_offset == 0) && (pc_offset == 0))); | |
49 CodeSourceMap::EncodeInteger(&encoded_data_, pc_offset - prev_pc_offset); | |
50 CodeSourceMap::EncodeInteger(&encoded_data_, | |
51 token_pos.value() - prev_token_pos); | |
52 | |
53 prev_pc_offset = pc_offset; | |
54 prev_token_pos = token_pos.value(); | |
55 } | |
56 | |
57 | |
58 RawCodeSourceMap* CodeSourceMapBuilder::Finalize() { | |
59 return CodeSourceMap::New(&encoded_data_); | |
60 } | |
61 | |
62 | |
63 void StackMapTableBuilder::AddEntry(intptr_t pc_offset, | 46 void StackMapTableBuilder::AddEntry(intptr_t pc_offset, |
64 BitmapBuilder* bitmap, | 47 BitmapBuilder* bitmap, |
65 intptr_t register_bit_count) { | 48 intptr_t register_bit_count) { |
66 stack_map_ = StackMap::New(pc_offset, bitmap, register_bit_count); | 49 stack_map_ = StackMap::New(pc_offset, bitmap, register_bit_count); |
67 list_.Add(stack_map_, Heap::kOld); | 50 list_.Add(stack_map_, Heap::kOld); |
68 } | 51 } |
69 | 52 |
70 | 53 |
71 bool StackMapTableBuilder::Verify() { | 54 bool StackMapTableBuilder::Verify() { |
72 intptr_t num_entries = Length(); | 55 intptr_t num_entries = Length(); |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
125 const bool has_catch_all = ContainsDynamic(*list_[i].handler_types); | 108 const bool has_catch_all = ContainsDynamic(*list_[i].handler_types); |
126 handlers.SetHandlerInfo(i, list_[i].outer_try_index, list_[i].pc_offset, | 109 handlers.SetHandlerInfo(i, list_[i].outer_try_index, list_[i].pc_offset, |
127 list_[i].needs_stacktrace, has_catch_all); | 110 list_[i].needs_stacktrace, has_catch_all); |
128 handlers.SetHandledTypes(i, *list_[i].handler_types); | 111 handlers.SetHandledTypes(i, *list_[i].handler_types); |
129 } | 112 } |
130 } | 113 } |
131 return handlers.raw(); | 114 return handlers.raw(); |
132 } | 115 } |
133 | 116 |
134 | 117 |
| 118 static uint8_t* zone_allocator(uint8_t* ptr, |
| 119 intptr_t old_size, |
| 120 intptr_t new_size) { |
| 121 Zone* zone = Thread::Current()->zone(); |
| 122 return zone->Realloc<uint8_t>(ptr, old_size, new_size); |
| 123 } |
| 124 |
| 125 |
| 126 const TokenPosition CodeSourceMapBuilder::kInitialPosition = |
| 127 TokenPosition::kDartCodePrologue; |
| 128 |
| 129 |
| 130 CodeSourceMapBuilder::CodeSourceMapBuilder( |
| 131 const GrowableArray<intptr_t>& caller_inline_id, |
| 132 const GrowableArray<TokenPosition>& inline_id_to_token_pos, |
| 133 const GrowableArray<const Function*>& inline_id_to_function) |
| 134 : pc_offset_(0), |
| 135 advance_pc_peephole_(0), |
| 136 inline_id_stack_(), |
| 137 token_pos_stack_(), |
| 138 caller_inline_id_(caller_inline_id), |
| 139 inline_id_to_token_pos_(inline_id_to_token_pos), |
| 140 inline_id_to_function_(inline_id_to_function), |
| 141 buffer_(NULL), |
| 142 stream_(&buffer_, zone_allocator, 64) { |
| 143 inline_id_stack_.Add(0); |
| 144 token_pos_stack_.Add(TokenPosition::kDartCodePrologue); |
| 145 } |
| 146 |
| 147 |
| 148 void CodeSourceMapBuilder::StartInliningInterval(int32_t pc_offset, |
| 149 intptr_t inline_id) { |
| 150 if (inline_id_stack_.Last() == inline_id) { |
| 151 // No change in function stack. |
| 152 return; |
| 153 } |
| 154 if (inline_id == -1) { |
| 155 // Basic blocking missing an inline_id. |
| 156 return; |
| 157 } |
| 158 |
| 159 // Find a minimal set of pops and pushes to bring us to the new function |
| 160 // stack. |
| 161 |
| 162 // Pop to a common ancestor. |
| 163 intptr_t common_parent = inline_id; |
| 164 while (!IsOnStack(common_parent)) { |
| 165 common_parent = caller_inline_id_[common_parent]; |
| 166 } |
| 167 while (inline_id_stack_.Last() != common_parent) { |
| 168 EmitPop(); |
| 169 inline_id_stack_.RemoveLast(); |
| 170 token_pos_stack_.RemoveLast(); |
| 171 } |
| 172 |
| 173 // Push to the new top-of-stack function. |
| 174 GrowableArray<intptr_t> to_push; |
| 175 intptr_t id = inline_id; |
| 176 while (id != common_parent) { |
| 177 to_push.Add(id); |
| 178 id = caller_inline_id_[id]; |
| 179 } |
| 180 for (intptr_t i = to_push.length() - 1; i >= 0; i--) { |
| 181 intptr_t push_id = to_push[i]; |
| 182 TokenPosition call_token; |
| 183 if (push_id != 0) { |
| 184 // TODO(rmacnak): Should make this array line up with the others. |
| 185 call_token = inline_id_to_token_pos_[push_id - 1]; |
| 186 } |
| 187 |
| 188 // Report caller as at the position of the call. |
| 189 if (call_token != token_pos_stack_.Last()) { |
| 190 EmitPosition(call_token); |
| 191 token_pos_stack_[token_pos_stack_.length() - 1] = call_token; |
| 192 } |
| 193 |
| 194 // Push the callee. |
| 195 EmitPush(push_id); |
| 196 inline_id_stack_.Add(push_id); |
| 197 token_pos_stack_.Add(TokenPosition::kDartCodePrologue); |
| 198 } |
| 199 } |
| 200 |
| 201 |
| 202 void CodeSourceMapBuilder::BeginCodeSourceRange(int32_t pc_offset) {} |
| 203 |
| 204 |
| 205 void CodeSourceMapBuilder::EndCodeSourceRange(int32_t pc_offset, |
| 206 TokenPosition pos) { |
| 207 if (pc_offset == pc_offset_) { |
| 208 return; // Empty intermediate instruction. |
| 209 } |
| 210 if (pos != token_pos_stack_.Last()) { |
| 211 EmitPosition(pos); |
| 212 token_pos_stack_[token_pos_stack_.length() - 1] = pos; |
| 213 } |
| 214 EmitAdvancePC(pc_offset - pc_offset_); |
| 215 pc_offset_ = pc_offset; |
| 216 } |
| 217 |
| 218 |
| 219 RawArray* CodeSourceMapBuilder::InliningIdToFunction() { |
| 220 if (inline_id_to_function_.length() <= 1) { |
| 221 // Not optimizing, or optimizing and nothing inlined. |
| 222 return Object::empty_array().raw(); |
| 223 } |
| 224 const Array& res = |
| 225 Array::Handle(Array::New(inline_id_to_function_.length(), Heap::kOld)); |
| 226 for (intptr_t i = 0; i < inline_id_to_function_.length(); i++) { |
| 227 res.SetAt(i, *inline_id_to_function_[i]); |
| 228 } |
| 229 return res.raw(); |
| 230 } |
| 231 |
| 232 |
| 233 RawCodeSourceMap* CodeSourceMapBuilder::Finalize() { |
| 234 FlushPeephole(); |
| 235 intptr_t length = stream_.bytes_written(); |
| 236 const CodeSourceMap& map = CodeSourceMap::Handle(CodeSourceMap::New(length)); |
| 237 NoSafepointScope no_safepoint; |
| 238 memmove(map.Data(), buffer_, length); |
| 239 return map.raw(); |
| 240 } |
| 241 |
| 242 |
| 243 void CodeSourceMapReader::GetInlinedFunctionsAt( |
| 244 int32_t pc_offset, |
| 245 GrowableArray<const Function*>* function_stack, |
| 246 GrowableArray<TokenPosition>* token_positions) { |
| 247 function_stack->Clear(); |
| 248 token_positions->Clear(); |
| 249 |
| 250 NoSafepointScope no_safepoint; |
| 251 ReadStream stream(map_.Data(), map_.Length()); |
| 252 |
| 253 int32_t current_pc_offset = 0; |
| 254 function_stack->Add(&root_); |
| 255 token_positions->Add(CodeSourceMapBuilder::kInitialPosition); |
| 256 |
| 257 while (stream.PendingBytes() > 0) { |
| 258 uint8_t opcode = stream.Read<uint8_t>(); |
| 259 switch (opcode) { |
| 260 case CodeSourceMapBuilder::kChangePosition: { |
| 261 int32_t position = stream.Read<int32_t>(); |
| 262 (*token_positions)[token_positions->length() - 1] = |
| 263 TokenPosition(position); |
| 264 break; |
| 265 } |
| 266 case CodeSourceMapBuilder::kAdvancePC: { |
| 267 int32_t delta = stream.Read<int32_t>(); |
| 268 current_pc_offset += delta; |
| 269 if (current_pc_offset > pc_offset) { |
| 270 return; |
| 271 } |
| 272 break; |
| 273 } |
| 274 case CodeSourceMapBuilder::kPushFunction: { |
| 275 int32_t func = stream.Read<int32_t>(); |
| 276 function_stack->Add( |
| 277 &Function::Handle(Function::RawCast(functions_.At(func)))); |
| 278 token_positions->Add(CodeSourceMapBuilder::kInitialPosition); |
| 279 break; |
| 280 } |
| 281 case CodeSourceMapBuilder::kPopFunction: { |
| 282 // We never pop the root function. |
| 283 ASSERT(function_stack->length() > 1); |
| 284 ASSERT(token_positions->length() > 1); |
| 285 function_stack->RemoveLast(); |
| 286 token_positions->RemoveLast(); |
| 287 break; |
| 288 } |
| 289 default: |
| 290 UNREACHABLE(); |
| 291 } |
| 292 } |
| 293 } |
| 294 |
| 295 |
| 296 #ifndef PRODUCT |
| 297 void CodeSourceMapReader::PrintJSONInlineIntervals(JSONObject* jsobj) { |
| 298 { |
| 299 JSONArray inlined_functions(jsobj, "_inlinedFunctions"); |
| 300 Function& function = Function::Handle(); |
| 301 for (intptr_t i = 0; i < functions_.Length(); i++) { |
| 302 function ^= functions_.At(i); |
| 303 ASSERT(!function.IsNull()); |
| 304 inlined_functions.AddValue(function); |
| 305 } |
| 306 } |
| 307 |
| 308 GrowableArray<intptr_t> function_stack; |
| 309 JSONArray inline_intervals(jsobj, "_inlinedIntervals"); |
| 310 NoSafepointScope no_safepoint; |
| 311 ReadStream stream(map_.Data(), map_.Length()); |
| 312 |
| 313 int32_t current_pc_offset = 0; |
| 314 function_stack.Add(0); |
| 315 |
| 316 while (stream.PendingBytes() > 0) { |
| 317 uint8_t opcode = stream.Read<uint8_t>(); |
| 318 switch (opcode) { |
| 319 case CodeSourceMapBuilder::kChangePosition: { |
| 320 stream.Read<int32_t>(); |
| 321 break; |
| 322 } |
| 323 case CodeSourceMapBuilder::kAdvancePC: { |
| 324 int32_t delta = stream.Read<int32_t>(); |
| 325 // Format: [start, end, inline functions...] |
| 326 JSONArray inline_interval(&inline_intervals); |
| 327 inline_interval.AddValue(static_cast<intptr_t>(current_pc_offset)); |
| 328 inline_interval.AddValue( |
| 329 static_cast<intptr_t>(current_pc_offset + delta - 1)); |
| 330 for (intptr_t i = 0; i < function_stack.length(); i++) { |
| 331 inline_interval.AddValue(function_stack[i]); |
| 332 } |
| 333 current_pc_offset += delta; |
| 334 break; |
| 335 } |
| 336 case CodeSourceMapBuilder::kPushFunction: { |
| 337 int32_t func = stream.Read<int32_t>(); |
| 338 function_stack.Add(func); |
| 339 break; |
| 340 } |
| 341 case CodeSourceMapBuilder::kPopFunction: { |
| 342 // We never pop the root function. |
| 343 ASSERT(function_stack.length() > 1); |
| 344 function_stack.RemoveLast(); |
| 345 break; |
| 346 } |
| 347 default: |
| 348 UNREACHABLE(); |
| 349 } |
| 350 } |
| 351 } |
| 352 #endif // !PRODUCT |
| 353 |
| 354 |
| 355 void CodeSourceMapReader::DumpInlineIntervals(uword start) { |
| 356 GrowableArray<const Function*> function_stack; |
| 357 LogBlock lb; |
| 358 NoSafepointScope no_safepoint; |
| 359 ReadStream stream(map_.Data(), map_.Length()); |
| 360 |
| 361 int32_t current_pc_offset = 0; |
| 362 function_stack.Add(&root_); |
| 363 |
| 364 THR_Print("Inline intervals {\n"); |
| 365 while (stream.PendingBytes() > 0) { |
| 366 uint8_t opcode = stream.Read<uint8_t>(); |
| 367 switch (opcode) { |
| 368 case CodeSourceMapBuilder::kChangePosition: { |
| 369 stream.Read<int32_t>(); |
| 370 break; |
| 371 } |
| 372 case CodeSourceMapBuilder::kAdvancePC: { |
| 373 int32_t delta = stream.Read<int32_t>(); |
| 374 THR_Print("%" Px "-%" Px ": ", start + current_pc_offset, |
| 375 start + current_pc_offset + delta - 1); |
| 376 for (intptr_t i = 0; i < function_stack.length(); i++) { |
| 377 THR_Print("%s ", function_stack[i]->ToCString()); |
| 378 } |
| 379 THR_Print("\n"); |
| 380 current_pc_offset += delta; |
| 381 break; |
| 382 } |
| 383 case CodeSourceMapBuilder::kPushFunction: { |
| 384 int32_t func = stream.Read<int32_t>(); |
| 385 function_stack.Add( |
| 386 &Function::Handle(Function::RawCast(functions_.At(func)))); |
| 387 break; |
| 388 } |
| 389 case CodeSourceMapBuilder::kPopFunction: { |
| 390 // We never pop the root function. |
| 391 ASSERT(function_stack.length() > 1); |
| 392 function_stack.RemoveLast(); |
| 393 break; |
| 394 } |
| 395 default: |
| 396 UNREACHABLE(); |
| 397 } |
| 398 } |
| 399 THR_Print("}\n"); |
| 400 } |
| 401 |
| 402 |
| 403 void CodeSourceMapReader::DumpSourcePositions(uword start) { |
| 404 GrowableArray<const Function*> function_stack; |
| 405 GrowableArray<TokenPosition> token_positions; |
| 406 LogBlock lb; |
| 407 NoSafepointScope no_safepoint; |
| 408 ReadStream stream(map_.Data(), map_.Length()); |
| 409 |
| 410 int32_t current_pc_offset = 0; |
| 411 function_stack.Add(&root_); |
| 412 token_positions.Add(CodeSourceMapBuilder::kInitialPosition); |
| 413 |
| 414 THR_Print("Source positions {\n"); |
| 415 while (stream.PendingBytes() > 0) { |
| 416 uint8_t opcode = stream.Read<uint8_t>(); |
| 417 switch (opcode) { |
| 418 case CodeSourceMapBuilder::kChangePosition: { |
| 419 int32_t position = stream.Read<int32_t>(); |
| 420 token_positions[token_positions.length() - 1] = TokenPosition(position); |
| 421 break; |
| 422 } |
| 423 case CodeSourceMapBuilder::kAdvancePC: { |
| 424 int32_t delta = stream.Read<int32_t>(); |
| 425 THR_Print("%" Px "-%" Px ": ", start + current_pc_offset, |
| 426 start + current_pc_offset + delta - 1); |
| 427 for (intptr_t i = 0; i < function_stack.length(); i++) { |
| 428 THR_Print("%s@%" Pd " ", function_stack[i]->ToCString(), |
| 429 token_positions[i].value()); |
| 430 } |
| 431 THR_Print("\n"); |
| 432 current_pc_offset += delta; |
| 433 break; |
| 434 } |
| 435 case CodeSourceMapBuilder::kPushFunction: { |
| 436 int32_t func = stream.Read<int32_t>(); |
| 437 function_stack.Add( |
| 438 &Function::Handle(Function::RawCast(functions_.At(func)))); |
| 439 token_positions.Add(CodeSourceMapBuilder::kInitialPosition); |
| 440 break; |
| 441 } |
| 442 case CodeSourceMapBuilder::kPopFunction: { |
| 443 // We never pop the root function. |
| 444 ASSERT(function_stack.length() > 1); |
| 445 ASSERT(token_positions.length() > 1); |
| 446 function_stack.RemoveLast(); |
| 447 token_positions.RemoveLast(); |
| 448 break; |
| 449 } |
| 450 default: |
| 451 UNREACHABLE(); |
| 452 } |
| 453 } |
| 454 THR_Print("}\n"); |
| 455 } |
| 456 |
135 } // namespace dart | 457 } // namespace dart |
OLD | NEW |