[nci] Adapt HasProperty, InstanceOf, CreateClosure

HasProperty and InstanceOf now both have a feedback vector input, and
collect feedback in generic lowering.

CreateClosure loads the feedback cell (in nci mode) instead of embedding
a heap constant.

Bug: v8:8888
Change-Id: Id479cda344684aeb5054f687b087c4fedeac05d8
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2282530
Reviewed-by: Georg Neis <neis@chromium.org>
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#68711}
This commit is contained in:
Jakob Gruber 2020-07-07 13:48:02 +02:00 committed by Commit Bot
parent e63bae121b
commit db5d8d1983
17 changed files with 176 additions and 112 deletions

View File

@ -671,6 +671,7 @@ namespace internal {
/* instanceof */ \
TFC(OrdinaryHasInstance, Compare) \
TFC(InstanceOf, Compare) \
TFC(InstanceOf_WithFeedback, Compare_WithFeedback) \
\
/* for-in */ \
TFS(ForInEnumerate, kReceiver) \

View File

@ -1156,6 +1156,18 @@ TF_BUILTIN(InstanceOf, ObjectBuiltinsAssembler) {
Return(InstanceOf(object, callable, context));
}
TF_BUILTIN(InstanceOf_WithFeedback, ObjectBuiltinsAssembler) {
TNode<Object> object = CAST(Parameter(Descriptor::kLeft));
TNode<Object> callable = CAST(Parameter(Descriptor::kRight));
TNode<Context> context = CAST(Parameter(Descriptor::kContext));
TNode<HeapObject> maybe_feedback_vector =
CAST(Parameter(Descriptor::kMaybeFeedbackVector));
TNode<UintPtrT> slot = UncheckedCast<UintPtrT>(Parameter(Descriptor::kSlot));
CollectInstanceOfFeedback(callable, context, maybe_feedback_vector, slot);
Return(InstanceOf(object, callable, context));
}
// ES6 section 7.3.19 OrdinaryHasInstance ( C, O )
TF_BUILTIN(OrdinaryHasInstance, ObjectBuiltinsAssembler) {
TNode<Object> constructor = CAST(Parameter(Descriptor::kLeft));

View File

@ -1177,6 +1177,16 @@ FieldAccess AccessBuilder::ForFeedbackCellValue() {
return access;
}
// static
FieldAccess AccessBuilder::ForFeedbackVectorClosureFeedbackCellArray() {
FieldAccess access = {
kTaggedBase, FeedbackVector::kClosureFeedbackCellArrayOffset,
Handle<Name>(), MaybeHandle<Map>(),
Type::Any(), MachineType::TaggedPointer(),
kFullWriteBarrier};
return access;
}
} // namespace compiler
} // namespace internal
} // namespace v8

View File

@ -330,6 +330,9 @@ class V8_EXPORT_PRIVATE AccessBuilder final
// Provides access to a FeedbackCell's value.
static FieldAccess ForFeedbackCellValue();
// Provides access to a FeedbackVector fields.
static FieldAccess ForFeedbackVectorClosureFeedbackCellArray();
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(AccessBuilder);
};

View File

@ -80,6 +80,8 @@ class BytecodeGraphBuilder {
return feedback_vector_node_;
}
Node* BuildLoadFeedbackCell(int index);
// Builder for loading the a native context field.
Node* BuildLoadNativeContextField(int index);
@ -183,7 +185,6 @@ class BytecodeGraphBuilder {
void BuildUnaryOp(const Operator* op);
void BuildBinaryOp(const Operator* op);
void BuildBinaryOpWithImmediate(const Operator* op);
void BuildInstanceOf(const Operator* op);
void BuildCompareOp(const Operator* op);
void BuildDelete(LanguageMode language_mode);
void BuildCastOperator(const Operator* op);
@ -1036,6 +1037,30 @@ Node* BytecodeGraphBuilder::BuildLoadFeedbackVector() {
return vector;
}
Node* BytecodeGraphBuilder::BuildLoadFeedbackCell(int index) {
if (native_context_independent()) {
Environment* env = environment();
Node* control = env->GetControlDependency();
Node* effect = env->GetEffectDependency();
// TODO(jgruber,v8:8888): Assumes that the feedback vector has been
// allocated.
Node* closure_feedback_cell_array = effect = graph()->NewNode(
simplified()->LoadField(
AccessBuilder::ForFeedbackVectorClosureFeedbackCellArray()),
feedback_vector_node(), effect, control);
Node* feedback_cell = effect = graph()->NewNode(
simplified()->LoadField(AccessBuilder::ForFixedArraySlot(index)),
closure_feedback_cell_array, effect, control);
env->UpdateEffectDependency(effect);
return feedback_cell;
} else {
return jsgraph()->Constant(feedback_vector().GetClosureFeedbackCell(index));
}
}
Node* BytecodeGraphBuilder::BuildLoadNativeContextField(int index) {
Node* result = NewNode(javascript()->LoadContext(0, index, true));
NodeProperties::ReplaceContextInput(result,
@ -2071,12 +2096,10 @@ void BytecodeGraphBuilder::VisitCreateClosure() {
const Operator* op = javascript()->CreateClosure(
shared_info.object(),
feedback_vector()
.GetClosureFeedbackCell(bytecode_iterator().GetIndexOperand(1))
.object(),
jsgraph()->isolate()->builtins()->builtin_handle(Builtins::kCompileLazy),
allocation);
Node* closure = NewNode(op);
Node* closure = NewNode(
op, BuildLoadFeedbackCell(bytecode_iterator().GetIndexOperand(1)));
environment()->BindAccumulator(closure);
}
@ -3067,29 +3090,6 @@ void BytecodeGraphBuilder::VisitGetSuperConstructor() {
Environment::kAttachFrameState);
}
void BytecodeGraphBuilder::BuildInstanceOf(const Operator* op) {
// TODO(jgruber, v8:8888): Treat InstanceOf like other compare ops.
DCHECK_EQ(op->opcode(), IrOpcode::kJSInstanceOf);
PrepareEagerCheckpoint();
Node* left =
environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
Node* right = environment()->LookupAccumulator();
FeedbackSlot slot = bytecode_iterator().GetSlotOperand(1);
JSTypeHintLowering::LoweringResult lowering =
TryBuildSimplifiedBinaryOp(op, left, right, slot);
if (lowering.IsExit()) return;
Node* node = nullptr;
if (lowering.IsSideEffectFree()) {
node = lowering.value();
} else {
DCHECK(!lowering.Changed());
node = NewNode(op, left, right);
}
environment()->BindAccumulator(node, Environment::kAttachFrameState);
}
void BytecodeGraphBuilder::BuildCompareOp(const Operator* op) {
DCHECK(JSOperator::IsBinaryWithFeedback(op->opcode()));
PrepareEagerCheckpoint();
@ -3172,8 +3172,9 @@ void BytecodeGraphBuilder::VisitTestIn() {
}
void BytecodeGraphBuilder::VisitTestInstanceOf() {
int const slot_index = bytecode_iterator().GetIndexOperand(1);
BuildInstanceOf(javascript()->InstanceOf(CreateFeedbackSource(slot_index)));
FeedbackSource feedback = CreateFeedbackSource(
bytecode_iterator().GetSlotOperand(kCompareOperationHintIndex));
BuildCompareOp(javascript()->InstanceOf(feedback));
}
void BytecodeGraphBuilder::VisitTestUndetectable() {

View File

@ -828,13 +828,13 @@ class PromiseBuiltinReducerAssembler : public JSCallReducerAssembler {
TNode<JSFunction> CreateClosureFromBuiltinSharedFunctionInfo(
SharedFunctionInfoRef shared, TNode<Context> context) {
DCHECK(shared.HasBuiltinId());
Handle<FeedbackCell> feedback_cell =
isolate()->factory()->many_closures_cell();
Callable const callable = Builtins::CallableFor(
isolate(), static_cast<Builtins::Name>(shared.builtin_id()));
return AddNode<JSFunction>(graph()->NewNode(
javascript()->CreateClosure(shared.object(),
isolate()->factory()->many_closures_cell(),
callable.code()),
context, effect(), control()));
javascript()->CreateClosure(shared.object(), callable.code()),
HeapConstant(feedback_cell), context, effect(), control()));
}
void CallPromiseExecutor(TNode<Object> executor, TNode<JSFunction> resolve,
@ -3987,7 +3987,7 @@ Reduction JSCallReducer::ReduceJSCall(Node* node) {
// the {target} must have the same native context as the call site.
// Same if the {target} is the result of a CheckClosure operation.
if (target->opcode() == IrOpcode::kJSCreateClosure) {
CreateClosureParameters const& p = CreateClosureParametersOf(target->op());
CreateClosureParameters const& p = JSCreateClosureNode{target}.Parameters();
return ReduceJSCall(node, SharedFunctionInfoRef(broker(), p.shared_info()));
} else if (target->opcode() == IrOpcode::kCheckClosure) {
FeedbackCellRef cell(broker(), FeedbackCellOf(target->op()));
@ -4495,8 +4495,12 @@ Reduction JSCallReducer::ReduceJSConstruct(Node* node) {
node, DeoptimizeReason::kInsufficientTypeFeedbackForConstruct);
}
// TODO(jgruber,v8:8888): Remove the special case for native context
// independent codegen below once we control available feedback through
// this flag.
base::Optional<HeapObjectRef> feedback_target = feedback.AsCall().target();
if (feedback_target.has_value() && feedback_target->IsAllocationSite()) {
if (feedback_target.has_value() && feedback_target->IsAllocationSite() &&
!broker()->is_native_context_independent()) {
// The feedback is an AllocationSite, which means we have called the
// Array function and collected transition (and pretenuring) feedback
// for the resulting arrays. This has to be kept in sync with the
@ -6341,12 +6345,13 @@ Reduction JSCallReducer::ReducePromisePrototypeCatch(Node* node) {
Node* JSCallReducer::CreateClosureFromBuiltinSharedFunctionInfo(
SharedFunctionInfoRef shared, Node* context, Node* effect, Node* control) {
DCHECK(shared.HasBuiltinId());
Handle<FeedbackCell> feedback_cell =
isolate()->factory()->many_closures_cell();
Callable const callable = Builtins::CallableFor(
isolate(), static_cast<Builtins::Name>(shared.builtin_id()));
return graph()->NewNode(
javascript()->CreateClosure(
shared.object(), factory()->many_closures_cell(), callable.code()),
context, effect, control);
javascript()->CreateClosure(shared.object(), callable.code()),
jsgraph()->HeapConstant(feedback_cell), context, effect, control);
}
// ES section #sec-promise.prototype.finally

View File

@ -924,14 +924,14 @@ Reduction JSCreateLowering::ReduceJSCreateBoundFunction(Node* node) {
}
Reduction JSCreateLowering::ReduceJSCreateClosure(Node* node) {
DCHECK_EQ(IrOpcode::kJSCreateClosure, node->opcode());
CreateClosureParameters const& p = CreateClosureParametersOf(node->op());
JSCreateClosureNode n(node);
CreateClosureParameters const& p = n.Parameters();
SharedFunctionInfoRef shared(broker(), p.shared_info());
FeedbackCellRef feedback_cell(broker(), p.feedback_cell());
FeedbackCellRef feedback_cell = n.GetFeedbackCellRefChecked(broker());
HeapObjectRef code(broker(), p.code());
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
Node* context = NodeProperties::GetContextInput(node);
Effect effect = n.effect();
Control control = n.control();
Node* context = n.context();
// Use inline allocation of closures only for instantiation sites that have
// seen more than one instantiation, this simplifies the generated code and

View File

@ -200,6 +200,7 @@ DEF_BINARY_LOWERING(Subtract)
DEF_BINARY_LOWERING(Equal)
DEF_BINARY_LOWERING(GreaterThan)
DEF_BINARY_LOWERING(GreaterThanOrEqual)
DEF_BINARY_LOWERING(InstanceOf)
DEF_BINARY_LOWERING(LessThan)
DEF_BINARY_LOWERING(LessThanOrEqual)
#undef DEF_BINARY_LOWERING
@ -247,9 +248,17 @@ bool ShouldUseMegamorphicLoadBuiltin(FeedbackSource const& source,
} // namespace
void JSGenericLowering::LowerJSHasProperty(Node* node) {
// TODO(jgruber,v8:8888): Collect feedback.
node->RemoveInput(JSHasPropertyNode::FeedbackVectorIndex());
ReplaceWithBuiltinCall(node, Builtins::kHasProperty);
JSHasPropertyNode n(node);
const PropertyAccess& p = n.Parameters();
if (!p.feedback().IsValid()) {
node->RemoveInput(JSHasPropertyNode::FeedbackVectorIndex());
ReplaceWithBuiltinCall(node, Builtins::kHasProperty);
} else {
STATIC_ASSERT(n.FeedbackVectorIndex() == 2);
n->InsertInput(zone(), 2,
jsgraph()->TaggedIndexConstant(p.feedback().index()));
ReplaceWithBuiltinCall(node, Builtins::kKeyedHasIC);
}
}
void JSGenericLowering::LowerJSLoadProperty(Node* node) {
@ -471,11 +480,6 @@ void JSGenericLowering::LowerJSHasInPrototypeChain(Node* node) {
ReplaceWithRuntimeCall(node, Runtime::kHasInPrototypeChain);
}
void JSGenericLowering::LowerJSInstanceOf(Node* node) {
// TODO(jgruber, v8:8888): Collect feedback.
ReplaceWithBuiltinCall(node, Builtins::kInstanceOf);
}
void JSGenericLowering::LowerJSOrdinaryHasInstance(Node* node) {
ReplaceWithBuiltinCall(node, Builtins::kOrdinaryHasInstance);
}
@ -570,12 +574,11 @@ void JSGenericLowering::LowerJSRegExpTest(Node* node) {
}
void JSGenericLowering::LowerJSCreateClosure(Node* node) {
// TODO(jgruber,v8:8888): Load the feedback cell instead of embedding a
// (context-dependent) constant.
CreateClosureParameters const& p = CreateClosureParametersOf(node->op());
JSCreateClosureNode n(node);
CreateClosureParameters const& p = n.Parameters();
Handle<SharedFunctionInfo> const shared_info = p.shared_info();
STATIC_ASSERT(n.FeedbackCellIndex() == 0);
node->InsertInput(zone(), 0, jsgraph()->HeapConstant(shared_info));
node->InsertInput(zone(), 1, jsgraph()->HeapConstant(p.feedback_cell()));
node->RemoveInput(4); // control
// Use the FastNewClosure builtin only for functions allocated in new space.
@ -586,7 +589,6 @@ void JSGenericLowering::LowerJSCreateClosure(Node* node) {
}
}
void JSGenericLowering::LowerJSCreateFunctionContext(Node* node) {
const CreateFunctionContextParameters& parameters =
CreateFunctionContextParametersOf(node->op());

View File

@ -74,7 +74,6 @@ Reduction JSHeapCopyReducer::Reduce(Node* node) {
case IrOpcode::kJSCreateClosure: {
CreateClosureParameters const& p = CreateClosureParametersOf(node->op());
SharedFunctionInfoRef(broker(), p.shared_info());
FeedbackCellRef(broker(), p.feedback_cell());
HeapObjectRef(broker(), p.code());
break;
}

View File

@ -124,8 +124,9 @@ JSInliningHeuristic::Candidate JSInliningHeuristic::CollectFunctions(
}
if (m.IsJSCreateClosure()) {
DCHECK(!out.functions[0].has_value());
CreateClosureParameters const& p = CreateClosureParametersOf(m.op());
FeedbackCellRef feedback_cell(broker(), p.feedback_cell());
JSCreateClosureNode n(callee);
CreateClosureParameters const& p = n.Parameters();
FeedbackCellRef feedback_cell = n.GetFeedbackCellRefChecked(broker());
SharedFunctionInfoRef shared_info(broker(), p.shared_info());
out.shared_info = shared_info;
if (feedback_cell.value().IsFeedbackVector() &&

View File

@ -280,7 +280,8 @@ bool NeedsImplicitReceiver(SharedFunctionInfoRef shared_info) {
base::Optional<SharedFunctionInfoRef> JSInliner::DetermineCallTarget(
Node* node) {
DCHECK(IrOpcode::IsInlineeOpcode(node->opcode()));
HeapObjectMatcher match(node->InputAt(JSCallOrConstructNode::TargetIndex()));
Node* target = node->InputAt(JSCallOrConstructNode::TargetIndex());
HeapObjectMatcher match(target);
// This reducer can handle both normal function calls as well a constructor
// calls whenever the target is a constant function object, as follows:
@ -315,8 +316,8 @@ base::Optional<SharedFunctionInfoRef> JSInliner::DetermineCallTarget(
// - JSConstruct(JSCreateClosure[shared](context),
// new.target, args..., vector)
if (match.IsJSCreateClosure()) {
CreateClosureParameters const& p = CreateClosureParametersOf(match.op());
FeedbackCellRef cell(broker(), p.feedback_cell());
JSCreateClosureNode n(target);
FeedbackCellRef cell = n.GetFeedbackCellRefChecked(broker());
return cell.shared_function_info();
} else if (match.IsCheckClosure()) {
FeedbackCellRef cell(broker(), FeedbackCellOf(match.op()));
@ -334,7 +335,8 @@ base::Optional<SharedFunctionInfoRef> JSInliner::DetermineCallTarget(
FeedbackVectorRef JSInliner::DetermineCallContext(Node* node,
Node** context_out) {
DCHECK(IrOpcode::IsInlineeOpcode(node->opcode()));
HeapObjectMatcher match(node->InputAt(JSCallOrConstructNode::TargetIndex()));
Node* target = node->InputAt(JSCallOrConstructNode::TargetIndex());
HeapObjectMatcher match(target);
if (match.HasValue() && match.Ref(broker()).IsJSFunction()) {
JSFunctionRef function = match.Ref(broker()).AsJSFunction();
@ -347,11 +349,10 @@ FeedbackVectorRef JSInliner::DetermineCallContext(Node* node,
}
if (match.IsJSCreateClosure()) {
CreateClosureParameters const& p = CreateClosureParametersOf(match.op());
// Load the feedback vector of the target by looking up its vector cell at
// the instantiation site (we only decide to inline if it's populated).
FeedbackCellRef cell(broker(), p.feedback_cell());
JSCreateClosureNode n(target);
FeedbackCellRef cell = n.GetFeedbackCellRefChecked(broker());
// The inlinee uses the locally provided context at instantiation.
*context_out = NodeProperties::GetContextInput(match.node());

View File

@ -376,14 +376,14 @@ Reduction JSNativeContextSpecialization::ReduceJSGetSuperConstructor(
}
Reduction JSNativeContextSpecialization::ReduceJSInstanceOf(Node* node) {
DCHECK_EQ(IrOpcode::kJSInstanceOf, node->opcode());
FeedbackParameter const& p = FeedbackParameterOf(node->op());
Node* object = NodeProperties::GetValueInput(node, 0);
Node* constructor = NodeProperties::GetValueInput(node, 1);
Node* context = NodeProperties::GetContextInput(node);
Node* effect = NodeProperties::GetEffectInput(node);
Node* frame_state = NodeProperties::GetFrameStateInput(node);
Node* control = NodeProperties::GetControlInput(node);
JSInstanceOfNode n(node);
FeedbackParameter const& p = n.Parameters();
Node* object = n.left();
Node* constructor = n.right();
TNode<Object> context = n.context();
FrameState frame_state = n.frame_state();
Effect effect = n.effect();
Control control = n.control();
// Check if the right hand side is a known {receiver}, or
// we have feedback from the InstanceOfIC.
@ -441,6 +441,8 @@ Reduction JSNativeContextSpecialization::ReduceJSInstanceOf(Node* node) {
NodeProperties::ReplaceValueInput(node, constructor, 0);
NodeProperties::ReplaceValueInput(node, object, 1);
NodeProperties::ReplaceEffectInput(node, effect);
STATIC_ASSERT(n.FeedbackVectorIndex() == 2);
node->RemoveInput(n.FeedbackVectorIndex());
NodeProperties::ChangeOp(node, javascript()->OrdinaryHasInstance());
return Changed(node).FollowedBy(ReduceJSOrdinaryHasInstance(node));
}
@ -626,9 +628,14 @@ Reduction JSNativeContextSpecialization::ReduceJSOrdinaryHasInstance(
JSReceiverRef bound_target_function = function.bound_target_function();
NodeProperties::ReplaceValueInput(node, object, 0);
Node* feedback = jsgraph()->UndefinedConstant();
NodeProperties::ReplaceValueInput(node, object,
JSInstanceOfNode::LeftIndex());
NodeProperties::ReplaceValueInput(
node, jsgraph()->Constant(bound_target_function), 1);
node, jsgraph()->Constant(bound_target_function),
JSInstanceOfNode::RightIndex());
node->InsertInput(zone(), JSInstanceOfNode::FeedbackVectorIndex(),
feedback);
NodeProperties::ChangeOp(node, javascript()->InstanceOf(FeedbackSource()));
return Changed(node).FollowedBy(ReduceJSInstanceOf(node));
}

View File

@ -8,6 +8,7 @@
#include "src/base/lazy-instance.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/node-matchers.h"
#include "src/compiler/operator.h"
#include "src/handles/handles-inl.h"
#include "src/objects/objects-inl.h"
@ -36,6 +37,13 @@ TNode<Oddball> UndefinedConstant(JSGraph* jsgraph) {
} // namespace js_node_wrapper_utils
FeedbackCellRef JSCreateClosureNode::GetFeedbackCellRefChecked(
JSHeapBroker* broker) const {
HeapObjectMatcher m(feedback_cell());
CHECK(m.HasValue());
return FeedbackCellRef(broker, m.Value());
}
std::ostream& operator<<(std::ostream& os, CallFrequency const& f) {
if (f.IsUnknown()) return os << "unknown";
return os << f.value();
@ -523,7 +531,6 @@ bool operator==(CreateClosureParameters const& lhs,
CreateClosureParameters const& rhs) {
return lhs.allocation() == rhs.allocation() &&
lhs.code().location() == rhs.code().location() &&
lhs.feedback_cell().location() == rhs.feedback_cell().location() &&
lhs.shared_info().location() == rhs.shared_info().location();
}
@ -535,14 +542,13 @@ bool operator!=(CreateClosureParameters const& lhs,
size_t hash_value(CreateClosureParameters const& p) {
return base::hash_combine(p.allocation(), p.shared_info().location(),
p.feedback_cell().location());
return base::hash_combine(p.allocation(), p.shared_info().location());
}
std::ostream& operator<<(std::ostream& os, CreateClosureParameters const& p) {
return os << p.allocation() << ", " << Brief(*p.shared_info()) << ", "
<< Brief(*p.feedback_cell()) << ", " << Brief(*p.code());
<< Brief(*p.code());
}
@ -941,15 +947,6 @@ const Operator* JSOperatorBuilder::HasProperty(FeedbackSource const& feedback) {
access); // parameter
}
const Operator* JSOperatorBuilder::InstanceOf(FeedbackSource const& feedback) {
FeedbackParameter parameter(feedback);
return new (zone()) Operator1<FeedbackParameter>( // --
IrOpcode::kJSInstanceOf, Operator::kNoProperties, // opcode
"JSInstanceOf", // name
2, 1, 1, 1, 1, 2, // counts
parameter); // parameter
}
const Operator* JSOperatorBuilder::ForInNext(ForInMode mode) {
return new (zone()) Operator1<ForInMode>( // --
IrOpcode::kJSForInNext, Operator::kNoProperties, // opcode
@ -1188,14 +1185,15 @@ const Operator* JSOperatorBuilder::CreateBoundFunction(size_t arity,
}
const Operator* JSOperatorBuilder::CreateClosure(
Handle<SharedFunctionInfo> shared_info, Handle<FeedbackCell> feedback_cell,
Handle<Code> code, AllocationType allocation) {
CreateClosureParameters parameters(shared_info, feedback_cell, code,
allocation);
Handle<SharedFunctionInfo> shared_info, Handle<Code> code,
AllocationType allocation) {
static constexpr int kFeedbackCell = 1;
static constexpr int kArity = kFeedbackCell;
CreateClosureParameters parameters(shared_info, code, allocation);
return new (zone()) Operator1<CreateClosureParameters>( // --
IrOpcode::kJSCreateClosure, Operator::kEliminatable, // opcode
"JSCreateClosure", // name
0, 1, 1, 1, 1, 0, // counts
kArity, 1, 1, 1, 1, 0, // counts
parameters); // parameter
}

View File

@ -40,7 +40,8 @@ struct JSOperatorGlobalCache;
#define JS_BINOP_WITH_FEEDBACK(V) \
JS_ARITH_BINOP_LIST(V) \
JS_BITWISE_BINOP_LIST(V) \
JS_COMPARE_BINOP_LIST(V)
JS_COMPARE_BINOP_LIST(V) \
V(JSInstanceOf, InstanceOf)
// Predicates.
class JSOperator final : public AllStatic {
@ -657,21 +658,15 @@ const CreateBoundFunctionParameters& CreateBoundFunctionParametersOf(
class CreateClosureParameters final {
public:
CreateClosureParameters(Handle<SharedFunctionInfo> shared_info,
Handle<FeedbackCell> feedback_cell, Handle<Code> code,
AllocationType allocation)
: shared_info_(shared_info),
feedback_cell_(feedback_cell),
code_(code),
allocation_(allocation) {}
Handle<Code> code, AllocationType allocation)
: shared_info_(shared_info), code_(code), allocation_(allocation) {}
Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
Handle<FeedbackCell> feedback_cell() const { return feedback_cell_; }
Handle<Code> code() const { return code_; }
AllocationType allocation() const { return allocation_; }
private:
Handle<SharedFunctionInfo> const shared_info_;
Handle<FeedbackCell> const feedback_cell_;
Handle<Code> const code_;
AllocationType const allocation_;
};
@ -863,8 +858,7 @@ class V8_EXPORT_PRIVATE JSOperatorBuilder final
const Operator* CreateCollectionIterator(CollectionKind, IterationKind);
const Operator* CreateBoundFunction(size_t arity, Handle<Map> map);
const Operator* CreateClosure(
Handle<SharedFunctionInfo> shared_info,
Handle<FeedbackCell> feedback_cell, Handle<Code> code,
Handle<SharedFunctionInfo> shared_info, Handle<Code> code,
AllocationType allocation = AllocationType::kYoung);
const Operator* CreateIterResultObject();
const Operator* CreateStringIterator();
@ -1078,6 +1072,10 @@ class JSBinaryOpNode final : public JSNodeWrapperBase {
CONSTEXPR_DCHECK(JSOperator::IsBinaryWithFeedback(node->opcode()));
}
const FeedbackParameter& Parameters() const {
return FeedbackParameterOf(node()->op());
}
#define INPUTS(V) \
V(Left, left, 0, Object) \
V(Right, right, 1, Object) \
@ -1512,6 +1510,23 @@ class JSStoreInArrayLiteralNode final : public JSNodeWrapperBase {
#undef INPUTS
};
class JSCreateClosureNode final : public JSNodeWrapperBase {
public:
explicit constexpr JSCreateClosureNode(Node* node) : JSNodeWrapperBase(node) {
CONSTEXPR_DCHECK(node->opcode() == IrOpcode::kJSCreateClosure);
}
const CreateClosureParameters& Parameters() const {
return CreateClosureParametersOf(node()->op());
}
#define INPUTS(V) V(FeedbackCell, feedback_cell, 0, FeedbackCell)
INPUTS(DEFINE_INPUT_ACCESSORS)
#undef INPUTS
FeedbackCellRef GetFeedbackCellRefChecked(JSHeapBroker* broker) const;
};
#undef DEFINE_INPUT_ACCESSORS
} // namespace compiler

View File

@ -1735,7 +1735,7 @@ Reduction JSTypedLowering::ReduceJSCall(Node* node) {
shared = function->shared();
} else if (target->opcode() == IrOpcode::kJSCreateClosure) {
CreateClosureParameters const& ccp =
CreateClosureParametersOf(target->op());
JSCreateClosureNode{target}.Parameters();
shared = SharedFunctionInfoRef(broker(), ccp.shared_info());
} else if (target->opcode() == IrOpcode::kCheckClosure) {
FeedbackCellRef cell(broker(), FeedbackCellOf(target->op()));

View File

@ -109,8 +109,8 @@ void PropertyAccessBuilder::BuildCheckMaps(
*effect, control);
}
Node* PropertyAccessBuilder::BuildCheckValue(Node* receiver, Node** effect,
Node* control,
Node* PropertyAccessBuilder::BuildCheckValue(Node* receiver, Effect* effect,
Control control,
Handle<HeapObject> value) {
HeapObjectMatcher m(receiver);
if (m.Is(value)) return receiver;

View File

@ -9,6 +9,7 @@
#include "src/codegen/machine-type.h"
#include "src/compiler/js-heap-broker.h"
#include "src/compiler/node.h"
#include "src/handles/handles.h"
#include "src/objects/map.h"
#include "src/zone/zone-containers.h"
@ -22,7 +23,6 @@ class CompilationDependencies;
class Graph;
class JSGraph;
class JSHeapBroker;
class Node;
class PropertyAccessInfo;
class SimplifiedOperatorBuilder;
@ -42,9 +42,18 @@ class PropertyAccessBuilder {
ZoneVector<Handle<Map>> const& maps, Node** receiver,
Node** effect, Node* control);
// TODO(jgruber): Remove the untyped version once all uses are
// updated.
void BuildCheckMaps(Node* receiver, Node** effect, Node* control,
ZoneVector<Handle<Map>> const& receiver_maps);
Node* BuildCheckValue(Node* receiver, Node** effect, Node* control,
void BuildCheckMaps(Node* receiver, Effect* effect, Control control,
ZoneVector<Handle<Map>> const& receiver_maps) {
Node* e = *effect;
Node* c = control;
BuildCheckMaps(receiver, &e, c, receiver_maps);
*effect = e;
}
Node* BuildCheckValue(Node* receiver, Effect* effect, Control control,
Handle<HeapObject> value);
// Builds the actual load for data-field and data-constant-field