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

Side by Side Diff: src/isolate.cc

Issue 1010883002: Switch full-codegen from StackHandlers to handler table. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@local_cleanup-isolate-dead-code
Patch Set: Fix debugger-pause-on-promise-rejection. Created 5 years, 9 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
« no previous file with comments | « src/isolate.h ('k') | src/objects.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 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 960 matching lines...) Expand 10 before | Expand all | Expand 10 after
971 ReportBootstrappingException(exception_handle, location); 971 ReportBootstrappingException(exception_handle, location);
972 } else { 972 } else {
973 Handle<Object> message_obj = CreateMessage(exception_handle, location); 973 Handle<Object> message_obj = CreateMessage(exception_handle, location);
974 thread_local_top()->pending_message_obj_ = *message_obj; 974 thread_local_top()->pending_message_obj_ = *message_obj;
975 975
976 // If the abort-on-uncaught-exception flag is specified, abort on any 976 // If the abort-on-uncaught-exception flag is specified, abort on any
977 // exception not caught by JavaScript, even when an external handler is 977 // exception not caught by JavaScript, even when an external handler is
978 // present. This flag is intended for use by JavaScript developers, so 978 // present. This flag is intended for use by JavaScript developers, so
979 // print a user-friendly stack trace (not an internal one). 979 // print a user-friendly stack trace (not an internal one).
980 if (FLAG_abort_on_uncaught_exception && 980 if (FLAG_abort_on_uncaught_exception &&
981 !PredictWhetherExceptionIsCaught(*exception_handle)) { 981 PredictExceptionCatcher() != CAUGHT_BY_JAVASCRIPT) {
982 FLAG_abort_on_uncaught_exception = false; // Prevent endless recursion. 982 FLAG_abort_on_uncaught_exception = false; // Prevent endless recursion.
983 PrintF(stderr, "%s\n\nFROM\n", 983 PrintF(stderr, "%s\n\nFROM\n",
984 MessageHandler::GetLocalizedMessage(this, message_obj).get()); 984 MessageHandler::GetLocalizedMessage(this, message_obj).get());
985 PrintCurrentStackTrace(stderr); 985 PrintCurrentStackTrace(stderr);
986 base::OS::Abort(); 986 base::OS::Abort();
987 } 987 }
988 } 988 }
989 } 989 }
990 990
991 // Set the exception being thrown. 991 // Set the exception being thrown.
992 set_pending_exception(*exception_handle); 992 set_pending_exception(*exception_handle);
993 return heap()->exception(); 993 return heap()->exception();
994 } 994 }
995 995
996 996
997 Object* Isolate::ReThrow(Object* exception) { 997 Object* Isolate::ReThrow(Object* exception) {
998 DCHECK(!has_pending_exception()); 998 DCHECK(!has_pending_exception());
999 999
1000 // Set the exception being re-thrown. 1000 // Set the exception being re-thrown.
1001 set_pending_exception(exception); 1001 set_pending_exception(exception);
1002 return heap()->exception(); 1002 return heap()->exception();
1003 } 1003 }
1004 1004
1005 1005
1006 // TODO(turbofan): Make sure table is sorted and use binary search.
1007 static int LookupInHandlerTable(Code* code, int pc_offset) {
1008 FixedArray* handler_table = code->handler_table();
1009 for (int i = 0; i < handler_table->length(); i += 2) {
1010 int return_offset = Smi::cast(handler_table->get(i))->value();
1011 int handler_offset = Smi::cast(handler_table->get(i + 1))->value();
1012 if (pc_offset == return_offset) return handler_offset;
1013 }
1014 return -1;
1015 }
1016
1017
1018 Object* Isolate::FindHandler() { 1006 Object* Isolate::FindHandler() {
1019 Object* exception = pending_exception(); 1007 Object* exception = pending_exception();
1020 1008
1021 Code* code = nullptr; 1009 Code* code = nullptr;
1022 Context* context = nullptr; 1010 Context* context = nullptr;
1023 intptr_t offset = 0; 1011 intptr_t offset = 0;
1024 Address handler_sp = nullptr; 1012 Address handler_sp = nullptr;
1025 Address handler_fp = nullptr; 1013 Address handler_fp = nullptr;
1026 1014
1027 // Special handling of termination exceptions, uncatchable by JavaScript code, 1015 // Special handling of termination exceptions, uncatchable by JavaScript code,
1028 // we unwind the handlers until the top ENTRY handler is found. 1016 // we unwind the handlers until the top ENTRY handler is found.
1029 bool catchable_by_js = is_catchable_by_javascript(exception); 1017 bool catchable_by_js = is_catchable_by_javascript(exception);
1030 1018
1031 // Compute handler and stack unwinding information by performing a full walk 1019 // Compute handler and stack unwinding information by performing a full walk
1032 // over the stack and dispatching according to the frame type. 1020 // over the stack and dispatching according to the frame type.
1033 for (StackFrameIterator iter(this); !iter.done(); iter.Advance()) { 1021 for (StackFrameIterator iter(this); !iter.done(); iter.Advance()) {
1034 StackFrame* frame = iter.frame(); 1022 StackFrame* frame = iter.frame();
1035 1023
1036 // For JSEntryStub frames we always have a handler. 1024 // For JSEntryStub frames we always have a handler.
1037 if (frame->is_entry() || frame->is_entry_construct()) { 1025 if (frame->is_entry() || frame->is_entry_construct()) {
1038 StackHandler* handler = frame->top_handler(); 1026 StackHandler* handler = frame->top_handler();
1039 DCHECK_EQ(0, handler->index());
1040 1027
1041 // Restore the next handler. 1028 // Restore the next handler.
1042 thread_local_top()->handler_ = handler->next()->address(); 1029 thread_local_top()->handler_ = handler->next()->address();
1043 1030
1044 // Gather information from the handler. 1031 // Gather information from the handler.
1045 code = frame->LookupCode(); 1032 code = frame->LookupCode();
1046 handler_sp = handler->address() + StackHandlerConstants::kSize; 1033 handler_sp = handler->address() + StackHandlerConstants::kSize;
1047 offset = Smi::cast(code->handler_table()->get(0))->value(); 1034 offset = Smi::cast(code->handler_table()->get(0))->value();
1048 break; 1035 break;
1049 } 1036 }
1050 1037
1051 // For JavaScript frames which have a handler, we use the handler.
1052 if (frame->is_java_script() && catchable_by_js && frame->HasHandler()) {
1053 StackHandler* handler = frame->top_handler();
1054
1055 // Restore the next handler.
1056 thread_local_top()->handler_ = handler->next()->address();
1057
1058 // Gather information from the handler.
1059 code = frame->LookupCode();
1060 context = handler->context();
1061 offset = Smi::cast(code->handler_table()->get(handler->index()))->value();
1062 handler_sp = handler->address() + StackHandlerConstants::kSize;
1063 handler_fp = frame->fp();
1064 break;
1065 }
1066
1067 // For optimized frames we perform a lookup in the handler table. 1038 // For optimized frames we perform a lookup in the handler table.
1068 if (frame->is_optimized() && catchable_by_js) { 1039 if (frame->is_optimized() && catchable_by_js) {
1069 Code* frame_code = frame->LookupCode(); 1040 OptimizedFrame* js_frame = static_cast<OptimizedFrame*>(frame);
1070 DCHECK(frame_code->is_optimized_code()); 1041 int stack_slots = 0; // Will contain stack slot count of frame.
1071 int pc_offset = static_cast<int>(frame->pc() - frame_code->entry()); 1042 offset = js_frame->LookupExceptionHandlerInTable(&stack_slots);
1072 int handler_offset = LookupInHandlerTable(frame_code, pc_offset); 1043 if (offset < 0) continue;
1073 if (handler_offset < 0) continue;
1074 1044
1075 // Compute the stack pointer from the frame pointer. This ensures that 1045 // Compute the stack pointer from the frame pointer. This ensures that
1076 // argument slots on the stack are dropped as returning would. 1046 // argument slots on the stack are dropped as returning would.
1077 Address return_sp = frame->fp() - 1047 Address return_sp = frame->fp() -
1078 StandardFrameConstants::kFixedFrameSizeFromFp - 1048 StandardFrameConstants::kFixedFrameSizeFromFp -
1079 frame_code->stack_slots() * kPointerSize; 1049 stack_slots * kPointerSize;
1080 1050
1081 // Gather information from the frame. 1051 // Gather information from the frame.
1082 code = frame_code; 1052 code = frame->LookupCode();
1083 offset = handler_offset;
1084 handler_sp = return_sp; 1053 handler_sp = return_sp;
1085 handler_fp = frame->fp(); 1054 handler_fp = frame->fp();
1086 break; 1055 break;
1056 }
1057
1058 // For JavaScript frames we perform a range lookup in the handler table.
1059 if (frame->is_java_script() && catchable_by_js) {
1060 JavaScriptFrame* js_frame = static_cast<JavaScriptFrame*>(frame);
1061 int stack_slots = 0; // Will contain operand stack depth of handler.
1062 offset = js_frame->LookupExceptionHandlerInTable(&stack_slots);
1063 if (offset < 0) continue;
1064
1065 // Compute the stack pointer from the frame pointer. This ensures that
1066 // operand stack slots are dropped for nested statements. Also restore
1067 // correct context for the handler which is pushed within the try-block.
1068 Address return_sp = frame->fp() -
1069 StandardFrameConstants::kFixedFrameSizeFromFp -
1070 stack_slots * kPointerSize;
1071 STATIC_ASSERT(TryBlockConstant::kElementCount == 1);
1072 context = Context::cast(Memory::Object_at(return_sp - kPointerSize));
1073
1074 // Gather information from the frame.
1075 code = frame->LookupCode();
1076 handler_sp = return_sp;
1077 handler_fp = frame->fp();
1078 break;
1087 } 1079 }
1088 } 1080 }
1089 1081
1090 // Handler must exist. 1082 // Handler must exist.
1091 CHECK(code != nullptr); 1083 CHECK(code != nullptr);
1092 1084
1093 // Store information to be consumed by the CEntryStub. 1085 // Store information to be consumed by the CEntryStub.
1094 thread_local_top()->pending_handler_context_ = context; 1086 thread_local_top()->pending_handler_context_ = context;
1095 thread_local_top()->pending_handler_code_ = code; 1087 thread_local_top()->pending_handler_code_ = code;
1096 thread_local_top()->pending_handler_offset_ = offset; 1088 thread_local_top()->pending_handler_offset_ = offset;
1097 thread_local_top()->pending_handler_fp_ = handler_fp; 1089 thread_local_top()->pending_handler_fp_ = handler_fp;
1098 thread_local_top()->pending_handler_sp_ = handler_sp; 1090 thread_local_top()->pending_handler_sp_ = handler_sp;
1099 1091
1100 // Return and clear pending exception. 1092 // Return and clear pending exception.
1101 clear_pending_exception(); 1093 clear_pending_exception();
1102 return exception; 1094 return exception;
1103 } 1095 }
1104 1096
1105 1097
1106 // TODO(mstarzinger): We shouldn't need the exception object here. 1098 Isolate::CatchType Isolate::PredictExceptionCatcher() {
1107 bool Isolate::PredictWhetherExceptionIsCaught(Object* exception) { 1099 Address external_handler = thread_local_top()->try_catch_handler_address();
1108 if (IsExternalHandlerOnTop(exception)) return true; 1100 Address entry_handler = Isolate::handler(thread_local_top());
1101 if (IsExternalHandlerOnTop(nullptr)) return CAUGHT_BY_EXTERNAL;
1109 1102
1110 // Search for a JavaScript handler by performing a full walk over the stack 1103 // Search for an exception handler by performing a full walk over the stack.
1111 // and dispatching according to the frame type.
1112 for (StackFrameIterator iter(this); !iter.done(); iter.Advance()) { 1104 for (StackFrameIterator iter(this); !iter.done(); iter.Advance()) {
1113 StackFrame* frame = iter.frame(); 1105 StackFrame* frame = iter.frame();
1114 1106
1115 // For JavaScript frames which have a handler, we use the handler. 1107 // For JSEntryStub frames we update the JS_ENTRY handler.
1116 if (frame->is_java_script() && frame->HasHandler()) { 1108 if (frame->is_entry() || frame->is_entry_construct()) {
1117 return true; 1109 entry_handler = frame->top_handler()->next()->address();
1118 } 1110 }
1119 1111
1120 // For optimized frames we perform a lookup in the handler table. 1112 // For JavaScript frames we perform a lookup in the handler table.
1121 if (frame->is_optimized()) { 1113 if (frame->is_java_script()) {
1122 Code* frame_code = frame->LookupCode(); 1114 JavaScriptFrame* js_frame = static_cast<JavaScriptFrame*>(frame);
1123 DCHECK(frame_code->is_optimized_code()); 1115 int stack_slots = 0; // The computed stack slot count is not used.
1124 int pc_offset = static_cast<int>(frame->pc() - frame_code->entry()); 1116 if (js_frame->LookupExceptionHandlerInTable(&stack_slots) > 0) {
1125 int handler_offset = LookupInHandlerTable(frame_code, pc_offset); 1117 return CAUGHT_BY_JAVASCRIPT;
1126 if (handler_offset < 0) continue; 1118 }
1127 return true; 1119 }
1120
1121 // The exception has been externally caught if and only if there is an
1122 // external handler which is on top of the top-most JS_ENTRY handler.
1123 if (external_handler != nullptr && !try_catch_handler()->is_verbose_) {
1124 if (entry_handler == nullptr || entry_handler > external_handler) {
1125 return CAUGHT_BY_EXTERNAL;
1126 }
1128 } 1127 }
1129 } 1128 }
1130 1129
1131 // Handler not found. 1130 // Handler not found.
1132 return false; 1131 return NOT_CAUGHT;
1133 } 1132 }
1134 1133
1135 1134
1136 Object* Isolate::ThrowIllegalOperation() { 1135 Object* Isolate::ThrowIllegalOperation() {
1137 if (FLAG_stack_trace_on_illegal) PrintStack(stdout); 1136 if (FLAG_stack_trace_on_illegal) PrintStack(stdout);
1138 return Throw(heap()->illegal_access_string()); 1137 return Throw(heap()->illegal_access_string());
1139 } 1138 }
1140 1139
1141 1140
1142 void Isolate::ScheduleThrow(Object* exception) { 1141 void Isolate::ScheduleThrow(Object* exception) {
(...skipping 361 matching lines...) Expand 10 before | Expand all | Expand 10 after
1504 return false; 1503 return false;
1505 } 1504 }
1506 1505
1507 // Reschedule the exception. 1506 // Reschedule the exception.
1508 thread_local_top()->scheduled_exception_ = pending_exception(); 1507 thread_local_top()->scheduled_exception_ = pending_exception();
1509 clear_pending_exception(); 1508 clear_pending_exception();
1510 return true; 1509 return true;
1511 } 1510 }
1512 1511
1513 1512
1514 void Isolate::PushPromise(Handle<JSObject> promise) { 1513 void Isolate::PushPromise(Handle<JSObject> promise,
1514 Handle<JSFunction> function) {
1515 ThreadLocalTop* tltop = thread_local_top(); 1515 ThreadLocalTop* tltop = thread_local_top();
1516 PromiseOnStack* prev = tltop->promise_on_stack_; 1516 PromiseOnStack* prev = tltop->promise_on_stack_;
1517 StackHandler* handler = StackHandler::FromAddress(Isolate::handler(tltop)); 1517 Handle<JSObject> global_promise =
1518 Handle<JSObject> global_handle =
1519 Handle<JSObject>::cast(global_handles()->Create(*promise)); 1518 Handle<JSObject>::cast(global_handles()->Create(*promise));
1520 tltop->promise_on_stack_ = new PromiseOnStack(handler, global_handle, prev); 1519 Handle<JSFunction> global_function =
1520 Handle<JSFunction>::cast(global_handles()->Create(*function));
1521 tltop->promise_on_stack_ =
1522 new PromiseOnStack(global_function, global_promise, prev);
1521 } 1523 }
1522 1524
1523 1525
1524 void Isolate::PopPromise() { 1526 void Isolate::PopPromise() {
1525 ThreadLocalTop* tltop = thread_local_top(); 1527 ThreadLocalTop* tltop = thread_local_top();
1526 if (tltop->promise_on_stack_ == NULL) return; 1528 if (tltop->promise_on_stack_ == NULL) return;
1527 PromiseOnStack* prev = tltop->promise_on_stack_->prev(); 1529 PromiseOnStack* prev = tltop->promise_on_stack_->prev();
1528 Handle<Object> global_handle = tltop->promise_on_stack_->promise(); 1530 Handle<Object> global_function = tltop->promise_on_stack_->function();
1531 Handle<Object> global_promise = tltop->promise_on_stack_->promise();
1529 delete tltop->promise_on_stack_; 1532 delete tltop->promise_on_stack_;
1530 tltop->promise_on_stack_ = prev; 1533 tltop->promise_on_stack_ = prev;
1531 global_handles()->Destroy(global_handle.location()); 1534 global_handles()->Destroy(global_function.location());
1535 global_handles()->Destroy(global_promise.location());
1532 } 1536 }
1533 1537
1534 1538
1535 Handle<Object> Isolate::GetPromiseOnStackOnThrow() { 1539 Handle<Object> Isolate::GetPromiseOnStackOnThrow() {
1536 Handle<Object> undefined = factory()->undefined_value(); 1540 Handle<Object> undefined = factory()->undefined_value();
1537 ThreadLocalTop* tltop = thread_local_top(); 1541 ThreadLocalTop* tltop = thread_local_top();
1538 if (tltop->promise_on_stack_ == NULL) return undefined; 1542 if (tltop->promise_on_stack_ == NULL) return undefined;
1539 StackHandler* promise_try = tltop->promise_on_stack_->handler(); 1543 Handle<JSFunction> promise_function = tltop->promise_on_stack_->function();
1540 // Find the top-most try-catch handler. 1544 // Find the top-most try-catch or try-finally handler.
1541 StackHandler* handler = StackHandler::FromAddress(Isolate::handler(tltop)); 1545 if (PredictExceptionCatcher() != CAUGHT_BY_JAVASCRIPT) return undefined;
1542 // Throwing inside a Promise only leads to a reject if not caught by an inner 1546 for (JavaScriptFrameIterator it(this); !it.done(); it.Advance()) {
1543 // try-catch or try-finally. 1547 JavaScriptFrame* frame = it.frame();
1544 if (handler == promise_try) return tltop->promise_on_stack_->promise(); 1548 int stack_slots = 0; // The computed stack slot count is not used.
1549 if (frame->LookupExceptionHandlerInTable(&stack_slots) > 0) {
1550 // Throwing inside a Promise only leads to a reject if not caught by an
1551 // inner try-catch or try-finally.
1552 if (frame->function() == *promise_function) {
1553 return tltop->promise_on_stack_->promise();
1554 }
1555 return undefined;
1556 }
1557 }
1545 return undefined; 1558 return undefined;
1546 } 1559 }
1547 1560
1548 1561
1549 void Isolate::SetCaptureStackTraceForUncaughtExceptions( 1562 void Isolate::SetCaptureStackTraceForUncaughtExceptions(
1550 bool capture, 1563 bool capture,
1551 int frame_limit, 1564 int frame_limit,
1552 StackTrace::StackTraceOptions options) { 1565 StackTrace::StackTraceOptions options) {
1553 capture_stack_trace_for_uncaught_exceptions_ = capture; 1566 capture_stack_trace_for_uncaught_exceptions_ = capture;
1554 stack_trace_for_uncaught_exceptions_frame_limit_ = frame_limit; 1567 stack_trace_for_uncaught_exceptions_frame_limit_ = frame_limit;
(...skipping 1087 matching lines...) Expand 10 before | Expand all | Expand 10 after
2642 if (prev_ && prev_->Intercept(flag)) return true; 2655 if (prev_ && prev_->Intercept(flag)) return true;
2643 // Then check whether this scope intercepts. 2656 // Then check whether this scope intercepts.
2644 if ((flag & intercept_mask_)) { 2657 if ((flag & intercept_mask_)) {
2645 intercepted_flags_ |= flag; 2658 intercepted_flags_ |= flag;
2646 return true; 2659 return true;
2647 } 2660 }
2648 return false; 2661 return false;
2649 } 2662 }
2650 2663
2651 } } // namespace v8::internal 2664 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/isolate.h ('k') | src/objects.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698