From: mstarzinger@chromium.org Date: Wed, 25 Apr 2012 13:22:04 +0000 (+0000) Subject: Fix deopted construct stub frame to contain code object. X-Git-Tag: upstream/4.7.83~16800 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=21fc0fef6abbd1fa355bb5067b3aaa7894f6a059;p=platform%2Fupstream%2Fv8.git Fix deopted construct stub frame to contain code object. R=danno@chromium.org BUG=chromium:124594 TEST=mjsunit/regress/regress-124594 Review URL: https://chromiumcodereview.appspot.com/10155024 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@11436 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- diff --git a/src/arm/deoptimizer-arm.cc b/src/arm/deoptimizer-arm.cc index 7b2a3c4..699e6aa 100644 --- a/src/arm/deoptimizer-arm.cc +++ b/src/arm/deoptimizer-arm.cc @@ -457,6 +457,8 @@ void Deoptimizer::DoComputeArgumentsAdaptorFrame(TranslationIterator* iterator, void Deoptimizer::DoComputeConstructStubFrame(TranslationIterator* iterator, int frame_index) { + Builtins* builtins = isolate_->builtins(); + Code* construct_stub = builtins->builtin(Builtins::kJSConstructStubGeneric); JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next())); unsigned height = iterator->Next(); unsigned height_in_bytes = height * kPointerSize; @@ -464,7 +466,7 @@ void Deoptimizer::DoComputeConstructStubFrame(TranslationIterator* iterator, PrintF(" translating construct stub => height=%d\n", height_in_bytes); } - unsigned fixed_frame_size = 7 * kPointerSize; + unsigned fixed_frame_size = 8 * kPointerSize; unsigned output_frame_size = height_in_bytes + fixed_frame_size; // Allocate and store the output frame description. @@ -529,6 +531,15 @@ void Deoptimizer::DoComputeConstructStubFrame(TranslationIterator* iterator, top_address + output_offset, output_offset, value); } + // The output frame reflects a JSConstructStubGeneric frame. + output_offset -= kPointerSize; + value = reinterpret_cast(construct_stub); + output_frame->SetFrameSlot(output_offset, value); + if (FLAG_trace_deopt) { + PrintF(" 0x%08x: [top + %d] <- 0x%08x ; code object\n", + top_address + output_offset, output_offset, value); + } + // Number of incoming arguments. output_offset -= kPointerSize; value = reinterpret_cast(Smi::FromInt(height - 1)); @@ -559,8 +570,6 @@ void Deoptimizer::DoComputeConstructStubFrame(TranslationIterator* iterator, ASSERT(0 == output_offset); - Builtins* builtins = isolate_->builtins(); - Code* construct_stub = builtins->builtin(Builtins::kJSConstructStubGeneric); uint32_t pc = reinterpret_cast( construct_stub->instruction_start() + isolate_->heap()->construct_stub_deopt_pc_offset()->value()); diff --git a/src/ia32/deoptimizer-ia32.cc b/src/ia32/deoptimizer-ia32.cc index 3f10c09..73961e1 100644 --- a/src/ia32/deoptimizer-ia32.cc +++ b/src/ia32/deoptimizer-ia32.cc @@ -548,6 +548,8 @@ void Deoptimizer::DoComputeArgumentsAdaptorFrame(TranslationIterator* iterator, void Deoptimizer::DoComputeConstructStubFrame(TranslationIterator* iterator, int frame_index) { + Builtins* builtins = isolate_->builtins(); + Code* construct_stub = builtins->builtin(Builtins::kJSConstructStubGeneric); JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next())); unsigned height = iterator->Next(); unsigned height_in_bytes = height * kPointerSize; @@ -555,7 +557,7 @@ void Deoptimizer::DoComputeConstructStubFrame(TranslationIterator* iterator, PrintF(" translating construct stub => height=%d\n", height_in_bytes); } - unsigned fixed_frame_size = 6 * kPointerSize; + unsigned fixed_frame_size = 7 * kPointerSize; unsigned output_frame_size = height_in_bytes + fixed_frame_size; // Allocate and store the output frame description. @@ -620,6 +622,15 @@ void Deoptimizer::DoComputeConstructStubFrame(TranslationIterator* iterator, top_address + output_offset, output_offset, value); } + // The output frame reflects a JSConstructStubGeneric frame. + output_offset -= kPointerSize; + value = reinterpret_cast(construct_stub); + output_frame->SetFrameSlot(output_offset, value); + if (FLAG_trace_deopt) { + PrintF(" 0x%08x: [top + %d] <- 0x%08x ; code object\n", + top_address + output_offset, output_offset, value); + } + // Number of incoming arguments. output_offset -= kPointerSize; value = reinterpret_cast(Smi::FromInt(height - 1)); @@ -641,8 +652,6 @@ void Deoptimizer::DoComputeConstructStubFrame(TranslationIterator* iterator, ASSERT(0 == output_offset); - Builtins* builtins = isolate_->builtins(); - Code* construct_stub = builtins->builtin(Builtins::kJSConstructStubGeneric); uint32_t pc = reinterpret_cast( construct_stub->instruction_start() + isolate_->heap()->construct_stub_deopt_pc_offset()->value()); diff --git a/src/mips/deoptimizer-mips.cc b/src/mips/deoptimizer-mips.cc index 51c2e46..62f3155 100644 --- a/src/mips/deoptimizer-mips.cc +++ b/src/mips/deoptimizer-mips.cc @@ -447,6 +447,8 @@ void Deoptimizer::DoComputeArgumentsAdaptorFrame(TranslationIterator* iterator, void Deoptimizer::DoComputeConstructStubFrame(TranslationIterator* iterator, int frame_index) { + Builtins* builtins = isolate_->builtins(); + Code* construct_stub = builtins->builtin(Builtins::kJSConstructStubGeneric); JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next())); unsigned height = iterator->Next(); unsigned height_in_bytes = height * kPointerSize; @@ -454,7 +456,7 @@ void Deoptimizer::DoComputeConstructStubFrame(TranslationIterator* iterator, PrintF(" translating construct stub => height=%d\n", height_in_bytes); } - unsigned fixed_frame_size = 7 * kPointerSize; + unsigned fixed_frame_size = 8 * kPointerSize; unsigned output_frame_size = height_in_bytes + fixed_frame_size; // Allocate and store the output frame description. @@ -519,6 +521,15 @@ void Deoptimizer::DoComputeConstructStubFrame(TranslationIterator* iterator, top_address + output_offset, output_offset, value); } + // The output frame reflects a JSConstructStubGeneric frame. + output_offset -= kPointerSize; + value = reinterpret_cast(construct_stub); + output_frame->SetFrameSlot(output_offset, value); + if (FLAG_trace_deopt) { + PrintF(" 0x%08x: [top + %d] <- 0x%08x ; code object\n", + top_address + output_offset, output_offset, value); + } + // Number of incoming arguments. output_offset -= kPointerSize; value = reinterpret_cast(Smi::FromInt(height - 1)); @@ -549,8 +560,6 @@ void Deoptimizer::DoComputeConstructStubFrame(TranslationIterator* iterator, ASSERT(0 == output_offset); - Builtins* builtins = isolate_->builtins(); - Code* construct_stub = builtins->builtin(Builtins::kJSConstructStubGeneric); uint32_t pc = reinterpret_cast( construct_stub->instruction_start() + isolate_->heap()->construct_stub_deopt_pc_offset()->value()); diff --git a/src/x64/deoptimizer-x64.cc b/src/x64/deoptimizer-x64.cc index 40b9a1c..f3046b9 100644 --- a/src/x64/deoptimizer-x64.cc +++ b/src/x64/deoptimizer-x64.cc @@ -458,6 +458,8 @@ void Deoptimizer::DoComputeArgumentsAdaptorFrame(TranslationIterator* iterator, void Deoptimizer::DoComputeConstructStubFrame(TranslationIterator* iterator, int frame_index) { + Builtins* builtins = isolate_->builtins(); + Code* construct_stub = builtins->builtin(Builtins::kJSConstructStubGeneric); JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next())); unsigned height = iterator->Next(); unsigned height_in_bytes = height * kPointerSize; @@ -465,7 +467,7 @@ void Deoptimizer::DoComputeConstructStubFrame(TranslationIterator* iterator, PrintF(" translating construct stub => height=%d\n", height_in_bytes); } - unsigned fixed_frame_size = 6 * kPointerSize; + unsigned fixed_frame_size = 7 * kPointerSize; unsigned output_frame_size = height_in_bytes + fixed_frame_size; // Allocate and store the output frame description. @@ -534,6 +536,16 @@ void Deoptimizer::DoComputeConstructStubFrame(TranslationIterator* iterator, top_address + output_offset, output_offset, value); } + // The output frame reflects a JSConstructStubGeneric frame. + output_offset -= kPointerSize; + value = reinterpret_cast(construct_stub); + output_frame->SetFrameSlot(output_offset, value); + if (FLAG_trace_deopt) { + PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" + V8PRIxPTR " ; code object\n", + top_address + output_offset, output_offset, value); + } + // Number of incoming arguments. output_offset -= kPointerSize; value = reinterpret_cast(Smi::FromInt(height - 1)); @@ -557,8 +569,6 @@ void Deoptimizer::DoComputeConstructStubFrame(TranslationIterator* iterator, ASSERT(0 == output_offset); - Builtins* builtins = isolate_->builtins(); - Code* construct_stub = builtins->builtin(Builtins::kJSConstructStubGeneric); intptr_t pc = reinterpret_cast( construct_stub->instruction_start() + isolate_->heap()->construct_stub_deopt_pc_offset()->value()); diff --git a/test/mjsunit/regress/regress-124594.js b/test/mjsunit/regress/regress-124594.js new file mode 100644 index 0000000..d51e1f6 --- /dev/null +++ b/test/mjsunit/regress/regress-124594.js @@ -0,0 +1,50 @@ +// Copyright 2012 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Flags: --allow-natives-syntax --expose-gc + +// Test that a GC inside a constructor frame is correctly handled right +// after we deoptimize from an inlined constructor to a constructor stub +// stack frame. + +function f(deopt) { + var x = 1; + if (deopt) { + x = x + "foo"; + gc(); + } + this.x = x; +} + +function g(deopt) { + return new f(deopt); +} + +assertEquals({x:1}, g(false)); +assertEquals({x:1}, g(false)); +%OptimizeFunctionOnNextCall(g); +assertEquals({x:"1foo"}, g(true));