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

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

Issue 149853004: Find all compiled copies of a function when setting breakpoint (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 10 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/debugger.h ('k') | tests/standalone/debugger/closure_bp_test.dart » ('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) 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/debugger.h" 5 #include "vm/debugger.h"
6 6
7 #include "include/dart_api.h" 7 #include "include/dart_api.h"
8 8
9 #include "vm/code_generator.h" 9 #include "vm/code_generator.h"
10 #include "vm/code_patcher.h" 10 #include "vm/code_patcher.h"
(...skipping 1349 matching lines...) Expand 10 before | Expand all | Expand 10 after
1360 } 1360 }
1361 code_bpt->set_src_bpt(bpt); 1361 code_bpt->set_src_bpt(bpt);
1362 if (bpt->IsEnabled()) { 1362 if (bpt->IsEnabled()) {
1363 code_bpt->Enable(); 1363 code_bpt->Enable();
1364 } 1364 }
1365 } 1365 }
1366 } 1366 }
1367 } 1367 }
1368 1368
1369 1369
1370 void Debugger::FindEquivalentFunctions(const Script& script, 1370 void Debugger::FindCompiledFunctions(const Script& script,
1371 intptr_t start_pos, 1371 intptr_t start_pos,
1372 intptr_t end_pos, 1372 intptr_t end_pos,
1373 GrowableObjectArray* function_list) { 1373 GrowableObjectArray* function_list) {
1374 Class& cls = Class::Handle(isolate_); 1374 Class& cls = Class::Handle(isolate_);
1375 Array& functions = Array::Handle(isolate_); 1375 Array& functions = Array::Handle(isolate_);
1376 GrowableObjectArray& closures = GrowableObjectArray::Handle(isolate_); 1376 GrowableObjectArray& closures = GrowableObjectArray::Handle(isolate_);
1377 Function& function = Function::Handle(isolate_); 1377 Function& function = Function::Handle(isolate_);
1378 1378
1379 const ClassTable& class_table = *isolate_->class_table(); 1379 const ClassTable& class_table = *isolate_->class_table();
1380 const intptr_t num_classes = class_table.NumCids(); 1380 const intptr_t num_classes = class_table.NumCids();
1381 for (intptr_t i = 1; i < num_classes; i++) { 1381 for (intptr_t i = 1; i < num_classes; i++) {
1382 if (class_table.HasValidClassAt(i)) { 1382 if (class_table.HasValidClassAt(i)) {
1383 cls = class_table.At(i); 1383 cls = class_table.At(i);
(...skipping 11 matching lines...) Expand all
1395 if (!functions.IsNull()) { 1395 if (!functions.IsNull()) {
1396 const intptr_t num_functions = functions.Length(); 1396 const intptr_t num_functions = functions.Length();
1397 for (intptr_t pos = 0; pos < num_functions; pos++) { 1397 for (intptr_t pos = 0; pos < num_functions; pos++) {
1398 function ^= functions.At(pos); 1398 function ^= functions.At(pos);
1399 ASSERT(!function.IsNull()); 1399 ASSERT(!function.IsNull());
1400 // Check token position first to avoid unnecessary calls 1400 // Check token position first to avoid unnecessary calls
1401 // to script() which allocates handles. 1401 // to script() which allocates handles.
1402 if ((function.token_pos() == start_pos) 1402 if ((function.token_pos() == start_pos)
1403 && (function.end_token_pos() == end_pos) 1403 && (function.end_token_pos() == end_pos)
1404 && (function.script() == script.raw())) { 1404 && (function.script() == script.raw())) {
1405 function_list->Add(function); 1405 if (function.HasCode()) {
1406 function_list->Add(function);
1407 }
1406 if (function.HasImplicitClosureFunction()) { 1408 if (function.HasImplicitClosureFunction()) {
1407 function = function.ImplicitClosureFunction(); 1409 function = function.ImplicitClosureFunction();
1408 function_list->Add(function); 1410 if (function.HasCode()) {
1411 function_list->Add(function);
1412 }
1409 } 1413 }
1410 } 1414 }
1411 } 1415 }
1412 } 1416 }
1413 closures = cls.closures(); 1417 closures = cls.closures();
1414 if (!closures.IsNull()) { 1418 if (!closures.IsNull()) {
1415 const intptr_t num_closures = closures.Length(); 1419 const intptr_t num_closures = closures.Length();
1416 for (intptr_t pos = 0; pos < num_closures; pos++) { 1420 for (intptr_t pos = 0; pos < num_closures; pos++) {
1417 function ^= closures.At(pos); 1421 function ^= closures.At(pos);
1418 ASSERT(!function.IsNull()); 1422 ASSERT(!function.IsNull());
1419 if ((function.token_pos() == start_pos) 1423 if ((function.token_pos() == start_pos)
1420 && (function.end_token_pos() == end_pos) 1424 && (function.end_token_pos() == end_pos)
1421 && (function.script() == script.raw())) { 1425 && (function.script() == script.raw())) {
1422 function_list->Add(function); 1426 if (function.HasCode()) {
1427 function_list->Add(function);
1428 }
1423 if (function.HasImplicitClosureFunction()) { 1429 if (function.HasImplicitClosureFunction()) {
1424 function = function.ImplicitClosureFunction(); 1430 function = function.ImplicitClosureFunction();
1425 function_list->Add(function); 1431 if (function.HasCode()) {
1432 function_list->Add(function);
1433 }
1426 } 1434 }
1427 } 1435 }
1428 } 1436 }
1429 } 1437 }
1430 } 1438 }
1431 } 1439 }
1432 } 1440 }
1433 1441
1434 1442
1435 static void SelectBestFit(Function* best_fit, Function* func) { 1443 static void SelectBestFit(Function* best_fit, Function* func) {
1436 if (best_fit->IsNull()) { 1444 if (best_fit->IsNull()) {
1437 *best_fit = func->raw(); 1445 *best_fit = func->raw();
1438 } 1446 } else {
1439 if (func->token_pos() > best_fit->token_pos()) { 1447 if ((func->token_pos() > best_fit->token_pos()) &&
1440 if (func->end_token_pos() <= best_fit->end_token_pos()) { 1448 ((func->end_token_pos() <= best_fit->end_token_pos()))) {
1441 // func is contained within best_fit. Select it even if it
1442 // has not been compiled yet.
1443 *best_fit = func->raw(); 1449 *best_fit = func->raw();
1444 if (func->HasImplicitClosureFunction()) {
1445 *func = func->ImplicitClosureFunction();
1446 if (func->HasCode()) {
1447 *best_fit = func->raw();
1448 }
1449 }
1450 } 1450 }
1451 } else if ((func->token_pos() == best_fit->token_pos())
1452 && (func->end_token_pos() == best_fit->end_token_pos())
1453 && func->HasCode()) {
1454 // If func covers the same range, it is considered a better fit if
1455 // it has been compiled.
1456 *best_fit = func->raw();
1457 } 1451 }
1458 } 1452 }
1459 1453
1460 1454
1461 RawFunction* Debugger::FindBestFit(const Script& script, 1455 RawFunction* Debugger::FindBestFit(const Script& script,
1462 intptr_t token_pos) { 1456 intptr_t token_pos) {
1463 Class& cls = Class::Handle(isolate_); 1457 Class& cls = Class::Handle(isolate_);
1464 Array& functions = Array::Handle(isolate_); 1458 Array& functions = Array::Handle(isolate_);
1465 GrowableObjectArray& closures = GrowableObjectArray::Handle(isolate_); 1459 GrowableObjectArray& closures = GrowableObjectArray::Handle(isolate_);
1466 Function& function = Function::Handle(isolate_); 1460 Function& function = Function::Handle(isolate_);
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
1511 } 1505 }
1512 1506
1513 1507
1514 SourceBreakpoint* Debugger::SetBreakpoint(const Script& script, 1508 SourceBreakpoint* Debugger::SetBreakpoint(const Script& script,
1515 intptr_t token_pos) { 1509 intptr_t token_pos) {
1516 Function& func = Function::Handle(isolate_); 1510 Function& func = Function::Handle(isolate_);
1517 func = FindBestFit(script, token_pos); 1511 func = FindBestFit(script, token_pos);
1518 if (func.IsNull()) { 1512 if (func.IsNull()) {
1519 return NULL; 1513 return NULL;
1520 } 1514 }
1521 if (!func.IsNull() && func.HasCode()) { 1515 // There may be more than one function object for a given function
1522 // A function containing this breakpoint location has already 1516 // in source code. There may be implicit closure functions, and
1523 // been compiled. We can resolve the breakpoint now. 1517 // there may be copies of mixin functions. Collect all compiled
1518 // functions whose source code range matches exactly the best fit
1519 // function we found.
1520 GrowableObjectArray& functions =
1521 GrowableObjectArray::Handle(GrowableObjectArray::New());
1522 FindCompiledFunctions(script,
1523 func.token_pos(),
1524 func.end_token_pos(),
1525 &functions);
1526
1527 if (functions.Length() > 0) {
1528 // One or more function object containing this breakpoint location
1529 // have already been compiled. We can resolve the breakpoint now.
1524 DeoptimizeWorld(); 1530 DeoptimizeWorld();
1531 func ^= functions.At(0);
1525 intptr_t breakpoint_pos = ResolveBreakpointPos(func, token_pos); 1532 intptr_t breakpoint_pos = ResolveBreakpointPos(func, token_pos);
1526 if (breakpoint_pos >= 0) { 1533 if (breakpoint_pos >= 0) {
1527 SourceBreakpoint* bpt = GetSourceBreakpoint(script, breakpoint_pos); 1534 SourceBreakpoint* bpt = GetSourceBreakpoint(script, breakpoint_pos);
1528 if (bpt != NULL) { 1535 if (bpt != NULL) {
1529 // A source breakpoint for this location already exists. 1536 // A source breakpoint for this location already exists.
1530 return bpt; 1537 return bpt;
1531 } 1538 }
1532 bpt = new SourceBreakpoint(nextId(), script, token_pos); 1539 bpt = new SourceBreakpoint(nextId(), script, token_pos);
1533 bpt->SetResolved(func, breakpoint_pos); 1540 bpt->SetResolved(func, breakpoint_pos);
1534 RegisterSourceBreakpoint(bpt); 1541 RegisterSourceBreakpoint(bpt);
1535 // There may be more than one function object for a given function 1542
1536 // in source code. There may be implicit closure functions, and 1543 // Create code breakpoints for all compiled functions we found.
1537 // there may be copies of mixin functions. Collect all functions whose
1538 // source code range matches exactly the best fit function we
1539 // found.
1540 GrowableObjectArray& functions =
1541 GrowableObjectArray::Handle(GrowableObjectArray::New());
1542 FindEquivalentFunctions(script,
1543 func.token_pos(),
1544 func.end_token_pos(),
1545 &functions);
1546 const intptr_t num_functions = functions.Length(); 1544 const intptr_t num_functions = functions.Length();
1547 // We must have found at least one function: func.
1548 ASSERT(num_functions > 0);
1549 // Create code breakpoints for all compiled functions we found.
1550 for (intptr_t i = 0; i < num_functions; i++) { 1545 for (intptr_t i = 0; i < num_functions; i++) {
1551 func ^= functions.At(i); 1546 func ^= functions.At(i);
1552 if (func.HasCode()) { 1547 ASSERT(func.HasCode());
1553 MakeCodeBreakpointsAt(func, bpt); 1548 MakeCodeBreakpointsAt(func, bpt);
1554 }
1555 } 1549 }
1556 bpt->Enable(); 1550 bpt->Enable();
1557 SignalBpResolved(bpt); 1551 SignalBpResolved(bpt);
1558 return bpt; 1552 return bpt;
1559 } 1553 }
1560 } 1554 }
1561 // There is no compiled function at this token position. 1555 // There is no compiled function at this token position.
1562 // Register an unresolved breakpoint. 1556 // Register an unresolved breakpoint.
1563 if (FLAG_verbose_debug && !func.IsNull()) { 1557 if (FLAG_verbose_debug && !func.IsNull()) {
1564 intptr_t line_number; 1558 intptr_t line_number;
(...skipping 530 matching lines...) Expand 10 before | Expand all | Expand 10 after
2095 2089
2096 void Debugger::NotifyCompilation(const Function& func) { 2090 void Debugger::NotifyCompilation(const Function& func) {
2097 if (src_breakpoints_ == NULL) { 2091 if (src_breakpoints_ == NULL) {
2098 // Return with minimal overhead if there are no breakpoints. 2092 // Return with minimal overhead if there are no breakpoints.
2099 return; 2093 return;
2100 } 2094 }
2101 // Iterate over all source breakpoints to check whether breakpoints 2095 // Iterate over all source breakpoints to check whether breakpoints
2102 // need to be set in the newly compiled function. 2096 // need to be set in the newly compiled function.
2103 Script& script = Script::Handle(isolate_); 2097 Script& script = Script::Handle(isolate_);
2104 for (SourceBreakpoint* bpt = src_breakpoints_; 2098 for (SourceBreakpoint* bpt = src_breakpoints_;
2105 bpt != NULL; 2099 bpt != NULL;
2106 bpt = bpt->next()) { 2100 bpt = bpt->next()) {
2107 script = bpt->script(); 2101 script = bpt->script();
2108 if (FunctionContains(func, script, bpt->token_pos())) { 2102 if (FunctionContains(func, script, bpt->token_pos())) {
2109 Function& inner_function = Function::Handle(isolate_); 2103 Function& inner_function = Function::Handle(isolate_);
2110 inner_function = FindInnermostClosure(func, bpt->token_pos()); 2104 inner_function = FindInnermostClosure(func, bpt->token_pos());
2111 if (!inner_function.IsNull()) { 2105 if (!inner_function.IsNull()) {
2112 // The local function of a function we just compiled cannot 2106 // The local function of a function we just compiled cannot
2113 // be compiled already. 2107 // be compiled already.
2114 ASSERT(!inner_function.HasCode()); 2108 ASSERT(!inner_function.HasCode());
2115 if (FLAG_verbose_debug) { 2109 if (FLAG_verbose_debug) {
2116 OS::Print("Pending BP remains unresolved in inner function '%s'\n", 2110 OS::Print("Pending BP remains unresolved in inner function '%s'\n",
2117 inner_function.ToFullyQualifiedCString()); 2111 inner_function.ToFullyQualifiedCString());
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
2292 } 2286 }
2293 2287
2294 2288
2295 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) { 2289 void Debugger::RegisterCodeBreakpoint(CodeBreakpoint* bpt) {
2296 ASSERT(bpt->next() == NULL); 2290 ASSERT(bpt->next() == NULL);
2297 bpt->set_next(code_breakpoints_); 2291 bpt->set_next(code_breakpoints_);
2298 code_breakpoints_ = bpt; 2292 code_breakpoints_ = bpt;
2299 } 2293 }
2300 2294
2301 } // namespace dart 2295 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/debugger.h ('k') | tests/standalone/debugger/closure_bp_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698