Line data Source code
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
3 : // found in the LICENSE file.
4 :
5 : #include "test/cctest/compiler/function-tester.h"
6 :
7 : #include "src/api.h"
8 : #include "src/ast/ast-numbering.h"
9 : #include "src/compilation-info.h"
10 : #include "src/compiler.h"
11 : #include "src/compiler/linkage.h"
12 : #include "src/compiler/pipeline.h"
13 : #include "src/execution.h"
14 : #include "src/handles.h"
15 : #include "src/objects-inl.h"
16 : #include "src/parsing/parse-info.h"
17 : #include "test/cctest/cctest.h"
18 :
19 : namespace v8 {
20 : namespace internal {
21 : namespace compiler {
22 :
23 972 : FunctionTester::FunctionTester(const char* source, uint32_t flags)
24 : : isolate(main_isolate()),
25 : function((FLAG_allow_natives_syntax = true, NewFunction(source))),
26 972 : flags_(flags) {
27 972 : Compile(function);
28 : const uint32_t supported_flags = CompilationInfo::kInliningEnabled;
29 972 : CHECK_EQ(0u, flags_ & ~supported_flags);
30 972 : }
31 :
32 6 : FunctionTester::FunctionTester(Graph* graph, int param_count)
33 : : isolate(main_isolate()),
34 12 : function(NewFunction(BuildFunction(param_count).c_str())),
35 18 : flags_(0) {
36 6 : CompileGraph(graph);
37 6 : }
38 :
39 576 : FunctionTester::FunctionTester(Handle<Code> code, int param_count)
40 : : isolate(main_isolate()),
41 : function((FLAG_allow_natives_syntax = true,
42 1152 : NewFunction(BuildFunction(param_count).c_str()))),
43 1728 : flags_(0) {
44 576 : CHECK(!code.is_null());
45 576 : Compile(function);
46 576 : function->set_code(*code);
47 576 : }
48 :
49 66 : FunctionTester::FunctionTester(Handle<Code> code) : FunctionTester(code, 0) {}
50 :
51 6 : void FunctionTester::CheckThrows(Handle<Object> a) {
52 6 : TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate));
53 6 : MaybeHandle<Object> no_result = Call(a);
54 6 : CHECK(isolate->has_pending_exception());
55 6 : CHECK(try_catch.HasCaught());
56 6 : CHECK(no_result.is_null());
57 6 : isolate->OptionalRescheduleException(true);
58 6 : }
59 :
60 90 : void FunctionTester::CheckThrows(Handle<Object> a, Handle<Object> b) {
61 90 : TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate));
62 90 : MaybeHandle<Object> no_result = Call(a, b);
63 90 : CHECK(isolate->has_pending_exception());
64 90 : CHECK(try_catch.HasCaught());
65 90 : CHECK(no_result.is_null());
66 90 : isolate->OptionalRescheduleException(true);
67 90 : }
68 :
69 42 : v8::Local<v8::Message> FunctionTester::CheckThrowsReturnMessage(
70 : Handle<Object> a, Handle<Object> b) {
71 42 : TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate));
72 42 : MaybeHandle<Object> no_result = Call(a, b);
73 42 : CHECK(isolate->has_pending_exception());
74 42 : CHECK(try_catch.HasCaught());
75 42 : CHECK(no_result.is_null());
76 42 : isolate->OptionalRescheduleException(true);
77 84 : CHECK(!try_catch.Message().IsEmpty());
78 42 : return try_catch.Message();
79 : }
80 :
81 452196 : void FunctionTester::CheckCall(Handle<Object> expected, Handle<Object> a,
82 : Handle<Object> b, Handle<Object> c,
83 : Handle<Object> d) {
84 904392 : Handle<Object> result = Call(a, b, c, d).ToHandleChecked();
85 452196 : CHECK(expected->SameValue(*result));
86 452196 : }
87 :
88 1614 : Handle<JSFunction> FunctionTester::NewFunction(const char* source) {
89 : return Handle<JSFunction>::cast(v8::Utils::OpenHandle(
90 1614 : *v8::Local<v8::Function>::Cast(CompileRun(source))));
91 : }
92 :
93 756 : Handle<JSObject> FunctionTester::NewObject(const char* source) {
94 : return Handle<JSObject>::cast(
95 756 : v8::Utils::OpenHandle(*v8::Local<v8::Object>::Cast(CompileRun(source))));
96 : }
97 :
98 1956 : Handle<String> FunctionTester::Val(const char* string) {
99 1956 : return isolate->factory()->InternalizeUtf8String(string);
100 : }
101 :
102 3858 : Handle<Object> FunctionTester::Val(double value) {
103 3864 : return isolate->factory()->NewNumber(value);
104 : }
105 :
106 6 : Handle<Object> FunctionTester::infinity() {
107 12 : return isolate->factory()->infinity_value();
108 : }
109 :
110 12 : Handle<Object> FunctionTester::minus_infinity() { return Val(-V8_INFINITY); }
111 :
112 276 : Handle<Object> FunctionTester::nan() { return isolate->factory()->nan_value(); }
113 :
114 1258764 : Handle<Object> FunctionTester::undefined() {
115 2969862 : return isolate->factory()->undefined_value();
116 : }
117 :
118 60 : Handle<Object> FunctionTester::null() {
119 120 : return isolate->factory()->null_value();
120 : }
121 :
122 56430 : Handle<Object> FunctionTester::true_value() {
123 112860 : return isolate->factory()->true_value();
124 : }
125 :
126 870 : Handle<Object> FunctionTester::false_value() {
127 1740 : return isolate->factory()->false_value();
128 : }
129 :
130 0 : Handle<JSFunction> FunctionTester::ForMachineGraph(Graph* graph,
131 : int param_count) {
132 : JSFunction* p = nullptr;
133 : { // because of the implicit handle scope of FunctionTester.
134 0 : FunctionTester f(graph, param_count);
135 : p = *f.function;
136 : }
137 0 : return Handle<JSFunction>(p); // allocated in outer handle scope.
138 : }
139 :
140 1548 : Handle<JSFunction> FunctionTester::Compile(Handle<JSFunction> function) {
141 : Handle<SharedFunctionInfo> shared(function->shared());
142 1548 : ParseInfo parse_info(shared);
143 : CompilationInfo info(parse_info.zone(), function->GetIsolate(), shared,
144 3096 : function);
145 :
146 1548 : if (flags_ & CompilationInfo::kInliningEnabled) {
147 : info.MarkAsInliningEnabled();
148 : }
149 :
150 1548 : CHECK(function->is_compiled() ||
151 : Compiler::Compile(function, Compiler::CLEAR_EXCEPTION));
152 1548 : CHECK(info.shared_info()->HasBytecodeArray());
153 1548 : JSFunction::EnsureLiterals(function);
154 :
155 1548 : Handle<Code> code = Pipeline::GenerateCodeForTesting(&info);
156 1548 : CHECK(!code.is_null());
157 1548 : info.dependencies()->Commit(code);
158 3096 : info.context()->native_context()->AddOptimizedCode(*code);
159 1548 : function->set_code(*code);
160 3096 : return function;
161 : }
162 :
163 : // Compile the given machine graph instead of the source of the function
164 : // and replace the JSFunction's code with the result.
165 6 : Handle<JSFunction> FunctionTester::CompileGraph(Graph* graph) {
166 : Handle<SharedFunctionInfo> shared(function->shared());
167 6 : ParseInfo parse_info(shared);
168 : CompilationInfo info(parse_info.zone(), function->GetIsolate(), shared,
169 12 : function);
170 :
171 6 : Handle<Code> code = Pipeline::GenerateCodeForTesting(&info, graph);
172 6 : CHECK(!code.is_null());
173 6 : function->set_code(*code);
174 12 : return function;
175 : }
176 :
177 : } // namespace compiler
178 : } // namespace internal
179 71154 : } // namespace v8
|