[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:
parent
b105df6d1e
commit
f52d005395
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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),
|
||||
]
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -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();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user