Commit db62f69d authored by Georg Neis's avatar Georg Neis Committed by V8 LUCI CQ

[compiler] Simplify JSBoundFunctionRef

These methods are called only during the inlining phase, so even in the
default configuration we follow the same branch as concurrent inlining
and ignore the serialized data. We can thus tighten their return types
and cut down JSBoundFunctionData.

Bug: v8:7790
Change-Id: Ic48f8f2651d684440dc5f6a9934de2ae3a5b5132
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3123410Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Commit-Queue: Georg Neis <neis@chromium.org>
Cr-Commit-Position: refs/heads/main@{#76561}
parent 5c287a67
...@@ -624,28 +624,6 @@ class JSBoundFunctionData : public JSObjectData { ...@@ -624,28 +624,6 @@ class JSBoundFunctionData : public JSObjectData {
JSBoundFunctionData(JSHeapBroker* broker, ObjectData** storage, JSBoundFunctionData(JSHeapBroker* broker, ObjectData** storage,
Handle<JSBoundFunction> object, ObjectDataKind kind) Handle<JSBoundFunction> object, ObjectDataKind kind)
: JSObjectData(broker, storage, object, kind) {} : JSObjectData(broker, storage, object, kind) {}
bool Serialize(JSHeapBroker* broker, NotConcurrentInliningTag tag);
ObjectData* bound_target_function() const {
DCHECK(!broker()->is_concurrent_inlining());
return bound_target_function_;
}
ObjectData* bound_this() const {
DCHECK(!broker()->is_concurrent_inlining());
return bound_this_;
}
ObjectData* bound_arguments() const {
DCHECK(!broker()->is_concurrent_inlining());
return bound_arguments_;
}
private:
bool serialized_ = false;
ObjectData* bound_target_function_ = nullptr;
ObjectData* bound_this_ = nullptr;
ObjectData* bound_arguments_ = nullptr;
}; };
class JSFunctionData : public JSObjectData { class JSFunctionData : public JSObjectData {
...@@ -1245,48 +1223,6 @@ class ScriptContextTableData : public FixedArrayData { ...@@ -1245,48 +1223,6 @@ class ScriptContextTableData : public FixedArrayData {
: FixedArrayData(broker, storage, object, kind) {} : FixedArrayData(broker, storage, object, kind) {}
}; };
bool JSBoundFunctionData::Serialize(JSHeapBroker* broker,
NotConcurrentInliningTag tag) {
DCHECK(!broker->is_concurrent_inlining());
if (serialized_) return true;
if (broker->StackHasOverflowed()) return false;
TraceScope tracer(broker, this, "JSBoundFunctionData::Serialize");
Handle<JSBoundFunction> function = Handle<JSBoundFunction>::cast(object());
// We don't immediately set {serialized_} in order to correctly handle the
// case where a recursive call to this method reaches the stack limit.
DCHECK_NULL(bound_target_function_);
bound_target_function_ =
broker->GetOrCreateData(function->bound_target_function());
bool serialized_nested = true;
if (!bound_target_function_->should_access_heap()) {
if (bound_target_function_->IsJSBoundFunction()) {
serialized_nested =
bound_target_function_->AsJSBoundFunction()->Serialize(broker, tag);
}
}
if (!serialized_nested) {
// We couldn't serialize all nested bound functions due to stack
// overflow. Give up.
DCHECK(!serialized_);
bound_target_function_ = nullptr; // Reset to sync with serialized_.
return false;
}
serialized_ = true;
DCHECK_NULL(bound_arguments_);
bound_arguments_ = broker->GetOrCreateData(function->bound_arguments());
DCHECK_NULL(bound_this_);
bound_this_ = broker->GetOrCreateData(function->bound_this());
return true;
}
JSObjectData::JSObjectData(JSHeapBroker* broker, ObjectData** storage, JSObjectData::JSObjectData(JSHeapBroker* broker, ObjectData** storage,
Handle<JSObject> object, ObjectDataKind kind) Handle<JSObject> object, ObjectDataKind kind)
: JSReceiverData(broker, storage, object, kind), : JSReceiverData(broker, storage, object, kind),
...@@ -2270,31 +2206,22 @@ uint64_t HeapNumberRef::value_as_bits() const { ...@@ -2270,31 +2206,22 @@ uint64_t HeapNumberRef::value_as_bits() const {
return object()->value_as_bits(kRelaxedLoad); return object()->value_as_bits(kRelaxedLoad);
} }
base::Optional<JSReceiverRef> JSBoundFunctionRef::bound_target_function() JSReceiverRef JSBoundFunctionRef::bound_target_function() const {
const { DCHECK(data_->should_access_heap() || broker()->is_concurrent_inlining());
if (data_->should_access_heap() || broker()->is_concurrent_inlining()) { // Immutable after initialization.
// Immutable after initialization. return MakeRefAssumeMemoryFence(broker(), object()->bound_target_function());
return TryMakeRef(broker(), object()->bound_target_function(),
kAssumeMemoryFence);
}
return TryMakeRef<JSReceiver>(
broker(), data()->AsJSBoundFunction()->bound_target_function());
} }
base::Optional<ObjectRef> JSBoundFunctionRef::bound_this() const {
if (data_->should_access_heap() || broker()->is_concurrent_inlining()) { ObjectRef JSBoundFunctionRef::bound_this() const {
// Immutable after initialization. DCHECK(data_->should_access_heap() || broker()->is_concurrent_inlining());
return TryMakeRef(broker(), object()->bound_this(), kAssumeMemoryFence); // Immutable after initialization.
} return MakeRefAssumeMemoryFence(broker(), object()->bound_this());
return TryMakeRef<Object>(broker(),
data()->AsJSBoundFunction()->bound_this());
} }
FixedArrayRef JSBoundFunctionRef::bound_arguments() const { FixedArrayRef JSBoundFunctionRef::bound_arguments() const {
if (data_->should_access_heap() || broker()->is_concurrent_inlining()) { DCHECK(data_->should_access_heap() || broker()->is_concurrent_inlining());
// Immutable after initialization. // Immutable after initialization.
return MakeRefAssumeMemoryFence(broker(), object()->bound_arguments()); return MakeRefAssumeMemoryFence(broker(), object()->bound_arguments());
}
return FixedArrayRef(broker(),
data()->AsJSBoundFunction()->bound_arguments());
} }
// Immutable after initialization. // Immutable after initialization.
...@@ -3116,14 +3043,6 @@ Handle<T> TinyRef<T>::object() const { ...@@ -3116,14 +3043,6 @@ Handle<T> TinyRef<T>::object() const {
HEAP_BROKER_OBJECT_LIST(V) HEAP_BROKER_OBJECT_LIST(V)
#undef V #undef V
bool JSBoundFunctionRef::Serialize(NotConcurrentInliningTag tag) {
if (data_->should_access_heap()) {
return true;
}
CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
return data()->AsJSBoundFunction()->Serialize(broker(), tag);
}
void JSFunctionRef::RecordDependencyIfNeeded( void JSFunctionRef::RecordDependencyIfNeeded(
CompilationDependencies* dependencies) const { CompilationDependencies* dependencies) const {
CHECK_NOT_NULL(dependencies); CHECK_NOT_NULL(dependencies);
......
...@@ -451,12 +451,8 @@ class JSBoundFunctionRef : public JSObjectRef { ...@@ -451,12 +451,8 @@ class JSBoundFunctionRef : public JSObjectRef {
Handle<JSBoundFunction> object() const; Handle<JSBoundFunction> object() const;
bool Serialize(NotConcurrentInliningTag tag); JSReceiverRef bound_target_function() const;
ObjectRef bound_this() const;
// TODO(neis): Make return types non-optional once JSFunction is no longer
// fg-serialized.
base::Optional<JSReceiverRef> bound_target_function() const;
base::Optional<ObjectRef> bound_this() const;
FixedArrayRef bound_arguments() const; FixedArrayRef bound_arguments() const;
}; };
......
...@@ -4308,13 +4308,9 @@ Reduction JSCallReducer::ReduceJSCall(Node* node) { ...@@ -4308,13 +4308,9 @@ Reduction JSCallReducer::ReduceJSCall(Node* node) {
return ReduceJSCall(node, function.shared(dependencies())); return ReduceJSCall(node, function.shared(dependencies()));
} else if (target_ref.IsJSBoundFunction()) { } else if (target_ref.IsJSBoundFunction()) {
JSBoundFunctionRef function = target_ref.AsJSBoundFunction(); JSBoundFunctionRef function = target_ref.AsJSBoundFunction();
base::Optional<JSReceiverRef> bound_target_function = ObjectRef bound_this = function.bound_this();
function.bound_target_function();
if (!bound_target_function.has_value()) return NoChange();
base::Optional<ObjectRef> bound_this = function.bound_this();
if (!bound_this.has_value()) return NoChange();
ConvertReceiverMode const convert_mode = ConvertReceiverMode const convert_mode =
bound_this->IsNullOrUndefined() bound_this.IsNullOrUndefined()
? ConvertReceiverMode::kNullOrUndefined ? ConvertReceiverMode::kNullOrUndefined
: ConvertReceiverMode::kNotNullOrUndefined; : ConvertReceiverMode::kNotNullOrUndefined;
...@@ -4335,9 +4331,9 @@ Reduction JSCallReducer::ReduceJSCall(Node* node) { ...@@ -4335,9 +4331,9 @@ Reduction JSCallReducer::ReduceJSCall(Node* node) {
// Patch {node} to use [[BoundTargetFunction]] and [[BoundThis]]. // Patch {node} to use [[BoundTargetFunction]] and [[BoundThis]].
NodeProperties::ReplaceValueInput( NodeProperties::ReplaceValueInput(
node, jsgraph()->Constant(*bound_target_function), node, jsgraph()->Constant(function.bound_target_function()),
JSCallNode::TargetIndex()); JSCallNode::TargetIndex());
NodeProperties::ReplaceValueInput(node, jsgraph()->Constant(*bound_this), NodeProperties::ReplaceValueInput(node, jsgraph()->Constant(bound_this),
JSCallNode::ReceiverIndex()); JSCallNode::ReceiverIndex());
// Insert the [[BoundArguments]] for {node}. // Insert the [[BoundArguments]] for {node}.
...@@ -5055,9 +5051,7 @@ Reduction JSCallReducer::ReduceJSConstruct(Node* node) { ...@@ -5055,9 +5051,7 @@ Reduction JSCallReducer::ReduceJSConstruct(Node* node) {
} }
} else if (target_ref.IsJSBoundFunction()) { } else if (target_ref.IsJSBoundFunction()) {
JSBoundFunctionRef function = target_ref.AsJSBoundFunction(); JSBoundFunctionRef function = target_ref.AsJSBoundFunction();
base::Optional<JSReceiverRef> bound_target_function = JSReceiverRef bound_target_function = function.bound_target_function();
function.bound_target_function();
if (!bound_target_function.has_value()) return NoChange();
FixedArrayRef bound_arguments = function.bound_arguments(); FixedArrayRef bound_arguments = function.bound_arguments();
const int bound_arguments_length = bound_arguments.length(); const int bound_arguments_length = bound_arguments.length();
...@@ -5076,20 +5070,20 @@ Reduction JSCallReducer::ReduceJSConstruct(Node* node) { ...@@ -5076,20 +5070,20 @@ Reduction JSCallReducer::ReduceJSConstruct(Node* node) {
// Patch {node} to use [[BoundTargetFunction]]. // Patch {node} to use [[BoundTargetFunction]].
node->ReplaceInput(n.TargetIndex(), node->ReplaceInput(n.TargetIndex(),
jsgraph()->Constant(*bound_target_function)); jsgraph()->Constant(bound_target_function));
// Patch {node} to use [[BoundTargetFunction]] // Patch {node} to use [[BoundTargetFunction]]
// as new.target if {new_target} equals {target}. // as new.target if {new_target} equals {target}.
if (target == new_target) { if (target == new_target) {
node->ReplaceInput(n.NewTargetIndex(), node->ReplaceInput(n.NewTargetIndex(),
jsgraph()->Constant(*bound_target_function)); jsgraph()->Constant(bound_target_function));
} else { } else {
node->ReplaceInput( node->ReplaceInput(
n.NewTargetIndex(), n.NewTargetIndex(),
graph()->NewNode(common()->Select(MachineRepresentation::kTagged), graph()->NewNode(common()->Select(MachineRepresentation::kTagged),
graph()->NewNode(simplified()->ReferenceEqual(), graph()->NewNode(simplified()->ReferenceEqual(),
target, new_target), target, new_target),
jsgraph()->Constant(*bound_target_function), jsgraph()->Constant(bound_target_function),
new_target)); new_target));
} }
......
...@@ -172,7 +172,6 @@ class V8_EXPORT_PRIVATE JSHeapBroker { ...@@ -172,7 +172,6 @@ class V8_EXPORT_PRIVATE JSHeapBroker {
ProcessedFeedback const* feedback); ProcessedFeedback const* feedback);
FeedbackSlotKind GetFeedbackSlotKind(FeedbackSource const& source) const; FeedbackSlotKind GetFeedbackSlotKind(FeedbackSource const& source) const;
// TODO(neis): Move these into serializer when we're always in the background.
ElementAccessFeedback const& ProcessFeedbackMapsForElementAccess( ElementAccessFeedback const& ProcessFeedbackMapsForElementAccess(
ZoneVector<MapRef>& maps, KeyedAccessMode const& keyed_mode, ZoneVector<MapRef>& maps, KeyedAccessMode const& keyed_mode,
FeedbackSlotKind slot_kind); FeedbackSlotKind slot_kind);
......
...@@ -617,15 +617,11 @@ Reduction JSNativeContextSpecialization::ReduceJSOrdinaryHasInstance( ...@@ -617,15 +617,11 @@ Reduction JSNativeContextSpecialization::ReduceJSOrdinaryHasInstance(
// OrdinaryHasInstance on bound functions turns into a recursive invocation // OrdinaryHasInstance on bound functions turns into a recursive invocation
// of the instanceof operator again. // of the instanceof operator again.
JSBoundFunctionRef function = m.Ref(broker()).AsJSBoundFunction(); JSBoundFunctionRef function = m.Ref(broker()).AsJSBoundFunction();
base::Optional<JSReceiverRef> bound_target_function =
function.bound_target_function();
if (bound_target_function.has_value()) return NoChange();
Node* feedback = jsgraph()->UndefinedConstant(); Node* feedback = jsgraph()->UndefinedConstant();
NodeProperties::ReplaceValueInput(node, object, NodeProperties::ReplaceValueInput(node, object,
JSInstanceOfNode::LeftIndex()); JSInstanceOfNode::LeftIndex());
NodeProperties::ReplaceValueInput( NodeProperties::ReplaceValueInput(
node, jsgraph()->Constant(*bound_target_function), node, jsgraph()->Constant(function.bound_target_function()),
JSInstanceOfNode::RightIndex()); JSInstanceOfNode::RightIndex());
node->InsertInput(zone(), JSInstanceOfNode::FeedbackVectorIndex(), node->InsertInput(zone(), JSInstanceOfNode::FeedbackVectorIndex(),
feedback); feedback);
......
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