OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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/compiler/ast-graph-builder.h" | 5 #include "src/compiler/ast-graph-builder.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/compilation-info.h" | 9 #include "src/compilation-info.h" |
10 #include "src/compiler.h" | 10 #include "src/compiler.h" |
(...skipping 2267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2278 | 2278 |
2279 void AstGraphBuilder::VisitCall(Call* expr) { | 2279 void AstGraphBuilder::VisitCall(Call* expr) { |
2280 Expression* callee = expr->expression(); | 2280 Expression* callee = expr->expression(); |
2281 Call::CallType call_type = expr->GetCallType(); | 2281 Call::CallType call_type = expr->GetCallType(); |
2282 | 2282 |
2283 // Prepare the callee and the receiver to the function call. This depends on | 2283 // Prepare the callee and the receiver to the function call. This depends on |
2284 // the semantics of the underlying call type. | 2284 // the semantics of the underlying call type. |
2285 ConvertReceiverMode receiver_hint = ConvertReceiverMode::kAny; | 2285 ConvertReceiverMode receiver_hint = ConvertReceiverMode::kAny; |
2286 Node* receiver_value = nullptr; | 2286 Node* receiver_value = nullptr; |
2287 Node* callee_value = nullptr; | 2287 Node* callee_value = nullptr; |
2288 bool possibly_eval = false; | 2288 if (expr->is_possibly_eval()) { |
2289 switch (call_type) { | 2289 if (callee->AsVariableProxy()->var()->IsLookupSlot()) { |
2290 case Call::GLOBAL_CALL: { | |
2291 VariableProxy* proxy = callee->AsVariableProxy(); | |
2292 VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot()); | |
2293 PrepareEagerCheckpoint(BeforeId(proxy)); | |
2294 callee_value = BuildVariableLoad(proxy->var(), expr->expression()->id(), | |
2295 pair, OutputFrameStateCombine::Push()); | |
2296 receiver_hint = ConvertReceiverMode::kNullOrUndefined; | |
2297 receiver_value = jsgraph()->UndefinedConstant(); | |
2298 break; | |
2299 } | |
2300 case Call::WITH_CALL: { | |
2301 Variable* variable = callee->AsVariableProxy()->var(); | 2290 Variable* variable = callee->AsVariableProxy()->var(); |
2302 DCHECK(variable->location() == VariableLocation::LOOKUP); | |
2303 Node* name = jsgraph()->Constant(variable->name()); | 2291 Node* name = jsgraph()->Constant(variable->name()); |
2304 const Operator* op = | 2292 const Operator* op = |
2305 javascript()->CallRuntime(Runtime::kLoadLookupSlotForCall); | 2293 javascript()->CallRuntime(Runtime::kLoadLookupSlotForCall); |
2306 Node* pair = NewNode(op, name); | 2294 Node* pair = NewNode(op, name); |
2307 callee_value = NewNode(common()->Projection(0), pair); | 2295 callee_value = NewNode(common()->Projection(0), pair); |
2308 receiver_value = NewNode(common()->Projection(1), pair); | 2296 receiver_value = NewNode(common()->Projection(1), pair); |
2309 PrepareFrameState(pair, expr->LookupId(), | 2297 PrepareFrameState(pair, expr->LookupId(), |
2310 OutputFrameStateCombine::Push(2)); | 2298 OutputFrameStateCombine::Push(2)); |
2311 break; | 2299 } else { |
| 2300 VisitForValue(callee); |
| 2301 callee_value = environment()->Pop(); |
| 2302 receiver_hint = ConvertReceiverMode::kNullOrUndefined; |
| 2303 receiver_value = jsgraph()->UndefinedConstant(); |
2312 } | 2304 } |
2313 case Call::NAMED_PROPERTY_CALL: { | 2305 } else { |
2314 Property* property = callee->AsProperty(); | 2306 switch (call_type) { |
2315 VectorSlotPair feedback = | 2307 case Call::GLOBAL_CALL: { |
2316 CreateVectorSlotPair(property->PropertyFeedbackSlot()); | 2308 VariableProxy* proxy = callee->AsVariableProxy(); |
2317 VisitForValue(property->obj()); | 2309 VectorSlotPair pair = |
2318 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName(); | 2310 CreateVectorSlotPair(proxy->VariableFeedbackSlot()); |
2319 Node* object = environment()->Top(); | 2311 PrepareEagerCheckpoint(BeforeId(proxy)); |
2320 callee_value = BuildNamedLoad(object, name, feedback); | 2312 callee_value = BuildVariableLoad(proxy->var(), expr->expression()->id(), |
2321 PrepareFrameState(callee_value, property->LoadId(), | 2313 pair, OutputFrameStateCombine::Push()); |
2322 OutputFrameStateCombine::Push()); | 2314 receiver_hint = ConvertReceiverMode::kNullOrUndefined; |
2323 // Note that a property call requires the receiver to be wrapped into | 2315 receiver_value = jsgraph()->UndefinedConstant(); |
2324 // an object for sloppy callees. However the receiver is guaranteed | 2316 break; |
2325 // not to be null or undefined at this point. | 2317 } |
2326 receiver_hint = ConvertReceiverMode::kNotNullOrUndefined; | 2318 case Call::WITH_CALL: { |
2327 receiver_value = environment()->Pop(); | |
2328 break; | |
2329 } | |
2330 case Call::KEYED_PROPERTY_CALL: { | |
2331 Property* property = callee->AsProperty(); | |
2332 VectorSlotPair feedback = | |
2333 CreateVectorSlotPair(property->PropertyFeedbackSlot()); | |
2334 VisitForValue(property->obj()); | |
2335 VisitForValue(property->key()); | |
2336 Node* key = environment()->Pop(); | |
2337 Node* object = environment()->Top(); | |
2338 callee_value = BuildKeyedLoad(object, key, feedback); | |
2339 PrepareFrameState(callee_value, property->LoadId(), | |
2340 OutputFrameStateCombine::Push()); | |
2341 // Note that a property call requires the receiver to be wrapped into | |
2342 // an object for sloppy callees. However the receiver is guaranteed | |
2343 // not to be null or undefined at this point. | |
2344 receiver_hint = ConvertReceiverMode::kNotNullOrUndefined; | |
2345 receiver_value = environment()->Pop(); | |
2346 break; | |
2347 } | |
2348 case Call::NAMED_SUPER_PROPERTY_CALL: { | |
2349 Property* property = callee->AsProperty(); | |
2350 SuperPropertyReference* super_ref = | |
2351 property->obj()->AsSuperPropertyReference(); | |
2352 VisitForValue(super_ref->home_object()); | |
2353 VisitForValue(super_ref->this_var()); | |
2354 Node* home = environment()->Peek(1); | |
2355 Node* object = environment()->Top(); | |
2356 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName(); | |
2357 callee_value = BuildNamedSuperLoad(object, home, name, VectorSlotPair()); | |
2358 PrepareFrameState(callee_value, property->LoadId(), | |
2359 OutputFrameStateCombine::Push()); | |
2360 // Note that a property call requires the receiver to be wrapped into | |
2361 // an object for sloppy callees. Since the receiver is not the target of | |
2362 // the load, it could very well be null or undefined at this point. | |
2363 receiver_value = environment()->Pop(); | |
2364 environment()->Drop(1); | |
2365 break; | |
2366 } | |
2367 case Call::KEYED_SUPER_PROPERTY_CALL: { | |
2368 Property* property = callee->AsProperty(); | |
2369 SuperPropertyReference* super_ref = | |
2370 property->obj()->AsSuperPropertyReference(); | |
2371 VisitForValue(super_ref->home_object()); | |
2372 VisitForValue(super_ref->this_var()); | |
2373 environment()->Push(environment()->Top()); // Duplicate this_var. | |
2374 environment()->Push(environment()->Peek(2)); // Duplicate home_obj. | |
2375 VisitForValue(property->key()); | |
2376 Node* key = environment()->Pop(); | |
2377 Node* home = environment()->Pop(); | |
2378 Node* object = environment()->Pop(); | |
2379 callee_value = BuildKeyedSuperLoad(object, home, key, VectorSlotPair()); | |
2380 PrepareFrameState(callee_value, property->LoadId(), | |
2381 OutputFrameStateCombine::Push()); | |
2382 // Note that a property call requires the receiver to be wrapped into | |
2383 // an object for sloppy callees. Since the receiver is not the target of | |
2384 // the load, it could very well be null or undefined at this point. | |
2385 receiver_value = environment()->Pop(); | |
2386 environment()->Drop(1); | |
2387 break; | |
2388 } | |
2389 case Call::SUPER_CALL: | |
2390 return VisitCallSuper(expr); | |
2391 case Call::POSSIBLY_EVAL_CALL: | |
2392 possibly_eval = true; | |
2393 if (callee->AsVariableProxy()->var()->IsLookupSlot()) { | |
2394 Variable* variable = callee->AsVariableProxy()->var(); | 2319 Variable* variable = callee->AsVariableProxy()->var(); |
2395 Node* name = jsgraph()->Constant(variable->name()); | 2320 Node* name = jsgraph()->Constant(variable->name()); |
2396 const Operator* op = | 2321 const Operator* op = |
2397 javascript()->CallRuntime(Runtime::kLoadLookupSlotForCall); | 2322 javascript()->CallRuntime(Runtime::kLoadLookupSlotForCall); |
2398 Node* pair = NewNode(op, name); | 2323 Node* pair = NewNode(op, name); |
2399 callee_value = NewNode(common()->Projection(0), pair); | 2324 callee_value = NewNode(common()->Projection(0), pair); |
2400 receiver_value = NewNode(common()->Projection(1), pair); | 2325 receiver_value = NewNode(common()->Projection(1), pair); |
2401 PrepareFrameState(pair, expr->LookupId(), | 2326 PrepareFrameState(pair, expr->LookupId(), |
2402 OutputFrameStateCombine::Push(2)); | 2327 OutputFrameStateCombine::Push(2)); |
| 2328 } |
| 2329 case Call::NAMED_PROPERTY_CALL: { |
| 2330 Property* property = callee->AsProperty(); |
| 2331 VectorSlotPair feedback = |
| 2332 CreateVectorSlotPair(property->PropertyFeedbackSlot()); |
| 2333 VisitForValue(property->obj()); |
| 2334 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName(); |
| 2335 Node* object = environment()->Top(); |
| 2336 callee_value = BuildNamedLoad(object, name, feedback); |
| 2337 PrepareFrameState(callee_value, property->LoadId(), |
| 2338 OutputFrameStateCombine::Push()); |
| 2339 // Note that a property call requires the receiver to be wrapped into |
| 2340 // an object for sloppy callees. However the receiver is guaranteed |
| 2341 // not to be null or undefined at this point. |
| 2342 receiver_hint = ConvertReceiverMode::kNotNullOrUndefined; |
| 2343 receiver_value = environment()->Pop(); |
2403 break; | 2344 break; |
2404 } | 2345 } |
2405 // Fall through. | 2346 case Call::KEYED_PROPERTY_CALL: { |
2406 case Call::OTHER_CALL: | 2347 Property* property = callee->AsProperty(); |
2407 VisitForValue(callee); | 2348 VectorSlotPair feedback = |
2408 callee_value = environment()->Pop(); | 2349 CreateVectorSlotPair(property->PropertyFeedbackSlot()); |
2409 receiver_hint = ConvertReceiverMode::kNullOrUndefined; | 2350 VisitForValue(property->obj()); |
2410 receiver_value = jsgraph()->UndefinedConstant(); | 2351 VisitForValue(property->key()); |
2411 break; | 2352 Node* key = environment()->Pop(); |
| 2353 Node* object = environment()->Top(); |
| 2354 callee_value = BuildKeyedLoad(object, key, feedback); |
| 2355 PrepareFrameState(callee_value, property->LoadId(), |
| 2356 OutputFrameStateCombine::Push()); |
| 2357 // Note that a property call requires the receiver to be wrapped into |
| 2358 // an object for sloppy callees. However the receiver is guaranteed |
| 2359 // not to be null or undefined at this point. |
| 2360 receiver_hint = ConvertReceiverMode::kNotNullOrUndefined; |
| 2361 receiver_value = environment()->Pop(); |
| 2362 break; |
| 2363 } |
| 2364 case Call::NAMED_SUPER_PROPERTY_CALL: { |
| 2365 Property* property = callee->AsProperty(); |
| 2366 SuperPropertyReference* super_ref = |
| 2367 property->obj()->AsSuperPropertyReference(); |
| 2368 VisitForValue(super_ref->home_object()); |
| 2369 VisitForValue(super_ref->this_var()); |
| 2370 Node* home = environment()->Peek(1); |
| 2371 Node* object = environment()->Top(); |
| 2372 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName(); |
| 2373 callee_value = |
| 2374 BuildNamedSuperLoad(object, home, name, VectorSlotPair()); |
| 2375 PrepareFrameState(callee_value, property->LoadId(), |
| 2376 OutputFrameStateCombine::Push()); |
| 2377 // Note that a property call requires the receiver to be wrapped into |
| 2378 // an object for sloppy callees. Since the receiver is not the target of |
| 2379 // the load, it could very well be null or undefined at this point. |
| 2380 receiver_value = environment()->Pop(); |
| 2381 environment()->Drop(1); |
| 2382 break; |
| 2383 } |
| 2384 case Call::KEYED_SUPER_PROPERTY_CALL: { |
| 2385 Property* property = callee->AsProperty(); |
| 2386 SuperPropertyReference* super_ref = |
| 2387 property->obj()->AsSuperPropertyReference(); |
| 2388 VisitForValue(super_ref->home_object()); |
| 2389 VisitForValue(super_ref->this_var()); |
| 2390 environment()->Push(environment()->Top()); // Duplicate this_var. |
| 2391 environment()->Push(environment()->Peek(2)); // Duplicate home_obj. |
| 2392 VisitForValue(property->key()); |
| 2393 Node* key = environment()->Pop(); |
| 2394 Node* home = environment()->Pop(); |
| 2395 Node* object = environment()->Pop(); |
| 2396 callee_value = BuildKeyedSuperLoad(object, home, key, VectorSlotPair()); |
| 2397 PrepareFrameState(callee_value, property->LoadId(), |
| 2398 OutputFrameStateCombine::Push()); |
| 2399 // Note that a property call requires the receiver to be wrapped into |
| 2400 // an object for sloppy callees. Since the receiver is not the target of |
| 2401 // the load, it could very well be null or undefined at this point. |
| 2402 receiver_value = environment()->Pop(); |
| 2403 environment()->Drop(1); |
| 2404 break; |
| 2405 } |
| 2406 case Call::SUPER_CALL: |
| 2407 return VisitCallSuper(expr); |
| 2408 case Call::OTHER_CALL: |
| 2409 VisitForValue(callee); |
| 2410 callee_value = environment()->Pop(); |
| 2411 receiver_hint = ConvertReceiverMode::kNullOrUndefined; |
| 2412 receiver_value = jsgraph()->UndefinedConstant(); |
| 2413 break; |
| 2414 } |
2412 } | 2415 } |
2413 | 2416 |
2414 // The callee and the receiver both have to be pushed onto the operand stack | 2417 // The callee and the receiver both have to be pushed onto the operand stack |
2415 // before arguments are being evaluated. | 2418 // before arguments are being evaluated. |
2416 environment()->Push(callee_value); | 2419 environment()->Push(callee_value); |
2417 environment()->Push(receiver_value); | 2420 environment()->Push(receiver_value); |
2418 | 2421 |
2419 // Evaluate all arguments to the function call, | 2422 // Evaluate all arguments to the function call, |
2420 ZoneList<Expression*>* args = expr->arguments(); | 2423 ZoneList<Expression*>* args = expr->arguments(); |
2421 VisitForValues(args); | 2424 VisitForValues(args); |
2422 | 2425 |
2423 // Resolve callee for a potential direct eval call. This block will mutate the | 2426 // Resolve callee for a potential direct eval call. This block will mutate the |
2424 // callee value pushed onto the environment. | 2427 // callee value pushed onto the environment. |
2425 if (possibly_eval && args->length() > 0) { | 2428 if (expr->is_possibly_eval() && args->length() > 0) { |
2426 int arg_count = args->length(); | 2429 int arg_count = args->length(); |
2427 | 2430 |
2428 // Extract callee and source string from the environment. | 2431 // Extract callee and source string from the environment. |
2429 Node* callee = environment()->Peek(arg_count + 1); | 2432 Node* callee = environment()->Peek(arg_count + 1); |
2430 Node* source = environment()->Peek(arg_count - 1); | 2433 Node* source = environment()->Peek(arg_count - 1); |
2431 | 2434 |
2432 // Create node to ask for help resolving potential eval call. This will | 2435 // Create node to ask for help resolving potential eval call. This will |
2433 // provide a fully resolved callee to patch into the environment. | 2436 // provide a fully resolved callee to patch into the environment. |
2434 Node* function = GetFunctionClosure(); | 2437 Node* function = GetFunctionClosure(); |
2435 Node* language = jsgraph()->Constant(language_mode()); | 2438 Node* language = jsgraph()->Constant(language_mode()); |
(...skipping 10 matching lines...) Expand all Loading... |
2446 // Patch callee on the environment. | 2449 // Patch callee on the environment. |
2447 environment()->Poke(arg_count + 1, new_callee); | 2450 environment()->Poke(arg_count + 1, new_callee); |
2448 } | 2451 } |
2449 | 2452 |
2450 // Create node to perform the function call. | 2453 // Create node to perform the function call. |
2451 float const frequency = ComputeCallFrequency(expr->CallFeedbackICSlot()); | 2454 float const frequency = ComputeCallFrequency(expr->CallFeedbackICSlot()); |
2452 VectorSlotPair feedback = CreateVectorSlotPair(expr->CallFeedbackICSlot()); | 2455 VectorSlotPair feedback = CreateVectorSlotPair(expr->CallFeedbackICSlot()); |
2453 const Operator* call = | 2456 const Operator* call = |
2454 javascript()->CallFunction(args->length() + 2, frequency, feedback, | 2457 javascript()->CallFunction(args->length() + 2, frequency, feedback, |
2455 receiver_hint, expr->tail_call_mode()); | 2458 receiver_hint, expr->tail_call_mode()); |
2456 PrepareEagerCheckpoint(possibly_eval ? expr->EvalId() : expr->CallId()); | 2459 PrepareEagerCheckpoint(expr->is_possibly_eval() ? expr->EvalId() |
| 2460 : expr->CallId()); |
2457 Node* value = ProcessArguments(call, args->length() + 2); | 2461 Node* value = ProcessArguments(call, args->length() + 2); |
2458 // The callee passed to the call, we just need to push something here to | 2462 // The callee passed to the call, we just need to push something here to |
2459 // satisfy the bailout location contract. The fullcodegen code will not | 2463 // satisfy the bailout location contract. The fullcodegen code will not |
2460 // ever look at this value, so we just push optimized_out here. | 2464 // ever look at this value, so we just push optimized_out here. |
2461 environment()->Push(jsgraph()->OptimizedOutConstant()); | 2465 environment()->Push(jsgraph()->OptimizedOutConstant()); |
2462 PrepareFrameState(value, expr->ReturnId(), OutputFrameStateCombine::Push()); | 2466 PrepareFrameState(value, expr->ReturnId(), OutputFrameStateCombine::Push()); |
2463 environment()->Drop(1); | 2467 environment()->Drop(1); |
2464 ast_context()->ProduceValue(expr, value); | 2468 ast_context()->ProduceValue(expr, value); |
2465 } | 2469 } |
2466 | 2470 |
(...skipping 1892 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4359 // Phi does not exist yet, introduce one. | 4363 // Phi does not exist yet, introduce one. |
4360 value = NewPhi(inputs, value, control); | 4364 value = NewPhi(inputs, value, control); |
4361 value->ReplaceInput(inputs - 1, other); | 4365 value->ReplaceInput(inputs - 1, other); |
4362 } | 4366 } |
4363 return value; | 4367 return value; |
4364 } | 4368 } |
4365 | 4369 |
4366 } // namespace compiler | 4370 } // namespace compiler |
4367 } // namespace internal | 4371 } // namespace internal |
4368 } // namespace v8 | 4372 } // namespace v8 |
OLD | NEW |