[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:
parent
7a1deffbd1
commit
667d8ad099
@ -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)); }
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
18
test/mjsunit/regress/regress-crbug-633585.js
Normal file
18
test/mjsunit/regress/regress-crbug-633585.js
Normal 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();
|
Loading…
Reference in New Issue
Block a user