Fix an assertion failure in the full code generator.
We hit an assertion failure when we tried to record the AST ID of the (shared) .arguments variable proxy more than once. This was hit when we had multiple calls to the same parameter in a function that used the arguments object. The fix is to not visit the subexpressions of the (shared) property access expression. BUG=1060 Review URL: http://codereview.chromium.org/6368007 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@6404 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
3ff8e4d3fa
commit
70910af7a0
@ -1988,16 +1988,21 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
// Call to a keyed property.
|
||||
// For a synthetic property use keyed load IC followed by function call,
|
||||
// for a regular property use keyed CallIC.
|
||||
{ PreservePositionScope scope(masm()->positions_recorder());
|
||||
VisitForStackValue(prop->obj());
|
||||
}
|
||||
if (prop->is_synthetic()) {
|
||||
{ PreservePositionScope scope(masm()->positions_recorder());
|
||||
VisitForAccumulatorValue(prop->key());
|
||||
}
|
||||
// Do not visit the object and key subexpressions (they are shared
|
||||
// by all occurrences of the same rewritten parameter).
|
||||
ASSERT(prop->obj()->AsVariableProxy() != NULL);
|
||||
ASSERT(prop->obj()->AsVariableProxy()->var()->AsSlot() != NULL);
|
||||
Slot* slot = prop->obj()->AsVariableProxy()->var()->AsSlot();
|
||||
MemOperand operand = EmitSlotSearch(slot, r1);
|
||||
__ ldr(r1, operand);
|
||||
|
||||
ASSERT(prop->key()->AsLiteral() != NULL);
|
||||
ASSERT(prop->key()->AsLiteral()->handle()->IsSmi());
|
||||
__ mov(r0, Operand(prop->key()->AsLiteral()->handle()));
|
||||
|
||||
// Record source code position for IC call.
|
||||
SetSourcePosition(prop->position());
|
||||
__ pop(r1); // We do not need to keep the receiver.
|
||||
|
||||
Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
|
||||
EmitCallIC(ic, RelocInfo::CODE_TARGET);
|
||||
@ -2006,6 +2011,9 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
__ Push(r0, r1); // Function, receiver.
|
||||
EmitCallWithStub(expr);
|
||||
} else {
|
||||
{ PreservePositionScope scope(masm()->positions_recorder());
|
||||
VisitForStackValue(prop->obj());
|
||||
}
|
||||
EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET);
|
||||
}
|
||||
}
|
||||
|
@ -2339,16 +2339,21 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
// Call to a keyed property.
|
||||
// For a synthetic property use keyed load IC followed by function call,
|
||||
// for a regular property use keyed EmitCallIC.
|
||||
{ PreservePositionScope scope(masm()->positions_recorder());
|
||||
VisitForStackValue(prop->obj());
|
||||
}
|
||||
if (prop->is_synthetic()) {
|
||||
{ PreservePositionScope scope(masm()->positions_recorder());
|
||||
VisitForAccumulatorValue(prop->key());
|
||||
}
|
||||
// Do not visit the object and key subexpressions (they are shared
|
||||
// by all occurrences of the same rewritten parameter).
|
||||
ASSERT(prop->obj()->AsVariableProxy() != NULL);
|
||||
ASSERT(prop->obj()->AsVariableProxy()->var()->AsSlot() != NULL);
|
||||
Slot* slot = prop->obj()->AsVariableProxy()->var()->AsSlot();
|
||||
MemOperand operand = EmitSlotSearch(slot, edx);
|
||||
__ mov(edx, operand);
|
||||
|
||||
ASSERT(prop->key()->AsLiteral() != NULL);
|
||||
ASSERT(prop->key()->AsLiteral()->handle()->IsSmi());
|
||||
__ mov(eax, prop->key()->AsLiteral()->handle());
|
||||
|
||||
// Record source code position for IC call.
|
||||
SetSourcePosition(prop->position());
|
||||
__ pop(edx); // We do not need to keep the receiver.
|
||||
|
||||
Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
|
||||
EmitCallIC(ic, RelocInfo::CODE_TARGET);
|
||||
@ -2359,6 +2364,9 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
__ push(FieldOperand(ecx, GlobalObject::kGlobalReceiverOffset));
|
||||
EmitCallWithStub(expr);
|
||||
} else {
|
||||
{ PreservePositionScope scope(masm()->positions_recorder());
|
||||
VisitForStackValue(prop->obj());
|
||||
}
|
||||
EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET);
|
||||
}
|
||||
}
|
||||
|
@ -2006,16 +2006,21 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
// Call to a keyed property.
|
||||
// For a synthetic property use keyed load IC followed by function call,
|
||||
// for a regular property use keyed EmitCallIC.
|
||||
{ PreservePositionScope scope(masm()->positions_recorder());
|
||||
VisitForStackValue(prop->obj());
|
||||
}
|
||||
if (prop->is_synthetic()) {
|
||||
{ PreservePositionScope scope(masm()->positions_recorder());
|
||||
VisitForAccumulatorValue(prop->key());
|
||||
}
|
||||
// Do not visit the object and key subexpressions (they are shared
|
||||
// by all occurrences of the same rewritten parameter).
|
||||
ASSERT(prop->obj()->AsVariableProxy() != NULL);
|
||||
ASSERT(prop->obj()->AsVariableProxy()->var()->AsSlot() != NULL);
|
||||
Slot* slot = prop->obj()->AsVariableProxy()->var()->AsSlot();
|
||||
MemOperand operand = EmitSlotSearch(slot, rdx);
|
||||
__ movq(rdx, operand);
|
||||
|
||||
ASSERT(prop->key()->AsLiteral() != NULL);
|
||||
ASSERT(prop->key()->AsLiteral()->handle()->IsSmi());
|
||||
__ Move(rax, prop->key()->AsLiteral()->handle());
|
||||
|
||||
// Record source code position for IC call.
|
||||
SetSourcePosition(prop->position());
|
||||
__ pop(rdx); // We do not need to keep the receiver.
|
||||
|
||||
Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
|
||||
EmitCallIC(ic, RelocInfo::CODE_TARGET);
|
||||
@ -2026,6 +2031,9 @@ void FullCodeGenerator::VisitCall(Call* expr) {
|
||||
__ push(FieldOperand(rcx, GlobalObject::kGlobalReceiverOffset));
|
||||
EmitCallWithStub(expr);
|
||||
} else {
|
||||
{ PreservePositionScope scope(masm()->positions_recorder());
|
||||
VisitForStackValue(prop->obj());
|
||||
}
|
||||
EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET);
|
||||
}
|
||||
}
|
||||
|
32
test/mjsunit/regress/regress-1060.js
Normal file
32
test/mjsunit/regress/regress-1060.js
Normal file
@ -0,0 +1,32 @@
|
||||
// Copyright 2011 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.
|
||||
|
||||
// Make sure that we do not record multiple bailouts in the unoptimized code
|
||||
// for the (shared) .arguments proxy, even for calls.
|
||||
function f(x) { arguments; return x() + x(); }
|
||||
|
||||
assertEquals("hesthest", f(function () { return "hest"; }));
|
Loading…
Reference in New Issue
Block a user