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 <stdlib.h> | 5 #include <stdlib.h> |
6 | 6 |
7 #include <fstream> // NOLINT(readability/streams) | 7 #include <fstream> // NOLINT(readability/streams) |
8 #include <sstream> | 8 #include <sstream> |
9 | 9 |
10 #include "src/v8.h" | 10 #include "src/v8.h" |
(...skipping 990 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1001 | 1001 |
1002 Object* Isolate::ReThrow(Object* exception) { | 1002 Object* Isolate::ReThrow(Object* exception) { |
1003 DCHECK(!has_pending_exception()); | 1003 DCHECK(!has_pending_exception()); |
1004 | 1004 |
1005 // Set the exception being re-thrown. | 1005 // Set the exception being re-thrown. |
1006 set_pending_exception(exception); | 1006 set_pending_exception(exception); |
1007 return heap()->exception(); | 1007 return heap()->exception(); |
1008 } | 1008 } |
1009 | 1009 |
1010 | 1010 |
1011 // TODO(turbofan): Make sure table is sorted and use binary search. | |
1012 static int LookupInHandlerTable(Code* code, int pc_offset) { | |
1013 FixedArray* handler_table = code->handler_table(); | |
1014 for (int i = 0; i < handler_table->length(); i += 2) { | |
1015 int return_offset = Smi::cast(handler_table->get(i))->value(); | |
1016 int handler_offset = Smi::cast(handler_table->get(i + 1))->value(); | |
1017 if (pc_offset == return_offset) return handler_offset; | |
1018 } | |
1019 return -1; | |
1020 } | |
1021 | |
1022 | |
1023 Object* Isolate::FindHandler() { | 1011 Object* Isolate::FindHandler() { |
1024 Object* exception = pending_exception(); | 1012 Object* exception = pending_exception(); |
1025 | 1013 |
1026 Code* code = nullptr; | 1014 Code* code = nullptr; |
1027 Context* context = nullptr; | 1015 Context* context = nullptr; |
1028 intptr_t offset = 0; | 1016 intptr_t offset = 0; |
1029 Address handler_sp = nullptr; | 1017 Address handler_sp = nullptr; |
1030 Address handler_fp = nullptr; | 1018 Address handler_fp = nullptr; |
1031 | 1019 |
1032 // Special handling of termination exceptions, uncatchable by JavaScript code, | 1020 // Special handling of termination exceptions, uncatchable by JavaScript code, |
1033 // we unwind the handlers until the top ENTRY handler is found. | 1021 // we unwind the handlers until the top ENTRY handler is found. |
1034 bool catchable_by_js = is_catchable_by_javascript(exception); | 1022 bool catchable_by_js = is_catchable_by_javascript(exception); |
1035 | 1023 |
1036 // Compute handler and stack unwinding information by performing a full walk | 1024 // Compute handler and stack unwinding information by performing a full walk |
1037 // over the stack and dispatching according to the frame type. | 1025 // over the stack and dispatching according to the frame type. |
1038 for (StackFrameIterator iter(this); !iter.done(); iter.Advance()) { | 1026 for (StackFrameIterator iter(this); !iter.done(); iter.Advance()) { |
1039 StackFrame* frame = iter.frame(); | 1027 StackFrame* frame = iter.frame(); |
1040 | 1028 |
1041 // For JSEntryStub frames we always have a handler. | 1029 // For JSEntryStub frames we always have a handler. |
1042 if (frame->is_entry() || frame->is_entry_construct()) { | 1030 if (frame->is_entry() || frame->is_entry_construct()) { |
1043 StackHandler* handler = frame->top_handler(); | 1031 StackHandler* handler = frame->top_handler(); |
1044 DCHECK_EQ(0, handler->index()); | |
1045 | 1032 |
1046 // Restore the next handler. | 1033 // Restore the next handler. |
1047 thread_local_top()->handler_ = handler->next()->address(); | 1034 thread_local_top()->handler_ = handler->next()->address(); |
1048 | 1035 |
1049 // Gather information from the handler. | 1036 // Gather information from the handler. |
1050 code = frame->LookupCode(); | 1037 code = frame->LookupCode(); |
1051 handler_sp = handler->address() + StackHandlerConstants::kSize; | 1038 handler_sp = handler->address() + StackHandlerConstants::kSize; |
1052 offset = Smi::cast(code->handler_table()->get(0))->value(); | 1039 offset = Smi::cast(code->handler_table()->get(0))->value(); |
1053 break; | 1040 break; |
1054 } | 1041 } |
1055 | 1042 |
1056 // For JavaScript frames which have a handler, we use the handler. | |
1057 if (frame->is_java_script() && catchable_by_js && frame->HasHandler()) { | |
1058 StackHandler* handler = frame->top_handler(); | |
1059 | |
1060 // Restore the next handler. | |
1061 thread_local_top()->handler_ = handler->next()->address(); | |
1062 | |
1063 // Gather information from the handler. | |
1064 code = frame->LookupCode(); | |
1065 context = handler->context(); | |
1066 offset = Smi::cast(code->handler_table()->get(handler->index()))->value(); | |
1067 handler_sp = handler->address() + StackHandlerConstants::kSize; | |
1068 handler_fp = frame->fp(); | |
1069 break; | |
1070 } | |
1071 | |
1072 // For optimized frames we perform a lookup in the handler table. | 1043 // For optimized frames we perform a lookup in the handler table. |
1073 if (frame->is_optimized() && catchable_by_js) { | 1044 if (frame->is_optimized() && catchable_by_js) { |
1074 Code* frame_code = frame->LookupCode(); | 1045 OptimizedFrame* js_frame = static_cast<OptimizedFrame*>(frame); |
1075 DCHECK(frame_code->is_optimized_code()); | 1046 int stack_slots = 0; // Will contain stack slot count of frame. |
1076 int pc_offset = static_cast<int>(frame->pc() - frame_code->entry()); | 1047 offset = js_frame->LookupExceptionHandlerInTable(&stack_slots); |
1077 int handler_offset = LookupInHandlerTable(frame_code, pc_offset); | 1048 if (offset < 0) continue; |
1078 if (handler_offset < 0) continue; | |
1079 | 1049 |
1080 // Compute the stack pointer from the frame pointer. This ensures that | 1050 // Compute the stack pointer from the frame pointer. This ensures that |
1081 // argument slots on the stack are dropped as returning would. | 1051 // argument slots on the stack are dropped as returning would. |
1082 Address return_sp = frame->fp() - | 1052 Address return_sp = frame->fp() - |
1083 StandardFrameConstants::kFixedFrameSizeFromFp - | 1053 StandardFrameConstants::kFixedFrameSizeFromFp - |
1084 frame_code->stack_slots() * kPointerSize; | 1054 stack_slots * kPointerSize; |
1085 | 1055 |
1086 // Gather information from the frame. | 1056 // Gather information from the frame. |
1087 code = frame_code; | 1057 code = frame->LookupCode(); |
1088 offset = handler_offset; | |
1089 handler_sp = return_sp; | 1058 handler_sp = return_sp; |
1090 handler_fp = frame->fp(); | 1059 handler_fp = frame->fp(); |
1091 break; | 1060 break; |
| 1061 } |
| 1062 |
| 1063 // For JavaScript frames we perform a range lookup in the handler table. |
| 1064 if (frame->is_java_script() && catchable_by_js) { |
| 1065 JavaScriptFrame* js_frame = static_cast<JavaScriptFrame*>(frame); |
| 1066 int stack_slots = 0; // Will contain operand stack depth of handler. |
| 1067 offset = js_frame->LookupExceptionHandlerInTable(&stack_slots); |
| 1068 if (offset < 0) continue; |
| 1069 |
| 1070 // Compute the stack pointer from the frame pointer. This ensures that |
| 1071 // operand stack slots are dropped for nested statements. Also restore |
| 1072 // correct context for the handler which is pushed within the try-block. |
| 1073 Address return_sp = frame->fp() - |
| 1074 StandardFrameConstants::kFixedFrameSizeFromFp - |
| 1075 stack_slots * kPointerSize; |
| 1076 STATIC_ASSERT(TryBlockConstant::kElementCount == 1); |
| 1077 context = Context::cast(Memory::Object_at(return_sp - kPointerSize)); |
| 1078 |
| 1079 // Gather information from the frame. |
| 1080 code = frame->LookupCode(); |
| 1081 handler_sp = return_sp; |
| 1082 handler_fp = frame->fp(); |
| 1083 break; |
1092 } | 1084 } |
1093 } | 1085 } |
1094 | 1086 |
1095 // Handler must exist. | 1087 // Handler must exist. |
1096 CHECK(code != nullptr); | 1088 CHECK(code != nullptr); |
1097 | 1089 |
1098 // Store information to be consumed by the CEntryStub. | 1090 // Store information to be consumed by the CEntryStub. |
1099 thread_local_top()->pending_handler_context_ = context; | 1091 thread_local_top()->pending_handler_context_ = context; |
1100 thread_local_top()->pending_handler_code_ = code; | 1092 thread_local_top()->pending_handler_code_ = code; |
1101 thread_local_top()->pending_handler_offset_ = offset; | 1093 thread_local_top()->pending_handler_offset_ = offset; |
1102 thread_local_top()->pending_handler_fp_ = handler_fp; | 1094 thread_local_top()->pending_handler_fp_ = handler_fp; |
1103 thread_local_top()->pending_handler_sp_ = handler_sp; | 1095 thread_local_top()->pending_handler_sp_ = handler_sp; |
1104 | 1096 |
1105 // Return and clear pending exception. | 1097 // Return and clear pending exception. |
1106 clear_pending_exception(); | 1098 clear_pending_exception(); |
1107 return exception; | 1099 return exception; |
1108 } | 1100 } |
1109 | 1101 |
1110 | 1102 |
1111 // TODO(mstarzinger): We shouldn't need the exception object here. | 1103 // TODO(mstarzinger): We shouldn't need the exception object here. |
1112 bool Isolate::PredictWhetherExceptionIsCaught(Object* exception) { | 1104 bool Isolate::PredictWhetherExceptionIsCaught(Object* exception) { |
1113 if (IsExternalHandlerOnTop(exception)) return true; | 1105 if (IsExternalHandlerOnTop(exception)) return true; |
1114 | 1106 |
1115 // Search for a JavaScript handler by performing a full walk over the stack | 1107 // Search for a JavaScript handler by performing a full walk over the stack. |
1116 // and dispatching according to the frame type. | 1108 for (JavaScriptFrameIterator iter(this); !iter.done(); iter.Advance()) { |
1117 for (StackFrameIterator iter(this); !iter.done(); iter.Advance()) { | 1109 JavaScriptFrame* frame = iter.frame(); |
1118 StackFrame* frame = iter.frame(); | 1110 int stack_slots = 0; // The computed stack slot count is not used. |
1119 | 1111 if (frame->LookupExceptionHandlerInTable(&stack_slots) > 0) return true; |
1120 // For JavaScript frames which have a handler, we use the handler. | |
1121 if (frame->is_java_script() && frame->HasHandler()) { | |
1122 return true; | |
1123 } | |
1124 | |
1125 // For optimized frames we perform a lookup in the handler table. | |
1126 if (frame->is_optimized()) { | |
1127 Code* frame_code = frame->LookupCode(); | |
1128 DCHECK(frame_code->is_optimized_code()); | |
1129 int pc_offset = static_cast<int>(frame->pc() - frame_code->entry()); | |
1130 int handler_offset = LookupInHandlerTable(frame_code, pc_offset); | |
1131 if (handler_offset < 0) continue; | |
1132 return true; | |
1133 } | |
1134 } | 1112 } |
1135 | 1113 |
1136 // Handler not found. | 1114 // Handler not found. |
1137 return false; | 1115 return false; |
1138 } | 1116 } |
1139 | 1117 |
1140 | 1118 |
1141 Object* Isolate::ThrowIllegalOperation() { | 1119 Object* Isolate::ThrowIllegalOperation() { |
1142 if (FLAG_stack_trace_on_illegal) PrintStack(stdout); | 1120 if (FLAG_stack_trace_on_illegal) PrintStack(stdout); |
1143 return Throw(heap()->illegal_access_string()); | 1121 return Throw(heap()->illegal_access_string()); |
(...skipping 1478 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2622 if (prev_ && prev_->Intercept(flag)) return true; | 2600 if (prev_ && prev_->Intercept(flag)) return true; |
2623 // Then check whether this scope intercepts. | 2601 // Then check whether this scope intercepts. |
2624 if ((flag & intercept_mask_)) { | 2602 if ((flag & intercept_mask_)) { |
2625 intercepted_flags_ |= flag; | 2603 intercepted_flags_ |= flag; |
2626 return true; | 2604 return true; |
2627 } | 2605 } |
2628 return false; | 2606 return false; |
2629 } | 2607 } |
2630 | 2608 |
2631 } } // namespace v8::internal | 2609 } } // namespace v8::internal |
OLD | NEW |