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/frames.h" | 5 #include "src/frames.h" |
6 | 6 |
7 #include <sstream> | 7 #include <sstream> |
8 | 8 |
9 #include "src/v8.h" | 9 #include "src/v8.h" |
10 | 10 |
(...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
373 } | 373 } |
374 | 374 |
375 // Fill in the results and return the code. | 375 // Fill in the results and return the code. |
376 Code* code = entry->code; | 376 Code* code = entry->code; |
377 *safepoint_entry = entry->safepoint_entry; | 377 *safepoint_entry = entry->safepoint_entry; |
378 *stack_slots = code->stack_slots(); | 378 *stack_slots = code->stack_slots(); |
379 return code; | 379 return code; |
380 } | 380 } |
381 | 381 |
382 | 382 |
383 bool StackFrame::HasHandler() const { | |
384 StackHandlerIterator it(this, top_handler()); | |
385 return !it.done(); | |
386 } | |
387 | |
388 | |
389 #ifdef DEBUG | 383 #ifdef DEBUG |
390 static bool GcSafeCodeContains(HeapObject* object, Address addr); | 384 static bool GcSafeCodeContains(HeapObject* object, Address addr); |
391 #endif | 385 #endif |
392 | 386 |
393 | 387 |
394 void StackFrame::IteratePc(ObjectVisitor* v, | 388 void StackFrame::IteratePc(ObjectVisitor* v, |
395 Address* pc_address, | 389 Address* pc_address, |
396 Code* holder) { | 390 Code* holder) { |
397 Address pc = *pc_address; | 391 Address pc = *pc_address; |
398 DCHECK(GcSafeCodeContains(holder, pc)); | 392 DCHECK(GcSafeCodeContains(holder, pc)); |
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
601 reinterpret_cast<Address*>(ComputeConstantPoolAddress(fp())); | 595 reinterpret_cast<Address*>(ComputeConstantPoolAddress(fp())); |
602 } | 596 } |
603 | 597 |
604 | 598 |
605 void StandardFrame::SetCallerFp(Address caller_fp) { | 599 void StandardFrame::SetCallerFp(Address caller_fp) { |
606 Memory::Address_at(fp() + StandardFrameConstants::kCallerFPOffset) = | 600 Memory::Address_at(fp() + StandardFrameConstants::kCallerFPOffset) = |
607 caller_fp; | 601 caller_fp; |
608 } | 602 } |
609 | 603 |
610 | 604 |
611 bool StandardFrame::IsExpressionInsideHandler(int n) const { | |
612 Address address = GetExpressionAddress(n); | |
613 for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) { | |
614 if (it.handler()->includes(address)) return true; | |
615 } | |
616 return false; | |
617 } | |
618 | |
619 | |
620 void StandardFrame::IterateCompiledFrame(ObjectVisitor* v) const { | 605 void StandardFrame::IterateCompiledFrame(ObjectVisitor* v) const { |
621 // Make sure that we're not doing "safe" stack frame iteration. We cannot | 606 // Make sure that we're not doing "safe" stack frame iteration. We cannot |
622 // possibly find pointers in optimized frames in that state. | 607 // possibly find pointers in optimized frames in that state. |
623 DCHECK(can_access_heap_objects()); | 608 DCHECK(can_access_heap_objects()); |
624 | 609 |
625 // Compute the safepoint information. | 610 // Compute the safepoint information. |
626 unsigned stack_slots = 0; | 611 unsigned stack_slots = 0; |
627 SafepointEntry safepoint_entry; | 612 SafepointEntry safepoint_entry; |
628 Code* code = StackFrame::GetSafepointData( | 613 Code* code = StackFrame::GetSafepointData( |
629 isolate(), pc(), &safepoint_entry, &stack_slots); | 614 isolate(), pc(), &safepoint_entry, &stack_slots); |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
703 return fp() + ExitFrameConstants::kCallerSPDisplacement; | 688 return fp() + ExitFrameConstants::kCallerSPDisplacement; |
704 } | 689 } |
705 | 690 |
706 | 691 |
707 int StubFrame::GetNumberOfIncomingArguments() const { | 692 int StubFrame::GetNumberOfIncomingArguments() const { |
708 return 0; | 693 return 0; |
709 } | 694 } |
710 | 695 |
711 | 696 |
712 void OptimizedFrame::Iterate(ObjectVisitor* v) const { | 697 void OptimizedFrame::Iterate(ObjectVisitor* v) const { |
713 #ifdef DEBUG | |
714 // Make sure that optimized frames do not contain any stack handlers. | |
715 StackHandlerIterator it(this, top_handler()); | |
716 DCHECK(it.done()); | |
717 #endif | |
718 | |
719 IterateCompiledFrame(v); | 698 IterateCompiledFrame(v); |
720 } | 699 } |
721 | 700 |
722 | 701 |
723 void JavaScriptFrame::SetParameterValue(int index, Object* value) const { | 702 void JavaScriptFrame::SetParameterValue(int index, Object* value) const { |
724 Memory::Object_at(GetParameterSlot(index)) = value; | 703 Memory::Object_at(GetParameterSlot(index)) = value; |
725 } | 704 } |
726 | 705 |
727 | 706 |
728 bool JavaScriptFrame::IsConstructor() const { | 707 bool JavaScriptFrame::IsConstructor() const { |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
775 int offset = static_cast<int>(pc() - code_pointer->address()); | 754 int offset = static_cast<int>(pc() - code_pointer->address()); |
776 FrameSummary summary(receiver(), | 755 FrameSummary summary(receiver(), |
777 function(), | 756 function(), |
778 code_pointer, | 757 code_pointer, |
779 offset, | 758 offset, |
780 IsConstructor()); | 759 IsConstructor()); |
781 functions->Add(summary); | 760 functions->Add(summary); |
782 } | 761 } |
783 | 762 |
784 | 763 |
| 764 int JavaScriptFrame::LookupExceptionHandlerInTable(int* stack_slots) { |
| 765 Code* code = LookupCode(); |
| 766 DCHECK(!code->is_optimized_code()); |
| 767 HandlerTable* table = HandlerTable::cast(code->handler_table()); |
| 768 int pc_offset = static_cast<int>(pc() - code->entry()); |
| 769 return table->LookupRange(pc_offset, stack_slots); |
| 770 } |
| 771 |
| 772 |
785 void JavaScriptFrame::PrintFunctionAndOffset(JSFunction* function, Code* code, | 773 void JavaScriptFrame::PrintFunctionAndOffset(JSFunction* function, Code* code, |
786 Address pc, FILE* file, | 774 Address pc, FILE* file, |
787 bool print_line_number) { | 775 bool print_line_number) { |
788 PrintF(file, "%s", function->IsOptimized() ? "*" : "~"); | 776 PrintF(file, "%s", function->IsOptimized() ? "*" : "~"); |
789 function->PrintName(file); | 777 function->PrintName(file); |
790 int code_offset = static_cast<int>(pc - code->instruction_start()); | 778 int code_offset = static_cast<int>(pc - code->instruction_start()); |
791 PrintF(file, "+%d", code_offset); | 779 PrintF(file, "+%d", code_offset); |
792 if (print_line_number) { | 780 if (print_line_number) { |
793 SharedFunctionInfo* shared = function->shared(); | 781 SharedFunctionInfo* shared = function->shared(); |
794 int source_pos = code->SourcePosition(pc); | 782 int source_pos = code->SourcePosition(pc); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
836 } | 824 } |
837 PrintF(file, ")"); | 825 PrintF(file, ")"); |
838 } | 826 } |
839 break; | 827 break; |
840 } | 828 } |
841 it.Advance(); | 829 it.Advance(); |
842 } | 830 } |
843 } | 831 } |
844 | 832 |
845 | 833 |
846 void JavaScriptFrame::SaveOperandStack(FixedArray* store, | 834 void JavaScriptFrame::SaveOperandStack(FixedArray* store) const { |
847 int* stack_handler_index) const { | |
848 int operands_count = store->length(); | 835 int operands_count = store->length(); |
849 DCHECK_LE(operands_count, ComputeOperandsCount()); | 836 DCHECK_LE(operands_count, ComputeOperandsCount()); |
850 | 837 for (int i = 0; i < operands_count; i++) { |
851 // Visit the stack in LIFO order, saving operands and stack handlers into the | |
852 // array. The saved stack handlers store a link to the next stack handler, | |
853 // which will allow RestoreOperandStack to rewind the handlers. | |
854 StackHandlerIterator it(this, top_handler()); | |
855 int i = operands_count - 1; | |
856 *stack_handler_index = -1; | |
857 for (; !it.done(); it.Advance()) { | |
858 StackHandler* handler = it.handler(); | |
859 // Save operands pushed after the handler was pushed. | |
860 for (; GetOperandSlot(i) < handler->address(); i--) { | |
861 store->set(i, GetOperand(i)); | |
862 } | |
863 DCHECK_GE(i + 1, StackHandlerConstants::kSlotCount); | |
864 DCHECK_EQ(handler->address(), GetOperandSlot(i)); | |
865 int next_stack_handler_index = i + 1 - StackHandlerConstants::kSlotCount; | |
866 handler->Unwind(isolate(), store, next_stack_handler_index, | |
867 *stack_handler_index); | |
868 *stack_handler_index = next_stack_handler_index; | |
869 i -= StackHandlerConstants::kSlotCount; | |
870 } | |
871 | |
872 // Save any remaining operands. | |
873 for (; i >= 0; i--) { | |
874 store->set(i, GetOperand(i)); | 838 store->set(i, GetOperand(i)); |
875 } | 839 } |
876 } | 840 } |
877 | 841 |
878 | 842 |
879 void JavaScriptFrame::RestoreOperandStack(FixedArray* store, | 843 void JavaScriptFrame::RestoreOperandStack(FixedArray* store) { |
880 int stack_handler_index) { | |
881 int operands_count = store->length(); | 844 int operands_count = store->length(); |
882 DCHECK_LE(operands_count, ComputeOperandsCount()); | 845 DCHECK_LE(operands_count, ComputeOperandsCount()); |
883 int i = 0; | 846 for (int i = 0; i < operands_count; i++) { |
884 while (i <= stack_handler_index) { | |
885 if (i < stack_handler_index) { | |
886 // An operand. | |
887 DCHECK_EQ(GetOperand(i), isolate()->heap()->the_hole_value()); | |
888 Memory::Object_at(GetOperandSlot(i)) = store->get(i); | |
889 i++; | |
890 } else { | |
891 // A stack handler. | |
892 DCHECK_EQ(i, stack_handler_index); | |
893 // The FixedArray store grows up. The stack grows down. So the operand | |
894 // slot for i actually points to the bottom of the top word in the | |
895 // handler. The base of the StackHandler* is the address of the bottom | |
896 // word, which will be the last slot that is in the handler. | |
897 int handler_slot_index = i + StackHandlerConstants::kSlotCount - 1; | |
898 StackHandler *handler = | |
899 StackHandler::FromAddress(GetOperandSlot(handler_slot_index)); | |
900 stack_handler_index = handler->Rewind(isolate(), store, i, fp()); | |
901 i += StackHandlerConstants::kSlotCount; | |
902 } | |
903 } | |
904 | |
905 for (; i < operands_count; i++) { | |
906 DCHECK_EQ(GetOperand(i), isolate()->heap()->the_hole_value()); | 847 DCHECK_EQ(GetOperand(i), isolate()->heap()->the_hole_value()); |
907 Memory::Object_at(GetOperandSlot(i)) = store->get(i); | 848 Memory::Object_at(GetOperandSlot(i)) = store->get(i); |
908 } | 849 } |
909 } | 850 } |
910 | 851 |
911 | 852 |
912 void FrameSummary::Print() { | 853 void FrameSummary::Print() { |
913 PrintF("receiver: "); | 854 PrintF("receiver: "); |
914 receiver_->ShortPrint(); | 855 receiver_->ShortPrint(); |
915 PrintF("\nfunction: "); | 856 PrintF("\nfunction: "); |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1028 is_constructor = true; | 969 is_constructor = true; |
1029 } else { | 970 } else { |
1030 // Skip over operands to advance to the next opcode. | 971 // Skip over operands to advance to the next opcode. |
1031 it.Skip(Translation::NumberOfOperandsFor(opcode)); | 972 it.Skip(Translation::NumberOfOperandsFor(opcode)); |
1032 } | 973 } |
1033 } | 974 } |
1034 DCHECK(!is_constructor); | 975 DCHECK(!is_constructor); |
1035 } | 976 } |
1036 | 977 |
1037 | 978 |
| 979 int OptimizedFrame::LookupExceptionHandlerInTable(int* stack_slots) { |
| 980 Code* code = LookupCode(); |
| 981 DCHECK(code->is_optimized_code()); |
| 982 HandlerTable* table = HandlerTable::cast(code->handler_table()); |
| 983 int pc_offset = static_cast<int>(pc() - code->entry()); |
| 984 *stack_slots = code->stack_slots(); |
| 985 return table->LookupReturn(pc_offset); |
| 986 } |
| 987 |
| 988 |
1038 DeoptimizationInputData* OptimizedFrame::GetDeoptimizationData( | 989 DeoptimizationInputData* OptimizedFrame::GetDeoptimizationData( |
1039 int* deopt_index) { | 990 int* deopt_index) { |
1040 DCHECK(is_optimized()); | 991 DCHECK(is_optimized()); |
1041 | 992 |
1042 JSFunction* opt_function = function(); | 993 JSFunction* opt_function = function(); |
1043 Code* code = opt_function->code(); | 994 Code* code = opt_function->code(); |
1044 | 995 |
1045 // The code object may have been replaced by lazy deoptimization. Fall | 996 // The code object may have been replaced by lazy deoptimization. Fall |
1046 // back to a slow search in this case to find the original optimized | 997 // back to a slow search in this case to find the original optimized |
1047 // code object. | 998 // code object. |
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1279 } | 1230 } |
1280 accumulator->Add("\n"); | 1231 accumulator->Add("\n"); |
1281 } | 1232 } |
1282 | 1233 |
1283 // Print the expression stack. | 1234 // Print the expression stack. |
1284 int expressions_start = stack_locals_count; | 1235 int expressions_start = stack_locals_count; |
1285 if (expressions_start < expressions_count) { | 1236 if (expressions_start < expressions_count) { |
1286 accumulator->Add(" // expression stack (top to bottom)\n"); | 1237 accumulator->Add(" // expression stack (top to bottom)\n"); |
1287 } | 1238 } |
1288 for (int i = expressions_count - 1; i >= expressions_start; i--) { | 1239 for (int i = expressions_count - 1; i >= expressions_start; i--) { |
1289 if (IsExpressionInsideHandler(i)) continue; | |
1290 accumulator->Add(" [%02d] : %o\n", i, GetExpression(i)); | 1240 accumulator->Add(" [%02d] : %o\n", i, GetExpression(i)); |
1291 } | 1241 } |
1292 | 1242 |
1293 // Print details about the function. | 1243 // Print details about the function. |
1294 if (FLAG_max_stack_trace_source_length != 0 && code != NULL) { | 1244 if (FLAG_max_stack_trace_source_length != 0 && code != NULL) { |
1295 std::ostringstream os; | 1245 std::ostringstream os; |
1296 SharedFunctionInfo* shared = function->shared(); | 1246 SharedFunctionInfo* shared = function->shared(); |
1297 os << "--------- s o u r c e c o d e ---------\n" | 1247 os << "--------- s o u r c e c o d e ---------\n" |
1298 << SourceCodeOf(shared, FLAG_max_stack_trace_source_length) | 1248 << SourceCodeOf(shared, FLAG_max_stack_trace_source_length) |
1299 << "\n-----------------------------------------\n"; | 1249 << "\n-----------------------------------------\n"; |
(...skipping 28 matching lines...) Expand all Loading... |
1328 accumulator->Add(" // not passed to callee"); | 1278 accumulator->Add(" // not passed to callee"); |
1329 } | 1279 } |
1330 accumulator->Add("\n"); | 1280 accumulator->Add("\n"); |
1331 } | 1281 } |
1332 | 1282 |
1333 accumulator->Add("}\n\n"); | 1283 accumulator->Add("}\n\n"); |
1334 } | 1284 } |
1335 | 1285 |
1336 | 1286 |
1337 void EntryFrame::Iterate(ObjectVisitor* v) const { | 1287 void EntryFrame::Iterate(ObjectVisitor* v) const { |
1338 StackHandlerIterator it(this, top_handler()); | |
1339 DCHECK(!it.done()); | |
1340 StackHandler* handler = it.handler(); | |
1341 handler->Iterate(v, LookupCode()); | |
1342 #ifdef DEBUG | |
1343 // Make sure that the entry frame does not contain more than one | |
1344 // stack handler. | |
1345 it.Advance(); | |
1346 DCHECK(it.done()); | |
1347 #endif | |
1348 IteratePc(v, pc_address(), LookupCode()); | 1288 IteratePc(v, pc_address(), LookupCode()); |
1349 } | 1289 } |
1350 | 1290 |
1351 | 1291 |
1352 void StandardFrame::IterateExpressions(ObjectVisitor* v) const { | 1292 void StandardFrame::IterateExpressions(ObjectVisitor* v) const { |
1353 const int offset = StandardFrameConstants::kLastObjectOffset; | 1293 const int offset = StandardFrameConstants::kLastObjectOffset; |
1354 Object** base = &Memory::Object_at(sp()); | 1294 Object** base = &Memory::Object_at(sp()); |
1355 Object** limit = &Memory::Object_at(fp() + offset) + 1; | 1295 Object** limit = &Memory::Object_at(fp() + offset) + 1; |
1356 for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) { | |
1357 StackHandler* handler = it.handler(); | |
1358 // Traverse pointers down to - but not including - the next | |
1359 // handler in the handler chain. Update the base to skip the | |
1360 // handler and allow the handler to traverse its own pointers. | |
1361 const Address address = handler->address(); | |
1362 v->VisitPointers(base, reinterpret_cast<Object**>(address)); | |
1363 base = reinterpret_cast<Object**>(address + StackHandlerConstants::kSize); | |
1364 // Traverse the pointers in the handler itself. | |
1365 handler->Iterate(v, LookupCode()); | |
1366 } | |
1367 v->VisitPointers(base, limit); | 1296 v->VisitPointers(base, limit); |
1368 } | 1297 } |
1369 | 1298 |
1370 | 1299 |
1371 void JavaScriptFrame::Iterate(ObjectVisitor* v) const { | 1300 void JavaScriptFrame::Iterate(ObjectVisitor* v) const { |
1372 IterateExpressions(v); | 1301 IterateExpressions(v); |
1373 IteratePc(v, pc_address(), LookupCode()); | 1302 IteratePc(v, pc_address(), LookupCode()); |
1374 } | 1303 } |
1375 | 1304 |
1376 | 1305 |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1522 entry->safepoint_entry.Reset(); | 1451 entry->safepoint_entry.Reset(); |
1523 entry->inner_pointer = inner_pointer; | 1452 entry->inner_pointer = inner_pointer; |
1524 } | 1453 } |
1525 return entry; | 1454 return entry; |
1526 } | 1455 } |
1527 | 1456 |
1528 | 1457 |
1529 // ------------------------------------------------------------------------- | 1458 // ------------------------------------------------------------------------- |
1530 | 1459 |
1531 | 1460 |
1532 void StackHandler::Unwind(Isolate* isolate, | |
1533 FixedArray* array, | |
1534 int offset, | |
1535 int previous_handler_offset) const { | |
1536 STATIC_ASSERT(StackHandlerConstants::kSlotCount >= 3); | |
1537 DCHECK_LE(0, offset); | |
1538 DCHECK_GE(array->length(), offset + StackHandlerConstants::kSlotCount); | |
1539 // Unwinding a stack handler into an array chains it in the opposite | |
1540 // direction, re-using the "next" slot as a "previous" link, so that stack | |
1541 // handlers can be later re-wound in the correct order. | |
1542 int s = Memory::int_at(address() + StackHandlerConstants::kStateIntOffset); | |
1543 array->set(offset, Smi::FromInt(previous_handler_offset)); // next | |
1544 array->set(offset + 1, Smi::FromInt(static_cast<int>(s))); // state | |
1545 array->set(offset + 2, *context_address()); // context | |
1546 | |
1547 *isolate->handler_address() = next()->address(); | |
1548 } | |
1549 | |
1550 | |
1551 int StackHandler::Rewind(Isolate* isolate, | |
1552 FixedArray* array, | |
1553 int offset, | |
1554 Address fp) { | |
1555 STATIC_ASSERT(StackHandlerConstants::kSlotCount >= 3); | |
1556 DCHECK_LE(0, offset); | |
1557 DCHECK_GE(array->length(), offset + StackHandlerConstants::kSlotCount); | |
1558 Smi* prev_handler_offset = Smi::cast(array->get(offset)); | |
1559 Smi* smi_state = Smi::cast(array->get(offset + 1)); | |
1560 Object* context = array->get(offset + 2); | |
1561 | |
1562 Memory::Address_at(address() + StackHandlerConstants::kNextOffset) = | |
1563 *isolate->handler_address(); | |
1564 Memory::int_at(address() + StackHandlerConstants::kStateIntOffset) = | |
1565 smi_state->value(); | |
1566 Memory::Object_at(address() + StackHandlerConstants::kContextOffset) = | |
1567 context; | |
1568 | |
1569 *isolate->handler_address() = address(); | |
1570 | |
1571 return prev_handler_offset->value(); | |
1572 } | |
1573 | |
1574 | |
1575 // ------------------------------------------------------------------------- | |
1576 | |
1577 int NumRegs(RegList reglist) { return base::bits::CountPopulation32(reglist); } | 1461 int NumRegs(RegList reglist) { return base::bits::CountPopulation32(reglist); } |
1578 | 1462 |
1579 | 1463 |
1580 struct JSCallerSavedCodeData { | 1464 struct JSCallerSavedCodeData { |
1581 int reg_code[kNumJSCallerSaved]; | 1465 int reg_code[kNumJSCallerSaved]; |
1582 }; | 1466 }; |
1583 | 1467 |
1584 JSCallerSavedCodeData caller_saved_code_data; | 1468 JSCallerSavedCodeData caller_saved_code_data; |
1585 | 1469 |
1586 void SetUpJSCallerSavedCodeData() { | 1470 void SetUpJSCallerSavedCodeData() { |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1630 ZoneList<StackFrame*> list(10, zone); | 1514 ZoneList<StackFrame*> list(10, zone); |
1631 for (StackFrameIterator it(isolate); !it.done(); it.Advance()) { | 1515 for (StackFrameIterator it(isolate); !it.done(); it.Advance()) { |
1632 StackFrame* frame = AllocateFrameCopy(it.frame(), zone); | 1516 StackFrame* frame = AllocateFrameCopy(it.frame(), zone); |
1633 list.Add(frame, zone); | 1517 list.Add(frame, zone); |
1634 } | 1518 } |
1635 return list.ToVector(); | 1519 return list.ToVector(); |
1636 } | 1520 } |
1637 | 1521 |
1638 | 1522 |
1639 } } // namespace v8::internal | 1523 } } // namespace v8::internal |
OLD | NEW |