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

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

Issue 10836020: First step toward deoptimization using deoptimization info: splits deoptimization into two steps: c… (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/isolate.h » ('j') | runtime/vm/isolate.h » ('J')
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/exceptions.h" 14 #include "vm/exceptions.h"
15 #include "vm/intermediate_language.h"
15 #include "vm/object_store.h" 16 #include "vm/object_store.h"
16 #include "vm/message.h" 17 #include "vm/message.h"
17 #include "vm/message_handler.h" 18 #include "vm/message_handler.h"
18 #include "vm/resolver.h" 19 #include "vm/resolver.h"
19 #include "vm/runtime_entry.h" 20 #include "vm/runtime_entry.h"
20 #include "vm/stack_frame.h" 21 #include "vm/stack_frame.h"
21 #include "vm/symbols.h" 22 #include "vm/symbols.h"
22 #include "vm/verifier.h" 23 #include "vm/verifier.h"
23 24
24 namespace dart { 25 namespace dart {
(...skipping 1372 matching lines...) Expand 10 before | Expand all | Expand 10 after
1397 #define DEOPT_REASON_ID_TO_TEXT(name) case k##name: return #name; 1398 #define DEOPT_REASON_ID_TO_TEXT(name) case k##name: return #name;
1398 DEOPT_REASONS(DEOPT_REASON_ID_TO_TEXT) 1399 DEOPT_REASONS(DEOPT_REASON_ID_TO_TEXT)
1399 #undef DEOPT_REASON_ID_TO_TEXT 1400 #undef DEOPT_REASON_ID_TO_TEXT
1400 default: 1401 default:
1401 UNREACHABLE(); 1402 UNREACHABLE();
1402 return ""; 1403 return "";
1403 } 1404 }
1404 } 1405 }
1405 1406
1406 1407
1407 // The top Dart frame belongs to the optimized method that needs to be 1408 static intptr_t GetDeoptInfo(const Code& code, uword pc) {
1408 // deoptimized. The pc of the Dart frame points to the deoptimization point. 1409 const PcDescriptors& descriptors =
1409 // Find the node id of the deoptimization point and find the continuation 1410 PcDescriptors::Handle(code.pc_descriptors());
1410 // pc in the unoptimized code. 1411 ASSERT(!descriptors.IsNull());
1411 // Since both unoptimized and optimized code have the same layout, we need only 1412 // Locate deopt id at deoptimization point inside optimized code.
1412 // to patch the pc of the Dart frame and to disable/enable appropriate code. 1413 for (int i = 0; i < descriptors.Length(); i++) {
1413 DEFINE_RUNTIME_ENTRY(Deoptimize, 1) { 1414 if (static_cast<uword>(descriptors.PC(i)) == pc) {
1414 ASSERT(arguments.Count() == kDeoptimizeRuntimeEntry.argument_count()); 1415 return descriptors.NodeId(i);
1415 const Smi& deoptimization_reason_id = Smi::CheckedHandle(arguments.At(0)); 1416 }
1416 DartFrameIterator iterator; 1417 }
1418 return Computation::kNoCid;
1419 }
1420
1421
1422 // Copy saved registers and caller's frame into temporary buffers.
1423 // Access the deopt information for the deoptimziation point.
siva 2012/07/31 01:59:12 deoptimization
srdjan 2012/07/31 16:21:28 Done.
1424 // Return the new stack size (including PC marker and deopt return address,
1425 // excluding FP).
1426 DEFINE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame,
1427 intptr_t deopt_reason,
1428 intptr_t* saved_registers_address) {
1429 Isolate* isolate = Isolate::Current();
1430 Zone zone(isolate);
1431 HANDLESCOPE(isolate);
1432
1433 // Copy saved registers.
1434 intptr_t* registers_copy = new intptr_t[kNumberOfCpuRegisters];
siva 2012/07/31 01:59:12 ASSERT(saved_registers_address != NULL); ASSERT(re
srdjan 2012/07/31 16:21:28 Done.
1435 for (intptr_t i = 0; i < kNumberOfCpuRegisters; i++) {
1436 registers_copy[i] = *saved_registers_address;
1437 saved_registers_address++;
1438 }
1439 isolate->set_deopt_registers_copy(registers_copy);
1440
1441 DartFrameIterator iterator(reinterpret_cast<uword>(saved_registers_address));
siva 2012/07/31 01:59:12 maybe instead of saved_registers_address you could
srdjan 2012/07/31 16:21:28 Done.
1442 StackFrame* caller_frame = iterator.NextFrame();
1443 ASSERT(caller_frame != NULL);
1444 const Code& optimized_code = Code::Handle(caller_frame->LookupDartCode());
1445 ASSERT(optimized_code.is_optimized());
1446
1447 const intptr_t deopt_id = GetDeoptInfo(optimized_code, caller_frame->pc());
1448 ASSERT(deopt_id != Computation::kNoCid);
1449
1450 // Add incoming arguments.
1451 const Function& function = Function::Handle(optimized_code.function());
1452 // Think of copied arguments.
1453 const intptr_t num_args = (function.num_optional_parameters() > 0) ?
1454 0 : function.num_fixed_parameters();
1455 // FP, PC marker and return address will all be copied.
1456 const intptr_t frame_copy_size =
1457 1 // Deoptimized function's return address: caller_frame->pc().
1458 + ((caller_frame->fp() - caller_frame->sp()) / kWordSize)
1459 + 1 // PC marker.
1460 + 1 // Caller return address.
1461 + num_args;
1462 intptr_t* frame_copy = new intptr_t[frame_copy_size];
1463 isolate->SetDeoptFrameCopy(frame_copy, frame_copy_size);
siva 2012/07/31 01:59:12 for consistency you should probably set frame_copy
srdjan 2012/07/31 16:21:28 Done.
1464 // Include the return address of deoptimized code.
1465 intptr_t* start = reinterpret_cast<intptr_t*>(caller_frame->sp() - kWordSize);
1466 for (intptr_t i = 0; i < frame_copy_size; i++) {
1467 frame_copy[i] = *(start + i);
1468 }
1469 if (FLAG_trace_deopt) {
1470 OS::Print("Deoptimizing (reason %d '%s') at pc 0x%x id %d '%s'\n",
1471 deopt_reason,
1472 DeoptReasonToText(deopt_reason),
1473 caller_frame->pc(),
1474 deopt_id,
1475 function.ToFullyQualifiedCString());
1476 }
1477 // TODO(srdjan): find deopt info and the size of stack, currently stack size
1478 // is the same as before.
1479 const intptr_t stack_size_in_bytes = caller_frame->fp() - caller_frame->sp();
1480 // Include the space for return address.
1481 return stack_size_in_bytes + kWordSize;
1482 }
1483 END_LEAF_RUNTIME_ENTRY
1484
1485
1486 // The stack has been adjusted to fit all values for unoptimized frame.
1487 // Fill the unoptimized frame.
1488 DEFINE_LEAF_RUNTIME_ENTRY(void, DeoptimizeFillFrame, uword last_fp) {
1489 Isolate* isolate = Isolate::Current();
1490 Zone zone(isolate);
1491 HANDLESCOPE(isolate);
1492
1493 DartFrameIterator iterator(last_fp);
1417 StackFrame* caller_frame = iterator.NextFrame(); 1494 StackFrame* caller_frame = iterator.NextFrame();
1418 ASSERT(caller_frame != NULL); 1495 ASSERT(caller_frame != NULL);
1419 const Code& optimized_code = Code::Handle(caller_frame->LookupDartCode()); 1496 const Code& optimized_code = Code::Handle(caller_frame->LookupDartCode());
1420 const Function& function = Function::Handle(optimized_code.function()); 1497 const Function& function = Function::Handle(optimized_code.function());
1421 ASSERT(!function.IsNull()); 1498 ASSERT(!function.IsNull());
1422 const Code& unoptimized_code = Code::Handle(function.unoptimized_code()); 1499 const Code& unoptimized_code = Code::Handle(function.unoptimized_code());
siva 2012/07/31 01:59:12 At this point it is possible that there is no unop
srdjan 2012/07/31 16:21:28 Function always refers to unoptimized code, i.e.,
1423 ASSERT(!optimized_code.IsNull() && optimized_code.is_optimized()); 1500 ASSERT(!optimized_code.IsNull() && optimized_code.is_optimized());
1424 ASSERT(!unoptimized_code.IsNull() && !unoptimized_code.is_optimized()); 1501 ASSERT(!unoptimized_code.IsNull() && !unoptimized_code.is_optimized());
1425 const PcDescriptors& descriptors = 1502
1426 PcDescriptors::Handle(optimized_code.pc_descriptors()); 1503 intptr_t* frame_copy = isolate->deopt_frame_copy();
siva 2012/07/31 01:59:12 the setter function is named SetDeoptFrameCopy and
srdjan 2012/07/31 16:21:28 SetDeoptFrameCopy sets the size and the buffer, it
1427 ASSERT(!descriptors.IsNull()); 1504 intptr_t* registers_copy = isolate->deopt_registers_copy();
siva 2012/07/31 01:59:12 Where is registers_copy used in this code?
srdjan 2012/07/31 16:21:28 Current deoptimization stubs already save the regi
1428 // Locate node id at deoptimization point inside optimized code. 1505
1429 intptr_t deopt_node_id = AstNode::kNoId; 1506 intptr_t deopt_id = GetDeoptInfo(optimized_code, caller_frame->pc());
1430 intptr_t deopt_token_index = 0; 1507 ASSERT(deopt_id != Computation::kNoCid);
1431 for (int i = 0; i < descriptors.Length(); i++) { 1508 uword continue_at_pc = unoptimized_code.GetDeoptPcAtNodeId(deopt_id);
1432 if (static_cast<uword>(descriptors.PC(i)) == caller_frame->pc()) { 1509 if (FLAG_trace_deopt) {
1433 deopt_node_id = descriptors.NodeId(i); 1510 OS::Print(" -> continue at 0x%x\n", continue_at_pc);
1434 deopt_token_index = descriptors.TokenIndex(i); 1511 // TODO(srdjan): If we could allow GC, we could print the line where
1435 break; 1512 // deoptimization occured.
1436 }
1437 } 1513 }
1438 ASSERT(deopt_node_id != AstNode::kNoId); 1514 const intptr_t deopt_frame_copy_size = isolate->deopt_frame_copy_size();
1439 uword continue_at_pc = 1515 // TODO(srdjan): Use deopt info to copy the values to right place.
1440 unoptimized_code.GetDeoptPcAtNodeId(deopt_node_id); 1516 const intptr_t pc_marker_index =
1441 ASSERT(continue_at_pc != 0); 1517 ((caller_frame->fp() - caller_frame->sp()) / kWordSize);
1442 if (FLAG_trace_deopt) {
1443 OS::Print("Deoptimizing (reason %d '%s') at pc 0x%x id %d '%s' "
1444 "-> continue at 0x%x \n",
1445 deoptimization_reason_id.Value(),
1446 DeoptReasonToText(deoptimization_reason_id.Value()),
1447 caller_frame->pc(),
1448 deopt_node_id,
1449 function.ToFullyQualifiedCString(),
1450 continue_at_pc);
1451 const Class& cls = Class::Handle(function.owner());
1452 const Script& script = Script::Handle(cls.script());
1453 intptr_t line, column;
1454 script.GetTokenLocation(deopt_token_index, &line, &column);
1455 OS::Print(" Line: %d Column: %d ", line, column);
1456 OS::Print(">> %s\n", String::Handle(script.GetLine(line)).ToCString());
1457 }
1458 // Patch the return PC and saved PC marker in frame to point to the 1518 // Patch the return PC and saved PC marker in frame to point to the
1459 // unoptimized version. 1519 // unoptimized version.
1460 caller_frame->set_pc(continue_at_pc); 1520 frame_copy[0] = continue_at_pc;
1461 caller_frame->SetEntrypointMarker( 1521 frame_copy[pc_marker_index] = unoptimized_code.EntryPoint() +
1462 unoptimized_code.EntryPoint() + 1522 AssemblerMacros::kOffsetOfSavedPCfromEntrypoint;
1463 AssemblerMacros::kOffsetOfSavedPCfromEntrypoint); 1523 intptr_t* start = reinterpret_cast<intptr_t*>(caller_frame->sp() - kWordSize);
1524 for (intptr_t i = 0; i < deopt_frame_copy_size; i++) {
1525 *(start + i) = frame_copy[i];
1526 }
1527 isolate->SetDeoptFrameCopy(NULL, 0);
1528 isolate->set_deopt_registers_copy(NULL);
1529 delete[] frame_copy;
1530 delete[] registers_copy;
1464 1531
1465 // Clear invocation counter so that the function gets optimized after 1532 // Clear invocation counter so that the function gets optimized after
1466 // types/classes have been collected. 1533 // classes have been collected.
1467 function.set_usage_counter(0); 1534 function.set_usage_counter(0);
1468 function.set_deoptimization_counter(function.deoptimization_counter() + 1); 1535 function.set_deoptimization_counter(function.deoptimization_counter() + 1);
1469 1536
1470 // We have to skip the following otherwise the compiler will complain
1471 // when it attempts to install unoptimized code into a function that
1472 // was already deoptimized.
1473 if (function.HasOptimizedCode()) { 1537 if (function.HasOptimizedCode()) {
1474 // Get unoptimized code. Compilation restores (reenables) the entry of 1538 function.SwitchToUnoptimizedCode();
1475 // unoptimized code.
1476 const Error& error = Error::Handle(Compiler::CompileFunction(function));
1477 if (!error.IsNull()) {
1478 Exceptions::PropagateError(error);
1479 }
1480 }
1481 // TODO(srdjan): Handle better complex cases, e.g. when an older optimized
1482 // code is alive on frame and gets deoptimized after the function was
1483 // optimized a second time.
1484 if (FLAG_trace_deopt) {
1485 OS::Print("After patching ->0x%x:\n", continue_at_pc);
1486 } 1539 }
1487 } 1540 }
1541 END_LEAF_RUNTIME_ENTRY
1488 1542
1489 1543
1490 // We are entering function name for a valid argument count. 1544 // We are entering function name for a valid argument count.
1491 void FunctionsCache::EnterFunctionAt(int i, 1545 void FunctionsCache::EnterFunctionAt(int i,
1492 const Array& cache, 1546 const Array& cache,
1493 const Function& function, 1547 const Function& function,
1494 int num_arguments, 1548 int num_arguments,
1495 int num_named_arguments) { 1549 int num_named_arguments) {
1496 ASSERT((i % kNumEntries) == 0); 1550 ASSERT((i % kNumEntries) == 0);
1497 ASSERT(function.AreValidArgumentCounts(num_arguments, 1551 ASSERT(function.AreValidArgumentCounts(num_arguments,
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
1568 } 1622 }
1569 } 1623 }
1570 } 1624 }
1571 // The cache is null terminated, therefore the loop above should never 1625 // The cache is null terminated, therefore the loop above should never
1572 // terminate by itself. 1626 // terminate by itself.
1573 UNREACHABLE(); 1627 UNREACHABLE();
1574 return Code::null(); 1628 return Code::null();
1575 } 1629 }
1576 1630
1577 } // namespace dart 1631 } // namespace dart
OLDNEW
« no previous file with comments | « no previous file | runtime/vm/isolate.h » ('j') | runtime/vm/isolate.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698