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

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

Issue 2557173004: [Interpreter] Allocate registers used as call arguments on-demand. (Closed)
Patch Set: Created 4 years 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-generator.h ('k') | src/interpreter/bytecode-register.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/code-stubs.h" 9 #include "src/code-stubs.h"
10 #include "src/compilation-info.h" 10 #include "src/compilation-info.h"
(...skipping 2309 matching lines...) Expand 10 before | Expand all | Expand 10 after
2320 } 2320 }
2321 case NAMED_SUPER_PROPERTY: 2321 case NAMED_SUPER_PROPERTY:
2322 VisitNamedSuperPropertyLoad(expr, Register::invalid_value()); 2322 VisitNamedSuperPropertyLoad(expr, Register::invalid_value());
2323 break; 2323 break;
2324 case KEYED_SUPER_PROPERTY: 2324 case KEYED_SUPER_PROPERTY:
2325 VisitKeyedSuperPropertyLoad(expr, Register::invalid_value()); 2325 VisitKeyedSuperPropertyLoad(expr, Register::invalid_value());
2326 break; 2326 break;
2327 } 2327 }
2328 } 2328 }
2329 2329
2330 void BytecodeGenerator::VisitPropertyLoadForAccumulator(Register obj, 2330 void BytecodeGenerator::VisitPropertyLoadForRegister(Register obj,
2331 Property* expr) { 2331 Property* expr,
2332 Register destination) {
2332 ValueResultScope result_scope(this); 2333 ValueResultScope result_scope(this);
2333 VisitPropertyLoad(obj, expr); 2334 VisitPropertyLoad(obj, expr);
2335 builder()->StoreAccumulatorInRegister(destination);
2334 } 2336 }
2335 2337
2336 void BytecodeGenerator::VisitNamedSuperPropertyLoad(Property* property, 2338 void BytecodeGenerator::VisitNamedSuperPropertyLoad(Property* property,
2337 Register opt_receiver_out) { 2339 Register opt_receiver_out) {
2338 RegisterAllocationScope register_scope(this); 2340 RegisterAllocationScope register_scope(this);
2339 SuperPropertyReference* super_property = 2341 SuperPropertyReference* super_property =
2340 property->obj()->AsSuperPropertyReference(); 2342 property->obj()->AsSuperPropertyReference();
2341 RegisterList args = register_allocator()->NewRegisterList(3); 2343 RegisterList args = register_allocator()->NewRegisterList(3);
2342 VisitForRegisterValue(super_property->this_var(), args[0]); 2344 VisitForRegisterValue(super_property->this_var(), args[0]);
2343 VisitForRegisterValue(super_property->home_object(), args[1]); 2345 VisitForRegisterValue(super_property->home_object(), args[1]);
(...skipping 28 matching lines...) Expand all
2372 if (property_kind != NAMED_SUPER_PROPERTY && 2374 if (property_kind != NAMED_SUPER_PROPERTY &&
2373 property_kind != KEYED_SUPER_PROPERTY) { 2375 property_kind != KEYED_SUPER_PROPERTY) {
2374 Register obj = VisitForRegisterValue(expr->obj()); 2376 Register obj = VisitForRegisterValue(expr->obj());
2375 VisitPropertyLoad(obj, expr); 2377 VisitPropertyLoad(obj, expr);
2376 } else { 2378 } else {
2377 VisitPropertyLoad(Register::invalid_value(), expr); 2379 VisitPropertyLoad(Register::invalid_value(), expr);
2378 } 2380 }
2379 } 2381 }
2380 2382
2381 void BytecodeGenerator::VisitArguments(ZoneList<Expression*>* args, 2383 void BytecodeGenerator::VisitArguments(ZoneList<Expression*>* args,
2382 RegisterList arg_regs, 2384 RegisterList* arg_regs) {
2383 size_t first_argument_register) {
2384 // Visit arguments. 2385 // Visit arguments.
2385 for (int i = 0; i < static_cast<int>(args->length()); i++) { 2386 for (int i = 0; i < static_cast<int>(args->length()); i++) {
2386 VisitForRegisterValue(args->at(i), arg_regs[first_argument_register + i]); 2387 VisitAndPushIntoRegisterList(args->at(i), arg_regs);
2387 } 2388 }
2388 } 2389 }
2389 2390
2390 void BytecodeGenerator::VisitCall(Call* expr) { 2391 void BytecodeGenerator::VisitCall(Call* expr) {
2391 Expression* callee_expr = expr->expression(); 2392 Expression* callee_expr = expr->expression();
2392 Call::CallType call_type = expr->GetCallType(); 2393 Call::CallType call_type = expr->GetCallType();
2393 2394
2394 if (call_type == Call::SUPER_CALL) { 2395 if (call_type == Call::SUPER_CALL) {
2395 return VisitCallSuper(expr); 2396 return VisitCallSuper(expr);
2396 } 2397 }
2397 2398
2398 Register callee = register_allocator()->NewRegister(); 2399 Register callee = register_allocator()->NewRegister();
2399 2400 // Grow the args list as we visit receiver / arguments to avoid allocating all
2400 // Add an argument register for the receiver. 2401 // the registers up-front. Otherwise these registers are unavailable during
2401 RegisterList args = 2402 // receiver / argument visiting and we can end up with memory leaks due to
2402 register_allocator()->NewRegisterList(expr->arguments()->length() + 1); 2403 // registers keeping objects alive.
2403 Register receiver = args[0]; 2404 RegisterList args = register_allocator()->NewGrowableRegisterList();
2404 2405
2405 // Prepare the callee and the receiver to the function call. This depends on 2406 // Prepare the callee and the receiver to the function call. This depends on
2406 // the semantics of the underlying call type. 2407 // the semantics of the underlying call type.
2407 switch (call_type) { 2408 switch (call_type) {
2408 case Call::NAMED_PROPERTY_CALL: 2409 case Call::NAMED_PROPERTY_CALL:
2409 case Call::KEYED_PROPERTY_CALL: { 2410 case Call::KEYED_PROPERTY_CALL: {
2410 Property* property = callee_expr->AsProperty(); 2411 Property* property = callee_expr->AsProperty();
2411 VisitForAccumulatorValue(property->obj()); 2412 VisitAndPushIntoRegisterList(property->obj(), &args);
2412 builder()->StoreAccumulatorInRegister(receiver); 2413 VisitPropertyLoadForRegister(args[0], property, callee);
2413 VisitPropertyLoadForAccumulator(receiver, property);
2414 builder()->StoreAccumulatorInRegister(callee);
2415 break; 2414 break;
2416 } 2415 }
2417 case Call::GLOBAL_CALL: { 2416 case Call::GLOBAL_CALL: {
2418 // Receiver is undefined for global calls. 2417 // Receiver is undefined for global calls.
2419 builder()->LoadUndefined().StoreAccumulatorInRegister(receiver); 2418 BuildPushUndefinedIntoRegisterList(&args);
2420 // Load callee as a global variable. 2419 // Load callee as a global variable.
2421 VariableProxy* proxy = callee_expr->AsVariableProxy(); 2420 VariableProxy* proxy = callee_expr->AsVariableProxy();
2422 BuildVariableLoadForAccumulatorValue(proxy->var(), 2421 BuildVariableLoadForAccumulatorValue(proxy->var(),
2423 proxy->VariableFeedbackSlot(), 2422 proxy->VariableFeedbackSlot(),
2424 proxy->hole_check_mode()); 2423 proxy->hole_check_mode());
2425 builder()->StoreAccumulatorInRegister(callee); 2424 builder()->StoreAccumulatorInRegister(callee);
2426 break; 2425 break;
2427 } 2426 }
2428 case Call::WITH_CALL: { 2427 case Call::WITH_CALL: {
2428 Register receiver = register_allocator()->GrowRegisterList(&args);
2429 DCHECK(callee_expr->AsVariableProxy()->var()->IsLookupSlot()); 2429 DCHECK(callee_expr->AsVariableProxy()->var()->IsLookupSlot());
2430 RegisterAllocationScope inner_register_scope(this); 2430 {
2431 Register name = register_allocator()->NewRegister(); 2431 RegisterAllocationScope inner_register_scope(this);
2432 Register name = register_allocator()->NewRegister();
2432 2433
2433 // Call %LoadLookupSlotForCall to get the callee and receiver. 2434 // Call %LoadLookupSlotForCall to get the callee and receiver.
2434 DCHECK(Register::AreContiguous(callee, receiver)); 2435 DCHECK(Register::AreContiguous(callee, receiver));
2435 RegisterList result_pair(callee.index(), 2); 2436 RegisterList result_pair(callee.index(), 2);
2436 Variable* variable = callee_expr->AsVariableProxy()->var(); 2437 Variable* variable = callee_expr->AsVariableProxy()->var();
2437 builder() 2438 builder()
2438 ->LoadLiteral(variable->name()) 2439 ->LoadLiteral(variable->name())
2439 .StoreAccumulatorInRegister(name) 2440 .StoreAccumulatorInRegister(name)
2440 .CallRuntimeForPair(Runtime::kLoadLookupSlotForCall, name, 2441 .CallRuntimeForPair(Runtime::kLoadLookupSlotForCall, name,
2441 result_pair); 2442 result_pair);
2443 }
2442 break; 2444 break;
2443 } 2445 }
2444 case Call::OTHER_CALL: 2446 case Call::OTHER_CALL: {
2445 builder()->LoadUndefined().StoreAccumulatorInRegister(receiver); 2447 BuildPushUndefinedIntoRegisterList(&args);
2446 VisitForRegisterValue(callee_expr, callee); 2448 VisitForRegisterValue(callee_expr, callee);
2447 break; 2449 break;
2450 }
2448 case Call::NAMED_SUPER_PROPERTY_CALL: { 2451 case Call::NAMED_SUPER_PROPERTY_CALL: {
2452 Register receiver = register_allocator()->GrowRegisterList(&args);
2449 Property* property = callee_expr->AsProperty(); 2453 Property* property = callee_expr->AsProperty();
2450 VisitNamedSuperPropertyLoad(property, receiver); 2454 VisitNamedSuperPropertyLoad(property, receiver);
2451 builder()->StoreAccumulatorInRegister(callee); 2455 builder()->StoreAccumulatorInRegister(callee);
2452 break; 2456 break;
2453 } 2457 }
2454 case Call::KEYED_SUPER_PROPERTY_CALL: { 2458 case Call::KEYED_SUPER_PROPERTY_CALL: {
2459 Register receiver = register_allocator()->GrowRegisterList(&args);
2455 Property* property = callee_expr->AsProperty(); 2460 Property* property = callee_expr->AsProperty();
2456 VisitKeyedSuperPropertyLoad(property, receiver); 2461 VisitKeyedSuperPropertyLoad(property, receiver);
2457 builder()->StoreAccumulatorInRegister(callee); 2462 builder()->StoreAccumulatorInRegister(callee);
2458 break; 2463 break;
2459 } 2464 }
2460 case Call::SUPER_CALL: 2465 case Call::SUPER_CALL:
2461 UNREACHABLE(); 2466 UNREACHABLE();
2462 break; 2467 break;
2463 } 2468 }
2464 2469
2465 // Evaluate all arguments to the function call and store in sequential args 2470 // Evaluate all arguments to the function call and store in sequential args
2466 // registers. 2471 // registers.
2467 VisitArguments(expr->arguments(), args, 1); 2472 VisitArguments(expr->arguments(), &args);
2473 CHECK_EQ(expr->arguments()->length() + 1, args.register_count());
2468 2474
2469 // Resolve callee for a potential direct eval call. This block will mutate the 2475 // Resolve callee for a potential direct eval call. This block will mutate the
2470 // callee value. 2476 // callee value.
2471 if (expr->is_possibly_eval() && expr->arguments()->length() > 0) { 2477 if (expr->is_possibly_eval() && expr->arguments()->length() > 0) {
2472 RegisterAllocationScope inner_register_scope(this); 2478 RegisterAllocationScope inner_register_scope(this);
2473 // Set up arguments for ResolvePossiblyDirectEval by copying callee, source 2479 // Set up arguments for ResolvePossiblyDirectEval by copying callee, source
2474 // strings and function closure, and loading language and 2480 // strings and function closure, and loading language and
2475 // position. 2481 // position.
2476 RegisterList runtime_call_args = register_allocator()->NewRegisterList(6); 2482 RegisterList runtime_call_args = register_allocator()->NewRegisterList(6);
2477 builder() 2483 builder()
(...skipping 30 matching lines...) Expand all
2508 builder()->CallRuntime(Runtime::kInlineGetSuperConstructor, this_function); 2514 builder()->CallRuntime(Runtime::kInlineGetSuperConstructor, this_function);
2509 2515
2510 Register constructor = this_function; // Re-use dead this_function register. 2516 Register constructor = this_function; // Re-use dead this_function register.
2511 builder()->StoreAccumulatorInRegister(constructor); 2517 builder()->StoreAccumulatorInRegister(constructor);
2512 2518
2513 ZoneList<Expression*>* args = expr->arguments(); 2519 ZoneList<Expression*>* args = expr->arguments();
2514 2520
2515 // When a super call contains a spread, a CallSuper AST node is only created 2521 // When a super call contains a spread, a CallSuper AST node is only created
2516 // if there is exactly one spread, and it is the last argument. 2522 // if there is exactly one spread, and it is the last argument.
2517 if (!args->is_empty() && args->last()->IsSpread()) { 2523 if (!args->is_empty() && args->last()->IsSpread()) {
2518 RegisterList args_regs = 2524 RegisterList args_regs = register_allocator()->NewGrowableRegisterList();
2519 register_allocator()->NewRegisterList(args->length() + 2); 2525 Register constructor_arg =
2520 builder()->MoveRegister(constructor, args_regs[0]); 2526 register_allocator()->GrowRegisterList(&args_regs);
2521 VisitForRegisterValue(super->new_target_var(), args_regs[1]); 2527 builder()->MoveRegister(constructor, constructor_arg);
2522 VisitArguments(args, args_regs, 2); 2528 VisitAndPushIntoRegisterList(super->new_target_var(), &args_regs);
2529 VisitArguments(args, &args_regs);
2523 builder()->NewWithSpread(args_regs); 2530 builder()->NewWithSpread(args_regs);
2524 } else { 2531 } else {
2525 RegisterList args_regs = 2532 RegisterList args_regs = register_allocator()->NewGrowableRegisterList();
2526 register_allocator()->NewRegisterList(args->length()); 2533 VisitArguments(args, &args_regs);
2527 VisitArguments(args, args_regs);
2528 // The new target is loaded into the accumulator from the 2534 // The new target is loaded into the accumulator from the
2529 // {new.target} variable. 2535 // {new.target} variable.
2530 VisitForAccumulatorValue(super->new_target_var()); 2536 VisitForAccumulatorValue(super->new_target_var());
2531 2537
2532 // Call construct. 2538 // Call construct.
2533 builder()->SetExpressionPosition(expr); 2539 builder()->SetExpressionPosition(expr);
2534 // TODO(turbofan): For now we do gather feedback on super constructor 2540 // TODO(turbofan): For now we do gather feedback on super constructor
2535 // calls, utilizing the existing machinery to inline the actual call 2541 // calls, utilizing the existing machinery to inline the actual call
2536 // target and the JSCreate for the implicit receiver allocation. This 2542 // target and the JSCreate for the implicit receiver allocation. This
2537 // is not an ideal solution for super constructor calls, but it gets 2543 // is not an ideal solution for super constructor calls, but it gets
2538 // the job done for now. In the long run we might want to revisit this 2544 // the job done for now. In the long run we might want to revisit this
2539 // and come up with a better way. 2545 // and come up with a better way.
2540 int const feedback_slot_index = feedback_index(expr->CallFeedbackICSlot()); 2546 int const feedback_slot_index = feedback_index(expr->CallFeedbackICSlot());
2541 builder()->New(constructor, args_regs, feedback_slot_index); 2547 builder()->New(constructor, args_regs, feedback_slot_index);
2542 } 2548 }
2543 } 2549 }
2544 2550
2545 void BytecodeGenerator::VisitCallNew(CallNew* expr) { 2551 void BytecodeGenerator::VisitCallNew(CallNew* expr) {
2546 Register constructor = VisitForRegisterValue(expr->expression()); 2552 Register constructor = VisitForRegisterValue(expr->expression());
2547 RegisterList args = 2553 RegisterList args = register_allocator()->NewGrowableRegisterList();
2548 register_allocator()->NewRegisterList(expr->arguments()->length()); 2554 VisitArguments(expr->arguments(), &args);
2549 VisitArguments(expr->arguments(), args);
2550 2555
2551 builder()->SetExpressionPosition(expr); 2556 builder()->SetExpressionPosition(expr);
2552 // The accumulator holds new target which is the same as the 2557 // The accumulator holds new target which is the same as the
2553 // constructor for CallNew. 2558 // constructor for CallNew.
2554 builder() 2559 builder()
2555 ->LoadAccumulatorWithRegister(constructor) 2560 ->LoadAccumulatorWithRegister(constructor)
2556 .New(constructor, args, feedback_index(expr->CallNewFeedbackSlot())); 2561 .New(constructor, args, feedback_index(expr->CallNewFeedbackSlot()));
2557 } 2562 }
2558 2563
2559 void BytecodeGenerator::VisitCallRuntime(CallRuntime* expr) { 2564 void BytecodeGenerator::VisitCallRuntime(CallRuntime* expr) {
2560 if (expr->is_jsruntime()) { 2565 if (expr->is_jsruntime()) {
2566 RegisterList args = register_allocator()->NewGrowableRegisterList();
2561 // Allocate a register for the receiver and load it with undefined. 2567 // Allocate a register for the receiver and load it with undefined.
2562 RegisterList args = 2568 BuildPushUndefinedIntoRegisterList(&args);
2563 register_allocator()->NewRegisterList(expr->arguments()->length() + 1); 2569 VisitArguments(expr->arguments(), &args);
2564 Register receiver = args[0];
2565 builder()->LoadUndefined().StoreAccumulatorInRegister(receiver);
2566 VisitArguments(expr->arguments(), args, 1);
2567 builder()->CallJSRuntime(expr->context_index(), args); 2570 builder()->CallJSRuntime(expr->context_index(), args);
2568 } else { 2571 } else {
2569 // Evaluate all arguments to the runtime call. 2572 // Evaluate all arguments to the runtime call.
2570 RegisterList args = 2573 RegisterList args = register_allocator()->NewGrowableRegisterList();
2571 register_allocator()->NewRegisterList(expr->arguments()->length()); 2574 VisitArguments(expr->arguments(), &args);
2572 VisitArguments(expr->arguments(), args);
2573 Runtime::FunctionId function_id = expr->function()->function_id; 2575 Runtime::FunctionId function_id = expr->function()->function_id;
2574 builder()->CallRuntime(function_id, args); 2576 builder()->CallRuntime(function_id, args);
2575 } 2577 }
2576 } 2578 }
2577 2579
2578 void BytecodeGenerator::VisitVoid(UnaryOperation* expr) { 2580 void BytecodeGenerator::VisitVoid(UnaryOperation* expr) {
2579 VisitForEffect(expr->expression()); 2581 VisitForEffect(expr->expression());
2580 builder()->LoadUndefined(); 2582 builder()->LoadUndefined();
2581 } 2583 }
2582 2584
(...skipping 619 matching lines...) Expand 10 before | Expand all | Expand 10 after
3202 3204
3203 // Visits the expression |expr| and stores the expression result in 3205 // Visits the expression |expr| and stores the expression result in
3204 // |destination|. 3206 // |destination|.
3205 void BytecodeGenerator::VisitForRegisterValue(Expression* expr, 3207 void BytecodeGenerator::VisitForRegisterValue(Expression* expr,
3206 Register destination) { 3208 Register destination) {
3207 ValueResultScope register_scope(this); 3209 ValueResultScope register_scope(this);
3208 Visit(expr); 3210 Visit(expr);
3209 builder()->StoreAccumulatorInRegister(destination); 3211 builder()->StoreAccumulatorInRegister(destination);
3210 } 3212 }
3211 3213
3214 // Visits the expression |expr| and pushes the result into a new register
3215 // added to the end of |reg_list|.
3216 void BytecodeGenerator::VisitAndPushIntoRegisterList(Expression* expr,
3217 RegisterList* reg_list) {
3218 {
3219 ValueResultScope register_scope(this);
3220 Visit(expr);
3221 }
3222 Register destination = register_allocator()->GrowRegisterList(reg_list);
mythria 2016/12/12 11:16:43 May be a comment here saying we have to GrowRegist
rmcilroy 2016/12/15 10:18:02 Done.
3223 builder()->StoreAccumulatorInRegister(destination);
3224 }
3225
3226 void BytecodeGenerator::BuildPushUndefinedIntoRegisterList(
3227 RegisterList* reg_list) {
3228 Register reg = register_allocator()->GrowRegisterList(reg_list);
3229 builder()->LoadUndefined().StoreAccumulatorInRegister(reg);
3230 }
3231
3212 // Visits the expression |expr| for testing its boolean value and jumping to the 3232 // Visits the expression |expr| for testing its boolean value and jumping to the
3213 // |then| or |other| label depending on value and short-circuit semantics 3233 // |then| or |other| label depending on value and short-circuit semantics
3214 void BytecodeGenerator::VisitForTest(Expression* expr, 3234 void BytecodeGenerator::VisitForTest(Expression* expr,
3215 BytecodeLabels* then_labels, 3235 BytecodeLabels* then_labels,
3216 BytecodeLabels* else_labels, 3236 BytecodeLabels* else_labels,
3217 TestFallthrough fallthrough) { 3237 TestFallthrough fallthrough) {
3218 bool result_consumed; 3238 bool result_consumed;
3219 { 3239 {
3220 // To make sure that all temporary registers are returned before generating 3240 // To make sure that all temporary registers are returned before generating
3221 // jumps below, we ensure that the result scope is deleted before doing so. 3241 // jumps below, we ensure that the result scope is deleted before doing so.
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
3259 } 3279 }
3260 3280
3261 Runtime::FunctionId BytecodeGenerator::StoreKeyedToSuperRuntimeId() { 3281 Runtime::FunctionId BytecodeGenerator::StoreKeyedToSuperRuntimeId() {
3262 return is_strict(language_mode()) ? Runtime::kStoreKeyedToSuper_Strict 3282 return is_strict(language_mode()) ? Runtime::kStoreKeyedToSuper_Strict
3263 : Runtime::kStoreKeyedToSuper_Sloppy; 3283 : Runtime::kStoreKeyedToSuper_Sloppy;
3264 } 3284 }
3265 3285
3266 } // namespace interpreter 3286 } // namespace interpreter
3267 } // namespace internal 3287 } // namespace internal
3268 } // namespace v8 3288 } // namespace v8
OLDNEW
« no previous file with comments | « src/interpreter/bytecode-generator.h ('k') | src/interpreter/bytecode-register.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698