From 8847b52097a99a5116923e1c8bbf2c84d4ea20d9 Mon Sep 17 00:00:00 2001 From: "yangguo@chromium.org" Date: Thu, 27 Mar 2014 10:41:45 +0000 Subject: [PATCH] Reland "Correctly OOM in the CEntryStub after retries." R=svenpanne@chromium.org Review URL: https://codereview.chromium.org/214473003 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@20297 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/arm/code-stubs-arm.cc | 6 ++++++ src/arm64/code-stubs-arm64.cc | 8 +++++--- src/assembler.cc | 6 ++++++ src/assembler.h | 1 + src/ia32/code-stubs-ia32.cc | 6 ++++++ src/mips/code-stubs-mips.cc | 6 ++++++ src/runtime.cc | 5 +++++ src/runtime.h | 1 + src/serialize.cc | 5 +++++ src/x64/code-stubs-x64.cc | 6 ++++++ test/cctest/test-heap.cc | 25 ++++++++++++++++++++++++- 11 files changed, 71 insertions(+), 4 deletions(-) diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc index fe2095a..832296b 100644 --- a/src/arm/code-stubs-arm.cc +++ b/src/arm/code-stubs-arm.cc @@ -1685,6 +1685,12 @@ void CEntryStub::Generate(MacroAssembler* masm) { true, true); + { FrameScope scope(masm, StackFrame::MANUAL); + __ PrepareCallCFunction(0, r0); + __ CallCFunction( + ExternalReference::out_of_memory_function(masm->isolate()), 0, 0); + } + __ bind(&throw_termination_exception); __ ThrowUncatchable(r0); diff --git a/src/arm64/code-stubs-arm64.cc b/src/arm64/code-stubs-arm64.cc index b6411d9..b097fc5 100644 --- a/src/arm64/code-stubs-arm64.cc +++ b/src/arm64/code-stubs-arm64.cc @@ -1755,13 +1755,15 @@ void CEntryStub::Generate(MacroAssembler* masm) { true, true); + { FrameScope scope(masm, StackFrame::MANUAL); + __ CallCFunction( + ExternalReference::out_of_memory_function(masm->isolate()), 0); + } + // We didn't execute a return case, so the stack frame hasn't been updated // (except for the return address slot). However, we don't need to initialize // jssp because the throw method will immediately overwrite it when it // unwinds the stack. - if (__ emit_debug_code()) { - __ Mov(jssp, kDebugZapValue); - } __ SetStackPointer(jssp); // Throw exceptions. diff --git a/src/assembler.cc b/src/assembler.cc index e53ca7c..772b6d6 100644 --- a/src/assembler.cc +++ b/src/assembler.cc @@ -1059,6 +1059,12 @@ ExternalReference ExternalReference::perform_gc_function(Isolate* isolate) { } +ExternalReference ExternalReference::out_of_memory_function(Isolate* isolate) { + return + ExternalReference(Redirect(isolate, FUNCTION_ADDR(Runtime::OutOfMemory))); +} + + ExternalReference ExternalReference::delete_handle_scope_extensions( Isolate* isolate) { return ExternalReference(Redirect( diff --git a/src/assembler.h b/src/assembler.h index b0eff94..0349b06 100644 --- a/src/assembler.h +++ b/src/assembler.h @@ -748,6 +748,7 @@ class ExternalReference BASE_EMBEDDED { Isolate* isolate); static ExternalReference flush_icache_function(Isolate* isolate); static ExternalReference perform_gc_function(Isolate* isolate); + static ExternalReference out_of_memory_function(Isolate* isolate); static ExternalReference delete_handle_scope_extensions(Isolate* isolate); static ExternalReference get_date_field_function(Isolate* isolate); diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc index 44f2472..ab29167 100644 --- a/src/ia32/code-stubs-ia32.cc +++ b/src/ia32/code-stubs-ia32.cc @@ -2751,6 +2751,12 @@ void CEntryStub::Generate(MacroAssembler* masm) { true, true); + { FrameScope scope(masm, StackFrame::MANUAL); + __ PrepareCallCFunction(0, eax); + __ CallCFunction( + ExternalReference::out_of_memory_function(masm->isolate()), 0); + } + __ bind(&throw_termination_exception); __ ThrowUncatchable(eax); diff --git a/src/mips/code-stubs-mips.cc b/src/mips/code-stubs-mips.cc index c119c8e..332ed4b 100644 --- a/src/mips/code-stubs-mips.cc +++ b/src/mips/code-stubs-mips.cc @@ -1794,6 +1794,12 @@ void CEntryStub::Generate(MacroAssembler* masm) { true, true); + { FrameScope scope(masm, StackFrame::MANUAL); + __ PrepareCallCFunction(0, v0); + __ CallCFunction( + ExternalReference::out_of_memory_function(masm->isolate()), 0); + } + __ bind(&throw_termination_exception); __ ThrowUncatchable(v0); diff --git a/src/runtime.cc b/src/runtime.cc index 41c91c5..8f4c4ca 100644 --- a/src/runtime.cc +++ b/src/runtime.cc @@ -15175,4 +15175,9 @@ void Runtime::PerformGC(Object* result, Isolate* isolate) { } +void Runtime::OutOfMemory() { + Heap::FatalProcessOutOfMemory("CALL_AND_RETRY_LAST", true); + UNREACHABLE(); +} + } } // namespace v8::internal diff --git a/src/runtime.h b/src/runtime.h index 407bf6f..58cd525 100644 --- a/src/runtime.h +++ b/src/runtime.h @@ -895,6 +895,7 @@ class Runtime : public AllStatic { // Helper functions used stubs. static void PerformGC(Object* result, Isolate* isolate); + static void OutOfMemory(); // Used in runtime.cc and hydrogen's VisitArrayLiteral. static Handle CreateArrayLiteralBoilerplate( diff --git a/src/serialize.cc b/src/serialize.cc index 45bc8f2..4048886 100644 --- a/src/serialize.cc +++ b/src/serialize.cc @@ -313,6 +313,11 @@ void ExternalReferenceTable::PopulateTable(Isolate* isolate) { RUNTIME_ENTRY, 1, "Runtime::PerformGC"); + // Runtime entries + Add(ExternalReference::out_of_memory_function(isolate).address(), + RUNTIME_ENTRY, + 2, + "Runtime::OutOfMemory"); Add(ExternalReference::delete_handle_scope_extensions(isolate).address(), RUNTIME_ENTRY, 4, diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc index cfb7f75..c949a42 100644 --- a/src/x64/code-stubs-x64.cc +++ b/src/x64/code-stubs-x64.cc @@ -2603,6 +2603,12 @@ void CEntryStub::Generate(MacroAssembler* masm) { true, true); + { FrameScope scope(masm, StackFrame::MANUAL); + __ PrepareCallCFunction(0); + __ CallCFunction( + ExternalReference::out_of_memory_function(masm->isolate()), 0); + } + __ bind(&throw_termination_exception); __ ThrowUncatchable(rax); diff --git a/test/cctest/test-heap.cc b/test/cctest/test-heap.cc index 55bb466..c1f20f1f 100644 --- a/test/cctest/test-heap.cc +++ b/test/cctest/test-heap.cc @@ -3889,4 +3889,27 @@ TEST(AddInstructionChangesNewSpacePromotion) { g->Call(global, 1, args1); heap->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); } -#endif + + +void OnFatalErrorExpectOOM(const char* location, const char* message) { + // Exit with 0 if the location matches our expectation. + exit(strcmp(location, "CALL_AND_RETRY_LAST")); +} + + +TEST(CEntryStubOOM) { + i::FLAG_allow_natives_syntax = true; + CcTest::InitializeVM(); + v8::HandleScope scope(CcTest::isolate()); + v8::V8::SetFatalErrorHandler(OnFatalErrorExpectOOM); + + v8::Handle result = CompileRun( + "%SetFlags('--gc-interval=1');" + "var a = [];" + "a.__proto__ = [];" + "a.unshift(1)"); + + CHECK(result->IsNumber()); +} + +#endif // DEBUG -- 2.7.4