Skip to content

Commit

Permalink
Reland "[ic] Migrate StoreGlobal to data handler"
Browse files Browse the repository at this point in the history
The problem was that transitioning element stores had a similar shape to
the new StoreGlobal case.

The problem was fixed by https://chromium-review.googlesource.com/c/457341/

BUG=v8:5561

Change-Id: If996e9b37809ba8edf6dcb228b116b77021ce7bc
Reviewed-on: https://chromium-review.googlesource.com/457324
Reviewed-by: Igor Sheludko <[email protected]>
Commit-Queue: Toon Verwaest <[email protected]>
Cr-Commit-Position: refs/heads/master@{#43992}
  • Loading branch information
verwaest authored and Commit Bot committed Mar 21, 2017
1 parent 8258361 commit 5097f3d
Show file tree
Hide file tree
Showing 10 changed files with 114 additions and 214 deletions.
2 changes: 1 addition & 1 deletion src/code-stub-assembler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2960,7 +2960,7 @@ Node* CodeStubAssembler::IsJSArray(Node* object) {
}

Node* CodeStubAssembler::IsWeakCell(Node* object) {
return HasInstanceType(object, WEAK_CELL_TYPE);
return IsWeakCellMap(LoadMap(object));
}

Node* CodeStubAssembler::IsBoolean(Node* object) {
Expand Down
3 changes: 2 additions & 1 deletion src/code-stub-assembler.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ enum class PrimitiveType { kBoolean, kNumber, kString, kSymbol };
V(TrueValue, True) \
V(Tuple2Map, Tuple2Map) \
V(Tuple3Map, Tuple3Map) \
V(UndefinedValue, Undefined)
V(UndefinedValue, Undefined) \
V(WeakCellMap, WeakCellMap)

// Provides JavaScript-specific "macro-assembler" functionality on top of the
// CodeAssembler. By factoring the JavaScript-isms out of the CodeAssembler,
Expand Down
82 changes: 0 additions & 82 deletions src/code-stubs.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1490,88 +1490,6 @@ void SubStringStub::GenerateAssembly(
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(
compiler::CodeAssemblerState* state) const {
typedef CodeStubAssembler::Label Label;
Expand Down
44 changes: 0 additions & 44 deletions src/code-stubs.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@ class Node;
V(StringAdd) \
V(GetProperty) \
V(StoreFastElement) \
V(StoreGlobal) \
V(StoreInterceptor) \
V(LoadIndexedInterceptor) \
V(GrowArrayElements)
Expand Down Expand Up @@ -895,49 +894,6 @@ class KeyedStoreSloppyArgumentsStub : public 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 {
public:
static const int kArgBits = 3;
Expand Down
4 changes: 2 additions & 2 deletions src/counters.h
Original file line number Diff line number Diff line change
Expand Up @@ -815,8 +815,8 @@ class RuntimeCallTimer final {
V(StoreIC_StoreField) \
V(StoreIC_StoreFieldDH) \
V(StoreIC_StoreFieldStub) \
V(StoreIC_StoreGlobal) \
V(StoreIC_StoreGlobalTransition) \
V(StoreIC_StoreGlobalDH) \
V(StoreIC_StoreGlobalTransitionDH) \
V(StoreIC_StoreInterceptorStub) \
V(StoreIC_StoreNormalDH) \
V(StoreIC_StoreScriptContextFieldStub) \
Expand Down
64 changes: 63 additions & 1 deletion src/ic/accessor-assembler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -580,7 +580,8 @@ void AccessorAssembler::HandleStoreICHandlerCase(
const StoreICParameters* p, Node* handler, Label* miss,
ElementSupport support_elements) {
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);

Expand Down Expand Up @@ -628,6 +629,7 @@ void AccessorAssembler::HandleStoreICHandlerCase(
if (support_elements == kSupportElements) {
GotoIf(IsTuple2Map(handler_map), &if_element_handler);
}
GotoIf(IsWeakCellMap(handler_map), &store_global);
Branch(IsCodeMap(handler_map), &call_handler, &if_proto_handler);
}

Expand All @@ -646,6 +648,66 @@ void AccessorAssembler::HandleStoreICHandlerCase(
TailCallStub(descriptor, handler, p->context, p->receiver, p->name,
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(
Expand Down
32 changes: 16 additions & 16 deletions src/ic/handler-configuration-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,15 +92,15 @@ Handle<Smi> LoadHandler::LoadElement(Isolate* isolate,
return handle(Smi::FromInt(config), isolate);
}

Handle<Object> StoreHandler::StoreNormal(Isolate* isolate) {
Handle<Smi> StoreHandler::StoreNormal(Isolate* isolate) {
int config = KindBits::encode(kStoreNormal);
return handle(Smi::FromInt(config), isolate);
}

Handle<Object> StoreHandler::StoreField(Isolate* isolate, Kind kind,
int descriptor, FieldIndex field_index,
Representation representation,
bool extend_storage) {
Handle<Smi> StoreHandler::StoreField(Isolate* isolate, Kind kind,
int descriptor, FieldIndex field_index,
Representation representation,
bool extend_storage) {
StoreHandler::FieldRepresentation field_rep;
switch (representation.kind()) {
case Representation::kSmi:
Expand All @@ -117,7 +117,7 @@ Handle<Object> StoreHandler::StoreField(Isolate* isolate, Kind kind,
break;
default:
UNREACHABLE();
return Handle<Object>::null();
return Handle<Smi>::null();
}

DCHECK(kind == kStoreField || kind == kTransitionToField ||
Expand All @@ -134,26 +134,26 @@ Handle<Object> StoreHandler::StoreField(Isolate* isolate, Kind kind,
return handle(Smi::FromInt(config), isolate);
}

Handle<Object> StoreHandler::StoreField(Isolate* isolate, int descriptor,
FieldIndex field_index,
PropertyConstness constness,
Representation representation) {
Handle<Smi> StoreHandler::StoreField(Isolate* isolate, int descriptor,
FieldIndex field_index,
PropertyConstness constness,
Representation representation) {
DCHECK_IMPLIES(!FLAG_track_constant_fields, constness == kMutable);
Kind kind = constness == kMutable ? kStoreField : kStoreConstField;
return StoreField(isolate, kind, descriptor, field_index, representation,
false);
}

Handle<Object> StoreHandler::TransitionToField(Isolate* isolate, int descriptor,
FieldIndex field_index,
Representation representation,
bool extend_storage) {
Handle<Smi> StoreHandler::TransitionToField(Isolate* isolate, int descriptor,
FieldIndex field_index,
Representation representation,
bool extend_storage) {
return StoreField(isolate, kTransitionToField, descriptor, field_index,
representation, extend_storage);
}

Handle<Object> StoreHandler::TransitionToConstant(Isolate* isolate,
int descriptor) {
Handle<Smi> StoreHandler::TransitionToConstant(Isolate* isolate,
int descriptor) {
DCHECK(!FLAG_track_constant_fields);
int config =
StoreHandler::KindBits::encode(StoreHandler::kTransitionToConstant) |
Expand Down
32 changes: 15 additions & 17 deletions src/ic/handler-configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -191,32 +191,30 @@ class StoreHandler {
static const int kFirstPrototypeIndex = 3;

// Creates a Smi-handler for storing a field to fast object.
static inline Handle<Object> StoreField(Isolate* isolate, int descriptor,
FieldIndex field_index,
PropertyConstness constness,
Representation representation);
static inline Handle<Smi> StoreField(Isolate* isolate, int descriptor,
FieldIndex field_index,
PropertyConstness constness,
Representation representation);

// Creates a Smi-handler for storing a property to a slow object.
static inline Handle<Object> StoreNormal(Isolate* isolate);
static inline Handle<Smi> StoreNormal(Isolate* isolate);

// Creates a Smi-handler for transitioning store to a field.
static inline Handle<Object> TransitionToField(Isolate* isolate,
int descriptor,
FieldIndex field_index,
Representation representation,
bool extend_storage);
static inline Handle<Smi> TransitionToField(Isolate* isolate, int descriptor,
FieldIndex field_index,
Representation representation,
bool extend_storage);

// 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).
static inline Handle<Object> TransitionToConstant(Isolate* isolate,
int descriptor);
static inline Handle<Smi> TransitionToConstant(Isolate* isolate,
int descriptor);

private:
static inline Handle<Object> StoreField(Isolate* isolate, Kind kind,
int descriptor,
FieldIndex field_index,
Representation representation,
bool extend_storage);
static inline Handle<Smi> StoreField(Isolate* isolate, Kind kind,
int descriptor, FieldIndex field_index,
Representation representation,
bool extend_storage);
};

} // namespace internal
Expand Down
2 changes: 1 addition & 1 deletion src/ic/ic-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ Code* IC::target() const {

bool IC::IsHandler(Object* object) {
return (object->IsSmi() && (object != nullptr)) || object->IsTuple2() ||
object->IsTuple3() || object->IsFixedArray() ||
object->IsTuple3() || object->IsFixedArray() || object->IsWeakCell() ||
(object->IsCode() && Code::cast(object)->is_handler());
}

Expand Down
Loading

0 comments on commit 5097f3d

Please sign in to comment.