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