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 "vm/code_generator.h" | 5 #include "vm/code_generator.h" |
6 | 6 |
7 #include "vm/assembler.h" | 7 #include "vm/assembler.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" |
(...skipping 646 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
657 if (!target_function.HasCode()) { | 657 if (!target_function.HasCode()) { |
658 const Error& error = | 658 const Error& error = |
659 Error::Handle(Compiler::CompileFunction(thread, target_function)); | 659 Error::Handle(Compiler::CompileFunction(thread, target_function)); |
660 if (!error.IsNull()) { | 660 if (!error.IsNull()) { |
661 Exceptions::PropagateError(error); | 661 Exceptions::PropagateError(error); |
662 } | 662 } |
663 } | 663 } |
664 const Code& target_code = Code::Handle(target_function.CurrentCode()); | 664 const Code& target_code = Code::Handle(target_function.CurrentCode()); |
665 // Before patching verify that we are not repeatedly patching to the same | 665 // Before patching verify that we are not repeatedly patching to the same |
666 // target. | 666 // target. |
667 ASSERT(target_code.EntryPoint() != | 667 ASSERT(target_code.raw() != |
668 CodePatcher::GetStaticCallTargetAt(caller_frame->pc(), caller_code)); | 668 CodePatcher::GetStaticCallTargetAt(caller_frame->pc(), caller_code)); |
669 const Instructions& instrs = | 669 const Instructions& instrs = |
670 Instructions::Handle(caller_code.instructions()); | 670 Instructions::Handle(caller_code.instructions()); |
671 { | 671 { |
672 WritableInstructionsScope writable(instrs.EntryPoint(), instrs.size()); | 672 WritableInstructionsScope writable(instrs.EntryPoint(), instrs.size()); |
673 CodePatcher::PatchStaticCallAt(caller_frame->pc(), caller_code, | 673 CodePatcher::PatchStaticCallAt(caller_frame->pc(), |
674 target_code.EntryPoint()); | 674 caller_code, |
| 675 target_code); |
675 caller_code.SetStaticCallTargetCodeAt(caller_frame->pc(), target_code); | 676 caller_code.SetStaticCallTargetCodeAt(caller_frame->pc(), target_code); |
676 } | 677 } |
677 if (FLAG_trace_patching) { | 678 if (FLAG_trace_patching) { |
678 OS::PrintErr("PatchStaticCall: patching caller pc %#" Px "" | 679 OS::PrintErr("PatchStaticCall: patching caller pc %#" Px "" |
679 " to '%s' new entry point %#" Px " (%s)\n", | 680 " to '%s' new entry point %#" Px " (%s)\n", |
680 caller_frame->pc(), | 681 caller_frame->pc(), |
681 target_function.ToFullyQualifiedCString(), | 682 target_function.ToFullyQualifiedCString(), |
682 target_code.EntryPoint(), | 683 target_code.EntryPoint(), |
683 target_code.is_optimized() ? "optimized" : "unoptimized"); | 684 target_code.is_optimized() ? "optimized" : "unoptimized"); |
684 } | 685 } |
(...skipping 10 matching lines...) Expand all Loading... |
695 } | 696 } |
696 | 697 |
697 | 698 |
698 // Gets called from debug stub when code reaches a breakpoint | 699 // Gets called from debug stub when code reaches a breakpoint |
699 // set on a runtime stub call. | 700 // set on a runtime stub call. |
700 DEFINE_RUNTIME_ENTRY(BreakpointRuntimeHandler, 0) { | 701 DEFINE_RUNTIME_ENTRY(BreakpointRuntimeHandler, 0) { |
701 ASSERT(isolate->debugger() != NULL); | 702 ASSERT(isolate->debugger() != NULL); |
702 DartFrameIterator iterator; | 703 DartFrameIterator iterator; |
703 StackFrame* caller_frame = iterator.NextFrame(); | 704 StackFrame* caller_frame = iterator.NextFrame(); |
704 ASSERT(caller_frame != NULL); | 705 ASSERT(caller_frame != NULL); |
705 uword orig_stub = | 706 const Code& orig_stub = Code::Handle( |
706 isolate->debugger()->GetPatchedStubAddress(caller_frame->pc()); | 707 isolate->debugger()->GetPatchedStubAddress(caller_frame->pc())); |
707 isolate->debugger()->SignalBpReached(); | 708 isolate->debugger()->SignalBpReached(); |
708 ASSERT((orig_stub & kSmiTagMask) == kSmiTag); | 709 arguments.SetReturn(orig_stub); |
709 arguments.SetReturn(Smi::Handle(reinterpret_cast<RawSmi*>(orig_stub))); | |
710 } | 710 } |
711 | 711 |
712 | 712 |
713 DEFINE_RUNTIME_ENTRY(SingleStepHandler, 0) { | 713 DEFINE_RUNTIME_ENTRY(SingleStepHandler, 0) { |
714 ASSERT(isolate->debugger() != NULL); | 714 ASSERT(isolate->debugger() != NULL); |
715 isolate->debugger()->DebuggerStepCallback(); | 715 isolate->debugger()->DebuggerStepCallback(); |
716 } | 716 } |
717 | 717 |
718 | 718 |
719 // An instance call of the form o.f(...) could not be resolved. Check if | 719 // An instance call of the form o.f(...) could not be resolved. Check if |
(...skipping 549 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1269 const Code& optimized_code = Code::Handle(function.CurrentCode()); | 1269 const Code& optimized_code = Code::Handle(function.CurrentCode()); |
1270 // The current code will not be changed in the case that the compiler | 1270 // The current code will not be changed in the case that the compiler |
1271 // bailed out during OSR compilation. | 1271 // bailed out during OSR compilation. |
1272 if (optimized_code.raw() != original_code.raw()) { | 1272 if (optimized_code.raw() != original_code.raw()) { |
1273 // The OSR code does not work for calling the function, so restore the | 1273 // The OSR code does not work for calling the function, so restore the |
1274 // unoptimized code. Patch the stack frame to return into the OSR | 1274 // unoptimized code. Patch the stack frame to return into the OSR |
1275 // code. | 1275 // code. |
1276 uword optimized_entry = | 1276 uword optimized_entry = |
1277 Instructions::Handle(optimized_code.instructions()).EntryPoint(); | 1277 Instructions::Handle(optimized_code.instructions()).EntryPoint(); |
1278 function.AttachCode(original_code); | 1278 function.AttachCode(original_code); |
| 1279 // TODO(vegorov) figure out if it is GC safe. |
1279 frame->set_pc(optimized_entry); | 1280 frame->set_pc(optimized_entry); |
| 1281 frame->set_pc_marker(reinterpret_cast<uword>(optimized_code.raw())); |
1280 } | 1282 } |
1281 } | 1283 } |
1282 } | 1284 } |
1283 | 1285 |
1284 | 1286 |
1285 DEFINE_RUNTIME_ENTRY(TraceICCall, 2) { | 1287 DEFINE_RUNTIME_ENTRY(TraceICCall, 2) { |
1286 const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(0)); | 1288 const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(0)); |
1287 const Function& function = Function::CheckedHandle(arguments.ArgAt(1)); | 1289 const Function& function = Function::CheckedHandle(arguments.ArgAt(1)); |
1288 DartFrameIterator iterator; | 1290 DartFrameIterator iterator; |
1289 StackFrame* frame = iterator.NextFrame(); | 1291 StackFrame* frame = iterator.NextFrame(); |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1355 } | 1357 } |
1356 ASSERT(target_function.HasCode()); | 1358 ASSERT(target_function.HasCode()); |
1357 ASSERT(target_function.raw() == target_code.function()); | 1359 ASSERT(target_function.raw() == target_code.function()); |
1358 | 1360 |
1359 const Code& current_target_code = Code::Handle( | 1361 const Code& current_target_code = Code::Handle( |
1360 isolate, target_function.CurrentCode()); | 1362 isolate, target_function.CurrentCode()); |
1361 const Instructions& instrs = Instructions::Handle( | 1363 const Instructions& instrs = Instructions::Handle( |
1362 isolate, caller_code.instructions()); | 1364 isolate, caller_code.instructions()); |
1363 { | 1365 { |
1364 WritableInstructionsScope writable(instrs.EntryPoint(), instrs.size()); | 1366 WritableInstructionsScope writable(instrs.EntryPoint(), instrs.size()); |
1365 CodePatcher::PatchStaticCallAt(frame->pc(), caller_code, | 1367 CodePatcher::PatchStaticCallAt(frame->pc(), |
1366 current_target_code.EntryPoint()); | 1368 caller_code, |
| 1369 current_target_code); |
1367 caller_code.SetStaticCallTargetCodeAt(frame->pc(), current_target_code); | 1370 caller_code.SetStaticCallTargetCodeAt(frame->pc(), current_target_code); |
1368 } | 1371 } |
1369 if (FLAG_trace_patching) { | 1372 if (FLAG_trace_patching) { |
1370 OS::PrintErr("FixCallersTarget: caller %#" Px " " | 1373 OS::PrintErr("FixCallersTarget: caller %#" Px " " |
1371 "target '%s' %#" Px " -> %#" Px "\n", | 1374 "target '%s' %#" Px " -> %#" Px "\n", |
1372 frame->pc(), | 1375 frame->pc(), |
1373 target_function.ToFullyQualifiedCString(), | 1376 target_function.ToFullyQualifiedCString(), |
1374 target_code.EntryPoint(), | 1377 target_code.EntryPoint(), |
1375 current_target_code.EntryPoint()); | 1378 current_target_code.EntryPoint()); |
1376 } | 1379 } |
(...skipping 11 matching lines...) Expand all Loading... |
1388 frame = iterator.NextFrame(); | 1391 frame = iterator.NextFrame(); |
1389 ASSERT(frame != NULL); | 1392 ASSERT(frame != NULL); |
1390 } | 1393 } |
1391 if (frame->IsEntryFrame()) { | 1394 if (frame->IsEntryFrame()) { |
1392 // There must be a valid Dart frame. | 1395 // There must be a valid Dart frame. |
1393 UNREACHABLE(); | 1396 UNREACHABLE(); |
1394 } | 1397 } |
1395 ASSERT(frame->IsDartFrame()); | 1398 ASSERT(frame->IsDartFrame()); |
1396 const Code& caller_code = Code::Handle(isolate, frame->LookupDartCode()); | 1399 const Code& caller_code = Code::Handle(isolate, frame->LookupDartCode()); |
1397 ASSERT(!caller_code.IsNull()); | 1400 ASSERT(!caller_code.IsNull()); |
1398 const uword target = | 1401 const Code& stub = Code::Handle( |
1399 CodePatcher::GetStaticCallTargetAt(frame->pc(), caller_code); | 1402 CodePatcher::GetStaticCallTargetAt(frame->pc(), caller_code)); |
1400 const Code& stub = Code::Handle(isolate, Code::LookupCode(target)); | |
1401 Class& alloc_class = Class::ZoneHandle(zone); | 1403 Class& alloc_class = Class::ZoneHandle(zone); |
1402 alloc_class ^= stub.owner(); | 1404 alloc_class ^= stub.owner(); |
1403 Code& alloc_stub = Code::Handle(isolate, alloc_class.allocation_stub()); | 1405 Code& alloc_stub = Code::Handle(isolate, alloc_class.allocation_stub()); |
1404 if (alloc_stub.IsNull()) { | 1406 if (alloc_stub.IsNull()) { |
1405 alloc_stub = isolate->stub_code()->GetAllocationStubForClass(alloc_class); | 1407 alloc_stub = isolate->stub_code()->GetAllocationStubForClass(alloc_class); |
1406 ASSERT(!CodePatcher::IsEntryPatched(alloc_stub)); | 1408 ASSERT(!CodePatcher::IsEntryPatched(alloc_stub)); |
1407 } | 1409 } |
1408 const Instructions& instrs = | 1410 const Instructions& instrs = |
1409 Instructions::Handle(isolate, caller_code.instructions()); | 1411 Instructions::Handle(isolate, caller_code.instructions()); |
1410 { | 1412 { |
1411 WritableInstructionsScope writable(instrs.EntryPoint(), instrs.size()); | 1413 WritableInstructionsScope writable(instrs.EntryPoint(), instrs.size()); |
1412 CodePatcher::PatchStaticCallAt(frame->pc(), | 1414 CodePatcher::PatchStaticCallAt(frame->pc(), |
1413 caller_code, | 1415 caller_code, |
1414 alloc_stub.EntryPoint()); | 1416 alloc_stub); |
1415 caller_code.SetStubCallTargetCodeAt(frame->pc(), alloc_stub); | 1417 caller_code.SetStubCallTargetCodeAt(frame->pc(), alloc_stub); |
1416 } | 1418 } |
1417 if (FLAG_trace_patching) { | 1419 if (FLAG_trace_patching) { |
1418 OS::PrintErr("FixAllocationStubTarget: caller %#" Px " alloc-class %s " | 1420 OS::PrintErr("FixAllocationStubTarget: caller %#" Px " alloc-class %s " |
1419 " -> %#" Px "\n", | 1421 " -> %#" Px "\n", |
1420 frame->pc(), | 1422 frame->pc(), |
1421 alloc_class.ToCString(), | 1423 alloc_class.ToCString(), |
1422 alloc_stub.EntryPoint()); | 1424 alloc_stub.EntryPoint()); |
1423 } | 1425 } |
1424 arguments.SetReturn(alloc_stub); | 1426 arguments.SetReturn(alloc_stub); |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1517 *reinterpret_cast<intptr_t*>(saved_registers_address); | 1519 *reinterpret_cast<intptr_t*>(saved_registers_address); |
1518 saved_registers_address += kWordSize; | 1520 saved_registers_address += kWordSize; |
1519 } | 1521 } |
1520 *cpu_registers = cpu_registers_copy; | 1522 *cpu_registers = cpu_registers_copy; |
1521 } | 1523 } |
1522 | 1524 |
1523 | 1525 |
1524 // Copies saved registers and caller's frame into temporary buffers. | 1526 // Copies saved registers and caller's frame into temporary buffers. |
1525 // Returns the stack size of unoptimized frame. | 1527 // Returns the stack size of unoptimized frame. |
1526 DEFINE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame, | 1528 DEFINE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame, |
1527 1, uword saved_registers_address) { | 1529 2, |
| 1530 uword saved_registers_address, |
| 1531 uword is_lazy_deopt) { |
1528 Isolate* isolate = Isolate::Current(); | 1532 Isolate* isolate = Isolate::Current(); |
1529 StackZone zone(isolate); | 1533 StackZone zone(isolate); |
1530 HANDLESCOPE(isolate); | 1534 HANDLESCOPE(isolate); |
1531 | 1535 |
1532 // All registers have been saved below last-fp as if they were locals. | 1536 // All registers have been saved below last-fp as if they were locals. |
1533 const uword last_fp = saved_registers_address | 1537 const uword last_fp = saved_registers_address |
1534 + (kNumberOfCpuRegisters * kWordSize) | 1538 + (kNumberOfCpuRegisters * kWordSize) |
1535 + (kNumberOfFpuRegisters * kFpuRegisterSize) | 1539 + (kNumberOfFpuRegisters * kFpuRegisterSize) |
1536 - ((kFirstLocalSlotFromFp + 1) * kWordSize); | 1540 - ((kFirstLocalSlotFromFp + 1) * kWordSize); |
1537 | 1541 |
1538 // Get optimized code and frame that need to be deoptimized. | 1542 // Get optimized code and frame that need to be deoptimized. |
1539 DartFrameIterator iterator(last_fp); | 1543 DartFrameIterator iterator(last_fp); |
1540 StackFrame* caller_frame = iterator.NextFrame(); | 1544 StackFrame* caller_frame = iterator.NextFrame(); |
1541 ASSERT(caller_frame != NULL); | 1545 ASSERT(caller_frame != NULL); |
1542 const Code& optimized_code = Code::Handle(caller_frame->LookupDartCode()); | 1546 const Code& optimized_code = Code::Handle(caller_frame->LookupDartCode()); |
1543 ASSERT(optimized_code.is_optimized()); | 1547 ASSERT(optimized_code.is_optimized()); |
1544 | 1548 |
1545 // Copy the saved registers from the stack. | 1549 // Copy the saved registers from the stack. |
1546 fpu_register_t* fpu_registers; | 1550 fpu_register_t* fpu_registers; |
1547 intptr_t* cpu_registers; | 1551 intptr_t* cpu_registers; |
1548 CopySavedRegisters(saved_registers_address, &fpu_registers, &cpu_registers); | 1552 CopySavedRegisters(saved_registers_address, &fpu_registers, &cpu_registers); |
1549 | 1553 |
1550 // Create the DeoptContext. | 1554 // Create the DeoptContext. |
1551 DeoptContext* deopt_context = | 1555 DeoptContext* deopt_context = |
1552 new DeoptContext(caller_frame, optimized_code, | 1556 new DeoptContext(caller_frame, |
| 1557 optimized_code, |
1553 DeoptContext::kDestIsOriginalFrame, | 1558 DeoptContext::kDestIsOriginalFrame, |
1554 fpu_registers, cpu_registers); | 1559 fpu_registers, |
| 1560 cpu_registers, |
| 1561 is_lazy_deopt != 0); |
1555 isolate->set_deopt_context(deopt_context); | 1562 isolate->set_deopt_context(deopt_context); |
1556 | 1563 |
1557 // Stack size (FP - SP) in bytes. | 1564 // Stack size (FP - SP) in bytes. |
1558 return deopt_context->DestStackAdjustment() * kWordSize; | 1565 return deopt_context->DestStackAdjustment() * kWordSize; |
1559 } | 1566 } |
1560 END_LEAF_RUNTIME_ENTRY | 1567 END_LEAF_RUNTIME_ENTRY |
1561 | 1568 |
1562 | 1569 |
1563 // The stack has been adjusted to fit all values for unoptimized frame. | 1570 // The stack has been adjusted to fit all values for unoptimized frame. |
1564 // Fill the unoptimized frame. | 1571 // Fill the unoptimized frame. |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1684 const intptr_t elm_size = old_data.ElementSizeInBytes(); | 1691 const intptr_t elm_size = old_data.ElementSizeInBytes(); |
1685 const TypedData& new_data = | 1692 const TypedData& new_data = |
1686 TypedData::Handle(TypedData::New(cid, new_size, Heap::kOld)); | 1693 TypedData::Handle(TypedData::New(cid, new_size, Heap::kOld)); |
1687 TypedData::Copy(new_data, 0, old_data, 0, old_size * elm_size); | 1694 TypedData::Copy(new_data, 0, old_data, 0, old_size * elm_size); |
1688 typed_data_cell.SetAt(0, new_data); | 1695 typed_data_cell.SetAt(0, new_data); |
1689 arguments.SetReturn(new_data); | 1696 arguments.SetReturn(new_data); |
1690 } | 1697 } |
1691 | 1698 |
1692 | 1699 |
1693 } // namespace dart | 1700 } // namespace dart |
OLD | NEW |