Commit 0b4350ae authored by Georg Neis's avatar Georg Neis Committed by Commit Bot

[turbofan] Introduce JSBoundFunctionRef class.

... and use it in JSCallReducer.

Bug: v8:7790
Change-Id: I1ff3d8d4d4a2936e6184ae5e842674117a96c7e2
Reviewed-on: https://chromium-review.googlesource.com/c/1314335Reviewed-by: 's avatarMaya Lekova <mslekova@chromium.org>
Commit-Queue: Georg Neis <neis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#57210}
parent db239849
......@@ -3223,8 +3223,9 @@ Reduction JSCallReducer::ReduceJSCall(Node* node) {
// Try to specialize JSCall {node}s with constant {target}s.
HeapObjectMatcher m(target);
if (m.HasValue()) {
if (m.Ref(broker()).IsJSFunction()) {
JSFunctionRef function = m.Ref(broker()).AsJSFunction();
ObjectRef target_ref = m.Ref(broker());
if (target_ref.IsJSFunction()) {
JSFunctionRef function = target_ref.AsJSFunction();
function.Serialize();
// Don't inline cross native context.
......@@ -3233,33 +3234,34 @@ Reduction JSCallReducer::ReduceJSCall(Node* node) {
}
return ReduceJSCall(node, function.shared().object());
} else if (m.Value()->IsJSBoundFunction()) {
Handle<JSBoundFunction> function =
Handle<JSBoundFunction>::cast(m.Value());
Handle<JSReceiver> bound_target_function(
function->bound_target_function(), isolate());
Handle<Object> bound_this(function->bound_this(), isolate());
Handle<FixedArray> bound_arguments(function->bound_arguments(),
isolate());
} else if (target_ref.IsJSBoundFunction()) {
JSBoundFunctionRef function = target_ref.AsJSBoundFunction();
function.Serialize();
ObjectRef bound_this = function.bound_this();
ConvertReceiverMode const convert_mode =
(bound_this->IsNullOrUndefined(isolate()))
bound_this.IsNullOrUndefined()
? ConvertReceiverMode::kNullOrUndefined
: ConvertReceiverMode::kNotNullOrUndefined;
// Patch {node} to use [[BoundTargetFunction]] and [[BoundThis]].
NodeProperties::ReplaceValueInput(
node, jsgraph()->Constant(bound_target_function), 0);
node, jsgraph()->Constant(function.bound_target_function()), 0);
NodeProperties::ReplaceValueInput(node, jsgraph()->Constant(bound_this),
1);
// Insert the [[BoundArguments]] for {node}.
for (int i = 0; i < bound_arguments->length(); ++i) {
node->InsertInput(
graph()->zone(), i + 2,
jsgraph()->Constant(handle(bound_arguments->get(i), isolate())));
FixedArrayRef bound_arguments = function.bound_arguments();
for (int i = 0; i < bound_arguments.length(); ++i) {
node->InsertInput(graph()->zone(), i + 2,
jsgraph()->Constant(bound_arguments.get(i)));
arity++;
}
NodeProperties::ChangeOp(
node, javascript()->Call(arity, p.frequency(), VectorSlotPair(),
convert_mode));
// Try to further reduce the JSCall {node}.
Reduction const reduction = ReduceJSCall(node);
return reduction.Changed() ? reduction : Changed(node);
......@@ -3818,8 +3820,9 @@ Reduction JSCallReducer::ReduceJSConstruct(Node* node) {
return Changed(node);
}
if (m.Ref(broker()).IsJSFunction()) {
JSFunctionRef function = m.Ref(broker()).AsJSFunction();
ObjectRef target_ref = m.Ref(broker());
if (target_ref.IsJSFunction()) {
JSFunctionRef function = target_ref.AsJSFunction();
function.Serialize();
// Do not reduce constructors with break points.
......@@ -3876,13 +3879,12 @@ Reduction JSCallReducer::ReduceJSConstruct(Node* node) {
default:
break;
}
} else if (m.Value()->IsJSBoundFunction()) {
Handle<JSBoundFunction> function =
Handle<JSBoundFunction>::cast(m.Value());
Handle<JSReceiver> bound_target_function(
function->bound_target_function(), isolate());
Handle<FixedArray> bound_arguments(function->bound_arguments(),
isolate());
} else if (target_ref.IsJSBoundFunction()) {
JSBoundFunctionRef function = target_ref.AsJSBoundFunction();
function.Serialize();
ObjectRef bound_target_function = function.bound_target_function();
FixedArrayRef bound_arguments = function.bound_arguments();
// Patch {node} to use [[BoundTargetFunction]].
NodeProperties::ReplaceValueInput(
......@@ -3900,10 +3902,9 @@ Reduction JSCallReducer::ReduceJSConstruct(Node* node) {
arity + 1);
// Insert the [[BoundArguments]] for {node}.
for (int i = 0; i < bound_arguments->length(); ++i) {
node->InsertInput(
graph()->zone(), i + 1,
jsgraph()->Constant(handle(bound_arguments->get(i), isolate())));
for (int i = 0; i < bound_arguments.length(); ++i) {
node->InsertInput(graph()->zone(), i + 1,
jsgraph()->Constant(bound_arguments.get(i)));
arity++;
}
......
......@@ -271,6 +271,25 @@ void JSTypedArrayData::Serialize(JSHeapBroker* broker) {
}
}
class JSBoundFunctionData : public JSObjectData {
public:
JSBoundFunctionData(JSHeapBroker* broker, ObjectData** storage,
Handle<JSBoundFunction> object);
void Serialize(JSHeapBroker* broker);
ObjectData* bound_target_function() const { return bound_target_function_; }
ObjectData* bound_this() const { return bound_this_; }
FixedArrayData* bound_arguments() const { return bound_arguments_; }
private:
bool serialized_ = false;
ObjectData* bound_target_function_ = nullptr;
ObjectData* bound_this_ = nullptr;
FixedArrayData* bound_arguments_ = nullptr;
};
class JSFunctionData : public JSObjectData {
public:
JSFunctionData(JSHeapBroker* broker, ObjectData** storage,
......@@ -872,11 +891,6 @@ class FixedArrayBaseData : public HeapObjectData {
int const length_;
};
JSObjectData::JSObjectData(JSHeapBroker* broker, ObjectData** storage,
Handle<JSObject> object)
: HeapObjectData(broker, storage, object),
inobject_fields_(broker->zone()) {}
class FixedArrayData : public FixedArrayBaseData {
public:
FixedArrayData(JSHeapBroker* broker, ObjectData** storage,
......@@ -892,6 +906,40 @@ class FixedArrayData : public FixedArrayBaseData {
ZoneVector<ObjectData*> contents_;
};
JSBoundFunctionData::JSBoundFunctionData(JSHeapBroker* broker,
ObjectData** storage,
Handle<JSBoundFunction> object)
: JSObjectData(broker, storage, object) {}
void JSBoundFunctionData::Serialize(JSHeapBroker* broker) {
if (serialized_) return;
serialized_ = true;
TraceScope tracer(broker, this, "JSBoundFunctionData::Serialize");
Handle<JSBoundFunction> function = Handle<JSBoundFunction>::cast(object());
DCHECK_NULL(bound_target_function_);
DCHECK_NULL(bound_this_);
DCHECK_NULL(bound_arguments_);
bound_target_function_ =
broker->GetOrCreateData(function->bound_target_function());
bound_this_ = broker->GetOrCreateData(function->bound_this());
bound_arguments_ =
broker->GetOrCreateData(function->bound_arguments())->AsFixedArray();
bound_arguments_->SerializeContents(broker);
}
JSObjectData::JSObjectData(JSHeapBroker* broker, ObjectData** storage,
Handle<JSObject> object)
: HeapObjectData(broker, storage, object),
inobject_fields_(broker->zone()) {}
FixedArrayData::FixedArrayData(JSHeapBroker* broker, ObjectData** storage,
Handle<FixedArray> object)
: FixedArrayBaseData(broker, storage, object), contents_(broker->zone()) {}
void FixedArrayData::SerializeContents(JSHeapBroker* broker) {
if (serialized_contents_) return;
serialized_contents_ = true;
......@@ -909,10 +957,6 @@ void FixedArrayData::SerializeContents(JSHeapBroker* broker) {
broker->Trace("Copied %zu elements.\n", contents_.size());
}
FixedArrayData::FixedArrayData(JSHeapBroker* broker, ObjectData** storage,
Handle<FixedArray> object)
: FixedArrayBaseData(broker, storage, object), contents_(broker->zone()) {}
class FixedDoubleArrayData : public FixedArrayBaseData {
public:
FixedDoubleArrayData(JSHeapBroker* broker, ObjectData** storage,
......@@ -2060,6 +2104,10 @@ BIMODAL_ACCESSOR(HeapObject, Map, map)
BIMODAL_ACCESSOR(JSArray, Object, length)
BIMODAL_ACCESSOR(JSBoundFunction, Object, bound_target_function)
BIMODAL_ACCESSOR(JSBoundFunction, Object, bound_this)
BIMODAL_ACCESSOR(JSBoundFunction, FixedArray, bound_arguments)
BIMODAL_ACCESSOR_C(JSFunction, bool, has_prototype)
BIMODAL_ACCESSOR_C(JSFunction, bool, has_initial_map)
BIMODAL_ACCESSOR_C(JSFunction, bool, PrototypeRequiresRuntimeLookup)
......@@ -2220,6 +2268,12 @@ base::Optional<JSFunctionRef> NativeContextRef::GetConstructorFunction(
}
}
bool ObjectRef::IsNullOrUndefined() const {
if (IsSmi()) return false;
OddballType type = AsHeapObject().map().oddball_type();
return type == OddballType::kNull || type == OddballType::kUndefined;
}
bool ObjectRef::BooleanValue() const {
if (broker()->mode() == JSHeapBroker::kDisabled) {
AllowHandleDereference allow_handle_dereference;
......@@ -2536,6 +2590,12 @@ void JSTypedArrayRef::Serialize() {
data()->AsJSTypedArray()->Serialize(broker());
}
void JSBoundFunctionRef::Serialize() {
if (broker()->mode() == JSHeapBroker::kDisabled) return;
CHECK_EQ(broker()->mode(), JSHeapBroker::kSerializing);
data()->AsJSBoundFunction()->Serialize(broker());
}
#undef BIMODAL_ACCESSOR
#undef BIMODAL_ACCESSOR_B
#undef BIMODAL_ACCESSOR_C
......
......@@ -20,6 +20,7 @@ namespace internal {
class BytecodeArray;
class FixedDoubleArray;
class InternalizedString;
class JSBoundFunction;
class JSGlobalProxy;
class JSRegExp;
class JSTypedArray;
......@@ -43,6 +44,7 @@ enum class OddballType : uint8_t {
#define HEAP_BROKER_OBJECT_LIST(V) \
/* Subtypes of JSObject */ \
V(JSArray) \
V(JSBoundFunction) \
V(JSFunction) \
V(JSGlobalProxy) \
V(JSRegExp) \
......@@ -109,6 +111,8 @@ class ObjectRef {
HEAP_BROKER_OBJECT_LIST(HEAP_AS_METHOD_DECL)
#undef HEAP_AS_METHOD_DECL
bool IsNullOrUndefined() const;
bool BooleanValue() const;
double OddballToNumber() const;
......@@ -194,6 +198,19 @@ class JSObjectRef : public HeapObjectRef {
base::Optional<MapRef> GetObjectCreateMap() const;
};
class JSBoundFunctionRef : public JSObjectRef {
public:
using JSObjectRef::JSObjectRef;
Handle<JSBoundFunction> object() const;
void Serialize();
// The following are available only after calling Serialize().
ObjectRef bound_target_function() const;
ObjectRef bound_this() const;
FixedArrayRef bound_arguments() const;
};
class JSFunctionRef : public JSObjectRef {
public:
using JSObjectRef::JSObjectRef;
......
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