X87: Vector ICs: The Oracle needs to report feedback for the object literals and the count operation.
port 752b0308df
(r30686).
original commit message:
The refactoring is because it's awkward and error-prone to deterimine which IC slot an
ObjectLiteralProperty uses for feedback. The fix is for each one to know it's own slot. In the
numbering pass, we allocate slots for the ObjectLiteral, then hand out those slots into the
properties.
It adds one word to the ObjectLiteralProperty expression - I'm investigating if thats a
problem.
This changes makes compiling the object literal cleaner across the three compilers. Also, the
slot allocation logic in ObjectLiteral::ComputeFeedbackRequirements() was refactoring to mimic
the style in full-codegen. This is useful since it must remain in sync with
FullCodegen::VisitObjectLiteral().
BUG=
Review URL: https://codereview.chromium.org/1341223002
Cr-Commit-Position: refs/heads/master@{#30739}
This commit is contained in:
parent
9e47ec6eda
commit
1b8610088c
@ -1173,18 +1173,27 @@ void FullCodeGenerator::EmitNewClosure(Handle<SharedFunctionInfo> info,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitSetHomeObjectIfNeeded(Expression* initializer,
|
void FullCodeGenerator::EmitSetHomeObject(Expression* initializer, int offset,
|
||||||
int offset,
|
FeedbackVectorICSlot slot) {
|
||||||
FeedbackVectorICSlot slot) {
|
DCHECK(NeedsHomeObject(initializer));
|
||||||
if (NeedsHomeObject(initializer)) {
|
__ mov(StoreDescriptor::ReceiverRegister(), Operand(esp, 0));
|
||||||
__ mov(StoreDescriptor::ReceiverRegister(), Operand(esp, 0));
|
__ mov(StoreDescriptor::NameRegister(),
|
||||||
__ mov(StoreDescriptor::NameRegister(),
|
Immediate(isolate()->factory()->home_object_symbol()));
|
||||||
Immediate(isolate()->factory()->home_object_symbol()));
|
__ mov(StoreDescriptor::ValueRegister(), Operand(esp, offset * kPointerSize));
|
||||||
__ mov(StoreDescriptor::ValueRegister(),
|
if (FLAG_vector_stores) EmitLoadStoreICSlot(slot);
|
||||||
Operand(esp, offset * kPointerSize));
|
CallStoreIC();
|
||||||
if (FLAG_vector_stores) EmitLoadStoreICSlot(slot);
|
}
|
||||||
CallStoreIC();
|
|
||||||
}
|
|
||||||
|
void FullCodeGenerator::EmitSetHomeObjectAccumulator(
|
||||||
|
Expression* initializer, int offset, FeedbackVectorICSlot slot) {
|
||||||
|
DCHECK(NeedsHomeObject(initializer));
|
||||||
|
__ mov(StoreDescriptor::ReceiverRegister(), eax);
|
||||||
|
__ mov(StoreDescriptor::NameRegister(),
|
||||||
|
Immediate(isolate()->factory()->home_object_symbol()));
|
||||||
|
__ mov(StoreDescriptor::ValueRegister(), Operand(esp, offset * kPointerSize));
|
||||||
|
if (FLAG_vector_stores) EmitLoadStoreICSlot(slot);
|
||||||
|
CallStoreIC();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1355,6 +1364,7 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy,
|
|||||||
DCHECK_EQ(NOT_INSIDE_TYPEOF, typeof_mode);
|
DCHECK_EQ(NOT_INSIDE_TYPEOF, typeof_mode);
|
||||||
Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable"
|
Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable"
|
||||||
: "[ Stack variable");
|
: "[ Stack variable");
|
||||||
|
|
||||||
if (NeedsHoleCheckForLoad(proxy)) {
|
if (NeedsHoleCheckForLoad(proxy)) {
|
||||||
// Let and const need a read barrier.
|
// Let and const need a read barrier.
|
||||||
Label done;
|
Label done;
|
||||||
@ -1455,11 +1465,18 @@ void FullCodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitAccessor(Expression* expression) {
|
void FullCodeGenerator::EmitAccessor(ObjectLiteralProperty* property) {
|
||||||
|
Expression* expression = (property == NULL) ? NULL : property->value();
|
||||||
if (expression == NULL) {
|
if (expression == NULL) {
|
||||||
__ push(Immediate(isolate()->factory()->null_value()));
|
__ push(Immediate(isolate()->factory()->null_value()));
|
||||||
} else {
|
} else {
|
||||||
VisitForStackValue(expression);
|
VisitForStackValue(expression);
|
||||||
|
if (NeedsHomeObject(expression)) {
|
||||||
|
DCHECK(property->kind() == ObjectLiteral::Property::GETTER ||
|
||||||
|
property->kind() == ObjectLiteral::Property::SETTER);
|
||||||
|
int offset = property->kind() == ObjectLiteral::Property::GETTER ? 2 : 3;
|
||||||
|
EmitSetHomeObject(expression, offset, property->GetSlot());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1495,10 +1512,6 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
|||||||
|
|
||||||
AccessorTable accessor_table(zone());
|
AccessorTable accessor_table(zone());
|
||||||
int property_index = 0;
|
int property_index = 0;
|
||||||
// store_slot_index points to the vector IC slot for the next store IC used.
|
|
||||||
// ObjectLiteral::ComputeFeedbackRequirements controls the allocation of slots
|
|
||||||
// and must be updated if the number of store ICs emitted here changes.
|
|
||||||
int store_slot_index = 0;
|
|
||||||
for (; property_index < expr->properties()->length(); property_index++) {
|
for (; property_index < expr->properties()->length(); property_index++) {
|
||||||
ObjectLiteral::Property* property = expr->properties()->at(property_index);
|
ObjectLiteral::Property* property = expr->properties()->at(property_index);
|
||||||
if (property->is_computed_name()) break;
|
if (property->is_computed_name()) break;
|
||||||
@ -1526,22 +1539,14 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
|||||||
__ mov(StoreDescriptor::NameRegister(), Immediate(key->value()));
|
__ mov(StoreDescriptor::NameRegister(), Immediate(key->value()));
|
||||||
__ mov(StoreDescriptor::ReceiverRegister(), Operand(esp, 0));
|
__ mov(StoreDescriptor::ReceiverRegister(), Operand(esp, 0));
|
||||||
if (FLAG_vector_stores) {
|
if (FLAG_vector_stores) {
|
||||||
EmitLoadStoreICSlot(expr->GetNthSlot(store_slot_index++));
|
EmitLoadStoreICSlot(property->GetSlot(0));
|
||||||
CallStoreIC();
|
CallStoreIC();
|
||||||
} else {
|
} else {
|
||||||
CallStoreIC(key->LiteralFeedbackId());
|
CallStoreIC(key->LiteralFeedbackId());
|
||||||
}
|
}
|
||||||
PrepareForBailoutForId(key->id(), NO_REGISTERS);
|
PrepareForBailoutForId(key->id(), NO_REGISTERS);
|
||||||
|
|
||||||
if (NeedsHomeObject(value)) {
|
if (NeedsHomeObject(value)) {
|
||||||
__ mov(StoreDescriptor::ReceiverRegister(), eax);
|
EmitSetHomeObjectAccumulator(value, 0, property->GetSlot(1));
|
||||||
__ mov(StoreDescriptor::NameRegister(),
|
|
||||||
Immediate(isolate()->factory()->home_object_symbol()));
|
|
||||||
__ mov(StoreDescriptor::ValueRegister(), Operand(esp, 0));
|
|
||||||
if (FLAG_vector_stores) {
|
|
||||||
EmitLoadStoreICSlot(expr->GetNthSlot(store_slot_index++));
|
|
||||||
}
|
|
||||||
CallStoreIC();
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
VisitForEffect(value);
|
VisitForEffect(value);
|
||||||
@ -1552,8 +1557,9 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
|||||||
VisitForStackValue(key);
|
VisitForStackValue(key);
|
||||||
VisitForStackValue(value);
|
VisitForStackValue(value);
|
||||||
if (property->emit_store()) {
|
if (property->emit_store()) {
|
||||||
EmitSetHomeObjectIfNeeded(
|
if (NeedsHomeObject(value)) {
|
||||||
value, 2, expr->SlotForHomeObject(value, &store_slot_index));
|
EmitSetHomeObject(value, 2, property->GetSlot());
|
||||||
|
}
|
||||||
__ push(Immediate(Smi::FromInt(SLOPPY))); // Language mode
|
__ push(Immediate(Smi::FromInt(SLOPPY))); // Language mode
|
||||||
__ CallRuntime(Runtime::kSetProperty, 4);
|
__ CallRuntime(Runtime::kSetProperty, 4);
|
||||||
} else {
|
} else {
|
||||||
@ -1568,12 +1574,12 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
|||||||
break;
|
break;
|
||||||
case ObjectLiteral::Property::GETTER:
|
case ObjectLiteral::Property::GETTER:
|
||||||
if (property->emit_store()) {
|
if (property->emit_store()) {
|
||||||
accessor_table.lookup(key)->second->getter = value;
|
accessor_table.lookup(key)->second->getter = property;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ObjectLiteral::Property::SETTER:
|
case ObjectLiteral::Property::SETTER:
|
||||||
if (property->emit_store()) {
|
if (property->emit_store()) {
|
||||||
accessor_table.lookup(key)->second->setter = value;
|
accessor_table.lookup(key)->second->setter = property;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1586,15 +1592,9 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
|||||||
++it) {
|
++it) {
|
||||||
__ push(Operand(esp, 0)); // Duplicate receiver.
|
__ push(Operand(esp, 0)); // Duplicate receiver.
|
||||||
VisitForStackValue(it->first);
|
VisitForStackValue(it->first);
|
||||||
EmitAccessor(it->second->getter);
|
|
||||||
EmitSetHomeObjectIfNeeded(
|
|
||||||
it->second->getter, 2,
|
|
||||||
expr->SlotForHomeObject(it->second->getter, &store_slot_index));
|
|
||||||
|
|
||||||
|
EmitAccessor(it->second->getter);
|
||||||
EmitAccessor(it->second->setter);
|
EmitAccessor(it->second->setter);
|
||||||
EmitSetHomeObjectIfNeeded(
|
|
||||||
it->second->setter, 3,
|
|
||||||
expr->SlotForHomeObject(it->second->setter, &store_slot_index));
|
|
||||||
|
|
||||||
__ push(Immediate(Smi::FromInt(NONE)));
|
__ push(Immediate(Smi::FromInt(NONE)));
|
||||||
__ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5);
|
__ CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5);
|
||||||
@ -1628,8 +1628,9 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
|||||||
} else {
|
} else {
|
||||||
EmitPropertyKey(property, expr->GetIdForProperty(property_index));
|
EmitPropertyKey(property, expr->GetIdForProperty(property_index));
|
||||||
VisitForStackValue(value);
|
VisitForStackValue(value);
|
||||||
EmitSetHomeObjectIfNeeded(
|
if (NeedsHomeObject(value)) {
|
||||||
value, 2, expr->SlotForHomeObject(value, &store_slot_index));
|
EmitSetHomeObject(value, 2, property->GetSlot());
|
||||||
|
}
|
||||||
|
|
||||||
switch (property->kind()) {
|
switch (property->kind()) {
|
||||||
case ObjectLiteral::Property::CONSTANT:
|
case ObjectLiteral::Property::CONSTANT:
|
||||||
@ -1671,10 +1672,6 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
|
|||||||
} else {
|
} else {
|
||||||
context()->Plug(eax);
|
context()->Plug(eax);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify that compilation exactly consumed the number of store ic slots that
|
|
||||||
// the ObjectLiteral node had to offer.
|
|
||||||
DCHECK(!FLAG_vector_stores || store_slot_index == expr->slot_count());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2343,8 +2340,7 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit,
|
void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
|
||||||
int* used_store_slots) {
|
|
||||||
// Constructor is in eax.
|
// Constructor is in eax.
|
||||||
DCHECK(lit != NULL);
|
DCHECK(lit != NULL);
|
||||||
__ push(eax);
|
__ push(eax);
|
||||||
@ -2376,8 +2372,9 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit,
|
|||||||
}
|
}
|
||||||
|
|
||||||
VisitForStackValue(value);
|
VisitForStackValue(value);
|
||||||
EmitSetHomeObjectIfNeeded(value, 2,
|
if (NeedsHomeObject(value)) {
|
||||||
lit->SlotForHomeObject(value, used_store_slots));
|
EmitSetHomeObject(value, 2, property->GetSlot());
|
||||||
|
}
|
||||||
|
|
||||||
switch (property->kind()) {
|
switch (property->kind()) {
|
||||||
case ObjectLiteral::Property::CONSTANT:
|
case ObjectLiteral::Property::CONSTANT:
|
||||||
|
Loading…
Reference in New Issue
Block a user