From ee173152efcf24299306ccbaddaf3c3f72876d43 Mon Sep 17 00:00:00 2001 From: "jarin@chromium.org" Date: Fri, 28 Mar 2014 13:26:20 +0000 Subject: [PATCH] Raise StackOverflow during bootstrapping See https://github.com/joyent/node/issues/7120 R=jarin@chromium.org BUG= Review URL: https://codereview.chromium.org/178073002 Patch from Alexis Campailla . git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@20335 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/bootstrapper.cc | 15 ++++++---- src/isolate.h | 5 ++++ test/cctest/test-api.cc | 61 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+), 6 deletions(-) diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc index 6496e2629c..ce625b7495 100644 --- a/src/bootstrapper.cc +++ b/src/bootstrapper.cc @@ -1476,11 +1476,6 @@ bool Genesis::CompileNative(Isolate* isolate, #ifdef ENABLE_DEBUGGER_SUPPORT isolate->debugger()->set_compiling_natives(true); #endif - // During genesis, the boilerplate for stack overflow won't work until the - // environment has been at least partially initialized. Add a stack check - // before entering JS code to catch overflow early. - StackLimitCheck check(isolate); - if (check.HasOverflowed()) return false; bool result = CompileScriptCached(isolate, name, @@ -2614,8 +2609,16 @@ Genesis::Genesis(Isolate* isolate, // During genesis, the boilerplate for stack overflow won't work until the // environment has been at least partially initialized. Add a stack check // before entering JS code to catch overflow early. + const uint32_t stack_to_get_through_genesis = 3500 * sizeof(intptr_t); StackLimitCheck check(isolate); - if (check.HasOverflowed()) return; + if (check.WillOverflow(stack_to_get_through_genesis)) { + // Only raise a StackOverflow if there is a valid current context + if (isolate->context() != NULL) { + isolate->StackOverflow(); + isolate->OptionalRescheduleException(true); + } + return; + } // We can only de-serialize a context if the isolate was initialized from // a snapshot. Otherwise we have to build the context from scratch. diff --git a/src/isolate.h b/src/isolate.h index b4713786ab..bcb7cd40f5 100644 --- a/src/isolate.h +++ b/src/isolate.h @@ -1438,6 +1438,11 @@ class StackLimitCheck BASE_EMBEDDED { StackGuard* stack_guard = isolate_->stack_guard(); return (reinterpret_cast(this) < stack_guard->real_climit()); } + bool WillOverflow(uint32_t additionalUsage) const { + StackGuard* stack_guard = isolate_->stack_guard(); + return (reinterpret_cast(this) < stack_guard->real_climit() + + additionalUsage); + } private: Isolate* isolate_; }; diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc index 276663a111..ed0a2fbc4a 100644 --- a/test/cctest/test-api.cc +++ b/test/cctest/test-api.cc @@ -5023,6 +5023,67 @@ TEST(APIStackOverflowAndVerboseTryCatch) { v8::V8::RemoveMessageListeners(receive_message); } +void APIStackOverflowNestedContextsHelper(bool is_bottom_call); + +void APIStackOverflowNestedContextsCallback( + const v8::FunctionCallbackInfo& args) { + APIStackOverflowNestedContextsHelper(false); +} + + +void APIStackOverflowNestedContextsHelper(bool is_bottom_call) { + v8::Isolate* isolate = CcTest::isolate(); + TryCatch try_catch; + + Local global = ObjectTemplate::New(); + global->Set(String::NewFromUtf8(isolate, "recur"), + FunctionTemplate::New(isolate, APIStackOverflowNestedContextsCallback)); + + Local innerContext = Context::New(isolate, NULL, global); + if (try_catch.HasCaught()) { + try_catch.ReThrow(); + return; + } + if (innerContext.IsEmpty()) return; + + Context::Scope context_scope(innerContext); + Local