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-inl.h"
8 : #include "src/assembler.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/handles.h"
14 : #include "src/objects-inl.h"
15 : #include "src/optimized-compilation-info.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 785 : FunctionTester::FunctionTester(const char* source, uint32_t flags)
24 : : isolate(main_isolate()),
25 : canonical(isolate),
26 : function((FLAG_allow_natives_syntax = true, NewFunction(source))),
27 785 : flags_(flags) {
28 785 : Compile(function);
29 : const uint32_t supported_flags = OptimizedCompilationInfo::kInliningEnabled;
30 785 : CHECK_EQ(0u, flags_ & ~supported_flags);
31 785 : }
32 :
33 0 : FunctionTester::FunctionTester(Graph* graph, int param_count)
34 : : isolate(main_isolate()),
35 : canonical(isolate),
36 0 : function(NewFunction(BuildFunction(param_count).c_str())),
37 0 : flags_(0) {
38 0 : CompileGraph(graph);
39 0 : }
40 :
41 1070 : FunctionTester::FunctionTester(Handle<Code> code, int param_count)
42 : : isolate(main_isolate()),
43 : canonical(isolate),
44 : function((FLAG_allow_natives_syntax = true,
45 2140 : NewFunction(BuildFunction(param_count).c_str()))),
46 3210 : flags_(0) {
47 1070 : CHECK(!code.is_null());
48 1070 : Compile(function);
49 1070 : function->set_code(*code);
50 1070 : }
51 :
52 55 : FunctionTester::FunctionTester(Handle<Code> code) : FunctionTester(code, 0) {}
53 :
54 5 : void FunctionTester::CheckThrows(Handle<Object> a) {
55 5 : TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate));
56 5 : MaybeHandle<Object> no_result = Call(a);
57 5 : CHECK(isolate->has_pending_exception());
58 5 : CHECK(try_catch.HasCaught());
59 5 : CHECK(no_result.is_null());
60 5 : isolate->OptionalRescheduleException(true);
61 5 : }
62 :
63 75 : void FunctionTester::CheckThrows(Handle<Object> a, Handle<Object> b) {
64 75 : TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate));
65 75 : MaybeHandle<Object> no_result = Call(a, b);
66 75 : CHECK(isolate->has_pending_exception());
67 75 : CHECK(try_catch.HasCaught());
68 75 : CHECK(no_result.is_null());
69 75 : isolate->OptionalRescheduleException(true);
70 75 : }
71 :
72 35 : v8::Local<v8::Message> FunctionTester::CheckThrowsReturnMessage(
73 : Handle<Object> a, Handle<Object> b) {
74 35 : TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate));
75 35 : MaybeHandle<Object> no_result = Call(a, b);
76 35 : CHECK(isolate->has_pending_exception());
77 35 : CHECK(try_catch.HasCaught());
78 35 : CHECK(no_result.is_null());
79 35 : isolate->OptionalRescheduleException(true);
80 70 : CHECK(!try_catch.Message().IsEmpty());
81 35 : return try_catch.Message();
82 : }
83 :
84 368200 : void FunctionTester::CheckCall(Handle<Object> expected, Handle<Object> a,
85 : Handle<Object> b, Handle<Object> c,
86 : Handle<Object> d) {
87 736400 : Handle<Object> result = Call(a, b, c, d).ToHandleChecked();
88 368200 : CHECK(expected->SameValue(*result));
89 368200 : }
90 :
91 1905 : Handle<JSFunction> FunctionTester::NewFunction(const char* source) {
92 : return Handle<JSFunction>::cast(v8::Utils::OpenHandle(
93 1905 : *v8::Local<v8::Function>::Cast(CompileRun(source))));
94 : }
95 :
96 560 : Handle<JSObject> FunctionTester::NewObject(const char* source) {
97 : return Handle<JSObject>::cast(
98 560 : v8::Utils::OpenHandle(*v8::Local<v8::Object>::Cast(CompileRun(source))));
99 : }
100 :
101 1510 : Handle<String> FunctionTester::Val(const char* string) {
102 1510 : return isolate->factory()->InternalizeUtf8String(string);
103 : }
104 :
105 3175 : Handle<Object> FunctionTester::Val(double value) {
106 3180 : return isolate->factory()->NewNumber(value);
107 : }
108 :
109 5 : Handle<Object> FunctionTester::infinity() {
110 10 : return isolate->factory()->infinity_value();
111 : }
112 :
113 10 : Handle<Object> FunctionTester::minus_infinity() { return Val(-V8_INFINITY); }
114 :
115 230 : Handle<Object> FunctionTester::nan() { return isolate->factory()->nan_value(); }
116 :
117 1044640 : Handle<Object> FunctionTester::undefined() {
118 2457595 : return isolate->factory()->undefined_value();
119 : }
120 :
121 15 : Handle<Object> FunctionTester::null() {
122 30 : return isolate->factory()->null_value();
123 : }
124 :
125 38545 : Handle<Object> FunctionTester::true_value() {
126 77090 : return isolate->factory()->true_value();
127 : }
128 :
129 645 : Handle<Object> FunctionTester::false_value() {
130 1290 : return isolate->factory()->false_value();
131 : }
132 :
133 0 : Handle<JSFunction> FunctionTester::ForMachineGraph(Graph* graph,
134 : int param_count) {
135 : JSFunction p;
136 : { // because of the implicit handle scope of FunctionTester.
137 0 : FunctionTester f(graph, param_count);
138 : p = *f.function;
139 : }
140 : return Handle<JSFunction>(
141 0 : p, p->GetIsolate()); // allocated in outer handle scope.
142 : }
143 :
144 1855 : Handle<JSFunction> FunctionTester::Compile(Handle<JSFunction> function) {
145 7420 : Handle<SharedFunctionInfo> shared(function->shared(), isolate);
146 1855 : IsCompiledScope is_compiled_scope(shared->is_compiled_scope());
147 1855 : CHECK(is_compiled_scope.is_compiled() ||
148 : Compiler::Compile(function, Compiler::CLEAR_EXCEPTION,
149 : &is_compiled_scope));
150 :
151 3710 : Zone zone(isolate->allocator(), ZONE_NAME);
152 3710 : OptimizedCompilationInfo info(&zone, isolate, shared, function);
153 :
154 1855 : if (flags_ & OptimizedCompilationInfo::kInliningEnabled) {
155 : info.MarkAsInliningEnabled();
156 : }
157 :
158 1855 : CHECK(info.shared_info()->HasBytecodeArray());
159 1855 : JSFunction::EnsureFeedbackVector(function);
160 :
161 : Handle<Code> code =
162 3710 : Pipeline::GenerateCodeForTesting(&info, isolate).ToHandleChecked();
163 1855 : info.native_context()->AddOptimizedCode(*code);
164 1855 : function->set_code(*code);
165 3710 : return function;
166 : }
167 :
168 : // Compile the given machine graph instead of the source of the function
169 : // and replace the JSFunction's code with the result.
170 0 : Handle<JSFunction> FunctionTester::CompileGraph(Graph* graph) {
171 0 : Handle<SharedFunctionInfo> shared(function->shared(), isolate);
172 0 : Zone zone(isolate->allocator(), ZONE_NAME);
173 0 : OptimizedCompilationInfo info(&zone, isolate, shared, function);
174 :
175 0 : auto call_descriptor = Linkage::ComputeIncoming(&zone, &info);
176 : Handle<Code> code =
177 : Pipeline::GenerateCodeForTesting(&info, isolate, call_descriptor, graph,
178 0 : AssemblerOptions::Default(isolate))
179 0 : .ToHandleChecked();
180 0 : function->set_code(*code);
181 0 : return function;
182 : }
183 :
184 : } // namespace compiler
185 : } // namespace internal
186 85011 : } // namespace v8
|