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) { ...@@ -3223,8 +3223,9 @@ Reduction JSCallReducer::ReduceJSCall(Node* node) {
// Try to specialize JSCall {node}s with constant {target}s. // Try to specialize JSCall {node}s with constant {target}s.
HeapObjectMatcher m(target); HeapObjectMatcher m(target);
if (m.HasValue()) { if (m.HasValue()) {
if (m.Ref(broker()).IsJSFunction()) { ObjectRef target_ref = m.Ref(broker());
JSFunctionRef function = m.Ref(broker()).AsJSFunction(); if (target_ref.IsJSFunction()) {
JSFunctionRef function = target_ref.AsJSFunction();
function.Serialize(); function.Serialize();
// Don't inline cross native context. // Don't inline cross native context.
...@@ -3233,33 +3234,34 @@ Reduction JSCallReducer::ReduceJSCall(Node* node) { ...@@ -3233,33 +3234,34 @@ Reduction JSCallReducer::ReduceJSCall(Node* node) {
} }
return ReduceJSCall(node, function.shared().object()); return ReduceJSCall(node, function.shared().object());
} else if (m.Value()->IsJSBoundFunction()) { } else if (target_ref.IsJSBoundFunction()) {
Handle<JSBoundFunction> function = JSBoundFunctionRef function = target_ref.AsJSBoundFunction();
Handle<JSBoundFunction>::cast(m.Value()); function.Serialize();
Handle<JSReceiver> bound_target_function(
function->bound_target_function(), isolate()); ObjectRef bound_this = function.bound_this();
Handle<Object> bound_this(function->bound_this(), isolate());
Handle<FixedArray> bound_arguments(function->bound_arguments(),
isolate());
ConvertReceiverMode const convert_mode = ConvertReceiverMode const convert_mode =
(bound_this->IsNullOrUndefined(isolate())) bound_this.IsNullOrUndefined()
? ConvertReceiverMode::kNullOrUndefined ? ConvertReceiverMode::kNullOrUndefined
: ConvertReceiverMode::kNotNullOrUndefined; : ConvertReceiverMode::kNotNullOrUndefined;
// Patch {node} to use [[BoundTargetFunction]] and [[BoundThis]]. // Patch {node} to use [[BoundTargetFunction]] and [[BoundThis]].
NodeProperties::ReplaceValueInput( NodeProperties::ReplaceValueInput(
node, jsgraph()->Constant(bound_target_function), 0); node, jsgraph()->Constant(function.bound_target_function()), 0);
NodeProperties::ReplaceValueInput(node, jsgraph()->Constant(bound_this), NodeProperties::ReplaceValueInput(node, jsgraph()->Constant(bound_this),
1); 1);
// Insert the [[BoundArguments]] for {node}. // Insert the [[BoundArguments]] for {node}.
for (int i = 0; i < bound_arguments->length(); ++i) { FixedArrayRef bound_arguments = function.bound_arguments();
node->InsertInput( for (int i = 0; i < bound_arguments.length(); ++i) {
graph()->zone(), i + 2, node->InsertInput(graph()->zone(), i + 2,
jsgraph()->Constant(handle(bound_arguments->get(i), isolate()))); jsgraph()->Constant(bound_arguments.get(i)));
arity++; arity++;
} }
NodeProperties::ChangeOp( NodeProperties::ChangeOp(
node, javascript()->Call(arity, p.frequency(), VectorSlotPair(), node, javascript()->Call(arity, p.frequency(), VectorSlotPair(),
convert_mode)); convert_mode));
// Try to further reduce the JSCall {node}. // Try to further reduce the JSCall {node}.
Reduction const reduction = ReduceJSCall(node); Reduction const reduction = ReduceJSCall(node);
return reduction.Changed() ? reduction : Changed(node); return reduction.Changed() ? reduction : Changed(node);
...@@ -3818,8 +3820,9 @@ Reduction JSCallReducer::ReduceJSConstruct(Node* node) { ...@@ -3818,8 +3820,9 @@ Reduction JSCallReducer::ReduceJSConstruct(Node* node) {
return Changed(node); return Changed(node);
} }
if (m.Ref(broker()).IsJSFunction()) { ObjectRef target_ref = m.Ref(broker());
JSFunctionRef function = m.Ref(broker()).AsJSFunction(); if (target_ref.IsJSFunction()) {
JSFunctionRef function = target_ref.AsJSFunction();
function.Serialize(); function.Serialize();
// Do not reduce constructors with break points. // Do not reduce constructors with break points.
...@@ -3876,13 +3879,12 @@ Reduction JSCallReducer::ReduceJSConstruct(Node* node) { ...@@ -3876,13 +3879,12 @@ Reduction JSCallReducer::ReduceJSConstruct(Node* node) {
default: default:
break; break;
} }
} else if (m.Value()->IsJSBoundFunction()) { } else if (target_ref.IsJSBoundFunction()) {
Handle<JSBoundFunction> function = JSBoundFunctionRef function = target_ref.AsJSBoundFunction();
Handle<JSBoundFunction>::cast(m.Value()); function.Serialize();
Handle<JSReceiver> bound_target_function(
function->bound_target_function(), isolate()); ObjectRef bound_target_function = function.bound_target_function();
Handle<FixedArray> bound_arguments(function->bound_arguments(), FixedArrayRef bound_arguments = function.bound_arguments();
isolate());
// Patch {node} to use [[BoundTargetFunction]]. // Patch {node} to use [[BoundTargetFunction]].
NodeProperties::ReplaceValueInput( NodeProperties::ReplaceValueInput(
...@@ -3900,10 +3902,9 @@ Reduction JSCallReducer::ReduceJSConstruct(Node* node) { ...@@ -3900,10 +3902,9 @@ Reduction JSCallReducer::ReduceJSConstruct(Node* node) {
arity + 1); arity + 1);
// Insert the [[BoundArguments]] for {node}. // Insert the [[BoundArguments]] for {node}.
for (int i = 0; i < bound_arguments->length(); ++i) { for (int i = 0; i < bound_arguments.length(); ++i) {
node->InsertInput( node->InsertInput(graph()->zone(), i + 1,
graph()->zone(), i + 1, jsgraph()->Constant(bound_arguments.get(i)));
jsgraph()->Constant(handle(bound_arguments->get(i), isolate())));
arity++; arity++;
} }
......
...@@ -271,6 +271,25 @@ void JSTypedArrayData::Serialize(JSHeapBroker* broker) { ...@@ -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 { class JSFunctionData : public JSObjectData {
public: public:
JSFunctionData(JSHeapBroker* broker, ObjectData** storage, JSFunctionData(JSHeapBroker* broker, ObjectData** storage,
...@@ -872,11 +891,6 @@ class FixedArrayBaseData : public HeapObjectData { ...@@ -872,11 +891,6 @@ class FixedArrayBaseData : public HeapObjectData {
int const length_; int const length_;
}; };
JSObjectData::JSObjectData(JSHeapBroker* broker, ObjectData** storage,
Handle<JSObject> object)
: HeapObjectData(broker, storage, object),
inobject_fields_(broker->zone()) {}
class FixedArrayData : public FixedArrayBaseData { class FixedArrayData : public FixedArrayBaseData {
public: public:
FixedArrayData(JSHeapBroker* broker, ObjectData** storage, FixedArrayData(JSHeapBroker* broker, ObjectData** storage,
...@@ -892,6 +906,40 @@ class FixedArrayData : public FixedArrayBaseData { ...@@ -892,6 +906,40 @@ class FixedArrayData : public FixedArrayBaseData {
ZoneVector<ObjectData*> contents_; 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) { void FixedArrayData::SerializeContents(JSHeapBroker* broker) {
if (serialized_contents_) return; if (serialized_contents_) return;
serialized_contents_ = true; serialized_contents_ = true;
...@@ -909,10 +957,6 @@ void FixedArrayData::SerializeContents(JSHeapBroker* broker) { ...@@ -909,10 +957,6 @@ void FixedArrayData::SerializeContents(JSHeapBroker* broker) {
broker->Trace("Copied %zu elements.\n", contents_.size()); 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 { class FixedDoubleArrayData : public FixedArrayBaseData {
public: public:
FixedDoubleArrayData(JSHeapBroker* broker, ObjectData** storage, FixedDoubleArrayData(JSHeapBroker* broker, ObjectData** storage,
...@@ -2060,6 +2104,10 @@ BIMODAL_ACCESSOR(HeapObject, Map, map) ...@@ -2060,6 +2104,10 @@ BIMODAL_ACCESSOR(HeapObject, Map, map)
BIMODAL_ACCESSOR(JSArray, Object, length) 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_prototype)
BIMODAL_ACCESSOR_C(JSFunction, bool, has_initial_map) BIMODAL_ACCESSOR_C(JSFunction, bool, has_initial_map)
BIMODAL_ACCESSOR_C(JSFunction, bool, PrototypeRequiresRuntimeLookup) BIMODAL_ACCESSOR_C(JSFunction, bool, PrototypeRequiresRuntimeLookup)
...@@ -2220,6 +2268,12 @@ base::Optional<JSFunctionRef> NativeContextRef::GetConstructorFunction( ...@@ -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 { bool ObjectRef::BooleanValue() const {
if (broker()->mode() == JSHeapBroker::kDisabled) { if (broker()->mode() == JSHeapBroker::kDisabled) {
AllowHandleDereference allow_handle_dereference; AllowHandleDereference allow_handle_dereference;
...@@ -2536,6 +2590,12 @@ void JSTypedArrayRef::Serialize() { ...@@ -2536,6 +2590,12 @@ void JSTypedArrayRef::Serialize() {
data()->AsJSTypedArray()->Serialize(broker()); 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
#undef BIMODAL_ACCESSOR_B #undef BIMODAL_ACCESSOR_B
#undef BIMODAL_ACCESSOR_C #undef BIMODAL_ACCESSOR_C
......
...@@ -20,6 +20,7 @@ namespace internal { ...@@ -20,6 +20,7 @@ namespace internal {
class BytecodeArray; class BytecodeArray;
class FixedDoubleArray; class FixedDoubleArray;
class InternalizedString; class InternalizedString;
class JSBoundFunction;
class JSGlobalProxy; class JSGlobalProxy;
class JSRegExp; class JSRegExp;
class JSTypedArray; class JSTypedArray;
...@@ -43,6 +44,7 @@ enum class OddballType : uint8_t { ...@@ -43,6 +44,7 @@ enum class OddballType : uint8_t {
#define HEAP_BROKER_OBJECT_LIST(V) \ #define HEAP_BROKER_OBJECT_LIST(V) \
/* Subtypes of JSObject */ \ /* Subtypes of JSObject */ \
V(JSArray) \ V(JSArray) \
V(JSBoundFunction) \
V(JSFunction) \ V(JSFunction) \
V(JSGlobalProxy) \ V(JSGlobalProxy) \
V(JSRegExp) \ V(JSRegExp) \
...@@ -109,6 +111,8 @@ class ObjectRef { ...@@ -109,6 +111,8 @@ class ObjectRef {
HEAP_BROKER_OBJECT_LIST(HEAP_AS_METHOD_DECL) HEAP_BROKER_OBJECT_LIST(HEAP_AS_METHOD_DECL)
#undef HEAP_AS_METHOD_DECL #undef HEAP_AS_METHOD_DECL
bool IsNullOrUndefined() const;
bool BooleanValue() const; bool BooleanValue() const;
double OddballToNumber() const; double OddballToNumber() const;
...@@ -194,6 +198,19 @@ class JSObjectRef : public HeapObjectRef { ...@@ -194,6 +198,19 @@ class JSObjectRef : public HeapObjectRef {
base::Optional<MapRef> GetObjectCreateMap() const; 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 { class JSFunctionRef : public JSObjectRef {
public: public:
using JSObjectRef::JSObjectRef; 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