Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(7)

Side by Side Diff: src/interpreter/bytecode-generator.cc

Issue 2629363002: [Ignition/turbo] Add a CallWithSpread bytecode. (Closed)
Patch Set: reparent on the bytecode CL Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/interpreter/bytecode-array-builder.cc ('k') | src/interpreter/bytecodes.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 the V8 project authors. All rights reserved. 1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/interpreter/bytecode-generator.h" 5 #include "src/interpreter/bytecode-generator.h"
6 6
7 #include "src/ast/compile-time-value.h" 7 #include "src/ast/compile-time-value.h"
8 #include "src/ast/scopes.h" 8 #include "src/ast/scopes.h"
9 #include "src/builtins/builtins-constructor.h" 9 #include "src/builtins/builtins-constructor.h"
10 #include "src/code-stubs.h" 10 #include "src/code-stubs.h"
(...skipping 2427 matching lines...) Expand 10 before | Expand all | Expand 10 after
2438 } 2438 }
2439 2439
2440 void BytecodeGenerator::VisitCall(Call* expr) { 2440 void BytecodeGenerator::VisitCall(Call* expr) {
2441 Expression* callee_expr = expr->expression(); 2441 Expression* callee_expr = expr->expression();
2442 Call::CallType call_type = expr->GetCallType(); 2442 Call::CallType call_type = expr->GetCallType();
2443 2443
2444 if (call_type == Call::SUPER_CALL) { 2444 if (call_type == Call::SUPER_CALL) {
2445 return VisitCallSuper(expr); 2445 return VisitCallSuper(expr);
2446 } 2446 }
2447 2447
2448 Register callee = register_allocator()->NewRegister();
2449 // Grow the args list as we visit receiver / arguments to avoid allocating all 2448 // Grow the args list as we visit receiver / arguments to avoid allocating all
2450 // the registers up-front. Otherwise these registers are unavailable during 2449 // the registers up-front. Otherwise these registers are unavailable during
2451 // receiver / argument visiting and we can end up with memory leaks due to 2450 // receiver / argument visiting and we can end up with memory leaks due to
2452 // registers keeping objects alive. 2451 // registers keeping objects alive.
2453 RegisterList args = register_allocator()->NewGrowableRegisterList(); 2452 RegisterList args;
2453 Register callee;
2454 // The CallWithSpread bytecode takes all arguments in a register list so that
2455 // it can easily call into a runtime function for its implementation. This
2456 // will change once CallWithSpread has an implementation in ASM.
2457 // TODO(petermarshall): Remove this special path when CallWithSpread is done.
2458 if (expr->only_last_arg_is_spread()) {
2459 args = register_allocator()->NewGrowableRegisterList();
2460 callee = register_allocator()->GrowRegisterList(&args);
2461 } else {
2462 callee = register_allocator()->NewRegister();
2463 args = register_allocator()->NewGrowableRegisterList();
2464 }
2465
2466 // TODO(petermarshall): We have a lot of call bytecodes that are very similar,
2467 // see if we can reduce the number by adding a separate argument which
2468 // specifies the call type (e.g., property, spread, tailcall, etc.).
2454 2469
2455 // Prepare the callee and the receiver to the function call. This depends on 2470 // Prepare the callee and the receiver to the function call. This depends on
2456 // the semantics of the underlying call type. 2471 // the semantics of the underlying call type.
2457 switch (call_type) { 2472 switch (call_type) {
2458 case Call::NAMED_PROPERTY_CALL: 2473 case Call::NAMED_PROPERTY_CALL:
2459 case Call::KEYED_PROPERTY_CALL: { 2474 case Call::KEYED_PROPERTY_CALL: {
2460 Property* property = callee_expr->AsProperty(); 2475 Property* property = callee_expr->AsProperty();
2461 VisitAndPushIntoRegisterList(property->obj(), &args); 2476 VisitAndPushIntoRegisterList(property->obj(), &args);
2462 VisitPropertyLoadForRegister(args[0], property, callee); 2477 VisitPropertyLoadForRegister(args.last_register(), property, callee);
2463 break; 2478 break;
2464 } 2479 }
2465 case Call::GLOBAL_CALL: { 2480 case Call::GLOBAL_CALL: {
2466 // Receiver is undefined for global calls. 2481 // Receiver is undefined for global calls.
2467 BuildPushUndefinedIntoRegisterList(&args); 2482 BuildPushUndefinedIntoRegisterList(&args);
2468 // Load callee as a global variable. 2483 // Load callee as a global variable.
2469 VariableProxy* proxy = callee_expr->AsVariableProxy(); 2484 VariableProxy* proxy = callee_expr->AsVariableProxy();
2470 BuildVariableLoadForAccumulatorValue(proxy->var(), 2485 BuildVariableLoadForAccumulatorValue(proxy->var(),
2471 proxy->VariableFeedbackSlot(), 2486 proxy->VariableFeedbackSlot(),
2472 proxy->hole_check_mode()); 2487 proxy->hole_check_mode());
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
2513 break; 2528 break;
2514 } 2529 }
2515 case Call::SUPER_CALL: 2530 case Call::SUPER_CALL:
2516 UNREACHABLE(); 2531 UNREACHABLE();
2517 break; 2532 break;
2518 } 2533 }
2519 2534
2520 // Evaluate all arguments to the function call and store in sequential args 2535 // Evaluate all arguments to the function call and store in sequential args
2521 // registers. 2536 // registers.
2522 VisitArguments(expr->arguments(), &args); 2537 VisitArguments(expr->arguments(), &args);
2523 CHECK_EQ(expr->arguments()->length() + 1, args.register_count()); 2538 // TODO(petermarshall): Check this for spread calls as well when
2539 // CallWithSpread is done.
2540 if (!expr->only_last_arg_is_spread()) {
2541 CHECK_EQ(expr->arguments()->length() + 1, args.register_count());
2542 }
2524 2543
2525 // Resolve callee for a potential direct eval call. This block will mutate the 2544 // Resolve callee for a potential direct eval call. This block will mutate the
2526 // callee value. 2545 // callee value.
2527 if (expr->is_possibly_eval() && expr->arguments()->length() > 0) { 2546 if (expr->is_possibly_eval() && expr->arguments()->length() > 0) {
2528 RegisterAllocationScope inner_register_scope(this); 2547 RegisterAllocationScope inner_register_scope(this);
2529 // Set up arguments for ResolvePossiblyDirectEval by copying callee, source 2548 // Set up arguments for ResolvePossiblyDirectEval by copying callee, source
2530 // strings and function closure, and loading language and 2549 // strings and function closure, and loading language and
2531 // position. 2550 // position.
2532 RegisterList runtime_call_args = register_allocator()->NewRegisterList(6); 2551 RegisterList runtime_call_args = register_allocator()->NewRegisterList(6);
2533 builder() 2552 builder()
2534 ->MoveRegister(callee, runtime_call_args[0]) 2553 ->MoveRegister(callee, runtime_call_args[0])
2535 .MoveRegister(args[1], runtime_call_args[1]) 2554 .MoveRegister(args[1], runtime_call_args[1])
2536 .MoveRegister(Register::function_closure(), runtime_call_args[2]) 2555 .MoveRegister(Register::function_closure(), runtime_call_args[2])
2537 .LoadLiteral(Smi::FromInt(language_mode())) 2556 .LoadLiteral(Smi::FromInt(language_mode()))
2538 .StoreAccumulatorInRegister(runtime_call_args[3]) 2557 .StoreAccumulatorInRegister(runtime_call_args[3])
2539 .LoadLiteral( 2558 .LoadLiteral(
2540 Smi::FromInt(execution_context()->scope()->start_position())) 2559 Smi::FromInt(execution_context()->scope()->start_position()))
2541 .StoreAccumulatorInRegister(runtime_call_args[4]) 2560 .StoreAccumulatorInRegister(runtime_call_args[4])
2542 .LoadLiteral(Smi::FromInt(expr->position())) 2561 .LoadLiteral(Smi::FromInt(expr->position()))
2543 .StoreAccumulatorInRegister(runtime_call_args[5]); 2562 .StoreAccumulatorInRegister(runtime_call_args[5]);
2544 2563
2545 // Call ResolvePossiblyDirectEval and modify the callee. 2564 // Call ResolvePossiblyDirectEval and modify the callee.
2546 builder() 2565 builder()
2547 ->CallRuntime(Runtime::kResolvePossiblyDirectEval, runtime_call_args) 2566 ->CallRuntime(Runtime::kResolvePossiblyDirectEval, runtime_call_args)
2548 .StoreAccumulatorInRegister(callee); 2567 .StoreAccumulatorInRegister(callee);
2549 } 2568 }
2550 2569
2551 builder()->SetExpressionPosition(expr); 2570 builder()->SetExpressionPosition(expr);
2552 2571
2553 int const feedback_slot_index = feedback_index(expr->CallFeedbackICSlot()); 2572 // When a call contains a spread, a Call AST node is only created if there is
2554 builder()->Call(callee, args, feedback_slot_index, call_type, 2573 // exactly one spread, and it is the last argument.
2555 expr->tail_call_mode()); 2574 if (expr->only_last_arg_is_spread()) {
2575 CHECK_EQ(expr->arguments()->length() + 2, args.register_count());
2576 DCHECK_EQ(TailCallMode::kDisallow, expr->tail_call_mode());
2577 builder()->CallWithSpread(args);
2578 } else {
2579 int const feedback_slot_index = feedback_index(expr->CallFeedbackICSlot());
2580 builder()->Call(callee, args, feedback_slot_index, call_type,
2581 expr->tail_call_mode());
2582 }
2556 } 2583 }
2557 2584
2558 void BytecodeGenerator::VisitCallSuper(Call* expr) { 2585 void BytecodeGenerator::VisitCallSuper(Call* expr) {
2559 RegisterAllocationScope register_scope(this); 2586 RegisterAllocationScope register_scope(this);
2560 SuperCallReference* super = expr->expression()->AsSuperCallReference(); 2587 SuperCallReference* super = expr->expression()->AsSuperCallReference();
2561 2588
2562 // Prepare the constructor to the super call. 2589 // Prepare the constructor to the super call.
2563 VisitForAccumulatorValue(super->this_function_var()); 2590 VisitForAccumulatorValue(super->this_function_var());
2564 Register constructor = register_allocator()->NewRegister(); 2591 Register constructor = register_allocator()->NewRegister();
2565 builder()->GetSuperConstructor(constructor); 2592 builder()->GetSuperConstructor(constructor);
2566 2593
2567 ZoneList<Expression*>* args = expr->arguments(); 2594 ZoneList<Expression*>* args = expr->arguments();
2568 RegisterList args_regs = register_allocator()->NewGrowableRegisterList(); 2595 RegisterList args_regs = register_allocator()->NewGrowableRegisterList();
2569 VisitArguments(args, &args_regs); 2596 VisitArguments(args, &args_regs);
2570 // The new target is loaded into the accumulator from the 2597 // The new target is loaded into the accumulator from the
2571 // {new.target} variable. 2598 // {new.target} variable.
2572 VisitForAccumulatorValue(super->new_target_var()); 2599 VisitForAccumulatorValue(super->new_target_var());
2573 builder()->SetExpressionPosition(expr); 2600 builder()->SetExpressionPosition(expr);
2574 2601
2575 // When a super call contains a spread, a CallSuper AST node is only created 2602 // When a super call contains a spread, a CallSuper AST node is only created
2576 // if there is exactly one spread, and it is the last argument. 2603 // if there is exactly one spread, and it is the last argument.
2577 if (!args->is_empty() && args->last()->IsSpread()) { 2604 if (expr->only_last_arg_is_spread()) {
2578 // TODO(petermarshall): Collect type on the feedback slot. 2605 // TODO(petermarshall): Collect type on the feedback slot.
2579 builder()->NewWithSpread(constructor, args_regs); 2606 builder()->NewWithSpread(constructor, args_regs);
2580 } else { 2607 } else {
2581 // Call construct. 2608 // Call construct.
2582 // TODO(turbofan): For now we do gather feedback on super constructor 2609 // TODO(turbofan): For now we do gather feedback on super constructor
2583 // calls, utilizing the existing machinery to inline the actual call 2610 // calls, utilizing the existing machinery to inline the actual call
2584 // target and the JSCreate for the implicit receiver allocation. This 2611 // target and the JSCreate for the implicit receiver allocation. This
2585 // is not an ideal solution for super constructor calls, but it gets 2612 // is not an ideal solution for super constructor calls, but it gets
2586 // the job done for now. In the long run we might want to revisit this 2613 // the job done for now. In the long run we might want to revisit this
2587 // and come up with a better way. 2614 // and come up with a better way.
2588 int const feedback_slot_index = feedback_index(expr->CallFeedbackICSlot()); 2615 int const feedback_slot_index = feedback_index(expr->CallFeedbackICSlot());
2589 builder()->New(constructor, args_regs, feedback_slot_index); 2616 builder()->New(constructor, args_regs, feedback_slot_index);
2590 } 2617 }
2591 } 2618 }
2592 2619
2593 void BytecodeGenerator::VisitCallNew(CallNew* expr) { 2620 void BytecodeGenerator::VisitCallNew(CallNew* expr) {
2594 Register constructor = VisitForRegisterValue(expr->expression()); 2621 Register constructor = VisitForRegisterValue(expr->expression());
2595 RegisterList args = register_allocator()->NewGrowableRegisterList(); 2622 RegisterList args = register_allocator()->NewGrowableRegisterList();
2596 VisitArguments(expr->arguments(), &args); 2623 VisitArguments(expr->arguments(), &args);
2597 2624
2598 builder()->SetExpressionPosition(expr);
2599 // The accumulator holds new target which is the same as the 2625 // The accumulator holds new target which is the same as the
2600 // constructor for CallNew. 2626 // constructor for CallNew.
2601 builder() 2627 builder()->SetExpressionPosition(expr);
2602 ->LoadAccumulatorWithRegister(constructor) 2628 builder()->LoadAccumulatorWithRegister(constructor);
2603 .New(constructor, args, feedback_index(expr->CallNewFeedbackSlot())); 2629
2630 if (expr->only_last_arg_is_spread()) {
2631 // TODO(petermarshall): Collect type on the feedback slot.
2632 builder()->NewWithSpread(constructor, args);
2633 } else {
2634 builder()->New(constructor, args,
2635 feedback_index(expr->CallNewFeedbackSlot()));
2636 }
2604 } 2637 }
2605 2638
2606 void BytecodeGenerator::VisitCallRuntime(CallRuntime* expr) { 2639 void BytecodeGenerator::VisitCallRuntime(CallRuntime* expr) {
2607 if (expr->is_jsruntime()) { 2640 if (expr->is_jsruntime()) {
2608 RegisterList args = register_allocator()->NewGrowableRegisterList(); 2641 RegisterList args = register_allocator()->NewGrowableRegisterList();
2609 // Allocate a register for the receiver and load it with undefined. 2642 // Allocate a register for the receiver and load it with undefined.
2610 BuildPushUndefinedIntoRegisterList(&args); 2643 BuildPushUndefinedIntoRegisterList(&args);
2611 VisitArguments(expr->arguments(), &args); 2644 VisitArguments(expr->arguments(), &args);
2612 builder()->CallJSRuntime(expr->context_index(), args); 2645 builder()->CallJSRuntime(expr->context_index(), args);
2613 } else { 2646 } else {
(...skipping 727 matching lines...) Expand 10 before | Expand all | Expand 10 after
3341 } 3374 }
3342 3375
3343 Runtime::FunctionId BytecodeGenerator::StoreKeyedToSuperRuntimeId() { 3376 Runtime::FunctionId BytecodeGenerator::StoreKeyedToSuperRuntimeId() {
3344 return is_strict(language_mode()) ? Runtime::kStoreKeyedToSuper_Strict 3377 return is_strict(language_mode()) ? Runtime::kStoreKeyedToSuper_Strict
3345 : Runtime::kStoreKeyedToSuper_Sloppy; 3378 : Runtime::kStoreKeyedToSuper_Sloppy;
3346 } 3379 }
3347 3380
3348 } // namespace interpreter 3381 } // namespace interpreter
3349 } // namespace internal 3382 } // namespace internal
3350 } // namespace v8 3383 } // namespace v8
OLDNEW
« no previous file with comments | « src/interpreter/bytecode-array-builder.cc ('k') | src/interpreter/bytecodes.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698