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 {
JSBoundFunctionData(JSHeapBroker* broker, ObjectData** storage,
Handle<JSBoundFunction> object, ObjectDataKind 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 {
......@@ -1245,48 +1223,6 @@ class ScriptContextTableData : public FixedArrayData {
: 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,
Handle<JSObject> object, ObjectDataKind kind)
: JSReceiverData(broker, storage, object, kind),
......@@ -2270,31 +2206,22 @@ uint64_t HeapNumberRef::value_as_bits() const {
return object()->value_as_bits(kRelaxedLoad);
}
base::Optional<JSReceiverRef> JSBoundFunctionRef::bound_target_function()
const {
if (data_->should_access_heap() || broker()->is_concurrent_inlining()) {
// Immutable after initialization.
return TryMakeRef(broker(), object()->bound_target_function(),
kAssumeMemoryFence);
}
return TryMakeRef<JSReceiver>(
broker(), data()->AsJSBoundFunction()->bound_target_function());
JSReceiverRef JSBoundFunctionRef::bound_target_function() const {
DCHECK(data_->should_access_heap() || broker()->is_concurrent_inlining());
// Immutable after initialization.
return MakeRefAssumeMemoryFence(broker(), object()->bound_target_function());
}
base::Optional<ObjectRef> JSBoundFunctionRef::bound_this() const {
if (data_->should_access_heap() || broker()->is_concurrent_inlining()) {
// Immutable after initialization.
return TryMakeRef(broker(), object()->bound_this(), kAssumeMemoryFence);
}
return TryMakeRef<Object>(broker(),
data()->AsJSBoundFunction()->bound_this());
ObjectRef JSBoundFunctionRef::bound_this() const {
DCHECK(data_->should_access_heap() || broker()->is_concurrent_inlining());
// Immutable after initialization.
return MakeRefAssumeMemoryFence(broker(), object()->bound_this());
}
FixedArrayRef JSBoundFunctionRef::bound_arguments() const {
if (data_->should_access_heap() || broker()->is_concurrent_inlining()) {
// Immutable after initialization.
return MakeRefAssumeMemoryFence(broker(), object()->bound_arguments());
}
return FixedArrayRef(broker(),
data()->AsJSBoundFunction()->bound_arguments());
DCHECK(data_->should_access_heap() || broker()->is_concurrent_inlining());
// Immutable after initialization.
return MakeRefAssumeMemoryFence(broker(), object()->bound_arguments());
}
// Immutable after initialization.
......@@ -3116,14 +3043,6 @@ Handle<T> TinyRef<T>::object() const {
HEAP_BROKER_OBJECT_LIST(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(
CompilationDependencies* dependencies) const {
CHECK_NOT_NULL(dependencies);
......
......@@ -451,12 +451,8 @@ class JSBoundFunctionRef : public JSObjectRef {
Handle<JSBoundFunction> object() const;
bool Serialize(NotConcurrentInliningTag tag);
// 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;
JSReceiverRef bound_target_function() const;
ObjectRef bound_this() const;
FixedArrayRef bound_arguments() const;
};
......
......@@ -4308,13 +4308,9 @@ Reduction JSCallReducer::ReduceJSCall(Node* node) {
return ReduceJSCall(node, function.shared(dependencies()));
} else if (target_ref.IsJSBoundFunction()) {
JSBoundFunctionRef function = target_ref.AsJSBoundFunction();
base::Optional<JSReceiverRef> bound_target_function =
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();
ObjectRef bound_this = function.bound_this();
ConvertReceiverMode const convert_mode =
bound_this->IsNullOrUndefined()
bound_this.IsNullOrUndefined()
? ConvertReceiverMode::kNullOrUndefined
: ConvertReceiverMode::kNotNullOrUndefined;
......@@ -4335,9 +4331,9 @@ Reduction JSCallReducer::ReduceJSCall(Node* node) {
// Patch {node} to use [[BoundTargetFunction]] and [[BoundThis]].
NodeProperties::ReplaceValueInput(
node, jsgraph()->Constant(*bound_target_function),
node, jsgraph()->Constant(function.bound_target_function()),
JSCallNode::TargetIndex());
NodeProperties::ReplaceValueInput(node, jsgraph()->Constant(*bound_this),
NodeProperties::ReplaceValueInput(node, jsgraph()->Constant(bound_this),
JSCallNode::ReceiverIndex());
// Insert the [[BoundArguments]] for {node}.
......@@ -5055,9 +5051,7 @@ Reduction JSCallReducer::ReduceJSConstruct(Node* node) {
}
} else if (target_ref.IsJSBoundFunction()) {
JSBoundFunctionRef function = target_ref.AsJSBoundFunction();
base::Optional<JSReceiverRef> bound_target_function =
function.bound_target_function();
if (!bound_target_function.has_value()) return NoChange();
JSReceiverRef bound_target_function = function.bound_target_function();
FixedArrayRef bound_arguments = function.bound_arguments();
const int bound_arguments_length = bound_arguments.length();
......@@ -5076,20 +5070,20 @@ Reduction JSCallReducer::ReduceJSConstruct(Node* node) {
// Patch {node} to use [[BoundTargetFunction]].
node->ReplaceInput(n.TargetIndex(),
jsgraph()->Constant(*bound_target_function));
jsgraph()->Constant(bound_target_function));
// Patch {node} to use [[BoundTargetFunction]]
// as new.target if {new_target} equals {target}.
if (target == new_target) {
node->ReplaceInput(n.NewTargetIndex(),
jsgraph()->Constant(*bound_target_function));
jsgraph()->Constant(bound_target_function));
} else {
node->ReplaceInput(
n.NewTargetIndex(),
graph()->NewNode(common()->Select(MachineRepresentation::kTagged),
graph()->NewNode(simplified()->ReferenceEqual(),
target, new_target),
jsgraph()->Constant(*bound_target_function),
jsgraph()->Constant(bound_target_function),
new_target));
}
......
......@@ -172,7 +172,6 @@ class V8_EXPORT_PRIVATE JSHeapBroker {
ProcessedFeedback const* feedback);
FeedbackSlotKind GetFeedbackSlotKind(FeedbackSource const& source) const;
// TODO(neis): Move these into serializer when we're always in the background.
ElementAccessFeedback const& ProcessFeedbackMapsForElementAccess(
ZoneVector<MapRef>& maps, KeyedAccessMode const& keyed_mode,
FeedbackSlotKind slot_kind);
......
......@@ -617,15 +617,11 @@ Reduction JSNativeContextSpecialization::ReduceJSOrdinaryHasInstance(
// OrdinaryHasInstance on bound functions turns into a recursive invocation
// of the instanceof operator again.
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();
NodeProperties::ReplaceValueInput(node, object,
JSInstanceOfNode::LeftIndex());
NodeProperties::ReplaceValueInput(
node, jsgraph()->Constant(*bound_target_function),
node, jsgraph()->Constant(function.bound_target_function()),
JSInstanceOfNode::RightIndex());
node->InsertInput(zone(), JSInstanceOfNode::FeedbackVectorIndex(),
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