Chromium Code Reviews| 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/code-stubs.h" | 9 #include "src/code-stubs.h" |
| 10 #include "src/compilation-info.h" | 10 #include "src/compilation-info.h" |
| (...skipping 2468 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2479 RegisterAllocationScope register_scope(this); | 2479 RegisterAllocationScope register_scope(this); |
| 2480 SuperCallReference* super = expr->expression()->AsSuperCallReference(); | 2480 SuperCallReference* super = expr->expression()->AsSuperCallReference(); |
| 2481 | 2481 |
| 2482 // Prepare the constructor to the super call. | 2482 // Prepare the constructor to the super call. |
| 2483 Register this_function = VisitForRegisterValue(super->this_function_var()); | 2483 Register this_function = VisitForRegisterValue(super->this_function_var()); |
| 2484 builder()->CallRuntime(Runtime::kInlineGetSuperConstructor, this_function); | 2484 builder()->CallRuntime(Runtime::kInlineGetSuperConstructor, this_function); |
| 2485 | 2485 |
| 2486 Register constructor = this_function; // Re-use dead this_function register. | 2486 Register constructor = this_function; // Re-use dead this_function register. |
| 2487 builder()->StoreAccumulatorInRegister(constructor); | 2487 builder()->StoreAccumulatorInRegister(constructor); |
| 2488 | 2488 |
| 2489 RegisterList args = | 2489 ZoneList<Expression*>* args = expr->arguments(); |
| 2490 register_allocator()->NewRegisterList(expr->arguments()->length()); | 2490 RegisterList args_regs = |
| 2491 VisitArguments(expr->arguments(), args); | 2491 register_allocator()->NewRegisterList(args->length()); |
|
rmcilroy
2016/11/29 15:51:56
These are only used in the else branch, please mov
petermarshall
2016/11/30 13:11:09
Done
| |
| 2492 | 2492 |
| 2493 // The new target is loaded into the accumulator from the | 2493 bool has_spread = false; |
| 2494 // {new.target} variable. | 2494 for (int i = 0; i < args->length(); i++) { |
| 2495 VisitForAccumulatorValue(super->new_target_var()); | 2495 if (args->at(i)->IsSpread()) has_spread = true; |
| 2496 } | |
| 2496 | 2497 |
| 2497 // Call construct. | 2498 if (has_spread) { |
| 2498 builder()->SetExpressionPosition(expr); | 2499 // Pre-allocate regs for ReflectConstruct so we can use them. |
| 2499 // TODO(turbofan): For now we do gather feedback on super constructor | 2500 RegisterList reflect_construct_args = |
| 2500 // calls, utilizing the existing machinery to inline the actual call | 2501 register_allocator()->NewRegisterList(4); |
|
rmcilroy
2016/11/29 15:51:56
You can move this down to the first point you use
petermarshall
2016/11/30 13:11:09
Done
| |
| 2501 // target and the JSCreate for the implicit receiver allocation. This | 2502 |
| 2502 // is not an ideal solution for super constructor calls, but it gets | 2503 // Deal with the spread arg |
|
rmcilroy
2016/11/29 15:51:56
fullstop on comments
petermarshall
2016/11/30 13:11:09
Done
| |
| 2503 // the job done for now. In the long run we might want to revisit this | 2504 if (args->length() == 1) { |
| 2504 // and come up with a better way. | 2505 Register spread_array = VisitForRegisterValue( |
| 2505 int const feedback_slot_index = feedback_index(expr->CallFeedbackICSlot()); | 2506 args->at(args->length() - 1)->AsSpread()->expression()); |
| 2506 builder()->New(constructor, args, feedback_slot_index); | 2507 Runtime::FunctionId function_id = Runtime::kSpreadIterablePrepare; |
| 2508 builder()->CallRuntime(function_id, spread_array); | |
| 2509 } else { | |
| 2510 RegisterList spread_prepare_args = | |
| 2511 register_allocator()->NewRegisterList(args->length()); | |
| 2512 // visit args at 0 --> length -2 inclusive | |
|
rmcilroy
2016/11/29 15:51:56
And capitals
rmcilroy
2016/11/29 15:51:56
length -2 -> length - 2
petermarshall
2016/11/30 13:11:09
Done
| |
| 2513 for (int i = 0; i < args->length() - 1; i++) { | |
| 2514 VisitForRegisterValue(args->at(i), spread_prepare_args[i]); | |
| 2515 } | |
| 2516 // visit the spread | |
| 2517 VisitForRegisterValue( | |
| 2518 args->at(args->length() - 1)->AsSpread()->expression(), | |
| 2519 spread_prepare_args[args->length() - 1]); | |
|
rmcilroy
2016/11/29 15:51:56
Is this not assuming the spread arg is at the end
petermarshall
2016/11/30 13:11:09
There are two cases here - with and without spread
rmcilroy
2016/11/30 14:35:32
Right, My point was more that if the spread is onl
petermarshall
2016/11/30 15:24:48
Ahhhh I see your point, that is much nicer. Need t
| |
| 2520 | |
| 2521 Runtime::FunctionId function_id = Runtime::kSpreadIterablePrepareVarargs; | |
| 2522 builder()->CallRuntime(function_id, spread_prepare_args); | |
| 2523 } | |
|
rmcilroy
2016/11/29 15:51:56
This seems a lot of special casing for either 1 sp
petermarshall
2016/11/30 13:11:09
Yeah that is definitely much simpler, done.
| |
| 2524 | |
|
rmcilroy
2016/11/29 15:51:56
Could the code dealing with spread arguments be mo
petermarshall
2016/11/30 13:11:09
Yep much simpler, done
| |
| 2525 builder()->StoreAccumulatorInRegister(reflect_construct_args[2]); | |
| 2526 | |
| 2527 // Do ReflectConstruct | |
| 2528 Register receiver = reflect_construct_args[0]; | |
| 2529 builder()->LoadUndefined().StoreAccumulatorInRegister(receiver); | |
| 2530 builder()->MoveRegister(constructor, reflect_construct_args[1]); | |
| 2531 VisitForRegisterValue(super->new_target_var(), reflect_construct_args[3]); | |
| 2532 builder()->CallJSRuntime(Context::REFLECT_CONSTRUCT_INDEX, | |
| 2533 reflect_construct_args); | |
|
rmcilroy
2016/11/29 15:51:56
Please add tests for this in test-bytecode-generat
petermarshall
2016/11/30 13:11:09
Done
| |
| 2534 } else { | |
| 2535 VisitArguments(args, args_regs); | |
| 2536 // The new target is loaded into the accumulator from the | |
| 2537 // {new.target} variable. | |
| 2538 VisitForAccumulatorValue(super->new_target_var()); | |
| 2539 | |
| 2540 // Call construct. | |
| 2541 builder()->SetExpressionPosition(expr); | |
| 2542 // TODO(turbofan): For now we do gather feedback on super constructor | |
| 2543 // calls, utilizing the existing machinery to inline the actual call | |
| 2544 // target and the JSCreate for the implicit receiver allocation. This | |
| 2545 // is not an ideal solution for super constructor calls, but it gets | |
| 2546 // the job done for now. In the long run we might want to revisit this | |
| 2547 // and come up with a better way. | |
| 2548 int const feedback_slot_index = feedback_index(expr->CallFeedbackICSlot()); | |
| 2549 builder()->New(constructor, args_regs, feedback_slot_index); | |
| 2550 } | |
| 2507 } | 2551 } |
| 2508 | 2552 |
| 2509 void BytecodeGenerator::VisitCallNew(CallNew* expr) { | 2553 void BytecodeGenerator::VisitCallNew(CallNew* expr) { |
| 2510 Register constructor = VisitForRegisterValue(expr->expression()); | 2554 Register constructor = VisitForRegisterValue(expr->expression()); |
| 2511 RegisterList args = | 2555 RegisterList args = |
| 2512 register_allocator()->NewRegisterList(expr->arguments()->length()); | 2556 register_allocator()->NewRegisterList(expr->arguments()->length()); |
| 2513 VisitArguments(expr->arguments(), args); | 2557 VisitArguments(expr->arguments(), args); |
| 2514 | 2558 |
| 2515 builder()->SetExpressionPosition(expr); | 2559 builder()->SetExpressionPosition(expr); |
| 2516 // The accumulator holds new target which is the same as the | 2560 // The accumulator holds new target which is the same as the |
| (...skipping 679 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3196 } | 3240 } |
| 3197 | 3241 |
| 3198 Runtime::FunctionId BytecodeGenerator::StoreKeyedToSuperRuntimeId() { | 3242 Runtime::FunctionId BytecodeGenerator::StoreKeyedToSuperRuntimeId() { |
| 3199 return is_strict(language_mode()) ? Runtime::kStoreKeyedToSuper_Strict | 3243 return is_strict(language_mode()) ? Runtime::kStoreKeyedToSuper_Strict |
| 3200 : Runtime::kStoreKeyedToSuper_Sloppy; | 3244 : Runtime::kStoreKeyedToSuper_Sloppy; |
| 3201 } | 3245 } |
| 3202 | 3246 |
| 3203 } // namespace interpreter | 3247 } // namespace interpreter |
| 3204 } // namespace internal | 3248 } // namespace internal |
| 3205 } // namespace v8 | 3249 } // namespace v8 |
| OLD | NEW |