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

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

Issue 10825236: Replace deopt stubs location/register shuffling with using deopt-info. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 4 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 | « no previous file | runtime/vm/deopt_instructions.h » ('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/code_generator.h" 5 #include "vm/code_generator.h"
6 6
7 #include "vm/assembler_macros.h" 7 #include "vm/assembler_macros.h"
8 #include "vm/ast.h" 8 #include "vm/ast.h"
9 #include "vm/code_patcher.h" 9 #include "vm/code_patcher.h"
10 #include "vm/compiler.h" 10 #include "vm/compiler.h"
11 #include "vm/dart_api_impl.h" 11 #include "vm/dart_api_impl.h"
12 #include "vm/dart_entry.h" 12 #include "vm/dart_entry.h"
13 #include "vm/debugger.h" 13 #include "vm/debugger.h"
14 #include "vm/deopt_instructions.h"
14 #include "vm/exceptions.h" 15 #include "vm/exceptions.h"
15 #include "vm/intermediate_language.h" 16 #include "vm/intermediate_language.h"
16 #include "vm/object_store.h" 17 #include "vm/object_store.h"
17 #include "vm/message.h" 18 #include "vm/message.h"
18 #include "vm/message_handler.h" 19 #include "vm/message_handler.h"
20 #include "vm/parser.h"
19 #include "vm/resolver.h" 21 #include "vm/resolver.h"
20 #include "vm/runtime_entry.h" 22 #include "vm/runtime_entry.h"
21 #include "vm/stack_frame.h" 23 #include "vm/stack_frame.h"
22 #include "vm/symbols.h" 24 #include "vm/symbols.h"
23 #include "vm/verifier.h" 25 #include "vm/verifier.h"
24 26
25 namespace dart { 27 namespace dart {
26 28
27 DEFINE_FLAG(bool, inline_cache, true, "Enable inline caches"); 29 DEFINE_FLAG(bool, inline_cache, true, "Enable inline caches");
28 DEFINE_FLAG(bool, trace_deopt, false, "Trace deoptimization"); 30 DEFINE_FLAG(bool, trace_deopt, false, "Trace deoptimization");
(...skipping 1352 matching lines...) Expand 10 before | Expand all | Expand 10 after
1381 #define DEOPT_REASON_ID_TO_TEXT(name) case k##name: return #name; 1383 #define DEOPT_REASON_ID_TO_TEXT(name) case k##name: return #name;
1382 DEOPT_REASONS(DEOPT_REASON_ID_TO_TEXT) 1384 DEOPT_REASONS(DEOPT_REASON_ID_TO_TEXT)
1383 #undef DEOPT_REASON_ID_TO_TEXT 1385 #undef DEOPT_REASON_ID_TO_TEXT
1384 default: 1386 default:
1385 UNREACHABLE(); 1387 UNREACHABLE();
1386 return ""; 1388 return "";
1387 } 1389 }
1388 } 1390 }
1389 1391
1390 1392
1391 static void GetDeoptInfo(const Code& code, 1393 static void GetDeoptIxDescrAtPc(const Code& code,
1392 uword pc, 1394 uword pc,
1393 intptr_t* deopt_id, 1395 intptr_t* deopt_id,
1394 intptr_t* deopt_reason) { 1396 intptr_t* deopt_reason,
1397 intptr_t* deopt_index) {
1395 const PcDescriptors& descriptors = 1398 const PcDescriptors& descriptors =
1396 PcDescriptors::Handle(code.pc_descriptors()); 1399 PcDescriptors::Handle(code.pc_descriptors());
1397 ASSERT(!descriptors.IsNull()); 1400 ASSERT(!descriptors.IsNull());
1398 // Locate deopt id at deoptimization point inside optimized code. 1401 // Locate deopt id at deoptimization point inside optimized code.
1399 for (int i = 0; i < descriptors.Length(); i++) { 1402 for (int i = 0; i < descriptors.Length(); i++) {
1400 if ((static_cast<uword>(descriptors.PC(i)) == pc) && 1403 if ((static_cast<uword>(descriptors.PC(i)) == pc) &&
1401 (descriptors.DescriptorKind(i) == PcDescriptors::kDeoptIndex)) { 1404 (descriptors.DescriptorKind(i) == PcDescriptors::kDeoptIndex)) {
1402 *deopt_id = descriptors.DeoptId(i); 1405 *deopt_id = descriptors.DeoptId(i);
1403 *deopt_reason = descriptors.DeoptReason(i); 1406 *deopt_reason = descriptors.DeoptReason(i);
1407 *deopt_index = descriptors.DeoptIndex(i);
1404 return; 1408 return;
1405 } 1409 }
1406 } 1410 }
1407 *deopt_id = Isolate::kNoDeoptId; 1411 *deopt_id = Isolate::kNoDeoptId;
1408 *deopt_reason = kDeoptUnknown; 1412 *deopt_reason = kDeoptUnknown;
1413 *deopt_index = -1;
1409 } 1414 }
1410 1415
1411 1416
1412 // Copy saved registers and caller's frame into temporary buffers.
1413 // Access the deopt information for the deoptimization point.
1414 // Return the new stack size (including PC marker and deopt return address,
1415 // excluding FP).
1416 DEFINE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame,
1417 intptr_t* saved_registers_address) {
1418 Isolate* isolate = Isolate::Current();
1419 Zone zone(isolate);
1420 HANDLESCOPE(isolate);
1421 1417
1422 const uword last_fp = 1418 // Copy saved registers into the isolate buffer.
1423 reinterpret_cast<uword>(saved_registers_address + kNumberOfCpuRegisters); 1419 static void CopySavedRegisters(intptr_t* saved_registers_address) {
1424 // Copy saved registers.
1425 intptr_t* registers_copy = new intptr_t[kNumberOfCpuRegisters]; 1420 intptr_t* registers_copy = new intptr_t[kNumberOfCpuRegisters];
1426 ASSERT(registers_copy != NULL); 1421 ASSERT(registers_copy != NULL);
1427 ASSERT(saved_registers_address != NULL); 1422 ASSERT(saved_registers_address != NULL);
1428 for (intptr_t i = 0; i < kNumberOfCpuRegisters; i++) { 1423 for (intptr_t i = 0; i < kNumberOfCpuRegisters; i++) {
1429 registers_copy[i] = *saved_registers_address; 1424 registers_copy[i] = *saved_registers_address;
1430 saved_registers_address++; 1425 saved_registers_address++;
1431 } 1426 }
1432 isolate->set_deopt_registers_copy(registers_copy); 1427 Isolate::Current()->set_deopt_registers_copy(registers_copy);
1433 ASSERT(reinterpret_cast<uword>(saved_registers_address) == last_fp); 1428 }
1429
1430
1431 // Copy optimized frame into the isolate buffer.
1432 // The first incoming argument is stored at the last entry in the
1433 // copied frame buffer.
1434 static void CopyFrame(const Code& optimized_code, const StackFrame& frame) {
1435 const Function& function = Function::Handle(optimized_code.function());
1436 // Do not copy incoming arguments if there are optional arguments (they
1437 // are copied into local space at method entry).
1438 const intptr_t num_args = (function.num_optional_parameters() > 0) ?
1439 0 : function.num_fixed_parameters();
1440 // FP, PC-marker and return-address will be copied as well.
1441 const intptr_t frame_copy_size =
1442 1 // Deoptimized function's return address: caller_frame->pc().
1443 + ((frame.fp() - frame.sp()) / kWordSize)
1444 + 1 // PC marker.
1445 + 1 // Caller return address.
1446 + num_args;
1447 intptr_t* frame_copy = new intptr_t[frame_copy_size];
1448 ASSERT(frame_copy != NULL);
1449 // Include the return address of optimized code.
1450 intptr_t* start = reinterpret_cast<intptr_t*>(frame.sp() - kWordSize);
1451 for (intptr_t i = 0; i < frame_copy_size; i++) {
1452 frame_copy[i] = *(start + i);
1453 }
1454 Isolate::Current()->SetDeoptFrameCopy(frame_copy, frame_copy_size);
1455 }
1456
1457
1458 // Copies saved registers and caller's frame into temporary buffers.
1459 // Returns the stack size of unoptimzied frame.
1460 DEFINE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame,
1461 intptr_t* saved_registers_address) {
1462 Isolate* isolate = Isolate::Current();
1463 Zone zone(isolate);
1464 HANDLESCOPE(isolate);
1465
1466 // All registers have been saved below last-fp.
1467 const uword last_fp =
1468 reinterpret_cast<uword>(saved_registers_address + kNumberOfCpuRegisters);
1469 CopySavedRegisters(saved_registers_address);
1470
1471 // Get optimized code and frame that need to be deoptimized.
1434 DartFrameIterator iterator(last_fp); 1472 DartFrameIterator iterator(last_fp);
1435 StackFrame* caller_frame = iterator.NextFrame(); 1473 StackFrame* caller_frame = iterator.NextFrame();
1436 ASSERT(caller_frame != NULL); 1474 ASSERT(caller_frame != NULL);
1437 const Code& optimized_code = Code::Handle(caller_frame->LookupDartCode()); 1475 const Code& optimized_code = Code::Handle(caller_frame->LookupDartCode());
1438 ASSERT(optimized_code.is_optimized()); 1476 ASSERT(optimized_code.is_optimized());
1439 1477
1440 intptr_t deopt_id, deopt_reason; 1478 intptr_t deopt_id, deopt_reason, deopt_index;
1441 GetDeoptInfo(optimized_code, caller_frame->pc(), &deopt_id, &deopt_reason); 1479 GetDeoptIxDescrAtPc(optimized_code, caller_frame->pc(),
1480 &deopt_id, &deopt_reason, &deopt_index);
1442 ASSERT(deopt_id != Isolate::kNoDeoptId); 1481 ASSERT(deopt_id != Isolate::kNoDeoptId);
1443 1482
1444 // Add incoming arguments. 1483 CopyFrame(optimized_code, *caller_frame);
1445 const Function& function = Function::Handle(optimized_code.function());
1446 // Think of copied arguments.
1447 const intptr_t num_args = (function.num_optional_parameters() > 0) ?
1448 0 : function.num_fixed_parameters();
1449 // FP, PC marker and return address will all be copied.
1450 const intptr_t frame_copy_size =
1451 1 // Deoptimized function's return address: caller_frame->pc().
1452 + ((caller_frame->fp() - caller_frame->sp()) / kWordSize)
1453 + 1 // PC marker.
1454 + 1 // Caller return address.
1455 + num_args;
1456 intptr_t* frame_copy = new intptr_t[frame_copy_size];
1457 ASSERT(frame_copy != NULL);
1458 // Include the return address of deoptimized code.
1459 intptr_t* start = reinterpret_cast<intptr_t*>(caller_frame->sp() - kWordSize);
1460 for (intptr_t i = 0; i < frame_copy_size; i++) {
1461 frame_copy[i] = *(start + i);
1462 }
1463 isolate->SetDeoptFrameCopy(frame_copy, frame_copy_size);
1464 if (FLAG_trace_deopt) { 1484 if (FLAG_trace_deopt) {
1485 intptr_t deopt_id, deopt_reason, deopt_index;
1486 GetDeoptIxDescrAtPc(optimized_code, caller_frame->pc(),
1487 &deopt_id, &deopt_reason, &deopt_index);
1465 OS::Print("Deoptimizing (reason %d '%s') at pc 0x%x id %d '%s'\n", 1488 OS::Print("Deoptimizing (reason %d '%s') at pc 0x%x id %d '%s'\n",
1466 deopt_reason, 1489 deopt_reason,
1467 DeoptReasonToText(deopt_reason), 1490 DeoptReasonToText(deopt_reason),
1468 caller_frame->pc(), 1491 caller_frame->pc(),
1469 deopt_id, 1492 deopt_id,
1470 function.ToFullyQualifiedCString()); 1493 Function::Handle(optimized_code.function()).ToFullyQualifiedCString());
1471 } 1494 }
1472 // TODO(srdjan): find deopt info and the size of stack, currently stack size 1495
1473 // is the same as before. 1496 // Compute the stack size of unoptimized frame
1474 const intptr_t stack_size_in_bytes = caller_frame->fp() - caller_frame->sp(); 1497 const Array& deopt_info_array =
1475 // Include the space for return address. 1498 Array::Handle(optimized_code.deopt_info_array());
1476 return stack_size_in_bytes + kWordSize; 1499 ASSERT(!deopt_info_array.IsNull());
1500 DeoptInfo& deopt_info = DeoptInfo::Handle();
1501 deopt_info ^= deopt_info_array.At(deopt_index);
1502 if (deopt_info.IsNull()) {
1503 // TODO(srdjan): Deprecate.
1504 // Include the space for return address.
1505 intptr_t stack_size_in_bytes = caller_frame->fp() - caller_frame->sp();
1506 return stack_size_in_bytes + kWordSize;
1507 } else {
1508 // For functions with optional argument deoptimization info does not
1509 // describe incoming arguments.
1510 const Function& function = Function::Handle(optimized_code.function());
1511 const intptr_t num_args = (function.num_optional_parameters() > 0) ?
1512 0 : function.num_fixed_parameters();
1513 intptr_t unoptimized_stack_size =
1514 + deopt_info.Length() - num_args
1515 - 2; // Subtract caller FP and PC.
1516 return unoptimized_stack_size * kWordSize;
1517 }
1477 } 1518 }
1478 END_LEAF_RUNTIME_ENTRY 1519 END_LEAF_RUNTIME_ENTRY
1479 1520
1480 1521
1522
1523 static void DeoptimizeWithDeoptInfo(const Code& code,
1524 const DeoptInfo& deopt_info,
1525 const StackFrame& caller_frame) {
1526 const intptr_t len = deopt_info.Length();
1527 GrowableArray<DeoptInstr*> deopt_instructions(len);
1528 for (intptr_t i = 0; i < len; i++) {
1529 deopt_instructions.Add(DeoptInstr::Create(deopt_info.Instruction(i),
1530 deopt_info.FromIndex(i)));
1531 }
1532
1533 intptr_t* start = reinterpret_cast<intptr_t*>(caller_frame.sp() - kWordSize);
1534 const Function& function = Function::Handle(code.function());
1535 const intptr_t num_args = (function.num_optional_parameters() > 0) ?
1536 0 : function.num_fixed_parameters();
1537 intptr_t to_frame_size =
1538 1 // Deoptimized function's return address.
1539 + (caller_frame.fp() - caller_frame.sp()) / kWordSize
1540 + 3 // caller-fp, pc, pc-marker.
1541 + num_args;
1542 DeoptimizationContext deopt_context(start,
1543 to_frame_size,
1544 Array::Handle(code.object_table()),
1545 num_args);
1546 for (intptr_t to_index = 0; to_index < len; to_index++) {
1547 deopt_instructions[to_index]->Execute(&deopt_context, to_index);
1548 }
1549 if (FLAG_trace_deopt) {
1550 for (intptr_t i = 0; i < len; i++) {
1551 OS::Print("*%d. 0x%x [%s]\n",
1552 i, start[i], deopt_instructions[i]->ToCString());
1553 }
1554 }
1555 }
1556
1557
1481 // The stack has been adjusted to fit all values for unoptimized frame. 1558 // The stack has been adjusted to fit all values for unoptimized frame.
1482 // Fill the unoptimized frame. 1559 // Fill the unoptimized frame.
1483 DEFINE_LEAF_RUNTIME_ENTRY(void, DeoptimizeFillFrame, uword last_fp) { 1560 DEFINE_LEAF_RUNTIME_ENTRY(void, DeoptimizeFillFrame, uword last_fp) {
1484 Isolate* isolate = Isolate::Current(); 1561 Isolate* isolate = Isolate::Current();
1485 Zone zone(isolate); 1562 Zone zone(isolate);
1486 HANDLESCOPE(isolate); 1563 HANDLESCOPE(isolate);
1487 1564
1488 DartFrameIterator iterator(last_fp); 1565 DartFrameIterator iterator(last_fp);
1489 StackFrame* caller_frame = iterator.NextFrame(); 1566 StackFrame* caller_frame = iterator.NextFrame();
1490 ASSERT(caller_frame != NULL); 1567 ASSERT(caller_frame != NULL);
1491 const Code& optimized_code = Code::Handle(caller_frame->LookupDartCode()); 1568 const Code& optimized_code = Code::Handle(caller_frame->LookupDartCode());
1492 const Function& function = Function::Handle(optimized_code.function()); 1569 const Function& function = Function::Handle(optimized_code.function());
1493 ASSERT(!function.IsNull()); 1570 ASSERT(!function.IsNull());
1494 const Code& unoptimized_code = Code::Handle(function.unoptimized_code()); 1571 const Code& unoptimized_code = Code::Handle(function.unoptimized_code());
1495 ASSERT(!optimized_code.IsNull() && optimized_code.is_optimized()); 1572 ASSERT(!optimized_code.IsNull() && optimized_code.is_optimized());
1496 ASSERT(!unoptimized_code.IsNull() && !unoptimized_code.is_optimized()); 1573 ASSERT(!unoptimized_code.IsNull() && !unoptimized_code.is_optimized());
1497 1574
1498 intptr_t* frame_copy = isolate->deopt_frame_copy(); 1575 intptr_t* frame_copy = isolate->deopt_frame_copy();
1499 intptr_t* registers_copy = isolate->deopt_registers_copy(); 1576 intptr_t* registers_copy = isolate->deopt_registers_copy();
1500 1577
1501 intptr_t deopt_id, deopt_reason; 1578 intptr_t deopt_id, deopt_reason, deopt_index;
1502 GetDeoptInfo(optimized_code, caller_frame->pc(), &deopt_id, &deopt_reason); 1579 GetDeoptIxDescrAtPc(optimized_code, caller_frame->pc(),
1580 &deopt_id, &deopt_reason, &deopt_index);
1503 ASSERT(deopt_id != Isolate::kNoDeoptId); 1581 ASSERT(deopt_id != Isolate::kNoDeoptId);
1504 uword continue_at_pc = unoptimized_code.GetDeoptPcAtDeoptId(deopt_id); 1582 uword continue_at_pc = unoptimized_code.GetDeoptPcAtDeoptId(deopt_id);
1505 if (FLAG_trace_deopt) { 1583 if (FLAG_trace_deopt) {
1506 OS::Print(" -> continue at 0x%x\n", continue_at_pc); 1584 OS::Print(" -> continue at 0x%x\n", continue_at_pc);
1507 // TODO(srdjan): If we could allow GC, we could print the line where 1585 // TODO(srdjan): If we could allow GC, we could print the line where
1508 // deoptimization occured. 1586 // deoptimization occured.
1509 } 1587 }
1510 const intptr_t deopt_frame_copy_size = isolate->deopt_frame_copy_size(); 1588 const Array& deopt_info_array =
1511 // TODO(srdjan): Use deopt info to copy the values to right place. 1589 Array::Handle(optimized_code.deopt_info_array());
1512 const intptr_t pc_marker_index = 1590 ASSERT(!deopt_info_array.IsNull());
1513 ((caller_frame->fp() - caller_frame->sp()) / kWordSize); 1591 DeoptInfo& deopt_info = DeoptInfo::Handle();
1514 // Patch the return PC and saved PC marker in frame to point to the 1592 deopt_info ^= deopt_info_array.At(deopt_index);
1515 // unoptimized version. 1593 if (deopt_info.IsNull()) {
1516 frame_copy[0] = continue_at_pc; 1594 // TODO(srdjan): Deprecate.
1517 frame_copy[pc_marker_index] = unoptimized_code.EntryPoint() + 1595 const intptr_t deopt_frame_copy_size = isolate->deopt_frame_copy_size();
1518 AssemblerMacros::kOffsetOfSavedPCfromEntrypoint; 1596 const intptr_t pc_marker_index =
1519 intptr_t* start = reinterpret_cast<intptr_t*>(caller_frame->sp() - kWordSize); 1597 ((caller_frame->fp() - caller_frame->sp()) / kWordSize);
1520 for (intptr_t i = 0; i < deopt_frame_copy_size; i++) { 1598 // Patch the return PC and saved PC marker in frame to point to the
1521 *(start + i) = frame_copy[i]; 1599 // unoptimized version.
1600 frame_copy[0] = continue_at_pc;
1601 frame_copy[pc_marker_index] =
1602 unoptimized_code.EntryPoint() +
1603 AssemblerMacros::kOffsetOfSavedPCfromEntrypoint;
1604 intptr_t* start =
1605 reinterpret_cast<intptr_t*>(caller_frame->sp() - kWordSize);
1606 for (intptr_t i = 0; i < deopt_frame_copy_size; i++) {
1607 if (FLAG_trace_deopt) {
1608 OS::Print("%d. 0x%x\n", i, frame_copy[i]);
1609 }
1610 *(start + i) = frame_copy[i];
1611 }
1612 } else {
1613 DeoptimizeWithDeoptInfo(optimized_code, deopt_info, *caller_frame);
1522 } 1614 }
1615
1523 isolate->SetDeoptFrameCopy(NULL, 0); 1616 isolate->SetDeoptFrameCopy(NULL, 0);
1524 isolate->set_deopt_registers_copy(NULL); 1617 isolate->set_deopt_registers_copy(NULL);
1525 delete[] frame_copy; 1618 delete[] frame_copy;
1526 delete[] registers_copy; 1619 delete[] registers_copy;
1527 1620
1528 // Clear invocation counter so that the function gets optimized after 1621 // Clear invocation counter so that the function gets optimized after
1529 // classes have been collected. 1622 // classes have been collected.
1530 function.set_usage_counter(0); 1623 function.set_usage_counter(0);
1531 function.set_deoptimization_counter(function.deoptimization_counter() + 1); 1624 function.set_deoptimization_counter(function.deoptimization_counter() + 1);
1532 1625
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
1618 } 1711 }
1619 } 1712 }
1620 } 1713 }
1621 // The cache is null terminated, therefore the loop above should never 1714 // The cache is null terminated, therefore the loop above should never
1622 // terminate by itself. 1715 // terminate by itself.
1623 UNREACHABLE(); 1716 UNREACHABLE();
1624 return Code::null(); 1717 return Code::null();
1625 } 1718 }
1626 1719
1627 } // namespace dart 1720 } // namespace dart
OLDNEW
« no previous file with comments | « no previous file | runtime/vm/deopt_instructions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698