| 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 #ifndef V8_CCTEST_COMPILER_FUNCTION_TESTER_H_ | 5 #ifndef V8_CCTEST_COMPILER_FUNCTION_TESTER_H_ |
| 6 #define V8_CCTEST_COMPILER_FUNCTION_TESTER_H_ | 6 #define V8_CCTEST_COMPILER_FUNCTION_TESTER_H_ |
| 7 | 7 |
| 8 #include "src/ast/ast-numbering.h" | |
| 9 #include "src/compiler.h" | |
| 10 #include "src/compiler/linkage.h" | |
| 11 #include "src/compiler/pipeline.h" | |
| 12 #include "src/execution.h" | |
| 13 #include "src/full-codegen/full-codegen.h" | |
| 14 #include "src/handles.h" | 8 #include "src/handles.h" |
| 15 #include "src/objects-inl.h" | |
| 16 #include "src/parsing/parse-info.h" | |
| 17 #include "src/parsing/parser.h" | |
| 18 #include "src/parsing/rewriter.h" | |
| 19 #include "test/cctest/cctest.h" | 9 #include "test/cctest/cctest.h" |
| 20 | 10 |
| 21 namespace v8 { | 11 namespace v8 { |
| 22 namespace internal { | 12 namespace internal { |
| 13 |
| 14 class CallInterfaceDescriptor; |
| 15 class Isolate; |
| 16 |
| 23 namespace compiler { | 17 namespace compiler { |
| 24 | 18 |
| 19 class Graph; |
| 20 |
| 25 class FunctionTester : public InitializedHandleScope { | 21 class FunctionTester : public InitializedHandleScope { |
| 26 public: | 22 public: |
| 27 explicit FunctionTester(const char* source, uint32_t flags = 0) | 23 explicit FunctionTester(const char* source, uint32_t flags = 0); |
| 28 : isolate(main_isolate()), | |
| 29 function((FLAG_allow_natives_syntax = true, NewFunction(source))), | |
| 30 flags_(flags) { | |
| 31 Compile(function); | |
| 32 const uint32_t supported_flags = | |
| 33 CompilationInfo::kNativeContextSpecializing | | |
| 34 CompilationInfo::kInliningEnabled; | |
| 35 CHECK_EQ(0u, flags_ & ~supported_flags); | |
| 36 } | |
| 37 | 24 |
| 38 FunctionTester(Graph* graph, int param_count) | 25 FunctionTester(Graph* graph, int param_count); |
| 39 : isolate(main_isolate()), | |
| 40 function(NewFunction(BuildFunction(param_count).c_str())), | |
| 41 flags_(0) { | |
| 42 CompileGraph(graph); | |
| 43 } | |
| 44 | 26 |
| 45 FunctionTester(Handle<Code> code, int param_count) | 27 FunctionTester(Handle<Code> code, int param_count); |
| 46 : isolate(main_isolate()), | |
| 47 function((FLAG_allow_natives_syntax = true, | |
| 48 NewFunction(BuildFunction(param_count).c_str()))), | |
| 49 flags_(0) { | |
| 50 Compile(function); | |
| 51 function->ReplaceCode(*code); | |
| 52 } | |
| 53 | 28 |
| 54 FunctionTester(const CallInterfaceDescriptor& descriptor, Handle<Code> code) | 29 FunctionTester(const CallInterfaceDescriptor& descriptor, Handle<Code> code); |
| 55 : FunctionTester(code, descriptor.GetParameterCount()) {} | |
| 56 | 30 |
| 57 Isolate* isolate; | 31 Isolate* isolate; |
| 58 Handle<JSFunction> function; | 32 Handle<JSFunction> function; |
| 59 | 33 |
| 60 MaybeHandle<Object> Call() { | 34 MaybeHandle<Object> Call(); |
| 61 return Execution::Call(isolate, function, undefined(), 0, nullptr); | 35 MaybeHandle<Object> Call(Handle<Object> a); |
| 62 } | 36 MaybeHandle<Object> Call(Handle<Object> a, Handle<Object> b); |
| 37 MaybeHandle<Object> Call(Handle<Object> a, Handle<Object> b, |
| 38 Handle<Object> c); |
| 39 MaybeHandle<Object> Call(Handle<Object> a, Handle<Object> b, Handle<Object> c, |
| 40 Handle<Object> d); |
| 63 | 41 |
| 64 MaybeHandle<Object> Call(Handle<Object> a) { | 42 void CheckThrows(Handle<Object> a, Handle<Object> b); |
| 65 Handle<Object> args[] = {a}; | |
| 66 return Execution::Call(isolate, function, undefined(), 1, args); | |
| 67 } | |
| 68 | |
| 69 MaybeHandle<Object> Call(Handle<Object> a, Handle<Object> b) { | |
| 70 Handle<Object> args[] = {a, b}; | |
| 71 return Execution::Call(isolate, function, undefined(), 2, args); | |
| 72 } | |
| 73 | |
| 74 MaybeHandle<Object> Call(Handle<Object> a, Handle<Object> b, | |
| 75 Handle<Object> c) { | |
| 76 Handle<Object> args[] = {a, b, c}; | |
| 77 return Execution::Call(isolate, function, undefined(), 3, args); | |
| 78 } | |
| 79 | |
| 80 MaybeHandle<Object> Call(Handle<Object> a, Handle<Object> b, Handle<Object> c, | |
| 81 Handle<Object> d) { | |
| 82 Handle<Object> args[] = {a, b, c, d}; | |
| 83 return Execution::Call(isolate, function, undefined(), 4, args); | |
| 84 } | |
| 85 | |
| 86 void CheckThrows(Handle<Object> a, Handle<Object> b) { | |
| 87 TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate)); | |
| 88 MaybeHandle<Object> no_result = Call(a, b); | |
| 89 CHECK(isolate->has_pending_exception()); | |
| 90 CHECK(try_catch.HasCaught()); | |
| 91 CHECK(no_result.is_null()); | |
| 92 isolate->OptionalRescheduleException(true); | |
| 93 } | |
| 94 | |
| 95 v8::Local<v8::Message> CheckThrowsReturnMessage(Handle<Object> a, | 43 v8::Local<v8::Message> CheckThrowsReturnMessage(Handle<Object> a, |
| 96 Handle<Object> b) { | 44 Handle<Object> b); |
| 97 TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate)); | |
| 98 MaybeHandle<Object> no_result = Call(a, b); | |
| 99 CHECK(isolate->has_pending_exception()); | |
| 100 CHECK(try_catch.HasCaught()); | |
| 101 CHECK(no_result.is_null()); | |
| 102 isolate->OptionalRescheduleException(true); | |
| 103 CHECK(!try_catch.Message().IsEmpty()); | |
| 104 return try_catch.Message(); | |
| 105 } | |
| 106 | |
| 107 void CheckCall(Handle<Object> expected, Handle<Object> a, Handle<Object> b, | 45 void CheckCall(Handle<Object> expected, Handle<Object> a, Handle<Object> b, |
| 108 Handle<Object> c, Handle<Object> d) { | 46 Handle<Object> c, Handle<Object> d) { |
| 109 Handle<Object> result = Call(a, b, c, d).ToHandleChecked(); | 47 Handle<Object> result = Call(a, b, c, d).ToHandleChecked(); |
| 110 CHECK(expected->SameValue(*result)); | 48 CHECK(expected->SameValue(*result)); |
| 111 } | 49 } |
| 112 | 50 |
| 113 void CheckCall(Handle<Object> expected, Handle<Object> a, Handle<Object> b, | 51 void CheckCall(Handle<Object> expected, Handle<Object> a, Handle<Object> b, |
| 114 Handle<Object> c) { | 52 Handle<Object> c) { |
| 115 return CheckCall(expected, a, b, c, undefined()); | 53 return CheckCall(expected, a, b, c, undefined()); |
| 116 } | 54 } |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 161 Handle<JSFunction> NewFunction(const char* source) { | 99 Handle<JSFunction> NewFunction(const char* source) { |
| 162 return Handle<JSFunction>::cast(v8::Utils::OpenHandle( | 100 return Handle<JSFunction>::cast(v8::Utils::OpenHandle( |
| 163 *v8::Local<v8::Function>::Cast(CompileRun(source)))); | 101 *v8::Local<v8::Function>::Cast(CompileRun(source)))); |
| 164 } | 102 } |
| 165 | 103 |
| 166 Handle<JSObject> NewObject(const char* source) { | 104 Handle<JSObject> NewObject(const char* source) { |
| 167 return Handle<JSObject>::cast(v8::Utils::OpenHandle( | 105 return Handle<JSObject>::cast(v8::Utils::OpenHandle( |
| 168 *v8::Local<v8::Object>::Cast(CompileRun(source)))); | 106 *v8::Local<v8::Object>::Cast(CompileRun(source)))); |
| 169 } | 107 } |
| 170 | 108 |
| 171 Handle<String> Val(const char* string) { | 109 Handle<String> Val(const char* string); |
| 172 return isolate->factory()->InternalizeUtf8String(string); | 110 Handle<Object> Val(double value); |
| 173 } | 111 Handle<Object> infinity(); |
| 174 | 112 Handle<Object> minus_infinity(); |
| 175 Handle<Object> Val(double value) { | 113 Handle<Object> nan(); |
| 176 return isolate->factory()->NewNumber(value); | 114 Handle<Object> undefined(); |
| 177 } | 115 Handle<Object> null(); |
| 178 | 116 Handle<Object> true_value(); |
| 179 Handle<Object> infinity() { return isolate->factory()->infinity_value(); } | 117 Handle<Object> false_value(); |
| 180 | |
| 181 Handle<Object> minus_infinity() { return Val(-V8_INFINITY); } | |
| 182 | |
| 183 Handle<Object> nan() { return isolate->factory()->nan_value(); } | |
| 184 | |
| 185 Handle<Object> undefined() { return isolate->factory()->undefined_value(); } | |
| 186 | |
| 187 Handle<Object> null() { return isolate->factory()->null_value(); } | |
| 188 | |
| 189 Handle<Object> true_value() { return isolate->factory()->true_value(); } | |
| 190 | |
| 191 Handle<Object> false_value() { return isolate->factory()->false_value(); } | |
| 192 | 118 |
| 193 static Handle<JSFunction> ForMachineGraph(Graph* graph, int param_count) { | 119 static Handle<JSFunction> ForMachineGraph(Graph* graph, int param_count) { |
| 194 JSFunction* p = NULL; | 120 JSFunction* p = NULL; |
| 195 { // because of the implicit handle scope of FunctionTester. | 121 { // because of the implicit handle scope of FunctionTester. |
| 196 FunctionTester f(graph, param_count); | 122 FunctionTester f(graph, param_count); |
| 197 p = *f.function; | 123 p = *f.function; |
| 198 } | 124 } |
| 199 return Handle<JSFunction>(p); // allocated in outer handle scope. | 125 return Handle<JSFunction>(p); // allocated in outer handle scope. |
| 200 } | 126 } |
| 201 | 127 |
| 202 private: | 128 private: |
| 203 uint32_t flags_; | 129 uint32_t flags_; |
| 204 | 130 |
| 205 Handle<JSFunction> Compile(Handle<JSFunction> function) { | 131 Handle<JSFunction> Compile(Handle<JSFunction> function); |
| 206 Zone zone(function->GetIsolate()->allocator()); | |
| 207 ParseInfo parse_info(&zone, function); | |
| 208 CompilationInfo info(&parse_info, function); | |
| 209 info.MarkAsDeoptimizationEnabled(); | |
| 210 | |
| 211 if (!FLAG_turbo_from_bytecode) { | |
| 212 CHECK(Parser::ParseStatic(info.parse_info())); | |
| 213 } | |
| 214 info.SetOptimizing(); | |
| 215 if (flags_ & CompilationInfo::kNativeContextSpecializing) { | |
| 216 info.MarkAsNativeContextSpecializing(); | |
| 217 } | |
| 218 if (flags_ & CompilationInfo::kInliningEnabled) { | |
| 219 info.MarkAsInliningEnabled(); | |
| 220 } | |
| 221 if (FLAG_turbo_from_bytecode) { | |
| 222 CHECK(Compiler::EnsureBytecode(&info)); | |
| 223 info.MarkAsOptimizeFromBytecode(); | |
| 224 } else { | |
| 225 CHECK(Compiler::Analyze(info.parse_info())); | |
| 226 CHECK(Compiler::EnsureDeoptimizationSupport(&info)); | |
| 227 } | |
| 228 JSFunction::EnsureLiterals(function); | |
| 229 | |
| 230 Handle<Code> code = Pipeline::GenerateCodeForTesting(&info); | |
| 231 CHECK(!code.is_null()); | |
| 232 info.dependencies()->Commit(code); | |
| 233 info.context()->native_context()->AddOptimizedCode(*code); | |
| 234 function->ReplaceCode(*code); | |
| 235 return function; | |
| 236 } | |
| 237 | |
| 238 std::string BuildFunction(int param_count) { | 132 std::string BuildFunction(int param_count) { |
| 239 std::string function_string = "(function("; | 133 std::string function_string = "(function("; |
| 240 if (param_count > 0) { | 134 if (param_count > 0) { |
| 241 function_string += 'a'; | 135 function_string += 'a'; |
| 242 for (int i = 1; i < param_count; i++) { | 136 for (int i = 1; i < param_count; i++) { |
| 243 function_string += ','; | 137 function_string += ','; |
| 244 function_string += static_cast<char>('a' + i); | 138 function_string += static_cast<char>('a' + i); |
| 245 } | 139 } |
| 246 } | 140 } |
| 247 function_string += "){})"; | 141 function_string += "){})"; |
| 248 return function_string; | 142 return function_string; |
| 249 } | 143 } |
| 250 | 144 |
| 251 // Compile the given machine graph instead of the source of the function | 145 // Compile the given machine graph instead of the source of the function |
| 252 // and replace the JSFunction's code with the result. | 146 // and replace the JSFunction's code with the result. |
| 253 Handle<JSFunction> CompileGraph(Graph* graph) { | 147 Handle<JSFunction> CompileGraph(Graph* graph); |
| 254 Zone zone(function->GetIsolate()->allocator()); | |
| 255 ParseInfo parse_info(&zone, function); | |
| 256 CompilationInfo info(&parse_info, function); | |
| 257 | |
| 258 CHECK(Parser::ParseStatic(info.parse_info())); | |
| 259 info.SetOptimizing(); | |
| 260 | |
| 261 Handle<Code> code = Pipeline::GenerateCodeForTesting(&info, graph); | |
| 262 CHECK(!code.is_null()); | |
| 263 function->ReplaceCode(*code); | |
| 264 return function; | |
| 265 } | |
| 266 }; | 148 }; |
| 267 } // namespace compiler | 149 } // namespace compiler |
| 268 } // namespace internal | 150 } // namespace internal |
| 269 } // namespace v8 | 151 } // namespace v8 |
| 270 | 152 |
| 271 #endif // V8_CCTEST_COMPILER_FUNCTION_TESTER_H_ | 153 #endif // V8_CCTEST_COMPILER_FUNCTION_TESTER_H_ |
| OLD | NEW |