OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/api.h" | 7 #include "src/api.h" |
8 #include "src/arguments.h" | 8 #include "src/arguments.h" |
9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
(...skipping 1418 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1429 } else if (frame->function()->IsJSFunction()) { | 1429 } else if (frame->function()->IsJSFunction()) { |
1430 JSFunction* function = frame->function(); | 1430 JSFunction* function = frame->function(); |
1431 DCHECK(frame->LookupCode()->kind() == Code::FUNCTION); | 1431 DCHECK(frame->LookupCode()->kind() == Code::FUNCTION); |
1432 active_functions->Add(Handle<JSFunction>(function)); | 1432 active_functions->Add(Handle<JSFunction>(function)); |
1433 function->shared()->code()->set_gc_metadata(active_code_marker); | 1433 function->shared()->code()->set_gc_metadata(active_code_marker); |
1434 } | 1434 } |
1435 } | 1435 } |
1436 } | 1436 } |
1437 | 1437 |
1438 | 1438 |
1439 // Figure out how many bytes of "pc_offset" correspond to actual code by | 1439 // Count the number of calls before the current frame PC to find the |
1440 // subtracting off the bytes that correspond to constant/veneer pools. See | 1440 // corresponding PC in the newly recompiled code. |
1441 // Assembler::CheckConstPool() and Assembler::CheckVeneerPool(). Note that this | 1441 static Address ComputeNewPcForRedirect(Code* new_code, Code* old_code, |
1442 // is only useful for architectures using constant pools or veneer pools. | 1442 Address old_pc) { |
1443 static int ComputeCodeOffsetFromPcOffset(Code *code, int pc_offset) { | 1443 DCHECK_EQ(old_code->kind(), Code::FUNCTION); |
1444 DCHECK_EQ(code->kind(), Code::FUNCTION); | 1444 DCHECK_EQ(new_code->kind(), Code::FUNCTION); |
1445 DCHECK(!code->has_debug_break_slots()); | 1445 DCHECK(!old_code->has_debug_break_slots()); |
1446 DCHECK_LE(0, pc_offset); | 1446 DCHECK(new_code->has_debug_break_slots()); |
1447 DCHECK_LT(pc_offset, code->instruction_end() - code->instruction_start()); | 1447 int mask = RelocInfo::kCodeTargetMask; |
1448 | 1448 int index = 0; |
1449 int mask = RelocInfo::ModeMask(RelocInfo::CONST_POOL) | | 1449 intptr_t delta = 0; |
1450 RelocInfo::ModeMask(RelocInfo::VENEER_POOL); | 1450 for (RelocIterator it(old_code, mask); !it.done(); it.next()) { |
1451 byte *pc = code->instruction_start() + pc_offset; | 1451 RelocInfo* rinfo = it.rinfo(); |
1452 int code_offset = pc_offset; | 1452 Address current_pc = rinfo->pc(); |
1453 for (RelocIterator it(code, mask); !it.done(); it.next()) { | 1453 // The frame PC is behind the call instruction by the call instruction size. |
1454 RelocInfo* info = it.rinfo(); | 1454 if (current_pc > old_pc) break; |
1455 if (info->pc() >= pc) break; | 1455 index++; |
1456 DCHECK(RelocInfo::IsConstPool(info->rmode())); | 1456 delta = old_pc - current_pc; |
1457 code_offset -= static_cast<int>(info->data()); | |
1458 DCHECK_LE(0, code_offset); | |
1459 } | 1457 } |
1460 | 1458 |
1461 return code_offset; | 1459 RelocIterator it(new_code, mask); |
| 1460 for (int i = 1; i < index; i++) it.next(); |
| 1461 return it.rinfo()->pc() + delta; |
1462 } | 1462 } |
1463 | 1463 |
1464 | 1464 |
1465 // The inverse of ComputeCodeOffsetFromPcOffset. | 1465 // Count the number of continuations at which the current pc offset is at. |
1466 static int ComputePcOffsetFromCodeOffset(Code *code, int code_offset) { | 1466 static int ComputeContinuationIndexFromPcOffset(Code* code, int pc_offset) { |
1467 DCHECK_EQ(code->kind(), Code::FUNCTION); | 1467 DCHECK_EQ(code->kind(), Code::FUNCTION); |
1468 | 1468 DCHECK(!code->has_debug_break_slots()); |
1469 int mask = RelocInfo::kDebugBreakSlotMask | | 1469 Address pc = code->instruction_start() + pc_offset; |
1470 RelocInfo::ModeMask(RelocInfo::CONST_POOL) | | 1470 int mask = RelocInfo::ModeMask(RelocInfo::GENERATOR_CONTINUATION); |
1471 RelocInfo::ModeMask(RelocInfo::VENEER_POOL); | 1471 int index = 0; |
1472 int reloc = 0; | |
1473 for (RelocIterator it(code, mask); !it.done(); it.next()) { | 1472 for (RelocIterator it(code, mask); !it.done(); it.next()) { |
1474 RelocInfo* info = it.rinfo(); | 1473 index++; |
1475 if (info->pc() - code->instruction_start() - reloc >= code_offset) break; | 1474 RelocInfo* rinfo = it.rinfo(); |
1476 if (RelocInfo::IsDebugBreakSlot(info->rmode())) { | 1475 Address current_pc = rinfo->pc(); |
1477 reloc += Assembler::kDebugBreakSlotLength; | 1476 if (current_pc == pc) break; |
1478 } else { | 1477 DCHECK(current_pc < pc); |
1479 DCHECK(RelocInfo::IsConstPool(info->rmode())); | |
1480 reloc += static_cast<int>(info->data()); | |
1481 } | |
1482 } | 1478 } |
1483 | 1479 return index; |
1484 int pc_offset = code_offset + reloc; | |
1485 | |
1486 DCHECK_LT(code->instruction_start() + pc_offset, code->instruction_end()); | |
1487 | |
1488 return pc_offset; | |
1489 } | 1480 } |
1490 | 1481 |
1491 | 1482 |
| 1483 // Find the pc offset for the given continuation index. |
| 1484 static int ComputePcOffsetFromContinuationIndex(Code* code, int index) { |
| 1485 DCHECK_EQ(code->kind(), Code::FUNCTION); |
| 1486 DCHECK(code->has_debug_break_slots()); |
| 1487 int mask = RelocInfo::ModeMask(RelocInfo::GENERATOR_CONTINUATION); |
| 1488 RelocIterator it(code, mask); |
| 1489 for (int i = 1; i < index; i++) it.next(); |
| 1490 return static_cast<int>(it.rinfo()->pc() - code->instruction_start()); |
| 1491 } |
| 1492 |
| 1493 |
1492 static void RedirectActivationsToRecompiledCodeOnThread( | 1494 static void RedirectActivationsToRecompiledCodeOnThread( |
1493 Isolate* isolate, | 1495 Isolate* isolate, |
1494 ThreadLocalTop* top) { | 1496 ThreadLocalTop* top) { |
1495 for (JavaScriptFrameIterator it(isolate, top); !it.done(); it.Advance()) { | 1497 for (JavaScriptFrameIterator it(isolate, top); !it.done(); it.Advance()) { |
1496 JavaScriptFrame* frame = it.frame(); | 1498 JavaScriptFrame* frame = it.frame(); |
1497 | 1499 |
1498 if (frame->is_optimized() || !frame->function()->IsJSFunction()) continue; | 1500 if (frame->is_optimized() || !frame->function()->IsJSFunction()) continue; |
1499 | 1501 |
1500 JSFunction* function = frame->function(); | 1502 JSFunction* function = frame->function(); |
1501 | 1503 |
1502 DCHECK(frame->LookupCode()->kind() == Code::FUNCTION); | 1504 DCHECK(frame->LookupCode()->kind() == Code::FUNCTION); |
1503 | 1505 |
1504 Handle<Code> frame_code(frame->LookupCode()); | 1506 Handle<Code> frame_code(frame->LookupCode()); |
1505 if (frame_code->has_debug_break_slots()) continue; | 1507 if (frame_code->has_debug_break_slots()) continue; |
1506 | 1508 |
1507 Handle<Code> new_code(function->shared()->code()); | 1509 Handle<Code> new_code(function->shared()->code()); |
1508 if (new_code->kind() != Code::FUNCTION || | 1510 if (new_code->kind() != Code::FUNCTION || |
1509 !new_code->has_debug_break_slots()) { | 1511 !new_code->has_debug_break_slots()) { |
1510 continue; | 1512 continue; |
1511 } | 1513 } |
1512 | 1514 |
1513 int old_pc_offset = | 1515 Address new_pc = |
1514 static_cast<int>(frame->pc() - frame_code->instruction_start()); | 1516 ComputeNewPcForRedirect(*new_code, *frame_code, frame->pc()); |
1515 int code_offset = ComputeCodeOffsetFromPcOffset(*frame_code, old_pc_offset); | |
1516 int new_pc_offset = ComputePcOffsetFromCodeOffset(*new_code, code_offset); | |
1517 | |
1518 // Compute the equivalent pc in the new code. | |
1519 byte* new_pc = new_code->instruction_start() + new_pc_offset; | |
1520 | 1517 |
1521 if (FLAG_trace_deopt) { | 1518 if (FLAG_trace_deopt) { |
1522 PrintF("Replacing code %08" V8PRIxPTR " - %08" V8PRIxPTR " (%d) " | 1519 PrintF("Replacing code %08" V8PRIxPTR " - %08" V8PRIxPTR " (%d) " |
1523 "with %08" V8PRIxPTR " - %08" V8PRIxPTR " (%d) " | 1520 "with %08" V8PRIxPTR " - %08" V8PRIxPTR " (%d) " |
1524 "for debugging, " | 1521 "for debugging, " |
1525 "changing pc from %08" V8PRIxPTR " to %08" V8PRIxPTR "\n", | 1522 "changing pc from %08" V8PRIxPTR " to %08" V8PRIxPTR "\n", |
1526 reinterpret_cast<intptr_t>( | 1523 reinterpret_cast<intptr_t>( |
1527 frame_code->instruction_start()), | 1524 frame_code->instruction_start()), |
1528 reinterpret_cast<intptr_t>( | 1525 reinterpret_cast<intptr_t>( |
1529 frame_code->instruction_start()) + | 1526 frame_code->instruction_start()) + |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1596 } | 1593 } |
1597 | 1594 |
1598 | 1595 |
1599 static void RecompileAndRelocateSuspendedGenerators( | 1596 static void RecompileAndRelocateSuspendedGenerators( |
1600 const List<Handle<JSGeneratorObject> > &generators) { | 1597 const List<Handle<JSGeneratorObject> > &generators) { |
1601 for (int i = 0; i < generators.length(); i++) { | 1598 for (int i = 0; i < generators.length(); i++) { |
1602 Handle<JSFunction> fun(generators[i]->function()); | 1599 Handle<JSFunction> fun(generators[i]->function()); |
1603 | 1600 |
1604 EnsureFunctionHasDebugBreakSlots(fun); | 1601 EnsureFunctionHasDebugBreakSlots(fun); |
1605 | 1602 |
1606 int code_offset = generators[i]->continuation(); | 1603 int index = generators[i]->continuation(); |
1607 int pc_offset = ComputePcOffsetFromCodeOffset(fun->code(), code_offset); | 1604 int pc_offset = ComputePcOffsetFromContinuationIndex(fun->code(), index); |
1608 generators[i]->set_continuation(pc_offset); | 1605 generators[i]->set_continuation(pc_offset); |
1609 } | 1606 } |
1610 } | 1607 } |
1611 | 1608 |
1612 | 1609 |
1613 static bool SkipSharedFunctionInfo(SharedFunctionInfo* shared, | 1610 static bool SkipSharedFunctionInfo(SharedFunctionInfo* shared, |
1614 Object* active_code_marker) { | 1611 Object* active_code_marker) { |
1615 if (!shared->allows_lazy_compilation()) return true; | 1612 if (!shared->allows_lazy_compilation()) return true; |
1616 Object* script = shared->script(); | 1613 Object* script = shared->script(); |
1617 if (!script->IsScript()) return true; | 1614 if (!script->IsScript()) return true; |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1719 JSGeneratorObject* gen = JSGeneratorObject::cast(obj); | 1716 JSGeneratorObject* gen = JSGeneratorObject::cast(obj); |
1720 if (!gen->is_suspended()) continue; | 1717 if (!gen->is_suspended()) continue; |
1721 | 1718 |
1722 JSFunction* fun = gen->function(); | 1719 JSFunction* fun = gen->function(); |
1723 DCHECK_EQ(fun->code()->kind(), Code::FUNCTION); | 1720 DCHECK_EQ(fun->code()->kind(), Code::FUNCTION); |
1724 if (fun->code()->has_debug_break_slots()) continue; | 1721 if (fun->code()->has_debug_break_slots()) continue; |
1725 | 1722 |
1726 int pc_offset = gen->continuation(); | 1723 int pc_offset = gen->continuation(); |
1727 DCHECK_LT(0, pc_offset); | 1724 DCHECK_LT(0, pc_offset); |
1728 | 1725 |
1729 int code_offset = | 1726 int index = |
1730 ComputeCodeOffsetFromPcOffset(fun->code(), pc_offset); | 1727 ComputeContinuationIndexFromPcOffset(fun->code(), pc_offset); |
1731 | 1728 |
1732 // This will be fixed after we recompile the functions. | 1729 // This will be fixed after we recompile the functions. |
1733 gen->set_continuation(code_offset); | 1730 gen->set_continuation(index); |
1734 | 1731 |
1735 suspended_generators.Add(Handle<JSGeneratorObject>(gen, isolate_)); | 1732 suspended_generators.Add(Handle<JSGeneratorObject>(gen, isolate_)); |
1736 } else if (obj->IsSharedFunctionInfo()) { | 1733 } else if (obj->IsSharedFunctionInfo()) { |
1737 SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj); | 1734 SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj); |
1738 if (SkipSharedFunctionInfo(shared, active_code_marker)) continue; | 1735 if (SkipSharedFunctionInfo(shared, active_code_marker)) continue; |
1739 if (shared->is_generator()) continue; | 1736 if (shared->is_generator()) continue; |
1740 if (HasDebugBreakSlots(shared->code())) continue; | 1737 if (HasDebugBreakSlots(shared->code())) continue; |
1741 shared->ReplaceCode(*lazy_compile); | 1738 shared->ReplaceCode(*lazy_compile); |
1742 } | 1739 } |
1743 } | 1740 } |
(...skipping 1449 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3193 masm->RecordDebugBreakSlotForCall(call_argc); | 3190 masm->RecordDebugBreakSlotForCall(call_argc); |
3194 return; | 3191 return; |
3195 case DEBUG_BREAK_AT_CONSTRUCT_CALL: | 3192 case DEBUG_BREAK_AT_CONSTRUCT_CALL: |
3196 masm->RecordDebugBreakSlotForConstructCall(); | 3193 masm->RecordDebugBreakSlotForConstructCall(); |
3197 return; | 3194 return; |
3198 } | 3195 } |
3199 } | 3196 } |
3200 | 3197 |
3201 } // namespace internal | 3198 } // namespace internal |
3202 } // namespace v8 | 3199 } // namespace v8 |
OLD | NEW |