| 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 |