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 // TODO(jochen): Remove this after the setting is turned on globally. | 5 // TODO(jochen): Remove this after the setting is turned on globally. |
6 #define V8_IMMINENT_DEPRECATION_WARNINGS | 6 #define V8_IMMINENT_DEPRECATION_WARNINGS |
7 | 7 |
8 #include <utility> | 8 #include <utility> |
9 | 9 |
10 #include "src/compiler/pipeline.h" | 10 #include "src/compiler/pipeline.h" |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
60 } | 60 } |
61 | 61 |
62 private: | 62 private: |
63 Isolate* isolate_; | 63 Isolate* isolate_; |
64 Handle<JSFunction> function_; | 64 Handle<JSFunction> function_; |
65 }; | 65 }; |
66 | 66 |
67 | 67 |
68 class BytecodeGraphTester { | 68 class BytecodeGraphTester { |
69 public: | 69 public: |
70 BytecodeGraphTester(Isolate* isolate, Zone* zone, const char* script) | 70 BytecodeGraphTester(Isolate* isolate, Zone* zone, const char* script, |
71 const char* filter = kFunctionName) | |
71 : isolate_(isolate), zone_(zone), script_(script) { | 72 : isolate_(isolate), zone_(zone), script_(script) { |
72 i::FLAG_ignition = true; | 73 i::FLAG_ignition = true; |
73 i::FLAG_always_opt = false; | 74 i::FLAG_always_opt = false; |
74 i::FLAG_allow_natives_syntax = true; | 75 i::FLAG_allow_natives_syntax = true; |
75 // Set ignition filter flag via SetFlagsFromString to avoid double-free | 76 // Set ignition filter flag via SetFlagsFromString to avoid double-free |
76 // (or potential leak with StrDup() based on ownership confusion). | 77 // (or potential leak with StrDup() based on ownership confusion). |
77 ScopedVector<char> ignition_filter(64); | 78 ScopedVector<char> ignition_filter(64); |
78 SNPrintF(ignition_filter, "--ignition-filter=%s", kFunctionName); | 79 SNPrintF(ignition_filter, "--ignition-filter=%s", filter); |
79 FlagList::SetFlagsFromString(ignition_filter.start(), | 80 FlagList::SetFlagsFromString(ignition_filter.start(), |
80 ignition_filter.length()); | 81 ignition_filter.length()); |
81 // Ensure handler table is generated. | 82 // Ensure handler table is generated. |
82 isolate->interpreter()->Initialize(); | 83 isolate->interpreter()->Initialize(); |
83 } | 84 } |
84 virtual ~BytecodeGraphTester() {} | 85 virtual ~BytecodeGraphTester() {} |
85 | 86 |
86 template <class... A> | 87 template <class... A> |
87 BytecodeGraphCallable<A...> GetCallable() { | 88 BytecodeGraphCallable<A...> GetCallable( |
88 return BytecodeGraphCallable<A...>(isolate_, GetFunction()); | 89 const char* functionName = kFunctionName) { |
90 return BytecodeGraphCallable<A...>(isolate_, GetFunction(functionName)); | |
89 } | 91 } |
90 | 92 |
91 Local<Message> CheckThrowsReturnMessage() { | 93 Local<Message> CheckThrowsReturnMessage() { |
92 TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate_)); | 94 TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate_)); |
93 auto callable = GetCallable<>(); | 95 auto callable = GetCallable<>(); |
94 MaybeHandle<Object> no_result = callable(); | 96 MaybeHandle<Object> no_result = callable(); |
95 CHECK(isolate_->has_pending_exception()); | 97 CHECK(isolate_->has_pending_exception()); |
96 CHECK(try_catch.HasCaught()); | 98 CHECK(try_catch.HasCaught()); |
97 CHECK(no_result.is_null()); | 99 CHECK(no_result.is_null()); |
98 isolate_->OptionalRescheduleException(true); | 100 isolate_->OptionalRescheduleException(true); |
99 CHECK(!try_catch.Message().IsEmpty()); | 101 CHECK(!try_catch.Message().IsEmpty()); |
100 return try_catch.Message(); | 102 return try_catch.Message(); |
101 } | 103 } |
102 | 104 |
103 static Handle<Object> NewObject(const char* script) { | 105 static Handle<Object> NewObject(const char* script) { |
104 return v8::Utils::OpenHandle(*CompileRun(script)); | 106 return v8::Utils::OpenHandle(*CompileRun(script)); |
105 } | 107 } |
106 | 108 |
107 private: | 109 private: |
108 Isolate* isolate_; | 110 Isolate* isolate_; |
109 Zone* zone_; | 111 Zone* zone_; |
110 const char* script_; | 112 const char* script_; |
111 | 113 |
112 Handle<JSFunction> GetFunction() { | 114 Handle<JSFunction> GetFunction(const char* functionName) { |
113 CompileRun(script_); | 115 CompileRun(script_); |
114 Local<Function> api_function = Local<Function>::Cast( | 116 Local<Function> api_function = Local<Function>::Cast( |
115 CcTest::global() | 117 CcTest::global() |
116 ->Get(CcTest::isolate()->GetCurrentContext(), v8_str(kFunctionName)) | 118 ->Get(CcTest::isolate()->GetCurrentContext(), v8_str(functionName)) |
117 .ToLocalChecked()); | 119 .ToLocalChecked()); |
118 Handle<JSFunction> function = | 120 Handle<JSFunction> function = |
119 Handle<JSFunction>::cast(v8::Utils::OpenHandle(*api_function)); | 121 Handle<JSFunction>::cast(v8::Utils::OpenHandle(*api_function)); |
120 CHECK(function->shared()->HasBytecodeArray()); | 122 CHECK(function->shared()->HasBytecodeArray()); |
121 | 123 |
122 ParseInfo parse_info(zone_, function); | 124 ParseInfo parse_info(zone_, function); |
123 | 125 |
124 CompilationInfo compilation_info(&parse_info); | 126 CompilationInfo compilation_info(&parse_info); |
125 compilation_info.SetOptimizing(BailoutId::None(), Handle<Code>()); | 127 compilation_info.SetOptimizing(BailoutId::None(), Handle<Code>()); |
126 // TODO(mythria): Remove this step once parse_info is not needed. | 128 // TODO(mythria): Remove this step once parse_info is not needed. |
(...skipping 868 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
995 snippets[i].code_snippet, kFunctionName); | 997 snippets[i].code_snippet, kFunctionName); |
996 BytecodeGraphTester tester(isolate, zone, script.start()); | 998 BytecodeGraphTester tester(isolate, zone, script.start()); |
997 v8::Local<v8::String> message = tester.CheckThrowsReturnMessage()->Get(); | 999 v8::Local<v8::String> message = tester.CheckThrowsReturnMessage()->Get(); |
998 v8::Local<v8::String> expected_string = v8_str(snippets[i].return_value()); | 1000 v8::Local<v8::String> expected_string = v8_str(snippets[i].return_value()); |
999 CHECK( | 1001 CHECK( |
1000 message->Equals(CcTest::isolate()->GetCurrentContext(), expected_string) | 1002 message->Equals(CcTest::isolate()->GetCurrentContext(), expected_string) |
1001 .FromJust()); | 1003 .FromJust()); |
1002 } | 1004 } |
1003 } | 1005 } |
1004 | 1006 |
1007 | |
1008 TEST(BytecodeGraphBuilderContext) { | |
1009 HandleAndZoneScope scope; | |
1010 Isolate* isolate = scope.main_isolate(); | |
1011 Zone* zone = scope.main_zone(); | |
1012 Factory* factory = isolate->factory(); | |
1013 | |
1014 ExpectedSnippet<0> snippets[] = { | |
1015 {"var x = 'outer';" | |
1016 "function f() {" | |
1017 " 'use strict';" | |
1018 " {" | |
1019 " let x = 'inner';" | |
1020 " (function() {x});" | |
1021 " }" | |
1022 "return(x);" | |
1023 "}" | |
1024 "f();", | |
1025 {factory->NewStringFromStaticChars("outer")}}, | |
1026 {"var x = 'outer';" | |
1027 "function f() {" | |
1028 " 'use strict';" | |
1029 " {" | |
1030 " let x = 'inner ';" | |
1031 " var innerFunc = function() {return x};" | |
1032 " }" | |
1033 "return(innerFunc() + x);" | |
1034 "}" | |
1035 "f();", | |
1036 {factory->NewStringFromStaticChars("inner outer")}}, | |
1037 {"var x = 'outer';" | |
1038 "function f() {" | |
1039 " 'use strict';" | |
1040 " {" | |
1041 " let x = 'inner ';" | |
1042 " var innerFunc = function() {return x;};" | |
1043 " {" | |
1044 " let x = 'innermost ';" | |
1045 " var innerMostFunc = function() {return x + innerFunc();};" | |
1046 " }" | |
1047 " x = 'inner_changed ';" | |
1048 " }" | |
1049 " return(innerMostFunc() + x);" | |
1050 "}" | |
1051 "f();", | |
1052 {factory->NewStringFromStaticChars("innermost inner_changed outer")}}, | |
1053 }; | |
1054 | |
1055 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); | |
1056 for (size_t i = 0; i < num_snippets; i++) { | |
1057 ScopedVector<char> script(1024); | |
1058 SNPrintF(script, "%s", snippets[i].code_snippet); | |
1059 | |
1060 BytecodeGraphTester tester(isolate, zone, script.start(), "f"); | |
1061 auto callable = tester.GetCallable<>("f"); | |
1062 Handle<Object> return_value = callable().ToHandleChecked(); | |
1063 CHECK(return_value->SameValue(*snippets[i].return_value())); | |
1064 } | |
1065 } | |
1066 | |
1067 | |
1068 TEST(BytecodeGraphBuilderLoadContext) { | |
1069 HandleAndZoneScope scope; | |
1070 Isolate* isolate = scope.main_isolate(); | |
1071 Zone* zone = scope.main_zone(); | |
1072 Factory* factory = isolate->factory(); | |
1073 | |
1074 ExpectedSnippet<1> snippets[] = { | |
1075 {"function Outer() {" | |
1076 " var outerVar = 2;" | |
1077 " function Inner(innerArg) {" | |
1078 " this.innerFunc = function () {" | |
1079 " return outerVar * innerArg;" | |
1080 " };" | |
1081 " };" | |
1082 " this.getInnerFunc = function GetInner() {" | |
1083 " return new Inner(2).innerFunc;" | |
Michael Starzinger
2015/12/01 15:54:57
nit: s/2/3/ so that we recognize when the wrong sl
mythria
2015/12/01 16:12:12
Done.
| |
1084 " }" | |
1085 "}" | |
1086 "var f = new Outer().getInnerFunc();" | |
1087 "f();", | |
1088 {factory->NewNumberFromInt(4), factory->undefined_value()}}, | |
1089 {"function Outer() {" | |
1090 " var outerVar = 2;" | |
1091 " function Inner(innerArg) {" | |
1092 " this.innerFunc = function () {" | |
1093 " outerVar = innerArg; return outerVar;" | |
1094 " };" | |
1095 " };" | |
1096 " this.getInnerFunc = function GetInner() {" | |
1097 " return new Inner(10).innerFunc;" | |
1098 " }" | |
1099 "}" | |
1100 "var f = new Outer().getInnerFunc();" | |
1101 "f();", | |
1102 {factory->NewNumberFromInt(10), factory->undefined_value()}}, | |
1103 {"function testOuter(outerArg) {" | |
1104 " this.testinnerFunc = function testInner(innerArg) {" | |
1105 " return innerArg + outerArg;" | |
1106 " }" | |
1107 "}" | |
1108 "var f = new testOuter(10).testinnerFunc;" | |
1109 "f(0);", | |
1110 {factory->NewNumberFromInt(14), factory->NewNumberFromInt(4)}}, | |
1111 {"function testOuter(outerArg) {" | |
1112 " var outerVar = outerArg * 2;" | |
1113 " this.testinnerFunc = function testInner(innerArg) {" | |
1114 " outerVar = outerVar + innerArg; return outerVar;" | |
1115 " }" | |
1116 "}" | |
1117 "var f = new testOuter(10).testinnerFunc;" | |
1118 "f(0);", | |
1119 {factory->NewNumberFromInt(24), factory->NewNumberFromInt(4)}}}; | |
1120 | |
1121 size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]); | |
1122 for (size_t i = 0; i < num_snippets; i++) { | |
1123 ScopedVector<char> script(1024); | |
1124 SNPrintF(script, "%s", snippets[i].code_snippet); | |
1125 | |
1126 BytecodeGraphTester tester(isolate, zone, script.start(), "*"); | |
1127 auto callable = tester.GetCallable<Handle<Object>>("f"); | |
1128 Handle<Object> return_value = | |
1129 callable(snippets[i].parameter(0)).ToHandleChecked(); | |
1130 CHECK(return_value->SameValue(*snippets[i].return_value())); | |
1131 } | |
1132 } | |
1133 | |
1005 } // namespace compiler | 1134 } // namespace compiler |
1006 } // namespace internal | 1135 } // namespace internal |
1007 } // namespace v8 | 1136 } // namespace v8 |
OLD | NEW |