[ic] Split StoreIC into StoreGlobalIC and StoreIC.

The former will handle stores to global variables, lets and undeclared
variables. The latter will handle named stores to explicit receiver.

BUG=chromium:576312, v8:5561

Change-Id: I335fa21db47c3d001da8cc79fa8cb6f8abcbb7e2
Reviewed-on: https://chromium-review.googlesource.com/458639
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Ross McIlroy <rmcilroy@chromium.org>
Reviewed-by: Toon Verwaest <verwaest@chromium.org>
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#44085}
This commit is contained in:
Igor Sheludko 2017-03-23 17:46:53 +01:00 committed by Commit Bot
parent 083a8d7209
commit 16c38aa820
28 changed files with 205 additions and 110 deletions

View File

@ -250,16 +250,16 @@ static void AssignVectorSlots(Expression* expr, FeedbackVectorSpec* spec,
FeedbackSlot* out_slot) { FeedbackSlot* out_slot) {
Property* property = expr->AsProperty(); Property* property = expr->AsProperty();
LhsKind assign_type = Property::GetAssignType(property); LhsKind assign_type = Property::GetAssignType(property);
if ((assign_type == VARIABLE && // TODO(ishell): consider using ICSlotCache for variables here.
expr->AsVariableProxy()->var()->IsUnallocated()) || if (assign_type == VARIABLE &&
assign_type == NAMED_PROPERTY || assign_type == KEYED_PROPERTY) { expr->AsVariableProxy()->var()->IsUnallocated()) {
// TODO(ishell): consider using ICSlotCache for variables here. *out_slot = spec->AddStoreGlobalICSlot(language_mode);
if (assign_type == KEYED_PROPERTY) {
*out_slot = spec->AddKeyedStoreICSlot(language_mode);
} else { } else if (assign_type == NAMED_PROPERTY) {
*out_slot = spec->AddStoreICSlot(language_mode); *out_slot = spec->AddStoreICSlot(language_mode);
}
} else if (assign_type == KEYED_PROPERTY) {
*out_slot = spec->AddKeyedStoreICSlot(language_mode);
} }
} }

View File

@ -65,6 +65,7 @@ class String;
V(REG_EXP_TAG, "RegExp") \ V(REG_EXP_TAG, "RegExp") \
V(SCRIPT_TAG, "Script") \ V(SCRIPT_TAG, "Script") \
V(STORE_IC_TAG, "StoreIC") \ V(STORE_IC_TAG, "StoreIC") \
V(STORE_GLOBAL_IC_TAG, "StoreGlobalIC") \
V(STORE_POLYMORPHIC_IC_TAG, "StorePolymorphicIC") \ V(STORE_POLYMORPHIC_IC_TAG, "StorePolymorphicIC") \
V(STUB_TAG, "Stub") \ V(STUB_TAG, "Stub") \
V(NATIVE_FUNCTION_TAG, "Function") \ V(NATIVE_FUNCTION_TAG, "Function") \

View File

@ -147,6 +147,25 @@ Callable CodeFactory::StoreOwnICInOptimizedCode(Isolate* isolate) {
StoreWithVectorDescriptor(isolate)); StoreWithVectorDescriptor(isolate));
} }
// static
Callable CodeFactory::StoreGlobalIC(Isolate* isolate,
LanguageMode language_mode) {
// TODO(ishell): Use StoreGlobalIC[Strict]Trampoline when it's ready.
return Callable(language_mode == STRICT
? isolate->builtins()->StoreICStrictTrampoline()
: isolate->builtins()->StoreICTrampoline(),
StoreDescriptor(isolate));
}
// static
Callable CodeFactory::StoreGlobalICInOptimizedCode(Isolate* isolate,
LanguageMode language_mode) {
// TODO(ishell): Use StoreGlobalIC[Strict] when it's ready.
return Callable(language_mode == STRICT ? isolate->builtins()->StoreICStrict()
: isolate->builtins()->StoreIC(),
StoreWithVectorDescriptor(isolate));
}
// static // static
Callable CodeFactory::KeyedStoreIC(Isolate* isolate, Callable CodeFactory::KeyedStoreIC(Isolate* isolate,
LanguageMode language_mode) { LanguageMode language_mode) {

View File

@ -41,6 +41,9 @@ class V8_EXPORT_PRIVATE CodeFactory final {
static Callable CallICTrampoline( static Callable CallICTrampoline(
Isolate* isolate, ConvertReceiverMode mode = ConvertReceiverMode::kAny, Isolate* isolate, ConvertReceiverMode mode = ConvertReceiverMode::kAny,
TailCallMode tail_call_mode = TailCallMode::kDisallow); TailCallMode tail_call_mode = TailCallMode::kDisallow);
static Callable StoreGlobalIC(Isolate* isolate, LanguageMode mode);
static Callable StoreGlobalICInOptimizedCode(Isolate* isolate,
LanguageMode mode);
static Callable StoreIC(Isolate* isolate, LanguageMode mode); static Callable StoreIC(Isolate* isolate, LanguageMode mode);
static Callable StoreICInOptimizedCode(Isolate* isolate, LanguageMode mode); static Callable StoreICInOptimizedCode(Isolate* isolate, LanguageMode mode);
static Callable StoreIC_Uninitialized(Isolate* isolate, LanguageMode mode); static Callable StoreIC_Uninitialized(Isolate* isolate, LanguageMode mode);

View File

@ -256,7 +256,7 @@ void JSGenericLowering::LowerJSStoreGlobal(Node* node) {
CallDescriptor::Flags flags = FrameStateFlagForCall(node); CallDescriptor::Flags flags = FrameStateFlagForCall(node);
const StoreGlobalParameters& p = StoreGlobalParametersOf(node->op()); const StoreGlobalParameters& p = StoreGlobalParametersOf(node->op());
Callable callable = Callable callable =
CodeFactory::StoreICInOptimizedCode(isolate(), p.language_mode()); CodeFactory::StoreGlobalICInOptimizedCode(isolate(), p.language_mode());
Node* vector = jsgraph()->HeapConstant(p.feedback().vector()); Node* vector = jsgraph()->HeapConstant(p.feedback().vector());
// Load global object from the context. // Load global object from the context.
Node* native_context = effect = Node* native_context = effect =

View File

@ -6573,13 +6573,15 @@ void HOptimizedGraphBuilder::HandleGlobalVariableAssignment(Variable* var,
HValue* name = Add<HConstant>(var->name()); HValue* name = Add<HConstant>(var->name());
HValue* vector_value = Add<HConstant>(vector); HValue* vector_value = Add<HConstant>(vector);
HValue* slot_value = Add<HConstant>(vector->GetIndex(slot)); HValue* slot_value = Add<HConstant>(vector->GetIndex(slot));
DCHECK(vector->IsStoreGlobalIC(slot));
DCHECK_EQ(vector->GetLanguageMode(slot), function_language_mode()); DCHECK_EQ(vector->GetLanguageMode(slot), function_language_mode());
Callable callable = CodeFactory::StoreICInOptimizedCode( Callable callable = CodeFactory::StoreGlobalICInOptimizedCode(
isolate(), function_language_mode()); isolate(), function_language_mode());
HValue* stub = Add<HConstant>(callable.code()); HValue* stub = Add<HConstant>(callable.code());
HValue* values[] = {global_object, name, value, slot_value, vector_value}; HValue* values[] = {global_object, name, value, slot_value, vector_value};
HCallWithDescriptor* instr = Add<HCallWithDescriptor>( HCallWithDescriptor* instr =
Code::STORE_IC, stub, 0, callable.descriptor(), ArrayVector(values)); Add<HCallWithDescriptor>(Code::STORE_GLOBAL_IC, stub, 0,
callable.descriptor(), ArrayVector(values));
USE(instr); USE(instr);
DCHECK(instr->HasObservableSideEffects()); DCHECK(instr->HasObservableSideEffects());
Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);

View File

@ -65,6 +65,8 @@ int FeedbackMetadata::GetSlotSize(FeedbackSlotKind kind) {
case FeedbackSlotKind::kStoreNamedSloppy: case FeedbackSlotKind::kStoreNamedSloppy:
case FeedbackSlotKind::kStoreNamedStrict: case FeedbackSlotKind::kStoreNamedStrict:
case FeedbackSlotKind::kStoreOwnNamed: case FeedbackSlotKind::kStoreOwnNamed:
case FeedbackSlotKind::kStoreGlobalSloppy:
case FeedbackSlotKind::kStoreGlobalStrict:
case FeedbackSlotKind::kStoreKeyedSloppy: case FeedbackSlotKind::kStoreKeyedSloppy:
case FeedbackSlotKind::kStoreKeyedStrict: case FeedbackSlotKind::kStoreKeyedStrict:
case FeedbackSlotKind::kStoreDataPropertyInLiteral: case FeedbackSlotKind::kStoreDataPropertyInLiteral:
@ -185,6 +187,8 @@ void FeedbackVector::ComputeCounts(int* with_type_info, int* generic,
case FeedbackSlotKind::kStoreNamedSloppy: case FeedbackSlotKind::kStoreNamedSloppy:
case FeedbackSlotKind::kStoreNamedStrict: case FeedbackSlotKind::kStoreNamedStrict:
case FeedbackSlotKind::kStoreOwnNamed: case FeedbackSlotKind::kStoreOwnNamed:
case FeedbackSlotKind::kStoreGlobalSloppy:
case FeedbackSlotKind::kStoreGlobalStrict:
case FeedbackSlotKind::kStoreKeyedSloppy: case FeedbackSlotKind::kStoreKeyedSloppy:
case FeedbackSlotKind::kStoreKeyedStrict: case FeedbackSlotKind::kStoreKeyedStrict:
case FeedbackSlotKind::kStoreDataPropertyInLiteral: case FeedbackSlotKind::kStoreDataPropertyInLiteral:

View File

@ -116,43 +116,47 @@ bool FeedbackMetadata::SpecDiffersFrom(
const char* FeedbackMetadata::Kind2String(FeedbackSlotKind kind) { const char* FeedbackMetadata::Kind2String(FeedbackSlotKind kind) {
switch (kind) { switch (kind) {
case FeedbackSlotKind::kInvalid: case FeedbackSlotKind::kInvalid:
return "INVALID"; return "Invalid";
case FeedbackSlotKind::kCall: case FeedbackSlotKind::kCall:
return "CALL_IC"; return "Call";
case FeedbackSlotKind::kLoadProperty: case FeedbackSlotKind::kLoadProperty:
return "LOAD_IC"; return "LoadProperty";
case FeedbackSlotKind::kLoadGlobalInsideTypeof: case FeedbackSlotKind::kLoadGlobalInsideTypeof:
return "LOAD_GLOBAL_INSIDE_TYPEOF_IC"; return "LoadGlobalInsideTypeof";
case FeedbackSlotKind::kLoadGlobalNotInsideTypeof: case FeedbackSlotKind::kLoadGlobalNotInsideTypeof:
return "LOAD_GLOBAL_NOT_INSIDE_TYPEOF_IC"; return "LoadGlobalNotInsideTypeof";
case FeedbackSlotKind::kLoadKeyed: case FeedbackSlotKind::kLoadKeyed:
return "KEYED_LOAD_IC"; return "LoadKeyed";
case FeedbackSlotKind::kStoreNamedSloppy: case FeedbackSlotKind::kStoreNamedSloppy:
return "STORE_SLOPPY_IC"; return "StoreNamedSloppy";
case FeedbackSlotKind::kStoreNamedStrict: case FeedbackSlotKind::kStoreNamedStrict:
return "STORE_STRICT_IC"; return "StoreNamedStrict";
case FeedbackSlotKind::kStoreOwnNamed: case FeedbackSlotKind::kStoreOwnNamed:
return "STORE_OWN_IC"; return "StoreOwnNamed";
case FeedbackSlotKind::kStoreGlobalSloppy:
return "StoreGlobalSloppy";
case FeedbackSlotKind::kStoreGlobalStrict:
return "StoreGlobalStrict";
case FeedbackSlotKind::kStoreKeyedSloppy: case FeedbackSlotKind::kStoreKeyedSloppy:
return "KEYED_STORE_SLOPPY_IC"; return "StoreKeyedSloppy";
case FeedbackSlotKind::kStoreKeyedStrict: case FeedbackSlotKind::kStoreKeyedStrict:
return "KEYED_STORE_STRICT_IC"; return "StoreKeyedStrict";
case FeedbackSlotKind::kBinaryOp: case FeedbackSlotKind::kBinaryOp:
return "INTERPRETER_BINARYOP_IC"; return "BinaryOp";
case FeedbackSlotKind::kCompareOp: case FeedbackSlotKind::kCompareOp:
return "INTERPRETER_COMPARE_IC"; return "CompareOp";
case FeedbackSlotKind::kToBoolean: case FeedbackSlotKind::kToBoolean:
return "TO_BOOLEAN_IC"; return "ToBoolean";
case FeedbackSlotKind::kStoreDataPropertyInLiteral: case FeedbackSlotKind::kStoreDataPropertyInLiteral:
return "STORE_DATA_PROPERTY_IN_LITERAL_IC"; return "StoreDataPropertyInLiteral";
case FeedbackSlotKind::kCreateClosure: case FeedbackSlotKind::kCreateClosure:
return "kCreateClosure"; return "kCreateClosure";
case FeedbackSlotKind::kLiteral: case FeedbackSlotKind::kLiteral:
return "LITERAL"; return "Literal";
case FeedbackSlotKind::kTypeProfile: case FeedbackSlotKind::kTypeProfile:
return "TYPE_PROFILE"; return "TypeProfile";
case FeedbackSlotKind::kGeneral: case FeedbackSlotKind::kGeneral:
return "STUB"; return "General";
case FeedbackSlotKind::kKindsNumber: case FeedbackSlotKind::kKindsNumber:
break; break;
} }
@ -240,6 +244,8 @@ Handle<FeedbackVector> FeedbackVector::New(Isolate* isolate,
case FeedbackSlotKind::kStoreNamedSloppy: case FeedbackSlotKind::kStoreNamedSloppy:
case FeedbackSlotKind::kStoreNamedStrict: case FeedbackSlotKind::kStoreNamedStrict:
case FeedbackSlotKind::kStoreOwnNamed: case FeedbackSlotKind::kStoreOwnNamed:
case FeedbackSlotKind::kStoreGlobalSloppy:
case FeedbackSlotKind::kStoreGlobalStrict:
case FeedbackSlotKind::kStoreKeyedSloppy: case FeedbackSlotKind::kStoreKeyedSloppy:
case FeedbackSlotKind::kStoreKeyedStrict: case FeedbackSlotKind::kStoreKeyedStrict:
case FeedbackSlotKind::kStoreDataPropertyInLiteral: case FeedbackSlotKind::kStoreDataPropertyInLiteral:
@ -341,7 +347,9 @@ void FeedbackVector::ClearSlots(JSFunction* host_function) {
} }
case FeedbackSlotKind::kStoreNamedSloppy: case FeedbackSlotKind::kStoreNamedSloppy:
case FeedbackSlotKind::kStoreNamedStrict: case FeedbackSlotKind::kStoreNamedStrict:
case FeedbackSlotKind::kStoreOwnNamed: { case FeedbackSlotKind::kStoreOwnNamed:
case FeedbackSlotKind::kStoreGlobalSloppy:
case FeedbackSlotKind::kStoreGlobalStrict: {
StoreICNexus nexus(this, slot); StoreICNexus nexus(this, slot);
if (!nexus.IsCleared()) { if (!nexus.IsCleared()) {
nexus.Clear(); nexus.Clear();

View File

@ -27,6 +27,8 @@ enum class FeedbackSlotKind {
kLoadGlobalNotInsideTypeof, kLoadGlobalNotInsideTypeof,
kLoadGlobalInsideTypeof, kLoadGlobalInsideTypeof,
kLoadKeyed, kLoadKeyed,
kStoreGlobalSloppy,
kStoreGlobalStrict,
kStoreNamedSloppy, kStoreNamedSloppy,
kStoreNamedStrict, kStoreNamedStrict,
kStoreOwnNamed, kStoreOwnNamed,
@ -62,6 +64,11 @@ inline bool IsKeyedLoadICKind(FeedbackSlotKind kind) {
return kind == FeedbackSlotKind::kLoadKeyed; return kind == FeedbackSlotKind::kLoadKeyed;
} }
inline bool IsStoreGlobalICKind(FeedbackSlotKind kind) {
return kind == FeedbackSlotKind::kStoreGlobalSloppy ||
kind == FeedbackSlotKind::kStoreGlobalStrict;
}
inline bool IsStoreICKind(FeedbackSlotKind kind) { inline bool IsStoreICKind(FeedbackSlotKind kind) {
return kind == FeedbackSlotKind::kStoreNamedSloppy || return kind == FeedbackSlotKind::kStoreNamedSloppy ||
kind == FeedbackSlotKind::kStoreNamedStrict; kind == FeedbackSlotKind::kStoreNamedStrict;
@ -89,8 +96,9 @@ inline TypeofMode GetTypeofModeFromSlotKind(FeedbackSlotKind kind) {
inline LanguageMode GetLanguageModeFromSlotKind(FeedbackSlotKind kind) { inline LanguageMode GetLanguageModeFromSlotKind(FeedbackSlotKind kind) {
DCHECK(IsStoreICKind(kind) || IsStoreOwnICKind(kind) || DCHECK(IsStoreICKind(kind) || IsStoreOwnICKind(kind) ||
IsKeyedStoreICKind(kind)); IsStoreGlobalICKind(kind) || IsKeyedStoreICKind(kind));
return (kind == FeedbackSlotKind::kStoreNamedSloppy || return (kind == FeedbackSlotKind::kStoreNamedSloppy ||
kind == FeedbackSlotKind::kStoreGlobalSloppy ||
kind == FeedbackSlotKind::kStoreKeyedSloppy) kind == FeedbackSlotKind::kStoreKeyedSloppy)
? SLOPPY ? SLOPPY
: STRICT; : STRICT;
@ -132,6 +140,13 @@ class FeedbackVectorSpecBase {
return AddSlot(FeedbackSlotKind::kStoreOwnNamed); return AddSlot(FeedbackSlotKind::kStoreOwnNamed);
} }
FeedbackSlot AddStoreGlobalICSlot(LanguageMode language_mode) {
STATIC_ASSERT(LANGUAGE_END == 2);
return AddSlot(is_strict(language_mode)
? FeedbackSlotKind::kStoreGlobalStrict
: FeedbackSlotKind::kStoreGlobalSloppy);
}
FeedbackSlot AddKeyedStoreICSlot(LanguageMode language_mode) { FeedbackSlot AddKeyedStoreICSlot(LanguageMode language_mode) {
STATIC_ASSERT(LANGUAGE_END == 2); STATIC_ASSERT(LANGUAGE_END == 2);
return AddSlot(is_strict(language_mode) return AddSlot(is_strict(language_mode)
@ -336,6 +351,7 @@ class FeedbackVector : public FixedArray {
DEFINE_SLOT_KIND_PREDICATE(IsKeyedLoadIC) DEFINE_SLOT_KIND_PREDICATE(IsKeyedLoadIC)
DEFINE_SLOT_KIND_PREDICATE(IsStoreIC) DEFINE_SLOT_KIND_PREDICATE(IsStoreIC)
DEFINE_SLOT_KIND_PREDICATE(IsStoreOwnIC) DEFINE_SLOT_KIND_PREDICATE(IsStoreOwnIC)
DEFINE_SLOT_KIND_PREDICATE(IsStoreGlobalIC)
DEFINE_SLOT_KIND_PREDICATE(IsKeyedStoreIC) DEFINE_SLOT_KIND_PREDICATE(IsKeyedStoreIC)
DEFINE_SLOT_KIND_PREDICATE(IsTypeProfile) DEFINE_SLOT_KIND_PREDICATE(IsTypeProfile)
#undef DEFINE_SLOT_KIND_PREDICATE #undef DEFINE_SLOT_KIND_PREDICATE
@ -616,11 +632,13 @@ class StoreICNexus : public FeedbackNexus {
public: public:
StoreICNexus(Handle<FeedbackVector> vector, FeedbackSlot slot) StoreICNexus(Handle<FeedbackVector> vector, FeedbackSlot slot)
: FeedbackNexus(vector, slot) { : FeedbackNexus(vector, slot) {
DCHECK(vector->IsStoreIC(slot) || vector->IsStoreOwnIC(slot)); DCHECK(vector->IsStoreIC(slot) || vector->IsStoreOwnIC(slot) ||
vector->IsStoreGlobalIC(slot));
} }
StoreICNexus(FeedbackVector* vector, FeedbackSlot slot) StoreICNexus(FeedbackVector* vector, FeedbackSlot slot)
: FeedbackNexus(vector, slot) { : FeedbackNexus(vector, slot) {
DCHECK(vector->IsStoreIC(slot) || vector->IsStoreOwnIC(slot)); DCHECK(vector->IsStoreIC(slot) || vector->IsStoreOwnIC(slot) ||
vector->IsStoreGlobalIC(slot));
} }
void Clear() override { ConfigurePremonomorphic(); } void Clear() override { ConfigurePremonomorphic(); }

View File

@ -1265,7 +1265,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
VisitForAccumulatorValue(value); VisitForAccumulatorValue(value);
DCHECK(StoreDescriptor::ValueRegister().is(r0)); DCHECK(StoreDescriptor::ValueRegister().is(r0));
__ ldr(StoreDescriptor::ReceiverRegister(), MemOperand(sp)); __ ldr(StoreDescriptor::ReceiverRegister(), MemOperand(sp));
CallStoreIC(property->GetSlot(0), key->value(), true); CallStoreIC(property->GetSlot(0), key->value(), kStoreOwn);
PrepareForBailoutForId(key->id(), BailoutState::NO_REGISTERS); PrepareForBailoutForId(key->id(), BailoutState::NO_REGISTERS);
if (NeedsHomeObject(value)) { if (NeedsHomeObject(value)) {
@ -1722,7 +1722,7 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op,
if (var->IsUnallocated()) { if (var->IsUnallocated()) {
// Global var, const, or let. // Global var, const, or let.
__ LoadGlobalObject(StoreDescriptor::ReceiverRegister()); __ LoadGlobalObject(StoreDescriptor::ReceiverRegister());
CallStoreIC(slot, var->name()); CallStoreIC(slot, var->name(), kStoreGlobal);
} else if (IsLexicalVariableMode(var->mode()) && op != Token::INIT) { } else if (IsLexicalVariableMode(var->mode()) && op != Token::INIT) {
DCHECK(!var->IsLookupSlot()); DCHECK(!var->IsLookupSlot());

View File

@ -1251,7 +1251,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
VisitForAccumulatorValue(value); VisitForAccumulatorValue(value);
DCHECK(StoreDescriptor::ValueRegister().is(x0)); DCHECK(StoreDescriptor::ValueRegister().is(x0));
__ Peek(StoreDescriptor::ReceiverRegister(), 0); __ Peek(StoreDescriptor::ReceiverRegister(), 0);
CallStoreIC(property->GetSlot(0), key->value(), true); CallStoreIC(property->GetSlot(0), key->value(), kStoreOwn);
PrepareForBailoutForId(key->id(), BailoutState::NO_REGISTERS); PrepareForBailoutForId(key->id(), BailoutState::NO_REGISTERS);
if (NeedsHomeObject(value)) { if (NeedsHomeObject(value)) {
@ -1669,7 +1669,7 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op,
if (var->IsUnallocated()) { if (var->IsUnallocated()) {
// Global var, const, or let. // Global var, const, or let.
__ LoadGlobalObject(StoreDescriptor::ReceiverRegister()); __ LoadGlobalObject(StoreDescriptor::ReceiverRegister());
CallStoreIC(slot, var->name()); CallStoreIC(slot, var->name(), kStoreGlobal);
} else if (IsLexicalVariableMode(var->mode()) && op != Token::INIT) { } else if (IsLexicalVariableMode(var->mode()) && op != Token::INIT) {
DCHECK(!var->IsLookupSlot()); DCHECK(!var->IsLookupSlot());

View File

@ -217,7 +217,7 @@ void FullCodeGenerator::CallLoadIC(FeedbackSlot slot, Handle<Object> name) {
} }
void FullCodeGenerator::CallStoreIC(FeedbackSlot slot, Handle<Object> name, void FullCodeGenerator::CallStoreIC(FeedbackSlot slot, Handle<Object> name,
bool store_own_property) { StoreICKind store_ic_kind) {
DCHECK(name->IsName()); DCHECK(name->IsName());
__ Move(StoreDescriptor::NameRegister(), name); __ Move(StoreDescriptor::NameRegister(), name);
@ -231,16 +231,26 @@ void FullCodeGenerator::CallStoreIC(FeedbackSlot slot, Handle<Object> name,
} }
Handle<Code> code; Handle<Code> code;
if (store_own_property) { switch (store_ic_kind) {
DCHECK_EQ(FeedbackSlotKind::kStoreOwnNamed, case kStoreOwn:
feedback_vector_spec()->GetKind(slot)); DCHECK_EQ(FeedbackSlotKind::kStoreOwnNamed,
code = CodeFactory::StoreOwnIC(isolate()).code(); feedback_vector_spec()->GetKind(slot));
} else { code = CodeFactory::StoreOwnIC(isolate()).code();
// Ensure that language mode is in sync with the IC slot kind. break;
DCHECK_EQ( case kStoreGlobal:
GetLanguageModeFromSlotKind(feedback_vector_spec()->GetKind(slot)), // Ensure that language mode is in sync with the IC slot kind.
language_mode()); DCHECK_EQ(
code = CodeFactory::StoreIC(isolate(), language_mode()).code(); GetLanguageModeFromSlotKind(feedback_vector_spec()->GetKind(slot)),
language_mode());
code = CodeFactory::StoreGlobalIC(isolate(), language_mode()).code();
break;
case kStoreNamed:
// Ensure that language mode is in sync with the IC slot kind.
DCHECK_EQ(
GetLanguageModeFromSlotKind(feedback_vector_spec()->GetKind(slot)),
language_mode());
code = CodeFactory::StoreIC(isolate(), language_mode()).code();
break;
} }
__ Call(code, RelocInfo::CODE_TARGET); __ Call(code, RelocInfo::CODE_TARGET);
RestoreContext(); RestoreContext();

View File

@ -512,8 +512,9 @@ class FullCodeGenerator final : public AstVisitor<FullCodeGenerator> {
TypeFeedbackId id = TypeFeedbackId::None()); TypeFeedbackId id = TypeFeedbackId::None());
void CallLoadIC(FeedbackSlot slot, Handle<Object> name); void CallLoadIC(FeedbackSlot slot, Handle<Object> name);
enum StoreICKind { kStoreNamed, kStoreOwn, kStoreGlobal };
void CallStoreIC(FeedbackSlot slot, Handle<Object> name, void CallStoreIC(FeedbackSlot slot, Handle<Object> name,
bool store_own_property = false); StoreICKind store_ic_kind = kStoreNamed);
void CallKeyedStoreIC(FeedbackSlot slot); void CallKeyedStoreIC(FeedbackSlot slot);
void SetFunctionPosition(FunctionLiteral* fun); void SetFunctionPosition(FunctionLiteral* fun);

View File

@ -1193,7 +1193,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
VisitForAccumulatorValue(value); VisitForAccumulatorValue(value);
DCHECK(StoreDescriptor::ValueRegister().is(eax)); DCHECK(StoreDescriptor::ValueRegister().is(eax));
__ mov(StoreDescriptor::ReceiverRegister(), Operand(esp, 0)); __ mov(StoreDescriptor::ReceiverRegister(), Operand(esp, 0));
CallStoreIC(property->GetSlot(0), key->value(), true); CallStoreIC(property->GetSlot(0), key->value(), kStoreOwn);
PrepareForBailoutForId(key->id(), BailoutState::NO_REGISTERS); PrepareForBailoutForId(key->id(), BailoutState::NO_REGISTERS);
if (NeedsHomeObject(value)) { if (NeedsHomeObject(value)) {
EmitSetHomeObjectAccumulator(value, 0, property->GetSlot(1)); EmitSetHomeObjectAccumulator(value, 0, property->GetSlot(1));
@ -1645,7 +1645,7 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op,
__ mov(StoreDescriptor::ReceiverRegister(), __ mov(StoreDescriptor::ReceiverRegister(),
ContextOperand(StoreDescriptor::ReceiverRegister(), ContextOperand(StoreDescriptor::ReceiverRegister(),
Context::EXTENSION_INDEX)); Context::EXTENSION_INDEX));
CallStoreIC(slot, var->name()); CallStoreIC(slot, var->name(), kStoreGlobal);
} else if (IsLexicalVariableMode(var->mode()) && op != Token::INIT) { } else if (IsLexicalVariableMode(var->mode()) && op != Token::INIT) {
DCHECK(!var->IsLookupSlot()); DCHECK(!var->IsLookupSlot());

View File

@ -1262,7 +1262,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
__ mov(StoreDescriptor::ValueRegister(), result_register()); __ mov(StoreDescriptor::ValueRegister(), result_register());
DCHECK(StoreDescriptor::ValueRegister().is(a0)); DCHECK(StoreDescriptor::ValueRegister().is(a0));
__ lw(StoreDescriptor::ReceiverRegister(), MemOperand(sp)); __ lw(StoreDescriptor::ReceiverRegister(), MemOperand(sp));
CallStoreIC(property->GetSlot(0), key->value(), true); CallStoreIC(property->GetSlot(0), key->value(), kStoreOwn);
PrepareForBailoutForId(key->id(), BailoutState::NO_REGISTERS); PrepareForBailoutForId(key->id(), BailoutState::NO_REGISTERS);
if (NeedsHomeObject(value)) { if (NeedsHomeObject(value)) {
@ -1733,7 +1733,7 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op,
// Global var, const, or let. // Global var, const, or let.
__ mov(StoreDescriptor::ValueRegister(), result_register()); __ mov(StoreDescriptor::ValueRegister(), result_register());
__ LoadGlobalObject(StoreDescriptor::ReceiverRegister()); __ LoadGlobalObject(StoreDescriptor::ReceiverRegister());
CallStoreIC(slot, var->name()); CallStoreIC(slot, var->name(), kStoreGlobal);
} else if (IsLexicalVariableMode(var->mode()) && op != Token::INIT) { } else if (IsLexicalVariableMode(var->mode()) && op != Token::INIT) {
DCHECK(!var->IsLookupSlot()); DCHECK(!var->IsLookupSlot());

View File

@ -1264,7 +1264,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
__ mov(StoreDescriptor::ValueRegister(), result_register()); __ mov(StoreDescriptor::ValueRegister(), result_register());
DCHECK(StoreDescriptor::ValueRegister().is(a0)); DCHECK(StoreDescriptor::ValueRegister().is(a0));
__ ld(StoreDescriptor::ReceiverRegister(), MemOperand(sp)); __ ld(StoreDescriptor::ReceiverRegister(), MemOperand(sp));
CallStoreIC(property->GetSlot(0), key->value(), true); CallStoreIC(property->GetSlot(0), key->value(), kStoreOwn);
PrepareForBailoutForId(key->id(), BailoutState::NO_REGISTERS); PrepareForBailoutForId(key->id(), BailoutState::NO_REGISTERS);
if (NeedsHomeObject(value)) { if (NeedsHomeObject(value)) {
@ -1734,7 +1734,7 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op,
// Global var, const, or let. // Global var, const, or let.
__ mov(StoreDescriptor::ValueRegister(), result_register()); __ mov(StoreDescriptor::ValueRegister(), result_register());
__ LoadGlobalObject(StoreDescriptor::ReceiverRegister()); __ LoadGlobalObject(StoreDescriptor::ReceiverRegister());
CallStoreIC(slot, var->name()); CallStoreIC(slot, var->name(), kStoreGlobal);
} else if (IsLexicalVariableMode(var->mode()) && op != Token::INIT) { } else if (IsLexicalVariableMode(var->mode()) && op != Token::INIT) {
DCHECK(!var->IsLookupSlot()); DCHECK(!var->IsLookupSlot());

View File

@ -1232,7 +1232,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
VisitForAccumulatorValue(value); VisitForAccumulatorValue(value);
DCHECK(StoreDescriptor::ValueRegister().is(r3)); DCHECK(StoreDescriptor::ValueRegister().is(r3));
__ LoadP(StoreDescriptor::ReceiverRegister(), MemOperand(sp)); __ LoadP(StoreDescriptor::ReceiverRegister(), MemOperand(sp));
CallStoreIC(property->GetSlot(0), key->value(), true); CallStoreIC(property->GetSlot(0), key->value(), kStoreOwn);
PrepareForBailoutForId(key->id(), BailoutState::NO_REGISTERS); PrepareForBailoutForId(key->id(), BailoutState::NO_REGISTERS);
if (NeedsHomeObject(value)) { if (NeedsHomeObject(value)) {
@ -1731,7 +1731,7 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op,
if (var->IsUnallocated()) { if (var->IsUnallocated()) {
// Global var, const, or let. // Global var, const, or let.
__ LoadGlobalObject(StoreDescriptor::ReceiverRegister()); __ LoadGlobalObject(StoreDescriptor::ReceiverRegister());
CallStoreIC(slot, var->name()); CallStoreIC(slot, var->name(), kStoreGlobal);
} else if (IsLexicalVariableMode(var->mode()) && op != Token::INIT) { } else if (IsLexicalVariableMode(var->mode()) && op != Token::INIT) {
DCHECK(!var->IsLookupSlot()); DCHECK(!var->IsLookupSlot());

View File

@ -1197,7 +1197,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
VisitForAccumulatorValue(value); VisitForAccumulatorValue(value);
DCHECK(StoreDescriptor::ValueRegister().is(r2)); DCHECK(StoreDescriptor::ValueRegister().is(r2));
__ LoadP(StoreDescriptor::ReceiverRegister(), MemOperand(sp)); __ LoadP(StoreDescriptor::ReceiverRegister(), MemOperand(sp));
CallStoreIC(property->GetSlot(0), key->value(), true); CallStoreIC(property->GetSlot(0), key->value(), kStoreOwn);
PrepareForBailoutForId(key->id(), BailoutState::NO_REGISTERS); PrepareForBailoutForId(key->id(), BailoutState::NO_REGISTERS);
if (NeedsHomeObject(value)) { if (NeedsHomeObject(value)) {
@ -1704,7 +1704,7 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op,
if (var->IsUnallocated()) { if (var->IsUnallocated()) {
// Global var, const, or let. // Global var, const, or let.
__ LoadGlobalObject(StoreDescriptor::ReceiverRegister()); __ LoadGlobalObject(StoreDescriptor::ReceiverRegister());
CallStoreIC(slot, var->name()); CallStoreIC(slot, var->name(), kStoreGlobal);
} else if (IsLexicalVariableMode(var->mode()) && op != Token::INIT) { } else if (IsLexicalVariableMode(var->mode()) && op != Token::INIT) {
// Non-initializing assignment to let variable needs a write barrier. // Non-initializing assignment to let variable needs a write barrier.

View File

@ -1224,7 +1224,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
VisitForAccumulatorValue(value); VisitForAccumulatorValue(value);
DCHECK(StoreDescriptor::ValueRegister().is(rax)); DCHECK(StoreDescriptor::ValueRegister().is(rax));
__ movp(StoreDescriptor::ReceiverRegister(), Operand(rsp, 0)); __ movp(StoreDescriptor::ReceiverRegister(), Operand(rsp, 0));
CallStoreIC(property->GetSlot(0), key->value(), true); CallStoreIC(property->GetSlot(0), key->value(), kStoreOwn);
PrepareForBailoutForId(key->id(), BailoutState::NO_REGISTERS); PrepareForBailoutForId(key->id(), BailoutState::NO_REGISTERS);
if (NeedsHomeObject(value)) { if (NeedsHomeObject(value)) {
@ -1636,7 +1636,7 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op,
if (var->IsUnallocated()) { if (var->IsUnallocated()) {
// Global var, const, or let. // Global var, const, or let.
__ LoadGlobalObject(StoreDescriptor::ReceiverRegister()); __ LoadGlobalObject(StoreDescriptor::ReceiverRegister());
CallStoreIC(slot, var->name()); CallStoreIC(slot, var->name(), kStoreGlobal);
} else if (IsLexicalVariableMode(var->mode()) && op != Token::INIT) { } else if (IsLexicalVariableMode(var->mode()) && op != Token::INIT) {
DCHECK(!var->IsLookupSlot()); DCHECK(!var->IsLookupSlot());

View File

@ -1183,7 +1183,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
VisitForAccumulatorValue(value); VisitForAccumulatorValue(value);
DCHECK(StoreDescriptor::ValueRegister().is(eax)); DCHECK(StoreDescriptor::ValueRegister().is(eax));
__ mov(StoreDescriptor::ReceiverRegister(), Operand(esp, 0)); __ mov(StoreDescriptor::ReceiverRegister(), Operand(esp, 0));
CallStoreIC(property->GetSlot(0), key->value(), true); CallStoreIC(property->GetSlot(0), key->value(), kStoreOwn);
PrepareForBailoutForId(key->id(), BailoutState::NO_REGISTERS); PrepareForBailoutForId(key->id(), BailoutState::NO_REGISTERS);
if (NeedsHomeObject(value)) { if (NeedsHomeObject(value)) {
EmitSetHomeObjectAccumulator(value, 0, property->GetSlot(1)); EmitSetHomeObjectAccumulator(value, 0, property->GetSlot(1));
@ -1635,7 +1635,7 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op,
__ mov(StoreDescriptor::ReceiverRegister(), __ mov(StoreDescriptor::ReceiverRegister(),
ContextOperand(StoreDescriptor::ReceiverRegister(), ContextOperand(StoreDescriptor::ReceiverRegister(),
Context::EXTENSION_INDEX)); Context::EXTENSION_INDEX));
CallStoreIC(slot, var->name()); CallStoreIC(slot, var->name(), kStoreGlobal);
} else if (IsLexicalVariableMode(var->mode()) && op != Token::INIT) { } else if (IsLexicalVariableMode(var->mode()) && op != Token::INIT) {
DCHECK(!var->IsLookupSlot()); DCHECK(!var->IsLookupSlot());

View File

@ -1471,46 +1471,51 @@ bool StoreIC::LookupForWrite(LookupIterator* it, Handle<Object> value,
return it->IsCacheableTransition(); return it->IsCacheableTransition();
} }
MaybeHandle<Object> StoreGlobalIC::Store(Handle<Object> object,
Handle<Name> name,
Handle<Object> value) {
DCHECK(object->IsJSGlobalObject());
DCHECK(name->IsString());
// Look up in script context table.
Handle<String> str_name = Handle<String>::cast(name);
Handle<JSGlobalObject> global = Handle<JSGlobalObject>::cast(object);
Handle<ScriptContextTable> script_contexts(
global->native_context()->script_context_table());
ScriptContextTable::LookupResult lookup_result;
if (ScriptContextTable::Lookup(script_contexts, str_name, &lookup_result)) {
Handle<Context> script_context = ScriptContextTable::GetContext(
script_contexts, lookup_result.context_index);
if (lookup_result.mode == CONST) {
return TypeError(MessageTemplate::kConstAssign, object, name);
}
Handle<Object> previous_value =
FixedArray::get(*script_context, lookup_result.slot_index, isolate());
if (previous_value->IsTheHole(isolate())) {
// Do not install stubs and stay pre-monomorphic for
// uninitialized accesses.
return ReferenceError(name);
}
if (FLAG_use_ic && StoreScriptContextFieldStub::Accepted(&lookup_result)) {
TRACE_HANDLER_STATS(isolate(), StoreIC_StoreScriptContextFieldStub);
StoreScriptContextFieldStub stub(isolate(), &lookup_result);
PatchCache(name, stub.GetCode());
}
script_context->set(lookup_result.slot_index, *value);
return value;
}
return StoreIC::Store(object, name, value);
}
MaybeHandle<Object> StoreIC::Store(Handle<Object> object, Handle<Name> name, MaybeHandle<Object> StoreIC::Store(Handle<Object> object, Handle<Name> name,
Handle<Object> value, Handle<Object> value,
JSReceiver::StoreFromKeyed store_mode) { JSReceiver::StoreFromKeyed store_mode) {
if (object->IsJSGlobalObject() && name->IsString()) {
// Look up in script context table.
Handle<String> str_name = Handle<String>::cast(name);
Handle<JSGlobalObject> global = Handle<JSGlobalObject>::cast(object);
Handle<ScriptContextTable> script_contexts(
global->native_context()->script_context_table());
ScriptContextTable::LookupResult lookup_result;
if (ScriptContextTable::Lookup(script_contexts, str_name, &lookup_result)) {
Handle<Context> script_context = ScriptContextTable::GetContext(
script_contexts, lookup_result.context_index);
if (lookup_result.mode == CONST) {
return TypeError(MessageTemplate::kConstAssign, object, name);
}
Handle<Object> previous_value =
FixedArray::get(*script_context, lookup_result.slot_index, isolate());
if (previous_value->IsTheHole(isolate())) {
// Do not install stubs and stay pre-monomorphic for
// uninitialized accesses.
return ReferenceError(name);
}
if (FLAG_use_ic &&
StoreScriptContextFieldStub::Accepted(&lookup_result)) {
TRACE_HANDLER_STATS(isolate(), StoreIC_StoreScriptContextFieldStub);
StoreScriptContextFieldStub stub(isolate(), &lookup_result);
PatchCache(name, stub.GetCode());
}
script_context->set(lookup_result.slot_index, *value);
return value;
}
}
// TODO(verwaest): Let SetProperty do the migration, since storing a property // TODO(verwaest): Let SetProperty do the migration, since storing a property
// might deprecate the current map again, if value does not fit. // might deprecate the current map again, if value does not fit.
if (MigrateDeprecated(object) || object->IsJSProxy()) { if (MigrateDeprecated(object) || object->IsJSProxy()) {
@ -2361,6 +2366,11 @@ RUNTIME_FUNCTION(Runtime_StoreIC_Miss) {
StoreIC ic(isolate, &nexus); StoreIC ic(isolate, &nexus);
ic.UpdateState(receiver, key); ic.UpdateState(receiver, key);
RETURN_RESULT_OR_FAILURE(isolate, ic.Store(receiver, key, value)); RETURN_RESULT_OR_FAILURE(isolate, ic.Store(receiver, key, value));
} else if (IsStoreGlobalICKind(kind)) {
StoreICNexus nexus(vector, vector_slot);
StoreGlobalIC ic(isolate, &nexus);
ic.UpdateState(receiver, key);
RETURN_RESULT_OR_FAILURE(isolate, ic.Store(receiver, key, value));
} else { } else {
DCHECK(IsKeyedStoreICKind(kind)); DCHECK(IsKeyedStoreICKind(kind));
KeyedStoreICNexus nexus(vector, vector_slot); KeyedStoreICNexus nexus(vector, vector_slot);

View File

@ -55,7 +55,8 @@ class IC {
return IsLoadIC() || IsLoadGlobalIC() || IsKeyedLoadIC(); return IsLoadIC() || IsLoadGlobalIC() || IsKeyedLoadIC();
} }
bool IsAnyStore() const { bool IsAnyStore() const {
return IsStoreIC() || IsStoreOwnIC() || IsKeyedStoreIC(); return IsStoreIC() || IsStoreOwnIC() || IsStoreGlobalIC() ||
IsKeyedStoreIC();
} }
// The ICs that don't pass slot and vector through the stack have to // The ICs that don't pass slot and vector through the stack have to
@ -140,6 +141,7 @@ class IC {
bool IsLoadIC() const { return IsLoadICKind(kind_); } bool IsLoadIC() const { return IsLoadICKind(kind_); }
bool IsLoadGlobalIC() const { return IsLoadGlobalICKind(kind_); } bool IsLoadGlobalIC() const { return IsLoadGlobalICKind(kind_); }
bool IsKeyedLoadIC() const { return IsKeyedLoadICKind(kind_); } bool IsKeyedLoadIC() const { return IsKeyedLoadICKind(kind_); }
bool IsStoreGlobalIC() const { return IsStoreGlobalICKind(kind_); }
bool IsStoreIC() const { return IsStoreICKind(kind_); } bool IsStoreIC() const { return IsStoreICKind(kind_); }
bool IsStoreOwnIC() const { return IsStoreOwnICKind(kind_); } bool IsStoreOwnIC() const { return IsStoreOwnICKind(kind_); }
bool IsKeyedStoreIC() const { return IsKeyedStoreICKind(kind_); } bool IsKeyedStoreIC() const { return IsKeyedStoreICKind(kind_); }
@ -348,7 +350,7 @@ class StoreIC : public IC {
protected: protected:
// Stub accessors. // Stub accessors.
Handle<Code> slow_stub() const { Handle<Code> slow_stub() const {
// StoreIC and KeyedStoreIC share the same slow stub. // All StoreICs share the same slow stub.
return isolate()->builtins()->KeyedStoreIC_Slow(); return isolate()->builtins()->KeyedStoreIC_Slow();
} }
@ -367,6 +369,15 @@ class StoreIC : public IC {
friend class IC; friend class IC;
}; };
class StoreGlobalIC : public StoreIC {
public:
StoreGlobalIC(Isolate* isolate, FeedbackNexus* nexus)
: StoreIC(isolate, nexus) {}
MUST_USE_RESULT MaybeHandle<Object> Store(Handle<Object> object,
Handle<Name> name,
Handle<Object> value);
};
enum KeyedStoreCheckMap { kDontCheckMap, kCheckMap }; enum KeyedStoreCheckMap { kDontCheckMap, kCheckMap };

View File

@ -388,7 +388,7 @@ void InterpreterGenerator::DoStaGlobal(Callable ic,
// Store the value in the accumulator into the global with name in constant pool // Store the value in the accumulator into the global with name in constant pool
// entry <name_index> using FeedBackVector slot <slot> in sloppy mode. // entry <name_index> using FeedBackVector slot <slot> in sloppy mode.
void InterpreterGenerator::DoStaGlobalSloppy(InterpreterAssembler* assembler) { void InterpreterGenerator::DoStaGlobalSloppy(InterpreterAssembler* assembler) {
Callable ic = CodeFactory::StoreICInOptimizedCode(isolate_, SLOPPY); Callable ic = CodeFactory::StoreGlobalICInOptimizedCode(isolate_, SLOPPY);
DoStaGlobal(ic, assembler); DoStaGlobal(ic, assembler);
} }
@ -397,7 +397,7 @@ void InterpreterGenerator::DoStaGlobalSloppy(InterpreterAssembler* assembler) {
// Store the value in the accumulator into the global with name in constant pool // Store the value in the accumulator into the global with name in constant pool
// entry <name_index> using FeedBackVector slot <slot> in strict mode. // entry <name_index> using FeedBackVector slot <slot> in strict mode.
void InterpreterGenerator::DoStaGlobalStrict(InterpreterAssembler* assembler) { void InterpreterGenerator::DoStaGlobalStrict(InterpreterAssembler* assembler) {
Callable ic = CodeFactory::StoreICInOptimizedCode(isolate_, STRICT); Callable ic = CodeFactory::StoreGlobalICInOptimizedCode(isolate_, STRICT);
DoStaGlobal(ic, assembler); DoStaGlobal(ic, assembler);
} }

View File

@ -1566,6 +1566,10 @@ void Logger::LogCodeObject(Object* object) {
description = "A store IC from the snapshot"; description = "A store IC from the snapshot";
tag = CodeEventListener::STORE_IC_TAG; tag = CodeEventListener::STORE_IC_TAG;
break; break;
case AbstractCode::STORE_GLOBAL_IC:
description = "A store global IC from the snapshot";
tag = CodeEventListener::STORE_GLOBAL_IC_TAG;
break;
case AbstractCode::KEYED_STORE_IC: case AbstractCode::KEYED_STORE_IC:
description = "A keyed store IC from the snapshot"; description = "A keyed store IC from the snapshot";
tag = CodeEventListener::KEYED_STORE_IC_TAG; tag = CodeEventListener::KEYED_STORE_IC_TAG;

View File

@ -722,7 +722,9 @@ void FeedbackVector::FeedbackVectorPrint(std::ostream& os) { // NOLINT
} }
case FeedbackSlotKind::kStoreNamedSloppy: case FeedbackSlotKind::kStoreNamedSloppy:
case FeedbackSlotKind::kStoreNamedStrict: case FeedbackSlotKind::kStoreNamedStrict:
case FeedbackSlotKind::kStoreOwnNamed: { case FeedbackSlotKind::kStoreOwnNamed:
case FeedbackSlotKind::kStoreGlobalSloppy:
case FeedbackSlotKind::kStoreGlobalStrict: {
StoreICNexus nexus(this, slot); StoreICNexus nexus(this, slot);
os << Code::ICState2String(nexus.StateFromFeedback()); os << Code::ICState2String(nexus.StateFromFeedback());
break; break;

View File

@ -4877,6 +4877,7 @@ class Code: public HeapObject {
V(LOAD_GLOBAL_IC) \ V(LOAD_GLOBAL_IC) \
V(KEYED_LOAD_IC) \ V(KEYED_LOAD_IC) \
V(STORE_IC) \ V(STORE_IC) \
V(STORE_GLOBAL_IC) \
V(KEYED_STORE_IC) \ V(KEYED_STORE_IC) \
V(BINARY_OP_IC) \ V(BINARY_OP_IC) \
V(COMPARE_IC) \ V(COMPARE_IC) \

View File

@ -89,7 +89,7 @@ InlineCacheState TypeFeedbackOracle::LoadInlineCacheState(FeedbackSlot slot) {
bool TypeFeedbackOracle::StoreIsUninitialized(FeedbackSlot slot) { bool TypeFeedbackOracle::StoreIsUninitialized(FeedbackSlot slot) {
if (!slot.IsInvalid()) { if (!slot.IsInvalid()) {
FeedbackSlotKind kind = feedback_vector_->GetKind(slot); FeedbackSlotKind kind = feedback_vector_->GetKind(slot);
if (IsStoreICKind(kind)) { if (IsStoreICKind(kind) || IsStoreGlobalICKind(kind)) {
StoreICNexus nexus(feedback_vector_, slot); StoreICNexus nexus(feedback_vector_, slot);
return nexus.StateFromFeedback() == UNINITIALIZED; return nexus.StateFromFeedback() == UNINITIALIZED;
} else if (IsKeyedStoreICKind(kind)) { } else if (IsKeyedStoreICKind(kind)) {
@ -454,7 +454,8 @@ void TypeFeedbackOracle::CollectReceiverTypes(StubCache* stub_cache,
void TypeFeedbackOracle::CollectReceiverTypes(FeedbackSlot slot, void TypeFeedbackOracle::CollectReceiverTypes(FeedbackSlot slot,
SmallMapList* types) { SmallMapList* types) {
FeedbackSlotKind kind = feedback_vector_->GetKind(slot); FeedbackSlotKind kind = feedback_vector_->GetKind(slot);
if (IsStoreICKind(kind) || IsStoreOwnICKind(kind)) { if (IsStoreICKind(kind) || IsStoreOwnICKind(kind) ||
IsStoreGlobalICKind(kind)) {
StoreICNexus nexus(feedback_vector_, slot); StoreICNexus nexus(feedback_vector_, slot);
CollectReceiverTypes(&nexus, types); CollectReceiverTypes(&nexus, types);
} else { } else {

View File

@ -481,9 +481,9 @@ TEST(ReferenceContextAllocatesNoSlots) {
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(4, helper.slot_count());
CHECK_SLOT_KIND(helper, 0, FeedbackSlotKind::kStoreNamedSloppy); 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::kStoreNamedSloppy); CHECK_SLOT_KIND(helper, 2, FeedbackSlotKind::kStoreGlobalSloppy);
CHECK_SLOT_KIND(helper, 3, FeedbackSlotKind::kLoadGlobalNotInsideTypeof); CHECK_SLOT_KIND(helper, 3, FeedbackSlotKind::kLoadGlobalNotInsideTypeof);
} }