[turbofan] Fix missing bailout for accessors in literals.

This adds the missing lazy bailout point when defining accessor pairs
within object literals via Runtime::kDefineAccessorPropertyUnchecked.
The runtime function in question can indeed trigger a lazy deopt due
to a DependentCode::kPrototypeCheckGroup dependency.

R=bmeurer@chromium.org
TEST=mjsunit/regress/regress-crbug-633585
BUG=chromium:633585

Review-Url: https://codereview.chromium.org/2207413002
Cr-Commit-Position: refs/heads/master@{#38336}
This commit is contained in:
mstarzinger 2016-08-04 03:25:03 -07:00 committed by Commit bot
parent 7a1deffbd1
commit 667d8ad099
12 changed files with 98 additions and 31 deletions

View File

@ -1451,9 +1451,10 @@ class ObjectLiteral final : public MaterializedLiteral {
};
struct Accessors: public ZoneObject {
Accessors() : getter(NULL), setter(NULL) {}
Accessors() : getter(NULL), setter(NULL), bailout_id(BailoutId::None()) {}
ObjectLiteralProperty* getter;
ObjectLiteralProperty* setter;
BailoutId bailout_id;
};
BailoutId CreateLiteralId() const { return BailoutId(local_id(0)); }

View File

@ -1809,12 +1809,16 @@ void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
}
case ObjectLiteral::Property::GETTER:
if (property->emit_store()) {
accessor_table.lookup(key)->second->getter = property;
AccessorTable::Iterator it = accessor_table.lookup(key);
it->second->bailout_id = expr->GetIdForPropertySet(property_index);
it->second->getter = property;
}
break;
case ObjectLiteral::Property::SETTER:
if (property->emit_store()) {
accessor_table.lookup(key)->second->setter = property;
AccessorTable::Iterator it = accessor_table.lookup(key);
it->second->bailout_id = expr->GetIdForPropertySet(property_index);
it->second->setter = property;
}
break;
}
@ -1835,8 +1839,7 @@ void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
const Operator* op =
javascript()->CallRuntime(Runtime::kDefineAccessorPropertyUnchecked);
Node* call = NewNode(op, literal, name, getter, setter, attr);
// This should not lazy deopt on a new literal.
PrepareFrameState(call, BailoutId::None());
PrepareFrameState(call, it->second->bailout_id);
}
// Object literals have two parts. The "static" part on the left contains no

View File

@ -1470,12 +1470,16 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
case ObjectLiteral::Property::GETTER:
if (property->emit_store()) {
accessor_table.lookup(key)->second->getter = property;
AccessorTable::Iterator it = accessor_table.lookup(key);
it->second->bailout_id = expr->GetIdForPropertySet(property_index);
it->second->getter = property;
}
break;
case ObjectLiteral::Property::SETTER:
if (property->emit_store()) {
accessor_table.lookup(key)->second->setter = property;
AccessorTable::Iterator it = accessor_table.lookup(key);
it->second->bailout_id = expr->GetIdForPropertySet(property_index);
it->second->setter = property;
}
break;
}
@ -1494,6 +1498,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
__ mov(r0, Operand(Smi::FromInt(NONE)));
PushOperand(r0);
CallRuntimeWithOperands(Runtime::kDefineAccessorPropertyUnchecked);
PrepareForBailoutForId(it->second->bailout_id, BailoutState::NO_REGISTERS);
}
// Object literals have two parts. The "static" part on the left contains no

View File

@ -1454,12 +1454,16 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
break;
case ObjectLiteral::Property::GETTER:
if (property->emit_store()) {
accessor_table.lookup(key)->second->getter = property;
AccessorTable::Iterator it = accessor_table.lookup(key);
it->second->bailout_id = expr->GetIdForPropertySet(property_index);
it->second->getter = property;
}
break;
case ObjectLiteral::Property::SETTER:
if (property->emit_store()) {
accessor_table.lookup(key)->second->setter = property;
AccessorTable::Iterator it = accessor_table.lookup(key);
it->second->bailout_id = expr->GetIdForPropertySet(property_index);
it->second->setter = property;
}
break;
}
@ -1470,14 +1474,15 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
for (AccessorTable::Iterator it = accessor_table.begin();
it != accessor_table.end();
++it) {
__ Peek(x10, 0); // Duplicate receiver.
PushOperand(x10);
VisitForStackValue(it->first);
EmitAccessor(it->second->getter);
EmitAccessor(it->second->setter);
__ Mov(x10, Smi::FromInt(NONE));
PushOperand(x10);
CallRuntimeWithOperands(Runtime::kDefineAccessorPropertyUnchecked);
__ Peek(x10, 0); // Duplicate receiver.
PushOperand(x10);
VisitForStackValue(it->first);
EmitAccessor(it->second->getter);
EmitAccessor(it->second->setter);
__ Mov(x10, Smi::FromInt(NONE));
PushOperand(x10);
CallRuntimeWithOperands(Runtime::kDefineAccessorPropertyUnchecked);
PrepareForBailoutForId(it->second->bailout_id, BailoutState::NO_REGISTERS);
}
// Object literals have two parts. The "static" part on the left contains no

View File

@ -1391,12 +1391,16 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
break;
case ObjectLiteral::Property::GETTER:
if (property->emit_store()) {
accessor_table.lookup(key)->second->getter = property;
AccessorTable::Iterator it = accessor_table.lookup(key);
it->second->bailout_id = expr->GetIdForPropertySet(property_index);
it->second->getter = property;
}
break;
case ObjectLiteral::Property::SETTER:
if (property->emit_store()) {
accessor_table.lookup(key)->second->setter = property;
AccessorTable::Iterator it = accessor_table.lookup(key);
it->second->bailout_id = expr->GetIdForPropertySet(property_index);
it->second->setter = property;
}
break;
}
@ -1415,6 +1419,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
PushOperand(Smi::FromInt(NONE));
CallRuntimeWithOperands(Runtime::kDefineAccessorPropertyUnchecked);
PrepareForBailoutForId(it->second->bailout_id, BailoutState::NO_REGISTERS);
}
// Object literals have two parts. The "static" part on the left contains no

View File

@ -1465,12 +1465,16 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
break;
case ObjectLiteral::Property::GETTER:
if (property->emit_store()) {
accessor_table.lookup(key)->second->getter = property;
AccessorTable::Iterator it = accessor_table.lookup(key);
it->second->bailout_id = expr->GetIdForPropertySet(property_index);
it->second->getter = property;
}
break;
case ObjectLiteral::Property::SETTER:
if (property->emit_store()) {
accessor_table.lookup(key)->second->setter = property;
AccessorTable::Iterator it = accessor_table.lookup(key);
it->second->bailout_id = expr->GetIdForPropertySet(property_index);
it->second->setter = property;
}
break;
}
@ -1489,6 +1493,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
__ li(a0, Operand(Smi::FromInt(NONE)));
PushOperand(a0);
CallRuntimeWithOperands(Runtime::kDefineAccessorPropertyUnchecked);
PrepareForBailoutForId(it->second->bailout_id, BailoutState::NO_REGISTERS);
}
// Object literals have two parts. The "static" part on the left contains no

View File

@ -1466,12 +1466,16 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
break;
case ObjectLiteral::Property::GETTER:
if (property->emit_store()) {
accessor_table.lookup(key)->second->getter = property;
AccessorTable::Iterator it = accessor_table.lookup(key);
it->second->bailout_id = expr->GetIdForPropertySet(property_index);
it->second->getter = property;
}
break;
case ObjectLiteral::Property::SETTER:
if (property->emit_store()) {
accessor_table.lookup(key)->second->setter = property;
AccessorTable::Iterator it = accessor_table.lookup(key);
it->second->bailout_id = expr->GetIdForPropertySet(property_index);
it->second->setter = property;
}
break;
}
@ -1490,6 +1494,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
__ li(a0, Operand(Smi::FromInt(NONE)));
PushOperand(a0);
CallRuntimeWithOperands(Runtime::kDefineAccessorPropertyUnchecked);
PrepareForBailoutForId(it->second->bailout_id, BailoutState::NO_REGISTERS);
}
// Object literals have two parts. The "static" part on the left contains no

View File

@ -1433,12 +1433,16 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
break;
case ObjectLiteral::Property::GETTER:
if (property->emit_store()) {
accessor_table.lookup(key)->second->getter = property;
AccessorTable::Iterator it = accessor_table.lookup(key);
it->second->bailout_id = expr->GetIdForPropertySet(property_index);
it->second->getter = property;
}
break;
case ObjectLiteral::Property::SETTER:
if (property->emit_store()) {
accessor_table.lookup(key)->second->setter = property;
AccessorTable::Iterator it = accessor_table.lookup(key);
it->second->bailout_id = expr->GetIdForPropertySet(property_index);
it->second->setter = property;
}
break;
}
@ -1456,6 +1460,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
__ LoadSmiLiteral(r3, Smi::FromInt(NONE));
PushOperand(r3);
CallRuntimeWithOperands(Runtime::kDefineAccessorPropertyUnchecked);
PrepareForBailoutForId(it->second->bailout_id, BailoutState::NO_REGISTERS);
}
// Object literals have two parts. The "static" part on the left contains no

View File

@ -1393,12 +1393,16 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
break;
case ObjectLiteral::Property::GETTER:
if (property->emit_store()) {
accessor_table.lookup(key)->second->getter = property;
AccessorTable::Iterator it = accessor_table.lookup(key);
it->second->bailout_id = expr->GetIdForPropertySet(property_index);
it->second->getter = property;
}
break;
case ObjectLiteral::Property::SETTER:
if (property->emit_store()) {
accessor_table.lookup(key)->second->setter = property;
AccessorTable::Iterator it = accessor_table.lookup(key);
it->second->bailout_id = expr->GetIdForPropertySet(property_index);
it->second->setter = property;
}
break;
}
@ -1416,6 +1420,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
__ LoadSmiLiteral(r2, Smi::FromInt(NONE));
PushOperand(r2);
CallRuntimeWithOperands(Runtime::kDefineAccessorPropertyUnchecked);
PrepareForBailoutForId(it->second->bailout_id, BailoutState::NO_REGISTERS);
}
// Object literals have two parts. The "static" part on the left contains no

View File

@ -1418,12 +1418,16 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
break;
case ObjectLiteral::Property::GETTER:
if (property->emit_store()) {
accessor_table.lookup(key)->second->getter = property;
AccessorTable::Iterator it = accessor_table.lookup(key);
it->second->bailout_id = expr->GetIdForPropertySet(property_index);
it->second->getter = property;
}
break;
case ObjectLiteral::Property::SETTER:
if (property->emit_store()) {
accessor_table.lookup(key)->second->setter = property;
AccessorTable::Iterator it = accessor_table.lookup(key);
it->second->bailout_id = expr->GetIdForPropertySet(property_index);
it->second->setter = property;
}
break;
}
@ -1440,6 +1444,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
EmitAccessor(it->second->setter);
PushOperand(Smi::FromInt(NONE));
CallRuntimeWithOperands(Runtime::kDefineAccessorPropertyUnchecked);
PrepareForBailoutForId(it->second->bailout_id, BailoutState::NO_REGISTERS);
}
// Object literals have two parts. The "static" part on the left contains no

View File

@ -1383,12 +1383,16 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
break;
case ObjectLiteral::Property::GETTER:
if (property->emit_store()) {
accessor_table.lookup(key)->second->getter = property;
AccessorTable::Iterator it = accessor_table.lookup(key);
it->second->bailout_id = expr->GetIdForPropertySet(property_index);
it->second->getter = property;
}
break;
case ObjectLiteral::Property::SETTER:
if (property->emit_store()) {
accessor_table.lookup(key)->second->setter = property;
AccessorTable::Iterator it = accessor_table.lookup(key);
it->second->bailout_id = expr->GetIdForPropertySet(property_index);
it->second->setter = property;
}
break;
}
@ -1407,6 +1411,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
PushOperand(Smi::FromInt(NONE));
CallRuntimeWithOperands(Runtime::kDefineAccessorPropertyUnchecked);
PrepareForBailoutForId(it->second->bailout_id, BailoutState::NO_REGISTERS);
}
// Object literals have two parts. The "static" part on the left contains no

View File

@ -0,0 +1,18 @@
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --expose-gc --turbo --always-opt
function f() { this.x = this.x.x; }
gc();
f.prototype.x = { x:1 }
new f();
new f();
function g() {
function h() {};
h.prototype = { set x(value) { } };
new f();
}
g();