GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — deps: V8: cherry-pick fd75c97d3f56 · nodejs/node@e3b75cb

File tree

Expand file treeCollapse file tree
Open diff view settings
Filter options
  • common.gypi
  • deps/v8
    • src
      • ast
        • ast.cc
        • ast.h
      • interpreter
        • bytecode-generator.cc
      • parsing
        • parser-base.h
        • parser.cc
        • parser.h
        • preparser.h
    • test
      • cctest/interpreter/bytecode_expectations
        • CallAndSpread.golden
      • mjsunit/regress
        • regress-11558.js
      • test262
        • test262.status
Expand file treeCollapse file tree
Open diff view settings
Collapse file

‎common.gypi‎

Copy file name to clipboardExpand all lines: common.gypi
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636

3737
# Reset this number to 0 on major V8 upgrades.
3838
# Increment by one for each non-official patch applied to deps/v8.
39-
'v8_embedder_string': '-node.10',
39+
'v8_embedder_string': '-node.11',
4040

4141
##### V8 defaults for Node.js #####
4242

Collapse file

‎deps/v8/src/ast/ast.cc‎

Copy file name to clipboardExpand all lines: deps/v8/src/ast/ast.cc
+16Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -935,6 +935,22 @@ Call::CallType Call::GetCallType() const {
935935
return OTHER_CALL;
936936
}
937937

938+
void Call::ComputeSpreadPosition() {
939+
int arguments_length = arguments_.length();
940+
int first_spread_index = 0;
941+
for (; first_spread_index < arguments_length; first_spread_index++) {
942+
if (arguments_.at(first_spread_index)->IsSpread()) break;
943+
}
944+
SpreadPosition position;
945+
if (first_spread_index == arguments_length - 1) {
946+
position = kHasFinalSpread;
947+
} else {
948+
DCHECK_LT(first_spread_index, arguments_length - 1);
949+
position = kHasNonFinalSpread;
950+
}
951+
bit_field_ |= SpreadPositionField::encode(position);
952+
}
953+
938954
CaseClause::CaseClause(Zone* zone, Expression* label,
939955
const ScopedPtrList<Statement>& statements)
940956
: label_(label), statements_(statements.ToConstVector(), zone) {}
Collapse file

‎deps/v8/src/ast/ast.h‎

Copy file name to clipboardExpand all lines: deps/v8/src/ast/ast.h
+19-5Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1635,6 +1635,12 @@ class Call final : public Expression {
16351635
return IsOptionalChainLinkField::decode(bit_field_);
16361636
}
16371637

1638+
enum SpreadPosition { kNoSpread, kHasFinalSpread, kHasNonFinalSpread };
1639+
SpreadPosition spread_position() const {
1640+
return SpreadPositionField::decode(bit_field_);
1641+
}
1642+
1643+
// TODO(syg): Remove this and its users.
16381644
bool only_last_arg_is_spread() {
16391645
return !arguments_.is_empty() && arguments_.last()->IsSpread();
16401646
}
@@ -1669,15 +1675,17 @@ class Call final : public Expression {
16691675
friend Zone;
16701676

16711677
Call(Zone* zone, Expression* expression,
1672-
const ScopedPtrList<Expression>& arguments, int pos,
1678+
const ScopedPtrList<Expression>& arguments, int pos, bool has_spread,
16731679
PossiblyEval possibly_eval, bool optional_chain)
16741680
: Expression(pos, kCall),
16751681
expression_(expression),
16761682
arguments_(arguments.ToConstVector(), zone) {
16771683
bit_field_ |=
16781684
IsPossiblyEvalField::encode(possibly_eval == IS_POSSIBLY_EVAL) |
16791685
IsTaggedTemplateField::encode(false) |
1680-
IsOptionalChainLinkField::encode(optional_chain);
1686+
IsOptionalChainLinkField::encode(optional_chain) |
1687+
SpreadPositionField::encode(kNoSpread);
1688+
if (has_spread) ComputeSpreadPosition();
16811689
}
16821690

16831691
Call(Zone* zone, Expression* expression,
@@ -1688,12 +1696,17 @@ class Call final : public Expression {
16881696
arguments_(arguments.ToConstVector(), zone) {
16891697
bit_field_ |= IsPossiblyEvalField::encode(false) |
16901698
IsTaggedTemplateField::encode(true) |
1691-
IsOptionalChainLinkField::encode(false);
1699+
IsOptionalChainLinkField::encode(false) |
1700+
SpreadPositionField::encode(kNoSpread);
16921701
}
16931702

1703+
// Only valid to be called if there is a spread in arguments_.
1704+
void ComputeSpreadPosition();
1705+
16941706
using IsPossiblyEvalField = Expression::NextBitField<bool, 1>;
16951707
using IsTaggedTemplateField = IsPossiblyEvalField::Next<bool, 1>;
16961708
using IsOptionalChainLinkField = IsTaggedTemplateField::Next<bool, 1>;
1709+
using SpreadPositionField = IsOptionalChainLinkField::Next<SpreadPosition, 2>;
16971710

16981711
Expression* expression_;
16991712
ZonePtrList<Expression> arguments_;
@@ -3064,11 +3077,12 @@ class AstNodeFactory final {
30643077

30653078
Call* NewCall(Expression* expression,
30663079
const ScopedPtrList<Expression>& arguments, int pos,
3080+
bool has_spread,
30673081
Call::PossiblyEval possibly_eval = Call::NOT_EVAL,
30683082
bool optional_chain = false) {
30693083
DCHECK_IMPLIES(possibly_eval == Call::IS_POSSIBLY_EVAL, !optional_chain);
3070-
return zone_->New<Call>(zone_, expression, arguments, pos, possibly_eval,
3071-
optional_chain);
3084+
return zone_->New<Call>(zone_, expression, arguments, pos, has_spread,
3085+
possibly_eval, optional_chain);
30723086
}
30733087

30743088
Call* NewTaggedTemplate(Expression* expression,
Collapse file

‎deps/v8/src/interpreter/bytecode-generator.cc‎

Copy file name to clipboardExpand all lines: deps/v8/src/interpreter/bytecode-generator.cc
+76-30Lines changed: 76 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3106,6 +3106,8 @@ void BytecodeGenerator::BuildCreateArrayLiteral(
31063106
.StoreAccumulatorInRegister(index);
31073107
}
31083108
} else {
3109+
// TODO(v8:11582): Support allocating boilerplates here.
3110+
31093111
// In other cases, we prepare an empty array to be filled in below.
31103112
DCHECK(!elements->is_empty());
31113113
int literal_index = feedback_index(feedback_spec()->AddLiteralSlot());
@@ -5022,17 +5024,30 @@ void BytecodeGenerator::VisitCall(Call* expr) {
50225024
return VisitCallSuper(expr);
50235025
}
50245026

5027+
// We compile the call differently depending on the presence of spreads and
5028+
// their positions.
5029+
//
5030+
// If there is only one spread and it is the final argument, there is a
5031+
// special CallWithSpread bytecode.
5032+
//
5033+
// If there is a non-final spread, we rewrite calls like
5034+
// callee(1, ...x, 2)
5035+
// to
5036+
// %reflect_apply(callee, receiver, [1, ...x, 2])
5037+
const Call::SpreadPosition spread_position = expr->spread_position();
5038+
50255039
// Grow the args list as we visit receiver / arguments to avoid allocating all
50265040
// the registers up-front. Otherwise these registers are unavailable during
50275041
// receiver / argument visiting and we can end up with memory leaks due to
50285042
// registers keeping objects alive.
5029-
Register callee = register_allocator()->NewRegister();
50305043
RegisterList args = register_allocator()->NewGrowableRegisterList();
50315044

5045+
// The callee is the first register in args for ease of calling %reflect_apply
5046+
// if we have a non-final spread. For all other cases it is popped from args
5047+
// before emitting the call below.
5048+
Register callee = register_allocator()->GrowRegisterList(&args);
5049+
50325050
bool implicit_undefined_receiver = false;
5033-
// When a call contains a spread, a Call AST node is only created if there is
5034-
// exactly one spread, and it is the last argument.
5035-
bool is_spread_call = expr->only_last_arg_is_spread();
50365051
bool optimize_as_one_shot = ShouldOptimizeAsOneShot();
50375052

50385053
// TODO(petermarshall): We have a lot of call bytecodes that are very similar,
@@ -5052,7 +5067,7 @@ void BytecodeGenerator::VisitCall(Call* expr) {
50525067
}
50535068
case Call::GLOBAL_CALL: {
50545069
// Receiver is undefined for global calls.
5055-
if (!is_spread_call && !optimize_as_one_shot) {
5070+
if (spread_position == Call::kNoSpread && !optimize_as_one_shot) {
50565071
implicit_undefined_receiver = true;
50575072
} else {
50585073
// TODO(leszeks): There's no special bytecode for tail calls or spread
@@ -5088,7 +5103,7 @@ void BytecodeGenerator::VisitCall(Call* expr) {
50885103
}
50895104
case Call::OTHER_CALL: {
50905105
// Receiver is undefined for other calls.
5091-
if (!is_spread_call && !optimize_as_one_shot) {
5106+
if (spread_position == Call::kNoSpread && !optimize_as_one_shot) {
50925107
implicit_undefined_receiver = true;
50935108
} else {
50945109
// TODO(leszeks): There's no special bytecode for tail calls or spread
@@ -5137,25 +5152,51 @@ void BytecodeGenerator::VisitCall(Call* expr) {
51375152
BuildIncrementBlockCoverageCounterIfEnabled(right_range);
51385153
}
51395154

5140-
// Evaluate all arguments to the function call and store in sequential args
5141-
// registers.
5142-
VisitArguments(expr->arguments(), &args);
5143-
int receiver_arg_count = implicit_undefined_receiver ? 0 : 1;
5144-
CHECK_EQ(receiver_arg_count + expr->arguments()->length(),
5145-
args.register_count());
5155+
int receiver_arg_count = -1;
5156+
if (spread_position == Call::kHasNonFinalSpread) {
5157+
// If we're building %reflect_apply, build the array literal and put it in
5158+
// the 3rd argument.
5159+
DCHECK(!implicit_undefined_receiver);
5160+
DCHECK_EQ(args.register_count(), 2);
5161+
BuildCreateArrayLiteral(expr->arguments(), nullptr);
5162+
builder()->StoreAccumulatorInRegister(
5163+
register_allocator()->GrowRegisterList(&args));
5164+
} else {
5165+
// If we're not building %reflect_apply and don't need to build an array
5166+
// literal, pop the callee and evaluate all arguments to the function call
5167+
// and store in sequential args registers.
5168+
args = args.PopLeft();
5169+
VisitArguments(expr->arguments(), &args);
5170+
receiver_arg_count = implicit_undefined_receiver ? 0 : 1;
5171+
CHECK_EQ(receiver_arg_count + expr->arguments()->length(),
5172+
args.register_count());
5173+
}
51465174

51475175
// Resolve callee for a potential direct eval call. This block will mutate the
51485176
// callee value.
51495177
if (expr->is_possibly_eval() && expr->arguments()->length() > 0) {
51505178
RegisterAllocationScope inner_register_scope(this);
5179+
RegisterList runtime_call_args = register_allocator()->NewRegisterList(6);
51515180
// Set up arguments for ResolvePossiblyDirectEval by copying callee, source
51525181
// strings and function closure, and loading language and
51535182
// position.
5154-
Register first_arg = args[receiver_arg_count];
5155-
RegisterList runtime_call_args = register_allocator()->NewRegisterList(6);
5183+
5184+
// Move the first arg.
5185+
if (spread_position == Call::kHasNonFinalSpread) {
5186+
int feedback_slot_index =
5187+
feedback_index(feedback_spec()->AddKeyedLoadICSlot());
5188+
Register args_array = args[2];
5189+
builder()
5190+
->LoadLiteral(Smi::FromInt(0))
5191+
.LoadKeyedProperty(args_array, feedback_slot_index)
5192+
.StoreAccumulatorInRegister(runtime_call_args[1]);
5193+
} else {
5194+
// FIXME(v8:5690): Support final spreads for eval.
5195+
DCHECK_GE(receiver_arg_count, 0);
5196+
builder()->MoveRegister(args[receiver_arg_count], runtime_call_args[1]);
5197+
}
51565198
builder()
51575199
->MoveRegister(callee, runtime_call_args[0])
5158-
.MoveRegister(first_arg, runtime_call_args[1])
51595200
.MoveRegister(Register::function_closure(), runtime_call_args[2])
51605201
.LoadLiteral(Smi::FromEnum(language_mode()))
51615202
.StoreAccumulatorInRegister(runtime_call_args[3])
@@ -5172,10 +5213,12 @@ void BytecodeGenerator::VisitCall(Call* expr) {
51725213

51735214
builder()->SetExpressionPosition(expr);
51745215

5175-
if (is_spread_call) {
5216+
if (spread_position == Call::kHasFinalSpread) {
51765217
DCHECK(!implicit_undefined_receiver);
51775218
builder()->CallWithSpread(callee, args,
51785219
feedback_index(feedback_spec()->AddCallICSlot()));
5220+
} else if (spread_position == Call::kHasNonFinalSpread) {
5221+
builder()->CallJSRuntime(Context::REFLECT_APPLY_INDEX, args);
51795222
} else if (optimize_as_one_shot) {
51805223
DCHECK(!implicit_undefined_receiver);
51815224
builder()->CallNoFeedback(callee, args);
@@ -5198,10 +5241,20 @@ void BytecodeGenerator::VisitCallSuper(Call* expr) {
51985241
SuperCallReference* super = expr->expression()->AsSuperCallReference();
51995242
const ZonePtrList<Expression>* args = expr->arguments();
52005243

5201-
int first_spread_index = 0;
5202-
for (; first_spread_index < args->length(); first_spread_index++) {
5203-
if (args->at(first_spread_index)->IsSpread()) break;
5204-
}
5244+
// We compile the super call differently depending on the presence of spreads
5245+
// and their positions.
5246+
//
5247+
// If there is only one spread and it is the final argument, there is a
5248+
// special ConstructWithSpread bytecode.
5249+
//
5250+
// It there is a non-final spread, we rewrite something like
5251+
// super(1, ...x, 2)
5252+
// to
5253+
// %reflect_construct(constructor, [1, ...x, 2], new_target)
5254+
//
5255+
// That is, we implement (non-last-arg) spreads in super calls via our
5256+
// mechanism for spreads in array literals.
5257+
const Call::SpreadPosition spread_position = expr->spread_position();
52055258

52065259
// Prepare the constructor to the super call.
52075260
Register this_function = VisitForRegisterValue(super->this_function_var());
@@ -5210,14 +5263,7 @@ void BytecodeGenerator::VisitCallSuper(Call* expr) {
52105263
->LoadAccumulatorWithRegister(this_function)
52115264
.GetSuperConstructor(constructor);
52125265

5213-
if (first_spread_index < expr->arguments()->length() - 1) {
5214-
// We rewrite something like
5215-
// super(1, ...x, 2)
5216-
// to
5217-
// %reflect_construct(constructor, [1, ...x, 2], new_target)
5218-
// That is, we implement (non-last-arg) spreads in super calls via our
5219-
// mechanism for spreads in array literals.
5220-
5266+
if (spread_position == Call::kHasNonFinalSpread) {
52215267
// First generate the array containing all arguments.
52225268
BuildCreateArrayLiteral(args, nullptr);
52235269

@@ -5244,11 +5290,11 @@ void BytecodeGenerator::VisitCallSuper(Call* expr) {
52445290

52455291
int feedback_slot_index = feedback_index(feedback_spec()->AddCallICSlot());
52465292

5247-
if (first_spread_index == expr->arguments()->length() - 1) {
5293+
if (spread_position == Call::kHasFinalSpread) {
52485294
builder()->ConstructWithSpread(constructor, args_regs,
52495295
feedback_slot_index);
52505296
} else {
5251-
DCHECK_EQ(first_spread_index, expr->arguments()->length());
5297+
DCHECK_EQ(spread_position, Call::kNoSpread);
52525298
// Call construct.
52535299
// TODO(turbofan): For now we do gather feedback on super constructor
52545300
// calls, utilizing the existing machinery to inline the actual call
Collapse file

‎deps/v8/src/parsing/parser-base.h‎

Copy file name to clipboardExpand all lines: deps/v8/src/parsing/parser-base.h
+4-12Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1186,6 +1186,7 @@ class ParserBase {
11861186
BlockT ParseClassStaticBlock(ClassInfo* class_info);
11871187
ObjectLiteralPropertyT ParseObjectPropertyDefinition(
11881188
ParsePropertyInfo* prop_info, bool* has_seen_proto);
1189+
// TODO(syg): Remove has_spread once SpreadCallNew is removed.
11891190
void ParseArguments(
11901191
ExpressionListT* args, bool* has_spread,
11911192
ParsingArrowHeadFlag maybe_arrow = kCertainlyNotArrowHead);
@@ -3392,11 +3393,7 @@ ParserBase<Impl>::ParseLeftHandSideContinuation(ExpressionT result) {
33923393
return result;
33933394
}
33943395

3395-
if (has_spread) {
3396-
result = impl()->SpreadCall(result, args, pos, Call::NOT_EVAL, false);
3397-
} else {
3398-
result = factory()->NewCall(result, args, pos, Call::NOT_EVAL);
3399-
}
3396+
result = factory()->NewCall(result, args, pos, has_spread);
34003397

34013398
maybe_arrow.ValidateExpression();
34023399

@@ -3490,13 +3487,8 @@ ParserBase<Impl>::ParseLeftHandSideContinuation(ExpressionT result) {
34903487
Call::PossiblyEval is_possibly_eval =
34913488
CheckPossibleEvalCall(result, is_optional, scope());
34923489

3493-
if (has_spread) {
3494-
result = impl()->SpreadCall(result, args, pos, is_possibly_eval,
3495-
is_optional);
3496-
} else {
3497-
result = factory()->NewCall(result, args, pos, is_possibly_eval,
3498-
is_optional);
3499-
}
3490+
result = factory()->NewCall(result, args, pos, has_spread,
3491+
is_possibly_eval, is_optional);
35003492

35013493
fni_.RemoveLastFunction();
35023494
break;
Collapse file

‎deps/v8/src/parsing/parser.cc‎

Copy file name to clipboardExpand all lines: deps/v8/src/parsing/parser.cc
+3-39Lines changed: 3 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,8 @@ FunctionLiteral* Parser::DefaultConstructor(const AstRawString* name,
6969

7070
args.Add(spread_args);
7171
Expression* super_call_ref = NewSuperCallReference(pos);
72-
call = factory()->NewCall(super_call_ref, args, pos);
72+
constexpr bool has_spread = true;
73+
call = factory()->NewCall(super_call_ref, args, pos, has_spread);
7374
}
7475
body.Add(factory()->NewReturnStatement(call, pos));
7576
}
@@ -3371,47 +3372,10 @@ ArrayLiteral* Parser::ArrayLiteralFromListWithSpread(
33713372
return factory()->NewArrayLiteral(list, first_spread, kNoSourcePosition);
33723373
}
33733374

3374-
Expression* Parser::SpreadCall(Expression* function,
3375-
const ScopedPtrList<Expression>& args_list,
3376-
int pos, Call::PossiblyEval is_possibly_eval,
3377-
bool optional_chain) {
3378-
// Handle this case in BytecodeGenerator.
3379-
if (OnlyLastArgIsSpread(args_list) || function->IsSuperCallReference()) {
3380-
return factory()->NewCall(function, args_list, pos, Call::NOT_EVAL,
3381-
optional_chain);
3382-
}
3383-
3384-
ScopedPtrList<Expression> args(pointer_buffer());
3385-
if (function->IsProperty()) {
3386-
// Method calls
3387-
if (function->AsProperty()->IsSuperAccess()) {
3388-
Expression* home = ThisExpression();
3389-
args.Add(function);
3390-
args.Add(home);
3391-
} else {
3392-
Variable* temp = NewTemporary(ast_value_factory()->empty_string());
3393-
VariableProxy* obj = factory()->NewVariableProxy(temp);
3394-
Assignment* assign_obj = factory()->NewAssignment(
3395-
Token::ASSIGN, obj, function->AsProperty()->obj(), kNoSourcePosition);
3396-
function =
3397-
factory()->NewProperty(assign_obj, function->AsProperty()->key(),
3398-
kNoSourcePosition, optional_chain);
3399-
args.Add(function);
3400-
obj = factory()->NewVariableProxy(temp);
3401-
args.Add(obj);
3402-
}
3403-
} else {
3404-
// Non-method calls
3405-
args.Add(function);
3406-
args.Add(factory()->NewUndefinedLiteral(kNoSourcePosition));
3407-
}
3408-
args.Add(ArrayLiteralFromListWithSpread(args_list));
3409-
return factory()->NewCallRuntime(Context::REFLECT_APPLY_INDEX, args, pos);
3410-
}
3411-
34123375
Expression* Parser::SpreadCallNew(Expression* function,
34133376
const ScopedPtrList<Expression>& args_list,
34143377
int pos) {
3378+
// TODO(syg): Handle all spread cases in BytecodeGenerator.
34153379
if (OnlyLastArgIsSpread(args_list)) {
34163380
// Handle in BytecodeGenerator.
34173381
return factory()->NewCallNew(function, args_list, pos);
Collapse file

‎deps/v8/src/parsing/parser.h‎

Copy file name to clipboardExpand all lines: deps/v8/src/parsing/parser.h
-4Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -493,10 +493,6 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
493493

494494
ArrayLiteral* ArrayLiteralFromListWithSpread(
495495
const ScopedPtrList<Expression>& list);
496-
Expression* SpreadCall(Expression* function,
497-
const ScopedPtrList<Expression>& args, int pos,
498-
Call::PossiblyEval is_possibly_eval,
499-
bool optional_chain);
500496
Expression* SpreadCallNew(Expression* function,
501497
const ScopedPtrList<Expression>& args, int pos);
502498
Expression* RewriteSuperCall(Expression* call_expression);

0 commit comments

Comments
0 (0)
You are visitor 01402520 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.