[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/970825
Reviewed-by: Mythri Alle <mythria@google.com>
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#52075}
This commit is contained in:
Igor Sheludko 2018-03-20 16:16:25 +01:00 committed by Commit Bot
parent b105df6d1e
commit f52d005395
5 changed files with 55 additions and 36 deletions

View File

@ -804,39 +804,40 @@ class BytecodeGenerator::CurrentScope final {
class BytecodeGenerator::FeedbackSlotCache : public ZoneObject {
public:
typedef std::pair<TypeofMode, void*> Key;
explicit FeedbackSlotCache(Zone* zone) : map_(zone) {}
void Put(TypeofMode typeof_mode, Variable* variable, FeedbackSlot slot) {
Key key = std::make_pair(typeof_mode, variable);
auto entry = std::make_pair(key, slot);
map_.insert(entry);
void Put(FeedbackSlotKind slot_kind, Variable* variable, FeedbackSlot slot) {
PutImpl(slot_kind, variable, slot);
}
void Put(AstNode* node, FeedbackSlot slot) {
Key key = std::make_pair(NOT_INSIDE_TYPEOF, node);
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(TypeofMode typeof_mode, Variable* variable) const {
Key key = std::make_pair(typeof_mode, variable);
auto iter = map_.find(key);
if (iter != map_.end()) {
return iter->second;
}
return FeedbackSlot();
FeedbackSlot Get(FeedbackSlotKind slot_kind, Variable* variable) const {
return GetImpl(slot_kind, variable);
}
FeedbackSlot Get(AstNode* node) const {
Key key = std::make_pair(NOT_INSIDE_TYPEOF, node);
auto iter = map_.find(key);
if (iter != map_.end()) {
return iter->second;
}
return FeedbackSlot();
FeedbackSlot Get(FeedbackSlotKind slot_kind, AstNode* node) const {
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);
map_.insert(entry);
}
FeedbackSlot GetImpl(FeedbackSlotKind slot_kind, void* node) const {
Key key = std::make_pair(slot_kind, node);
auto iter = map_.find(key);
if (iter != map_.end()) {
return iter->second;
}
return FeedbackSlot();
}
ZoneMap<Key, FeedbackSlot> map_;
};
@ -2658,9 +2659,7 @@ void BytecodeGenerator::BuildVariableAssignment(
break;
}
case VariableLocation::UNALLOCATED: {
// TODO(ishell): consider using FeedbackSlotCache for variables here.
FeedbackSlot slot =
feedback_spec()->AddStoreGlobalICSlot(language_mode());
FeedbackSlot slot = GetCachedStoreGlobalICSlot(language_mode(), variable);
builder()->StoreGlobal(variable->raw_name(), feedback_index(slot));
break;
}
@ -4963,23 +4962,42 @@ int BytecodeGenerator::feedback_index(FeedbackSlot slot) const {
FeedbackSlot BytecodeGenerator::GetCachedLoadGlobalICSlot(
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()) {
return slot;
}
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;
}
FeedbackSlot BytecodeGenerator::GetCachedCreateClosureSlot(
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()) {
return slot;
}
slot = feedback_spec()->AddCreateClosureSlot();
feedback_slot_cache()->Put(literal, slot);
feedback_slot_cache()->Put(slot_kind, literal, slot);
return slot;
}

View File

@ -262,6 +262,8 @@ class BytecodeGenerator final : public AstVisitor<BytecodeGenerator> {
// already exists.
FeedbackSlot GetCachedLoadGlobalICSlot(TypeofMode typeof_mode,
Variable* variable);
FeedbackSlot GetCachedStoreGlobalICSlot(LanguageMode language_mode,
Variable* variable);
FeedbackSlot GetCachedCreateClosureSlot(FunctionLiteral* literal);
void AddToEagerLiteralsIfEager(FunctionLiteral* literal);

View File

@ -76,7 +76,7 @@ bytecodes: [
/* 8 S> */ B(LdaSmi), I8(1),
/* 8 E> */ B(StaGlobal), U8(1), U8(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),
/* 15 S> */ B(Return),
]

View File

@ -495,11 +495,10 @@ TEST(ReferenceContextAllocatesNoSlots) {
Handle<FeedbackVector> feedback_vector =
handle(f->feedback_vector(), isolate);
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, 1, FeedbackSlotKind::kLoadGlobalNotInsideTypeof);
CHECK_SLOT_KIND(helper, 2, FeedbackSlotKind::kStoreGlobalSloppy);
CHECK_SLOT_KIND(helper, 3, FeedbackSlotKind::kLoadGlobalNotInsideTypeof);
CHECK_SLOT_KIND(helper, 2, FeedbackSlotKind::kLoadGlobalNotInsideTypeof);
}
{

View File

@ -1460,7 +1460,7 @@ TEST(CodeSerializerLargeCodeObjectWithIncrementalMarking) {
Vector<const uint8_t> source = ConstructSource(
STATIC_CHAR_VECTOR("var j=1; if (j == 0) {"),
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 =
isolate->factory()->NewStringFromOneByte(source).ToHandleChecked();