[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:
parent
083a8d7209
commit
16c38aa820
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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") \
|
||||||
|
@ -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) {
|
||||||
|
@ -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);
|
||||||
|
@ -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 =
|
||||||
|
@ -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);
|
||||||
|
@ -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:
|
||||||
|
@ -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();
|
||||||
|
@ -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(); }
|
||||||
|
@ -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());
|
||||||
|
@ -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());
|
||||||
|
@ -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();
|
||||||
|
@ -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);
|
||||||
|
@ -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());
|
||||||
|
@ -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());
|
||||||
|
@ -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());
|
||||||
|
@ -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());
|
||||||
|
@ -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.
|
||||||
|
@ -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());
|
||||||
|
@ -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());
|
||||||
|
82
src/ic/ic.cc
82
src/ic/ic.cc
@ -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);
|
||||||
|
15
src/ic/ic.h
15
src/ic/ic.h
@ -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 };
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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) \
|
||||||
|
@ -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 {
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user