OLD | NEW |
---|---|
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 2397 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2408 } | 2408 } |
2409 | 2409 |
2410 void BytecodeGenerator::VisitCall(Call* expr) { | 2410 void BytecodeGenerator::VisitCall(Call* expr) { |
2411 Expression* callee_expr = expr->expression(); | 2411 Expression* callee_expr = expr->expression(); |
2412 Call::CallType call_type = expr->GetCallType(); | 2412 Call::CallType call_type = expr->GetCallType(); |
2413 | 2413 |
2414 if (call_type == Call::SUPER_CALL) { | 2414 if (call_type == Call::SUPER_CALL) { |
2415 return VisitCallSuper(expr); | 2415 return VisitCallSuper(expr); |
2416 } | 2416 } |
2417 | 2417 |
2418 Register callee = register_allocator()->NewRegister(); | |
2419 // Grow the args list as we visit receiver / arguments to avoid allocating all | 2418 // Grow the args list as we visit receiver / arguments to avoid allocating all |
2420 // the registers up-front. Otherwise these registers are unavailable during | 2419 // the registers up-front. Otherwise these registers are unavailable during |
2421 // receiver / argument visiting and we can end up with memory leaks due to | 2420 // receiver / argument visiting and we can end up with memory leaks due to |
2422 // registers keeping objects alive. | 2421 // registers keeping objects alive. |
2423 RegisterList args = register_allocator()->NewGrowableRegisterList(); | 2422 RegisterList args; |
2423 Register callee; | |
2424 if (!expr->arguments()->is_empty() && expr->arguments()->last()->IsSpread()) { | |
rmcilroy
2017/01/16 10:29:40
Could you pull this out to a boolean and reuse it
petermarshall
2017/01/16 15:01:10
Yes I like it on the Call Expression (and CallNew)
| |
2425 args = register_allocator()->NewGrowableRegisterList(); | |
2426 callee = register_allocator()->GrowRegisterList(&args); | |
2427 } else { | |
2428 callee = register_allocator()->NewRegister(); | |
2429 args = register_allocator()->NewGrowableRegisterList(); | |
2430 } | |
2424 | 2431 |
2425 // Prepare the callee and the receiver to the function call. This depends on | 2432 // Prepare the callee and the receiver to the function call. This depends on |
2426 // the semantics of the underlying call type. | 2433 // the semantics of the underlying call type. |
2427 switch (call_type) { | 2434 switch (call_type) { |
2428 case Call::NAMED_PROPERTY_CALL: | 2435 case Call::NAMED_PROPERTY_CALL: |
2429 case Call::KEYED_PROPERTY_CALL: { | 2436 case Call::KEYED_PROPERTY_CALL: { |
2430 Property* property = callee_expr->AsProperty(); | 2437 Property* property = callee_expr->AsProperty(); |
2431 VisitAndPushIntoRegisterList(property->obj(), &args); | 2438 VisitAndPushIntoRegisterList(property->obj(), &args); |
2432 VisitPropertyLoadForRegister(args[0], property, callee); | 2439 VisitPropertyLoadForRegister(args.last_register(), property, callee); |
2433 break; | 2440 break; |
2434 } | 2441 } |
2435 case Call::GLOBAL_CALL: { | 2442 case Call::GLOBAL_CALL: { |
2436 // Receiver is undefined for global calls. | 2443 // Receiver is undefined for global calls. |
2437 BuildPushUndefinedIntoRegisterList(&args); | 2444 BuildPushUndefinedIntoRegisterList(&args); |
2438 // Load callee as a global variable. | 2445 // Load callee as a global variable. |
2439 VariableProxy* proxy = callee_expr->AsVariableProxy(); | 2446 VariableProxy* proxy = callee_expr->AsVariableProxy(); |
2440 BuildVariableLoadForAccumulatorValue(proxy->var(), | 2447 BuildVariableLoadForAccumulatorValue(proxy->var(), |
2441 proxy->VariableFeedbackSlot(), | 2448 proxy->VariableFeedbackSlot(), |
2442 proxy->hole_check_mode()); | 2449 proxy->hole_check_mode()); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2483 break; | 2490 break; |
2484 } | 2491 } |
2485 case Call::SUPER_CALL: | 2492 case Call::SUPER_CALL: |
2486 UNREACHABLE(); | 2493 UNREACHABLE(); |
2487 break; | 2494 break; |
2488 } | 2495 } |
2489 | 2496 |
2490 // Evaluate all arguments to the function call and store in sequential args | 2497 // Evaluate all arguments to the function call and store in sequential args |
2491 // registers. | 2498 // registers. |
2492 VisitArguments(expr->arguments(), &args); | 2499 VisitArguments(expr->arguments(), &args); |
2493 CHECK_EQ(expr->arguments()->length() + 1, args.register_count()); | |
rmcilroy
2017/01/16 10:29:40
Please leave this DCHECK in for non spread calls (
petermarshall
2017/01/16 15:01:10
Yep, Done.
| |
2494 | 2500 |
2495 // Resolve callee for a potential direct eval call. This block will mutate the | 2501 // Resolve callee for a potential direct eval call. This block will mutate the |
2496 // callee value. | 2502 // callee value. |
2497 if (expr->is_possibly_eval() && expr->arguments()->length() > 0) { | 2503 if (expr->is_possibly_eval() && expr->arguments()->length() > 0) { |
2498 RegisterAllocationScope inner_register_scope(this); | 2504 RegisterAllocationScope inner_register_scope(this); |
2499 // Set up arguments for ResolvePossiblyDirectEval by copying callee, source | 2505 // Set up arguments for ResolvePossiblyDirectEval by copying callee, source |
2500 // strings and function closure, and loading language and | 2506 // strings and function closure, and loading language and |
2501 // position. | 2507 // position. |
2502 RegisterList runtime_call_args = register_allocator()->NewRegisterList(6); | 2508 RegisterList runtime_call_args = register_allocator()->NewRegisterList(6); |
2503 builder() | 2509 builder() |
2504 ->MoveRegister(callee, runtime_call_args[0]) | 2510 ->MoveRegister(callee, runtime_call_args[0]) |
2505 .MoveRegister(args[1], runtime_call_args[1]) | 2511 .MoveRegister(args[1], runtime_call_args[1]) |
2506 .MoveRegister(Register::function_closure(), runtime_call_args[2]) | 2512 .MoveRegister(Register::function_closure(), runtime_call_args[2]) |
2507 .LoadLiteral(Smi::FromInt(language_mode())) | 2513 .LoadLiteral(Smi::FromInt(language_mode())) |
2508 .StoreAccumulatorInRegister(runtime_call_args[3]) | 2514 .StoreAccumulatorInRegister(runtime_call_args[3]) |
2509 .LoadLiteral( | 2515 .LoadLiteral( |
2510 Smi::FromInt(execution_context()->scope()->start_position())) | 2516 Smi::FromInt(execution_context()->scope()->start_position())) |
2511 .StoreAccumulatorInRegister(runtime_call_args[4]) | 2517 .StoreAccumulatorInRegister(runtime_call_args[4]) |
2512 .LoadLiteral(Smi::FromInt(expr->position())) | 2518 .LoadLiteral(Smi::FromInt(expr->position())) |
2513 .StoreAccumulatorInRegister(runtime_call_args[5]); | 2519 .StoreAccumulatorInRegister(runtime_call_args[5]); |
2514 | 2520 |
2515 // Call ResolvePossiblyDirectEval and modify the callee. | 2521 // Call ResolvePossiblyDirectEval and modify the callee. |
2516 builder() | 2522 builder() |
2517 ->CallRuntime(Runtime::kResolvePossiblyDirectEval, runtime_call_args) | 2523 ->CallRuntime(Runtime::kResolvePossiblyDirectEval, runtime_call_args) |
2518 .StoreAccumulatorInRegister(callee); | 2524 .StoreAccumulatorInRegister(callee); |
2519 } | 2525 } |
2520 | 2526 |
2521 builder()->SetExpressionPosition(expr); | 2527 builder()->SetExpressionPosition(expr); |
2522 | 2528 |
2523 int const feedback_slot_index = feedback_index(expr->CallFeedbackICSlot()); | 2529 // When a call contains a spread, a Call AST node is only created if there is |
2524 builder()->Call(callee, args, feedback_slot_index, call_type, | 2530 // exactly one spread, and it is the last argument. |
2525 expr->tail_call_mode()); | 2531 if (!expr->arguments()->is_empty() && expr->arguments()->last()->IsSpread()) { |
2532 CHECK_EQ(expr->arguments()->length() + 2, args.register_count()); | |
2533 DCHECK_EQ(expr->tail_call_mode(), TailCallMode::kDisallow); | |
Benedikt Meurer
2017/01/14 18:37:14
Nit: DCHECK_EQ(TailCallMode::kDisallow, ...)
petermarshall
2017/01/16 15:01:10
Done.
| |
2534 builder()->CallWithSpread(args); | |
rmcilroy
2017/01/16 10:29:40
The issue with this is that we already have a Call
petermarshall
2017/01/16 15:01:10
Yeah I think that suggestion makes sense - added a
| |
2535 } else { | |
2536 CHECK_EQ(expr->arguments()->length() + 1, args.register_count()); | |
2537 int const feedback_slot_index = feedback_index(expr->CallFeedbackICSlot()); | |
2538 builder()->Call(callee, args, feedback_slot_index, call_type, | |
2539 expr->tail_call_mode()); | |
2540 } | |
2526 } | 2541 } |
2527 | 2542 |
2528 void BytecodeGenerator::VisitCallSuper(Call* expr) { | 2543 void BytecodeGenerator::VisitCallSuper(Call* expr) { |
2529 RegisterAllocationScope register_scope(this); | 2544 RegisterAllocationScope register_scope(this); |
2530 SuperCallReference* super = expr->expression()->AsSuperCallReference(); | 2545 SuperCallReference* super = expr->expression()->AsSuperCallReference(); |
2531 | 2546 |
2532 // Prepare the constructor to the super call. | 2547 // Prepare the constructor to the super call. |
2533 VisitForAccumulatorValue(super->this_function_var()); | 2548 VisitForAccumulatorValue(super->this_function_var()); |
2534 Register constructor = register_allocator()->NewRegister(); | 2549 Register constructor = register_allocator()->NewRegister(); |
2535 builder()->GetSuperConstructor(constructor); | 2550 builder()->GetSuperConstructor(constructor); |
(...skipping 785 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3321 } | 3336 } |
3322 | 3337 |
3323 Runtime::FunctionId BytecodeGenerator::StoreKeyedToSuperRuntimeId() { | 3338 Runtime::FunctionId BytecodeGenerator::StoreKeyedToSuperRuntimeId() { |
3324 return is_strict(language_mode()) ? Runtime::kStoreKeyedToSuper_Strict | 3339 return is_strict(language_mode()) ? Runtime::kStoreKeyedToSuper_Strict |
3325 : Runtime::kStoreKeyedToSuper_Sloppy; | 3340 : Runtime::kStoreKeyedToSuper_Sloppy; |
3326 } | 3341 } |
3327 | 3342 |
3328 } // namespace interpreter | 3343 } // namespace interpreter |
3329 } // namespace internal | 3344 } // namespace internal |
3330 } // namespace v8 | 3345 } // namespace v8 |
OLD | NEW |