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 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2740 ScopedVector<char> script(1024); | 2739 ScopedVector<char> script(1024); |
2741 SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName, | 2740 SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName, |
2742 snippet.code_snippet, kFunctionName); | 2741 snippet.code_snippet, kFunctionName); |
2743 | 2742 |
2744 BytecodeGraphTester tester(isolate, zone, script.start()); | 2743 BytecodeGraphTester tester(isolate, zone, script.start()); |
2745 auto callable = tester.GetCallable<>(); | 2744 auto callable = tester.GetCallable<>(); |
2746 Handle<Object> return_value = callable().ToHandleChecked(); | 2745 Handle<Object> return_value = callable().ToHandleChecked(); |
2747 CHECK(return_value->SameValue(*snippet.return_value())); | 2746 CHECK(return_value->SameValue(*snippet.return_value())); |
2748 } | 2747 } |
2749 | 2748 |
| 2749 TEST(BytecodeGraphBuilderConstDeclaration) { |
| 2750 HandleAndZoneScope scope; |
| 2751 Isolate* isolate = scope.main_isolate(); |
| 2752 Zone* zone = scope.main_zone(); |
| 2753 Factory* factory = isolate->factory(); |
| 2754 |
| 2755 ExpectedSnippet<0> snippets[] = { |
| 2756 {"const x = 3; return x;", {handle(Smi::FromInt(3), isolate)}}, |
| 2757 {"let x = 10; x = x + 20; return x;", |
| 2758 {handle(Smi::FromInt(30), isolate)}}, |
| 2759 {"let x = 10; x = 20; return x;", {handle(Smi::FromInt(20), isolate)}}, |
| 2760 {"let x; x = 20; return x;", {handle(Smi::FromInt(20), isolate)}}, |
| 2761 {"let x; return x;", {factory->undefined_value()}}, |
| 2762 {"var x = 10; { let x = 30; } return x;", |
| 2763 {handle(Smi::FromInt(10), isolate)}}, |
| 2764 {"let x = 10; { let x = 20; } return x;", |
| 2765 {handle(Smi::FromInt(10), isolate)}}, |
| 2766 {"var x = 10; eval('let x = 20;'); return x;", |
| 2767 {handle(Smi::FromInt(10), isolate)}}, |
| 2768 {"var x = 10; eval('const x = 20;'); return x;", |
| 2769 {handle(Smi::FromInt(10), isolate)}}, |
| 2770 {"var x = 10; { const x = 20; } return x;", |
| 2771 {handle(Smi::FromInt(10), isolate)}}, |
| 2772 {"var x = 10; { const x = 20; return x;} return -1;", |
| 2773 {handle(Smi::FromInt(20), isolate)}}, |
| 2774 {"var a = 10;\n" |
| 2775 "for (var i = 0; i < 10; ++i) {\n" |
| 2776 " const x = i;\n" // const declarations are block scoped. |
| 2777 " a = a + x;\n" |
| 2778 "}\n" |
| 2779 "return a;\n", |
| 2780 {handle(Smi::FromInt(55), isolate)}}, |
| 2781 }; |
| 2782 |
| 2783 // Tests for sloppy mode. |
| 2784 for (size_t i = 0; i < arraysize(snippets); i++) { |
| 2785 ScopedVector<char> script(1024); |
| 2786 SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName, |
| 2787 snippets[i].code_snippet, kFunctionName); |
| 2788 |
| 2789 BytecodeGraphTester tester(isolate, zone, script.start()); |
| 2790 auto callable = tester.GetCallable<>(); |
| 2791 Handle<Object> return_value = callable().ToHandleChecked(); |
| 2792 CHECK(return_value->SameValue(*snippets[i].return_value())); |
| 2793 } |
| 2794 |
| 2795 // Tests for strict mode. |
| 2796 for (size_t i = 0; i < arraysize(snippets); i++) { |
| 2797 ScopedVector<char> script(1024); |
| 2798 SNPrintF(script, "function %s() {'use strict'; %s }\n%s();", kFunctionName, |
| 2799 snippets[i].code_snippet, kFunctionName); |
| 2800 |
| 2801 BytecodeGraphTester tester(isolate, zone, script.start()); |
| 2802 auto callable = tester.GetCallable<>(); |
| 2803 Handle<Object> return_value = callable().ToHandleChecked(); |
| 2804 CHECK(return_value->SameValue(*snippets[i].return_value())); |
| 2805 } |
| 2806 } |
| 2807 |
| 2808 TEST(BytecodeGraphBuilderConstDeclarationLookupSlots) { |
| 2809 HandleAndZoneScope scope; |
| 2810 Isolate* isolate = scope.main_isolate(); |
| 2811 Zone* zone = scope.main_zone(); |
| 2812 Factory* factory = isolate->factory(); |
| 2813 |
| 2814 ExpectedSnippet<0> snippets[] = { |
| 2815 {"const x = 3; function f1() {return x;}; return x;", |
| 2816 {handle(Smi::FromInt(3), isolate)}}, |
| 2817 {"let x = 10; x = x + 20; function f1() {return x;}; return x;", |
| 2818 {handle(Smi::FromInt(30), isolate)}}, |
| 2819 {"let x; x = 20; function f1() {return x;}; return x;", |
| 2820 {handle(Smi::FromInt(20), isolate)}}, |
| 2821 {"let x; function f1() {return x;}; return x;", |
| 2822 {factory->undefined_value()}}, |
| 2823 }; |
| 2824 |
| 2825 // Tests for sloppy mode. |
| 2826 for (size_t i = 0; i < arraysize(snippets); i++) { |
| 2827 ScopedVector<char> script(1024); |
| 2828 SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName, |
| 2829 snippets[i].code_snippet, kFunctionName); |
| 2830 |
| 2831 BytecodeGraphTester tester(isolate, zone, script.start()); |
| 2832 auto callable = tester.GetCallable<>(); |
| 2833 Handle<Object> return_value = callable().ToHandleChecked(); |
| 2834 CHECK(return_value->SameValue(*snippets[i].return_value())); |
| 2835 } |
| 2836 |
| 2837 // Tests for strict mode. |
| 2838 for (size_t i = 0; i < arraysize(snippets); i++) { |
| 2839 ScopedVector<char> script(1024); |
| 2840 SNPrintF(script, "function %s() {'use strict'; %s }\n%s();", kFunctionName, |
| 2841 snippets[i].code_snippet, kFunctionName); |
| 2842 |
| 2843 BytecodeGraphTester tester(isolate, zone, script.start()); |
| 2844 auto callable = tester.GetCallable<>(); |
| 2845 Handle<Object> return_value = callable().ToHandleChecked(); |
| 2846 CHECK(return_value->SameValue(*snippets[i].return_value())); |
| 2847 } |
| 2848 } |
| 2849 |
| 2850 TEST(BytecodeGraphBuilderConstInLookupContextChain) { |
| 2851 HandleAndZoneScope scope; |
| 2852 Isolate* isolate = scope.main_isolate(); |
| 2853 Zone* zone = scope.main_zone(); |
| 2854 |
| 2855 const char* prologue = |
| 2856 "function OuterMost() {\n" |
| 2857 " const outerConst = 10;\n" |
| 2858 " let outerLet = 20;\n" |
| 2859 " function Outer() {\n" |
| 2860 " function Inner() {\n" |
| 2861 " this.innerFunc = function() { "; |
| 2862 const char* epilogue = |
| 2863 " }\n" |
| 2864 " }\n" |
| 2865 " this.getInnerFunc =" |
| 2866 " function() {return new Inner().innerFunc;}\n" |
| 2867 " }\n" |
| 2868 " this.getOuterFunc =" |
| 2869 " function() {return new Outer().getInnerFunc();}" |
| 2870 "}\n" |
| 2871 "var f = new OuterMost().getOuterFunc();\n" |
| 2872 "f();\n"; |
| 2873 |
| 2874 // Tests for let / constant. |
| 2875 ExpectedSnippet<0> const_decl[] = { |
| 2876 {"return outerConst;", {handle(Smi::FromInt(10), isolate)}}, |
| 2877 {"return outerLet;", {handle(Smi::FromInt(20), isolate)}}, |
| 2878 {"outerLet = 30; return outerLet;", {handle(Smi::FromInt(30), isolate)}}, |
| 2879 {"var outerLet = 40; return outerLet;", |
| 2880 {handle(Smi::FromInt(40), isolate)}}, |
| 2881 {"var outerConst = 50; return outerConst;", |
| 2882 {handle(Smi::FromInt(50), isolate)}}, |
| 2883 {"try { outerConst = 30 } catch(e) { return -1; }", |
| 2884 {handle(Smi::FromInt(-1), isolate)}}}; |
| 2885 |
| 2886 for (size_t i = 0; i < arraysize(const_decl); i++) { |
| 2887 ScopedVector<char> script(1024); |
| 2888 SNPrintF(script, "%s %s %s", prologue, const_decl[i].code_snippet, |
| 2889 epilogue); |
| 2890 |
| 2891 BytecodeGraphTester tester(isolate, zone, script.start(), "*"); |
| 2892 auto callable = tester.GetCallable<>(); |
| 2893 Handle<Object> return_value = callable().ToHandleChecked(); |
| 2894 CHECK(return_value->SameValue(*const_decl[i].return_value())); |
| 2895 } |
| 2896 |
| 2897 // Tests for Legacy constant. |
| 2898 bool old_flag_legacy_const = FLAG_legacy_const; |
| 2899 FLAG_legacy_const = true; |
| 2900 |
| 2901 ExpectedSnippet<0> legacy_const_decl[] = { |
| 2902 {"return outerConst = 23;", {handle(Smi::FromInt(23), isolate)}}, |
| 2903 {"outerConst = 30; return outerConst;", |
| 2904 {handle(Smi::FromInt(10), isolate)}}, |
| 2905 }; |
| 2906 |
| 2907 for (size_t i = 0; i < arraysize(legacy_const_decl); i++) { |
| 2908 ScopedVector<char> script(1024); |
| 2909 SNPrintF(script, "%s %s %s", prologue, legacy_const_decl[i].code_snippet, |
| 2910 epilogue); |
| 2911 |
| 2912 BytecodeGraphTester tester(isolate, zone, script.start(), "*"); |
| 2913 auto callable = tester.GetCallable<>(); |
| 2914 Handle<Object> return_value = callable().ToHandleChecked(); |
| 2915 CHECK(return_value->SameValue(*legacy_const_decl[i].return_value())); |
| 2916 } |
| 2917 |
| 2918 FLAG_legacy_const = old_flag_legacy_const; |
| 2919 } |
| 2920 |
| 2921 TEST(BytecodeGraphBuilderIllegalConstDeclaration) { |
| 2922 HandleAndZoneScope scope; |
| 2923 Isolate* isolate = scope.main_isolate(); |
| 2924 Zone* zone = scope.main_zone(); |
| 2925 |
| 2926 ExpectedSnippet<0, const char*> illegal_const_decl[] = { |
| 2927 {"const x = x = 10 + 3; return x;", |
| 2928 {"Uncaught ReferenceError: x is not defined"}}, |
| 2929 {"const x = 10; x = 20; return x;", |
| 2930 {"Uncaught TypeError: Assignment to constant variable."}}, |
| 2931 {"const x = 10; { x = 20; } return x;", |
| 2932 {"Uncaught TypeError: Assignment to constant variable."}}, |
| 2933 {"const x = 10; eval('x = 20;'); return x;", |
| 2934 {"Uncaught TypeError: Assignment to constant variable."}}, |
| 2935 {"let x = x + 10; return x;", |
| 2936 {"Uncaught ReferenceError: x is not defined"}}, |
| 2937 {"'use strict'; (function f1() { f1 = 123; })() ", |
| 2938 {"Uncaught TypeError: Assignment to constant variable."}}, |
| 2939 }; |
| 2940 |
| 2941 // Tests for sloppy mode. |
| 2942 for (size_t i = 0; i < arraysize(illegal_const_decl); i++) { |
| 2943 ScopedVector<char> script(1024); |
| 2944 SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName, |
| 2945 illegal_const_decl[i].code_snippet, kFunctionName); |
| 2946 |
| 2947 BytecodeGraphTester tester(isolate, zone, script.start()); |
| 2948 v8::Local<v8::String> message = tester.CheckThrowsReturnMessage()->Get(); |
| 2949 v8::Local<v8::String> expected_string = |
| 2950 v8_str(illegal_const_decl[i].return_value()); |
| 2951 CHECK( |
| 2952 message->Equals(CcTest::isolate()->GetCurrentContext(), expected_string) |
| 2953 .FromJust()); |
| 2954 } |
| 2955 |
| 2956 // Tests for strict mode. |
| 2957 for (size_t i = 0; i < arraysize(illegal_const_decl); i++) { |
| 2958 ScopedVector<char> script(1024); |
| 2959 SNPrintF(script, "function %s() {'use strict'; %s }\n%s();", kFunctionName, |
| 2960 illegal_const_decl[i].code_snippet, kFunctionName); |
| 2961 |
| 2962 BytecodeGraphTester tester(isolate, zone, script.start()); |
| 2963 v8::Local<v8::String> message = tester.CheckThrowsReturnMessage()->Get(); |
| 2964 v8::Local<v8::String> expected_string = |
| 2965 v8_str(illegal_const_decl[i].return_value()); |
| 2966 CHECK( |
| 2967 message->Equals(CcTest::isolate()->GetCurrentContext(), expected_string) |
| 2968 .FromJust()); |
| 2969 } |
| 2970 } |
| 2971 |
| 2972 TEST(BytecodeGraphBuilderLegacyConstDeclaration) { |
| 2973 bool old_flag_legacy_const = FLAG_legacy_const; |
| 2974 FLAG_legacy_const = true; |
| 2975 |
| 2976 HandleAndZoneScope scope; |
| 2977 Isolate* isolate = scope.main_isolate(); |
| 2978 Zone* zone = scope.main_zone(); |
| 2979 |
| 2980 ExpectedSnippet<0> snippets[] = { |
| 2981 {"const x = (x = 10) + 3; return x;", |
| 2982 {handle(Smi::FromInt(13), isolate)}}, |
| 2983 {"const x = 10; x = 20; return x;", {handle(Smi::FromInt(10), isolate)}}, |
| 2984 {"var a = 10;\n" |
| 2985 "for (var i = 0; i < 10; ++i) {\n" |
| 2986 " const x = i;\n" // Legacy constants are not block scoped. |
| 2987 " a = a + x;\n" |
| 2988 "}\n" |
| 2989 "return a;\n", |
| 2990 {handle(Smi::FromInt(10), isolate)}}, |
| 2991 {"const x = 20; eval('x = 10;'); return x;", |
| 2992 {handle(Smi::FromInt(20), isolate)}}, |
| 2993 }; |
| 2994 |
| 2995 for (size_t i = 0; i < arraysize(snippets); i++) { |
| 2996 ScopedVector<char> script(1024); |
| 2997 SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName, |
| 2998 snippets[i].code_snippet, kFunctionName); |
| 2999 |
| 3000 BytecodeGraphTester tester(isolate, zone, script.start()); |
| 3001 auto callable = tester.GetCallable<>(); |
| 3002 Handle<Object> return_value = callable().ToHandleChecked(); |
| 3003 CHECK(return_value->SameValue(*snippets[i].return_value())); |
| 3004 } |
| 3005 |
| 3006 FLAG_legacy_const = old_flag_legacy_const; |
| 3007 } |
| 3008 |
2750 } // namespace compiler | 3009 } // namespace compiler |
2751 } // namespace internal | 3010 } // namespace internal |
2752 } // namespace v8 | 3011 } // namespace v8 |
OLD | NEW |