OLD | NEW |
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 <utility> | 5 #include <utility> |
6 | 6 |
7 #include "src/compiler/pipeline.h" | 7 #include "src/compiler/pipeline.h" |
8 #include "src/execution.h" | 8 #include "src/execution.h" |
9 #include "src/handles.h" | 9 #include "src/handles.h" |
10 #include "src/interpreter/bytecode-array-builder.h" | 10 #include "src/interpreter/bytecode-array-builder.h" |
(...skipping 2631 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2642 callable(factory->NewNumberFromInt(a)).ToHandleChecked(); | 2642 callable(factory->NewNumberFromInt(a)).ToHandleChecked(); |
2643 static const int results[] = {11, 12, 2}; | 2643 static const int results[] = {11, 12, 2}; |
2644 CHECK_EQ(Handle<Smi>::cast(return_val)->value(), results[a]); | 2644 CHECK_EQ(Handle<Smi>::cast(return_val)->value(), results[a]); |
2645 } | 2645 } |
2646 } | 2646 } |
2647 } | 2647 } |
2648 | 2648 |
2649 TEST(BytecodeGraphBuilderDoExpressions) { | 2649 TEST(BytecodeGraphBuilderDoExpressions) { |
2650 bool old_flag = FLAG_harmony_do_expressions; | 2650 bool old_flag = FLAG_harmony_do_expressions; |
2651 FLAG_harmony_do_expressions = true; | 2651 FLAG_harmony_do_expressions = true; |
2652 | |
2653 HandleAndZoneScope scope; | 2652 HandleAndZoneScope scope; |
2654 Isolate* isolate = scope.main_isolate(); | 2653 Isolate* isolate = scope.main_isolate(); |
2655 Zone* zone = scope.main_zone(); | 2654 Zone* zone = scope.main_zone(); |
2656 Factory* factory = isolate->factory(); | 2655 Factory* factory = isolate->factory(); |
2657 ExpectedSnippet<0> snippets[] = { | 2656 ExpectedSnippet<0> snippets[] = { |
2658 {"var a = do {}; return a;", {factory->undefined_value()}}, | 2657 {"var a = do {}; return a;", {factory->undefined_value()}}, |
2659 {"var a = do { var x = 100; }; return a;", {factory->undefined_value()}}, | 2658 {"var a = do { var x = 100; }; return a;", {factory->undefined_value()}}, |
2660 {"var a = do { var x = 100; }; return a;", {factory->undefined_value()}}, | 2659 {"var a = do { var x = 100; }; return a;", {factory->undefined_value()}}, |
2661 {"var a = do { var x = 100; x++; }; return a;", | 2660 {"var a = do { var x = 100; x++; }; return a;", |
2662 {handle(Smi::FromInt(100), isolate)}}, | 2661 {handle(Smi::FromInt(100), isolate)}}, |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2709 SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName, | 2708 SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName, |
2710 snippets[i].code_snippet, kFunctionName); | 2709 snippets[i].code_snippet, kFunctionName); |
2711 | 2710 |
2712 BytecodeGraphTester tester(isolate, zone, script.start()); | 2711 BytecodeGraphTester tester(isolate, zone, script.start()); |
2713 auto callable = tester.GetCallable<>(); | 2712 auto callable = tester.GetCallable<>(); |
2714 Handle<Object> return_value = callable().ToHandleChecked(); | 2713 Handle<Object> return_value = callable().ToHandleChecked(); |
2715 CHECK(return_value->SameValue(*snippets[i].return_value())); | 2714 CHECK(return_value->SameValue(*snippets[i].return_value())); |
2716 } | 2715 } |
2717 } | 2716 } |
2718 | 2717 |
| 2718 TEST(BytecodeGraphBuilderConstDeclaration) { |
| 2719 HandleAndZoneScope scope; |
| 2720 Isolate* isolate = scope.main_isolate(); |
| 2721 Zone* zone = scope.main_zone(); |
| 2722 Factory* factory = isolate->factory(); |
| 2723 |
| 2724 ExpectedSnippet<0> snippets[] = { |
| 2725 {"const x = 3; return x;", {handle(Smi::FromInt(3), isolate)}}, |
| 2726 {"let x = 10; x = x + 20; return x;", |
| 2727 {handle(Smi::FromInt(30), isolate)}}, |
| 2728 {"let x = 10; x = 20; return x;", {handle(Smi::FromInt(20), isolate)}}, |
| 2729 {"let x; x = 20; return x;", {handle(Smi::FromInt(20), isolate)}}, |
| 2730 {"let x; return x;", {factory->undefined_value()}}, |
| 2731 {"var x = 10; { let x = 30; } return x;", |
| 2732 {handle(Smi::FromInt(10), isolate)}}, |
| 2733 {"let x = 10; { let x = 20; } return x;", |
| 2734 {handle(Smi::FromInt(10), isolate)}}, |
| 2735 {"var x = 10; eval('let x = 20;'); return x;", |
| 2736 {handle(Smi::FromInt(10), isolate)}}, |
| 2737 {"var x = 10; eval('const x = 20;'); return x;", |
| 2738 {handle(Smi::FromInt(10), isolate)}}, |
| 2739 {"var x = 10; { const x = 20; } return x;", |
| 2740 {handle(Smi::FromInt(10), isolate)}}, |
| 2741 {"var x = 10; { const x = 20; return x;} return -1;", |
| 2742 {handle(Smi::FromInt(20), isolate)}}, |
| 2743 {"var a = 10;\n" |
| 2744 "for (var i = 0; i < 10; ++i) {\n" |
| 2745 " const x = i;\n" // const declarations are block scoped. |
| 2746 " a = a + x;\n" |
| 2747 "}\n" |
| 2748 "return a;\n", |
| 2749 {handle(Smi::FromInt(55), isolate)}}, |
| 2750 }; |
| 2751 |
| 2752 // Tests for sloppy mode. |
| 2753 for (size_t i = 0; i < arraysize(snippets); i++) { |
| 2754 ScopedVector<char> script(1024); |
| 2755 SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName, |
| 2756 snippets[i].code_snippet, kFunctionName); |
| 2757 |
| 2758 BytecodeGraphTester tester(isolate, zone, script.start()); |
| 2759 auto callable = tester.GetCallable<>(); |
| 2760 Handle<Object> return_value = callable().ToHandleChecked(); |
| 2761 CHECK(return_value->SameValue(*snippets[i].return_value())); |
| 2762 } |
| 2763 |
| 2764 // Tests for strict mode. |
| 2765 for (size_t i = 0; i < arraysize(snippets); i++) { |
| 2766 ScopedVector<char> script(1024); |
| 2767 SNPrintF(script, "function %s() {'use strict'; %s }\n%s();", kFunctionName, |
| 2768 snippets[i].code_snippet, kFunctionName); |
| 2769 |
| 2770 BytecodeGraphTester tester(isolate, zone, script.start()); |
| 2771 auto callable = tester.GetCallable<>(); |
| 2772 Handle<Object> return_value = callable().ToHandleChecked(); |
| 2773 CHECK(return_value->SameValue(*snippets[i].return_value())); |
| 2774 } |
| 2775 } |
| 2776 |
| 2777 TEST(BytecodeGraphBuilderConstDeclarationLookupSlots) { |
| 2778 HandleAndZoneScope scope; |
| 2779 Isolate* isolate = scope.main_isolate(); |
| 2780 Zone* zone = scope.main_zone(); |
| 2781 Factory* factory = isolate->factory(); |
| 2782 |
| 2783 ExpectedSnippet<0> snippets[] = { |
| 2784 {"const x = 3; function f1() {return x;}; return x;", |
| 2785 {handle(Smi::FromInt(3), isolate)}}, |
| 2786 {"let x = 10; x = x + 20; function f1() {return x;}; return x;", |
| 2787 {handle(Smi::FromInt(30), isolate)}}, |
| 2788 {"let x; x = 20; function f1() {return x;}; return x;", |
| 2789 {handle(Smi::FromInt(20), isolate)}}, |
| 2790 {"let x; function f1() {return x;}; return x;", |
| 2791 {factory->undefined_value()}}, |
| 2792 }; |
| 2793 |
| 2794 // Tests for sloppy mode. |
| 2795 for (size_t i = 0; i < arraysize(snippets); i++) { |
| 2796 ScopedVector<char> script(1024); |
| 2797 SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName, |
| 2798 snippets[i].code_snippet, kFunctionName); |
| 2799 |
| 2800 BytecodeGraphTester tester(isolate, zone, script.start()); |
| 2801 auto callable = tester.GetCallable<>(); |
| 2802 Handle<Object> return_value = callable().ToHandleChecked(); |
| 2803 CHECK(return_value->SameValue(*snippets[i].return_value())); |
| 2804 } |
| 2805 |
| 2806 // Tests for strict mode. |
| 2807 for (size_t i = 0; i < arraysize(snippets); i++) { |
| 2808 ScopedVector<char> script(1024); |
| 2809 SNPrintF(script, "function %s() {'use strict'; %s }\n%s();", kFunctionName, |
| 2810 snippets[i].code_snippet, kFunctionName); |
| 2811 |
| 2812 BytecodeGraphTester tester(isolate, zone, script.start()); |
| 2813 auto callable = tester.GetCallable<>(); |
| 2814 Handle<Object> return_value = callable().ToHandleChecked(); |
| 2815 CHECK(return_value->SameValue(*snippets[i].return_value())); |
| 2816 } |
| 2817 } |
| 2818 |
| 2819 TEST(BytecodeGraphBuilderConstInLookupContextChain) { |
| 2820 HandleAndZoneScope scope; |
| 2821 Isolate* isolate = scope.main_isolate(); |
| 2822 Zone* zone = scope.main_zone(); |
| 2823 |
| 2824 const char* prologue = |
| 2825 "function OuterMost() {\n" |
| 2826 " const outerConst = 10;\n" |
| 2827 " let outerLet = 20;\n" |
| 2828 " function Outer() {\n" |
| 2829 " function Inner() {\n" |
| 2830 " this.innerFunc = function() { "; |
| 2831 const char* epilogue = |
| 2832 " }\n" |
| 2833 " }\n" |
| 2834 " this.getInnerFunc =" |
| 2835 " function() {return new Inner().innerFunc;}\n" |
| 2836 " }\n" |
| 2837 " this.getOuterFunc =" |
| 2838 " function() {return new Outer().getInnerFunc();}" |
| 2839 "}\n" |
| 2840 "var f = new OuterMost().getOuterFunc();\n" |
| 2841 "f();\n"; |
| 2842 |
| 2843 // Tests for let / constant. |
| 2844 ExpectedSnippet<0> const_decl[] = { |
| 2845 {"return outerConst;", {handle(Smi::FromInt(10), isolate)}}, |
| 2846 {"return outerLet;", {handle(Smi::FromInt(20), isolate)}}, |
| 2847 {"outerLet = 30; return outerLet;", {handle(Smi::FromInt(30), isolate)}}, |
| 2848 {"var outerLet = 40; return outerLet;", |
| 2849 {handle(Smi::FromInt(40), isolate)}}, |
| 2850 {"var outerConst = 50; return outerConst;", |
| 2851 {handle(Smi::FromInt(50), isolate)}}, |
| 2852 {"try { outerConst = 30 } catch(e) { return -1; }", |
| 2853 {handle(Smi::FromInt(-1), isolate)}}}; |
| 2854 |
| 2855 for (size_t i = 0; i < arraysize(const_decl); i++) { |
| 2856 ScopedVector<char> script(1024); |
| 2857 SNPrintF(script, "%s %s %s", prologue, const_decl[i].code_snippet, |
| 2858 epilogue); |
| 2859 |
| 2860 BytecodeGraphTester tester(isolate, zone, script.start(), "*"); |
| 2861 auto callable = tester.GetCallable<>(); |
| 2862 Handle<Object> return_value = callable().ToHandleChecked(); |
| 2863 CHECK(return_value->SameValue(*const_decl[i].return_value())); |
| 2864 } |
| 2865 |
| 2866 // Tests for Legacy constant. |
| 2867 bool old_flag_legacy_const = FLAG_legacy_const; |
| 2868 FLAG_legacy_const = true; |
| 2869 |
| 2870 ExpectedSnippet<0> legacy_const_decl[] = { |
| 2871 {"return outerConst = 23;", {handle(Smi::FromInt(23), isolate)}}, |
| 2872 {"outerConst = 30; return outerConst;", |
| 2873 {handle(Smi::FromInt(10), isolate)}}, |
| 2874 }; |
| 2875 |
| 2876 for (size_t i = 0; i < arraysize(legacy_const_decl); i++) { |
| 2877 ScopedVector<char> script(1024); |
| 2878 SNPrintF(script, "%s %s %s", prologue, legacy_const_decl[i].code_snippet, |
| 2879 epilogue); |
| 2880 |
| 2881 BytecodeGraphTester tester(isolate, zone, script.start(), "*"); |
| 2882 auto callable = tester.GetCallable<>(); |
| 2883 Handle<Object> return_value = callable().ToHandleChecked(); |
| 2884 CHECK(return_value->SameValue(*legacy_const_decl[i].return_value())); |
| 2885 } |
| 2886 |
| 2887 FLAG_legacy_const = old_flag_legacy_const; |
| 2888 } |
| 2889 |
| 2890 TEST(BytecodeGraphBuilderIllegalConstDeclaration) { |
| 2891 HandleAndZoneScope scope; |
| 2892 Isolate* isolate = scope.main_isolate(); |
| 2893 Zone* zone = scope.main_zone(); |
| 2894 |
| 2895 ExpectedSnippet<0, const char*> illegal_const_decl[] = { |
| 2896 {"const x = x = 10 + 3; return x;", |
| 2897 {"Uncaught ReferenceError: x is not defined"}}, |
| 2898 {"const x = 10; x = 20; return x;", |
| 2899 {"Uncaught TypeError: Assignment to constant variable."}}, |
| 2900 {"const x = 10; { x = 20; } return x;", |
| 2901 {"Uncaught TypeError: Assignment to constant variable."}}, |
| 2902 {"const x = 10; eval('x = 20;'); return x;", |
| 2903 {"Uncaught TypeError: Assignment to constant variable."}}, |
| 2904 {"let x = x + 10; return x;", |
| 2905 {"Uncaught ReferenceError: x is not defined"}}, |
| 2906 {"'use strict'; (function f1() { f1 = 123; })() ", |
| 2907 {"Uncaught TypeError: Assignment to constant variable."}}, |
| 2908 }; |
| 2909 |
| 2910 // Tests for sloppy mode. |
| 2911 for (size_t i = 0; i < arraysize(illegal_const_decl); i++) { |
| 2912 ScopedVector<char> script(1024); |
| 2913 SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName, |
| 2914 illegal_const_decl[i].code_snippet, kFunctionName); |
| 2915 |
| 2916 BytecodeGraphTester tester(isolate, zone, script.start()); |
| 2917 v8::Local<v8::String> message = tester.CheckThrowsReturnMessage()->Get(); |
| 2918 v8::Local<v8::String> expected_string = |
| 2919 v8_str(illegal_const_decl[i].return_value()); |
| 2920 CHECK( |
| 2921 message->Equals(CcTest::isolate()->GetCurrentContext(), expected_string) |
| 2922 .FromJust()); |
| 2923 } |
| 2924 |
| 2925 // Tests for strict mode. |
| 2926 for (size_t i = 0; i < arraysize(illegal_const_decl); i++) { |
| 2927 ScopedVector<char> script(1024); |
| 2928 SNPrintF(script, "function %s() {'use strict'; %s }\n%s();", kFunctionName, |
| 2929 illegal_const_decl[i].code_snippet, kFunctionName); |
| 2930 |
| 2931 BytecodeGraphTester tester(isolate, zone, script.start()); |
| 2932 v8::Local<v8::String> message = tester.CheckThrowsReturnMessage()->Get(); |
| 2933 v8::Local<v8::String> expected_string = |
| 2934 v8_str(illegal_const_decl[i].return_value()); |
| 2935 CHECK( |
| 2936 message->Equals(CcTest::isolate()->GetCurrentContext(), expected_string) |
| 2937 .FromJust()); |
| 2938 } |
| 2939 } |
| 2940 |
| 2941 TEST(BytecodeGraphBuilderLegacyConstDeclaration) { |
| 2942 bool old_flag_legacy_const = FLAG_legacy_const; |
| 2943 FLAG_legacy_const = true; |
| 2944 |
| 2945 HandleAndZoneScope scope; |
| 2946 Isolate* isolate = scope.main_isolate(); |
| 2947 Zone* zone = scope.main_zone(); |
| 2948 |
| 2949 ExpectedSnippet<0> snippets[] = { |
| 2950 {"const x = (x = 10) + 3; return x;", |
| 2951 {handle(Smi::FromInt(13), isolate)}}, |
| 2952 {"const x = 10; x = 20; return x;", {handle(Smi::FromInt(10), isolate)}}, |
| 2953 {"var a = 10;\n" |
| 2954 "for (var i = 0; i < 10; ++i) {\n" |
| 2955 " const x = i;\n" // Legacy constants are not block scoped. |
| 2956 " a = a + x;\n" |
| 2957 "}\n" |
| 2958 "return a;\n", |
| 2959 {handle(Smi::FromInt(10), isolate)}}, |
| 2960 {"const x = 20; eval('x = 10;'); return x;", |
| 2961 {handle(Smi::FromInt(20), isolate)}}, |
| 2962 }; |
| 2963 |
| 2964 for (size_t i = 0; i < arraysize(snippets); i++) { |
| 2965 ScopedVector<char> script(1024); |
| 2966 SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName, |
| 2967 snippets[i].code_snippet, kFunctionName); |
| 2968 |
| 2969 BytecodeGraphTester tester(isolate, zone, script.start()); |
| 2970 auto callable = tester.GetCallable<>(); |
| 2971 Handle<Object> return_value = callable().ToHandleChecked(); |
| 2972 CHECK(return_value->SameValue(*snippets[i].return_value())); |
| 2973 } |
| 2974 |
| 2975 FLAG_legacy_const = old_flag_legacy_const; |
| 2976 } |
| 2977 |
2719 } // namespace compiler | 2978 } // namespace compiler |
2720 } // namespace internal | 2979 } // namespace internal |
2721 } // namespace v8 | 2980 } // namespace v8 |
OLD | NEW |