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/linkage.h"
10 : #include "src/compiler/pipeline.h"
11 : #include "src/execution.h"
12 : #include "src/handles.h"
13 : #include "src/objects-inl.h"
14 : #include "src/optimized-compilation-info.h"
15 : #include "src/parsing/parse-info.h"
16 : #include "test/cctest/cctest.h"
17 :
18 : namespace v8 {
19 : namespace internal {
20 : namespace compiler {
21 :
22 628 : FunctionTester::FunctionTester(const char* source, uint32_t flags)
23 : : isolate(main_isolate()),
24 : canonical(isolate),
25 : function((FLAG_allow_natives_syntax = true, NewFunction(source))),
26 1256 : flags_(flags) {
27 628 : Compile(function);
28 : const uint32_t supported_flags = OptimizedCompilationInfo::kInliningEnabled;
29 628 : CHECK_EQ(0u, flags_ & ~supported_flags);
30 628 : }
31 :
32 0 : FunctionTester::FunctionTester(Graph* graph, int param_count)
33 : : isolate(main_isolate()),
34 : canonical(isolate),
35 0 : function(NewFunction(BuildFunction(param_count).c_str())),
36 0 : flags_(0) {
37 0 : CompileGraph(graph);
38 0 : }
39 :
40 872 : FunctionTester::FunctionTester(Handle<Code> code, int param_count)
41 : : isolate(main_isolate()),
42 : canonical(isolate),
43 : function((FLAG_allow_natives_syntax = true,
44 1744 : NewFunction(BuildFunction(param_count).c_str()))),
45 2616 : flags_(0) {
46 872 : CHECK(!code.is_null());
47 872 : Compile(function);
48 872 : function->set_code(*code);
49 872 : }
50 :
51 44 : FunctionTester::FunctionTester(Handle<Code> code) : FunctionTester(code, 0) {}
52 :
53 4 : void FunctionTester::CheckThrows(Handle<Object> a) {
54 8 : TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate));
55 4 : MaybeHandle<Object> no_result = Call(a);
56 8 : CHECK(isolate->has_pending_exception());
57 4 : CHECK(try_catch.HasCaught());
58 4 : CHECK(no_result.is_null());
59 4 : isolate->OptionalRescheduleException(true);
60 4 : }
61 :
62 60 : void FunctionTester::CheckThrows(Handle<Object> a, Handle<Object> b) {
63 120 : TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate));
64 60 : MaybeHandle<Object> no_result = Call(a, b);
65 120 : CHECK(isolate->has_pending_exception());
66 60 : CHECK(try_catch.HasCaught());
67 60 : CHECK(no_result.is_null());
68 60 : isolate->OptionalRescheduleException(true);
69 60 : }
70 :
71 28 : v8::Local<v8::Message> FunctionTester::CheckThrowsReturnMessage(
72 : Handle<Object> a, Handle<Object> b) {
73 56 : TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate));
74 28 : MaybeHandle<Object> no_result = Call(a, b);
75 56 : CHECK(isolate->has_pending_exception());
76 28 : CHECK(try_catch.HasCaught());
77 28 : CHECK(no_result.is_null());
78 28 : isolate->OptionalRescheduleException(true);
79 56 : CHECK(!try_catch.Message().IsEmpty());
80 56 : return try_catch.Message();
81 : }
82 :
83 294560 : void FunctionTester::CheckCall(Handle<Object> expected, Handle<Object> a,
84 : Handle<Object> b, Handle<Object> c,
85 : Handle<Object> d) {
86 589120 : Handle<Object> result = Call(a, b, c, d).ToHandleChecked();
87 294560 : CHECK(expected->SameValue(*result));
88 294560 : }
89 :
90 40 : Handle<JSFunction> FunctionTester::NewFunction(const char* source) {
91 : return Handle<JSFunction>::cast(v8::Utils::OpenHandle(
92 40 : *v8::Local<v8::Function>::Cast(CompileRun(source))));
93 : }
94 :
95 448 : Handle<JSObject> FunctionTester::NewObject(const char* source) {
96 : return Handle<JSObject>::cast(
97 448 : v8::Utils::OpenHandle(*v8::Local<v8::Object>::Cast(CompileRun(source))));
98 : }
99 :
100 1208 : Handle<String> FunctionTester::Val(const char* string) {
101 1208 : return isolate->factory()->InternalizeUtf8String(string);
102 : }
103 :
104 2540 : Handle<Object> FunctionTester::Val(double value) {
105 2544 : return isolate->factory()->NewNumber(value);
106 : }
107 :
108 4 : Handle<Object> FunctionTester::infinity() {
109 8 : return isolate->factory()->infinity_value();
110 : }
111 :
112 8 : Handle<Object> FunctionTester::minus_infinity() { return Val(-V8_INFINITY); }
113 :
114 184 : Handle<Object> FunctionTester::nan() { return isolate->factory()->nan_value(); }
115 :
116 835728 : Handle<Object> FunctionTester::undefined() {
117 1966108 : return isolate->factory()->undefined_value();
118 : }
119 :
120 12 : Handle<Object> FunctionTester::null() {
121 24 : return isolate->factory()->null_value();
122 : }
123 :
124 30836 : Handle<Object> FunctionTester::true_value() {
125 61672 : return isolate->factory()->true_value();
126 : }
127 :
128 516 : Handle<Object> FunctionTester::false_value() {
129 1032 : return isolate->factory()->false_value();
130 : }
131 :
132 0 : Handle<JSFunction> FunctionTester::ForMachineGraph(Graph* graph,
133 : int param_count) {
134 : JSFunction p;
135 : { // because of the implicit handle scope of FunctionTester.
136 0 : FunctionTester f(graph, param_count);
137 : p = *f.function;
138 : }
139 : return Handle<JSFunction>(
140 0 : p, p->GetIsolate()); // allocated in outer handle scope.
141 : }
142 :
143 1500 : Handle<JSFunction> FunctionTester::Compile(Handle<JSFunction> function) {
144 3000 : Zone zone(isolate->allocator(), ZONE_NAME);
145 3000 : return Optimize(function, &zone, isolate, flags_);
146 : }
147 :
148 : // Compile the given machine graph instead of the source of the function
149 : // and replace the JSFunction's code with the result.
150 0 : Handle<JSFunction> FunctionTester::CompileGraph(Graph* graph) {
151 0 : Handle<SharedFunctionInfo> shared(function->shared(), isolate);
152 0 : Zone zone(isolate->allocator(), ZONE_NAME);
153 0 : OptimizedCompilationInfo info(&zone, isolate, shared, function);
154 :
155 0 : auto call_descriptor = Linkage::ComputeIncoming(&zone, &info);
156 : Handle<Code> code =
157 0 : Pipeline::GenerateCodeForTesting(&info, isolate, call_descriptor, graph,
158 0 : AssemblerOptions::Default(isolate))
159 : .ToHandleChecked();
160 0 : function->set_code(*code);
161 0 : return function;
162 : }
163 :
164 : } // namespace compiler
165 : } // namespace internal
166 79968 : } // namespace v8
|