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/ast/ast.h" | 9 #include "src/ast/ast.h" |
10 #include "src/ast/scopeinfo.h" | 10 #include "src/ast/scopeinfo.h" |
(...skipping 783 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
794 | 794 |
795 | 795 |
796 void JavaScriptFrame::GetFunctions(List<JSFunction*>* functions) const { | 796 void JavaScriptFrame::GetFunctions(List<JSFunction*>* functions) const { |
797 DCHECK(functions->length() == 0); | 797 DCHECK(functions->length() == 0); |
798 functions->Add(function()); | 798 functions->Add(function()); |
799 } | 799 } |
800 | 800 |
801 | 801 |
802 void JavaScriptFrame::Summarize(List<FrameSummary>* functions) { | 802 void JavaScriptFrame::Summarize(List<FrameSummary>* functions) { |
803 DCHECK(functions->length() == 0); | 803 DCHECK(functions->length() == 0); |
804 Code* code_pointer = LookupCode(); | 804 Code* code = LookupCode(); |
805 int offset = static_cast<int>(pc() - code_pointer->address()); | 805 int offset = static_cast<int>(pc() - code->instruction_start()); |
806 FrameSummary summary(receiver(), | 806 AbstractCode* abstract_code = AbstractCode::cast(code); |
807 function(), | 807 FrameSummary summary(receiver(), function(), abstract_code, offset, |
808 code_pointer, | |
809 offset, | |
810 IsConstructor()); | 808 IsConstructor()); |
811 functions->Add(summary); | 809 functions->Add(summary); |
812 } | 810 } |
813 | 811 |
814 | 812 |
815 int JavaScriptFrame::LookupExceptionHandlerInTable( | 813 int JavaScriptFrame::LookupExceptionHandlerInTable( |
816 int* stack_slots, HandlerTable::CatchPrediction* prediction) { | 814 int* stack_slots, HandlerTable::CatchPrediction* prediction) { |
817 Code* code = LookupCode(); | 815 Code* code = LookupCode(); |
818 DCHECK(!code->is_optimized_code()); | 816 DCHECK(!code->is_optimized_code()); |
819 HandlerTable* table = HandlerTable::cast(code->handler_table()); | 817 HandlerTable* table = HandlerTable::cast(code->handler_table()); |
820 int pc_offset = static_cast<int>(pc() - code->entry()); | 818 int pc_offset = static_cast<int>(pc() - code->entry()); |
821 return table->LookupRange(pc_offset, stack_slots, prediction); | 819 return table->LookupRange(pc_offset, stack_slots, prediction); |
822 } | 820 } |
823 | 821 |
824 | 822 |
825 void JavaScriptFrame::PrintFunctionAndOffset(JSFunction* function, Code* code, | 823 void JavaScriptFrame::PrintFunctionAndOffset(JSFunction* function, Code* code, |
826 Address pc, FILE* file, | 824 Address pc, FILE* file, |
827 bool print_line_number) { | 825 bool print_line_number) { |
828 PrintF(file, "%s", function->IsOptimized() ? "*" : "~"); | 826 PrintF(file, "%s", function->IsOptimized() ? "*" : "~"); |
829 function->PrintName(file); | 827 function->PrintName(file); |
830 int code_offset = static_cast<int>(pc - code->instruction_start()); | 828 int code_offset = static_cast<int>(pc - code->instruction_start()); |
831 PrintF(file, "+%d", code_offset); | 829 PrintF(file, "+%d", code_offset); |
832 if (print_line_number) { | 830 if (print_line_number) { |
833 SharedFunctionInfo* shared = function->shared(); | 831 SharedFunctionInfo* shared = function->shared(); |
834 int source_pos = code->SourcePosition(pc); | 832 int source_pos = code->SourcePosition(code_offset); |
835 Object* maybe_script = shared->script(); | 833 Object* maybe_script = shared->script(); |
836 if (maybe_script->IsScript()) { | 834 if (maybe_script->IsScript()) { |
837 Script* script = Script::cast(maybe_script); | 835 Script* script = Script::cast(maybe_script); |
838 int line = script->GetLineNumber(source_pos) + 1; | 836 int line = script->GetLineNumber(source_pos) + 1; |
839 Object* script_name_raw = script->name(); | 837 Object* script_name_raw = script->name(); |
840 if (script_name_raw->IsString()) { | 838 if (script_name_raw->IsString()) { |
841 String* script_name = String::cast(script->name()); | 839 String* script_name = String::cast(script->name()); |
842 base::SmartArrayPointer<char> c_script_name = | 840 base::SmartArrayPointer<char> c_script_name = |
843 script_name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL); | 841 script_name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL); |
844 PrintF(file, " at %s:%d", c_script_name.get(), line); | 842 PrintF(file, " at %s:%d", c_script_name.get(), line); |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
894 | 892 |
895 void JavaScriptFrame::RestoreOperandStack(FixedArray* store) { | 893 void JavaScriptFrame::RestoreOperandStack(FixedArray* store) { |
896 int operands_count = store->length(); | 894 int operands_count = store->length(); |
897 DCHECK_LE(operands_count, ComputeOperandsCount()); | 895 DCHECK_LE(operands_count, ComputeOperandsCount()); |
898 for (int i = 0; i < operands_count; i++) { | 896 for (int i = 0; i < operands_count; i++) { |
899 DCHECK_EQ(GetOperand(i), isolate()->heap()->the_hole_value()); | 897 DCHECK_EQ(GetOperand(i), isolate()->heap()->the_hole_value()); |
900 Memory::Object_at(GetOperandSlot(i)) = store->get(i); | 898 Memory::Object_at(GetOperandSlot(i)) = store->get(i); |
901 } | 899 } |
902 } | 900 } |
903 | 901 |
904 | 902 FrameSummary::FrameSummary(Object* receiver, JSFunction* function, |
905 FrameSummary::FrameSummary(Object* receiver, JSFunction* function, Code* code, | 903 AbstractCode* abstract_code, int code_offset, |
906 int offset, bool is_constructor) | 904 bool is_constructor) |
907 : receiver_(receiver, function->GetIsolate()), | 905 : receiver_(receiver, function->GetIsolate()), |
908 function_(function), | 906 function_(function), |
909 code_(code), | 907 abstract_code_(abstract_code), |
910 offset_(offset), | 908 code_offset_(code_offset), |
911 is_constructor_(is_constructor) {} | 909 is_constructor_(is_constructor) {} |
912 | 910 |
913 | |
914 void FrameSummary::Print() { | 911 void FrameSummary::Print() { |
915 PrintF("receiver: "); | 912 PrintF("receiver: "); |
916 receiver_->ShortPrint(); | 913 receiver_->ShortPrint(); |
917 PrintF("\nfunction: "); | 914 PrintF("\nfunction: "); |
918 function_->shared()->DebugName()->ShortPrint(); | 915 function_->shared()->DebugName()->ShortPrint(); |
919 PrintF("\ncode: "); | 916 PrintF("\ncode: "); |
920 code_->ShortPrint(); | 917 abstract_code_->ShortPrint(); |
921 if (code_->kind() == Code::FUNCTION) PrintF(" NON-OPT"); | 918 if (abstract_code_->IsCode()) { |
922 if (code_->kind() == Code::OPTIMIZED_FUNCTION) PrintF(" OPT"); | 919 Code* code = abstract_code_->GetCode(); |
923 PrintF("\npc: %d\n", offset_); | 920 if (code->kind() == Code::FUNCTION) PrintF(" UNOPT "); |
| 921 if (code->kind() == Code::OPTIMIZED_FUNCTION) PrintF(" OPT "); |
| 922 } else { |
| 923 PrintF(" BYTECODE "); |
| 924 } |
| 925 PrintF("\npc: %d\n", code_offset_); |
924 } | 926 } |
925 | 927 |
926 | 928 |
927 void OptimizedFrame::Summarize(List<FrameSummary>* frames) { | 929 void OptimizedFrame::Summarize(List<FrameSummary>* frames) { |
928 DCHECK(frames->length() == 0); | 930 DCHECK(frames->length() == 0); |
929 DCHECK(is_optimized()); | 931 DCHECK(is_optimized()); |
930 | 932 |
931 // Delegate to JS frame in absence of turbofan deoptimization. | 933 // Delegate to JS frame in absence of turbofan deoptimization. |
932 // TODO(turbofan): Revisit once we support deoptimization across the board. | 934 // TODO(turbofan): Revisit once we support deoptimization across the board. |
933 if (LookupCode()->is_turbofanned() && function()->shared()->asm_function() && | 935 if (LookupCode()->is_turbofanned() && function()->shared()->asm_function() && |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
992 } else { | 994 } else { |
993 // The receiver is not in a stack slot nor in a literal. We give up. | 995 // The receiver is not in a stack slot nor in a literal. We give up. |
994 it.Skip(Translation::NumberOfOperandsFor(opcode)); | 996 it.Skip(Translation::NumberOfOperandsFor(opcode)); |
995 // TODO(3029): Materializing a captured object (or duplicated | 997 // TODO(3029): Materializing a captured object (or duplicated |
996 // object) is hard, we return undefined for now. This breaks the | 998 // object) is hard, we return undefined for now. This breaks the |
997 // produced stack trace, as constructor frames aren't marked as | 999 // produced stack trace, as constructor frames aren't marked as |
998 // such anymore. | 1000 // such anymore. |
999 receiver = isolate()->heap()->undefined_value(); | 1001 receiver = isolate()->heap()->undefined_value(); |
1000 } | 1002 } |
1001 | 1003 |
1002 Code* const code = shared_info->code(); | 1004 AbstractCode* abstract_code; |
1003 | 1005 |
1004 unsigned pc_offset; | 1006 unsigned code_offset; |
1005 if (frame_opcode == Translation::JS_FRAME) { | 1007 if (frame_opcode == Translation::JS_FRAME) { |
| 1008 Code* code = shared_info->code(); |
1006 DeoptimizationOutputData* const output_data = | 1009 DeoptimizationOutputData* const output_data = |
1007 DeoptimizationOutputData::cast(code->deoptimization_data()); | 1010 DeoptimizationOutputData::cast(code->deoptimization_data()); |
1008 unsigned const entry = | 1011 unsigned const entry = |
1009 Deoptimizer::GetOutputInfo(output_data, ast_id, shared_info); | 1012 Deoptimizer::GetOutputInfo(output_data, ast_id, shared_info); |
1010 pc_offset = | 1013 code_offset = FullCodeGenerator::PcField::decode(entry); |
1011 FullCodeGenerator::PcField::decode(entry) + Code::kHeaderSize; | 1014 abstract_code = AbstractCode::cast(code); |
1012 DCHECK_NE(0U, pc_offset); | |
1013 } else { | 1015 } else { |
1014 // TODO(rmcilroy): Modify FrameSummary to enable us to summarize | 1016 // TODO(rmcilroy): Modify FrameSummary to enable us to summarize |
1015 // based on the BytecodeArray and bytecode offset. | 1017 // based on the BytecodeArray and bytecode offset. |
1016 DCHECK_EQ(frame_opcode, Translation::INTERPRETED_FRAME); | 1018 DCHECK_EQ(frame_opcode, Translation::INTERPRETED_FRAME); |
1017 pc_offset = 0; | 1019 code_offset = 0; |
| 1020 abstract_code = AbstractCode::cast(shared_info->bytecode_array()); |
1018 } | 1021 } |
1019 FrameSummary summary(receiver, function, code, pc_offset, is_constructor); | 1022 FrameSummary summary(receiver, function, abstract_code, code_offset, |
| 1023 is_constructor); |
1020 frames->Add(summary); | 1024 frames->Add(summary); |
1021 is_constructor = false; | 1025 is_constructor = false; |
1022 } else if (frame_opcode == Translation::CONSTRUCT_STUB_FRAME) { | 1026 } else if (frame_opcode == Translation::CONSTRUCT_STUB_FRAME) { |
1023 // The next encountered JS_FRAME will be marked as a constructor call. | 1027 // The next encountered JS_FRAME will be marked as a constructor call. |
1024 it.Skip(Translation::NumberOfOperandsFor(frame_opcode)); | 1028 it.Skip(Translation::NumberOfOperandsFor(frame_opcode)); |
1025 DCHECK(!is_constructor); | 1029 DCHECK(!is_constructor); |
1026 is_constructor = true; | 1030 is_constructor = true; |
1027 } else { | 1031 } else { |
1028 // Skip over operands to advance to the next opcode. | 1032 // Skip over operands to advance to the next opcode. |
1029 it.Skip(Translation::NumberOfOperandsFor(frame_opcode)); | 1033 it.Skip(Translation::NumberOfOperandsFor(frame_opcode)); |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1152 | 1156 |
1153 | 1157 |
1154 void InterpretedFrame::PatchBytecodeOffset(int new_offset) { | 1158 void InterpretedFrame::PatchBytecodeOffset(int new_offset) { |
1155 const int index = InterpreterFrameConstants::kBytecodeOffsetExpressionIndex; | 1159 const int index = InterpreterFrameConstants::kBytecodeOffsetExpressionIndex; |
1156 DCHECK_EQ(InterpreterFrameConstants::kBytecodeOffsetFromFp, | 1160 DCHECK_EQ(InterpreterFrameConstants::kBytecodeOffsetFromFp, |
1157 StandardFrameConstants::kExpressionsOffset - index * kPointerSize); | 1161 StandardFrameConstants::kExpressionsOffset - index * kPointerSize); |
1158 int raw_offset = new_offset + BytecodeArray::kHeaderSize - kHeapObjectTag; | 1162 int raw_offset = new_offset + BytecodeArray::kHeaderSize - kHeapObjectTag; |
1159 SetExpression(index, Smi::FromInt(raw_offset)); | 1163 SetExpression(index, Smi::FromInt(raw_offset)); |
1160 } | 1164 } |
1161 | 1165 |
| 1166 void InterpretedFrame::Summarize(List<FrameSummary>* functions) { |
| 1167 DCHECK(functions->length() == 0); |
| 1168 AbstractCode* abstract_code = |
| 1169 AbstractCode::cast(function()->shared()->bytecode_array()); |
| 1170 FrameSummary summary(receiver(), function(), abstract_code, |
| 1171 GetBytecodeOffset(), IsConstructor()); |
| 1172 functions->Add(summary); |
| 1173 } |
1162 | 1174 |
1163 int ArgumentsAdaptorFrame::GetNumberOfIncomingArguments() const { | 1175 int ArgumentsAdaptorFrame::GetNumberOfIncomingArguments() const { |
1164 return Smi::cast(GetExpression(0))->value(); | 1176 return Smi::cast(GetExpression(0))->value(); |
1165 } | 1177 } |
1166 | 1178 |
1167 | 1179 |
1168 Address ArgumentsAdaptorFrame::GetCallerStackPointer() const { | 1180 Address ArgumentsAdaptorFrame::GetCallerStackPointer() const { |
1169 return fp() + StandardFrameConstants::kCallerSPOffset; | 1181 return fp() + StandardFrameConstants::kCallerSPOffset; |
1170 } | 1182 } |
1171 | 1183 |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1237 ScopeInfo* scope_info = shared->scope_info(); | 1249 ScopeInfo* scope_info = shared->scope_info(); |
1238 Object* script_obj = shared->script(); | 1250 Object* script_obj = shared->script(); |
1239 if (script_obj->IsScript()) { | 1251 if (script_obj->IsScript()) { |
1240 Script* script = Script::cast(script_obj); | 1252 Script* script = Script::cast(script_obj); |
1241 accumulator->Add(" ["); | 1253 accumulator->Add(" ["); |
1242 accumulator->PrintName(script->name()); | 1254 accumulator->PrintName(script->name()); |
1243 | 1255 |
1244 Address pc = this->pc(); | 1256 Address pc = this->pc(); |
1245 if (code != NULL && code->kind() == Code::FUNCTION && | 1257 if (code != NULL && code->kind() == Code::FUNCTION && |
1246 pc >= code->instruction_start() && pc < code->instruction_end()) { | 1258 pc >= code->instruction_start() && pc < code->instruction_end()) { |
1247 int source_pos = code->SourcePosition(pc); | 1259 int offset = static_cast<int>(pc - code->instruction_start()); |
| 1260 int source_pos = code->SourcePosition(offset); |
1248 int line = script->GetLineNumber(source_pos) + 1; | 1261 int line = script->GetLineNumber(source_pos) + 1; |
1249 accumulator->Add(":%d", line); | 1262 accumulator->Add(":%d", line); |
1250 } else { | 1263 } else { |
1251 int function_start_pos = shared->start_position(); | 1264 int function_start_pos = shared->start_position(); |
1252 int line = script->GetLineNumber(function_start_pos) + 1; | 1265 int line = script->GetLineNumber(function_start_pos) + 1; |
1253 accumulator->Add(":~%d", line); | 1266 accumulator->Add(":~%d", line); |
1254 } | 1267 } |
1255 | 1268 |
1256 accumulator->Add("] [pc=%p] ", pc); | 1269 accumulator->Add("] [pc=%p] ", pc); |
1257 } | 1270 } |
(...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1621 for (StackFrameIterator it(isolate); !it.done(); it.Advance()) { | 1634 for (StackFrameIterator it(isolate); !it.done(); it.Advance()) { |
1622 StackFrame* frame = AllocateFrameCopy(it.frame(), zone); | 1635 StackFrame* frame = AllocateFrameCopy(it.frame(), zone); |
1623 list.Add(frame, zone); | 1636 list.Add(frame, zone); |
1624 } | 1637 } |
1625 return list.ToVector(); | 1638 return list.ToVector(); |
1626 } | 1639 } |
1627 | 1640 |
1628 | 1641 |
1629 } // namespace internal | 1642 } // namespace internal |
1630 } // namespace v8 | 1643 } // namespace v8 |
OLD | NEW |