Chromium Code Reviews| 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/bigint_operations.h" | 9 #include "vm/bigint_operations.h" |
| 10 #include "vm/code_patcher.h" | 10 #include "vm/code_patcher.h" |
| (...skipping 1463 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1474 // The first incoming argument is stored at the last entry in the | 1474 // The first incoming argument is stored at the last entry in the |
| 1475 // copied frame buffer. | 1475 // copied frame buffer. |
| 1476 static void CopyFrame(const Code& optimized_code, const StackFrame& frame) { | 1476 static void CopyFrame(const Code& optimized_code, const StackFrame& frame) { |
| 1477 const Function& function = Function::Handle(optimized_code.function()); | 1477 const Function& function = Function::Handle(optimized_code.function()); |
| 1478 // Do not copy incoming arguments if there are optional arguments (they | 1478 // Do not copy incoming arguments if there are optional arguments (they |
| 1479 // are copied into local space at method entry). | 1479 // are copied into local space at method entry). |
| 1480 const intptr_t num_args = | 1480 const intptr_t num_args = |
| 1481 function.HasOptionalParameters() ? 0 : function.num_fixed_parameters(); | 1481 function.HasOptionalParameters() ? 0 : function.num_fixed_parameters(); |
| 1482 // FP, PC-marker and return-address will be copied as well. | 1482 // FP, PC-marker and return-address will be copied as well. |
| 1483 const intptr_t frame_copy_size = | 1483 const intptr_t frame_copy_size = |
| 1484 1 // Deoptimized function's return address: caller_frame->pc(). | 1484 // Deoptimized function's return address: caller_frame->pc(). |
| 1485 - kPcSlotIndexFromSp | |
| 1485 + ((frame.fp() - frame.sp()) / kWordSize) | 1486 + ((frame.fp() - frame.sp()) / kWordSize) |
| 1486 + 1 // PC marker. | 1487 + kLastParamSlotIndex |
| 1487 + 1 // Caller return address. | |
| 1488 + num_args; | 1488 + num_args; |
| 1489 intptr_t* frame_copy = new intptr_t[frame_copy_size]; | 1489 intptr_t* frame_copy = new intptr_t[frame_copy_size]; |
| 1490 ASSERT(frame_copy != NULL); | 1490 ASSERT(frame_copy != NULL); |
| 1491 // Include the return address of optimized code. | 1491 // Include the return address of optimized code. |
| 1492 intptr_t* start = reinterpret_cast<intptr_t*>(frame.sp() - kWordSize); | 1492 intptr_t* start = reinterpret_cast<intptr_t*>( |
| 1493 frame.sp() + (kPcSlotIndexFromSp * kWordSize)); | |
| 1493 for (intptr_t i = 0; i < frame_copy_size; i++) { | 1494 for (intptr_t i = 0; i < frame_copy_size; i++) { |
| 1494 frame_copy[i] = *(start + i); | 1495 frame_copy[i] = *(start + i); |
| 1495 } | 1496 } |
| 1496 Isolate::Current()->SetDeoptFrameCopy(frame_copy, frame_copy_size); | 1497 Isolate::Current()->SetDeoptFrameCopy(frame_copy, frame_copy_size); |
| 1497 } | 1498 } |
| 1498 | 1499 |
| 1499 | 1500 |
| 1500 // Copies saved registers and caller's frame into temporary buffers. | 1501 // Copies saved registers and caller's frame into temporary buffers. |
| 1501 // Returns the stack size of unoptimized frame. | 1502 // Returns the stack size of unoptimized frame. |
| 1502 DEFINE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame, | 1503 DEFINE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame, |
| 1503 uword saved_registers_address) { | 1504 uword saved_registers_address) { |
| 1504 Isolate* isolate = Isolate::Current(); | 1505 Isolate* isolate = Isolate::Current(); |
| 1505 StackZone zone(isolate); | 1506 StackZone zone(isolate); |
| 1506 HANDLESCOPE(isolate); | 1507 HANDLESCOPE(isolate); |
| 1507 | 1508 |
| 1508 // All registers have been saved below last-fp. | 1509 // All registers have been saved below last-fp. |
| 1510 // Note that the deopt stub is not allowed to save any other values (pc | |
| 1511 // marker, pool pointer, alignment, etc...) below last-fp. | |
| 1509 const uword last_fp = saved_registers_address + | 1512 const uword last_fp = saved_registers_address + |
| 1510 kNumberOfCpuRegisters * kWordSize + | 1513 kNumberOfCpuRegisters * kWordSize + |
| 1511 kNumberOfFpuRegisters * kFpuRegisterSize; | 1514 kNumberOfFpuRegisters * kFpuRegisterSize; |
| 1512 CopySavedRegisters(saved_registers_address); | 1515 CopySavedRegisters(saved_registers_address); |
| 1513 | 1516 |
| 1514 // Get optimized code and frame that need to be deoptimized. | 1517 // Get optimized code and frame that need to be deoptimized. |
| 1515 DartFrameIterator iterator(last_fp); | 1518 DartFrameIterator iterator(last_fp); |
| 1516 StackFrame* caller_frame = iterator.NextFrame(); | 1519 StackFrame* caller_frame = iterator.NextFrame(); |
| 1517 ASSERT(caller_frame != NULL); | 1520 ASSERT(caller_frame != NULL); |
| 1518 const Code& optimized_code = Code::Handle(caller_frame->LookupDartCode()); | 1521 const Code& optimized_code = Code::Handle(caller_frame->LookupDartCode()); |
| 1519 ASSERT(optimized_code.is_optimized()); | 1522 ASSERT(optimized_code.is_optimized()); |
| 1520 | 1523 |
| 1521 | |
| 1522 intptr_t deopt_reason = kDeoptUnknown; | 1524 intptr_t deopt_reason = kDeoptUnknown; |
| 1523 const DeoptInfo& deopt_info = DeoptInfo::Handle( | 1525 const DeoptInfo& deopt_info = DeoptInfo::Handle( |
| 1524 optimized_code.GetDeoptInfoAtPc(caller_frame->pc(), &deopt_reason)); | 1526 optimized_code.GetDeoptInfoAtPc(caller_frame->pc(), &deopt_reason)); |
| 1525 ASSERT(!deopt_info.IsNull()); | 1527 ASSERT(!deopt_info.IsNull()); |
| 1526 | 1528 |
| 1527 CopyFrame(optimized_code, *caller_frame); | 1529 CopyFrame(optimized_code, *caller_frame); |
| 1528 if (FLAG_trace_deoptimization) { | 1530 if (FLAG_trace_deoptimization) { |
| 1529 Function& function = Function::Handle(optimized_code.function()); | 1531 Function& function = Function::Handle(optimized_code.function()); |
| 1530 OS::PrintErr( | 1532 OS::PrintErr( |
| 1531 "Deoptimizing (reason %"Pd" '%s') at pc %#"Px" '%s' (count %d)\n", | 1533 "Deoptimizing (reason %"Pd" '%s') at pc %#"Px" '%s' (count %d)\n", |
| 1532 deopt_reason, | 1534 deopt_reason, |
| 1533 DeoptReasonToText(deopt_reason), | 1535 DeoptReasonToText(deopt_reason), |
| 1534 caller_frame->pc(), | 1536 caller_frame->pc(), |
| 1535 function.ToFullyQualifiedCString(), | 1537 function.ToFullyQualifiedCString(), |
| 1536 function.deoptimization_counter()); | 1538 function.deoptimization_counter()); |
| 1537 } | 1539 } |
| 1538 | 1540 |
| 1539 // Compute the stack size of the unoptimized frame. For functions with | 1541 // Compute the stack size of the unoptimized frame. For functions with |
| 1540 // optional arguments the deoptimization info does not describe the | 1542 // optional arguments the deoptimization info does not describe the |
| 1541 // incoming arguments. | 1543 // incoming arguments. |
| 1542 const Function& function = Function::Handle(optimized_code.function()); | 1544 const Function& function = Function::Handle(optimized_code.function()); |
| 1543 const intptr_t num_args = | 1545 const intptr_t num_args = |
| 1544 function.HasOptionalParameters() ? 0 : function.num_fixed_parameters(); | 1546 function.HasOptionalParameters() ? 0 : function.num_fixed_parameters(); |
| 1545 intptr_t unoptimized_stack_size = | 1547 intptr_t unoptimized_stack_size = |
| 1546 + deopt_info.TranslationLength() - num_args | 1548 + deopt_info.TranslationLength() - num_args |
| 1547 - 2; // Subtract caller FP and PC. | 1549 - kLastParamSlotIndex; // Subtract caller FP and PC (possibly pc marker). |
| 1548 return unoptimized_stack_size * kWordSize; | 1550 return unoptimized_stack_size * kWordSize; |
| 1549 } | 1551 } |
| 1550 END_LEAF_RUNTIME_ENTRY | 1552 END_LEAF_RUNTIME_ENTRY |
| 1551 | 1553 |
| 1552 | 1554 |
| 1553 | |
| 1554 static intptr_t DeoptimizeWithDeoptInfo(const Code& code, | 1555 static intptr_t DeoptimizeWithDeoptInfo(const Code& code, |
| 1555 const DeoptInfo& deopt_info, | 1556 const DeoptInfo& deopt_info, |
| 1556 const StackFrame& caller_frame, | 1557 const StackFrame& caller_frame, |
| 1557 intptr_t deopt_reason) { | 1558 intptr_t deopt_reason) { |
| 1558 const intptr_t len = deopt_info.TranslationLength(); | 1559 const intptr_t len = deopt_info.TranslationLength(); |
| 1559 GrowableArray<DeoptInstr*> deopt_instructions(len); | 1560 GrowableArray<DeoptInstr*> deopt_instructions(len); |
| 1560 const Array& deopt_table = Array::Handle(code.deopt_info_array()); | 1561 const Array& deopt_table = Array::Handle(code.deopt_info_array()); |
| 1561 ASSERT(!deopt_table.IsNull()); | 1562 ASSERT(!deopt_table.IsNull()); |
| 1562 deopt_info.ToInstructions(deopt_table, &deopt_instructions); | 1563 deopt_info.ToInstructions(deopt_table, &deopt_instructions); |
| 1563 | 1564 |
| 1564 intptr_t* start = reinterpret_cast<intptr_t*>(caller_frame.sp() - kWordSize); | 1565 intptr_t* start = reinterpret_cast<intptr_t*>( |
| 1566 caller_frame.sp() + (kPcSlotIndexFromSp * kWordSize)); | |
| 1565 const Function& function = Function::Handle(code.function()); | 1567 const Function& function = Function::Handle(code.function()); |
| 1566 const intptr_t num_args = | 1568 const intptr_t num_args = |
| 1567 function.HasOptionalParameters() ? 0 : function.num_fixed_parameters(); | 1569 function.HasOptionalParameters() ? 0 : function.num_fixed_parameters(); |
| 1568 intptr_t to_frame_size = | 1570 const intptr_t to_frame_size = |
| 1569 1 // Deoptimized function's return address. | 1571 - kPcSlotIndexFromSp // Deoptimized function's return address. |
| 1570 + (caller_frame.fp() - caller_frame.sp()) / kWordSize | 1572 + (caller_frame.fp() - caller_frame.sp()) / kWordSize |
| 1571 + 3 // caller-fp, pc, pc-marker. | 1573 + kLastParamSlotIndex |
|
regis
2013/05/03 00:48:58
I think 3 was wrong for IA32 and X64, but it had n
srdjan
2013/05/03 17:16:18
Thanks for fixing it.
| |
| 1572 + num_args; | 1574 + num_args; |
| 1573 DeoptimizationContext deopt_context(start, | 1575 DeoptimizationContext deopt_context(start, |
| 1574 to_frame_size, | 1576 to_frame_size, |
| 1575 Array::Handle(code.object_table()), | 1577 Array::Handle(code.object_table()), |
| 1576 num_args, | 1578 num_args, |
| 1577 static_cast<DeoptReasonId>(deopt_reason)); | 1579 static_cast<DeoptReasonId>(deopt_reason)); |
| 1578 for (intptr_t to_index = len - 1; to_index >= 0; to_index--) { | 1580 for (intptr_t to_index = len - 1; to_index >= 0; to_index--) { |
| 1579 deopt_instructions[to_index]->Execute(&deopt_context, to_index); | 1581 deopt_instructions[to_index]->Execute(&deopt_context, to_index); |
| 1580 } | 1582 } |
| 1581 if (FLAG_trace_deoptimization_verbose) { | 1583 if (FLAG_trace_deoptimization_verbose) { |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1702 // Arg1: Value that is being stored. | 1704 // Arg1: Value that is being stored. |
| 1703 DEFINE_RUNTIME_ENTRY(UpdateFieldCid, 2) { | 1705 DEFINE_RUNTIME_ENTRY(UpdateFieldCid, 2) { |
| 1704 ASSERT(arguments.ArgCount() == kUpdateFieldCidRuntimeEntry.argument_count()); | 1706 ASSERT(arguments.ArgCount() == kUpdateFieldCidRuntimeEntry.argument_count()); |
| 1705 const Field& field = Field::CheckedHandle(arguments.ArgAt(0)); | 1707 const Field& field = Field::CheckedHandle(arguments.ArgAt(0)); |
| 1706 const Object& value = Object::Handle(arguments.ArgAt(1)); | 1708 const Object& value = Object::Handle(arguments.ArgAt(1)); |
| 1707 | 1709 |
| 1708 field.UpdateCid(Class::Handle(value.clazz()).id()); | 1710 field.UpdateCid(Class::Handle(value.clazz()).id()); |
| 1709 } | 1711 } |
| 1710 | 1712 |
| 1711 } // namespace dart | 1713 } // namespace dart |
| OLD | NEW |