| Index: src/compiler/js-global-specialization.cc
|
| diff --git a/src/compiler/js-global-specialization.cc b/src/compiler/js-global-specialization.cc
|
| index 00ade7a9c8546b596c922482ff65b40407f4e308..01a837b3450a02c33f4484564bfe511e6af2202e 100644
|
| --- a/src/compiler/js-global-specialization.cc
|
| +++ b/src/compiler/js-global-specialization.cc
|
| @@ -184,6 +184,7 @@ Reduction JSGlobalSpecialization::ReduceStoreToPropertyCell(
|
| Node* value = NodeProperties::GetValueInput(node, 2);
|
| Node* effect = NodeProperties::GetEffectInput(node);
|
| Node* control = NodeProperties::GetControlInput(node);
|
| + Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
|
| // We only specialize global data property access.
|
| PropertyDetails property_details = property_cell->property_details();
|
| DCHECK_EQ(kData, property_details.kind());
|
| @@ -193,19 +194,75 @@ Reduction JSGlobalSpecialization::ReduceStoreToPropertyCell(
|
| if (property_details.IsReadOnly()) return NoChange();
|
| // Not much we can do if we run the generic pipeline here.
|
| if (!(flags() & kTypingEnabled)) return NoChange();
|
| - // TODO(bmeurer): For now we deal only with cells in mutable state.
|
| - if (property_details.cell_type() != PropertyCellType::kMutable) {
|
| - return NoChange();
|
| - }
|
| - // Store to non-configurable, data property on the global can be lowered to
|
| - // a field store, even without deoptimization, because the property cannot be
|
| - // deleted or reconfigured to an accessor/interceptor property.
|
| - if (property_details.IsConfigurable()) {
|
| - // With deoptimization support, we can lower stores even to configurable
|
| - // data properties on the global object, by adding a code dependency on
|
| - // the cell.
|
| - if (!(flags() & kDeoptimizationEnabled)) return NoChange();
|
| - dependencies()->AssumePropertyCell(property_cell);
|
| + switch (property_details.cell_type()) {
|
| + case PropertyCellType::kUndefined: {
|
| + return NoChange();
|
| + }
|
| + case PropertyCellType::kConstant: {
|
| + // Store to constant property cell requires deoptimization support,
|
| + // because we might even need to eager deoptimize for mismatch.
|
| + if (!(flags() & kDeoptimizationEnabled)) return NoChange();
|
| + dependencies()->AssumePropertyCell(property_cell);
|
| + Node* check =
|
| + graph()->NewNode(simplified()->ReferenceEqual(Type::Tagged()), value,
|
| + jsgraph()->Constant(property_cell_value));
|
| + Node* branch =
|
| + graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
|
| + Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
|
| + Node* deoptimize = graph()->NewNode(common()->Deoptimize(), frame_state,
|
| + effect, if_false);
|
| + // TODO(bmeurer): This should be on the AdvancedReducer somehow.
|
| + NodeProperties::MergeControlToEnd(graph(), common(), deoptimize);
|
| + control = graph()->NewNode(common()->IfTrue(), branch);
|
| + return Replace(node, value, effect, control);
|
| + }
|
| + case PropertyCellType::kConstantType: {
|
| + // Store to constant-type property cell requires deoptimization support,
|
| + // because we might even need to eager deoptimize for mismatch.
|
| + if (!(flags() & kDeoptimizationEnabled)) return NoChange();
|
| + dependencies()->AssumePropertyCell(property_cell);
|
| + Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), value);
|
| + if (property_cell_value->IsHeapObject()) {
|
| + Node* branch = graph()->NewNode(common()->Branch(BranchHint::kFalse),
|
| + check, control);
|
| + Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
|
| + Node* deoptimize = graph()->NewNode(common()->Deoptimize(), frame_state,
|
| + effect, if_true);
|
| + // TODO(bmeurer): This should be on the AdvancedReducer somehow.
|
| + NodeProperties::MergeControlToEnd(graph(), common(), deoptimize);
|
| + control = graph()->NewNode(common()->IfFalse(), branch);
|
| + Node* value_map =
|
| + graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()),
|
| + value, effect, control);
|
| + Handle<Map> property_cell_value_map(
|
| + Handle<HeapObject>::cast(property_cell_value)->map(), isolate());
|
| + check = graph()->NewNode(simplified()->ReferenceEqual(Type::Internal()),
|
| + value_map,
|
| + jsgraph()->Constant(property_cell_value_map));
|
| + }
|
| + Node* branch =
|
| + graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
|
| + Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
|
| + Node* deoptimize = graph()->NewNode(common()->Deoptimize(), frame_state,
|
| + effect, if_false);
|
| + // TODO(bmeurer): This should be on the AdvancedReducer somehow.
|
| + NodeProperties::MergeControlToEnd(graph(), common(), deoptimize);
|
| + control = graph()->NewNode(common()->IfTrue(), branch);
|
| + break;
|
| + }
|
| + case PropertyCellType::kMutable: {
|
| + // Store to non-configurable, data property on the global can be lowered
|
| + // to a field store, even without deoptimization, because the property
|
| + // cannot be deleted or reconfigured to an accessor/interceptor property.
|
| + if (property_details.IsConfigurable()) {
|
| + // With deoptimization support, we can lower stores even to configurable
|
| + // data properties on the global object, by adding a code dependency on
|
| + // the cell.
|
| + if (!(flags() & kDeoptimizationEnabled)) return NoChange();
|
| + dependencies()->AssumePropertyCell(property_cell);
|
| + }
|
| + break;
|
| + }
|
| }
|
| effect = graph()->NewNode(
|
| simplified()->StoreField(AccessBuilder::ForPropertyCellValue()),
|
| @@ -230,6 +287,11 @@ Isolate* JSGlobalSpecialization::isolate() const {
|
| }
|
|
|
|
|
| +CommonOperatorBuilder* JSGlobalSpecialization::common() const {
|
| + return jsgraph()->common();
|
| +}
|
| +
|
| +
|
| JSOperatorBuilder* JSGlobalSpecialization::javascript() const {
|
| return jsgraph()->javascript();
|
| }
|
|
|