Commit 1dceb970 authored by Jakob Gruber's avatar Jakob Gruber Committed by Commit Bot

[compiler] Refactor FastApiCall reduction

This refactors the FastApiCall reduction to be more explicit about
which inputs of the JSCall node are used.

Bug: v8:8888
Change-Id: Ia950bbfcf359ec4ae232b8dd21adafb0b4a05177
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2276032
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Commit-Queue: Maya Lekova <mslekova@chromium.org>
Auto-Submit: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: 's avatarMaya Lekova <mslekova@chromium.org>
Cr-Commit-Position: refs/heads/master@{#68628}
parent 4d52549a
...@@ -890,72 +890,74 @@ class FastApiCallReducerAssembler : public JSCallReducerAssembler { ...@@ -890,72 +890,74 @@ class FastApiCallReducerAssembler : public JSCallReducerAssembler {
} }
TNode<Object> ReduceFastApiCall() { TNode<Object> ReduceFastApiCall() {
int c_arg_count = c_signature_->ArgumentCount(); // C arguments include the receiver at index 0. Thus C index 1 corresponds
Node* function_node = // to the JS argument 0, etc.
ExternalConstant(ExternalReference::Create(c_function_)); static constexpr int kReceiver = 1;
base::SmallVector<Node*, kInlineSize + kExtraInputsCount> inputs(0); const int c_argument_count =
inputs.emplace_back(function_node); static_cast<int>(c_signature_->ArgumentCount());
int wrapper_object_index = isolate()->embedder_wrapper_object_index(); const bool c_arguments_contain_receiver = c_argument_count > 0;
CHECK_GE(wrapper_object_index, 0);
int cursor = 0;
const int value_input_count_without_vector = base::SmallVector<Node*, kInlineSize + kExtraInputsCount> inputs(
node_ptr()->op()->ValueInputCount() - c_argument_count + kExtraInputsCount);
JSCallNode::kFeedbackVectorInputCount; inputs[cursor++] = ExternalConstant(ExternalReference::Create(c_function_));
for (int i = 0; i < c_arg_count; ++i) { if (c_arguments_contain_receiver) {
if (i + kFunctionArgCount < value_input_count_without_vector) { inputs[cursor++] = MaybeUnwrapApiObject(
inputs.emplace_back(ConvertArgumentIfJSWrapper( c_signature_->ArgumentInfo(0).GetType(), ReceiverInput());
c_signature_->ArgumentInfo(i).GetType(), }
NodeProperties::GetValueInput(node_ptr(), i + kFunctionArgCount),
wrapper_object_index)); // TODO(jgruber,mslekova): Consider refactoring CFunctionInfo to distinguish
// between receiver and arguments, simplifying this (and related) spots.
for (int i = 0; i < c_argument_count - kReceiver; ++i) {
if (i < ArgumentCount()) {
CTypeInfo::Type type =
c_signature_->ArgumentInfo(i + kReceiver).GetType();
inputs[cursor++] = MaybeUnwrapApiObject(type, Argument(i));
} else { } else {
inputs.emplace_back(UndefinedConstant()); inputs[cursor++] = UndefinedConstant();
} }
} }
inputs.emplace_back(effect());
inputs.emplace_back(control());
return FastApiCall(inputs); inputs[cursor++] = effect();
inputs[cursor++] = control();
DCHECK_EQ(cursor, c_argument_count + kExtraInputsCount);
return FastApiCall(inputs.begin(), inputs.size());
} }
private: private:
static constexpr int kFunctionArgCount = 1; static constexpr int kTargetEffectAndControl = 3;
static constexpr int kExtraInputsCount = static constexpr int kExtraInputsCount = kTargetEffectAndControl;
kFunctionArgCount + 2; // effect, control
static constexpr int kInlineSize = 10; static constexpr int kInlineSize = 10;
TNode<Object> FastApiCall( TNode<Object> FastApiCall(Node** inputs, size_t inputs_size) {
base::SmallVector<Node*, kInlineSize + kExtraInputsCount> const& inputs) {
return AddNode<Object>( return AddNode<Object>(
graph()->NewNode(simplified()->FastApiCall(c_signature_, feedback()), graph()->NewNode(simplified()->FastApiCall(c_signature_, feedback()),
static_cast<int>(inputs.size()), inputs.begin())); static_cast<int>(inputs_size), inputs));
} }
TNode<RawPtrT> UnwrapApiObject(TNode<JSObject> node, TNode<RawPtrT> UnwrapApiObject(TNode<JSObject> node) {
int wrapper_object_index) { CHECK_GE(isolate()->embedder_wrapper_object_index(), 0);
const int offset = const int offset = Internals::kJSObjectHeaderSize +
Internals::kJSObjectHeaderSize + (Internals::kEmbedderDataSlotSize *
(Internals::kEmbedderDataSlotSize * wrapper_object_index); isolate()->embedder_wrapper_object_index());
FieldAccess access( FieldAccess access(
kTaggedBase, offset, MaybeHandle<Name>(), MaybeHandle<Map>(), kTaggedBase, offset, MaybeHandle<Name>(), MaybeHandle<Map>(),
V8_HEAP_SANDBOX_BOOL ? Type::SandboxedExternalPointer() : Type::Any(), V8_HEAP_SANDBOX_BOOL ? Type::SandboxedExternalPointer() : Type::Any(),
MachineType::Pointer(), WriteBarrierKind::kNoWriteBarrier); MachineType::Pointer(), WriteBarrierKind::kNoWriteBarrier);
TNode<RawPtrT> load = AddNode<RawPtrT>(graph()->NewNode( return LoadField<RawPtrT>(access, node);
simplified()->LoadField(access), node, effect(), control()));
return load;
} }
Node* ConvertArgumentIfJSWrapper(CTypeInfo::Type type, Node* node, Node* MaybeUnwrapApiObject(CTypeInfo::Type type, TNode<Object> node) {
int wrapper_object_index) {
switch (type) { switch (type) {
case CTypeInfo::Type::kUnwrappedApiObject: case CTypeInfo::Type::kUnwrappedApiObject:
// This call assumes that {node} is a JSObject with an internal field // This call assumes that {node} is a JSObject with an internal field
// set to a C pointer. It should fail in all other cases. // set to a C pointer. It should fail in all other cases.
// TODO(mslekova): Implement instanceOf check for the C pointer type. // TODO(mslekova): Implement instanceOf check for the C pointer type.
// TODO(mslekova): Introduce a GraphAssembler primitive for safe cast. // TODO(mslekova): Introduce a GraphAssembler primitive for safe cast.
return UnwrapApiObject(TNode<JSObject>::UncheckedCast(node), return UnwrapApiObject(TNode<JSObject>::UncheckedCast(node));
wrapper_object_index);
default: default:
return node; return node;
} }
......
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