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 1013 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1024 | 1024 |
1025 thread_local_top()->catcher_ = can_be_caught_externally ? | 1025 thread_local_top()->catcher_ = can_be_caught_externally ? |
1026 try_catch_handler() : NULL; | 1026 try_catch_handler() : NULL; |
1027 | 1027 |
1028 // Set the exception being re-thrown. | 1028 // Set the exception being re-thrown. |
1029 set_pending_exception(exception); | 1029 set_pending_exception(exception); |
1030 return heap()->exception(); | 1030 return heap()->exception(); |
1031 } | 1031 } |
1032 | 1032 |
1033 | 1033 |
| 1034 // TODO(turbofan): Make sure table is sorted and use binary search. |
| 1035 static int LookupInHandlerTable(Code* code, int pc_offset) { |
| 1036 FixedArray* handler_table = code->handler_table(); |
| 1037 for (int i = 0; i < handler_table->length(); i += 2) { |
| 1038 int return_offset = Smi::cast(handler_table->get(i))->value(); |
| 1039 int handler_offset = Smi::cast(handler_table->get(i + 1))->value(); |
| 1040 if (pc_offset == return_offset) return handler_offset; |
| 1041 } |
| 1042 return -1; |
| 1043 } |
| 1044 |
| 1045 |
1034 Object* Isolate::FindHandler() { | 1046 Object* Isolate::FindHandler() { |
1035 Object* exception = pending_exception(); | 1047 Object* exception = pending_exception(); |
1036 | 1048 |
1037 // Determine target stack handler. Special handling of termination exceptions | 1049 Code* code = nullptr; |
1038 // which are uncatchable by JavaScript code, we unwind the handlers until the | 1050 Context* context = nullptr; |
1039 // top ENTRY handler is found. | 1051 intptr_t offset = 0; |
1040 StackHandler* handler = | 1052 Address handler_sp = nullptr; |
1041 StackHandler::FromAddress(Isolate::handler(thread_local_top())); | 1053 Address handler_fp = nullptr; |
1042 if (!is_catchable_by_javascript(exception)) { | 1054 |
1043 while (!handler->is_js_entry()) handler = handler->next(); | 1055 // Special handling of termination exceptions, uncatchable by JavaScript code, |
| 1056 // we unwind the handlers until the top ENTRY handler is found. |
| 1057 bool catchable_by_js = is_catchable_by_javascript(exception); |
| 1058 |
| 1059 // Compute handler and stack unwinding information by performing a full walk |
| 1060 // over the stack and dispatching according to the frame type. |
| 1061 for (StackFrameIterator iter(this); !iter.done(); iter.Advance()) { |
| 1062 StackFrame* frame = iter.frame(); |
| 1063 |
| 1064 // For JSEntryStub frames we always have a handler. |
| 1065 if (frame->is_entry() || frame->is_entry_construct()) { |
| 1066 StackHandler* handler = frame->top_handler(); |
| 1067 DCHECK_EQ(StackHandler::JS_ENTRY, handler->kind()); |
| 1068 DCHECK_EQ(0, handler->index()); |
| 1069 |
| 1070 // Restore the next handler. |
| 1071 thread_local_top()->handler_ = handler->next()->address(); |
| 1072 |
| 1073 // Gather information from the handler. |
| 1074 code = handler->code(); |
| 1075 handler_sp = handler->address() + StackHandlerConstants::kSize; |
| 1076 offset = Smi::cast(code->handler_table()->get(0))->value(); |
| 1077 break; |
| 1078 } |
| 1079 |
| 1080 // For JavaScript frames which have a handler, we use the handler. |
| 1081 if (frame->is_java_script() && catchable_by_js && frame->HasHandler()) { |
| 1082 StackHandler* handler = frame->top_handler(); |
| 1083 DCHECK_NE(StackHandler::JS_ENTRY, handler->kind()); |
| 1084 |
| 1085 // Restore the next handler. |
| 1086 thread_local_top()->handler_ = handler->next()->address(); |
| 1087 |
| 1088 // Gather information from the handler. |
| 1089 code = handler->code(); |
| 1090 context = handler->context(); |
| 1091 offset = Smi::cast(code->handler_table()->get(handler->index()))->value(); |
| 1092 handler_sp = handler->address() + StackHandlerConstants::kSize; |
| 1093 handler_fp = handler->frame_pointer(); |
| 1094 break; |
| 1095 } |
| 1096 |
| 1097 // For optimized frames we perform a lookup in the handler table. |
| 1098 if (frame->is_optimized() && catchable_by_js) { |
| 1099 Code* frame_code = frame->LookupCode(); |
| 1100 DCHECK(frame_code->is_optimized_code()); |
| 1101 int pc_offset = static_cast<int>(frame->pc() - frame_code->entry()); |
| 1102 int handler_offset = LookupInHandlerTable(frame_code, pc_offset); |
| 1103 if (handler_offset < 0) continue; |
| 1104 |
| 1105 // Compute the stack pointer from the frame pointer. This ensures that |
| 1106 // argument slots on the stack are dropped as returning would. |
| 1107 Address return_sp = frame->fp() - |
| 1108 StandardFrameConstants::kFixedFrameSizeFromFp - |
| 1109 frame_code->stack_slots() * kPointerSize; |
| 1110 |
| 1111 // Gather information from the frame. |
| 1112 code = frame_code; |
| 1113 offset = handler_offset; |
| 1114 handler_sp = return_sp; |
| 1115 handler_fp = frame->fp(); |
| 1116 break; |
| 1117 } |
1044 } | 1118 } |
1045 | 1119 |
1046 // Restore the next handler. | 1120 // Handler must exist. |
1047 thread_local_top()->handler_ = handler->next()->address(); | 1121 CHECK(code != nullptr); |
1048 | |
1049 // Compute handler and stack unwinding information. | |
1050 // TODO(mstarzinger): Extend this to perform actual stack-walk and take into | |
1051 // account that TurboFan code can contain handlers as well. | |
1052 Code* code = handler->code(); | |
1053 Context* context = handler->is_js_entry() ? nullptr : handler->context(); | |
1054 int offset = Smi::cast(code->handler_table()->get(handler->index()))->value(); | |
1055 Address handler_sp = handler->address() + StackHandlerConstants::kSize; | |
1056 Address handler_fp = handler->frame_pointer(); | |
1057 | 1122 |
1058 // Store information to be consumed by the CEntryStub. | 1123 // Store information to be consumed by the CEntryStub. |
1059 thread_local_top()->pending_handler_context_ = context; | 1124 thread_local_top()->pending_handler_context_ = context; |
1060 thread_local_top()->pending_handler_code_ = code; | 1125 thread_local_top()->pending_handler_code_ = code; |
1061 thread_local_top()->pending_handler_offset_ = offset; | 1126 thread_local_top()->pending_handler_offset_ = offset; |
1062 thread_local_top()->pending_handler_fp_ = handler_fp; | 1127 thread_local_top()->pending_handler_fp_ = handler_fp; |
1063 thread_local_top()->pending_handler_sp_ = handler_sp; | 1128 thread_local_top()->pending_handler_sp_ = handler_sp; |
1064 | 1129 |
1065 // Return and clear pending exception. | 1130 // Return and clear pending exception. |
1066 clear_pending_exception(); | 1131 clear_pending_exception(); |
(...skipping 1522 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2589 if (prev_ && prev_->Intercept(flag)) return true; | 2654 if (prev_ && prev_->Intercept(flag)) return true; |
2590 // Then check whether this scope intercepts. | 2655 // Then check whether this scope intercepts. |
2591 if ((flag & intercept_mask_)) { | 2656 if ((flag & intercept_mask_)) { |
2592 intercepted_flags_ |= flag; | 2657 intercepted_flags_ |= flag; |
2593 return true; | 2658 return true; |
2594 } | 2659 } |
2595 return false; | 2660 return false; |
2596 } | 2661 } |
2597 | 2662 |
2598 } } // namespace v8::internal | 2663 } } // namespace v8::internal |
OLD | NEW |