blob: b8fce7a1d400cf51f829cd67032b5b3740f4b17d [file] [log] [blame]
Ben Murdochda12d292016-06-02 14:46:10 +01001// 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
3// found in the LICENSE file.
4
5#include "src/v8.h"
6
7#include "src/interpreter/interpreter-intrinsics.h"
8#include "test/cctest/interpreter/interpreter-tester.h"
9
10namespace v8 {
11namespace internal {
12namespace interpreter {
13
14namespace {
15
16class InvokeIntrinsicHelper {
17 public:
18 InvokeIntrinsicHelper(Isolate* isolate, Zone* zone,
19 Runtime::FunctionId function_id)
20 : isolate_(isolate),
21 zone_(zone),
22 factory_(isolate->factory()),
23 function_id_(function_id) {}
24
25 template <class... A>
26 Handle<Object> Invoke(A... args) {
27 CHECK(IntrinsicsHelper::IsSupported(function_id_));
28 BytecodeArrayBuilder builder(isolate_, zone_, sizeof...(args), 0, 0);
29 builder.CallRuntime(function_id_, builder.Parameter(0), sizeof...(args))
30 .Return();
31 InterpreterTester tester(isolate_, builder.ToBytecodeArray());
Ben Murdoch61f157c2016-09-16 13:49:30 +010032 auto callable = tester.GetCallable<A...>();
Ben Murdochda12d292016-06-02 14:46:10 +010033 return callable(args...).ToHandleChecked();
34 }
35
36 Handle<Object> NewObject(const char* script) {
37 return v8::Utils::OpenHandle(*CompileRun(script));
38 }
39
40 Handle<Object> Undefined() { return factory_->undefined_value(); }
41 Handle<Object> Null() { return factory_->null_value(); }
42
43 private:
44 Isolate* isolate_;
45 Zone* zone_;
46 Factory* factory_;
47 Runtime::FunctionId function_id_;
48};
49
50} // namespace
51
52TEST(IsJSReceiver) {
53 HandleAndZoneScope handles;
54
55 InvokeIntrinsicHelper helper(handles.main_isolate(), handles.main_zone(),
56 Runtime::kInlineIsJSReceiver);
57 Factory* factory = handles.main_isolate()->factory();
58
59 CHECK_EQ(*factory->true_value(),
60 *helper.Invoke(helper.NewObject("new Date()")));
61 CHECK_EQ(*factory->true_value(),
62 *helper.Invoke(helper.NewObject("(function() {})")));
63 CHECK_EQ(*factory->true_value(), *helper.Invoke(helper.NewObject("([1])")));
64 CHECK_EQ(*factory->true_value(), *helper.Invoke(helper.NewObject("({})")));
65 CHECK_EQ(*factory->true_value(), *helper.Invoke(helper.NewObject("(/x/)")));
66 CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.Undefined()));
67 CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.Null()));
68 CHECK_EQ(*factory->false_value(),
69 *helper.Invoke(helper.NewObject("'string'")));
70 CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.NewObject("42")));
71}
72
73TEST(IsArray) {
74 HandleAndZoneScope handles;
75
76 InvokeIntrinsicHelper helper(handles.main_isolate(), handles.main_zone(),
77 Runtime::kInlineIsArray);
78 Factory* factory = handles.main_isolate()->factory();
79
80 CHECK_EQ(*factory->false_value(),
81 *helper.Invoke(helper.NewObject("new Date()")));
82 CHECK_EQ(*factory->false_value(),
83 *helper.Invoke(helper.NewObject("(function() {})")));
84 CHECK_EQ(*factory->true_value(), *helper.Invoke(helper.NewObject("([1])")));
85 CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.NewObject("({})")));
86 CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.NewObject("(/x/)")));
87 CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.Undefined()));
88 CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.Null()));
89 CHECK_EQ(*factory->false_value(),
90 *helper.Invoke(helper.NewObject("'string'")));
91 CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.NewObject("42")));
92}
93
Ben Murdoch61f157c2016-09-16 13:49:30 +010094TEST(IsJSProxy) {
95 HandleAndZoneScope handles;
96
97 InvokeIntrinsicHelper helper(handles.main_isolate(), handles.main_zone(),
98 Runtime::kInlineIsJSProxy);
99 Factory* factory = handles.main_isolate()->factory();
100
101 CHECK_EQ(*factory->false_value(),
102 *helper.Invoke(helper.NewObject("new Date()")));
103 CHECK_EQ(*factory->false_value(),
104 *helper.Invoke(helper.NewObject("(function() {})")));
105 CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.NewObject("([1])")));
106 CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.NewObject("({})")));
107 CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.NewObject("(/x/)")));
108 CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.Undefined()));
109 CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.Null()));
110 CHECK_EQ(*factory->false_value(),
111 *helper.Invoke(helper.NewObject("'string'")));
112 CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.NewObject("42")));
113 CHECK_EQ(*factory->true_value(),
114 *helper.Invoke(helper.NewObject("new Proxy({},{})")));
115}
116
117TEST(IsRegExp) {
118 HandleAndZoneScope handles;
119
120 InvokeIntrinsicHelper helper(handles.main_isolate(), handles.main_zone(),
121 Runtime::kInlineIsRegExp);
122 Factory* factory = handles.main_isolate()->factory();
123
124 CHECK_EQ(*factory->false_value(),
125 *helper.Invoke(helper.NewObject("new Date()")));
126 CHECK_EQ(*factory->false_value(),
127 *helper.Invoke(helper.NewObject("(function() {})")));
128 CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.NewObject("([1])")));
129 CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.NewObject("({})")));
130 CHECK_EQ(*factory->true_value(), *helper.Invoke(helper.NewObject("(/x/)")));
131 CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.Undefined()));
132 CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.Null()));
133 CHECK_EQ(*factory->false_value(),
134 *helper.Invoke(helper.NewObject("'string'")));
135 CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.NewObject("42")));
136}
137
138TEST(IsTypedArray) {
139 HandleAndZoneScope handles;
140
141 InvokeIntrinsicHelper helper(handles.main_isolate(), handles.main_zone(),
142 Runtime::kInlineIsTypedArray);
143 Factory* factory = handles.main_isolate()->factory();
144
145 CHECK_EQ(*factory->false_value(),
146 *helper.Invoke(helper.NewObject("new Date()")));
147 CHECK_EQ(*factory->false_value(),
148 *helper.Invoke(helper.NewObject("(function() {})")));
149 CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.NewObject("([1])")));
150 CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.NewObject("({})")));
151 CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.NewObject("(/x/)")));
152 CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.Undefined()));
153 CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.Null()));
154 CHECK_EQ(*factory->false_value(),
155 *helper.Invoke(helper.NewObject("'string'")));
156 CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.NewObject("42")));
157
158 CHECK_EQ(
159 *factory->true_value(),
160 *helper.Invoke(helper.NewObject("new Uint8Array(new ArrayBuffer(1));")));
161 CHECK_EQ(
162 *factory->true_value(),
163 *helper.Invoke(helper.NewObject("new Uint16Array(new ArrayBuffer(2));")));
164 CHECK_EQ(
165 *factory->true_value(),
166 *helper.Invoke(helper.NewObject("new Int32Array(new ArrayBuffer(4));")));
167}
168
169TEST(IsSmi) {
170 HandleAndZoneScope handles;
171
172 InvokeIntrinsicHelper helper(handles.main_isolate(), handles.main_zone(),
173 Runtime::kInlineIsSmi);
174 Factory* factory = handles.main_isolate()->factory();
175
176 CHECK_EQ(*factory->false_value(),
177 *helper.Invoke(helper.NewObject("new Date()")));
178 CHECK_EQ(*factory->false_value(),
179 *helper.Invoke(helper.NewObject("(function() {})")));
180 CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.NewObject("([1])")));
181 CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.NewObject("({})")));
182 CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.NewObject("(/x/)")));
183 CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.Undefined()));
184 CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.Null()));
185 CHECK_EQ(*factory->false_value(),
186 *helper.Invoke(helper.NewObject("'string'")));
187 CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.NewObject("42.2")));
188 CHECK_EQ(*factory->false_value(),
189 *helper.Invoke(helper.NewObject("4294967297")));
190 CHECK_EQ(*factory->true_value(), *helper.Invoke(helper.NewObject("42")));
191}
192
193TEST(Call) {
194 HandleAndZoneScope handles;
195 Isolate* isolate = handles.main_isolate();
196 Factory* factory = isolate->factory();
197 InvokeIntrinsicHelper helper(isolate, handles.main_zone(),
198 Runtime::kInlineCall);
199
200 CHECK_EQ(Smi::FromInt(20),
201 *helper.Invoke(helper.NewObject("(function() { return this.x; })"),
202 helper.NewObject("({ x: 20 })")));
203 CHECK_EQ(Smi::FromInt(50),
204 *helper.Invoke(helper.NewObject("(function(arg1) { return arg1; })"),
205 factory->undefined_value(),
206 handle(Smi::FromInt(50), isolate)));
207 CHECK_EQ(
208 Smi::FromInt(20),
209 *helper.Invoke(
210 helper.NewObject("(function(a, b, c) { return a + b + c; })"),
211 factory->undefined_value(), handle(Smi::FromInt(10), isolate),
212 handle(Smi::FromInt(7), isolate), handle(Smi::FromInt(3), isolate)));
213}
214
215TEST(IntrinsicAsStubCall) {
216 HandleAndZoneScope handles;
217 Isolate* isolate = handles.main_isolate();
218 Factory* factory = isolate->factory();
219 InvokeIntrinsicHelper to_number_helper(isolate, handles.main_zone(),
220 Runtime::kInlineToNumber);
221 CHECK_EQ(Smi::FromInt(46),
222 *to_number_helper.Invoke(to_number_helper.NewObject("'46'")));
223
224 InvokeIntrinsicHelper to_integer_helper(isolate, handles.main_zone(),
225 Runtime::kInlineToInteger);
226 CHECK_EQ(Smi::FromInt(502),
227 *to_integer_helper.Invoke(to_integer_helper.NewObject("502.67")));
228
229 InvokeIntrinsicHelper math_pow_helper(isolate, handles.main_zone(),
230 Runtime::kInlineMathPow);
231 CHECK(math_pow_helper
232 .Invoke(math_pow_helper.NewObject("3"),
233 math_pow_helper.NewObject("7"))
234 ->SameValue(Smi::FromInt(2187)));
235
236 InvokeIntrinsicHelper has_property_helper(isolate, handles.main_zone(),
237 Runtime::kInlineHasProperty);
238 CHECK_EQ(*factory->true_value(),
239 *has_property_helper.Invoke(
240 has_property_helper.NewObject("'x'"),
241 has_property_helper.NewObject("({ x: 20 })")));
242 CHECK_EQ(*factory->false_value(),
243 *has_property_helper.Invoke(
244 has_property_helper.NewObject("'y'"),
245 has_property_helper.NewObject("({ x: 20 })")));
246
247 InvokeIntrinsicHelper sub_string_helper(isolate, handles.main_zone(),
248 Runtime::kInlineSubString);
249 CHECK(sub_string_helper
250 .Invoke(sub_string_helper.NewObject("'foobar'"),
251 sub_string_helper.NewObject("3"),
252 sub_string_helper.NewObject("6"))
253 ->SameValue(*sub_string_helper.NewObject("'bar'")));
254}
255
256TEST(ValueOf) {
257 HandleAndZoneScope handles;
258 Isolate* isolate = handles.main_isolate();
259 Factory* factory = isolate->factory();
260 InvokeIntrinsicHelper helper(handles.main_isolate(), handles.main_zone(),
261 Runtime::kInlineValueOf);
262
263 CHECK_EQ(Smi::FromInt(1234), *helper.Invoke(helper.NewObject("1234")));
264 CHECK_EQ(Smi::FromInt(5678),
265 *helper.Invoke(helper.NewObject("new Object(5678)")));
266
267 CHECK_EQ(*factory->true_value(), *helper.Invoke(helper.NewObject("true")));
268 CHECK_EQ(*factory->false_value(),
269 *helper.Invoke(helper.NewObject("new Object(false)")));
270
271 CHECK(helper.Invoke(helper.NewObject("'foobar'"))
272 ->SameValue(*helper.NewObject("'foobar'")));
273 CHECK(helper.Invoke(helper.NewObject("new Object('foobar')"))
274 ->SameValue(*helper.NewObject("'foobar'")));
275}
276
Ben Murdochda12d292016-06-02 14:46:10 +0100277} // namespace interpreter
278} // namespace internal
279} // namespace v8