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/compiler.h" | 7 #include "src/compiler.h" |
8 #include "src/compiler/ast-loop-assignment-analyzer.h" | 8 #include "src/compiler/ast-loop-assignment-analyzer.h" |
9 #include "src/compiler/control-builders.h" | 9 #include "src/compiler/control-builders.h" |
10 #include "src/compiler/linkage.h" | 10 #include "src/compiler/linkage.h" |
(...skipping 433 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
444 // Initialize the incoming context. | 444 // Initialize the incoming context. |
445 function_context_ = NewOuterContextParam(); | 445 function_context_ = NewOuterContextParam(); |
446 ContextScope incoming(this, scope, function_context_); | 446 ContextScope incoming(this, scope, function_context_); |
447 | 447 |
448 // Build receiver check for sloppy mode if necessary. | 448 // Build receiver check for sloppy mode if necessary. |
449 // TODO(mstarzinger/verwaest): Should this be moved back into the CallIC? | 449 // TODO(mstarzinger/verwaest): Should this be moved back into the CallIC? |
450 Node* original_receiver = env.Lookup(scope->receiver()); | 450 Node* original_receiver = env.Lookup(scope->receiver()); |
451 Node* patched_receiver = BuildPatchReceiverToGlobalProxy(original_receiver); | 451 Node* patched_receiver = BuildPatchReceiverToGlobalProxy(original_receiver); |
452 env.Bind(scope->receiver(), patched_receiver); | 452 env.Bind(scope->receiver(), patched_receiver); |
453 | 453 |
454 bool ok; | 454 // Build function context only if there are context allocated variables. |
455 int heap_slots = info()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; | 455 int heap_slots = info()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; |
456 if (heap_slots > 0) { | 456 if (heap_slots > 0) { |
457 // Push a new inner context scope for the function. | 457 // Push a new inner context scope for the function. |
458 Node* closure = GetFunctionClosure(); | 458 Node* closure = GetFunctionClosure(); |
459 Node* inner_context = BuildLocalFunctionContext(function_context_, closure); | 459 Node* inner_context = BuildLocalFunctionContext(function_context_, closure); |
460 ContextScope top_context(this, scope, inner_context); | 460 ContextScope top_context(this, scope, inner_context); |
461 ok = CreateGraphBody(); | 461 CreateGraphBody(); |
462 } else { | 462 } else { |
463 // Simply use the outer function context in building the graph. | 463 // Simply use the outer function context in building the graph. |
464 ok = CreateGraphBody(); | 464 CreateGraphBody(); |
465 } | 465 } |
466 | 466 |
467 // Finish the basic structure of the graph. | 467 // Finish the basic structure of the graph. |
468 if (ok) { | 468 graph()->SetEnd(graph()->NewNode(common()->End(), exit_control())); |
469 environment()->UpdateControlDependency(exit_control()); | |
470 graph()->SetEnd(NewNode(common()->End())); | |
471 } | |
472 | 469 |
473 return ok; | 470 // Failures indicated by stack overflow. |
| 471 return !HasStackOverflow(); |
474 } | 472 } |
475 | 473 |
476 | 474 |
477 bool AstGraphBuilder::CreateGraphBody() { | 475 void AstGraphBuilder::CreateGraphBody() { |
478 Scope* scope = info()->scope(); | 476 Scope* scope = info()->scope(); |
| 477 |
479 // Build the arguments object if it is used. | 478 // Build the arguments object if it is used. |
480 BuildArgumentsObject(scope->arguments()); | 479 BuildArgumentsObject(scope->arguments()); |
481 | 480 |
482 // Build rest arguments array if it is used. | 481 // Build rest arguments array if it is used. |
483 int rest_index; | 482 int rest_index; |
484 Variable* rest_parameter = scope->rest_parameter(&rest_index); | 483 Variable* rest_parameter = scope->rest_parameter(&rest_index); |
485 BuildRestArgumentsArray(rest_parameter, rest_index); | 484 BuildRestArgumentsArray(rest_parameter, rest_index); |
486 | 485 |
487 // Emit tracing call if requested to do so. | 486 // Emit tracing call if requested to do so. |
488 if (FLAG_trace) { | 487 if (FLAG_trace) { |
489 NewNode(javascript()->CallRuntime(Runtime::kTraceEnter, 0)); | 488 NewNode(javascript()->CallRuntime(Runtime::kTraceEnter, 0)); |
490 } | 489 } |
491 | 490 |
492 // Visit implicit declaration of the function name. | 491 // Visit implicit declaration of the function name. |
493 if (scope->is_function_scope() && scope->function() != NULL) { | 492 if (scope->is_function_scope() && scope->function() != NULL) { |
494 VisitVariableDeclaration(scope->function()); | 493 VisitVariableDeclaration(scope->function()); |
495 } | 494 } |
496 | 495 |
497 // Visit declarations within the function scope. | 496 // Visit declarations within the function scope. |
498 VisitDeclarations(scope->declarations()); | 497 VisitDeclarations(scope->declarations()); |
499 | 498 |
500 // Build a stack-check before the body. | 499 // Build a stack-check before the body. |
501 Node* node = BuildStackCheck(); | 500 Node* node = BuildStackCheck(); |
502 PrepareFrameState(node, BailoutId::FunctionEntry()); | 501 PrepareFrameState(node, BailoutId::FunctionEntry()); |
503 | 502 |
504 // Visit statements in the function body. | 503 // Visit statements in the function body. |
505 VisitStatements(info()->function()->body()); | 504 VisitStatements(info()->function()->body()); |
506 if (HasStackOverflow()) return false; | |
507 | 505 |
508 // Emit tracing call if requested to do so. | 506 // Emit tracing call if requested to do so. |
509 if (FLAG_trace) { | 507 if (FLAG_trace) { |
510 // TODO(mstarzinger): Only traces implicit return. | 508 // TODO(mstarzinger): Only traces implicit return. |
511 Node* return_value = jsgraph()->UndefinedConstant(); | 509 Node* return_value = jsgraph()->UndefinedConstant(); |
512 NewNode(javascript()->CallRuntime(Runtime::kTraceExit, 1), return_value); | 510 NewNode(javascript()->CallRuntime(Runtime::kTraceExit, 1), return_value); |
513 } | 511 } |
514 | 512 |
515 // Return 'undefined' in case we can fall off the end. | 513 // Return 'undefined' in case we can fall off the end. |
516 BuildReturn(jsgraph()->UndefinedConstant()); | 514 BuildReturn(jsgraph()->UndefinedConstant()); |
517 | |
518 return true; | |
519 } | 515 } |
520 | 516 |
521 | 517 |
522 // Left-hand side can only be a property, a global or a variable slot. | 518 // Left-hand side can only be a property, a global or a variable slot. |
523 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; | 519 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY }; |
524 | 520 |
525 | 521 |
526 // Determine the left-hand side kind of an assignment. | 522 // Determine the left-hand side kind of an assignment. |
527 static LhsKind DetermineLhsKind(Expression* expr) { | 523 static LhsKind DetermineLhsKind(Expression* expr) { |
528 Property* property = expr->AsProperty(); | 524 Property* property = expr->AsProperty(); |
(...skipping 2678 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3207 // Phi does not exist yet, introduce one. | 3203 // Phi does not exist yet, introduce one. |
3208 value = NewPhi(inputs, value, control); | 3204 value = NewPhi(inputs, value, control); |
3209 value->ReplaceInput(inputs - 1, other); | 3205 value->ReplaceInput(inputs - 1, other); |
3210 } | 3206 } |
3211 return value; | 3207 return value; |
3212 } | 3208 } |
3213 | 3209 |
3214 } // namespace compiler | 3210 } // namespace compiler |
3215 } // namespace internal | 3211 } // namespace internal |
3216 } // namespace v8 | 3212 } // namespace v8 |
OLD | NEW |