summaryrefslogtreecommitdiff
path: root/chromium/v8/src/compiler/js-generic-lowering.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/v8/src/compiler/js-generic-lowering.cc')
-rw-r--r--chromium/v8/src/compiler/js-generic-lowering.cc739
1 files changed, 483 insertions, 256 deletions
diff --git a/chromium/v8/src/compiler/js-generic-lowering.cc b/chromium/v8/src/compiler/js-generic-lowering.cc
index cedb5bc42d5..8dbb64fe662 100644
--- a/chromium/v8/src/compiler/js-generic-lowering.cc
+++ b/chromium/v8/src/compiler/js-generic-lowering.cc
@@ -18,6 +18,7 @@
#include "src/objects/feedback-cell.h"
#include "src/objects/feedback-vector.h"
#include "src/objects/scope-info.h"
+#include "src/objects/template-objects-inl.h"
namespace v8 {
namespace internal {
@@ -42,10 +43,10 @@ JSGenericLowering::~JSGenericLowering() = default;
Reduction JSGenericLowering::Reduce(Node* node) {
switch (node->opcode()) {
-#define DECLARE_CASE(x) \
- case IrOpcode::k##x: \
- Lower##x(node); \
- break;
+#define DECLARE_CASE(x, ...) \
+ case IrOpcode::k##x: \
+ Lower##x(node); \
+ break;
JS_OP_LIST(DECLARE_CASE)
#undef DECLARE_CASE
default:
@@ -55,34 +56,11 @@ Reduction JSGenericLowering::Reduce(Node* node) {
return Changed(node);
}
-#define REPLACE_STUB_CALL(Name) \
- void JSGenericLowering::LowerJS##Name(Node* node) { \
- CallDescriptor::Flags flags = FrameStateFlagForCall(node); \
- Callable callable = Builtins::CallableFor(isolate(), Builtins::k##Name); \
- ReplaceWithStubCall(node, callable, flags); \
+#define REPLACE_STUB_CALL(Name) \
+ void JSGenericLowering::LowerJS##Name(Node* node) { \
+ ReplaceWithBuiltinCall(node, Builtins::k##Name); \
}
-REPLACE_STUB_CALL(Add)
-REPLACE_STUB_CALL(Subtract)
-REPLACE_STUB_CALL(Multiply)
-REPLACE_STUB_CALL(Divide)
-REPLACE_STUB_CALL(Modulus)
-REPLACE_STUB_CALL(Exponentiate)
-REPLACE_STUB_CALL(BitwiseAnd)
-REPLACE_STUB_CALL(BitwiseOr)
-REPLACE_STUB_CALL(BitwiseXor)
-REPLACE_STUB_CALL(ShiftLeft)
-REPLACE_STUB_CALL(ShiftRight)
-REPLACE_STUB_CALL(ShiftRightLogical)
-REPLACE_STUB_CALL(LessThan)
-REPLACE_STUB_CALL(LessThanOrEqual)
-REPLACE_STUB_CALL(GreaterThan)
-REPLACE_STUB_CALL(GreaterThanOrEqual)
-REPLACE_STUB_CALL(BitwiseNot)
-REPLACE_STUB_CALL(Decrement)
-REPLACE_STUB_CALL(Increment)
-REPLACE_STUB_CALL(Negate)
REPLACE_STUB_CALL(HasProperty)
-REPLACE_STUB_CALL(Equal)
REPLACE_STUB_CALL(ToLength)
REPLACE_STUB_CALL(ToNumber)
REPLACE_STUB_CALL(ToNumberConvertBigInt)
@@ -101,16 +79,21 @@ REPLACE_STUB_CALL(RejectPromise)
REPLACE_STUB_CALL(ResolvePromise)
#undef REPLACE_STUB_CALL
-void JSGenericLowering::ReplaceWithStubCall(Node* node,
- Callable callable,
- CallDescriptor::Flags flags) {
- ReplaceWithStubCall(node, callable, flags, node->op()->properties());
+void JSGenericLowering::ReplaceWithBuiltinCall(Node* node,
+ Builtins::Name builtin) {
+ CallDescriptor::Flags flags = FrameStateFlagForCall(node);
+ Callable callable = Builtins::CallableFor(isolate(), builtin);
+ ReplaceWithBuiltinCall(node, callable, flags);
}
-void JSGenericLowering::ReplaceWithStubCall(Node* node,
- Callable callable,
- CallDescriptor::Flags flags,
- Operator::Properties properties) {
+void JSGenericLowering::ReplaceWithBuiltinCall(Node* node, Callable callable,
+ CallDescriptor::Flags flags) {
+ ReplaceWithBuiltinCall(node, callable, flags, node->op()->properties());
+}
+
+void JSGenericLowering::ReplaceWithBuiltinCall(
+ Node* node, Callable callable, CallDescriptor::Flags flags,
+ Operator::Properties properties) {
const CallInterfaceDescriptor& descriptor = callable.descriptor();
auto call_descriptor = Linkage::GetStubCallDescriptor(
zone(), descriptor, descriptor.GetStackParameterCount(), flags,
@@ -120,7 +103,6 @@ void JSGenericLowering::ReplaceWithStubCall(Node* node,
NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
}
-
void JSGenericLowering::ReplaceWithRuntimeCall(Node* node,
Runtime::FunctionId f,
int nargs_override) {
@@ -138,13 +120,114 @@ void JSGenericLowering::ReplaceWithRuntimeCall(Node* node,
NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
}
+void JSGenericLowering::ReplaceUnaryOpWithBuiltinCall(
+ Node* node, Builtins::Name builtin_without_feedback,
+ Builtins::Name builtin_with_feedback) {
+ DCHECK(JSOperator::IsUnaryWithFeedback(node->opcode()));
+ const FeedbackParameter& p = FeedbackParameterOf(node->op());
+ if (CollectFeedbackInGenericLowering() && p.feedback().IsValid()) {
+ Callable callable = Builtins::CallableFor(isolate(), builtin_with_feedback);
+ Node* slot = jsgraph()->UintPtrConstant(p.feedback().slot.ToInt());
+ const CallInterfaceDescriptor& descriptor = callable.descriptor();
+ CallDescriptor::Flags flags = FrameStateFlagForCall(node);
+ auto call_descriptor = Linkage::GetStubCallDescriptor(
+ zone(), descriptor, descriptor.GetStackParameterCount(), flags,
+ node->op()->properties());
+ Node* stub_code = jsgraph()->HeapConstant(callable.code());
+ STATIC_ASSERT(JSUnaryOpNode::ValueIndex() == 0);
+ STATIC_ASSERT(JSUnaryOpNode::FeedbackVectorIndex() == 1);
+ DCHECK_EQ(node->op()->ValueInputCount(), 2);
+ node->InsertInput(zone(), 0, stub_code);
+ node->InsertInput(zone(), 2, slot);
+ NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
+ } else {
+ node->RemoveInput(JSUnaryOpNode::FeedbackVectorIndex());
+ ReplaceWithBuiltinCall(node, builtin_without_feedback);
+ }
+}
+
+#define DEF_UNARY_LOWERING(Name) \
+ void JSGenericLowering::LowerJS##Name(Node* node) { \
+ ReplaceUnaryOpWithBuiltinCall(node, Builtins::k##Name, \
+ Builtins::k##Name##_WithFeedback); \
+ }
+DEF_UNARY_LOWERING(BitwiseNot)
+DEF_UNARY_LOWERING(Decrement)
+DEF_UNARY_LOWERING(Increment)
+DEF_UNARY_LOWERING(Negate)
+#undef DEF_UNARY_LOWERING
+
+void JSGenericLowering::ReplaceBinaryOpWithBuiltinCall(
+ Node* node, Builtins::Name builtin_without_feedback,
+ Builtins::Name builtin_with_feedback) {
+ DCHECK(JSOperator::IsBinaryWithFeedback(node->opcode()));
+ Builtins::Name builtin_id;
+ const FeedbackParameter& p = FeedbackParameterOf(node->op());
+ if (CollectFeedbackInGenericLowering() && p.feedback().IsValid()) {
+ Node* slot = jsgraph()->UintPtrConstant(p.feedback().slot.ToInt());
+ STATIC_ASSERT(JSBinaryOpNode::LeftIndex() == 0);
+ STATIC_ASSERT(JSBinaryOpNode::RightIndex() == 1);
+ STATIC_ASSERT(JSBinaryOpNode::FeedbackVectorIndex() == 2);
+ DCHECK_EQ(node->op()->ValueInputCount(), 3);
+ node->InsertInput(zone(), 2, slot);
+ builtin_id = builtin_with_feedback;
+ } else {
+ node->RemoveInput(JSBinaryOpNode::FeedbackVectorIndex());
+ builtin_id = builtin_without_feedback;
+ }
+
+ ReplaceWithBuiltinCall(node, builtin_id);
+}
+
+#define DEF_BINARY_LOWERING(Name) \
+ void JSGenericLowering::LowerJS##Name(Node* node) { \
+ ReplaceBinaryOpWithBuiltinCall(node, Builtins::k##Name, \
+ Builtins::k##Name##_WithFeedback); \
+ }
+// Binary ops.
+DEF_BINARY_LOWERING(Add)
+DEF_BINARY_LOWERING(BitwiseAnd)
+DEF_BINARY_LOWERING(BitwiseOr)
+DEF_BINARY_LOWERING(BitwiseXor)
+DEF_BINARY_LOWERING(Divide)
+DEF_BINARY_LOWERING(Exponentiate)
+DEF_BINARY_LOWERING(Modulus)
+DEF_BINARY_LOWERING(Multiply)
+DEF_BINARY_LOWERING(ShiftLeft)
+DEF_BINARY_LOWERING(ShiftRight)
+DEF_BINARY_LOWERING(ShiftRightLogical)
+DEF_BINARY_LOWERING(Subtract)
+// Compare ops.
+DEF_BINARY_LOWERING(Equal)
+DEF_BINARY_LOWERING(GreaterThan)
+DEF_BINARY_LOWERING(GreaterThanOrEqual)
+DEF_BINARY_LOWERING(LessThan)
+DEF_BINARY_LOWERING(LessThanOrEqual)
+#undef DEF_BINARY_LOWERING
+
void JSGenericLowering::LowerJSStrictEqual(Node* node) {
// The === operator doesn't need the current context.
NodeProperties::ReplaceContextInput(node, jsgraph()->NoContextConstant());
- Callable callable = Builtins::CallableFor(isolate(), Builtins::kStrictEqual);
- node->RemoveInput(4); // control
- ReplaceWithStubCall(node, callable, CallDescriptor::kNoFlags,
- Operator::kEliminatable);
+ node->RemoveInput(NodeProperties::FirstControlIndex(node));
+
+ Builtins::Name builtin_id;
+ const FeedbackParameter& p = FeedbackParameterOf(node->op());
+ if (CollectFeedbackInGenericLowering() && p.feedback().IsValid()) {
+ Node* slot = jsgraph()->UintPtrConstant(p.feedback().slot.ToInt());
+ STATIC_ASSERT(JSStrictEqualNode::LeftIndex() == 0);
+ STATIC_ASSERT(JSStrictEqualNode::RightIndex() == 1);
+ STATIC_ASSERT(JSStrictEqualNode::FeedbackVectorIndex() == 2);
+ DCHECK_EQ(node->op()->ValueInputCount(), 3);
+ node->InsertInput(zone(), 2, slot);
+ builtin_id = Builtins::kStrictEqual_WithFeedback;
+ } else {
+ node->RemoveInput(JSStrictEqualNode::FeedbackVectorIndex());
+ builtin_id = Builtins::kStrictEqual;
+ }
+
+ Callable callable = Builtins::CallableFor(isolate(), builtin_id);
+ ReplaceWithBuiltinCall(node, callable, CallDescriptor::kNoFlags,
+ Operator::kEliminatable);
}
namespace {
@@ -164,57 +247,49 @@ bool ShouldUseMegamorphicLoadBuiltin(FeedbackSource const& source,
} // namespace
void JSGenericLowering::LowerJSLoadProperty(Node* node) {
- CallDescriptor::Flags flags = FrameStateFlagForCall(node);
const PropertyAccess& p = PropertyAccessOf(node->op());
Node* frame_state = NodeProperties::GetFrameStateInput(node);
Node* outer_state = frame_state->InputAt(kFrameStateOuterStateInput);
node->InsertInput(zone(), 2,
jsgraph()->TaggedIndexConstant(p.feedback().index()));
if (outer_state->opcode() != IrOpcode::kFrameState) {
- Callable callable = Builtins::CallableFor(
- isolate(), ShouldUseMegamorphicLoadBuiltin(p.feedback(), broker())
- ? Builtins::kKeyedLoadICTrampoline_Megamorphic
- : Builtins::kKeyedLoadICTrampoline);
- ReplaceWithStubCall(node, callable, flags);
+ ReplaceWithBuiltinCall(
+ node, ShouldUseMegamorphicLoadBuiltin(p.feedback(), broker())
+ ? Builtins::kKeyedLoadICTrampoline_Megamorphic
+ : Builtins::kKeyedLoadICTrampoline);
} else {
- Callable callable = Builtins::CallableFor(
- isolate(), ShouldUseMegamorphicLoadBuiltin(p.feedback(), broker())
- ? Builtins::kKeyedLoadIC_Megamorphic
- : Builtins::kKeyedLoadIC);
Node* vector = jsgraph()->HeapConstant(p.feedback().vector);
node->InsertInput(zone(), 3, vector);
- ReplaceWithStubCall(node, callable, flags);
+ ReplaceWithBuiltinCall(
+ node, ShouldUseMegamorphicLoadBuiltin(p.feedback(), broker())
+ ? Builtins::kKeyedLoadIC_Megamorphic
+ : Builtins::kKeyedLoadIC);
}
}
void JSGenericLowering::LowerJSLoadNamed(Node* node) {
- CallDescriptor::Flags flags = FrameStateFlagForCall(node);
NamedAccess const& p = NamedAccessOf(node->op());
Node* frame_state = NodeProperties::GetFrameStateInput(node);
Node* outer_state = frame_state->InputAt(kFrameStateOuterStateInput);
node->InsertInput(zone(), 1, jsgraph()->HeapConstant(p.name()));
if (!p.feedback().IsValid()) {
- Callable callable =
- Builtins::CallableFor(isolate(), Builtins::kGetProperty);
- ReplaceWithStubCall(node, callable, flags);
+ ReplaceWithBuiltinCall(node, Builtins::kGetProperty);
return;
}
node->InsertInput(zone(), 2,
jsgraph()->TaggedIndexConstant(p.feedback().index()));
if (outer_state->opcode() != IrOpcode::kFrameState) {
- Callable callable = Builtins::CallableFor(
- isolate(), ShouldUseMegamorphicLoadBuiltin(p.feedback(), broker())
- ? Builtins::kLoadICTrampoline_Megamorphic
- : Builtins::kLoadICTrampoline);
- ReplaceWithStubCall(node, callable, flags);
+ ReplaceWithBuiltinCall(
+ node, ShouldUseMegamorphicLoadBuiltin(p.feedback(), broker())
+ ? Builtins::kLoadICTrampoline_Megamorphic
+ : Builtins::kLoadICTrampoline);
} else {
- Callable callable = Builtins::CallableFor(
- isolate(), ShouldUseMegamorphicLoadBuiltin(p.feedback(), broker())
- ? Builtins::kLoadIC_Megamorphic
- : Builtins::kLoadIC);
Node* vector = jsgraph()->HeapConstant(p.feedback().vector);
node->InsertInput(zone(), 3, vector);
- ReplaceWithStubCall(node, callable, flags);
+ ReplaceWithBuiltinCall(
+ node, ShouldUseMegamorphicLoadBuiltin(p.feedback(), broker())
+ ? Builtins::kLoadIC_Megamorphic
+ : Builtins::kLoadIC);
}
}
@@ -228,50 +303,56 @@ void JSGenericLowering::LowerJSLoadGlobal(Node* node) {
jsgraph()->TaggedIndexConstant(p.feedback().index()));
if (outer_state->opcode() != IrOpcode::kFrameState) {
Callable callable = CodeFactory::LoadGlobalIC(isolate(), p.typeof_mode());
- ReplaceWithStubCall(node, callable, flags);
+ ReplaceWithBuiltinCall(node, callable, flags);
} else {
Callable callable =
CodeFactory::LoadGlobalICInOptimizedCode(isolate(), p.typeof_mode());
Node* vector = jsgraph()->HeapConstant(p.feedback().vector);
node->InsertInput(zone(), 2, vector);
- ReplaceWithStubCall(node, callable, flags);
+ ReplaceWithBuiltinCall(node, callable, flags);
}
}
void JSGenericLowering::LowerJSGetIterator(Node* node) {
// TODO(v8:9625): Currently, the GetIterator operator is desugared in the
// native context specialization phase. Thus, the following generic lowering
- // would never be reachable. We can add a check in native context
- // specialization to avoid desugaring the GetIterator operator when in the
- // case of megamorphic feedback and here, add a call to the
- // 'GetIteratorWithFeedback' builtin. This would reduce the size of the
- // compiled code as it would insert 1 call to the builtin instead of 2 calls
- // resulting from the generic lowering of the LoadNamed and Call operators.
- UNREACHABLE();
+ // is not reachable unless that phase is disabled (e.g. for
+ // native-context-independent code).
+ // We can add a check in native context specialization to avoid desugaring
+ // the GetIterator operator when feedback is megamorphic. This would reduce
+ // the size of the compiled code as it would insert 1 call to the builtin
+ // instead of 2 calls resulting from the generic lowering of the LoadNamed
+ // and Call operators.
+
+ GetIteratorParameters const& p = GetIteratorParametersOf(node->op());
+ Node* load_slot =
+ jsgraph()->TaggedIndexConstant(p.loadFeedback().slot.ToInt());
+ Node* call_slot =
+ jsgraph()->TaggedIndexConstant(p.callFeedback().slot.ToInt());
+ Node* feedback = jsgraph()->HeapConstant(p.callFeedback().vector);
+ node->InsertInput(zone(), 1, load_slot);
+ node->InsertInput(zone(), 2, call_slot);
+ node->InsertInput(zone(), 3, feedback);
+
+ ReplaceWithBuiltinCall(node, Builtins::kGetIteratorWithFeedback);
}
void JSGenericLowering::LowerJSStoreProperty(Node* node) {
- CallDescriptor::Flags flags = FrameStateFlagForCall(node);
PropertyAccess const& p = PropertyAccessOf(node->op());
Node* frame_state = NodeProperties::GetFrameStateInput(node);
Node* outer_state = frame_state->InputAt(kFrameStateOuterStateInput);
node->InsertInput(zone(), 3,
jsgraph()->TaggedIndexConstant(p.feedback().index()));
if (outer_state->opcode() != IrOpcode::kFrameState) {
- Callable callable =
- Builtins::CallableFor(isolate(), Builtins::kKeyedStoreICTrampoline);
- ReplaceWithStubCall(node, callable, flags);
+ ReplaceWithBuiltinCall(node, Builtins::kKeyedStoreICTrampoline);
} else {
- Callable callable =
- Builtins::CallableFor(isolate(), Builtins::kKeyedStoreIC);
Node* vector = jsgraph()->HeapConstant(p.feedback().vector);
node->InsertInput(zone(), 4, vector);
- ReplaceWithStubCall(node, callable, flags);
+ ReplaceWithBuiltinCall(node, Builtins::kKeyedStoreIC);
}
}
void JSGenericLowering::LowerJSStoreNamed(Node* node) {
- CallDescriptor::Flags flags = FrameStateFlagForCall(node);
NamedAccess const& p = NamedAccessOf(node->op());
Node* frame_state = NodeProperties::GetFrameStateInput(node);
Node* outer_state = frame_state->InputAt(kFrameStateOuterStateInput);
@@ -283,14 +364,11 @@ void JSGenericLowering::LowerJSStoreNamed(Node* node) {
node->InsertInput(zone(), 3,
jsgraph()->TaggedIndexConstant(p.feedback().index()));
if (outer_state->opcode() != IrOpcode::kFrameState) {
- Callable callable =
- Builtins::CallableFor(isolate(), Builtins::kStoreICTrampoline);
- ReplaceWithStubCall(node, callable, flags);
+ ReplaceWithBuiltinCall(node, Builtins::kStoreICTrampoline);
} else {
- Callable callable = Builtins::CallableFor(isolate(), Builtins::kStoreIC);
Node* vector = jsgraph()->HeapConstant(p.feedback().vector);
node->InsertInput(zone(), 4, vector);
- ReplaceWithStubCall(node, callable, flags);
+ ReplaceWithBuiltinCall(node, Builtins::kStoreIC);
}
}
@@ -304,17 +382,16 @@ void JSGenericLowering::LowerJSStoreNamedOwn(Node* node) {
jsgraph()->TaggedIndexConstant(p.feedback().index()));
if (outer_state->opcode() != IrOpcode::kFrameState) {
Callable callable = CodeFactory::StoreOwnIC(isolate());
- ReplaceWithStubCall(node, callable, flags);
+ ReplaceWithBuiltinCall(node, callable, flags);
} else {
Callable callable = CodeFactory::StoreOwnICInOptimizedCode(isolate());
Node* vector = jsgraph()->HeapConstant(p.feedback().vector);
node->InsertInput(zone(), 4, vector);
- ReplaceWithStubCall(node, callable, flags);
+ ReplaceWithBuiltinCall(node, callable, flags);
}
}
void JSGenericLowering::LowerJSStoreGlobal(Node* node) {
- CallDescriptor::Flags flags = FrameStateFlagForCall(node);
const StoreGlobalParameters& p = StoreGlobalParametersOf(node->op());
Node* frame_state = NodeProperties::GetFrameStateInput(node);
Node* outer_state = frame_state->InputAt(kFrameStateOuterStateInput);
@@ -322,15 +399,11 @@ void JSGenericLowering::LowerJSStoreGlobal(Node* node) {
node->InsertInput(zone(), 2,
jsgraph()->TaggedIndexConstant(p.feedback().index()));
if (outer_state->opcode() != IrOpcode::kFrameState) {
- Callable callable =
- Builtins::CallableFor(isolate(), Builtins::kStoreGlobalICTrampoline);
- ReplaceWithStubCall(node, callable, flags);
+ ReplaceWithBuiltinCall(node, Builtins::kStoreGlobalICTrampoline);
} else {
- Callable callable =
- Builtins::CallableFor(isolate(), Builtins::kStoreGlobalIC);
Node* vector = jsgraph()->HeapConstant(p.feedback().vector);
node->InsertInput(zone(), 3, vector);
- ReplaceWithStubCall(node, callable, flags);
+ ReplaceWithBuiltinCall(node, Builtins::kStoreGlobalIC);
}
}
@@ -344,29 +417,20 @@ void JSGenericLowering::LowerJSStoreDataPropertyInLiteral(Node* node) {
}
void JSGenericLowering::LowerJSStoreInArrayLiteral(Node* node) {
- Callable callable =
- Builtins::CallableFor(isolate(), Builtins::kStoreInArrayLiteralIC);
- CallDescriptor::Flags flags = FrameStateFlagForCall(node);
FeedbackParameter const& p = FeedbackParameterOf(node->op());
RelaxControls(node);
node->InsertInput(zone(), 3,
jsgraph()->TaggedIndexConstant(p.feedback().index()));
node->InsertInput(zone(), 4, jsgraph()->HeapConstant(p.feedback().vector));
- ReplaceWithStubCall(node, callable, flags);
+ ReplaceWithBuiltinCall(node, Builtins::kStoreInArrayLiteralIC);
}
void JSGenericLowering::LowerJSDeleteProperty(Node* node) {
- CallDescriptor::Flags flags = FrameStateFlagForCall(node);
- Callable callable =
- Builtins::CallableFor(isolate(), Builtins::kDeleteProperty);
- ReplaceWithStubCall(node, callable, flags);
+ ReplaceWithBuiltinCall(node, Builtins::kDeleteProperty);
}
void JSGenericLowering::LowerJSGetSuperConstructor(Node* node) {
- CallDescriptor::Flags flags = FrameStateFlagForCall(node);
- Callable callable =
- Builtins::CallableFor(isolate(), Builtins::kGetSuperConstructor);
- ReplaceWithStubCall(node, callable, flags);
+ ReplaceWithBuiltinCall(node, Builtins::kGetSuperConstructor);
}
void JSGenericLowering::LowerJSHasInPrototypeChain(Node* node) {
@@ -374,16 +438,12 @@ void JSGenericLowering::LowerJSHasInPrototypeChain(Node* node) {
}
void JSGenericLowering::LowerJSInstanceOf(Node* node) {
- CallDescriptor::Flags flags = FrameStateFlagForCall(node);
- Callable callable = Builtins::CallableFor(isolate(), Builtins::kInstanceOf);
- ReplaceWithStubCall(node, callable, flags);
+ // TODO(jgruber, v8:8888): Collect feedback.
+ ReplaceWithBuiltinCall(node, Builtins::kInstanceOf);
}
void JSGenericLowering::LowerJSOrdinaryHasInstance(Node* node) {
- CallDescriptor::Flags flags = FrameStateFlagForCall(node);
- Callable callable =
- Builtins::CallableFor(isolate(), Builtins::kOrdinaryHasInstance);
- ReplaceWithStubCall(node, callable, flags);
+ ReplaceWithBuiltinCall(node, Builtins::kOrdinaryHasInstance);
}
void JSGenericLowering::LowerJSHasContextExtension(Node* node) {
@@ -401,10 +461,7 @@ void JSGenericLowering::LowerJSStoreContext(Node* node) {
void JSGenericLowering::LowerJSCreate(Node* node) {
- CallDescriptor::Flags flags = FrameStateFlagForCall(node);
- Callable callable =
- Builtins::CallableFor(isolate(), Builtins::kFastNewObject);
- ReplaceWithStubCall(node, callable, flags);
+ ReplaceWithBuiltinCall(node, Builtins::kFastNewObject);
}
@@ -465,23 +522,15 @@ void JSGenericLowering::LowerJSObjectIsArray(Node* node) {
}
void JSGenericLowering::LowerJSCreateObject(Node* node) {
- CallDescriptor::Flags flags = FrameStateFlagForCall(node);
- Callable callable = Builtins::CallableFor(
- isolate(), Builtins::kCreateObjectWithoutProperties);
- ReplaceWithStubCall(node, callable, flags);
+ ReplaceWithBuiltinCall(node, Builtins::kCreateObjectWithoutProperties);
}
void JSGenericLowering::LowerJSParseInt(Node* node) {
- CallDescriptor::Flags flags = FrameStateFlagForCall(node);
- Callable callable = Builtins::CallableFor(isolate(), Builtins::kParseInt);
- ReplaceWithStubCall(node, callable, flags);
+ ReplaceWithBuiltinCall(node, Builtins::kParseInt);
}
void JSGenericLowering::LowerJSRegExpTest(Node* node) {
- CallDescriptor::Flags flags = FrameStateFlagForCall(node);
- Callable callable =
- Builtins::CallableFor(isolate(), Builtins::kRegExpPrototypeTestFast);
- ReplaceWithStubCall(node, callable, flags);
+ ReplaceWithBuiltinCall(node, Builtins::kRegExpPrototypeTestFast);
}
void JSGenericLowering::LowerJSCreateClosure(Node* node) {
@@ -493,10 +542,7 @@ void JSGenericLowering::LowerJSCreateClosure(Node* node) {
// Use the FastNewClosure builtin only for functions allocated in new space.
if (p.allocation() == AllocationType::kYoung) {
- Callable callable =
- Builtins::CallableFor(isolate(), Builtins::kFastNewClosure);
- CallDescriptor::Flags flags = FrameStateFlagForCall(node);
- ReplaceWithStubCall(node, callable, flags);
+ ReplaceWithBuiltinCall(node, Builtins::kFastNewClosure);
} else {
ReplaceWithRuntimeCall(node, Runtime::kNewClosure_Tenured);
}
@@ -516,7 +562,7 @@ void JSGenericLowering::LowerJSCreateFunctionContext(Node* node) {
CodeFactory::FastNewFunctionContext(isolate(), scope_type);
node->InsertInput(zone(), 0, jsgraph()->HeapConstant(scope_info));
node->InsertInput(zone(), 1, jsgraph()->Int32Constant(slot_count));
- ReplaceWithStubCall(node, callable, flags);
+ ReplaceWithBuiltinCall(node, callable, flags);
} else {
node->InsertInput(zone(), 0, jsgraph()->HeapConstant(scope_info));
ReplaceWithRuntimeCall(node, Runtime::kNewFunctionContext);
@@ -524,15 +570,12 @@ void JSGenericLowering::LowerJSCreateFunctionContext(Node* node) {
}
void JSGenericLowering::LowerJSCreateGeneratorObject(Node* node) {
- CallDescriptor::Flags flags = FrameStateFlagForCall(node);
- Callable callable =
- Builtins::CallableFor(isolate(), Builtins::kCreateGeneratorObject);
node->RemoveInput(4); // control
- ReplaceWithStubCall(node, callable, flags);
+ ReplaceWithBuiltinCall(node, Builtins::kCreateGeneratorObject);
}
void JSGenericLowering::LowerJSCreateIterResultObject(Node* node) {
- UNREACHABLE(); // Eliminated in typed lowering.
+ ReplaceWithBuiltinCall(node, Builtins::kCreateIterResultObject);
}
void JSGenericLowering::LowerJSCreateStringIterator(Node* node) {
@@ -548,15 +591,11 @@ void JSGenericLowering::LowerJSCreatePromise(Node* node) {
}
void JSGenericLowering::LowerJSCreateTypedArray(Node* node) {
- CallDescriptor::Flags flags = FrameStateFlagForCall(node);
- Callable callable =
- Builtins::CallableFor(isolate(), Builtins::kCreateTypedArray);
- ReplaceWithStubCall(node, callable, flags);
+ ReplaceWithBuiltinCall(node, Builtins::kCreateTypedArray);
}
void JSGenericLowering::LowerJSCreateLiteralArray(Node* node) {
CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
- CallDescriptor::Flags flags = FrameStateFlagForCall(node);
node->InsertInput(zone(), 0, jsgraph()->HeapConstant(p.feedback().vector));
node->InsertInput(zone(), 1,
jsgraph()->TaggedIndexConstant(p.feedback().index()));
@@ -566,9 +605,7 @@ void JSGenericLowering::LowerJSCreateLiteralArray(Node* node) {
// without properties up to the number of elements that the stubs can handle.
if ((p.flags() & AggregateLiteral::kIsShallow) != 0 &&
p.length() < ConstructorBuiltins::kMaximumClonedShallowArrayElements) {
- Callable callable =
- Builtins::CallableFor(isolate(), Builtins::kCreateShallowArrayLiteral);
- ReplaceWithStubCall(node, callable, flags);
+ ReplaceWithBuiltinCall(node, Builtins::kCreateShallowArrayLiteral);
} else {
node->InsertInput(zone(), 3, jsgraph()->SmiConstant(p.flags()));
ReplaceWithRuntimeCall(node, Runtime::kCreateArrayLiteral);
@@ -576,31 +613,36 @@ void JSGenericLowering::LowerJSCreateLiteralArray(Node* node) {
}
void JSGenericLowering::LowerJSGetTemplateObject(Node* node) {
- UNREACHABLE(); // Eliminated in native context specialization.
+ GetTemplateObjectParameters const& p =
+ GetTemplateObjectParametersOf(node->op());
+ SharedFunctionInfoRef shared(broker(), p.shared());
+ TemplateObjectDescriptionRef description(broker(), p.description());
+
+ node->InsertInput(zone(), 0, jsgraph()->Constant(shared));
+ node->InsertInput(zone(), 1, jsgraph()->Constant(description));
+ node->InsertInput(zone(), 2,
+ jsgraph()->UintPtrConstant(p.feedback().index()));
+ node->InsertInput(zone(), 3, jsgraph()->HeapConstant(p.feedback().vector));
+ node->RemoveInput(6); // control
+
+ ReplaceWithBuiltinCall(node, Builtins::kGetTemplateObject);
}
void JSGenericLowering::LowerJSCreateEmptyLiteralArray(Node* node) {
- CallDescriptor::Flags flags = FrameStateFlagForCall(node);
FeedbackParameter const& p = FeedbackParameterOf(node->op());
node->InsertInput(zone(), 0, jsgraph()->HeapConstant(p.feedback().vector));
node->InsertInput(zone(), 1,
jsgraph()->TaggedIndexConstant(p.feedback().index()));
node->RemoveInput(4); // control
- Callable callable =
- Builtins::CallableFor(isolate(), Builtins::kCreateEmptyArrayLiteral);
- ReplaceWithStubCall(node, callable, flags);
+ ReplaceWithBuiltinCall(node, Builtins::kCreateEmptyArrayLiteral);
}
void JSGenericLowering::LowerJSCreateArrayFromIterable(Node* node) {
- CallDescriptor::Flags flags = FrameStateFlagForCall(node);
- Callable callable = Builtins::CallableFor(
- isolate(), Builtins::kIterableToListWithSymbolLookup);
- ReplaceWithStubCall(node, callable, flags);
+ ReplaceWithBuiltinCall(node, Builtins::kIterableToListWithSymbolLookup);
}
void JSGenericLowering::LowerJSCreateLiteralObject(Node* node) {
CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
- CallDescriptor::Flags flags = FrameStateFlagForCall(node);
node->InsertInput(zone(), 0, jsgraph()->HeapConstant(p.feedback().vector));
node->InsertInput(zone(), 1,
jsgraph()->TaggedIndexConstant(p.feedback().index()));
@@ -612,9 +654,7 @@ void JSGenericLowering::LowerJSCreateLiteralObject(Node* node) {
if ((p.flags() & AggregateLiteral::kIsShallow) != 0 &&
p.length() <=
ConstructorBuiltins::kMaximumClonedShallowObjectProperties) {
- Callable callable =
- Builtins::CallableFor(isolate(), Builtins::kCreateShallowObjectLiteral);
- ReplaceWithStubCall(node, callable, flags);
+ ReplaceWithBuiltinCall(node, Builtins::kCreateShallowObjectLiteral);
} else {
ReplaceWithRuntimeCall(node, Runtime::kCreateObjectLiteral);
}
@@ -622,40 +662,38 @@ void JSGenericLowering::LowerJSCreateLiteralObject(Node* node) {
void JSGenericLowering::LowerJSCloneObject(Node* node) {
CloneObjectParameters const& p = CloneObjectParametersOf(node->op());
- CallDescriptor::Flags flags = FrameStateFlagForCall(node);
- Callable callable =
- Builtins::CallableFor(isolate(), Builtins::kCloneObjectIC);
node->InsertInput(zone(), 1, jsgraph()->SmiConstant(p.flags()));
node->InsertInput(zone(), 2,
jsgraph()->TaggedIndexConstant(p.feedback().index()));
node->InsertInput(zone(), 3, jsgraph()->HeapConstant(p.feedback().vector));
- ReplaceWithStubCall(node, callable, flags);
+ ReplaceWithBuiltinCall(node, Builtins::kCloneObjectIC);
}
void JSGenericLowering::LowerJSCreateEmptyLiteralObject(Node* node) {
- UNREACHABLE(); // Eliminated in typed lowering.
+ ReplaceWithBuiltinCall(node, Builtins::kCreateEmptyLiteralObject);
}
void JSGenericLowering::LowerJSCreateLiteralRegExp(Node* node) {
CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
- CallDescriptor::Flags flags = FrameStateFlagForCall(node);
- Callable callable =
- Builtins::CallableFor(isolate(), Builtins::kCreateRegExpLiteral);
node->InsertInput(zone(), 0, jsgraph()->HeapConstant(p.feedback().vector));
node->InsertInput(zone(), 1,
jsgraph()->TaggedIndexConstant(p.feedback().index()));
node->InsertInput(zone(), 2, jsgraph()->HeapConstant(p.constant()));
node->InsertInput(zone(), 3, jsgraph()->SmiConstant(p.flags()));
- ReplaceWithStubCall(node, callable, flags);
+ ReplaceWithBuiltinCall(node, Builtins::kCreateRegExpLiteral);
}
void JSGenericLowering::LowerJSCreateCatchContext(Node* node) {
- UNREACHABLE(); // Eliminated in typed lowering.
+ Handle<ScopeInfo> scope_info = ScopeInfoOf(node->op());
+ node->InsertInput(zone(), 1, jsgraph()->HeapConstant(scope_info));
+ ReplaceWithRuntimeCall(node, Runtime::kPushCatchContext);
}
void JSGenericLowering::LowerJSCreateWithContext(Node* node) {
- UNREACHABLE(); // Eliminated in typed lowering.
+ Handle<ScopeInfo> scope_info = ScopeInfoOf(node->op());
+ node->InsertInput(zone(), 1, jsgraph()->HeapConstant(scope_info));
+ ReplaceWithRuntimeCall(node, Runtime::kPushWithContext);
}
void JSGenericLowering::LowerJSCreateBlockContext(Node* node) {
@@ -688,64 +726,178 @@ void JSGenericLowering::LowerJSConstructForwardVarargs(Node* node) {
void JSGenericLowering::LowerJSConstruct(Node* node) {
ConstructParameters const& p = ConstructParametersOf(node->op());
- int const arg_count = static_cast<int>(p.arity() - 2);
+ int const arg_count = p.arity_without_implicit_args();
CallDescriptor::Flags flags = FrameStateFlagForCall(node);
- Callable callable = CodeFactory::Construct(isolate());
- auto call_descriptor = Linkage::GetStubCallDescriptor(
- zone(), callable.descriptor(), arg_count + 1, flags);
- Node* stub_code = jsgraph()->HeapConstant(callable.code());
- Node* stub_arity = jsgraph()->Int32Constant(arg_count);
- Node* new_target = node->InputAt(arg_count + 1);
- Node* receiver = jsgraph()->UndefinedConstant();
- node->RemoveInput(arg_count + 1); // Drop new target.
- node->InsertInput(zone(), 0, stub_code);
- node->InsertInput(zone(), 2, new_target);
- node->InsertInput(zone(), 3, stub_arity);
- node->InsertInput(zone(), 4, receiver);
- NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
+
+ // TODO(jgruber): Understand and document how stack_argument_count is
+ // calculated. I've made some educated guesses below but they should be
+ // verified and documented in other lowerings as well.
+ static constexpr int kReceiver = 1;
+ static constexpr int kMaybeFeedbackVector = 1;
+
+ if (CollectFeedbackInGenericLowering() && p.feedback().IsValid()) {
+ const int stack_argument_count =
+ arg_count + kReceiver + kMaybeFeedbackVector;
+ Callable callable =
+ Builtins::CallableFor(isolate(), Builtins::kConstruct_WithFeedback);
+ auto call_descriptor = Linkage::GetStubCallDescriptor(
+ zone(), callable.descriptor(), stack_argument_count, flags);
+ Node* feedback_vector = jsgraph()->HeapConstant(p.feedback().vector);
+ Node* stub_code = jsgraph()->HeapConstant(callable.code());
+ Node* new_target = node->InputAt(arg_count + 1);
+ Node* stub_arity = jsgraph()->Int32Constant(arg_count);
+ Node* slot = jsgraph()->Int32Constant(p.feedback().index());
+ Node* receiver = jsgraph()->UndefinedConstant();
+ node->RemoveInput(arg_count + 1); // Drop new target.
+ // Register argument inputs are followed by stack argument inputs (such as
+ // feedback_vector). Both are listed in ascending order. Note that
+ // the receiver is implicitly placed on the stack and is thus inserted
+ // between explicitly-specified register and stack arguments.
+ // TODO(jgruber): Implement a simpler way to specify these mutations.
+ node->InsertInput(zone(), arg_count + 1, feedback_vector);
+ node->InsertInput(zone(), 0, stub_code);
+ node->InsertInput(zone(), 2, new_target);
+ node->InsertInput(zone(), 3, stub_arity);
+ node->InsertInput(zone(), 4, slot);
+ node->InsertInput(zone(), 5, receiver);
+ NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
+ } else {
+ const int stack_argument_count = arg_count + kReceiver;
+ Callable callable = Builtins::CallableFor(isolate(), Builtins::kConstruct);
+ auto call_descriptor = Linkage::GetStubCallDescriptor(
+ zone(), callable.descriptor(), stack_argument_count, flags);
+ Node* stub_code = jsgraph()->HeapConstant(callable.code());
+ Node* stub_arity = jsgraph()->Int32Constant(arg_count);
+ Node* new_target = node->InputAt(arg_count + 1);
+ Node* receiver = jsgraph()->UndefinedConstant();
+ node->RemoveInput(arg_count + 1); // Drop new target.
+ node->InsertInput(zone(), 0, stub_code);
+ node->InsertInput(zone(), 2, new_target);
+ node->InsertInput(zone(), 3, stub_arity);
+ node->InsertInput(zone(), 4, receiver);
+ NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
+ }
}
void JSGenericLowering::LowerJSConstructWithArrayLike(Node* node) {
- Callable callable =
- Builtins::CallableFor(isolate(), Builtins::kConstructWithArrayLike);
+ ConstructParameters const& p = ConstructParametersOf(node->op());
CallDescriptor::Flags flags = FrameStateFlagForCall(node);
- auto call_descriptor =
- Linkage::GetStubCallDescriptor(zone(), callable.descriptor(), 1, flags);
- Node* stub_code = jsgraph()->HeapConstant(callable.code());
- Node* receiver = jsgraph()->UndefinedConstant();
- Node* arguments_list = node->InputAt(1);
- Node* new_target = node->InputAt(2);
- node->InsertInput(zone(), 0, stub_code);
- node->ReplaceInput(2, new_target);
- node->ReplaceInput(3, arguments_list);
- node->InsertInput(zone(), 4, receiver);
- NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
+ const int arg_count = p.arity_without_implicit_args();
+ DCHECK_EQ(arg_count, 1);
+
+ static constexpr int kReceiver = 1;
+ static constexpr int kArgumentList = 1;
+ static constexpr int kMaybeFeedbackVector = 1;
+
+ if (CollectFeedbackInGenericLowering() && p.feedback().IsValid()) {
+ const int stack_argument_count =
+ arg_count - kArgumentList + kReceiver + kMaybeFeedbackVector;
+ Callable callable = Builtins::CallableFor(
+ isolate(), Builtins::kConstructWithArrayLike_WithFeedback);
+ auto call_descriptor = Linkage::GetStubCallDescriptor(
+ zone(), callable.descriptor(), stack_argument_count, flags);
+ Node* stub_code = jsgraph()->HeapConstant(callable.code());
+ Node* receiver = jsgraph()->UndefinedConstant();
+ Node* arguments_list = node->InputAt(1);
+ Node* new_target = node->InputAt(2);
+ Node* feedback_vector = jsgraph()->HeapConstant(p.feedback().vector);
+ Node* slot = jsgraph()->Int32Constant(p.feedback().index());
+
+ node->InsertInput(zone(), 0, stub_code);
+ node->ReplaceInput(2, new_target);
+ node->ReplaceInput(3, arguments_list);
+ // Register argument inputs are followed by stack argument inputs (such as
+ // feedback_vector). Both are listed in ascending order. Note that
+ // the receiver is implicitly placed on the stack and is thus inserted
+ // between explicitly-specified register and stack arguments.
+ // TODO(jgruber): Implement a simpler way to specify these mutations.
+ node->InsertInput(zone(), 4, slot);
+ node->InsertInput(zone(), 5, receiver);
+ node->InsertInput(zone(), 6, feedback_vector);
+
+ NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
+ } else {
+ const int stack_argument_count = arg_count - kArgumentList + kReceiver;
+ Callable callable =
+ Builtins::CallableFor(isolate(), Builtins::kConstructWithArrayLike);
+ auto call_descriptor = Linkage::GetStubCallDescriptor(
+ zone(), callable.descriptor(), stack_argument_count, flags);
+ Node* stub_code = jsgraph()->HeapConstant(callable.code());
+ Node* receiver = jsgraph()->UndefinedConstant();
+ Node* arguments_list = node->InputAt(1);
+ Node* new_target = node->InputAt(2);
+ node->InsertInput(zone(), 0, stub_code);
+ node->ReplaceInput(2, new_target);
+ node->ReplaceInput(3, arguments_list);
+ node->InsertInput(zone(), 4, receiver);
+ NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
+ }
}
void JSGenericLowering::LowerJSConstructWithSpread(Node* node) {
ConstructParameters const& p = ConstructParametersOf(node->op());
- int const arg_count = static_cast<int>(p.arity() - 2);
+ int const arg_count = p.arity_without_implicit_args();
int const spread_index = arg_count;
int const new_target_index = arg_count + 1;
CallDescriptor::Flags flags = FrameStateFlagForCall(node);
- Callable callable = CodeFactory::ConstructWithSpread(isolate());
- auto call_descriptor = Linkage::GetStubCallDescriptor(
- zone(), callable.descriptor(), arg_count, flags);
- Node* stub_code = jsgraph()->HeapConstant(callable.code());
- Node* stack_arg_count = jsgraph()->Int32Constant(arg_count - 1);
- Node* new_target = node->InputAt(new_target_index);
- Node* spread = node->InputAt(spread_index);
- Node* receiver = jsgraph()->UndefinedConstant();
- DCHECK(new_target_index > spread_index);
- node->RemoveInput(new_target_index); // Drop new target.
- node->RemoveInput(spread_index);
- node->InsertInput(zone(), 0, stub_code);
- node->InsertInput(zone(), 2, new_target);
- node->InsertInput(zone(), 3, stack_arg_count);
- node->InsertInput(zone(), 4, spread);
- node->InsertInput(zone(), 5, receiver);
- NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
+ static constexpr int kReceiver = 1;
+ static constexpr int kTheSpread = 1; // Included in `arg_count`.
+ static constexpr int kMaybeFeedbackVector = 1;
+
+ if (CollectFeedbackInGenericLowering() && p.feedback().IsValid()) {
+ const int stack_argument_count =
+ arg_count + kReceiver + kMaybeFeedbackVector;
+ Callable callable = Builtins::CallableFor(
+ isolate(), Builtins::kConstructWithSpread_WithFeedback);
+ auto call_descriptor = Linkage::GetStubCallDescriptor(
+ zone(), callable.descriptor(), stack_argument_count, flags);
+ Node* stub_code = jsgraph()->HeapConstant(callable.code());
+ Node* feedback_vector = jsgraph()->HeapConstant(p.feedback().vector);
+ Node* slot = jsgraph()->Int32Constant(p.feedback().index());
+
+ // The single available register is needed for `slot`, thus `spread` remains
+ // on the stack here.
+ Node* stub_arity = jsgraph()->Int32Constant(arg_count - kTheSpread);
+ Node* new_target = node->InputAt(new_target_index);
+ Node* receiver = jsgraph()->UndefinedConstant();
+ node->RemoveInput(new_target_index);
+
+ // Register argument inputs are followed by stack argument inputs (such as
+ // feedback_vector). Both are listed in ascending order. Note that
+ // the receiver is implicitly placed on the stack and is thus inserted
+ // between explicitly-specified register and stack arguments.
+ // TODO(jgruber): Implement a simpler way to specify these mutations.
+ node->InsertInput(zone(), arg_count + 1, feedback_vector);
+ node->InsertInput(zone(), 0, stub_code);
+ node->InsertInput(zone(), 2, new_target);
+ node->InsertInput(zone(), 3, stub_arity);
+ node->InsertInput(zone(), 4, slot);
+ node->InsertInput(zone(), 5, receiver);
+ NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
+ } else {
+ const int stack_argument_count = arg_count + kReceiver - kTheSpread;
+ Callable callable = CodeFactory::ConstructWithSpread(isolate());
+ auto call_descriptor = Linkage::GetStubCallDescriptor(
+ zone(), callable.descriptor(), stack_argument_count, flags);
+ Node* stub_code = jsgraph()->HeapConstant(callable.code());
+
+ // We pass the spread in a register, not on the stack.
+ Node* stub_arity = jsgraph()->Int32Constant(arg_count - kTheSpread);
+ Node* new_target = node->InputAt(new_target_index);
+ Node* spread = node->InputAt(spread_index);
+ Node* receiver = jsgraph()->UndefinedConstant();
+ DCHECK(new_target_index > spread_index);
+ node->RemoveInput(new_target_index);
+ node->RemoveInput(spread_index);
+
+ node->InsertInput(zone(), 0, stub_code);
+ node->InsertInput(zone(), 2, new_target);
+ node->InsertInput(zone(), 3, stub_arity);
+ node->InsertInput(zone(), 4, spread);
+ node->InsertInput(zone(), 5, receiver);
+ NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
+ }
}
void JSGenericLowering::LowerJSCallForwardVarargs(Node* node) {
@@ -766,49 +918,126 @@ void JSGenericLowering::LowerJSCallForwardVarargs(Node* node) {
void JSGenericLowering::LowerJSCall(Node* node) {
CallParameters const& p = CallParametersOf(node->op());
- int const arg_count = static_cast<int>(p.arity() - 2);
+ int const arg_count = p.arity_without_implicit_args();
ConvertReceiverMode const mode = p.convert_mode();
- Callable callable = CodeFactory::Call(isolate(), mode);
- CallDescriptor::Flags flags = FrameStateFlagForCall(node);
- auto call_descriptor = Linkage::GetStubCallDescriptor(
- zone(), callable.descriptor(), arg_count + 1, flags);
- Node* stub_code = jsgraph()->HeapConstant(callable.code());
- Node* stub_arity = jsgraph()->Int32Constant(arg_count);
- node->InsertInput(zone(), 0, stub_code);
- node->InsertInput(zone(), 2, stub_arity);
- NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
+
+ if (CollectFeedbackInGenericLowering() && p.feedback().IsValid()) {
+ Callable callable = CodeFactory::Call_WithFeedback(isolate(), mode);
+ CallDescriptor::Flags flags = FrameStateFlagForCall(node);
+ auto call_descriptor = Linkage::GetStubCallDescriptor(
+ zone(), callable.descriptor(), arg_count + 1, flags);
+ Node* stub_code = jsgraph()->HeapConstant(callable.code());
+ Node* stub_arity = jsgraph()->Int32Constant(arg_count);
+ Node* feedback_vector = jsgraph()->HeapConstant(p.feedback().vector);
+ Node* slot = jsgraph()->Int32Constant(p.feedback().index());
+ node->InsertInput(zone(), 0, stub_code);
+ node->InsertInput(zone(), 2, stub_arity);
+ node->InsertInput(zone(), 3, slot);
+ node->InsertInput(zone(), 4, feedback_vector);
+ NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
+ } else {
+ Callable callable = CodeFactory::Call(isolate(), mode);
+ CallDescriptor::Flags flags = FrameStateFlagForCall(node);
+ auto call_descriptor = Linkage::GetStubCallDescriptor(
+ zone(), callable.descriptor(), arg_count + 1, flags);
+ Node* stub_code = jsgraph()->HeapConstant(callable.code());
+ Node* stub_arity = jsgraph()->Int32Constant(arg_count);
+ node->InsertInput(zone(), 0, stub_code);
+ node->InsertInput(zone(), 2, stub_arity);
+ NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
+ }
}
void JSGenericLowering::LowerJSCallWithArrayLike(Node* node) {
- Callable callable = CodeFactory::CallWithArrayLike(isolate());
+ CallParameters const& p = CallParametersOf(node->op());
+ const int arg_count = p.arity_without_implicit_args();
CallDescriptor::Flags flags = FrameStateFlagForCall(node);
- auto call_descriptor =
- Linkage::GetStubCallDescriptor(zone(), callable.descriptor(), 1, flags);
- Node* stub_code = jsgraph()->HeapConstant(callable.code());
- Node* receiver = node->InputAt(1);
- Node* arguments_list = node->InputAt(2);
- node->InsertInput(zone(), 0, stub_code);
- node->ReplaceInput(3, receiver);
- node->ReplaceInput(2, arguments_list);
- NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
+
+ DCHECK_EQ(arg_count, 0);
+ static constexpr int kReceiver = 1;
+
+ if (CollectFeedbackInGenericLowering() && p.feedback().IsValid()) {
+ Callable callable = Builtins::CallableFor(
+ isolate(), Builtins::kCallWithArrayLike_WithFeedback);
+ auto call_descriptor = Linkage::GetStubCallDescriptor(
+ zone(), callable.descriptor(), arg_count + kReceiver, flags);
+ Node* stub_code = jsgraph()->HeapConstant(callable.code());
+ Node* receiver = node->InputAt(1);
+ Node* arguments_list = node->InputAt(2);
+ Node* feedback_vector = jsgraph()->HeapConstant(p.feedback().vector);
+ Node* slot = jsgraph()->Int32Constant(p.feedback().index());
+ node->InsertInput(zone(), 0, stub_code);
+ node->ReplaceInput(2, arguments_list);
+ node->ReplaceInput(3, receiver);
+ node->InsertInput(zone(), 3, slot);
+ node->InsertInput(zone(), 4, feedback_vector);
+ NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
+ } else {
+ Callable callable = CodeFactory::CallWithArrayLike(isolate());
+ auto call_descriptor = Linkage::GetStubCallDescriptor(
+ zone(), callable.descriptor(), arg_count + kReceiver, flags);
+ Node* stub_code = jsgraph()->HeapConstant(callable.code());
+ Node* receiver = node->InputAt(1);
+ Node* arguments_list = node->InputAt(2);
+ node->InsertInput(zone(), 0, stub_code);
+ node->ReplaceInput(2, arguments_list);
+ node->ReplaceInput(3, receiver);
+ NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
+ }
}
void JSGenericLowering::LowerJSCallWithSpread(Node* node) {
CallParameters const& p = CallParametersOf(node->op());
- int const arg_count = static_cast<int>(p.arity() - 2);
- int const spread_index = static_cast<int>(p.arity() + 1);
+ int const arg_count = p.arity_without_implicit_args();
+ int const spread_index = arg_count + 1;
CallDescriptor::Flags flags = FrameStateFlagForCall(node);
- Callable callable = CodeFactory::CallWithSpread(isolate());
- auto call_descriptor = Linkage::GetStubCallDescriptor(
- zone(), callable.descriptor(), arg_count, flags);
- Node* stub_code = jsgraph()->HeapConstant(callable.code());
- // We pass the spread in a register, not on the stack.
- Node* stack_arg_count = jsgraph()->Int32Constant(arg_count - 1);
- node->InsertInput(zone(), 0, stub_code);
- node->InsertInput(zone(), 2, stack_arg_count);
- node->InsertInput(zone(), 3, node->InputAt(spread_index));
- node->RemoveInput(spread_index + 1);
- NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
+
+ static constexpr int kTheSpread = 1;
+ static constexpr int kMaybeFeedbackVector = 1;
+
+ if (CollectFeedbackInGenericLowering() && p.feedback().IsValid()) {
+ const int stack_argument_count = arg_count + kMaybeFeedbackVector;
+ Callable callable = Builtins::CallableFor(
+ isolate(), Builtins::kCallWithSpread_WithFeedback);
+ auto call_descriptor = Linkage::GetStubCallDescriptor(
+ zone(), callable.descriptor(), stack_argument_count, flags);
+ Node* stub_code = jsgraph()->HeapConstant(callable.code());
+ Node* feedback_vector = jsgraph()->HeapConstant(p.feedback().vector);
+ Node* slot = jsgraph()->Int32Constant(p.feedback().index());
+
+ // We pass the spread in a register, not on the stack.
+ Node* stub_arity = jsgraph()->Int32Constant(arg_count - kTheSpread);
+ Node* spread = node->InputAt(spread_index);
+ node->RemoveInput(spread_index);
+
+ // Register argument inputs are followed by stack argument inputs (such as
+ // feedback_vector). Both are listed in ascending order. Note that
+ // the receiver is implicitly placed on the stack and is thus inserted
+ // between explicitly-specified register and stack arguments.
+ // TODO(jgruber): Implement a simpler way to specify these mutations.
+ node->InsertInput(zone(), arg_count + 1, feedback_vector);
+ node->InsertInput(zone(), 0, stub_code);
+ node->InsertInput(zone(), 2, stub_arity);
+ node->InsertInput(zone(), 3, spread);
+ node->InsertInput(zone(), 4, slot);
+ NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
+ } else {
+ const int stack_argument_count = arg_count;
+ Callable callable = CodeFactory::CallWithSpread(isolate());
+ auto call_descriptor = Linkage::GetStubCallDescriptor(
+ zone(), callable.descriptor(), stack_argument_count, flags);
+ Node* stub_code = jsgraph()->HeapConstant(callable.code());
+
+ // We pass the spread in a register, not on the stack.
+ Node* stub_arity = jsgraph()->Int32Constant(arg_count - kTheSpread);
+ Node* spread = node->InputAt(spread_index);
+ node->RemoveInput(spread_index);
+
+ node->InsertInput(zone(), 0, stub_code);
+ node->InsertInput(zone(), 2, stub_arity);
+ node->InsertInput(zone(), 3, spread);
+ NodeProperties::ChangeOp(node, common()->Call(call_descriptor));
+ }
}
void JSGenericLowering::LowerJSCallRuntime(Node* node) {
@@ -932,9 +1161,7 @@ void JSGenericLowering::LowerJSStackCheck(Node* node) {
}
void JSGenericLowering::LowerJSDebugger(Node* node) {
- CallDescriptor::Flags flags = FrameStateFlagForCall(node);
- Callable callable = CodeFactory::HandleDebuggerStatement(isolate());
- ReplaceWithStubCall(node, callable, flags);
+ ReplaceWithBuiltinCall(node, Builtins::kHandleDebuggerStatement);
}
Zone* JSGenericLowering::zone() const { return graph()->zone(); }