Commit 9fa2a371 authored by Franziska Hinkelmann's avatar Franziska Hinkelmann Committed by Commit Bot

Revert "[ic] Migrate StoreGlobal to data handler"

This reverts commit ea4346be.

Reason for revert: This causes a crash in a Node.js test (parallel/test-repl-options). I can reproduce the crash locally. At a first glance, it doesn't look like we're doing anything terribly wrong in Node that explains the crash. I'll have a closer lock tomorrow. Feel free to reland if needed, we can always deactivate the test.  

Original change's description:
> [ic] Migrate StoreGlobal to data handler
> 
> BUG=v8:5561
> 
> Change-Id: If4c679c97af199ce1c90d055627186123bc88574
> Reviewed-on: https://chromium-review.googlesource.com/456698
> Reviewed-by: Igor Sheludko <ishell@chromium.org>
> Commit-Queue: Toon Verwaest <verwaest@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#43944}

TBR=ishell@chromium.org,verwaest@chromium.org,v8-reviews@googlegroups.com
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=v8:5561

Change-Id: I790ff9ab45016749fe2f3982045f497a995e282e
Reviewed-on: https://chromium-review.googlesource.com/456505Reviewed-by: 's avatarFranziska Hinkelmann <franzih@chromium.org>
Commit-Queue: Franziska Hinkelmann <franzih@chromium.org>
Cr-Commit-Position: refs/heads/master@{#43951}
parent bb7fc73d
...@@ -2960,7 +2960,7 @@ Node* CodeStubAssembler::IsJSArray(Node* object) { ...@@ -2960,7 +2960,7 @@ Node* CodeStubAssembler::IsJSArray(Node* object) {
} }
Node* CodeStubAssembler::IsWeakCell(Node* object) { Node* CodeStubAssembler::IsWeakCell(Node* object) {
return IsWeakCellMap(LoadMap(object)); return HasInstanceType(object, WEAK_CELL_TYPE);
} }
Node* CodeStubAssembler::IsBoolean(Node* object) { Node* CodeStubAssembler::IsBoolean(Node* object) {
......
...@@ -48,8 +48,7 @@ enum class PrimitiveType { kBoolean, kNumber, kString, kSymbol }; ...@@ -48,8 +48,7 @@ enum class PrimitiveType { kBoolean, kNumber, kString, kSymbol };
V(TrueValue, True) \ V(TrueValue, True) \
V(Tuple2Map, Tuple2Map) \ V(Tuple2Map, Tuple2Map) \
V(Tuple3Map, Tuple3Map) \ V(Tuple3Map, Tuple3Map) \
V(UndefinedValue, Undefined) \ V(UndefinedValue, Undefined)
V(WeakCellMap, WeakCellMap)
// Provides JavaScript-specific "macro-assembler" functionality on top of the // Provides JavaScript-specific "macro-assembler" functionality on top of the
// CodeAssembler. By factoring the JavaScript-isms out of the CodeAssembler, // CodeAssembler. By factoring the JavaScript-isms out of the CodeAssembler,
......
...@@ -1490,6 +1490,88 @@ void SubStringStub::GenerateAssembly( ...@@ -1490,6 +1490,88 @@ void SubStringStub::GenerateAssembly(
assembler.Parameter(Descriptor::kContext))); assembler.Parameter(Descriptor::kContext)));
} }
void StoreGlobalStub::GenerateAssembly(
compiler::CodeAssemblerState* state) const {
typedef CodeStubAssembler::Label Label;
typedef compiler::Node Node;
CodeStubAssembler assembler(state);
assembler.Comment("StoreGlobalStub: cell_type=%d, constant_type=%d",
cell_type(),
PropertyCellType::kConstantType == cell_type()
? static_cast<int>(constant_type())
: -1);
Node* receiver = assembler.Parameter(Descriptor::kReceiver);
Node* name = assembler.Parameter(Descriptor::kName);
Node* value = assembler.Parameter(Descriptor::kValue);
Node* slot = assembler.Parameter(Descriptor::kSlot);
Node* vector = assembler.Parameter(Descriptor::kVector);
Node* context = assembler.Parameter(Descriptor::kContext);
Label miss(&assembler);
Node* weak_cell = assembler.HeapConstant(isolate()->factory()->NewWeakCell(
StoreGlobalStub::property_cell_placeholder(isolate())));
Node* cell = assembler.LoadWeakCellValue(weak_cell);
assembler.GotoIf(assembler.TaggedIsSmi(cell), &miss);
// Load the payload of the global parameter cell. A hole indicates that the
// cell has been invalidated and that the store must be handled by the
// runtime.
Node* cell_contents =
assembler.LoadObjectField(cell, PropertyCell::kValueOffset);
PropertyCellType cell_type = this->cell_type();
if (cell_type == PropertyCellType::kConstant ||
cell_type == PropertyCellType::kUndefined) {
// This is always valid for all states a cell can be in.
assembler.GotoIf(assembler.WordNotEqual(cell_contents, value), &miss);
} else {
assembler.GotoIf(assembler.IsTheHole(cell_contents), &miss);
// When dealing with constant types, the type may be allowed to change, as
// long as optimized code remains valid.
bool value_is_smi = false;
if (cell_type == PropertyCellType::kConstantType) {
switch (constant_type()) {
case PropertyCellConstantType::kSmi:
assembler.GotoIfNot(assembler.TaggedIsSmi(value), &miss);
value_is_smi = true;
break;
case PropertyCellConstantType::kStableMap: {
// It is sufficient here to check that the value and cell contents
// have identical maps, no matter if they are stable or not or if they
// are the maps that were originally in the cell or not. If optimized
// code will deopt when a cell has a unstable map and if it has a
// dependency on a stable map, it will deopt if the map destabilizes.
assembler.GotoIf(assembler.TaggedIsSmi(value), &miss);
assembler.GotoIf(assembler.TaggedIsSmi(cell_contents), &miss);
Node* expected_map = assembler.LoadMap(cell_contents);
Node* map = assembler.LoadMap(value);
assembler.GotoIf(assembler.WordNotEqual(expected_map, map), &miss);
break;
}
}
}
if (value_is_smi) {
assembler.StoreObjectFieldNoWriteBarrier(cell, PropertyCell::kValueOffset,
value);
} else {
assembler.StoreObjectField(cell, PropertyCell::kValueOffset, value);
}
}
assembler.Return(value);
assembler.Bind(&miss);
{
assembler.Comment("Miss");
assembler.TailCallRuntime(Runtime::kStoreIC_Miss, context, value, slot,
vector, receiver, name);
}
}
void KeyedLoadSloppyArgumentsStub::GenerateAssembly( void KeyedLoadSloppyArgumentsStub::GenerateAssembly(
compiler::CodeAssemblerState* state) const { compiler::CodeAssemblerState* state) const {
typedef CodeStubAssembler::Label Label; typedef CodeStubAssembler::Label Label;
......
...@@ -90,6 +90,7 @@ class Node; ...@@ -90,6 +90,7 @@ class Node;
V(StringAdd) \ V(StringAdd) \
V(GetProperty) \ V(GetProperty) \
V(StoreFastElement) \ V(StoreFastElement) \
V(StoreGlobal) \
V(StoreInterceptor) \ V(StoreInterceptor) \
V(LoadIndexedInterceptor) \ V(LoadIndexedInterceptor) \
V(GrowArrayElements) V(GrowArrayElements)
...@@ -894,6 +895,49 @@ class KeyedStoreSloppyArgumentsStub : public TurboFanCodeStub { ...@@ -894,6 +895,49 @@ class KeyedStoreSloppyArgumentsStub : public TurboFanCodeStub {
DEFINE_TURBOFAN_CODE_STUB(KeyedStoreSloppyArguments, TurboFanCodeStub); DEFINE_TURBOFAN_CODE_STUB(KeyedStoreSloppyArguments, TurboFanCodeStub);
}; };
class StoreGlobalStub : public TurboFanCodeStub {
public:
StoreGlobalStub(Isolate* isolate, PropertyCellType type,
Maybe<PropertyCellConstantType> constant_type)
: TurboFanCodeStub(isolate) {
PropertyCellConstantType encoded_constant_type =
constant_type.FromMaybe(PropertyCellConstantType::kSmi);
minor_key_ = CellTypeBits::encode(type) |
ConstantTypeBits::encode(encoded_constant_type);
}
Code::Kind GetCodeKind() const override { return Code::HANDLER; }
ExtraICState GetExtraICState() const override { return Code::STORE_IC; }
static Handle<HeapObject> property_cell_placeholder(Isolate* isolate) {
return isolate->factory()->uninitialized_value();
}
Handle<Code> GetCodeCopyFromTemplate(Handle<PropertyCell> cell) {
FindAndReplacePattern pattern;
pattern.Add(handle(property_cell_placeholder(isolate())->map()),
isolate()->factory()->NewWeakCell(cell));
return CodeStub::GetCodeCopy(pattern);
}
PropertyCellType cell_type() const {
return CellTypeBits::decode(minor_key_);
}
PropertyCellConstantType constant_type() const {
DCHECK(PropertyCellType::kConstantType == cell_type());
return ConstantTypeBits::decode(minor_key_);
}
private:
class CellTypeBits : public BitField<PropertyCellType, 0, 2> {};
class ConstantTypeBits
: public BitField<PropertyCellConstantType, CellTypeBits::kNext, 2> {};
DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector);
DEFINE_TURBOFAN_CODE_STUB(StoreGlobal, TurboFanCodeStub);
};
class CallApiCallbackStub : public PlatformCodeStub { class CallApiCallbackStub : public PlatformCodeStub {
public: public:
static const int kArgBits = 3; static const int kArgBits = 3;
......
...@@ -814,8 +814,8 @@ class RuntimeCallTimer final { ...@@ -814,8 +814,8 @@ class RuntimeCallTimer final {
V(StoreIC_StoreField) \ V(StoreIC_StoreField) \
V(StoreIC_StoreFieldDH) \ V(StoreIC_StoreFieldDH) \
V(StoreIC_StoreFieldStub) \ V(StoreIC_StoreFieldStub) \
V(StoreIC_StoreGlobalDH) \ V(StoreIC_StoreGlobal) \
V(StoreIC_StoreGlobalTransitionDH) \ V(StoreIC_StoreGlobalTransition) \
V(StoreIC_StoreInterceptorStub) \ V(StoreIC_StoreInterceptorStub) \
V(StoreIC_StoreNormalDH) \ V(StoreIC_StoreNormalDH) \
V(StoreIC_StoreScriptContextFieldStub) \ V(StoreIC_StoreScriptContextFieldStub) \
......
...@@ -617,8 +617,7 @@ void AccessorAssembler::HandleStoreICHandlerCase( ...@@ -617,8 +617,7 @@ void AccessorAssembler::HandleStoreICHandlerCase(
const StoreICParameters* p, Node* handler, Label* miss, const StoreICParameters* p, Node* handler, Label* miss,
ElementSupport support_elements) { ElementSupport support_elements) {
Label if_smi_handler(this), if_nonsmi_handler(this); Label if_smi_handler(this), if_nonsmi_handler(this);
Label if_proto_handler(this), if_element_handler(this), call_handler(this), Label if_proto_handler(this), if_element_handler(this), call_handler(this);
store_global(this);
Branch(TaggedIsSmi(handler), &if_smi_handler, &if_nonsmi_handler); Branch(TaggedIsSmi(handler), &if_smi_handler, &if_nonsmi_handler);
...@@ -666,7 +665,6 @@ void AccessorAssembler::HandleStoreICHandlerCase( ...@@ -666,7 +665,6 @@ void AccessorAssembler::HandleStoreICHandlerCase(
if (support_elements == kSupportElements) { if (support_elements == kSupportElements) {
GotoIf(IsTuple2Map(handler_map), &if_element_handler); GotoIf(IsTuple2Map(handler_map), &if_element_handler);
} }
GotoIf(IsWeakCellMap(handler_map), &store_global);
Branch(IsCodeMap(handler_map), &call_handler, &if_proto_handler); Branch(IsCodeMap(handler_map), &call_handler, &if_proto_handler);
} }
...@@ -687,66 +685,6 @@ void AccessorAssembler::HandleStoreICHandlerCase( ...@@ -687,66 +685,6 @@ void AccessorAssembler::HandleStoreICHandlerCase(
TailCallStub(descriptor, handler, p->context, p->receiver, p->name, TailCallStub(descriptor, handler, p->context, p->receiver, p->name,
p->value, p->slot, p->vector); p->value, p->slot, p->vector);
} }
Bind(&store_global);
{
Node* cell = LoadWeakCellValue(handler, miss);
CSA_ASSERT(this, IsPropertyCell(cell));
// Load the payload of the global parameter cell. A hole indicates that
// the cell has been invalidated and that the store must be handled by the
// runtime.
Node* cell_contents = LoadObjectField(cell, PropertyCell::kValueOffset);
Node* details =
LoadAndUntagToWord32ObjectField(cell, PropertyCell::kDetailsOffset);
Node* type = DecodeWord32<PropertyDetails::PropertyCellTypeField>(details);
Label constant(this), store(this), not_smi(this);
GotoIf(
Word32Equal(
type, Int32Constant(static_cast<int>(PropertyCellType::kConstant))),
&constant);
GotoIf(IsTheHole(cell_contents), miss);
GotoIf(
Word32Equal(
type, Int32Constant(static_cast<int>(PropertyCellType::kMutable))),
&store);
CSA_ASSERT(this,
Word32Or(Word32Equal(type,
Int32Constant(static_cast<int>(
PropertyCellType::kConstantType))),
Word32Equal(type,
Int32Constant(static_cast<int>(
PropertyCellType::kUndefined)))));
GotoIfNot(TaggedIsSmi(cell_contents), &not_smi);
GotoIfNot(TaggedIsSmi(p->value), miss);
Goto(&store);
Bind(&not_smi);
{
GotoIf(TaggedIsSmi(p->value), miss);
Node* expected_map = LoadMap(cell_contents);
Node* map = LoadMap(p->value);
GotoIfNot(WordEqual(expected_map, map), miss);
Goto(&store);
}
Bind(&store);
{
StoreObjectField(cell, PropertyCell::kValueOffset, p->value);
Return(p->value);
}
Bind(&constant);
{
GotoIfNot(WordEqual(cell_contents, p->value), miss);
Return(p->value);
}
}
} }
void AccessorAssembler::HandleStoreICElementHandlerCase( void AccessorAssembler::HandleStoreICElementHandlerCase(
......
...@@ -92,15 +92,15 @@ Handle<Smi> LoadHandler::LoadElement(Isolate* isolate, ...@@ -92,15 +92,15 @@ Handle<Smi> LoadHandler::LoadElement(Isolate* isolate,
return handle(Smi::FromInt(config), isolate); return handle(Smi::FromInt(config), isolate);
} }
Handle<Smi> StoreHandler::StoreNormal(Isolate* isolate) { Handle<Object> StoreHandler::StoreNormal(Isolate* isolate) {
int config = KindBits::encode(kStoreNormal); int config = KindBits::encode(kStoreNormal);
return handle(Smi::FromInt(config), isolate); return handle(Smi::FromInt(config), isolate);
} }
Handle<Smi> StoreHandler::StoreField(Isolate* isolate, Kind kind, Handle<Object> StoreHandler::StoreField(Isolate* isolate, Kind kind,
int descriptor, FieldIndex field_index, int descriptor, FieldIndex field_index,
Representation representation, Representation representation,
bool extend_storage) { bool extend_storage) {
StoreHandler::FieldRepresentation field_rep; StoreHandler::FieldRepresentation field_rep;
switch (representation.kind()) { switch (representation.kind()) {
case Representation::kSmi: case Representation::kSmi:
...@@ -117,7 +117,7 @@ Handle<Smi> StoreHandler::StoreField(Isolate* isolate, Kind kind, ...@@ -117,7 +117,7 @@ Handle<Smi> StoreHandler::StoreField(Isolate* isolate, Kind kind,
break; break;
default: default:
UNREACHABLE(); UNREACHABLE();
return Handle<Smi>::null(); return Handle<Object>::null();
} }
DCHECK(kind == kStoreField || kind == kTransitionToField || DCHECK(kind == kStoreField || kind == kTransitionToField ||
...@@ -134,26 +134,26 @@ Handle<Smi> StoreHandler::StoreField(Isolate* isolate, Kind kind, ...@@ -134,26 +134,26 @@ Handle<Smi> StoreHandler::StoreField(Isolate* isolate, Kind kind,
return handle(Smi::FromInt(config), isolate); return handle(Smi::FromInt(config), isolate);
} }
Handle<Smi> StoreHandler::StoreField(Isolate* isolate, int descriptor, Handle<Object> StoreHandler::StoreField(Isolate* isolate, int descriptor,
FieldIndex field_index, FieldIndex field_index,
PropertyConstness constness, PropertyConstness constness,
Representation representation) { Representation representation) {
DCHECK_IMPLIES(!FLAG_track_constant_fields, constness == kMutable); DCHECK_IMPLIES(!FLAG_track_constant_fields, constness == kMutable);
Kind kind = constness == kMutable ? kStoreField : kStoreConstField; Kind kind = constness == kMutable ? kStoreField : kStoreConstField;
return StoreField(isolate, kind, descriptor, field_index, representation, return StoreField(isolate, kind, descriptor, field_index, representation,
false); false);
} }
Handle<Smi> StoreHandler::TransitionToField(Isolate* isolate, int descriptor, Handle<Object> StoreHandler::TransitionToField(Isolate* isolate, int descriptor,
FieldIndex field_index, FieldIndex field_index,
Representation representation, Representation representation,
bool extend_storage) { bool extend_storage) {
return StoreField(isolate, kTransitionToField, descriptor, field_index, return StoreField(isolate, kTransitionToField, descriptor, field_index,
representation, extend_storage); representation, extend_storage);
} }
Handle<Smi> StoreHandler::TransitionToConstant(Isolate* isolate, Handle<Object> StoreHandler::TransitionToConstant(Isolate* isolate,
int descriptor) { int descriptor) {
DCHECK(!FLAG_track_constant_fields); DCHECK(!FLAG_track_constant_fields);
int config = int config =
StoreHandler::KindBits::encode(StoreHandler::kTransitionToConstant) | StoreHandler::KindBits::encode(StoreHandler::kTransitionToConstant) |
......
...@@ -191,30 +191,32 @@ class StoreHandler { ...@@ -191,30 +191,32 @@ class StoreHandler {
static const int kFirstPrototypeIndex = 3; static const int kFirstPrototypeIndex = 3;
// Creates a Smi-handler for storing a field to fast object. // Creates a Smi-handler for storing a field to fast object.
static inline Handle<Smi> StoreField(Isolate* isolate, int descriptor, static inline Handle<Object> StoreField(Isolate* isolate, int descriptor,
FieldIndex field_index, FieldIndex field_index,
PropertyConstness constness, PropertyConstness constness,
Representation representation); Representation representation);
// Creates a Smi-handler for storing a property to a slow object. // Creates a Smi-handler for storing a property to a slow object.
static inline Handle<Smi> StoreNormal(Isolate* isolate); static inline Handle<Object> StoreNormal(Isolate* isolate);
// Creates a Smi-handler for transitioning store to a field. // Creates a Smi-handler for transitioning store to a field.
static inline Handle<Smi> TransitionToField(Isolate* isolate, int descriptor, static inline Handle<Object> TransitionToField(Isolate* isolate,
FieldIndex field_index, int descriptor,
Representation representation, FieldIndex field_index,
bool extend_storage); Representation representation,
bool extend_storage);
// Creates a Smi-handler for transitioning store to a constant field (in this // Creates a Smi-handler for transitioning store to a constant field (in this
// case the only thing that needs to be done is an update of a map). // case the only thing that needs to be done is an update of a map).
static inline Handle<Smi> TransitionToConstant(Isolate* isolate, static inline Handle<Object> TransitionToConstant(Isolate* isolate,
int descriptor); int descriptor);
private: private:
static inline Handle<Smi> StoreField(Isolate* isolate, Kind kind, static inline Handle<Object> StoreField(Isolate* isolate, Kind kind,
int descriptor, FieldIndex field_index, int descriptor,
Representation representation, FieldIndex field_index,
bool extend_storage); Representation representation,
bool extend_storage);
}; };
} // namespace internal } // namespace internal
......
...@@ -86,7 +86,7 @@ Code* IC::target() const { ...@@ -86,7 +86,7 @@ Code* IC::target() const {
bool IC::IsHandler(Object* object) { bool IC::IsHandler(Object* object) {
return (object->IsSmi() && (object != nullptr)) || object->IsTuple2() || return (object->IsSmi() && (object != nullptr)) || object->IsTuple2() ||
object->IsTuple3() || object->IsFixedArray() || object->IsWeakCell() || object->IsTuple3() || object->IsFixedArray() ||
(object->IsCode() && Code::cast(object)->is_handler()); (object->IsCode() && Code::cast(object)->is_handler());
} }
......
...@@ -1797,7 +1797,7 @@ Handle<Object> StoreIC::StoreTransition(Handle<Map> receiver_map, ...@@ -1797,7 +1797,7 @@ Handle<Object> StoreIC::StoreTransition(Handle<Map> receiver_map,
Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate()); Map::GetOrCreatePrototypeChainValidityCell(receiver_map, isolate());
if (validity_cell.is_null()) { if (validity_cell.is_null()) {
DCHECK_EQ(0, checks_count); DCHECK_EQ(0, checks_count);
validity_cell = handle(Smi::kZero, isolate()); validity_cell = handle(Smi::FromInt(0), isolate());
} }
Handle<WeakCell> transition_cell = Map::WeakCellForMap(transition); Handle<WeakCell> transition_cell = Map::WeakCellForMap(transition);
...@@ -1816,14 +1816,22 @@ Handle<Object> StoreIC::StoreTransition(Handle<Map> receiver_map, ...@@ -1816,14 +1816,22 @@ Handle<Object> StoreIC::StoreTransition(Handle<Map> receiver_map,
return handler_array; return handler_array;
} }
namespace { static Handle<Code> PropertyCellStoreHandler(Isolate* isolate,
Handle<JSObject> store_target,
Handle<Object> StoreGlobal(Isolate* isolate, Handle<PropertyCell> cell) { Handle<Name> name,
return isolate->factory()->NewWeakCell(cell); Handle<PropertyCell> cell,
PropertyCellType type) {
auto constant_type = Nothing<PropertyCellConstantType>();
if (type == PropertyCellType::kConstantType) {
constant_type = Just(cell->GetConstantType());
}
StoreGlobalStub stub(isolate, type, constant_type);
auto code = stub.GetCodeCopyFromTemplate(cell);
// TODO(verwaest): Move caching of these NORMAL stubs outside as well.
HeapObject::UpdateMapCodeCache(store_target, name, code);
return code;
} }
} // namespace
Handle<Object> StoreIC::GetMapIndependentHandler(LookupIterator* lookup) { Handle<Object> StoreIC::GetMapIndependentHandler(LookupIterator* lookup) {
DCHECK_NE(LookupIterator::JSPROXY, lookup->state()); DCHECK_NE(LookupIterator::JSPROXY, lookup->state());
...@@ -1836,8 +1844,7 @@ Handle<Object> StoreIC::GetMapIndependentHandler(LookupIterator* lookup) { ...@@ -1836,8 +1844,7 @@ Handle<Object> StoreIC::GetMapIndependentHandler(LookupIterator* lookup) {
case LookupIterator::TRANSITION: { case LookupIterator::TRANSITION: {
auto store_target = lookup->GetStoreTarget(); auto store_target = lookup->GetStoreTarget();
if (store_target->IsJSGlobalObject()) { if (store_target->IsJSGlobalObject()) {
TRACE_HANDLER_STATS(isolate(), StoreIC_StoreGlobalTransitionDH); break; // Custom-compiled handler.
return StoreGlobal(isolate(), lookup->transition_cell());
} }
// Currently not handled by CompileStoreTransition. // Currently not handled by CompileStoreTransition.
if (!holder->HasFastProperties()) { if (!holder->HasFastProperties()) {
...@@ -1914,8 +1921,7 @@ Handle<Object> StoreIC::GetMapIndependentHandler(LookupIterator* lookup) { ...@@ -1914,8 +1921,7 @@ Handle<Object> StoreIC::GetMapIndependentHandler(LookupIterator* lookup) {
DCHECK_EQ(kData, lookup->property_details().kind()); DCHECK_EQ(kData, lookup->property_details().kind());
if (lookup->is_dictionary_holder()) { if (lookup->is_dictionary_holder()) {
if (holder->IsJSGlobalObject()) { if (holder->IsJSGlobalObject()) {
TRACE_HANDLER_STATS(isolate(), StoreIC_StoreGlobalDH); break; // Custom-compiled handler.
return StoreGlobal(isolate(), lookup->GetPropertyCell());
} }
TRACE_HANDLER_STATS(isolate(), StoreIC_StoreNormalDH); TRACE_HANDLER_STATS(isolate(), StoreIC_StoreNormalDH);
DCHECK(holder.is_identical_to(receiver)); DCHECK(holder.is_identical_to(receiver));
...@@ -1963,6 +1969,24 @@ Handle<Object> StoreIC::CompileHandler(LookupIterator* lookup, ...@@ -1963,6 +1969,24 @@ Handle<Object> StoreIC::CompileHandler(LookupIterator* lookup,
DCHECK(!receiver->IsAccessCheckNeeded() || lookup->name()->IsPrivate()); DCHECK(!receiver->IsAccessCheckNeeded() || lookup->name()->IsPrivate());
switch (lookup->state()) { switch (lookup->state()) {
case LookupIterator::TRANSITION: {
auto store_target = lookup->GetStoreTarget();
if (store_target->IsJSGlobalObject()) {
TRACE_HANDLER_STATS(isolate(), StoreIC_StoreGlobalTransition);
Handle<PropertyCell> cell = lookup->transition_cell();
cell->set_value(*value);
Handle<Code> code =
PropertyCellStoreHandler(isolate(), receiver, lookup->name(), cell,
PropertyCellType::kConstant);
cell->set_value(isolate()->heap()->the_hole_value());
return code;
}
UNREACHABLE();
}
case LookupIterator::INTERCEPTOR:
UNREACHABLE();
case LookupIterator::ACCESSOR: { case LookupIterator::ACCESSOR: {
DCHECK(holder->HasFastProperties()); DCHECK(holder->HasFastProperties());
Handle<Object> accessors = lookup->GetAccessors(); Handle<Object> accessors = lookup->GetAccessors();
...@@ -2008,9 +2032,20 @@ Handle<Object> StoreIC::CompileHandler(LookupIterator* lookup, ...@@ -2008,9 +2032,20 @@ Handle<Object> StoreIC::CompileHandler(LookupIterator* lookup,
} }
} }
case LookupIterator::DATA: case LookupIterator::DATA: {
case LookupIterator::TRANSITION: DCHECK(lookup->is_dictionary_holder());
case LookupIterator::INTERCEPTOR: DCHECK(holder->IsJSGlobalObject());
TRACE_HANDLER_STATS(isolate(), StoreIC_StoreGlobal);
DCHECK(holder.is_identical_to(receiver) ||
receiver->map()->prototype() == *holder);
auto cell = lookup->GetPropertyCell();
auto updated_type =
PropertyCell::UpdatedType(cell, value, lookup->property_details());
auto code = PropertyCellStoreHandler(isolate(), receiver,
lookup->name(), cell, updated_type);
return code;
}
case LookupIterator::INTEGER_INDEXED_EXOTIC: case LookupIterator::INTEGER_INDEXED_EXOTIC:
case LookupIterator::ACCESS_CHECK: case LookupIterator::ACCESS_CHECK:
case LookupIterator::JSPROXY: case LookupIterator::JSPROXY:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment