OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
330 SetOncePointer<HConstant> constant_hole_; | 330 SetOncePointer<HConstant> constant_hole_; |
331 SetOncePointer<HArgumentsObject> arguments_object_; | 331 SetOncePointer<HArgumentsObject> arguments_object_; |
332 | 332 |
333 DISALLOW_COPY_AND_ASSIGN(HGraph); | 333 DISALLOW_COPY_AND_ASSIGN(HGraph); |
334 }; | 334 }; |
335 | 335 |
336 | 336 |
337 Zone* HBasicBlock::zone() { return graph_->zone(); } | 337 Zone* HBasicBlock::zone() { return graph_->zone(); } |
338 | 338 |
339 | 339 |
| 340 // Type of stack frame an environment might refer to. |
| 341 enum FrameType { JS_FUNCTION, JS_CONSTRUCT, ARGUMENTS_ADAPTOR }; |
| 342 |
| 343 |
340 class HEnvironment: public ZoneObject { | 344 class HEnvironment: public ZoneObject { |
341 public: | 345 public: |
342 HEnvironment(HEnvironment* outer, | 346 HEnvironment(HEnvironment* outer, |
343 Scope* scope, | 347 Scope* scope, |
344 Handle<JSFunction> closure); | 348 Handle<JSFunction> closure); |
345 | 349 |
346 bool is_arguments_adaptor() const { | |
347 return arguments_adaptor_; | |
348 } | |
349 | |
350 HEnvironment* DiscardInlined(bool drop_extra) { | 350 HEnvironment* DiscardInlined(bool drop_extra) { |
351 HEnvironment* outer = outer_->is_arguments_adaptor() ? | 351 HEnvironment* outer = outer_; |
352 outer_->outer_ : outer_; | 352 while (outer->frame_type() != JS_FUNCTION) outer = outer->outer_; |
353 if (drop_extra) outer->Drop(1); | 353 if (drop_extra) outer->Drop(1); |
354 return outer; | 354 return outer; |
355 } | 355 } |
356 | 356 |
357 // Simple accessors. | 357 // Simple accessors. |
358 Handle<JSFunction> closure() const { return closure_; } | 358 Handle<JSFunction> closure() const { return closure_; } |
359 const ZoneList<HValue*>* values() const { return &values_; } | 359 const ZoneList<HValue*>* values() const { return &values_; } |
360 const ZoneList<int>* assigned_variables() const { | 360 const ZoneList<int>* assigned_variables() const { |
361 return &assigned_variables_; | 361 return &assigned_variables_; |
362 } | 362 } |
| 363 FrameType frame_type() const { return frame_type_; } |
363 int parameter_count() const { return parameter_count_; } | 364 int parameter_count() const { return parameter_count_; } |
364 int specials_count() const { return specials_count_; } | 365 int specials_count() const { return specials_count_; } |
365 int local_count() const { return local_count_; } | 366 int local_count() const { return local_count_; } |
366 HEnvironment* outer() const { return outer_; } | 367 HEnvironment* outer() const { return outer_; } |
367 int pop_count() const { return pop_count_; } | 368 int pop_count() const { return pop_count_; } |
368 int push_count() const { return push_count_; } | 369 int push_count() const { return push_count_; } |
369 | 370 |
370 int ast_id() const { return ast_id_; } | 371 int ast_id() const { return ast_id_; } |
371 void set_ast_id(int id) { ast_id_ = id; } | 372 void set_ast_id(int id) { ast_id_ = id; } |
372 | 373 |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
434 HEnvironment* CopyWithoutHistory() const; | 435 HEnvironment* CopyWithoutHistory() const; |
435 HEnvironment* CopyAsLoopHeader(HBasicBlock* block) const; | 436 HEnvironment* CopyAsLoopHeader(HBasicBlock* block) const; |
436 | 437 |
437 // Create an "inlined version" of this environment, where the original | 438 // Create an "inlined version" of this environment, where the original |
438 // environment is the outer environment but the top expression stack | 439 // environment is the outer environment but the top expression stack |
439 // elements are moved to an inner environment as parameters. | 440 // elements are moved to an inner environment as parameters. |
440 HEnvironment* CopyForInlining(Handle<JSFunction> target, | 441 HEnvironment* CopyForInlining(Handle<JSFunction> target, |
441 int arguments, | 442 int arguments, |
442 FunctionLiteral* function, | 443 FunctionLiteral* function, |
443 HConstant* undefined, | 444 HConstant* undefined, |
444 CallKind call_kind) const; | 445 CallKind call_kind, |
| 446 bool is_construct) const; |
445 | 447 |
446 void AddIncomingEdge(HBasicBlock* block, HEnvironment* other); | 448 void AddIncomingEdge(HBasicBlock* block, HEnvironment* other); |
447 | 449 |
448 void ClearHistory() { | 450 void ClearHistory() { |
449 pop_count_ = 0; | 451 pop_count_ = 0; |
450 push_count_ = 0; | 452 push_count_ = 0; |
451 assigned_variables_.Rewind(0); | 453 assigned_variables_.Rewind(0); |
452 } | 454 } |
453 | 455 |
454 void SetValueAt(int index, HValue* value) { | 456 void SetValueAt(int index, HValue* value) { |
455 ASSERT(index < length()); | 457 ASSERT(index < length()); |
456 values_[index] = value; | 458 values_[index] = value; |
457 } | 459 } |
458 | 460 |
459 void PrintTo(StringStream* stream); | 461 void PrintTo(StringStream* stream); |
460 void PrintToStd(); | 462 void PrintToStd(); |
461 | 463 |
462 private: | 464 private: |
463 explicit HEnvironment(const HEnvironment* other); | 465 explicit HEnvironment(const HEnvironment* other); |
464 | 466 |
465 // Create an argument adaptor environment. | 467 HEnvironment(HEnvironment* outer, |
466 HEnvironment(HEnvironment* outer, Handle<JSFunction> closure, int arguments); | 468 Handle<JSFunction> closure, |
| 469 FrameType frame_type, |
| 470 int arguments); |
467 | 471 |
| 472 // Create an artificial stub environment (e.g. for argument adaptor or |
| 473 // constructor stub). |
| 474 HEnvironment* CreateStubEnvironment(HEnvironment* outer, |
| 475 Handle<JSFunction> target, |
| 476 FrameType frame_type, |
| 477 int arguments) const; |
468 | 478 |
469 // True if index is included in the expression stack part of the environment. | 479 // True if index is included in the expression stack part of the environment. |
470 bool HasExpressionAt(int index) const; | 480 bool HasExpressionAt(int index) const; |
471 | 481 |
472 void Initialize(int parameter_count, int local_count, int stack_height); | 482 void Initialize(int parameter_count, int local_count, int stack_height); |
473 void Initialize(const HEnvironment* other); | 483 void Initialize(const HEnvironment* other); |
474 | 484 |
475 // Map a variable to an environment index. Parameter indices are shifted | 485 // Map a variable to an environment index. Parameter indices are shifted |
476 // by 1 (receiver is parameter index -1 but environment index 0). | 486 // by 1 (receiver is parameter index -1 but environment index 0). |
477 // Stack-allocated local indices are shifted by the number of parameters. | 487 // Stack-allocated local indices are shifted by the number of parameters. |
478 int IndexFor(Variable* variable) const { | 488 int IndexFor(Variable* variable) const { |
479 ASSERT(variable->IsStackAllocated()); | 489 ASSERT(variable->IsStackAllocated()); |
480 int shift = variable->IsParameter() | 490 int shift = variable->IsParameter() |
481 ? 1 | 491 ? 1 |
482 : parameter_count_ + specials_count_; | 492 : parameter_count_ + specials_count_; |
483 return variable->index() + shift; | 493 return variable->index() + shift; |
484 } | 494 } |
485 | 495 |
486 Handle<JSFunction> closure_; | 496 Handle<JSFunction> closure_; |
487 // Value array [parameters] [specials] [locals] [temporaries]. | 497 // Value array [parameters] [specials] [locals] [temporaries]. |
488 ZoneList<HValue*> values_; | 498 ZoneList<HValue*> values_; |
489 ZoneList<int> assigned_variables_; | 499 ZoneList<int> assigned_variables_; |
| 500 FrameType frame_type_; |
490 int parameter_count_; | 501 int parameter_count_; |
491 int specials_count_; | 502 int specials_count_; |
492 int local_count_; | 503 int local_count_; |
493 HEnvironment* outer_; | 504 HEnvironment* outer_; |
494 int pop_count_; | 505 int pop_count_; |
495 int push_count_; | 506 int push_count_; |
496 int ast_id_; | 507 int ast_id_; |
497 bool arguments_adaptor_; | |
498 }; | 508 }; |
499 | 509 |
500 | 510 |
501 class HGraphBuilder; | 511 class HGraphBuilder; |
502 | 512 |
503 enum ArgumentsAllowedFlag { | 513 enum ArgumentsAllowedFlag { |
504 ARGUMENTS_NOT_ALLOWED, | 514 ARGUMENTS_NOT_ALLOWED, |
505 ARGUMENTS_ALLOWED | 515 ARGUMENTS_ALLOWED |
506 }; | 516 }; |
507 | 517 |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
615 // Build the shared core part of the translation unpacking a value into | 625 // Build the shared core part of the translation unpacking a value into |
616 // control flow. | 626 // control flow. |
617 void BuildBranch(HValue* value); | 627 void BuildBranch(HValue* value); |
618 | 628 |
619 Expression* condition_; | 629 Expression* condition_; |
620 HBasicBlock* if_true_; | 630 HBasicBlock* if_true_; |
621 HBasicBlock* if_false_; | 631 HBasicBlock* if_false_; |
622 }; | 632 }; |
623 | 633 |
624 | 634 |
| 635 enum ReturnHandlingFlag { |
| 636 NORMAL_RETURN, |
| 637 DROP_EXTRA_ON_RETURN, |
| 638 CONSTRUCT_CALL_RETURN |
| 639 }; |
| 640 |
| 641 |
625 class FunctionState { | 642 class FunctionState { |
626 public: | 643 public: |
| 644 |
627 FunctionState(HGraphBuilder* owner, | 645 FunctionState(HGraphBuilder* owner, |
628 CompilationInfo* info, | 646 CompilationInfo* info, |
629 TypeFeedbackOracle* oracle, | 647 TypeFeedbackOracle* oracle, |
630 bool drop_extra); | 648 ReturnHandlingFlag return_handling); |
631 ~FunctionState(); | 649 ~FunctionState(); |
632 | 650 |
633 CompilationInfo* compilation_info() { return compilation_info_; } | 651 CompilationInfo* compilation_info() { return compilation_info_; } |
634 TypeFeedbackOracle* oracle() { return oracle_; } | 652 TypeFeedbackOracle* oracle() { return oracle_; } |
635 AstContext* call_context() { return call_context_; } | 653 AstContext* call_context() { return call_context_; } |
636 bool drop_extra() { return drop_extra_; } | 654 bool drop_extra() { return return_handling_ == DROP_EXTRA_ON_RETURN; } |
| 655 bool is_construct() { return return_handling_ == CONSTRUCT_CALL_RETURN; } |
637 HBasicBlock* function_return() { return function_return_; } | 656 HBasicBlock* function_return() { return function_return_; } |
638 TestContext* test_context() { return test_context_; } | 657 TestContext* test_context() { return test_context_; } |
639 void ClearInlinedTestContext() { | 658 void ClearInlinedTestContext() { |
640 delete test_context_; | 659 delete test_context_; |
641 test_context_ = NULL; | 660 test_context_ = NULL; |
642 } | 661 } |
643 | 662 |
644 FunctionState* outer() { return outer_; } | 663 FunctionState* outer() { return outer_; } |
645 | 664 |
646 private: | 665 private: |
647 HGraphBuilder* owner_; | 666 HGraphBuilder* owner_; |
648 | 667 |
649 CompilationInfo* compilation_info_; | 668 CompilationInfo* compilation_info_; |
650 TypeFeedbackOracle* oracle_; | 669 TypeFeedbackOracle* oracle_; |
651 | 670 |
652 // During function inlining, expression context of the call being | 671 // During function inlining, expression context of the call being |
653 // inlined. NULL when not inlining. | 672 // inlined. NULL when not inlining. |
654 AstContext* call_context_; | 673 AstContext* call_context_; |
655 | 674 |
656 // Indicate if we have to drop an extra value from the environment on | 675 // Indicate whether we have to perform special handling on return from |
657 // return from inlined functions. | 676 // inlined functions. |
658 bool drop_extra_; | 677 // - DROP_EXTRA_ON_RETURN: Drop an extra value from the environment. |
| 678 // - CONSTRUCT_CALL_RETURN: Either use allocated receiver or return value. |
| 679 ReturnHandlingFlag return_handling_; |
659 | 680 |
660 // When inlining in an effect of value context, this is the return block. | 681 // When inlining in an effect or value context, this is the return block. |
661 // It is NULL otherwise. When inlining in a test context, there are a | 682 // It is NULL otherwise. When inlining in a test context, there are a |
662 // pair of return blocks in the context. When not inlining, there is no | 683 // pair of return blocks in the context. When not inlining, there is no |
663 // local return point. | 684 // local return point. |
664 HBasicBlock* function_return_; | 685 HBasicBlock* function_return_; |
665 | 686 |
666 // When inlining a call in a test context, a context containing a pair of | 687 // When inlining a call in a test context, a context containing a pair of |
667 // return blocks. NULL in all other cases. | 688 // return blocks. NULL in all other cases. |
668 TestContext* test_context_; | 689 TestContext* test_context_; |
669 | 690 |
670 FunctionState* outer_; | 691 FunctionState* outer_; |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
782 // Simple accessors. | 803 // Simple accessors. |
783 void set_function_state(FunctionState* state) { function_state_ = state; } | 804 void set_function_state(FunctionState* state) { function_state_ = state; } |
784 | 805 |
785 AstContext* ast_context() const { return ast_context_; } | 806 AstContext* ast_context() const { return ast_context_; } |
786 void set_ast_context(AstContext* context) { ast_context_ = context; } | 807 void set_ast_context(AstContext* context) { ast_context_ = context; } |
787 | 808 |
788 // Accessors forwarded to the function state. | 809 // Accessors forwarded to the function state. |
789 CompilationInfo* info() const { | 810 CompilationInfo* info() const { |
790 return function_state()->compilation_info(); | 811 return function_state()->compilation_info(); |
791 } | 812 } |
792 | |
793 AstContext* call_context() const { | 813 AstContext* call_context() const { |
794 return function_state()->call_context(); | 814 return function_state()->call_context(); |
795 } | 815 } |
796 HBasicBlock* function_return() const { | 816 HBasicBlock* function_return() const { |
797 return function_state()->function_return(); | 817 return function_state()->function_return(); |
798 } | 818 } |
799 TestContext* inlined_test_context() const { | 819 TestContext* inlined_test_context() const { |
800 return function_state()->test_context(); | 820 return function_state()->test_context(); |
801 } | 821 } |
802 void ClearInlinedTestContext() { | 822 void ClearInlinedTestContext() { |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
910 }; | 930 }; |
911 GlobalPropertyAccess LookupGlobalProperty(Variable* var, | 931 GlobalPropertyAccess LookupGlobalProperty(Variable* var, |
912 LookupResult* lookup, | 932 LookupResult* lookup, |
913 bool is_store); | 933 bool is_store); |
914 | 934 |
915 bool TryArgumentsAccess(Property* expr); | 935 bool TryArgumentsAccess(Property* expr); |
916 | 936 |
917 // Try to optimize fun.apply(receiver, arguments) pattern. | 937 // Try to optimize fun.apply(receiver, arguments) pattern. |
918 bool TryCallApply(Call* expr); | 938 bool TryCallApply(Call* expr); |
919 | 939 |
920 bool TryInline(Call* expr, bool drop_extra = false); | 940 bool TryInline(CallKind call_kind, |
| 941 Handle<JSFunction> target, |
| 942 ZoneList<Expression*>* arguments, |
| 943 HValue* receiver, |
| 944 int ast_id, |
| 945 int return_id, |
| 946 ReturnHandlingFlag return_handling); |
| 947 |
| 948 bool TryInlineCall(Call* expr, bool drop_extra = false); |
| 949 bool TryInlineConstruct(CallNew* expr, HValue* receiver); |
921 bool TryInlineBuiltinFunction(Call* expr, | 950 bool TryInlineBuiltinFunction(Call* expr, |
922 HValue* receiver, | 951 HValue* receiver, |
923 Handle<Map> receiver_map, | 952 Handle<Map> receiver_map, |
924 CheckType check_type); | 953 CheckType check_type); |
925 | 954 |
926 // If --trace-inlining, print a line of the inlining trace. Inlining | 955 // If --trace-inlining, print a line of the inlining trace. Inlining |
927 // succeeded if the reason string is NULL and failed if there is a | 956 // succeeded if the reason string is NULL and failed if there is a |
928 // non-NULL reason string. | 957 // non-NULL reason string. |
929 void TraceInline(Handle<JSFunction> target, | 958 void TraceInline(Handle<JSFunction> target, |
930 Handle<JSFunction> caller, | 959 Handle<JSFunction> caller, |
(...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1275 const char* filename_; | 1304 const char* filename_; |
1276 HeapStringAllocator string_allocator_; | 1305 HeapStringAllocator string_allocator_; |
1277 StringStream trace_; | 1306 StringStream trace_; |
1278 int indent_; | 1307 int indent_; |
1279 }; | 1308 }; |
1280 | 1309 |
1281 | 1310 |
1282 } } // namespace v8::internal | 1311 } } // namespace v8::internal |
1283 | 1312 |
1284 #endif // V8_HYDROGEN_H_ | 1313 #endif // V8_HYDROGEN_H_ |
OLD | NEW |