Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(720)

Side by Side Diff: src/deoptimizer.cc

Issue 20680002: Rebase of partial ia32 implementation of optimized try/catch (started by Kevin Millikin, continued … (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Fix detection of CATCH frames (fixes debuger exception reporting anf breaks another assertion...). Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/deoptimizer.h ('k') | src/flag-definitions.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
148 int commit_page_size = static_cast<int>(OS::CommitPageSize()); 148 int commit_page_size = static_cast<int>(OS::CommitPageSize());
149 int page_count = ((kDeoptTableMaxEpilogueCodeSize + entries_size - 1) / 149 int page_count = ((kDeoptTableMaxEpilogueCodeSize + entries_size - 1) /
150 commit_page_size) + 1; 150 commit_page_size) + 1;
151 return static_cast<size_t>(commit_page_size * page_count); 151 return static_cast<size_t>(commit_page_size * page_count);
152 } 152 }
153 153
154 154
155 Deoptimizer* Deoptimizer::Grab(Isolate* isolate) { 155 Deoptimizer* Deoptimizer::Grab(Isolate* isolate) {
156 Deoptimizer* result = isolate->deoptimizer_data()->current_; 156 Deoptimizer* result = isolate->deoptimizer_data()->current_;
157 ASSERT(result != NULL); 157 ASSERT(result != NULL);
158 if (isolate->optimized_handler_patch_buffer() != NULL) {
159 ASSERT(result->bailout_type_ == LAZY);
160 // Before allowing allocation, patch the optimized code back. The
161 // patched code has relocation info that does not agree with the code,
162 // so the patched code should not be seen by the garbage collector.
163 Code* code = result->compiled_code_;
164 DeoptimizationInputData* deopt_data =
165 DeoptimizationInputData::cast(code->deoptimization_data());
166 int deopt_index = isolate->optimized_handler_deopt_index();
167 byte* patch_address =
168 code->instruction_start() + deopt_data->Pc(deopt_index)->value();
169 memcpy(patch_address, isolate->optimized_handler_patch_buffer(),
170 patch_size());
171 // FIXME(mmassi): why doesn't it clear immediately also the patch buffer?
172 isolate->ClearOptimizedHandlerByDeopt(code);
173 }
158 result->DeleteFrameDescriptions(); 174 result->DeleteFrameDescriptions();
159 isolate->deoptimizer_data()->current_ = NULL; 175 isolate->deoptimizer_data()->current_ = NULL;
160 return result; 176 return result;
161 } 177 }
162 178
163 179
164 int Deoptimizer::ConvertJSFrameIndexToFrameIndex(int jsframe_index) { 180 int Deoptimizer::ConvertJSFrameIndexToFrameIndex(int jsframe_index) {
165 if (jsframe_index == 0) return 0; 181 if (jsframe_index == 0) return 0;
166 182
167 int frame_index = 0; 183 int frame_index = 0;
(...skipping 20 matching lines...) Expand all
188 // Get the function and code from the frame. 204 // Get the function and code from the frame.
189 JSFunction* function = JSFunction::cast(frame->function()); 205 JSFunction* function = JSFunction::cast(frame->function());
190 Code* code = frame->LookupCode(); 206 Code* code = frame->LookupCode();
191 207
192 // Locate the deoptimization point in the code. As we are at a call the 208 // Locate the deoptimization point in the code. As we are at a call the
193 // return address must be at a place in the code with deoptimization support. 209 // return address must be at a place in the code with deoptimization support.
194 SafepointEntry safepoint_entry = code->GetSafepointEntry(frame->pc()); 210 SafepointEntry safepoint_entry = code->GetSafepointEntry(frame->pc());
195 int deoptimization_index = safepoint_entry.deoptimization_index(); 211 int deoptimization_index = safepoint_entry.deoptimization_index();
196 ASSERT(deoptimization_index != Safepoint::kNoDeoptimizationIndex); 212 ASSERT(deoptimization_index != Safepoint::kNoDeoptimizationIndex);
197 213
214 // Find the size of exception handlers.
215 DeoptimizationInputData* deoptimization_data =
216 DeoptimizationInputData::cast(code->deoptimization_data());
217 unsigned handler_count =
218 deoptimization_data->HandlerCount(deoptimization_index)->value();
219 unsigned handler_size = handler_count * StackHandlerConstants::kSize;
220
198 // Always use the actual stack slots when calculating the fp to sp 221 // Always use the actual stack slots when calculating the fp to sp
199 // delta adding two for the function and context. 222 // delta adding two for the function and context.
200 unsigned stack_slots = code->stack_slots(); 223 unsigned stack_slots = code->stack_slots();
201 unsigned fp_to_sp_delta = ((stack_slots + 2) * kPointerSize); 224 unsigned fp_to_sp_delta = ((stack_slots + 2) * kPointerSize) + handler_size;
202 225
203 Deoptimizer* deoptimizer = new Deoptimizer(isolate, 226 Deoptimizer* deoptimizer = new Deoptimizer(isolate,
204 function, 227 function,
205 Deoptimizer::DEBUGGER, 228 Deoptimizer::DEBUGGER,
206 deoptimization_index, 229 deoptimization_index,
207 frame->pc(), 230 frame->pc(),
208 fp_to_sp_delta, 231 fp_to_sp_delta,
209 code); 232 code);
210 Address tos = frame->fp() - fp_to_sp_delta; 233 Address tos = frame->fp() - fp_to_sp_delta;
211 deoptimizer->FillInputFrame(tos, frame); 234 deoptimizer->FillInputFrame(tos, frame);
(...skipping 528 matching lines...) Expand 10 before | Expand all | Expand 10 after
740 TranslationIterator iterator(translations, translation_index); 763 TranslationIterator iterator(translations, translation_index);
741 Translation::Opcode opcode = 764 Translation::Opcode opcode =
742 static_cast<Translation::Opcode>(iterator.Next()); 765 static_cast<Translation::Opcode>(iterator.Next());
743 ASSERT(Translation::BEGIN == opcode); 766 ASSERT(Translation::BEGIN == opcode);
744 USE(opcode); 767 USE(opcode);
745 // Read the number of output frames and allocate an array for their 768 // Read the number of output frames and allocate an array for their
746 // descriptions. 769 // descriptions.
747 int count = iterator.Next(); 770 int count = iterator.Next();
748 iterator.Next(); // Drop JS frames count. 771 iterator.Next(); // Drop JS frames count.
749 ASSERT(output_ == NULL); 772 ASSERT(output_ == NULL);
773
774 // If this deoptimization is needed to transfer control to a catch clause
775 // only the first frame is relevant.
776 if (isolate_->optimized_handler_patch_buffer() != NULL) {
777 count = 1;
778 }
779
750 output_ = new FrameDescription*[count]; 780 output_ = new FrameDescription*[count];
751 for (int i = 0; i < count; ++i) { 781 for (int i = 0; i < count; ++i) {
752 output_[i] = NULL; 782 output_[i] = NULL;
753 } 783 }
754 output_count_ = count; 784 output_count_ = count;
755 785
756 // Translate each output frame. 786 // Translate each output frame.
757 for (int i = 0; i < count; ++i) { 787 for (int i = 0; i < count; ++i) {
758 // Read the ast node id, function, and frame height for this output frame. 788 // Read the ast node id, function, and frame height for this output frame.
759 Translation::Opcode opcode = 789 Translation::Opcode opcode =
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
824 BailoutId node_id = BailoutId(iterator->Next()); 854 BailoutId node_id = BailoutId(iterator->Next());
825 JSFunction* function; 855 JSFunction* function;
826 if (frame_index != 0) { 856 if (frame_index != 0) {
827 function = JSFunction::cast(ComputeLiteral(iterator->Next())); 857 function = JSFunction::cast(ComputeLiteral(iterator->Next()));
828 } else { 858 } else {
829 int closure_id = iterator->Next(); 859 int closure_id = iterator->Next();
830 USE(closure_id); 860 USE(closure_id);
831 ASSERT_EQ(Translation::kSelfLiteralId, closure_id); 861 ASSERT_EQ(Translation::kSelfLiteralId, closure_id);
832 function = function_; 862 function = function_;
833 } 863 }
864 Code* non_optimized_code = function->shared()->code();
834 unsigned height = iterator->Next(); 865 unsigned height = iterator->Next();
835 unsigned height_in_bytes = height * kPointerSize; 866 unsigned height_in_bytes = height * kPointerSize;
836 if (trace_) { 867 int handler_count = iterator->Next();
837 PrintF(" translating "); 868 // If we are doing lazy deoptimization for catching in an optimized frame,
838 function->PrintName(); 869 // one of the handlers in the frame description has already been dropped
839 PrintF(" => node=%d, height=%d\n", node_id.ToInt(), height_in_bytes); 870 // by throwing to it.
871 if (isolate_->optimized_handler_patch_buffer() != NULL) {
872 ASSERT(frame_index == 0 && output_count_ == 1);
873 ASSERT(bailout_type_ == LAZY);
874 ASSERT(handler_count > 0);
875 --handler_count;
840 } 876 }
877 int handlers_size = handler_count * StackHandlerConstants::kSize;
841 878
842 // The 'fixed' part of the frame consists of the incoming parameters and 879 // The 'fixed' part of the frame consists of the incoming parameters and
843 // the part described by JavaScriptFrameConstants. 880 // the part described by JavaScriptFrameConstants.
844 unsigned fixed_frame_size = ComputeFixedSize(function); 881 unsigned fixed_frame_size = ComputeFixedSize(function);
845 unsigned input_frame_size = input_->GetFrameSize(); 882 //TODO(mmassi): what's this for?
883 //unsigned input_frame_size = input_->GetFrameSize();
846 unsigned output_frame_size = height_in_bytes + fixed_frame_size; 884 unsigned output_frame_size = height_in_bytes + fixed_frame_size;
885 if (FLAG_trace_deopt) {
886 PrintF(" translating ");
887 function->PrintName();
888 PrintF(" => node=%d, height=%d\n",
889 node_id.ToInt(), height_in_bytes + handlers_size);
890 }
891
847 892
848 // Allocate and store the output frame description. 893 // Allocate and store the output frame description.
849 FrameDescription* output_frame = 894 FrameDescription* output_frame =
850 new(output_frame_size) FrameDescription(output_frame_size, function); 895 new(output_frame_size) FrameDescription(output_frame_size, function);
851 output_frame->SetFrameType(StackFrame::JAVA_SCRIPT); 896 output_frame->SetFrameType(StackFrame::JAVA_SCRIPT);
852 897
853 bool is_bottommost = (0 == frame_index); 898 bool is_bottommost = (0 == frame_index);
899 ASSERT(is_bottommost || handler_count == 0); // We do not inline try-catch.
854 bool is_topmost = (output_count_ - 1 == frame_index); 900 bool is_topmost = (output_count_ - 1 == frame_index);
855 ASSERT(frame_index >= 0 && frame_index < output_count_); 901 ASSERT(frame_index >= 0 && frame_index < output_count_);
856 ASSERT(output_[frame_index] == NULL); 902 ASSERT(output_[frame_index] == NULL);
857 output_[frame_index] = output_frame; 903 output_[frame_index] = output_frame;
858 904
859 // The top address for the bottommost output frame can be computed from 905 // The top address for the bottommost output frame can be computed from
860 // the input frame pointer and the output frame's height. For all 906 // the input frame pointer and the output frame's height. For all
861 // subsequent output frames, it can be computed from the previous one's 907 // subsequent output frames, it can be computed from the previous one's
862 // top address and the current frame's size. 908 // top address and the current frame's size.
863 Register fp_reg = JavaScriptFrame::fp_register(); 909 Register fp_reg = JavaScriptFrame::fp_register();
864 intptr_t top_address; 910 intptr_t top_address;
865 if (is_bottommost) { 911 if (is_bottommost) {
866 // Determine whether the input frame contains alignment padding. 912 // Determine whether the input frame contains alignment padding.
867 has_alignment_padding_ = HasAlignmentPadding(function) ? 1 : 0; 913 has_alignment_padding_ = HasAlignmentPadding(function) ? 1 : 0;
868 // 2 = context and function in the frame. 914 // 2 = context and function in the frame.
869 // If the optimized frame had alignment padding, adjust the frame pointer 915 // If the optimized frame had alignment padding, adjust the frame pointer
870 // to point to the new position of the old frame pointer after padding 916 // to point to the new position of the old frame pointer after padding
871 // is removed. Subtract 2 * kPointerSize for the context and function slots. 917 // is removed. Subtract 2 * kPointerSize for the context and function slots.
872 top_address = input_->GetRegister(fp_reg.code()) - (2 * kPointerSize) - 918 top_address = input_->GetRegister(fp_reg.code()) - (2 * kPointerSize) -
873 height_in_bytes + has_alignment_padding_ * kPointerSize; 919 height_in_bytes + has_alignment_padding_ * kPointerSize;
920 //TODO(mmassi): Is height_in_bytes the right value?
874 } else { 921 } else {
875 top_address = output_[frame_index - 1]->GetTop() - output_frame_size; 922 top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
876 } 923 }
877 output_frame->SetTop(top_address); 924 output_frame->SetTop(top_address);
878 925
879 // Compute the incoming parameter translation. 926 // Compute the incoming parameter translation.
880 int parameter_count = function->shared()->formal_parameter_count() + 1; 927 int parameter_count = function->shared()->formal_parameter_count() + 1;
881 unsigned output_offset = output_frame_size; 928 unsigned output_offset = output_frame_size;
882 unsigned input_offset = input_frame_size; 929 unsigned input_offset = input_->GetFrameSize();
883 for (int i = 0; i < parameter_count; ++i) { 930 for (int i = 0; i < parameter_count; ++i) {
884 output_offset -= kPointerSize; 931 output_offset -= kPointerSize;
885 DoTranslateCommand(iterator, frame_index, output_offset); 932 DoTranslateCommand(iterator, frame_index, output_offset);
886 } 933 }
887 input_offset -= (parameter_count * kPointerSize); 934 input_offset -= (parameter_count * kPointerSize);
888 935
889 // There are no translation commands for the caller's pc and fp, the 936 // There are no translation commands for the caller's pc and fp, the
890 // context, and the function. Synthesize their values and set them up 937 // context, and the function. Synthesize their values and set them up
891 // explicitly. 938 // explicitly.
892 // 939 //
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
961 // The function for the bottommost output frame should also agree with the 1008 // The function for the bottommost output frame should also agree with the
962 // input frame. 1009 // input frame.
963 ASSERT(!is_bottommost || input_->GetFrameSlot(input_offset) == value); 1010 ASSERT(!is_bottommost || input_->GetFrameSlot(input_offset) == value);
964 output_frame->SetFrameSlot(output_offset, value); 1011 output_frame->SetFrameSlot(output_offset, value);
965 if (trace_) { 1012 if (trace_) {
966 PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" 1013 PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
967 V8PRIxPTR "; function\n", 1014 V8PRIxPTR "; function\n",
968 top_address + output_offset, output_offset, value); 1015 top_address + output_offset, output_offset, value);
969 } 1016 }
970 1017
1018 // Translate the stack-allocated locals.
1019 int stack_slot_count = function->shared()->scope_info()->StackSlotCount();
1020 for (int i = 0; i < stack_slot_count; ++i) {
1021 output_offset -= kPointerSize;
1022 DoTranslateCommand(iterator, frame_index, output_offset);
1023 }
1024
1025 // If there are any exception handlers, translate them.
1026 if (handler_count > 0) {
1027 // Translate the handler blocks. The output frame needs:
1028 //
1029 // incoming args | fixed part | locals | handlers | expression stack
1030 //
1031 // because try occurs as a statement, i.e., with the expression stack
1032 // empty. The input frame has:
1033 //
1034 // incoming args | fixed part | spill slots | handlers | outgoing args
1035 //
1036 // also because try is a statement, i.e., there is no pending call to
1037 // interleave handlers and args. This would change if we began inlining
1038 // functions containing try/catch.
1039 //
1040 // TODO(kmillikin): Begin inlining functions containing try/catch.
1041 input_offset = ComputeOutgoingArgumentSize() + ComputeHandlersSize();
1042 intptr_t next_handler = 0;
1043 for (int i = 0; i < handler_count; ++i) {
1044 // The first two fields (fp and context) are invariant under
1045 // deoptimization.
1046 output_offset -= kPointerSize;
1047 input_offset -= kPointerSize;
1048 value = input_->GetFrameSlot(input_offset);
1049 ASSERT(value == fp_value);
1050 output_frame->SetFrameSlot(output_offset, value);
1051 if (FLAG_trace_deopt) {
1052 PrintF(" 0x%08x: [top + %d] <- 0x%08x ; handler[%d] fp\n",
1053 top_address + output_offset, output_offset, value, i);
1054 }
1055
1056 output_offset -= kPointerSize;
1057 input_offset -= kPointerSize;
1058 value = input_->GetFrameSlot(input_offset);
1059 output_frame->SetFrameSlot(output_offset, value);
1060 if (FLAG_trace_deopt) {
1061 PrintF(" 0x%08x: [top + %d] <- 0x%08x ; handler[%d] context\n",
1062 top_address + output_offset, output_offset, value, i);
1063 }
1064
1065 // The state is the same except that the kind is unoptimized.
1066 output_offset -= kPointerSize;
1067 input_offset -= kPointerSize;
1068 value =
1069 input_->GetFrameSlot(input_offset) & ~StackHandler::kIsOptimizedMask;
1070 output_frame->SetFrameSlot(output_offset, value);
1071 if (FLAG_trace_deopt) {
1072 PrintF(" 0x%08x: [top + %d] <- 0x%08x ; handler[%d] index + kind\n",
1073 top_address + output_offset, output_offset, value, i);
1074 }
1075
1076 // For all handlers in the frame, the code is the unoptimized code.
1077 output_offset -= kPointerSize;
1078 input_offset -= kPointerSize;
1079 value = reinterpret_cast<uint32_t>(non_optimized_code);
1080 output_frame->SetFrameSlot(output_offset, value);
1081 if (FLAG_trace_deopt) {
1082 PrintF(" 0x%08x: [top + %d] <- 0x%08x ; handler[%d] code\n",
1083 top_address + output_offset, output_offset, value, i);
1084 }
1085
1086 output_offset -= kPointerSize;
1087 input_offset -= kPointerSize;
1088 if (i == 0) {
1089 // Bottommost handler's next link is deoptimization invariant.
1090 value = input_->GetFrameSlot(input_offset);
1091 } else {
1092 value = next_handler;
1093 }
1094 output_frame->SetFrameSlot(output_offset, value);
1095 next_handler = top_address + output_offset;
1096 if (FLAG_trace_deopt) {
1097 PrintF(" 0x%08x: [top + %d] <- 0x%08x ; handler[%d] next\n",
1098 top_address + output_offset, output_offset, value, i);
1099 }
1100 }
1101 *reinterpret_cast<intptr_t*>(isolate_->handler_address()) = next_handler;
1102 }
1103
971 // Translate the rest of the frame. 1104 // Translate the rest of the frame.
972 for (unsigned i = 0; i < height; ++i) { 1105 while (output_offset > 0) {
973 output_offset -= kPointerSize; 1106 output_offset -= kPointerSize;
974 DoTranslateCommand(iterator, frame_index, output_offset); 1107 DoTranslateCommand(iterator, frame_index, output_offset);
975 } 1108 }
976 ASSERT(0 == output_offset); 1109 ASSERT(0 == output_offset);
977 1110
978 // Compute this frame's PC, state, and continuation. 1111 // Compute this frame's PC, state, and continuation.
979 Code* non_optimized_code = function->shared()->code(); 1112 //TODO(mmassi): Where is non_optimized_code needed?
980 FixedArray* raw_data = non_optimized_code->deoptimization_data(); 1113 //Code* non_optimized_code = function->shared()->code();
981 DeoptimizationOutputData* data = DeoptimizationOutputData::cast(raw_data); 1114 int pc_offset;
982 Address start = non_optimized_code->instruction_start(); 1115 FullCodeGenerator::State state;
983 unsigned pc_and_state = GetOutputInfo(data, node_id, function->shared()); 1116 Builtins::Name continuation;
984 unsigned pc_offset = FullCodeGenerator::PcField::decode(pc_and_state); 1117 if (isolate_->optimized_handler_patch_buffer() != NULL) {
985 intptr_t pc_value = reinterpret_cast<intptr_t>(start + pc_offset); 1118 ASSERT(frame_index == 0 && output_count_ == 1);
986 output_frame->SetPc(pc_value); 1119 // Catching in optimized code. Deopt to the corresponding unoptimized
987 1120 // catch handler (not to the instruction following the one that threw).
988 FullCodeGenerator::State state = 1121 FixedArray* handler_table = non_optimized_code->handler_table();
989 FullCodeGenerator::StateField::decode(pc_and_state); 1122 int handler_index = isolate_->optimized_handler_handler_index();
1123 pc_offset = Smi::cast(handler_table->get(handler_index))->value();
1124 state = FullCodeGenerator::NO_REGISTERS;
1125 continuation = Builtins::kNotifyLazyDeoptimized;
1126 // The exception value is needed in eax.
1127 output_frame->SetRegister(
1128 eax.code(),
1129 reinterpret_cast<intptr_t>(isolate_->optimized_pending_exception()));
1130 isolate_->clear_optimized_pending_exception();
1131 } else {
1132 FixedArray* raw_data = non_optimized_code->deoptimization_data();
1133 DeoptimizationOutputData* data = DeoptimizationOutputData::cast(raw_data);
1134 unsigned pc_and_state = GetOutputInfo(data, node_id, function->shared());
1135 pc_offset = FullCodeGenerator::PcField::decode(pc_and_state);
1136 state = FullCodeGenerator::StateField::decode(pc_and_state);
1137 continuation = (bailout_type_ == EAGER)
1138 ? Builtins::kNotifyDeoptimized
1139 : Builtins::kNotifyLazyDeoptimized;
1140 // For lazy deopt we preserve eax in the stack. Ensure that it is not
1141 // the zap value (a probably-invalid HeapObject*).
1142 // TODO(mmassi): According to Kevin the test should be "!= EAGER"...
1143 if (bailout_type_ == EAGER && is_topmost) {
1144 output_frame->SetRegister(eax.code(),
1145 reinterpret_cast<intptr_t>(Smi::FromInt(0)));
1146 }
1147 }
1148 byte* code_start = non_optimized_code->instruction_start();
1149 output_frame->SetPc(reinterpret_cast<uint32_t>(code_start + pc_offset));
1150
990 output_frame->SetState(Smi::FromInt(state)); 1151 output_frame->SetState(Smi::FromInt(state));
991 1152
992 // Set the continuation for the topmost frame. 1153 // Set the continuation for the topmost frame.
993 if (is_topmost && bailout_type_ != DEBUGGER) { 1154 if (is_topmost && bailout_type_ != DEBUGGER) {
994 Builtins* builtins = isolate_->builtins(); 1155 Builtins* builtins = isolate_->builtins();
995 Code* continuation = builtins->builtin(Builtins::kNotifyDeoptimized); 1156 byte* entry = builtins->builtin(continuation)->entry();
996 if (bailout_type_ == LAZY) { 1157 output_frame->SetContinuation(reinterpret_cast<uint32_t>(entry));
997 continuation = builtins->builtin(Builtins::kNotifyLazyDeoptimized);
998 } else if (bailout_type_ == SOFT) {
999 continuation = builtins->builtin(Builtins::kNotifySoftDeoptimized);
1000 } else {
1001 ASSERT(bailout_type_ == EAGER);
1002 }
1003 output_frame->SetContinuation(
1004 reinterpret_cast<intptr_t>(continuation->entry()));
1005 } 1158 }
1006 } 1159 }
1007 1160
1008 1161
1009 void Deoptimizer::DoComputeArgumentsAdaptorFrame(TranslationIterator* iterator, 1162 void Deoptimizer::DoComputeArgumentsAdaptorFrame(TranslationIterator* iterator,
1010 int frame_index) { 1163 int frame_index) {
1011 JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next())); 1164 JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next()));
1012 unsigned height = iterator->Next(); 1165 unsigned height = iterator->Next();
1013 unsigned height_in_bytes = height * kPointerSize; 1166 unsigned height_in_bytes = height * kPointerSize;
1014 if (trace_) { 1167 if (trace_) {
(...skipping 1025 matching lines...) Expand 10 before | Expand all | Expand 10 after
2040 // We save the untagged value on the side and store a GC-safe 2193 // We save the untagged value on the side and store a GC-safe
2041 // temporary placeholder in the frame. 2194 // temporary placeholder in the frame.
2042 AddDoubleValue(output_[frame_index]->GetTop() + output_offset, value); 2195 AddDoubleValue(output_[frame_index]->GetTop() + output_offset, value);
2043 output_[frame_index]->SetFrameSlot(output_offset, kPlaceholder); 2196 output_[frame_index]->SetFrameSlot(output_offset, kPlaceholder);
2044 return; 2197 return;
2045 } 2198 }
2046 2199
2047 case Translation::STACK_SLOT: { 2200 case Translation::STACK_SLOT: {
2048 int input_slot_index = iterator->Next(); 2201 int input_slot_index = iterator->Next();
2049 unsigned input_offset = input_->GetOffsetFromSlotIndex(input_slot_index); 2202 unsigned input_offset = input_->GetOffsetFromSlotIndex(input_slot_index);
2050 intptr_t input_value = input_->GetFrameSlot(input_offset); 2203 intptr_t input_value;
2204 if (isolate_->optimized_handler_patch_buffer() != NULL &&
2205 input_offset >= input_->frame_size()) {
2206 // Skip stack slots that were above the handler (they must be
2207 // arguments that must be thrown away because try is a statement).
2208 input_value = static_cast<intptr_t>(NULL);
2209 if (FLAG_trace_deopt) {
2210 PrintF(" SKIPPING SLOT ABOVE HANDLER (ARGUMENT)\n");
2211 }
2212 } else {
2213 input_value = input_->GetFrameSlot(input_offset);
2214 }
2051 if (trace_) { 2215 if (trace_) {
2052 PrintF(" 0x%08" V8PRIxPTR ": ", 2216 PrintF(" 0x%08" V8PRIxPTR ": ",
2053 output_[frame_index]->GetTop() + output_offset); 2217 output_[frame_index]->GetTop() + output_offset);
2054 PrintF("[top + %d] <- 0x%08" V8PRIxPTR " ; [sp + %d] ", 2218 PrintF("[top + %d] <- 0x%08" V8PRIxPTR " ; [sp + %d] ",
2055 output_offset, 2219 output_offset,
2056 input_value, 2220 input_value,
2057 input_offset); 2221 input_offset);
2058 reinterpret_cast<Object*>(input_value)->ShortPrint(); 2222 reinterpret_cast<Object*>(input_value)->ShortPrint();
2059 PrintF("\n"); 2223 PrintF("\n");
2060 } 2224 }
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
2205 switch (opcode) { 2369 switch (opcode) {
2206 case Translation::BEGIN: 2370 case Translation::BEGIN:
2207 case Translation::JS_FRAME: 2371 case Translation::JS_FRAME:
2208 case Translation::ARGUMENTS_ADAPTOR_FRAME: 2372 case Translation::ARGUMENTS_ADAPTOR_FRAME:
2209 case Translation::CONSTRUCT_STUB_FRAME: 2373 case Translation::CONSTRUCT_STUB_FRAME:
2210 case Translation::GETTER_STUB_FRAME: 2374 case Translation::GETTER_STUB_FRAME:
2211 case Translation::SETTER_STUB_FRAME: 2375 case Translation::SETTER_STUB_FRAME:
2212 case Translation::COMPILED_STUB_FRAME: 2376 case Translation::COMPILED_STUB_FRAME:
2213 case Translation::DUPLICATE: 2377 case Translation::DUPLICATE:
2214 UNREACHABLE(); // Malformed input. 2378 UNREACHABLE(); // Malformed input.
2215 return false; 2379 return false;
2216 2380
2217 case Translation::REGISTER: { 2381 case Translation::REGISTER: {
2218 int output_reg = iterator->Next(); 2382 int output_reg = iterator->Next();
2219 if (FLAG_trace_osr) { 2383 if (FLAG_trace_osr) {
2220 PrintF(" %s <- 0x%08" V8PRIxPTR " ; [sp + %d]\n", 2384 PrintF(" %s <- 0x%08" V8PRIxPTR " ; [sp + %d]\n",
2221 converter.NameOfCPURegister(output_reg), 2385 converter.NameOfCPURegister(output_reg),
2222 input_value, 2386 input_value,
2223 *input_offset); 2387 *input_offset);
2224 } 2388 }
2225 output->SetRegister(output_reg, input_value); 2389 output->SetRegister(output_reg, input_value);
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after
2461 pc_after, 2625 pc_after,
2462 interrupt_code, 2626 interrupt_code,
2463 replacement_code)); 2627 replacement_code));
2464 back_edge_cursor += FullCodeGenerator::kBackEdgeEntrySize; 2628 back_edge_cursor += FullCodeGenerator::kBackEdgeEntrySize;
2465 } 2629 }
2466 } 2630 }
2467 #endif // DEBUG 2631 #endif // DEBUG
2468 2632
2469 2633
2470 unsigned Deoptimizer::ComputeInputFrameSize() const { 2634 unsigned Deoptimizer::ComputeInputFrameSize() const {
2635 // This is the size of the frame that is the same for both optimized and
2636 // unoptimized frames---the incoming parameters and the fixed part of the
2637 // frame.
2471 unsigned fixed_size = ComputeFixedSize(function_); 2638 unsigned fixed_size = ComputeFixedSize(function_);
2639
2472 // The fp-to-sp delta already takes the context and the function 2640 // The fp-to-sp delta already takes the context and the function
2473 // into account so we have to avoid double counting them (-2). 2641 // into account so we have to avoid double counting them (-2).
2474 unsigned result = fixed_size + fp_to_sp_delta_ - (2 * kPointerSize); 2642 unsigned result = fixed_size + fp_to_sp_delta_ - (2 * kPointerSize);
2643
2475 #ifdef DEBUG 2644 #ifdef DEBUG
2476 if (bailout_type_ == OSR) { 2645 if (bailout_type_ == OSR) {
2477 // TODO(kasperl): It would be nice if we could verify that the 2646 // TODO(kasperl): It would be nice if we could verify that the
2478 // size matches with the stack height we can compute based on the 2647 // size matches with the stack height we can compute based on the
2479 // environment at the OSR entry. The code for that his built into 2648 // environment at the OSR entry. The code for that his built into
2480 // the DoComputeOsrOutputFrame function for now. 2649 // the DoComputeOsrOutputFrame function for now.
2481 } else if (compiled_code_->kind() == Code::OPTIMIZED_FUNCTION) { 2650 } else if (compiled_code_->kind() == Code::OPTIMIZED_FUNCTION) {
2482 unsigned stack_slots = compiled_code_->stack_slots(); 2651 // Verify the actual frame size matches the expected (fixed part +
2483 unsigned outgoing_size = ComputeOutgoingArgumentSize(); 2652 // spill slots + exception handlers + outgoing arguments).
2484 ASSERT(result == fixed_size + (stack_slots * kPointerSize) + outgoing_size); 2653 unsigned spill_slots_size = compiled_code_->stack_slots() * kPointerSize;
2654 unsigned handlers_size = ComputeHandlersSize();
2655 // If we are doing lazy deoptimization for catching in an optimized
2656 // frame, one of the handlers in the frame description has already been
2657 // dropped by throwing to it.
2658 if (isolate_->optimized_handler_patch_buffer() != NULL) {
2659 ASSERT(bailout_type_ == LAZY);
2660 ASSERT(static_cast<int>(handlers_size) >= StackHandlerConstants::kSize);
2661 handlers_size -= StackHandlerConstants::kSize;
2662 }
2663 unsigned outgoing_arg_size = ComputeOutgoingArgumentSize();
2664 ASSERT(result ==
2665 fixed_size + spill_slots_size + handlers_size + outgoing_arg_size);
2485 } 2666 }
2486 #endif 2667 #endif
2487 return result; 2668 return result;
2488 } 2669 }
2489 2670
2490 2671
2491 unsigned Deoptimizer::ComputeFixedSize(JSFunction* function) const { 2672 unsigned Deoptimizer::ComputeFixedSize(JSFunction* function) const {
2492 // The fixed part of the frame consists of the return address, frame 2673 // The fixed part of the frame consists of the return address, frame
2493 // pointer, function, context, and all the incoming arguments. 2674 // pointer, function, context, and all the incoming arguments.
2494 return ComputeIncomingArgumentSize(function) + 2675 return ComputeIncomingArgumentSize(function) +
2495 StandardFrameConstants::kFixedFrameSize; 2676 StandardFrameConstants::kFixedFrameSize;
2496 } 2677 }
2497 2678
2498 2679
2499 unsigned Deoptimizer::ComputeIncomingArgumentSize(JSFunction* function) const { 2680 unsigned Deoptimizer::ComputeIncomingArgumentSize(JSFunction* function) const {
2500 // The incoming arguments is the values for formal parameters and 2681 // The incoming arguments is the values for formal parameters and
2501 // the receiver. Every slot contains a pointer. 2682 // the receiver. Every slot contains a pointer.
2502 if (function->IsSmi()) { 2683 if (function->IsSmi()) {
2503 ASSERT(Smi::cast(function) == Smi::FromInt(StackFrame::STUB)); 2684 ASSERT(Smi::cast(function) == Smi::FromInt(StackFrame::STUB));
2504 return 0; 2685 return 0;
2505 } 2686 }
2506 unsigned arguments = function->shared()->formal_parameter_count() + 1; 2687 unsigned arguments = function->shared()->formal_parameter_count() + 1;
2507 return arguments * kPointerSize; 2688 return arguments * kPointerSize;
2508 } 2689 }
2509 2690
2510 2691
2511 unsigned Deoptimizer::ComputeOutgoingArgumentSize() const { 2692 unsigned Deoptimizer::ComputeOutgoingArgumentSize() const {
2693 // Since try is a statement there will not be arguments left on the stack
2694 // once we have popped the handler.
2695 if (isolate_->optimized_handler_patch_buffer() != NULL) {
2696 return 0;
2697 }
2698
2512 DeoptimizationInputData* data = DeoptimizationInputData::cast( 2699 DeoptimizationInputData* data = DeoptimizationInputData::cast(
2513 compiled_code_->deoptimization_data()); 2700 compiled_code_->deoptimization_data());
2514 unsigned height = data->ArgumentsStackHeight(bailout_id_)->value(); 2701 unsigned height = data->ArgumentsStackHeight(bailout_id_)->value();
2515 return height * kPointerSize; 2702 return height * kPointerSize;
2516 } 2703 }
2517 2704
2518 2705
2706 unsigned Deoptimizer::ComputeHandlersSize() const {
2707 DeoptimizationInputData* data = DeoptimizationInputData::cast(
2708 compiled_code_->deoptimization_data());
2709 unsigned handler_count = data->HandlerCount(bailout_id_)->value();
2710 return handler_count * StackHandlerConstants::kSize;
2711 }
2712
2713
2519 Object* Deoptimizer::ComputeLiteral(int index) const { 2714 Object* Deoptimizer::ComputeLiteral(int index) const {
2520 DeoptimizationInputData* data = DeoptimizationInputData::cast( 2715 DeoptimizationInputData* data = DeoptimizationInputData::cast(
2521 compiled_code_->deoptimization_data()); 2716 compiled_code_->deoptimization_data());
2522 FixedArray* literals = data->LiteralArray(); 2717 FixedArray* literals = data->LiteralArray();
2523 return literals->get(index); 2718 return literals->get(index);
2524 } 2719 }
2525 2720
2526 2721
2527 void Deoptimizer::AddObjectStart(intptr_t slot_address, int length) { 2722 void Deoptimizer::AddObjectStart(intptr_t slot_address, int length) {
2528 ObjectMaterializationDescriptor object_desc( 2723 ObjectMaterializationDescriptor object_desc(
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after
2743 2938
2744 void Translation::BeginArgumentsAdaptorFrame(int literal_id, unsigned height) { 2939 void Translation::BeginArgumentsAdaptorFrame(int literal_id, unsigned height) {
2745 buffer_->Add(ARGUMENTS_ADAPTOR_FRAME, zone()); 2940 buffer_->Add(ARGUMENTS_ADAPTOR_FRAME, zone());
2746 buffer_->Add(literal_id, zone()); 2941 buffer_->Add(literal_id, zone());
2747 buffer_->Add(height, zone()); 2942 buffer_->Add(height, zone());
2748 } 2943 }
2749 2944
2750 2945
2751 void Translation::BeginJSFrame(BailoutId node_id, 2946 void Translation::BeginJSFrame(BailoutId node_id,
2752 int literal_id, 2947 int literal_id,
2753 unsigned height) { 2948 unsigned height,
2949 int handler_count) {
2754 buffer_->Add(JS_FRAME, zone()); 2950 buffer_->Add(JS_FRAME, zone());
2755 buffer_->Add(node_id.ToInt(), zone()); 2951 buffer_->Add(node_id.ToInt(), zone());
2756 buffer_->Add(literal_id, zone()); 2952 buffer_->Add(literal_id, zone());
2757 buffer_->Add(height, zone()); 2953 buffer_->Add(height, zone());
2954 buffer_->Add(handler_count, zone());
2758 } 2955 }
2759 2956
2760 2957
2761 void Translation::BeginCompiledStubFrame() { 2958 void Translation::BeginCompiledStubFrame() {
2762 buffer_->Add(COMPILED_STUB_FRAME, zone()); 2959 buffer_->Add(COMPILED_STUB_FRAME, zone());
2763 } 2960 }
2764 2961
2765 2962
2766 void Translation::BeginArgumentsObject(int args_length) { 2963 void Translation::BeginArgumentsObject(int args_length) {
2767 buffer_->Add(ARGUMENTS_OBJECT, zone()); 2964 buffer_->Add(ARGUMENTS_OBJECT, zone());
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
2844 case UINT32_STACK_SLOT: 3041 case UINT32_STACK_SLOT:
2845 case DOUBLE_STACK_SLOT: 3042 case DOUBLE_STACK_SLOT:
2846 case LITERAL: 3043 case LITERAL:
2847 case COMPILED_STUB_FRAME: 3044 case COMPILED_STUB_FRAME:
2848 return 1; 3045 return 1;
2849 case BEGIN: 3046 case BEGIN:
2850 case ARGUMENTS_ADAPTOR_FRAME: 3047 case ARGUMENTS_ADAPTOR_FRAME:
2851 case CONSTRUCT_STUB_FRAME: 3048 case CONSTRUCT_STUB_FRAME:
2852 return 2; 3049 return 2;
2853 case JS_FRAME: 3050 case JS_FRAME:
2854 return 3; 3051 return 4;
2855 } 3052 }
2856 UNREACHABLE(); 3053 UNREACHABLE();
2857 return -1; 3054 return -1;
2858 } 3055 }
2859 3056
2860 3057
2861 #if defined(OBJECT_PRINT) || defined(ENABLE_DISASSEMBLER) 3058 #if defined(OBJECT_PRINT) || defined(ENABLE_DISASSEMBLER)
2862 3059
2863 const char* Translation::StringFor(Opcode opcode) { 3060 const char* Translation::StringFor(Opcode opcode) {
2864 switch (opcode) { 3061 switch (opcode) {
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after
3111 3308
3112 void DeoptimizedFrameInfo::Iterate(ObjectVisitor* v) { 3309 void DeoptimizedFrameInfo::Iterate(ObjectVisitor* v) {
3113 v->VisitPointer(BitCast<Object**>(&function_)); 3310 v->VisitPointer(BitCast<Object**>(&function_));
3114 v->VisitPointers(parameters_, parameters_ + parameters_count_); 3311 v->VisitPointers(parameters_, parameters_ + parameters_count_);
3115 v->VisitPointers(expression_stack_, expression_stack_ + expression_count_); 3312 v->VisitPointers(expression_stack_, expression_stack_ + expression_count_);
3116 } 3313 }
3117 3314
3118 #endif // ENABLE_DEBUGGER_SUPPORT 3315 #endif // ENABLE_DEBUGGER_SUPPORT
3119 3316
3120 } } // namespace v8::internal 3317 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/deoptimizer.h ('k') | src/flag-definitions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698