Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 <cstdio> | 5 #include <cstdio> |
| 6 | 6 |
| 7 #include "platform/utils.h" | 7 #include "platform/utils.h" |
| 8 | 8 |
| 9 #include "vm/allocation.h" | |
| 9 #include "vm/atomic.h" | 10 #include "vm/atomic.h" |
| 11 #include "vm/code_patcher.h" | |
| 10 #include "vm/isolate.h" | 12 #include "vm/isolate.h" |
| 11 #include "vm/json_stream.h" | 13 #include "vm/json_stream.h" |
| 12 #include "vm/native_symbol.h" | 14 #include "vm/native_symbol.h" |
| 13 #include "vm/object.h" | 15 #include "vm/object.h" |
| 14 #include "vm/os.h" | 16 #include "vm/os.h" |
| 15 #include "vm/profiler.h" | 17 #include "vm/profiler.h" |
| 16 #include "vm/signal_handler.h" | 18 #include "vm/signal_handler.h" |
| 17 #include "vm/simulator.h" | 19 #include "vm/simulator.h" |
| 18 | 20 |
| 19 namespace dart { | 21 namespace dart { |
| (...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 211 if ((stack_lower == 0) || (stack_upper == 0)) { | 213 if ((stack_lower == 0) || (stack_upper == 0)) { |
| 212 stack_lower = 0; | 214 stack_lower = 0; |
| 213 stack_upper = 0; | 215 stack_upper = 0; |
| 214 } | 216 } |
| 215 ProfilerSampleStackWalker stackWalker(sample, stack_lower, stack_upper, | 217 ProfilerSampleStackWalker stackWalker(sample, stack_lower, stack_upper, |
| 216 state.pc, state.fp, state.sp); | 218 state.pc, state.fp, state.sp); |
| 217 stackWalker.walk(); | 219 stackWalker.walk(); |
| 218 } | 220 } |
| 219 | 221 |
| 220 | 222 |
| 223 class SymbolLookupCache { | |
| 224 public: | |
| 225 explicit SymbolLookupCache(const intptr_t cache_size = 32) { | |
| 226 cache_index_ = 0; | |
| 227 cache_size_ = cache_size; | |
| 228 pcs_ = reinterpret_cast<uintptr_t*>( | |
| 229 calloc(cache_size, sizeof(uintptr_t))); // NOLINT | |
| 230 names_ = reinterpret_cast<const char**>( | |
| 231 calloc(cache_size, sizeof(const char*))); // NOLINT | |
| 232 } | |
| 233 | |
| 234 virtual ~SymbolLookupCache() { | |
| 235 for (intptr_t i = 0; i < cache_size_; i++) { | |
| 236 ClearCacheIndex(i); | |
| 237 } | |
| 238 free(pcs_); | |
| 239 free(names_); | |
| 240 } | |
| 241 | |
| 242 const char* Lookup(uintptr_t pc) { | |
| 243 const char* symbol = LookupInCache(pc); | |
| 244 if (symbol != NULL) { | |
| 245 return symbol; | |
| 246 } | |
| 247 symbol = QuerySource(pc); | |
| 248 if (symbol != NULL) { | |
| 249 InsertIntoCache(pc, symbol); | |
| 250 } | |
| 251 return symbol; | |
| 252 } | |
| 253 | |
| 254 virtual const char* QuerySource(uintptr_t pc) const = 0; | |
| 255 | |
| 256 protected: | |
| 257 const char* GenerateSymbolName(const char* prefix, uintptr_t pc) const { | |
| 258 // Generate a name by binning into buckets by PC. | |
| 259 const intptr_t kBucketSize = 256; | |
| 260 const intptr_t kBucketMask = ~(kBucketSize - 1); | |
| 261 pc &= kBucketMask; | |
| 262 const intptr_t kBuffSize = 256; | |
| 263 char buff[kBuffSize]; | |
| 264 OS::SNPrint(&buff[0], kBuffSize-1, "%s [%" Px ", %" Px ")", | |
| 265 prefix, pc, pc + kBucketSize); | |
| 266 return strdup(buff); | |
| 267 } | |
| 268 | |
| 269 private: | |
| 270 const char* LookupInCache(uintptr_t pc) { | |
| 271 for (intptr_t i = 0; i < cache_size_; i++) { | |
| 272 if (pcs_[i] == pc) { | |
| 273 ASSERT(names_[i] != NULL); | |
| 274 return names_[i]; | |
| 275 } | |
| 276 } | |
| 277 return NULL; | |
| 278 } | |
| 279 | |
| 280 intptr_t GetCacheIndex(uintptr_t pc) { | |
| 281 cache_index_ = (cache_index_ + 1) % cache_size_; | |
| 282 return cache_index_; | |
| 283 } | |
| 284 | |
| 285 void InsertIntoCache(uintptr_t pc, const char* name) { | |
| 286 intptr_t index = GetCacheIndex(pc); | |
| 287 ClearCacheIndex(index); | |
| 288 pcs_[index] = pc; | |
| 289 names_[index] = name; | |
| 290 } | |
| 291 | |
| 292 void ClearCacheIndex(intptr_t index) { | |
| 293 free(const_cast<char*>(names_[index])); | |
| 294 names_[index] = NULL; | |
| 295 pcs_[index] = 0; | |
| 296 } | |
| 297 | |
| 298 intptr_t cache_index_; | |
| 299 intptr_t cache_size_; | |
| 300 uintptr_t* pcs_; | |
| 301 const char** names_; | |
| 302 }; | |
| 303 | |
| 304 | |
| 305 class NativeSymbolLookup : public SymbolLookupCache { | |
| 306 public: | |
| 307 NativeSymbolLookup() : SymbolLookupCache(32) { | |
| 308 } | |
| 309 | |
| 310 const char* QuerySource(uintptr_t pc) const { | |
| 311 char* native_name = NativeSymbolResolver::LookupSymbolName(pc); | |
| 312 if (native_name == NULL) { | |
| 313 return GenerateSymbolName("Unknown", pc); | |
| 314 } | |
| 315 return native_name; | |
| 316 } | |
| 317 }; | |
| 318 | |
| 319 | |
| 320 class DartSymbolLookup : public SymbolLookupCache { | |
| 321 public: | |
| 322 explicit DartSymbolLookup(Isolate* isolate) : SymbolLookupCache(32), | |
| 323 isolate_(isolate), | |
| 324 heap_(isolate_->heap()) { | |
| 325 } | |
| 326 | |
| 327 bool InDartCodeSpace(uintptr_t pc) { | |
| 328 ASSERT(heap_ != NULL); | |
| 329 return heap_->CodeContains(pc); | |
| 330 } | |
| 331 | |
| 332 const char* QuerySource(uintptr_t pc) const { | |
| 333 const Code& code = Code::Handle(isolate_, Code::LookupCode(pc)); | |
| 334 if (!code.IsNull()) { | |
| 335 const Function& function = Function::Handle(isolate_, code.function()); | |
| 336 if (!function.IsNull()) { | |
| 337 const String& name = | |
| 338 String::Handle(isolate_, function.QualifiedUserVisibleName()); | |
| 339 if (!name.IsNull()) { | |
| 340 return strdup(name.ToCString()); | |
| 341 } | |
| 342 } else { | |
| 343 return GenerateSymbolName("Detached", pc); | |
| 344 } | |
| 345 } | |
| 346 return GenerateSymbolName("Collected", pc); | |
| 347 } | |
| 348 | |
| 349 private: | |
| 350 Isolate* isolate_; | |
| 351 Heap* heap_; | |
| 352 }; | |
| 353 | |
| 354 | |
| 355 class DartCodeTable { | |
| 356 public: | |
| 357 explicit DartCodeTable(Isolate* isolate) : | |
| 358 heap_(isolate->heap()), | |
| 359 code_table_(GrowableObjectArray::Handle(isolate)) { | |
| 360 code_table_ ^= GrowableObjectArray::New(); | |
| 361 ASSERT(!code_table_.IsNull()); | |
| 362 } | |
| 363 | |
| 364 ~DartCodeTable() { | |
| 365 } | |
| 366 | |
| 367 bool Contains(const Code& code) { | |
| 368 intptr_t length = code_table_.Length(); | |
| 369 Code& table_code = Code::Handle(); | |
| 370 for (intptr_t i = 0; i < length; i++) { | |
| 371 table_code ^= code_table_.At(i); | |
| 372 if (table_code.IsNull()) { | |
| 373 return false; | |
| 374 } | |
| 375 ASSERT(!table_code.IsNull()); | |
| 376 if (table_code.raw() == code.raw()) { | |
| 377 return true; | |
| 378 } | |
| 379 } | |
| 380 return false; | |
| 381 } | |
| 382 | |
| 383 void Add(const Code& code) { | |
| 384 ASSERT(!Contains(code)); | |
| 385 code_table_.Add(code); | |
| 386 } | |
| 387 | |
| 388 private: | |
| 389 Heap* heap_; | |
| 390 GrowableObjectArray& code_table_; | |
| 391 }; | |
| 392 | |
| 393 | |
| 394 class ProfilerSymbolHelper { | |
| 395 public: | |
| 396 explicit ProfilerSymbolHelper(Isolate* isolate) : | |
| 397 dart_symbol_(isolate), | |
| 398 code_table_(isolate) { | |
| 399 } | |
| 400 | |
| 401 ~ProfilerSymbolHelper() { | |
| 402 } | |
| 403 | |
| 404 | |
| 405 const char* GetSymbol(uintptr_t pc) { | |
| 406 if (pc == 0) { | |
| 407 return "<no frame>"; | |
| 408 } | |
| 409 if (dart_symbol_.InDartCodeSpace(pc)) { | |
|
Ivan Posva
2013/12/30 23:06:09
Restructuring this as discussed will avoid iterati
| |
| 410 return dart_symbol_.Lookup(pc); | |
| 411 } else { | |
| 412 return native_symbol_.Lookup(pc); | |
| 413 } | |
| 414 } | |
| 415 | |
| 416 | |
| 417 RawCode* GetNewCode(uintptr_t pc) { | |
| 418 Code& new_code = Code::Handle(); | |
| 419 new_code ^= Code::LookupCode(pc); | |
|
Ivan Posva
2013/12/30 23:06:09
Here you are walking through the heap again. Looki
| |
| 420 if (!new_code.IsNull()) { | |
| 421 Function& function = Function::Handle(new_code.function()); | |
| 422 if (function.IsNull()) { | |
| 423 // If code no longer has a function, ignore it. | |
| 424 new_code ^= Code::null(); | |
| 425 } else if (code_table_.Contains(new_code)) { | |
| 426 // If code has been serialized, ignore it. | |
| 427 new_code ^= Code::null(); | |
| 428 } else { | |
| 429 // Add code to code table. | |
| 430 code_table_.Add(new_code); | |
| 431 } | |
| 432 } | |
| 433 return new_code.raw(); | |
| 434 } | |
| 435 | |
| 436 private: | |
| 437 DartSymbolLookup dart_symbol_; | |
| 438 DartCodeTable code_table_; | |
| 439 NativeSymbolLookup native_symbol_; | |
| 440 }; | |
| 441 | |
| 442 | |
| 221 void Profiler::PrintToJSONStream(Isolate* isolate, JSONStream* stream) { | 443 void Profiler::PrintToJSONStream(Isolate* isolate, JSONStream* stream) { |
| 222 ASSERT(isolate == Isolate::Current()); | 444 ASSERT(isolate == Isolate::Current()); |
| 223 UNIMPLEMENTED(); | 445 // Disable profile interrupts while processing the buffer. |
| 446 EndExecution(isolate); | |
| 447 MutexLocker profiler_data_lock(isolate->profiler_data_mutex()); | |
| 448 IsolateProfilerData* profiler_data = isolate->profiler_data(); | |
| 449 if (profiler_data == NULL) { | |
| 450 return; | |
| 451 } | |
| 452 SampleBuffer* sample_buffer = profiler_data->sample_buffer(); | |
| 453 ASSERT(sample_buffer != NULL); | |
| 454 ProfilerSymbolHelper symbol_helper(isolate); | |
| 455 { | |
| 456 JSONArray events(stream); | |
| 457 for (intptr_t i = 0; i < sample_buffer->capacity(); i++) { | |
| 458 Sample sample = sample_buffer->GetSample(i); | |
| 459 if (sample.isolate != isolate) { | |
| 460 continue; | |
| 461 } | |
| 462 if (sample.timestamp == 0) { | |
| 463 continue; | |
| 464 } | |
| 465 WriteSample(isolate, &symbol_helper, &sample, events); | |
| 466 } | |
| 467 } | |
| 468 // Enable profile interrupts. | |
| 469 BeginExecution(isolate); | |
| 224 } | 470 } |
| 225 | 471 |
| 226 | 472 |
| 227 static const char* FindSymbolName(uintptr_t pc, bool* symbol_name_allocated) { | 473 void Profiler::WriteSample(Isolate* isolate, |
| 228 // TODO(johnmccutchan): Differentiate between symbols which can't be found | 474 ProfilerSymbolHelper* symbol_helper, |
| 229 // and symbols which were GCed. (Heap::CodeContains). | 475 Sample* sample, JSONArray& events) { |
| 230 ASSERT(symbol_name_allocated != NULL); | 476 StackZone zone(isolate); |
| 231 const char* symbol_name = "Unknown"; | 477 Code& new_code = Code::Handle(isolate); |
| 232 *symbol_name_allocated = false; | 478 Sample::SampleType type = sample->type; |
| 233 if (pc == 0) { | 479 if (type != Sample::kIsolateSample) { |
| 234 return const_cast<char*>(Sample::kNoFrame); | 480 return; |
| 235 } | 481 } |
| 236 const Code& code = Code::Handle(Code::LookupCode(pc)); | 482 double timestamp = static_cast<double>(sample->timestamp); |
| 237 if (!code.IsNull()) { | 483 bool any = false; |
| 238 const Function& function = Function::Handle(code.function()); | 484 for (int i = Sample::kNumStackFrames - 1; i >= 0; i--) { |
| 239 if (!function.IsNull()) { | 485 if (sample->pcs[i] == 0) { |
| 240 const String& name = String::Handle(function.QualifiedUserVisibleName()); | 486 continue; |
| 241 if (!name.IsNull()) { | 487 } |
| 242 symbol_name = name.ToCString(); | 488 any = true; |
| 243 return symbol_name; | 489 } |
| 244 } | 490 if (!any) { |
| 245 } | 491 // No frames in this sample. |
| 246 } else { | 492 return; |
| 247 // Possibly a native symbol. | 493 } |
| 248 char* native_name = NativeSymbolResolver::LookupSymbolName(pc); | |
| 249 if (native_name != NULL) { | |
| 250 symbol_name = native_name; | |
| 251 *symbol_name_allocated = true; | |
| 252 return symbol_name; | |
| 253 } | |
| 254 } | |
| 255 const intptr_t kBucketSize = 256; | |
| 256 const intptr_t kBucketMask = ~(kBucketSize - 1); | |
| 257 // Not a Dart symbol or a native symbol. Bin into buckets by PC. | |
| 258 pc &= kBucketMask; | |
| 259 { | 494 { |
| 260 const intptr_t kBuffSize = 256; | 495 JSONObject sample_event(&events); |
| 261 char buff[kBuffSize]; | 496 sample_event.AddProperty("ts", timestamp); |
| 262 OS::SNPrint(&buff[0], kBuffSize-1, "Unknown [%" Px ", %" Px ")", | 497 { |
| 263 pc, pc + kBucketSize); | 498 JSONArray frames(&sample_event, "f"); |
| 264 symbol_name = strdup(buff); | 499 for (int i = Sample::kNumStackFrames - 1; i >= 0; i--) { |
| 265 *symbol_name_allocated = true; | 500 if (sample->pcs[i] == 0) { |
| 266 } | 501 continue; |
| 267 return symbol_name; | 502 } |
| 503 const char* symbol_name = symbol_helper->GetSymbol(sample->pcs[i]); | |
| 504 new_code ^= symbol_helper->GetNewCode(sample->pcs[i]); | |
| 505 if (!new_code.IsNull()) { | |
| 506 // Dump code. | |
| 507 frames.AddValue(new_code, false); | |
| 508 } | |
| 509 { | |
| 510 JSONObject tick(&frames); | |
| 511 tick.AddProperty("s", symbol_name); | |
| 512 tick.AddPropertyF("pc", "%" Px "", sample->pcs[i]); | |
| 513 } | |
| 514 } | |
| 515 } | |
| 516 } | |
| 268 } | 517 } |
| 269 | 518 |
| 270 | 519 |
| 271 void Profiler::WriteTracingSample(Isolate* isolate, intptr_t pid, | 520 void Profiler::WriteSamples(Isolate* isolate) { |
| 272 Sample* sample, JSONArray& events) { | |
| 273 Sample::SampleType type = sample->type; | |
| 274 intptr_t tid = Thread::ThreadIdToIntPtr(sample->tid); | |
| 275 double timestamp = static_cast<double>(sample->timestamp); | |
| 276 const char* isolate_name = isolate->name(); | |
| 277 switch (type) { | |
| 278 case Sample::kIsolateStart: { | |
| 279 JSONObject begin(&events); | |
| 280 begin.AddProperty("ph", "B"); | |
| 281 begin.AddProperty("tid", tid); | |
| 282 begin.AddProperty("pid", pid); | |
| 283 begin.AddProperty("name", isolate_name); | |
| 284 begin.AddProperty("ts", timestamp); | |
| 285 } | |
| 286 break; | |
| 287 case Sample::kIsolateStop: { | |
| 288 JSONObject begin(&events); | |
| 289 begin.AddProperty("ph", "E"); | |
| 290 begin.AddProperty("tid", tid); | |
| 291 begin.AddProperty("pid", pid); | |
| 292 begin.AddProperty("name", isolate_name); | |
| 293 begin.AddProperty("ts", timestamp); | |
| 294 } | |
| 295 break; | |
| 296 case Sample::kIsolateSample: | |
| 297 // Write "B" events. | |
| 298 for (int i = Sample::kNumStackFrames - 1; i >= 0; i--) { | |
| 299 bool symbol_name_allocated = false; | |
| 300 const char* symbol_name = FindSymbolName(sample->pcs[i], | |
| 301 &symbol_name_allocated); | |
| 302 { | |
| 303 JSONObject begin(&events); | |
| 304 begin.AddProperty("ph", "B"); | |
| 305 begin.AddProperty("tid", tid); | |
| 306 begin.AddProperty("pid", pid); | |
| 307 begin.AddProperty("name", symbol_name); | |
| 308 begin.AddProperty("ts", timestamp); | |
| 309 } | |
| 310 if (symbol_name_allocated) { | |
| 311 free(const_cast<char*>(symbol_name)); | |
| 312 } | |
| 313 } | |
| 314 // Write "E" events. | |
| 315 for (int i = 0; i < Sample::kNumStackFrames; i++) { | |
| 316 bool symbol_name_allocated = false; | |
| 317 const char* symbol_name = FindSymbolName(sample->pcs[i], | |
| 318 &symbol_name_allocated); | |
| 319 { | |
| 320 JSONObject begin(&events); | |
| 321 begin.AddProperty("ph", "E"); | |
| 322 begin.AddProperty("tid", tid); | |
| 323 begin.AddProperty("pid", pid); | |
| 324 begin.AddProperty("name", symbol_name); | |
| 325 begin.AddProperty("ts", timestamp); | |
| 326 } | |
| 327 if (symbol_name_allocated) { | |
| 328 free(const_cast<char*>(symbol_name)); | |
| 329 } | |
| 330 } | |
| 331 break; | |
| 332 default: | |
| 333 UNIMPLEMENTED(); | |
| 334 } | |
| 335 } | |
| 336 | |
| 337 | |
| 338 void Profiler::WriteTracing(Isolate* isolate) { | |
| 339 if (isolate == NULL) { | 521 if (isolate == NULL) { |
| 340 return; | 522 return; |
| 341 } | 523 } |
| 342 if (!FLAG_profile) { | 524 if (!FLAG_profile) { |
| 343 return; | 525 return; |
| 344 } | 526 } |
| 345 ASSERT(initialized_); | 527 ASSERT(initialized_); |
| 346 if (FLAG_profile_dir == NULL) { | 528 if (FLAG_profile_dir == NULL) { |
| 347 return; | 529 return; |
| 348 } | 530 } |
| 349 Dart_FileOpenCallback file_open = Isolate::file_open_callback(); | 531 Dart_FileOpenCallback file_open = Isolate::file_open_callback(); |
| 350 Dart_FileCloseCallback file_close = Isolate::file_close_callback(); | 532 Dart_FileCloseCallback file_close = Isolate::file_close_callback(); |
| 351 Dart_FileWriteCallback file_write = Isolate::file_write_callback(); | 533 Dart_FileWriteCallback file_write = Isolate::file_write_callback(); |
| 352 if ((file_open == NULL) || (file_close == NULL) || (file_write == NULL)) { | 534 if ((file_open == NULL) || (file_close == NULL) || (file_write == NULL)) { |
| 353 // Embedder has not provided necessary callbacks. | 535 // Embedder has not provided necessary callbacks. |
| 354 return; | 536 return; |
| 355 } | 537 } |
| 356 // We will be looking up code objects within the isolate. | 538 // We will be looking up code objects within the isolate. |
| 357 ASSERT(Isolate::Current() != NULL); | 539 ASSERT(Isolate::Current() == isolate); |
| 358 // We do not want to be interrupted while processing the buffer. | |
| 359 EndExecution(isolate); | |
| 360 MutexLocker profiler_data_lock(isolate->profiler_data_mutex()); | |
| 361 IsolateProfilerData* profiler_data = isolate->profiler_data(); | |
| 362 if (profiler_data == NULL) { | |
| 363 return; | |
| 364 } | |
| 365 SampleBuffer* sample_buffer = profiler_data->sample_buffer(); | |
| 366 ASSERT(sample_buffer != NULL); | |
| 367 JSONStream stream(10 * MB); | 540 JSONStream stream(10 * MB); |
| 368 intptr_t pid = OS::ProcessId(); | 541 intptr_t pid = OS::ProcessId(); |
| 369 { | 542 PrintToJSONStream(isolate, &stream); |
| 370 JSONArray events(&stream); | |
| 371 { | |
| 372 JSONObject process_name(&events); | |
| 373 process_name.AddProperty("name", "process_name"); | |
| 374 process_name.AddProperty("ph", "M"); | |
| 375 process_name.AddProperty("pid", pid); | |
| 376 { | |
| 377 JSONObject args(&process_name, "args"); | |
| 378 args.AddProperty("name", "Dart VM"); | |
| 379 } | |
| 380 } | |
| 381 for (intptr_t i = 0; i < sample_buffer->capacity(); i++) { | |
| 382 Sample* sample = sample_buffer->GetSample(i); | |
| 383 if (sample->isolate != isolate) { | |
| 384 continue; | |
| 385 } | |
| 386 if (sample->timestamp == 0) { | |
| 387 continue; | |
| 388 } | |
| 389 WriteTracingSample(isolate, pid, sample, events); | |
| 390 } | |
| 391 } | |
| 392 const char* format = "%s/dart-profile-%" Pd "-%" Pd ".json"; | 543 const char* format = "%s/dart-profile-%" Pd "-%" Pd ".json"; |
| 393 intptr_t len = OS::SNPrint(NULL, 0, format, | 544 intptr_t len = OS::SNPrint(NULL, 0, format, |
| 394 FLAG_profile_dir, pid, isolate->main_port()); | 545 FLAG_profile_dir, pid, isolate->main_port()); |
| 395 char* filename = Isolate::Current()->current_zone()->Alloc<char>(len + 1); | 546 char* filename = Isolate::Current()->current_zone()->Alloc<char>(len + 1); |
| 396 OS::SNPrint(filename, len + 1, format, | 547 OS::SNPrint(filename, len + 1, format, |
| 397 FLAG_profile_dir, pid, isolate->main_port()); | 548 FLAG_profile_dir, pid, isolate->main_port()); |
| 398 void* f = file_open(filename, true); | 549 void* f = file_open(filename, true); |
| 399 if (f == NULL) { | 550 if (f == NULL) { |
| 400 // Cannot write. | 551 // Cannot write. |
| 401 return; | 552 return; |
| 402 } | 553 } |
| 403 TextBuffer* buffer = stream.buffer(); | 554 TextBuffer* buffer = stream.buffer(); |
| 404 ASSERT(buffer != NULL); | 555 ASSERT(buffer != NULL); |
| 405 file_write(buffer->buf(), buffer->length(), f); | 556 file_write(buffer->buf(), buffer->length(), f); |
| 406 file_close(f); | 557 file_close(f); |
| 407 BeginExecution(isolate); | |
| 408 } | 558 } |
| 409 | 559 |
| 410 | 560 |
| 411 IsolateProfilerData::IsolateProfilerData(SampleBuffer* sample_buffer, | 561 IsolateProfilerData::IsolateProfilerData(SampleBuffer* sample_buffer, |
| 412 bool own_sample_buffer) { | 562 bool own_sample_buffer) { |
| 413 sample_buffer_ = sample_buffer; | 563 sample_buffer_ = sample_buffer; |
| 414 own_sample_buffer_ = own_sample_buffer; | 564 own_sample_buffer_ = own_sample_buffer; |
| 415 } | 565 } |
| 416 | 566 |
| 417 | 567 |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 550 return false; | 700 return false; |
| 551 } | 701 } |
| 552 uintptr_t cursor = reinterpret_cast<uintptr_t>(fp); | 702 uintptr_t cursor = reinterpret_cast<uintptr_t>(fp); |
| 553 cursor += sizeof(fp); | 703 cursor += sizeof(fp); |
| 554 bool r = cursor >= lower_bound_ && cursor < stack_upper_; | 704 bool r = cursor >= lower_bound_ && cursor < stack_upper_; |
| 555 return r; | 705 return r; |
| 556 } | 706 } |
| 557 | 707 |
| 558 | 708 |
| 559 } // namespace dart | 709 } // namespace dart |
| OLD | NEW |