Commit f52d0053 authored by Igor Sheludko's avatar Igor Sheludko Committed by Commit Bot

[iterpreter] Share feedback slots for global stores to the same variable.

Bug: v8:7206, chromium:576312
Change-Id: I1628e7966a40fa7d6f628bd972b0ad0142a5d349
Reviewed-on: https://chromium-review.googlesource.com/970825Reviewed-by: 's avatarMythri Alle <mythria@google.com>
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#52075}
parent b105df6d
...@@ -804,31 +804,33 @@ class BytecodeGenerator::CurrentScope final { ...@@ -804,31 +804,33 @@ class BytecodeGenerator::CurrentScope final {
class BytecodeGenerator::FeedbackSlotCache : public ZoneObject { class BytecodeGenerator::FeedbackSlotCache : public ZoneObject {
public: public:
typedef std::pair<TypeofMode, void*> Key;
explicit FeedbackSlotCache(Zone* zone) : map_(zone) {} explicit FeedbackSlotCache(Zone* zone) : map_(zone) {}
void Put(TypeofMode typeof_mode, Variable* variable, FeedbackSlot slot) { void Put(FeedbackSlotKind slot_kind, Variable* variable, FeedbackSlot slot) {
Key key = std::make_pair(typeof_mode, variable); PutImpl(slot_kind, variable, slot);
auto entry = std::make_pair(key, slot); }
map_.insert(entry); void Put(FeedbackSlotKind slot_kind, AstNode* node, FeedbackSlot slot) {
PutImpl(slot_kind, node, slot);
}
FeedbackSlot Get(FeedbackSlotKind slot_kind, Variable* variable) const {
return GetImpl(slot_kind, variable);
} }
void Put(AstNode* node, FeedbackSlot slot) { FeedbackSlot Get(FeedbackSlotKind slot_kind, AstNode* node) const {
Key key = std::make_pair(NOT_INSIDE_TYPEOF, node); return GetImpl(slot_kind, node);
}
private:
typedef std::pair<FeedbackSlotKind, void*> Key;
void PutImpl(FeedbackSlotKind slot_kind, void* node, FeedbackSlot slot) {
Key key = std::make_pair(slot_kind, node);
auto entry = std::make_pair(key, slot); auto entry = std::make_pair(key, slot);
map_.insert(entry); map_.insert(entry);
} }
FeedbackSlot Get(TypeofMode typeof_mode, Variable* variable) const { FeedbackSlot GetImpl(FeedbackSlotKind slot_kind, void* node) const {
Key key = std::make_pair(typeof_mode, variable); Key key = std::make_pair(slot_kind, node);
auto iter = map_.find(key);
if (iter != map_.end()) {
return iter->second;
}
return FeedbackSlot();
}
FeedbackSlot Get(AstNode* node) const {
Key key = std::make_pair(NOT_INSIDE_TYPEOF, node);
auto iter = map_.find(key); auto iter = map_.find(key);
if (iter != map_.end()) { if (iter != map_.end()) {
return iter->second; return iter->second;
...@@ -836,7 +838,6 @@ class BytecodeGenerator::FeedbackSlotCache : public ZoneObject { ...@@ -836,7 +838,6 @@ class BytecodeGenerator::FeedbackSlotCache : public ZoneObject {
return FeedbackSlot(); return FeedbackSlot();
} }
private:
ZoneMap<Key, FeedbackSlot> map_; ZoneMap<Key, FeedbackSlot> map_;
}; };
...@@ -2658,9 +2659,7 @@ void BytecodeGenerator::BuildVariableAssignment( ...@@ -2658,9 +2659,7 @@ void BytecodeGenerator::BuildVariableAssignment(
break; break;
} }
case VariableLocation::UNALLOCATED: { case VariableLocation::UNALLOCATED: {
// TODO(ishell): consider using FeedbackSlotCache for variables here. FeedbackSlot slot = GetCachedStoreGlobalICSlot(language_mode(), variable);
FeedbackSlot slot =
feedback_spec()->AddStoreGlobalICSlot(language_mode());
builder()->StoreGlobal(variable->raw_name(), feedback_index(slot)); builder()->StoreGlobal(variable->raw_name(), feedback_index(slot));
break; break;
} }
...@@ -4963,23 +4962,42 @@ int BytecodeGenerator::feedback_index(FeedbackSlot slot) const { ...@@ -4963,23 +4962,42 @@ int BytecodeGenerator::feedback_index(FeedbackSlot slot) const {
FeedbackSlot BytecodeGenerator::GetCachedLoadGlobalICSlot( FeedbackSlot BytecodeGenerator::GetCachedLoadGlobalICSlot(
TypeofMode typeof_mode, Variable* variable) { TypeofMode typeof_mode, Variable* variable) {
FeedbackSlot slot = feedback_slot_cache()->Get(typeof_mode, variable); FeedbackSlotKind slot_kind =
typeof_mode == INSIDE_TYPEOF
? FeedbackSlotKind::kLoadGlobalInsideTypeof
: FeedbackSlotKind::kLoadGlobalNotInsideTypeof;
FeedbackSlot slot = feedback_slot_cache()->Get(slot_kind, variable);
if (!slot.IsInvalid()) { if (!slot.IsInvalid()) {
return slot; return slot;
} }
slot = feedback_spec()->AddLoadGlobalICSlot(typeof_mode); slot = feedback_spec()->AddLoadGlobalICSlot(typeof_mode);
feedback_slot_cache()->Put(typeof_mode, variable, slot); feedback_slot_cache()->Put(slot_kind, variable, slot);
return slot;
}
FeedbackSlot BytecodeGenerator::GetCachedStoreGlobalICSlot(
LanguageMode language_mode, Variable* variable) {
FeedbackSlotKind slot_kind = is_strict(language_mode)
? FeedbackSlotKind::kStoreGlobalStrict
: FeedbackSlotKind::kStoreGlobalSloppy;
FeedbackSlot slot = feedback_slot_cache()->Get(slot_kind, variable);
if (!slot.IsInvalid()) {
return slot;
}
slot = feedback_spec()->AddStoreGlobalICSlot(language_mode);
feedback_slot_cache()->Put(slot_kind, variable, slot);
return slot; return slot;
} }
FeedbackSlot BytecodeGenerator::GetCachedCreateClosureSlot( FeedbackSlot BytecodeGenerator::GetCachedCreateClosureSlot(
FunctionLiteral* literal) { FunctionLiteral* literal) {
FeedbackSlot slot = feedback_slot_cache()->Get(literal); FeedbackSlotKind slot_kind = FeedbackSlotKind::kCreateClosure;
FeedbackSlot slot = feedback_slot_cache()->Get(slot_kind, literal);
if (!slot.IsInvalid()) { if (!slot.IsInvalid()) {
return slot; return slot;
} }
slot = feedback_spec()->AddCreateClosureSlot(); slot = feedback_spec()->AddCreateClosureSlot();
feedback_slot_cache()->Put(literal, slot); feedback_slot_cache()->Put(slot_kind, literal, slot);
return slot; return slot;
} }
......
...@@ -262,6 +262,8 @@ class BytecodeGenerator final : public AstVisitor<BytecodeGenerator> { ...@@ -262,6 +262,8 @@ class BytecodeGenerator final : public AstVisitor<BytecodeGenerator> {
// already exists. // already exists.
FeedbackSlot GetCachedLoadGlobalICSlot(TypeofMode typeof_mode, FeedbackSlot GetCachedLoadGlobalICSlot(TypeofMode typeof_mode,
Variable* variable); Variable* variable);
FeedbackSlot GetCachedStoreGlobalICSlot(LanguageMode language_mode,
Variable* variable);
FeedbackSlot GetCachedCreateClosureSlot(FunctionLiteral* literal); FeedbackSlot GetCachedCreateClosureSlot(FunctionLiteral* literal);
void AddToEagerLiteralsIfEager(FunctionLiteral* literal); void AddToEagerLiteralsIfEager(FunctionLiteral* literal);
......
...@@ -76,7 +76,7 @@ bytecodes: [ ...@@ -76,7 +76,7 @@ bytecodes: [
/* 8 S> */ B(LdaSmi), I8(1), /* 8 S> */ B(LdaSmi), I8(1),
/* 8 E> */ B(StaGlobal), U8(1), U8(2), /* 8 E> */ B(StaGlobal), U8(1), U8(2),
/* 11 S> */ B(LdaSmi), I8(2), /* 11 S> */ B(LdaSmi), I8(2),
/* 12 E> */ B(StaGlobal), U8(1), U8(4), /* 12 E> */ B(StaGlobal), U8(1), U8(2),
B(Star), R(0), B(Star), R(0),
/* 15 S> */ B(Return), /* 15 S> */ B(Return),
] ]
......
...@@ -495,11 +495,10 @@ TEST(ReferenceContextAllocatesNoSlots) { ...@@ -495,11 +495,10 @@ TEST(ReferenceContextAllocatesNoSlots) {
Handle<FeedbackVector> feedback_vector = Handle<FeedbackVector> feedback_vector =
handle(f->feedback_vector(), isolate); handle(f->feedback_vector(), isolate);
FeedbackVectorHelper helper(feedback_vector); FeedbackVectorHelper helper(feedback_vector);
CHECK_EQ(4, helper.slot_count()); CHECK_EQ(3, helper.slot_count());
CHECK_SLOT_KIND(helper, 0, FeedbackSlotKind::kStoreGlobalSloppy); CHECK_SLOT_KIND(helper, 0, FeedbackSlotKind::kStoreGlobalSloppy);
CHECK_SLOT_KIND(helper, 1, FeedbackSlotKind::kLoadGlobalNotInsideTypeof); CHECK_SLOT_KIND(helper, 1, FeedbackSlotKind::kLoadGlobalNotInsideTypeof);
CHECK_SLOT_KIND(helper, 2, FeedbackSlotKind::kStoreGlobalSloppy); CHECK_SLOT_KIND(helper, 2, FeedbackSlotKind::kLoadGlobalNotInsideTypeof);
CHECK_SLOT_KIND(helper, 3, FeedbackSlotKind::kLoadGlobalNotInsideTypeof);
} }
{ {
......
...@@ -1460,7 +1460,7 @@ TEST(CodeSerializerLargeCodeObjectWithIncrementalMarking) { ...@@ -1460,7 +1460,7 @@ TEST(CodeSerializerLargeCodeObjectWithIncrementalMarking) {
Vector<const uint8_t> source = ConstructSource( Vector<const uint8_t> source = ConstructSource(
STATIC_CHAR_VECTOR("var j=1; if (j == 0) {"), STATIC_CHAR_VECTOR("var j=1; if (j == 0) {"),
STATIC_CHAR_VECTOR("for (var i = 0; i < Object.prototype; i++);"), STATIC_CHAR_VECTOR("for (var i = 0; i < Object.prototype; i++);"),
STATIC_CHAR_VECTOR("} j=7; var s = 'happy_hippo'; j"), 10000); STATIC_CHAR_VECTOR("} j=7; var s = 'happy_hippo'; j"), 20000);
Handle<String> source_str = Handle<String> source_str =
isolate->factory()->NewStringFromOneByte(source).ToHandleChecked(); isolate->factory()->NewStringFromOneByte(source).ToHandleChecked();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment