| OLD | NEW |
| 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" |
| (...skipping 1371 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1382 #define DEOPT_REASON_ID_TO_TEXT(name) case k##name: return #name; | 1382 #define DEOPT_REASON_ID_TO_TEXT(name) case k##name: return #name; |
| 1383 DEOPT_REASONS(DEOPT_REASON_ID_TO_TEXT) | 1383 DEOPT_REASONS(DEOPT_REASON_ID_TO_TEXT) |
| 1384 #undef DEOPT_REASON_ID_TO_TEXT | 1384 #undef DEOPT_REASON_ID_TO_TEXT |
| 1385 default: | 1385 default: |
| 1386 UNREACHABLE(); | 1386 UNREACHABLE(); |
| 1387 return ""; | 1387 return ""; |
| 1388 } | 1388 } |
| 1389 } | 1389 } |
| 1390 | 1390 |
| 1391 | 1391 |
| 1392 static intptr_t GetDeoptInfo(const Code& code, uword pc) { | 1392 static void GetDeoptInfo(const Code& code, |
| 1393 uword pc, |
| 1394 intptr_t* deopt_id, |
| 1395 intptr_t* deopt_reason) { |
| 1393 const PcDescriptors& descriptors = | 1396 const PcDescriptors& descriptors = |
| 1394 PcDescriptors::Handle(code.pc_descriptors()); | 1397 PcDescriptors::Handle(code.pc_descriptors()); |
| 1395 ASSERT(!descriptors.IsNull()); | 1398 ASSERT(!descriptors.IsNull()); |
| 1396 // Locate deopt id at deoptimization point inside optimized code. | 1399 // Locate deopt id at deoptimization point inside optimized code. |
| 1397 for (int i = 0; i < descriptors.Length(); i++) { | 1400 for (int i = 0; i < descriptors.Length(); i++) { |
| 1398 if (static_cast<uword>(descriptors.PC(i)) == pc) { | 1401 if ((static_cast<uword>(descriptors.PC(i)) == pc) && |
| 1399 return descriptors.DeoptId(i); | 1402 (descriptors.DescriptorKind(i) == PcDescriptors::kDeoptIndex)) { |
| 1403 *deopt_id = descriptors.DeoptId(i); |
| 1404 *deopt_reason = descriptors.DeoptReason(i); |
| 1405 return; |
| 1400 } | 1406 } |
| 1401 } | 1407 } |
| 1402 return Isolate::kNoDeoptId; | 1408 *deopt_id = Isolate::kNoDeoptId; |
| 1409 *deopt_reason = kDeoptUnknown; |
| 1403 } | 1410 } |
| 1404 | 1411 |
| 1405 | 1412 |
| 1406 // Copy saved registers and caller's frame into temporary buffers. | 1413 // Copy saved registers and caller's frame into temporary buffers. |
| 1407 // Access the deopt information for the deoptimization point. | 1414 // Access the deopt information for the deoptimization point. |
| 1408 // Return the new stack size (including PC marker and deopt return address, | 1415 // Return the new stack size (including PC marker and deopt return address, |
| 1409 // excluding FP). | 1416 // excluding FP). |
| 1410 DEFINE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame, | 1417 DEFINE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame, |
| 1411 intptr_t deopt_reason, | |
| 1412 intptr_t* saved_registers_address) { | 1418 intptr_t* saved_registers_address) { |
| 1413 Isolate* isolate = Isolate::Current(); | 1419 Isolate* isolate = Isolate::Current(); |
| 1414 Zone zone(isolate); | 1420 Zone zone(isolate); |
| 1415 HANDLESCOPE(isolate); | 1421 HANDLESCOPE(isolate); |
| 1416 | 1422 |
| 1417 const uword last_fp = | 1423 const uword last_fp = |
| 1418 reinterpret_cast<uword>(saved_registers_address + kNumberOfCpuRegisters); | 1424 reinterpret_cast<uword>(saved_registers_address + kNumberOfCpuRegisters); |
| 1419 // Copy saved registers. | 1425 // Copy saved registers. |
| 1420 intptr_t* registers_copy = new intptr_t[kNumberOfCpuRegisters]; | 1426 intptr_t* registers_copy = new intptr_t[kNumberOfCpuRegisters]; |
| 1421 ASSERT(registers_copy != NULL); | 1427 ASSERT(registers_copy != NULL); |
| 1422 ASSERT(saved_registers_address != NULL); | 1428 ASSERT(saved_registers_address != NULL); |
| 1423 for (intptr_t i = 0; i < kNumberOfCpuRegisters; i++) { | 1429 for (intptr_t i = 0; i < kNumberOfCpuRegisters; i++) { |
| 1424 registers_copy[i] = *saved_registers_address; | 1430 registers_copy[i] = *saved_registers_address; |
| 1425 saved_registers_address++; | 1431 saved_registers_address++; |
| 1426 } | 1432 } |
| 1427 isolate->set_deopt_registers_copy(registers_copy); | 1433 isolate->set_deopt_registers_copy(registers_copy); |
| 1428 ASSERT(reinterpret_cast<uword>(saved_registers_address) == last_fp); | 1434 ASSERT(reinterpret_cast<uword>(saved_registers_address) == last_fp); |
| 1429 DartFrameIterator iterator(last_fp); | 1435 DartFrameIterator iterator(last_fp); |
| 1430 StackFrame* caller_frame = iterator.NextFrame(); | 1436 StackFrame* caller_frame = iterator.NextFrame(); |
| 1431 ASSERT(caller_frame != NULL); | 1437 ASSERT(caller_frame != NULL); |
| 1432 const Code& optimized_code = Code::Handle(caller_frame->LookupDartCode()); | 1438 const Code& optimized_code = Code::Handle(caller_frame->LookupDartCode()); |
| 1433 ASSERT(optimized_code.is_optimized()); | 1439 ASSERT(optimized_code.is_optimized()); |
| 1434 | 1440 |
| 1435 const intptr_t deopt_id = GetDeoptInfo(optimized_code, caller_frame->pc()); | 1441 intptr_t deopt_id, deopt_reason; |
| 1442 GetDeoptInfo(optimized_code, caller_frame->pc(), &deopt_id, &deopt_reason); |
| 1436 ASSERT(deopt_id != Isolate::kNoDeoptId); | 1443 ASSERT(deopt_id != Isolate::kNoDeoptId); |
| 1437 | 1444 |
| 1438 // Add incoming arguments. | 1445 // Add incoming arguments. |
| 1439 const Function& function = Function::Handle(optimized_code.function()); | 1446 const Function& function = Function::Handle(optimized_code.function()); |
| 1440 // Think of copied arguments. | 1447 // Think of copied arguments. |
| 1441 const intptr_t num_args = (function.num_optional_parameters() > 0) ? | 1448 const intptr_t num_args = (function.num_optional_parameters() > 0) ? |
| 1442 0 : function.num_fixed_parameters(); | 1449 0 : function.num_fixed_parameters(); |
| 1443 // FP, PC marker and return address will all be copied. | 1450 // FP, PC marker and return address will all be copied. |
| 1444 const intptr_t frame_copy_size = | 1451 const intptr_t frame_copy_size = |
| 1445 1 // Deoptimized function's return address: caller_frame->pc(). | 1452 1 // Deoptimized function's return address: caller_frame->pc(). |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1485 const Code& optimized_code = Code::Handle(caller_frame->LookupDartCode()); | 1492 const Code& optimized_code = Code::Handle(caller_frame->LookupDartCode()); |
| 1486 const Function& function = Function::Handle(optimized_code.function()); | 1493 const Function& function = Function::Handle(optimized_code.function()); |
| 1487 ASSERT(!function.IsNull()); | 1494 ASSERT(!function.IsNull()); |
| 1488 const Code& unoptimized_code = Code::Handle(function.unoptimized_code()); | 1495 const Code& unoptimized_code = Code::Handle(function.unoptimized_code()); |
| 1489 ASSERT(!optimized_code.IsNull() && optimized_code.is_optimized()); | 1496 ASSERT(!optimized_code.IsNull() && optimized_code.is_optimized()); |
| 1490 ASSERT(!unoptimized_code.IsNull() && !unoptimized_code.is_optimized()); | 1497 ASSERT(!unoptimized_code.IsNull() && !unoptimized_code.is_optimized()); |
| 1491 | 1498 |
| 1492 intptr_t* frame_copy = isolate->deopt_frame_copy(); | 1499 intptr_t* frame_copy = isolate->deopt_frame_copy(); |
| 1493 intptr_t* registers_copy = isolate->deopt_registers_copy(); | 1500 intptr_t* registers_copy = isolate->deopt_registers_copy(); |
| 1494 | 1501 |
| 1495 intptr_t deopt_id = GetDeoptInfo(optimized_code, caller_frame->pc()); | 1502 intptr_t deopt_id, deopt_reason; |
| 1503 GetDeoptInfo(optimized_code, caller_frame->pc(), &deopt_id, &deopt_reason); |
| 1496 ASSERT(deopt_id != Isolate::kNoDeoptId); | 1504 ASSERT(deopt_id != Isolate::kNoDeoptId); |
| 1497 uword continue_at_pc = unoptimized_code.GetDeoptPcAtDeoptId(deopt_id); | 1505 uword continue_at_pc = unoptimized_code.GetDeoptPcAtDeoptId(deopt_id); |
| 1498 if (FLAG_trace_deopt) { | 1506 if (FLAG_trace_deopt) { |
| 1499 OS::Print(" -> continue at 0x%x\n", continue_at_pc); | 1507 OS::Print(" -> continue at 0x%x\n", continue_at_pc); |
| 1500 // TODO(srdjan): If we could allow GC, we could print the line where | 1508 // TODO(srdjan): If we could allow GC, we could print the line where |
| 1501 // deoptimization occured. | 1509 // deoptimization occured. |
| 1502 } | 1510 } |
| 1503 const intptr_t deopt_frame_copy_size = isolate->deopt_frame_copy_size(); | 1511 const intptr_t deopt_frame_copy_size = isolate->deopt_frame_copy_size(); |
| 1504 // TODO(srdjan): Use deopt info to copy the values to right place. | 1512 // TODO(srdjan): Use deopt info to copy the values to right place. |
| 1505 const intptr_t pc_marker_index = | 1513 const intptr_t pc_marker_index = |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1611 } | 1619 } |
| 1612 } | 1620 } |
| 1613 } | 1621 } |
| 1614 // The cache is null terminated, therefore the loop above should never | 1622 // The cache is null terminated, therefore the loop above should never |
| 1615 // terminate by itself. | 1623 // terminate by itself. |
| 1616 UNREACHABLE(); | 1624 UNREACHABLE(); |
| 1617 return Code::null(); | 1625 return Code::null(); |
| 1618 } | 1626 } |
| 1619 | 1627 |
| 1620 } // namespace dart | 1628 } // namespace dart |
| OLD | NEW |