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

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

Issue 2578183002: Merged: [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 2275 matching lines...) Expand 10 before | Expand all | Expand 10 after
2286 } 2286 }
2287 case NAMED_SUPER_PROPERTY: 2287 case NAMED_SUPER_PROPERTY:
2288 VisitNamedSuperPropertyLoad(expr, Register::invalid_value()); 2288 VisitNamedSuperPropertyLoad(expr, Register::invalid_value());
2289 break; 2289 break;
2290 case KEYED_SUPER_PROPERTY: 2290 case KEYED_SUPER_PROPERTY:
2291 VisitKeyedSuperPropertyLoad(expr, Register::invalid_value()); 2291 VisitKeyedSuperPropertyLoad(expr, Register::invalid_value());
2292 break; 2292 break;
2293 } 2293 }
2294 } 2294 }
2295 2295
2296 void BytecodeGenerator::VisitPropertyLoadForAccumulator(Register obj, 2296 void BytecodeGenerator::VisitPropertyLoadForRegister(Register obj,
2297 Property* expr) { 2297 Property* expr,
2298 Register destination) {
2298 ValueResultScope result_scope(this); 2299 ValueResultScope result_scope(this);
2299 VisitPropertyLoad(obj, expr); 2300 VisitPropertyLoad(obj, expr);
2301 builder()->StoreAccumulatorInRegister(destination);
2300 } 2302 }
2301 2303
2302 void BytecodeGenerator::VisitNamedSuperPropertyLoad(Property* property, 2304 void BytecodeGenerator::VisitNamedSuperPropertyLoad(Property* property,
2303 Register opt_receiver_out) { 2305 Register opt_receiver_out) {
2304 RegisterAllocationScope register_scope(this); 2306 RegisterAllocationScope register_scope(this);
2305 SuperPropertyReference* super_property = 2307 SuperPropertyReference* super_property =
2306 property->obj()->AsSuperPropertyReference(); 2308 property->obj()->AsSuperPropertyReference();
2307 RegisterList args = register_allocator()->NewRegisterList(3); 2309 RegisterList args = register_allocator()->NewRegisterList(3);
2308 VisitForRegisterValue(super_property->this_var(), args[0]); 2310 VisitForRegisterValue(super_property->this_var(), args[0]);
2309 VisitForRegisterValue(super_property->home_object(), args[1]); 2311 VisitForRegisterValue(super_property->home_object(), args[1]);
(...skipping 28 matching lines...) Expand all
2338 if (property_kind != NAMED_SUPER_PROPERTY && 2340 if (property_kind != NAMED_SUPER_PROPERTY &&
2339 property_kind != KEYED_SUPER_PROPERTY) { 2341 property_kind != KEYED_SUPER_PROPERTY) {
2340 Register obj = VisitForRegisterValue(expr->obj()); 2342 Register obj = VisitForRegisterValue(expr->obj());
2341 VisitPropertyLoad(obj, expr); 2343 VisitPropertyLoad(obj, expr);
2342 } else { 2344 } else {
2343 VisitPropertyLoad(Register::invalid_value(), expr); 2345 VisitPropertyLoad(Register::invalid_value(), expr);
2344 } 2346 }
2345 } 2347 }
2346 2348
2347 void BytecodeGenerator::VisitArguments(ZoneList<Expression*>* args, 2349 void BytecodeGenerator::VisitArguments(ZoneList<Expression*>* args,
2348 RegisterList arg_regs, 2350 RegisterList* arg_regs) {
2349 size_t first_argument_register) {
2350 // Visit arguments. 2351 // Visit arguments.
2351 for (int i = 0; i < static_cast<int>(args->length()); i++) { 2352 for (int i = 0; i < static_cast<int>(args->length()); i++) {
2352 VisitForRegisterValue(args->at(i), arg_regs[first_argument_register + i]); 2353 VisitAndPushIntoRegisterList(args->at(i), arg_regs);
2353 } 2354 }
2354 } 2355 }
2355 2356
2356 void BytecodeGenerator::VisitCall(Call* expr) { 2357 void BytecodeGenerator::VisitCall(Call* expr) {
2357 Expression* callee_expr = expr->expression(); 2358 Expression* callee_expr = expr->expression();
2358 Call::CallType call_type = expr->GetCallType(); 2359 Call::CallType call_type = expr->GetCallType();
2359 2360
2360 if (call_type == Call::SUPER_CALL) { 2361 if (call_type == Call::SUPER_CALL) {
2361 return VisitCallSuper(expr); 2362 return VisitCallSuper(expr);
2362 } 2363 }
2363 2364
2364 Register callee = register_allocator()->NewRegister(); 2365 Register callee = register_allocator()->NewRegister();
2365 2366 // Grow the args list as we visit receiver / arguments to avoid allocating all
2366 // Add an argument register for the receiver. 2367 // the registers up-front. Otherwise these registers are unavailable during
2367 RegisterList args = 2368 // receiver / argument visiting and we can end up with memory leaks due to
2368 register_allocator()->NewRegisterList(expr->arguments()->length() + 1); 2369 // registers keeping objects alive.
2369 Register receiver = args[0]; 2370 RegisterList args = register_allocator()->NewGrowableRegisterList();
2370 2371
2371 // Prepare the callee and the receiver to the function call. This depends on 2372 // Prepare the callee and the receiver to the function call. This depends on
2372 // the semantics of the underlying call type. 2373 // the semantics of the underlying call type.
2373 switch (call_type) { 2374 switch (call_type) {
2374 case Call::NAMED_PROPERTY_CALL: 2375 case Call::NAMED_PROPERTY_CALL:
2375 case Call::KEYED_PROPERTY_CALL: { 2376 case Call::KEYED_PROPERTY_CALL: {
2376 Property* property = callee_expr->AsProperty(); 2377 Property* property = callee_expr->AsProperty();
2377 VisitForAccumulatorValue(property->obj()); 2378 VisitAndPushIntoRegisterList(property->obj(), &args);
2378 builder()->StoreAccumulatorInRegister(receiver); 2379 VisitPropertyLoadForRegister(args[0], property, callee);
2379 VisitPropertyLoadForAccumulator(receiver, property);
2380 builder()->StoreAccumulatorInRegister(callee);
2381 break; 2380 break;
2382 } 2381 }
2383 case Call::GLOBAL_CALL: { 2382 case Call::GLOBAL_CALL: {
2384 // Receiver is undefined for global calls. 2383 // Receiver is undefined for global calls.
2385 builder()->LoadUndefined().StoreAccumulatorInRegister(receiver); 2384 BuildPushUndefinedIntoRegisterList(&args);
2386 // Load callee as a global variable. 2385 // Load callee as a global variable.
2387 VariableProxy* proxy = callee_expr->AsVariableProxy(); 2386 VariableProxy* proxy = callee_expr->AsVariableProxy();
2388 BuildVariableLoadForAccumulatorValue(proxy->var(), 2387 BuildVariableLoadForAccumulatorValue(proxy->var(),
2389 proxy->VariableFeedbackSlot(), 2388 proxy->VariableFeedbackSlot(),
2390 proxy->hole_check_mode()); 2389 proxy->hole_check_mode());
2391 builder()->StoreAccumulatorInRegister(callee); 2390 builder()->StoreAccumulatorInRegister(callee);
2392 break; 2391 break;
2393 } 2392 }
2394 case Call::WITH_CALL: { 2393 case Call::WITH_CALL: {
2394 Register receiver = register_allocator()->GrowRegisterList(&args);
2395 DCHECK(callee_expr->AsVariableProxy()->var()->IsLookupSlot()); 2395 DCHECK(callee_expr->AsVariableProxy()->var()->IsLookupSlot());
2396 RegisterAllocationScope inner_register_scope(this); 2396 {
2397 Register name = register_allocator()->NewRegister(); 2397 RegisterAllocationScope inner_register_scope(this);
2398 Register name = register_allocator()->NewRegister();
2398 2399
2399 // Call %LoadLookupSlotForCall to get the callee and receiver. 2400 // Call %LoadLookupSlotForCall to get the callee and receiver.
2400 DCHECK(Register::AreContiguous(callee, receiver)); 2401 DCHECK(Register::AreContiguous(callee, receiver));
2401 RegisterList result_pair(callee.index(), 2); 2402 RegisterList result_pair(callee.index(), 2);
2402 Variable* variable = callee_expr->AsVariableProxy()->var(); 2403 USE(receiver);
2403 builder() 2404 Variable* variable = callee_expr->AsVariableProxy()->var();
2404 ->LoadLiteral(variable->name()) 2405 builder()
2405 .StoreAccumulatorInRegister(name) 2406 ->LoadLiteral(variable->name())
2406 .CallRuntimeForPair(Runtime::kLoadLookupSlotForCall, name, 2407 .StoreAccumulatorInRegister(name)
2407 result_pair); 2408 .CallRuntimeForPair(Runtime::kLoadLookupSlotForCall, name,
2409 result_pair);
2410 }
2408 break; 2411 break;
2409 } 2412 }
2410 case Call::OTHER_CALL: 2413 case Call::OTHER_CALL: {
2411 builder()->LoadUndefined().StoreAccumulatorInRegister(receiver); 2414 BuildPushUndefinedIntoRegisterList(&args);
2412 VisitForRegisterValue(callee_expr, callee); 2415 VisitForRegisterValue(callee_expr, callee);
2413 break; 2416 break;
2417 }
2414 case Call::NAMED_SUPER_PROPERTY_CALL: { 2418 case Call::NAMED_SUPER_PROPERTY_CALL: {
2419 Register receiver = register_allocator()->GrowRegisterList(&args);
2415 Property* property = callee_expr->AsProperty(); 2420 Property* property = callee_expr->AsProperty();
2416 VisitNamedSuperPropertyLoad(property, receiver); 2421 VisitNamedSuperPropertyLoad(property, receiver);
2417 builder()->StoreAccumulatorInRegister(callee); 2422 builder()->StoreAccumulatorInRegister(callee);
2418 break; 2423 break;
2419 } 2424 }
2420 case Call::KEYED_SUPER_PROPERTY_CALL: { 2425 case Call::KEYED_SUPER_PROPERTY_CALL: {
2426 Register receiver = register_allocator()->GrowRegisterList(&args);
2421 Property* property = callee_expr->AsProperty(); 2427 Property* property = callee_expr->AsProperty();
2422 VisitKeyedSuperPropertyLoad(property, receiver); 2428 VisitKeyedSuperPropertyLoad(property, receiver);
2423 builder()->StoreAccumulatorInRegister(callee); 2429 builder()->StoreAccumulatorInRegister(callee);
2424 break; 2430 break;
2425 } 2431 }
2426 case Call::SUPER_CALL: 2432 case Call::SUPER_CALL:
2427 UNREACHABLE(); 2433 UNREACHABLE();
2428 break; 2434 break;
2429 } 2435 }
2430 2436
2431 // Evaluate all arguments to the function call and store in sequential args 2437 // Evaluate all arguments to the function call and store in sequential args
2432 // registers. 2438 // registers.
2433 VisitArguments(expr->arguments(), args, 1); 2439 VisitArguments(expr->arguments(), &args);
2440 CHECK_EQ(expr->arguments()->length() + 1, args.register_count());
2434 2441
2435 // Resolve callee for a potential direct eval call. This block will mutate the 2442 // Resolve callee for a potential direct eval call. This block will mutate the
2436 // callee value. 2443 // callee value.
2437 if (expr->is_possibly_eval() && expr->arguments()->length() > 0) { 2444 if (expr->is_possibly_eval() && expr->arguments()->length() > 0) {
2438 RegisterAllocationScope inner_register_scope(this); 2445 RegisterAllocationScope inner_register_scope(this);
2439 // Set up arguments for ResolvePossiblyDirectEval by copying callee, source 2446 // Set up arguments for ResolvePossiblyDirectEval by copying callee, source
2440 // strings and function closure, and loading language and 2447 // strings and function closure, and loading language and
2441 // position. 2448 // position.
2442 RegisterList runtime_call_args = register_allocator()->NewRegisterList(6); 2449 RegisterList runtime_call_args = register_allocator()->NewRegisterList(6);
2443 builder() 2450 builder()
(...skipping 25 matching lines...) Expand all
2469 RegisterAllocationScope register_scope(this); 2476 RegisterAllocationScope register_scope(this);
2470 SuperCallReference* super = expr->expression()->AsSuperCallReference(); 2477 SuperCallReference* super = expr->expression()->AsSuperCallReference();
2471 2478
2472 // Prepare the constructor to the super call. 2479 // Prepare the constructor to the super call.
2473 Register this_function = VisitForRegisterValue(super->this_function_var()); 2480 Register this_function = VisitForRegisterValue(super->this_function_var());
2474 builder()->CallRuntime(Runtime::kInlineGetSuperConstructor, this_function); 2481 builder()->CallRuntime(Runtime::kInlineGetSuperConstructor, this_function);
2475 2482
2476 Register constructor = this_function; // Re-use dead this_function register. 2483 Register constructor = this_function; // Re-use dead this_function register.
2477 builder()->StoreAccumulatorInRegister(constructor); 2484 builder()->StoreAccumulatorInRegister(constructor);
2478 2485
2479 RegisterList args = 2486 RegisterList args = register_allocator()->NewGrowableRegisterList();
2480 register_allocator()->NewRegisterList(expr->arguments()->length()); 2487 VisitArguments(expr->arguments(), &args);
2481 VisitArguments(expr->arguments(), args);
2482 2488
2483 // The new target is loaded into the accumulator from the 2489 // The new target is loaded into the accumulator from the
2484 // {new.target} variable. 2490 // {new.target} variable.
2485 VisitForAccumulatorValue(super->new_target_var()); 2491 VisitForAccumulatorValue(super->new_target_var());
2486 2492
2487 // Call construct. 2493 // Call construct.
2488 builder()->SetExpressionPosition(expr); 2494 builder()->SetExpressionPosition(expr);
2489 // TODO(turbofan): For now we do gather feedback on super constructor 2495 // TODO(turbofan): For now we do gather feedback on super constructor
2490 // calls, utilizing the existing machinery to inline the actual call 2496 // calls, utilizing the existing machinery to inline the actual call
2491 // target and the JSCreate for the implicit receiver allocation. This 2497 // target and the JSCreate for the implicit receiver allocation. This
2492 // is not an ideal solution for super constructor calls, but it gets 2498 // is not an ideal solution for super constructor calls, but it gets
2493 // the job done for now. In the long run we might want to revisit this 2499 // the job done for now. In the long run we might want to revisit this
2494 // and come up with a better way. 2500 // and come up with a better way.
2495 int const feedback_slot_index = feedback_index(expr->CallFeedbackICSlot()); 2501 int const feedback_slot_index = feedback_index(expr->CallFeedbackICSlot());
2496 builder()->New(constructor, args, feedback_slot_index); 2502 builder()->New(constructor, args, feedback_slot_index);
2497 } 2503 }
2498 2504
2499 void BytecodeGenerator::VisitCallNew(CallNew* expr) { 2505 void BytecodeGenerator::VisitCallNew(CallNew* expr) {
2500 Register constructor = VisitForRegisterValue(expr->expression()); 2506 Register constructor = VisitForRegisterValue(expr->expression());
2501 RegisterList args = 2507 RegisterList args = register_allocator()->NewGrowableRegisterList();
2502 register_allocator()->NewRegisterList(expr->arguments()->length()); 2508 VisitArguments(expr->arguments(), &args);
2503 VisitArguments(expr->arguments(), args);
2504 2509
2505 builder()->SetExpressionPosition(expr); 2510 builder()->SetExpressionPosition(expr);
2506 // The accumulator holds new target which is the same as the 2511 // The accumulator holds new target which is the same as the
2507 // constructor for CallNew. 2512 // constructor for CallNew.
2508 builder() 2513 builder()
2509 ->LoadAccumulatorWithRegister(constructor) 2514 ->LoadAccumulatorWithRegister(constructor)
2510 .New(constructor, args, feedback_index(expr->CallNewFeedbackSlot())); 2515 .New(constructor, args, feedback_index(expr->CallNewFeedbackSlot()));
2511 } 2516 }
2512 2517
2513 void BytecodeGenerator::VisitCallRuntime(CallRuntime* expr) { 2518 void BytecodeGenerator::VisitCallRuntime(CallRuntime* expr) {
2514 if (expr->is_jsruntime()) { 2519 if (expr->is_jsruntime()) {
2520 RegisterList args = register_allocator()->NewGrowableRegisterList();
2515 // Allocate a register for the receiver and load it with undefined. 2521 // Allocate a register for the receiver and load it with undefined.
2516 RegisterList args = 2522 BuildPushUndefinedIntoRegisterList(&args);
2517 register_allocator()->NewRegisterList(expr->arguments()->length() + 1); 2523 VisitArguments(expr->arguments(), &args);
2518 Register receiver = args[0];
2519 builder()->LoadUndefined().StoreAccumulatorInRegister(receiver);
2520 VisitArguments(expr->arguments(), args, 1);
2521 builder()->CallJSRuntime(expr->context_index(), args); 2524 builder()->CallJSRuntime(expr->context_index(), args);
2522 } else { 2525 } else {
2523 // Evaluate all arguments to the runtime call. 2526 // Evaluate all arguments to the runtime call.
2524 RegisterList args = 2527 RegisterList args = register_allocator()->NewGrowableRegisterList();
2525 register_allocator()->NewRegisterList(expr->arguments()->length()); 2528 VisitArguments(expr->arguments(), &args);
2526 VisitArguments(expr->arguments(), args);
2527 Runtime::FunctionId function_id = expr->function()->function_id; 2529 Runtime::FunctionId function_id = expr->function()->function_id;
2528 builder()->CallRuntime(function_id, args); 2530 builder()->CallRuntime(function_id, args);
2529 } 2531 }
2530 } 2532 }
2531 2533
2532 void BytecodeGenerator::VisitVoid(UnaryOperation* expr) { 2534 void BytecodeGenerator::VisitVoid(UnaryOperation* expr) {
2533 VisitForEffect(expr->expression()); 2535 VisitForEffect(expr->expression());
2534 builder()->LoadUndefined(); 2536 builder()->LoadUndefined();
2535 } 2537 }
2536 2538
(...skipping 592 matching lines...) Expand 10 before | Expand all | Expand 10 after
3129 3131
3130 // Visits the expression |expr| and stores the expression result in 3132 // Visits the expression |expr| and stores the expression result in
3131 // |destination|. 3133 // |destination|.
3132 void BytecodeGenerator::VisitForRegisterValue(Expression* expr, 3134 void BytecodeGenerator::VisitForRegisterValue(Expression* expr,
3133 Register destination) { 3135 Register destination) {
3134 ValueResultScope register_scope(this); 3136 ValueResultScope register_scope(this);
3135 Visit(expr); 3137 Visit(expr);
3136 builder()->StoreAccumulatorInRegister(destination); 3138 builder()->StoreAccumulatorInRegister(destination);
3137 } 3139 }
3138 3140
3141 // Visits the expression |expr| and pushes the result into a new register
3142 // added to the end of |reg_list|.
3143 void BytecodeGenerator::VisitAndPushIntoRegisterList(Expression* expr,
3144 RegisterList* reg_list) {
3145 {
3146 ValueResultScope register_scope(this);
3147 Visit(expr);
3148 }
3149 // Grow the register list after visiting the expression to avoid reserving
3150 // the register across the expression evaluation, which could cause memory
3151 // leaks for deep expressions due to dead objects being kept alive by pointers
3152 // in registers.
3153 Register destination = register_allocator()->GrowRegisterList(reg_list);
3154 builder()->StoreAccumulatorInRegister(destination);
3155 }
3156
3157 void BytecodeGenerator::BuildPushUndefinedIntoRegisterList(
3158 RegisterList* reg_list) {
3159 Register reg = register_allocator()->GrowRegisterList(reg_list);
3160 builder()->LoadUndefined().StoreAccumulatorInRegister(reg);
3161 }
3162
3139 // Visits the expression |expr| for testing its boolean value and jumping to the 3163 // Visits the expression |expr| for testing its boolean value and jumping to the
3140 // |then| or |other| label depending on value and short-circuit semantics 3164 // |then| or |other| label depending on value and short-circuit semantics
3141 void BytecodeGenerator::VisitForTest(Expression* expr, 3165 void BytecodeGenerator::VisitForTest(Expression* expr,
3142 BytecodeLabels* then_labels, 3166 BytecodeLabels* then_labels,
3143 BytecodeLabels* else_labels, 3167 BytecodeLabels* else_labels,
3144 TestFallthrough fallthrough) { 3168 TestFallthrough fallthrough) {
3145 bool result_consumed; 3169 bool result_consumed;
3146 { 3170 {
3147 // To make sure that all temporary registers are returned before generating 3171 // To make sure that all temporary registers are returned before generating
3148 // jumps below, we ensure that the result scope is deleted before doing so. 3172 // 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
3186 } 3210 }
3187 3211
3188 Runtime::FunctionId BytecodeGenerator::StoreKeyedToSuperRuntimeId() { 3212 Runtime::FunctionId BytecodeGenerator::StoreKeyedToSuperRuntimeId() {
3189 return is_strict(language_mode()) ? Runtime::kStoreKeyedToSuper_Strict 3213 return is_strict(language_mode()) ? Runtime::kStoreKeyedToSuper_Strict
3190 : Runtime::kStoreKeyedToSuper_Sloppy; 3214 : Runtime::kStoreKeyedToSuper_Sloppy;
3191 } 3215 }
3192 3216
3193 } // namespace interpreter 3217 } // namespace interpreter
3194 } // namespace internal 3218 } // namespace internal
3195 } // namespace v8 3219 } // 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