Skip to content

Commit 752b030

Browse files
ripsawridgeCommit bot
authored andcommitted
Vector ICs: The Oracle needs to report feedback for the object literals and the count operation.
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(). Review URL: https://codereview.chromium.org/1321993004 Cr-Commit-Position: refs/heads/master@{#30686}
1 parent 33ec0b7 commit 752b030

17 files changed

Lines changed: 482 additions & 440 deletions

src/ast-numbering.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -463,6 +463,7 @@ void AstNumberingVisitor::VisitClassLiteral(ClassLiteral* node) {
463463
VisitObjectLiteralProperty(node->properties()->at(i));
464464
}
465465
ReserveFeedbackSlots(node);
466+
node->LayoutFeedbackSlots();
466467
}
467468

468469

@@ -478,6 +479,7 @@ void AstNumberingVisitor::VisitObjectLiteral(ObjectLiteral* node) {
478479
// marked expressions, no store code will be is emitted.
479480
node->CalculateEmitStore(zone());
480481
ReserveFeedbackSlots(node);
482+
node->LayoutFeedbackSlots();
481483
}
482484

483485

src/ast.cc

Lines changed: 86 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,7 @@ ObjectLiteralProperty::ObjectLiteralProperty(Expression* key, Expression* value,
251251
bool is_computed_name)
252252
: key_(key),
253253
value_(value),
254+
ic_slot_or_count_(FeedbackVectorICSlot::Invalid().ToInt()),
254255
kind_(kind),
255256
emit_store_(true),
256257
is_static_(is_static),
@@ -263,6 +264,7 @@ ObjectLiteralProperty::ObjectLiteralProperty(AstValueFactory* ast_value_factory,
263264
bool is_computed_name)
264265
: key_(key),
265266
value_(value),
267+
ic_slot_or_count_(FeedbackVectorICSlot::Invalid().ToInt()),
266268
emit_store_(true),
267269
is_static_(is_static),
268270
is_computed_name_(is_computed_name) {
@@ -287,35 +289,34 @@ FeedbackVectorRequirements ClassLiteral::ComputeFeedbackRequirements(
287289
// This logic that computes the number of slots needed for vector store
288290
// ICs must mirror FullCodeGenerator::VisitClassLiteral.
289291
int ic_slots = 0;
292+
if (NeedsProxySlot()) {
293+
ic_slots++;
294+
}
295+
290296
for (int i = 0; i < properties()->length(); i++) {
291297
ObjectLiteral::Property* property = properties()->at(i);
298+
// In case we don't end up using any slots.
299+
property->set_ic_slot_count(0);
292300

293301
Expression* value = property->value();
294-
if (FunctionLiteral::NeedsHomeObject(value)) ic_slots++;
295-
}
296-
297-
if (scope() != NULL && class_variable_proxy()->var()->IsUnallocated()) {
298-
ic_slots++;
302+
if (FunctionLiteral::NeedsHomeObject(value)) {
303+
property->set_ic_slot_count(1);
304+
ic_slots++;
305+
}
299306
}
300307

301-
#ifdef DEBUG
302-
// FullCodeGenerator::VisitClassLiteral verifies that it consumes slot_count_
303-
// slots.
304-
slot_count_ = ic_slots;
305-
#endif
306308
return FeedbackVectorRequirements(0, ic_slots);
307309
}
308310

309311

310-
FeedbackVectorICSlot ClassLiteral::SlotForHomeObject(Expression* value,
311-
int* slot_index) const {
312-
if (FLAG_vector_stores && FunctionLiteral::NeedsHomeObject(value)) {
313-
DCHECK(slot_index != NULL && *slot_index >= 0 && *slot_index < slot_count_);
314-
FeedbackVectorICSlot slot = GetNthSlot(*slot_index);
315-
*slot_index += 1;
316-
return slot;
312+
void ClassLiteral::LayoutFeedbackSlots() {
313+
int base_slot = slot_.ToInt();
314+
if (NeedsProxySlot()) base_slot++;
315+
316+
for (int i = 0; i < properties()->length(); i++) {
317+
ObjectLiteral::Property* property = properties()->at(i);
318+
base_slot += property->set_base_slot(base_slot);
317319
}
318-
return FeedbackVectorICSlot::Invalid();
319320
}
320321

321322

@@ -336,55 +337,88 @@ bool ObjectLiteral::Property::emit_store() {
336337
}
337338

338339

340+
void ObjectLiteral::LayoutFeedbackSlots() {
341+
int base_slot = slot_.ToInt();
342+
for (int i = 0; i < properties()->length(); i++) {
343+
ObjectLiteral::Property* property = properties()->at(i);
344+
base_slot += property->set_base_slot(base_slot);
345+
}
346+
}
347+
348+
339349
FeedbackVectorRequirements ObjectLiteral::ComputeFeedbackRequirements(
340350
Isolate* isolate, const ICSlotCache* cache) {
341351
if (!FLAG_vector_stores) return FeedbackVectorRequirements(0, 0);
342352

343353
// This logic that computes the number of slots needed for vector store
344354
// ics must mirror FullCodeGenerator::VisitObjectLiteral.
345-
int ic_slots = 0;
346-
bool saw_computed_name = false;
347-
for (int i = 0; i < properties()->length(); i++) {
348-
ObjectLiteral::Property* property = properties()->at(i);
355+
int property_index = 0;
356+
for (; property_index < properties()->length(); property_index++) {
357+
ObjectLiteral::Property* property = properties()->at(property_index);
358+
// In case we don't end up using any slots.
359+
property->set_ic_slot_count(0);
360+
361+
if (property->is_computed_name()) break;
349362
if (property->IsCompileTimeValue()) continue;
350-
saw_computed_name |= property->is_computed_name();
351363

364+
Literal* key = property->key()->AsLiteral();
352365
Expression* value = property->value();
353-
if (saw_computed_name &&
354-
property->kind() != ObjectLiteral::Property::PROTOTYPE) {
355-
if (FunctionLiteral::NeedsHomeObject(value)) ic_slots++;
356-
} else if (property->emit_store()) {
357-
if (property->kind() == ObjectLiteral::Property::MATERIALIZED_LITERAL ||
358-
property->kind() == ObjectLiteral::Property::COMPUTED) {
359-
Literal* key = property->key()->AsLiteral();
360-
if (key->value()->IsInternalizedString()) ic_slots++;
361-
if (FunctionLiteral::NeedsHomeObject(value)) ic_slots++;
362-
} else if (property->kind() == ObjectLiteral::Property::GETTER ||
363-
property->kind() == ObjectLiteral::Property::SETTER) {
364-
// We might need a slot for the home object.
365-
if (FunctionLiteral::NeedsHomeObject(value)) ic_slots++;
366-
}
366+
switch (property->kind()) {
367+
case ObjectLiteral::Property::CONSTANT:
368+
UNREACHABLE();
369+
case ObjectLiteral::Property::MATERIALIZED_LITERAL:
370+
// Fall through.
371+
case ObjectLiteral::Property::COMPUTED:
372+
// It is safe to use [[Put]] here because the boilerplate already
373+
// contains computed properties with an uninitialized value.
374+
if (key->value()->IsInternalizedString()) {
375+
if (property->emit_store()) {
376+
int slot_count = 1;
377+
if (FunctionLiteral::NeedsHomeObject(value)) {
378+
slot_count++;
379+
}
380+
property->set_ic_slot_count(slot_count);
381+
}
382+
break;
383+
}
384+
if (property->emit_store() && FunctionLiteral::NeedsHomeObject(value)) {
385+
property->set_ic_slot_count(1);
386+
}
387+
break;
388+
case ObjectLiteral::Property::PROTOTYPE:
389+
break;
390+
case ObjectLiteral::Property::GETTER:
391+
if (property->emit_store() && FunctionLiteral::NeedsHomeObject(value)) {
392+
property->set_ic_slot_count(1);
393+
}
394+
break;
395+
case ObjectLiteral::Property::SETTER:
396+
if (property->emit_store() && FunctionLiteral::NeedsHomeObject(value)) {
397+
property->set_ic_slot_count(1);
398+
}
399+
break;
367400
}
368401
}
369402

370-
#ifdef DEBUG
371-
// FullCodeGenerator::VisitObjectLiteral verifies that it consumes slot_count_
372-
// slots.
373-
slot_count_ = ic_slots;
374-
#endif
375-
return FeedbackVectorRequirements(0, ic_slots);
376-
}
403+
for (; property_index < properties()->length(); property_index++) {
404+
ObjectLiteral::Property* property = properties()->at(property_index);
377405

406+
Expression* value = property->value();
407+
if (property->kind() != ObjectLiteral::Property::PROTOTYPE) {
408+
if (FunctionLiteral::NeedsHomeObject(value)) {
409+
property->set_ic_slot_count(1);
410+
}
411+
}
412+
}
378413

379-
FeedbackVectorICSlot ObjectLiteral::SlotForHomeObject(Expression* value,
380-
int* slot_index) const {
381-
if (FLAG_vector_stores && FunctionLiteral::NeedsHomeObject(value)) {
382-
DCHECK(slot_index != NULL && *slot_index >= 0 && *slot_index < slot_count_);
383-
FeedbackVectorICSlot slot = GetNthSlot(*slot_index);
384-
*slot_index += 1;
385-
return slot;
414+
// How many slots did we allocate?
415+
int ic_slots = 0;
416+
for (int i = 0; i < properties()->length(); i++) {
417+
ObjectLiteral::Property* property = properties()->at(i);
418+
ic_slots += property->ic_slot_count();
386419
}
387-
return FeedbackVectorICSlot::Invalid();
420+
421+
return FeedbackVectorRequirements(0, ic_slots);
388422
}
389423

390424

src/ast.h

Lines changed: 45 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1399,7 +1399,38 @@ class ObjectLiteralProperty final : public ZoneObject {
13991399
bool is_static() const { return is_static_; }
14001400
bool is_computed_name() const { return is_computed_name_; }
14011401

1402+
FeedbackVectorICSlot GetSlot(int offset = 0) const {
1403+
if (ic_slot_or_count_ == FeedbackVectorICSlot::Invalid().ToInt()) {
1404+
return FeedbackVectorICSlot::Invalid();
1405+
}
1406+
return FeedbackVectorICSlot(ic_slot_or_count_ + offset);
1407+
}
1408+
1409+
int ic_slot_count() const {
1410+
if (ic_slot_or_count_ == FeedbackVectorICSlot::Invalid().ToInt()) {
1411+
return 0;
1412+
}
1413+
return ic_slot_or_count_;
1414+
}
1415+
14021416
void set_receiver_type(Handle<Map> map) { receiver_type_ = map; }
1417+
void set_ic_slot_count(int count) {
1418+
// Should only be called once.
1419+
if (count == 0) {
1420+
ic_slot_or_count_ = FeedbackVectorICSlot::Invalid().ToInt();
1421+
} else {
1422+
ic_slot_or_count_ = count;
1423+
}
1424+
}
1425+
1426+
int set_base_slot(int slot) {
1427+
if (ic_slot_count() > 0) {
1428+
int count = ic_slot_count();
1429+
ic_slot_or_count_ = slot;
1430+
return count;
1431+
}
1432+
return 0;
1433+
}
14031434

14041435
protected:
14051436
friend class AstNodeFactory;
@@ -1413,6 +1444,7 @@ class ObjectLiteralProperty final : public ZoneObject {
14131444
private:
14141445
Expression* key_;
14151446
Expression* value_;
1447+
int ic_slot_or_count_;
14161448
Kind kind_;
14171449
bool emit_store_;
14181450
bool is_static_;
@@ -1477,8 +1509,8 @@ class ObjectLiteral final : public MaterializedLiteral {
14771509

14781510
struct Accessors: public ZoneObject {
14791511
Accessors() : getter(NULL), setter(NULL) {}
1480-
Expression* getter;
1481-
Expression* setter;
1512+
ObjectLiteralProperty* getter;
1513+
ObjectLiteralProperty* setter;
14821514
};
14831515

14841516
BailoutId CreateLiteralId() const { return BailoutId(local_id(0)); }
@@ -1499,18 +1531,10 @@ class ObjectLiteral final : public MaterializedLiteral {
14991531
slot_ = slot;
15001532
}
15011533
Code::Kind FeedbackICSlotKind(int index) override { return Code::STORE_IC; }
1502-
FeedbackVectorICSlot GetNthSlot(int n) const {
1503-
return FeedbackVectorICSlot(slot_.ToInt() + n);
1504-
}
15051534

1506-
// If value needs a home object, returns a valid feedback vector ic slot
1507-
// given by slot_index, and increments slot_index.
1508-
FeedbackVectorICSlot SlotForHomeObject(Expression* value,
1509-
int* slot_index) const;
1510-
1511-
#ifdef DEBUG
1512-
int slot_count() const { return slot_count_; }
1513-
#endif
1535+
// After feedback slots were assigned, propagate information to the properties
1536+
// which need it.
1537+
void LayoutFeedbackSlots();
15141538

15151539
protected:
15161540
ObjectLiteral(Zone* zone, ZoneList<Property*>* properties, int literal_index,
@@ -1523,9 +1547,6 @@ class ObjectLiteral final : public MaterializedLiteral {
15231547
has_elements_(false),
15241548
may_store_doubles_(false),
15251549
has_function_(has_function),
1526-
#ifdef DEBUG
1527-
slot_count_(0),
1528-
#endif
15291550
slot_(FeedbackVectorICSlot::Invalid()) {
15301551
}
15311552
static int parent_num_ids() { return MaterializedLiteral::num_ids(); }
@@ -1539,11 +1560,6 @@ class ObjectLiteral final : public MaterializedLiteral {
15391560
bool has_elements_;
15401561
bool may_store_doubles_;
15411562
bool has_function_;
1542-
#ifdef DEBUG
1543-
// slot_count_ helps validate that the logic to allocate ic slots and the
1544-
// logic to use them are in sync.
1545-
int slot_count_;
1546-
#endif
15471563
FeedbackVectorICSlot slot_;
15481564
};
15491565

@@ -2714,18 +2730,17 @@ class ClassLiteral final : public Expression {
27142730
slot_ = slot;
27152731
}
27162732
Code::Kind FeedbackICSlotKind(int index) override { return Code::STORE_IC; }
2717-
FeedbackVectorICSlot GetNthSlot(int n) const {
2718-
return FeedbackVectorICSlot(slot_.ToInt() + n);
2733+
2734+
bool NeedsProxySlot() const {
2735+
return FLAG_vector_stores && scope() != NULL &&
2736+
class_variable_proxy()->var()->IsUnallocated();
27192737
}
27202738

2721-
// If value needs a home object, returns a valid feedback vector ic slot
2722-
// given by slot_index, and increments slot_index.
2723-
FeedbackVectorICSlot SlotForHomeObject(Expression* value,
2724-
int* slot_index) const;
2739+
FeedbackVectorICSlot ProxySlot() const { return slot_; }
27252740

2726-
#ifdef DEBUG
2727-
int slot_count() const { return slot_count_; }
2728-
#endif
2741+
// After feedback slots were assigned, propagate information to the properties
2742+
// which need it.
2743+
void LayoutFeedbackSlots();
27292744

27302745
protected:
27312746
ClassLiteral(Zone* zone, const AstRawString* name, Scope* scope,
@@ -2740,9 +2755,6 @@ class ClassLiteral final : public Expression {
27402755
constructor_(constructor),
27412756
properties_(properties),
27422757
end_position_(end_position),
2743-
#ifdef DEBUG
2744-
slot_count_(0),
2745-
#endif
27462758
slot_(FeedbackVectorICSlot::Invalid()) {
27472759
}
27482760

@@ -2758,11 +2770,6 @@ class ClassLiteral final : public Expression {
27582770
FunctionLiteral* constructor_;
27592771
ZoneList<Property*>* properties_;
27602772
int end_position_;
2761-
#ifdef DEBUG
2762-
// slot_count_ helps validate that the logic to allocate ic slots and the
2763-
// logic to use them are in sync.
2764-
int slot_count_;
2765-
#endif
27662773
FeedbackVectorICSlot slot_;
27672774
};
27682775

0 commit comments

Comments
 (0)