Revert "[maglev] Unify call building functions"
This reverts commit 109e19554b
.
Reason for revert: https://ci.chromium.org/ui/p/v8/builders/ci/V8%20Linux64%20UBSan/23984/overview
Original change's description:
> [maglev] Unify call building functions
>
> ... so that we have more reduce/inline opportunities.
> It changes CallArguments to hold a vector of ValueNodes.
>
> Change-Id: I9c282631c0dcc2756edc2e2c1f892c3855e1286d
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4020381
> Reviewed-by: Leszek Swirski <leszeks@chromium.org>
> Commit-Queue: Victor Gomes <victorgomes@chromium.org>
> Cr-Commit-Position: refs/heads/main@{#84205}
Change-Id: Iaa18aa8a9b30202c2a0bb74e242f038d29bc738b
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4020427
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
Owners-Override: Nico Hartmann <nicohartmann@chromium.org>
Commit-Queue: Nico Hartmann <nicohartmann@chromium.org>
Cr-Commit-Position: refs/heads/main@{#84214}
This commit is contained in:
parent
03498726be
commit
7ce4dfd872
@ -86,72 +86,6 @@ class FunctionContextSpecialization final : public AllStatic {
|
||||
|
||||
} // namespace
|
||||
|
||||
class CallArguments {
|
||||
public:
|
||||
CallArguments(ConvertReceiverMode receiver_mode,
|
||||
interpreter::RegisterList reglist,
|
||||
const InterpreterFrameState& frame)
|
||||
: receiver_mode_(receiver_mode), args_(reglist.register_count()) {
|
||||
for (int i = 0; i < reglist.register_count(); i++) {
|
||||
args_[i] = frame.get(reglist[i]);
|
||||
}
|
||||
DCHECK_IMPLIES(args_.size() == 0,
|
||||
receiver_mode == ConvertReceiverMode::kNullOrUndefined);
|
||||
}
|
||||
|
||||
CallArguments(ConvertReceiverMode receiver_mode,
|
||||
std::initializer_list<ValueNode*> args)
|
||||
: receiver_mode_(receiver_mode), args_(args) {}
|
||||
|
||||
ValueNode* receiver() const {
|
||||
if (receiver_mode_ == ConvertReceiverMode::kNullOrUndefined) {
|
||||
return nullptr;
|
||||
}
|
||||
return args_[0];
|
||||
}
|
||||
|
||||
size_t count() const {
|
||||
if (receiver_mode_ == ConvertReceiverMode::kNullOrUndefined) {
|
||||
return args_.size();
|
||||
}
|
||||
return args_.size() - 1;
|
||||
}
|
||||
|
||||
size_t count_with_receiver() const { return count() + 1; }
|
||||
|
||||
ValueNode* operator[](size_t i) const {
|
||||
if (receiver_mode_ != ConvertReceiverMode::kNullOrUndefined) {
|
||||
i++;
|
||||
}
|
||||
if (i >= args_.size()) return nullptr;
|
||||
return args_[i];
|
||||
}
|
||||
|
||||
ConvertReceiverMode receiver_mode() const { return receiver_mode_; }
|
||||
|
||||
void PopReceiver(ConvertReceiverMode new_receiver_mode) {
|
||||
DCHECK_NE(receiver_mode_, ConvertReceiverMode::kNullOrUndefined);
|
||||
DCHECK_NE(new_receiver_mode, ConvertReceiverMode::kNullOrUndefined);
|
||||
|
||||
if (count() == 0) {
|
||||
// If there is no non-receiver argument to become the new receiver,
|
||||
// consider the new receiver to be known undefined.
|
||||
receiver_mode_ = ConvertReceiverMode::kNullOrUndefined;
|
||||
} else {
|
||||
// TODO(victorgomes): Do this better!
|
||||
for (size_t i = 0; i < args_.size() - 1; i++) {
|
||||
args_[i] = args_[i + 1];
|
||||
}
|
||||
args_.pop_back();
|
||||
receiver_mode_ = new_receiver_mode;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
ConvertReceiverMode receiver_mode_;
|
||||
base::SmallVector<ValueNode*, 8> args_;
|
||||
};
|
||||
|
||||
MaglevGraphBuilder::MaglevGraphBuilder(LocalIsolate* local_isolate,
|
||||
MaglevCompilationUnit* compilation_unit,
|
||||
Graph* graph, MaglevGraphBuilder* parent)
|
||||
@ -1578,8 +1512,12 @@ bool MaglevGraphBuilder::TryBuildPropertyGetterCall(
|
||||
receiver == lookup_start_object
|
||||
? ConvertReceiverMode::kNotNullOrUndefined
|
||||
: ConvertReceiverMode::kAny;
|
||||
CallArguments args(receiver_mode, {receiver});
|
||||
ReduceCall(constant.AsJSFunction(), args);
|
||||
Call* call = CreateNewNode<Call>(Call::kFixedInputCount + 1, receiver_mode,
|
||||
Call::TargetType::kJSFunction,
|
||||
compiler::FeedbackSource(),
|
||||
GetConstant(constant), GetContext());
|
||||
call->set_arg(0, receiver);
|
||||
SetAccumulator(AddNode(call));
|
||||
return true;
|
||||
} else {
|
||||
// TODO(victorgomes): API calls.
|
||||
@ -1592,9 +1530,13 @@ bool MaglevGraphBuilder::TryBuildPropertySetterCall(
|
||||
ValueNode* value) {
|
||||
compiler::ObjectRef constant = access_info.constant().value();
|
||||
if (constant.IsJSFunction()) {
|
||||
CallArguments args(ConvertReceiverMode::kNotNullOrUndefined,
|
||||
{receiver, value});
|
||||
ReduceCall(constant.AsJSFunction(), args);
|
||||
Call* call = CreateNewNode<Call>(
|
||||
Call::kFixedInputCount + 2, ConvertReceiverMode::kNotNullOrUndefined,
|
||||
Call::TargetType::kJSFunction, compiler::FeedbackSource(),
|
||||
GetConstant(constant), GetContext());
|
||||
call->set_arg(0, receiver);
|
||||
call->set_arg(1, value);
|
||||
SetAccumulator(AddNode(call));
|
||||
return true;
|
||||
} else {
|
||||
// TODO(victorgomes): API calls.
|
||||
@ -2693,17 +2635,16 @@ void MaglevGraphBuilder::InlineCallFromRegisters(
|
||||
->SetToBlockAndReturnNext(current_block_);
|
||||
}
|
||||
|
||||
ValueNode* MaglevGraphBuilder::TryReduceStringFromCharCode(
|
||||
compiler::JSFunctionRef target, CallArguments& args, bool set_accumulator) {
|
||||
if (args.count() != 1) return nullptr;
|
||||
return SetAccumulatorIfNeeded(
|
||||
AddNewNode<BuiltinStringFromCharCode>({GetInt32(args[0])}),
|
||||
set_accumulator);
|
||||
bool MaglevGraphBuilder::TryReduceStringFromCharCode(
|
||||
compiler::JSFunctionRef target, const CallArguments& args) {
|
||||
if (args.count() != 1) return false;
|
||||
SetAccumulator(AddNewNode<BuiltinStringFromCharCode>({GetInt32(args[0])}));
|
||||
return true;
|
||||
}
|
||||
|
||||
ValueNode* MaglevGraphBuilder::TryReduceStringPrototypeCharCodeAt(
|
||||
compiler::JSFunctionRef target, CallArguments& args, bool set_accumulator) {
|
||||
ValueNode* receiver = GetTaggedOrUndefined(args.receiver());
|
||||
bool MaglevGraphBuilder::TryReduceStringPrototypeCharCodeAt(
|
||||
compiler::JSFunctionRef target, const CallArguments& args) {
|
||||
ValueNode* receiver = GetTaggedReceiver(args);
|
||||
ValueNode* index;
|
||||
if (args.count() == 0) {
|
||||
// Index is the undefined object. ToIntegerOrInfinity(undefined) = 0.
|
||||
@ -2718,53 +2659,53 @@ ValueNode* MaglevGraphBuilder::TryReduceStringPrototypeCharCodeAt(
|
||||
ValueNode* length = AddNewNode<StringLength>({receiver});
|
||||
AddNewNode<CheckInt32Condition>({index, length}, AssertCondition::kLess,
|
||||
DeoptimizeReason::kOutOfBounds);
|
||||
return SetAccumulatorIfNeeded(
|
||||
AddNewNode<BuiltinStringPrototypeCharCodeAt>({receiver, index}),
|
||||
set_accumulator);
|
||||
SetAccumulator(
|
||||
AddNewNode<BuiltinStringPrototypeCharCodeAt>({receiver, index}));
|
||||
return true;
|
||||
}
|
||||
|
||||
ValueNode* MaglevGraphBuilder::TryReduceFunctionPrototypeCall(
|
||||
compiler::JSFunctionRef target, CallArguments& args, bool set_accumulator) {
|
||||
bool MaglevGraphBuilder::TryReduceFunctionPrototypeCall(
|
||||
compiler::JSFunctionRef target, const CallArguments& args) {
|
||||
// Use Function.prototype.call context, to ensure any exception is thrown in
|
||||
// the correct context.
|
||||
ValueNode* context = GetConstant(target.context());
|
||||
ValueNode* receiver = GetTaggedOrUndefined(args.receiver());
|
||||
args.PopReceiver(ConvertReceiverMode::kAny);
|
||||
return SetAccumulatorIfNeeded(
|
||||
BuildGenericCall(receiver, context, Call::TargetType::kAny, args),
|
||||
set_accumulator);
|
||||
ValueNode* receiver = GetTaggedReceiver(args);
|
||||
compiler::FeedbackSource feedback_source;
|
||||
BuildGenericCall(receiver, context, Call::TargetType::kAny,
|
||||
args.PopReceiver(ConvertReceiverMode::kAny),
|
||||
feedback_source);
|
||||
return true;
|
||||
}
|
||||
|
||||
ValueNode* MaglevGraphBuilder::TryReduceBuiltin(compiler::JSFunctionRef target,
|
||||
CallArguments& args,
|
||||
bool set_accumulator) {
|
||||
if (!target.shared().HasBuiltinId()) return nullptr;
|
||||
bool MaglevGraphBuilder::TryReduceBuiltin(compiler::JSFunctionRef target,
|
||||
const CallArguments& args) {
|
||||
if (!target.shared().HasBuiltinId()) return false;
|
||||
switch (target.shared().builtin_id()) {
|
||||
#define CASE(Name) \
|
||||
case Builtin::k##Name: \
|
||||
return TryReduce##Name(target, args, set_accumulator);
|
||||
return TryReduce##Name(target, args);
|
||||
MAGLEV_REDUCED_BUILTIN(CASE)
|
||||
#undef CASE
|
||||
default:
|
||||
// TODO(v8:7700): Inline more builtins.
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ValueNode* MaglevGraphBuilder::GetConvertReceiver(
|
||||
compiler::JSFunctionRef function, CallArguments& args) {
|
||||
compiler::JSFunctionRef function, const CallArguments& args) {
|
||||
compiler::SharedFunctionInfoRef shared = function.shared();
|
||||
if (shared.native() || shared.language_mode() == LanguageMode::kStrict) {
|
||||
if (args.receiver_mode() == ConvertReceiverMode::kNullOrUndefined) {
|
||||
return GetRootConstant(RootIndex::kUndefinedValue);
|
||||
} else {
|
||||
return GetTaggedValue(args.receiver());
|
||||
return GetTaggedValue(*args.receiver());
|
||||
}
|
||||
}
|
||||
if (args.receiver_mode() == ConvertReceiverMode::kNullOrUndefined) {
|
||||
return GetConstant(function.native_context().global_proxy_object());
|
||||
}
|
||||
ValueNode* receiver = GetTaggedValue(args.receiver());
|
||||
ValueNode* receiver = GetTaggedValue(*args.receiver());
|
||||
if (CheckType(receiver, NodeType::kJSReceiver)) return receiver;
|
||||
if (Constant* constant = receiver->TryCast<Constant>()) {
|
||||
const Handle<HeapObject> object = constant->object().object();
|
||||
@ -2778,37 +2719,36 @@ ValueNode* MaglevGraphBuilder::GetConvertReceiver(
|
||||
args.receiver_mode());
|
||||
}
|
||||
|
||||
ValueNode* MaglevGraphBuilder::TryBuildCallKnownJSFunction(
|
||||
compiler::JSFunctionRef function, CallArguments& args,
|
||||
bool set_accumulator) {
|
||||
bool MaglevGraphBuilder::TryBuildCallKnownJSFunction(
|
||||
compiler::JSFunctionRef function, const CallArguments& args) {
|
||||
// Don't inline CallFunction stub across native contexts.
|
||||
if (function.native_context() != broker()->target_native_context()) {
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
ValueNode* receiver = GetConvertReceiver(function, args);
|
||||
size_t input_count = args.count() + CallKnownJSFunction::kFixedInputCount;
|
||||
CallKnownJSFunction* call =
|
||||
CreateNewNode<CallKnownJSFunction>(input_count, function, receiver);
|
||||
for (int i = 0; i < static_cast<int>(args.count()); i++) {
|
||||
for (int i = 0; i < args.count(); i++) {
|
||||
call->set_arg(i, GetTaggedValue(args[i]));
|
||||
}
|
||||
return SetAccumulatorIfNeeded(AddNode(call), set_accumulator);
|
||||
SetAccumulator(AddNode(call));
|
||||
return true;
|
||||
}
|
||||
|
||||
Call* MaglevGraphBuilder::BuildGenericCall(
|
||||
void MaglevGraphBuilder::BuildGenericCall(
|
||||
ValueNode* target, ValueNode* context, Call::TargetType target_type,
|
||||
const CallArguments& args,
|
||||
const compiler::FeedbackSource& feedback_source) {
|
||||
const CallArguments& args, compiler::FeedbackSource& feedback_source) {
|
||||
size_t input_count = args.count_with_receiver() + Call::kFixedInputCount;
|
||||
Call* call =
|
||||
CreateNewNode<Call>(input_count, args.receiver_mode(), target_type,
|
||||
feedback_source, target, context);
|
||||
int arg_index = 0;
|
||||
call->set_arg(arg_index++, GetTaggedOrUndefined(args.receiver()));
|
||||
for (size_t i = 0; i < args.count(); ++i) {
|
||||
call->set_arg(arg_index++, GetTaggedReceiver(args));
|
||||
for (int i = 0; i < args.count(); ++i) {
|
||||
call->set_arg(arg_index++, GetTaggedValue(args[i]));
|
||||
}
|
||||
return AddNode(call);
|
||||
SetAccumulator(AddNode(call));
|
||||
}
|
||||
|
||||
bool MaglevGraphBuilder::BuildCheckValue(ValueNode* node,
|
||||
@ -2822,38 +2762,8 @@ bool MaglevGraphBuilder::BuildCheckValue(ValueNode* node,
|
||||
return true;
|
||||
}
|
||||
|
||||
ValueNode* MaglevGraphBuilder::ReduceCall(compiler::ObjectRef object,
|
||||
CallArguments& args,
|
||||
bool set_accumulator) {
|
||||
if (!object.IsJSFunction()) {
|
||||
return BuildGenericCall(GetConstant(object), GetContext(),
|
||||
Call::TargetType::kAny, args);
|
||||
}
|
||||
compiler::JSFunctionRef target = object.AsJSFunction();
|
||||
// Do not reduce calls to functions with break points.
|
||||
if (!target.shared().HasBreakInfo()) {
|
||||
if (target.object()->IsJSClassConstructor()) {
|
||||
// If we have a class constructor, we should raise an exception.
|
||||
return SetAccumulatorIfNeeded(
|
||||
BuildCallRuntime(Runtime::kThrowConstructorNonCallableError,
|
||||
{GetConstant(target)}),
|
||||
set_accumulator);
|
||||
}
|
||||
|
||||
DCHECK(target.object()->IsCallable());
|
||||
if (ValueNode* result = TryReduceBuiltin(target, args, set_accumulator)) {
|
||||
return result;
|
||||
}
|
||||
if (ValueNode* result =
|
||||
TryBuildCallKnownJSFunction(target, args, set_accumulator)) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return BuildGenericCall(GetConstant(target), GetContext(),
|
||||
Call::TargetType::kJSFunction, args);
|
||||
}
|
||||
|
||||
void MaglevGraphBuilder::BuildCall(ValueNode* target_node, CallArguments& args,
|
||||
void MaglevGraphBuilder::BuildCall(ValueNode* target_node,
|
||||
const CallArguments& args,
|
||||
compiler::FeedbackSource& feedback_source) {
|
||||
Call::TargetType target_type = Call::TargetType::kAny;
|
||||
const compiler::ProcessedFeedback& processed_feedback =
|
||||
@ -2877,10 +2787,29 @@ void MaglevGraphBuilder::BuildCall(ValueNode* target_node, CallArguments& args,
|
||||
if (!target.IsJSFunction()) break;
|
||||
compiler::JSFunctionRef function = target.AsJSFunction();
|
||||
|
||||
// Do not reduce calls to functions with break points.
|
||||
if (function.shared().HasBreakInfo()) break;
|
||||
|
||||
// Reset the feedback source
|
||||
feedback_source = compiler::FeedbackSource();
|
||||
target_type = Call::TargetType::kJSFunction;
|
||||
if (!BuildCheckValue(target_node, target)) return;
|
||||
|
||||
ReduceCall(function, args, true);
|
||||
return;
|
||||
if (function.object()->IsJSClassConstructor()) {
|
||||
// If we have a class constructor, we should raise an exception.
|
||||
SetAccumulator(BuildCallRuntime(
|
||||
Runtime::kThrowConstructorNonCallableError, {target_node}));
|
||||
return;
|
||||
}
|
||||
|
||||
DCHECK(function.object()->IsCallable());
|
||||
if (TryReduceBuiltin(function, args)) {
|
||||
return;
|
||||
}
|
||||
if (TryBuildCallKnownJSFunction(function, args)) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
@ -2889,8 +2818,7 @@ void MaglevGraphBuilder::BuildCall(ValueNode* target_node, CallArguments& args,
|
||||
|
||||
// On fallthrough, create a generic call.
|
||||
ValueNode* context = GetContext();
|
||||
SetAccumulator(BuildGenericCall(target_node, context, target_type, args,
|
||||
feedback_source));
|
||||
BuildGenericCall(target_node, context, target_type, args, feedback_source);
|
||||
}
|
||||
|
||||
void MaglevGraphBuilder::BuildCallFromRegisterList(
|
||||
@ -2899,7 +2827,7 @@ void MaglevGraphBuilder::BuildCallFromRegisterList(
|
||||
interpreter::RegisterList reg_list = iterator_.GetRegisterListOperand(1);
|
||||
FeedbackSlot slot = GetSlotOperand(3);
|
||||
compiler::FeedbackSource feedback_source(feedback(), slot);
|
||||
CallArguments args(receiver_mode, reg_list, current_interpreter_frame_);
|
||||
CallArguments args(receiver_mode, reg_list);
|
||||
BuildCall(target, args, feedback_source);
|
||||
}
|
||||
|
||||
@ -2909,29 +2837,32 @@ void MaglevGraphBuilder::BuildCallFromRegisters(
|
||||
const int receiver_count =
|
||||
(receiver_mode == ConvertReceiverMode::kNullOrUndefined) ? 0 : 1;
|
||||
const int reg_count = arg_count + receiver_count;
|
||||
FeedbackSlot slot = GetSlotOperand(reg_count + 1);
|
||||
int slot_operand_index = arg_count + receiver_count + 1;
|
||||
FeedbackSlot slot = GetSlotOperand(slot_operand_index);
|
||||
compiler::FeedbackSource feedback_source(feedback(), slot);
|
||||
switch (reg_count) {
|
||||
case 0: {
|
||||
DCHECK_EQ(receiver_mode, ConvertReceiverMode::kNullOrUndefined);
|
||||
CallArguments args(receiver_mode, {});
|
||||
CallArguments args(receiver_mode, reg_count);
|
||||
BuildCall(target, args, feedback_source);
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
CallArguments args(receiver_mode, {LoadRegisterRaw(1)});
|
||||
CallArguments args(receiver_mode, reg_count,
|
||||
iterator_.GetRegisterOperand(1));
|
||||
BuildCall(target, args, feedback_source);
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
CallArguments args(receiver_mode,
|
||||
{LoadRegisterRaw(1), LoadRegisterRaw(2)});
|
||||
CallArguments args(receiver_mode, reg_count,
|
||||
iterator_.GetRegisterOperand(1),
|
||||
iterator_.GetRegisterOperand(2));
|
||||
BuildCall(target, args, feedback_source);
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
CallArguments args(receiver_mode, {LoadRegisterRaw(1), LoadRegisterRaw(2),
|
||||
LoadRegisterRaw(3)});
|
||||
CallArguments args(
|
||||
receiver_mode, reg_count, iterator_.GetRegisterOperand(1),
|
||||
iterator_.GetRegisterOperand(2), iterator_.GetRegisterOperand(3));
|
||||
BuildCall(target, args, feedback_source);
|
||||
break;
|
||||
}
|
||||
@ -3008,11 +2939,21 @@ void MaglevGraphBuilder::VisitCallJSRuntime() {
|
||||
ValueNode* callee = LoadAndCacheContextSlot(
|
||||
context, NativeContext::OffsetOfElementAt(slot), kMutable);
|
||||
// Call the function.
|
||||
interpreter::RegisterList reglist = iterator_.GetRegisterListOperand(1);
|
||||
CallArguments args(ConvertReceiverMode::kNullOrUndefined, reglist,
|
||||
current_interpreter_frame_);
|
||||
SetAccumulator(BuildGenericCall(callee, GetContext(),
|
||||
Call::TargetType::kJSFunction, args));
|
||||
interpreter::RegisterList args = iterator_.GetRegisterListOperand(1);
|
||||
int kTheReceiver = 1;
|
||||
size_t input_count =
|
||||
args.register_count() + Call::kFixedInputCount + kTheReceiver;
|
||||
|
||||
Call* call =
|
||||
CreateNewNode<Call>(input_count, ConvertReceiverMode::kNullOrUndefined,
|
||||
Call::TargetType::kJSFunction,
|
||||
compiler::FeedbackSource(), callee, GetContext());
|
||||
int arg_index = 0;
|
||||
call->set_arg(arg_index++, GetRootConstant(RootIndex::kUndefinedValue));
|
||||
for (int i = 0; i < args.register_count(); ++i) {
|
||||
call->set_arg(arg_index++, GetTaggedValue(args[i]));
|
||||
}
|
||||
SetAccumulator(AddNode(call));
|
||||
}
|
||||
|
||||
void MaglevGraphBuilder::VisitCallRuntimeForPair() {
|
||||
@ -3468,25 +3409,23 @@ bool MaglevGraphBuilder::TryBuildFastInstanceOf(
|
||||
}
|
||||
|
||||
// Call @@hasInstance
|
||||
CallArguments args(ConvertReceiverMode::kNotNullOrUndefined,
|
||||
{callable_node, object});
|
||||
ValueNode* call =
|
||||
ReduceCall(has_instance_field->AsJSFunction(), args, false);
|
||||
Call* call = AddNewNode<Call>(
|
||||
Call::kFixedInputCount + 2, ConvertReceiverMode::kNotNullOrUndefined,
|
||||
Call::TargetType::kJSFunction, compiler::FeedbackSource(),
|
||||
GetConstant(*has_instance_field), GetContext());
|
||||
call->set_arg(0, callable_node);
|
||||
call->set_arg(1, object);
|
||||
|
||||
// Make sure that a lazy deopt after the @@hasInstance call also performs
|
||||
// ToBoolean before returning to the interpreter.
|
||||
// TODO(leszeks): Wrap this in a helper.
|
||||
if (call->properties().can_lazy_deopt()) {
|
||||
new (call->lazy_deopt_info()) LazyDeoptInfo(
|
||||
zone(),
|
||||
BuiltinContinuationDeoptFrame(
|
||||
Builtin::kToBooleanLazyDeoptContinuation, {}, GetContext(),
|
||||
zone()->New<InterpretedDeoptFrame>(
|
||||
call->lazy_deopt_info()->top_frame().as_interpreted())));
|
||||
}
|
||||
new (call->lazy_deopt_info()) LazyDeoptInfo(
|
||||
zone(),
|
||||
BuiltinContinuationDeoptFrame(
|
||||
Builtin::kToBooleanLazyDeoptContinuation, {}, GetContext(),
|
||||
zone()->New<InterpretedDeoptFrame>(
|
||||
call->lazy_deopt_info()->top_frame().as_interpreted())));
|
||||
|
||||
// TODO(v8:7700): Do we need to call ToBoolean here? If we have reduce the
|
||||
// call further, we might already have a boolean constant as result.
|
||||
SetAccumulator(AddNewNode<ToBoolean>({call}));
|
||||
return true;
|
||||
}
|
||||
|
@ -37,8 +37,6 @@ namespace v8 {
|
||||
namespace internal {
|
||||
namespace maglev {
|
||||
|
||||
class CallArguments;
|
||||
|
||||
class MaglevGraphBuilder {
|
||||
public:
|
||||
explicit MaglevGraphBuilder(LocalIsolate* local_isolate,
|
||||
@ -648,6 +646,9 @@ class MaglevGraphBuilder {
|
||||
current_interpreter_frame_.set(dst, current_interpreter_frame_.get(src));
|
||||
}
|
||||
|
||||
ValueNode* GetTaggedValue(interpreter::Register reg) {
|
||||
return GetTaggedValue(current_interpreter_frame_.get(reg));
|
||||
}
|
||||
ValueNode* GetTaggedValue(ValueNode* value) {
|
||||
switch (value->properties().value_representation()) {
|
||||
case ValueRepresentation::kTagged:
|
||||
@ -681,11 +682,6 @@ class MaglevGraphBuilder {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
ValueNode* GetTaggedValue(interpreter::Register reg) {
|
||||
ValueNode* value = current_interpreter_frame_.get(reg);
|
||||
return GetTaggedValue(value);
|
||||
}
|
||||
|
||||
void SetKnownType(ValueNode* node, NodeType type) {
|
||||
NodeInfo* known_info = known_node_aspects().GetOrCreateInfoFor(node);
|
||||
known_info->type = type;
|
||||
@ -745,8 +741,7 @@ class MaglevGraphBuilder {
|
||||
}
|
||||
|
||||
ValueNode* GetInt32(interpreter::Register reg) {
|
||||
ValueNode* value = current_interpreter_frame_.get(reg);
|
||||
return GetInt32(value);
|
||||
return GetInt32(current_interpreter_frame_.get(reg));
|
||||
}
|
||||
|
||||
ValueNode* GetFloat64(ValueNode* value) {
|
||||
@ -803,11 +798,6 @@ class MaglevGraphBuilder {
|
||||
current_interpreter_frame_.accumulator();
|
||||
}
|
||||
|
||||
ValueNode* LoadRegisterRaw(int operand_index) {
|
||||
return current_interpreter_frame_.get(
|
||||
iterator_.GetRegisterOperand(operand_index));
|
||||
}
|
||||
|
||||
ValueNode* LoadRegisterTagged(int operand_index) {
|
||||
return GetTaggedValue(iterator_.GetRegisterOperand(operand_index));
|
||||
}
|
||||
@ -832,14 +822,6 @@ class MaglevGraphBuilder {
|
||||
StoreRegister(interpreter::Register::virtual_accumulator(), node);
|
||||
}
|
||||
|
||||
template <typename NodeT>
|
||||
NodeT* SetAccumulatorIfNeeded(NodeT* node, bool set_accumulator) {
|
||||
if (set_accumulator) {
|
||||
SetAccumulator(node);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
ValueNode* GetSecondValue(ValueNode* result) {
|
||||
// GetSecondReturnedValue must be added just after a node that calls a
|
||||
// builtin that expects 2 returned values. It simply binds kReturnRegister1
|
||||
@ -1042,40 +1024,133 @@ class MaglevGraphBuilder {
|
||||
ConvertReceiverMode receiver_mode,
|
||||
compiler::JSFunctionRef function);
|
||||
|
||||
ValueNode* GetTaggedOrUndefined(ValueNode* maybe_value) {
|
||||
if (maybe_value == nullptr) {
|
||||
return GetRootConstant(RootIndex::kUndefinedValue);
|
||||
}
|
||||
return GetTaggedValue(maybe_value);
|
||||
}
|
||||
class CallArguments {
|
||||
public:
|
||||
enum Mode {
|
||||
kFromRegisters,
|
||||
kFromRegisterList,
|
||||
};
|
||||
|
||||
CallArguments(ConvertReceiverMode receiver_mode, int reg_count,
|
||||
interpreter::Register r0 = interpreter::Register(),
|
||||
interpreter::Register r1 = interpreter::Register(),
|
||||
interpreter::Register r2 = interpreter::Register())
|
||||
: receiver_mode_(receiver_mode),
|
||||
call_mode_(kFromRegisters),
|
||||
reg_count_(reg_count) {
|
||||
DCHECK_GE(reg_count, 0);
|
||||
DCHECK_LT(reg_count, 4);
|
||||
DCHECK_IMPLIES(receiver_mode_ != ConvertReceiverMode::kNullOrUndefined,
|
||||
reg_count > 0);
|
||||
DCHECK_IMPLIES(reg_count > 0, r0.is_valid());
|
||||
regs_[0] = r0;
|
||||
DCHECK_IMPLIES(reg_count > 1, r1.is_valid());
|
||||
regs_[1] = r1;
|
||||
DCHECK_IMPLIES(reg_count > 2, r2.is_valid());
|
||||
regs_[2] = r2;
|
||||
}
|
||||
|
||||
CallArguments(ConvertReceiverMode receiver_mode,
|
||||
interpreter::RegisterList reglist)
|
||||
: receiver_mode_(receiver_mode),
|
||||
call_mode_(kFromRegisterList),
|
||||
reglist_(reglist) {}
|
||||
|
||||
base::Optional<interpreter::Register> receiver() const {
|
||||
if (receiver_mode_ == ConvertReceiverMode::kNullOrUndefined) {
|
||||
return {};
|
||||
}
|
||||
if (call_mode_ == kFromRegisters) {
|
||||
DCHECK_GT(reg_count_, 0);
|
||||
return regs_[0];
|
||||
}
|
||||
return reglist_[0];
|
||||
}
|
||||
|
||||
int count() const {
|
||||
int register_count =
|
||||
call_mode_ == kFromRegisters ? reg_count_ : reglist_.register_count();
|
||||
if (receiver_mode_ == ConvertReceiverMode::kNullOrUndefined) {
|
||||
return register_count;
|
||||
}
|
||||
return register_count - 1;
|
||||
}
|
||||
|
||||
int count_with_receiver() const { return count() + 1; }
|
||||
|
||||
const interpreter::Register operator[](size_t i) const {
|
||||
if (receiver_mode_ != ConvertReceiverMode::kNullOrUndefined) {
|
||||
i++;
|
||||
}
|
||||
if (call_mode_ == kFromRegisters) {
|
||||
DCHECK_LT(i, reg_count_);
|
||||
DCHECK_GE(i, 0);
|
||||
return regs_[i];
|
||||
}
|
||||
return reglist_[i];
|
||||
}
|
||||
|
||||
ConvertReceiverMode receiver_mode() const { return receiver_mode_; }
|
||||
|
||||
CallArguments PopReceiver(ConvertReceiverMode new_receiver_mode) const {
|
||||
DCHECK_NE(receiver_mode_, ConvertReceiverMode::kNullOrUndefined);
|
||||
DCHECK_NE(new_receiver_mode, ConvertReceiverMode::kNullOrUndefined);
|
||||
// If there is no non-receiver argument to become the new receiver,
|
||||
// consider the new receiver to be known undefined.
|
||||
if (count() == 0) {
|
||||
new_receiver_mode = ConvertReceiverMode::kNullOrUndefined;
|
||||
}
|
||||
if (call_mode_ == kFromRegisters) {
|
||||
return CallArguments(new_receiver_mode, reg_count_ - 1, regs_[1],
|
||||
regs_[2]);
|
||||
}
|
||||
return CallArguments(new_receiver_mode, reglist_.PopLeft());
|
||||
}
|
||||
|
||||
private:
|
||||
const ConvertReceiverMode receiver_mode_;
|
||||
const Mode call_mode_;
|
||||
union {
|
||||
struct {
|
||||
interpreter::Register regs_[3];
|
||||
int reg_count_;
|
||||
};
|
||||
interpreter::RegisterList reglist_;
|
||||
};
|
||||
};
|
||||
|
||||
ValueNode* GetTaggedReceiver(const CallArguments& args) {
|
||||
auto maybe_receiver = args.receiver();
|
||||
if (maybe_receiver.has_value()) {
|
||||
return GetTaggedValue(*maybe_receiver);
|
||||
}
|
||||
DCHECK_EQ(args.receiver_mode(), ConvertReceiverMode::kNullOrUndefined);
|
||||
return GetRootConstant(RootIndex::kUndefinedValue);
|
||||
}
|
||||
ValueNode* GetConvertReceiver(compiler::JSFunctionRef function,
|
||||
CallArguments& args);
|
||||
const CallArguments& args);
|
||||
|
||||
#define MAGLEV_REDUCED_BUILTIN(V) \
|
||||
V(FunctionPrototypeCall) \
|
||||
V(StringFromCharCode) \
|
||||
V(StringPrototypeCharCodeAt)
|
||||
|
||||
#define DEFINE_BUILTIN_REDUCER(Name) \
|
||||
ValueNode* TryReduce##Name(compiler::JSFunctionRef builtin_target, \
|
||||
CallArguments& args, bool set_accumulator);
|
||||
#define DEFINE_BUILTIN_REDUCER(Name) \
|
||||
bool TryReduce##Name(compiler::JSFunctionRef builtin_target, \
|
||||
const CallArguments& args);
|
||||
MAGLEV_REDUCED_BUILTIN(DEFINE_BUILTIN_REDUCER)
|
||||
#undef DEFINE_BUILTIN_REDUCER
|
||||
|
||||
ValueNode* TryReduceBuiltin(compiler::JSFunctionRef builtin_target,
|
||||
CallArguments& args, bool set_accumulator);
|
||||
ValueNode* TryBuildCallKnownJSFunction(compiler::JSFunctionRef function,
|
||||
CallArguments& args,
|
||||
bool set_accumulator);
|
||||
Call* BuildGenericCall(ValueNode* target, ValueNode* context,
|
||||
Call::TargetType target_type,
|
||||
const CallArguments& args,
|
||||
const compiler::FeedbackSource& feedback_source =
|
||||
compiler::FeedbackSource());
|
||||
ValueNode* ReduceCall(compiler::ObjectRef target, CallArguments& args,
|
||||
bool set_accumulator = true);
|
||||
void BuildCall(ValueNode* target_node, CallArguments& args,
|
||||
bool TryReduceBuiltin(compiler::JSFunctionRef builtin_target,
|
||||
const CallArguments& args);
|
||||
|
||||
bool TryBuildCallKnownJSFunction(compiler::JSFunctionRef function,
|
||||
const CallArguments& args);
|
||||
|
||||
void BuildGenericCall(ValueNode* target, ValueNode* context,
|
||||
Call::TargetType target_type, const CallArguments& args,
|
||||
compiler::FeedbackSource& feedback_source);
|
||||
void BuildCall(ValueNode* target_node, const CallArguments& args,
|
||||
compiler::FeedbackSource& feedback_source);
|
||||
void BuildCallFromRegisterList(ConvertReceiverMode receiver_mode);
|
||||
void BuildCallFromRegisters(int argc_count,
|
||||
|
Loading…
Reference in New Issue
Block a user