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/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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |