blob: 7f27a6f8f5ac61eb1f55aa45c351b10adc797562 [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// 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
Ben Murdoch61f157c2016-09-16 13:49:30 +01005#include "src/compiler/code-assembler.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006#include "src/isolate.h"
Ben Murdoch61f157c2016-09-16 13:49:30 +01007#include "test/cctest/compiler/code-assembler-tester.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008#include "test/cctest/compiler/function-tester.h"
9
10namespace v8 {
11namespace internal {
12namespace compiler {
13
Ben Murdoch61f157c2016-09-16 13:49:30 +010014typedef CodeAssemblerTesterImpl<CodeAssembler> CodeAssemblerTester;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015
Ben Murdoch61f157c2016-09-16 13:49:30 +010016namespace {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000017
Ben Murdoch61f157c2016-09-16 13:49:30 +010018Node* SmiTag(CodeAssemblerTester& m, Node* value) {
19 int32_t constant_value;
20 if (m.ToInt32Constant(value, constant_value) &&
21 Smi::IsValid(constant_value)) {
22 return m.SmiConstant(Smi::FromInt(constant_value));
23 }
24 return m.WordShl(value, m.SmiShiftBitsConstant());
25}
Ben Murdochda12d292016-06-02 14:46:10 +010026
Ben Murdoch61f157c2016-09-16 13:49:30 +010027Node* UndefinedConstant(CodeAssemblerTester& m) {
28 return m.LoadRoot(Heap::kUndefinedValueRootIndex);
29}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000030
Ben Murdoch61f157c2016-09-16 13:49:30 +010031Node* LoadObjectField(CodeAssemblerTester& m, Node* object, int offset,
32 MachineType rep = MachineType::AnyTagged()) {
33 return m.Load(rep, object, m.IntPtrConstant(offset - kHeapObjectTag));
34}
35
36} // namespace
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000037
38TEST(SimpleSmiReturn) {
39 Isolate* isolate(CcTest::InitIsolateOnce());
40 VoidDescriptor descriptor(isolate);
Ben Murdoch61f157c2016-09-16 13:49:30 +010041 CodeAssemblerTester m(isolate, descriptor);
42 m.Return(SmiTag(m, m.Int32Constant(37)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000043 Handle<Code> code = m.GenerateCode();
44 FunctionTester ft(descriptor, code);
45 MaybeHandle<Object> result = ft.Call();
46 CHECK_EQ(37, Handle<Smi>::cast(result.ToHandleChecked())->value());
47}
48
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000049TEST(SimpleIntPtrReturn) {
50 Isolate* isolate(CcTest::InitIsolateOnce());
51 VoidDescriptor descriptor(isolate);
Ben Murdoch61f157c2016-09-16 13:49:30 +010052 CodeAssemblerTester m(isolate, descriptor);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000053 int test;
54 m.Return(m.IntPtrConstant(reinterpret_cast<intptr_t>(&test)));
55 Handle<Code> code = m.GenerateCode();
56 FunctionTester ft(descriptor, code);
57 MaybeHandle<Object> result = ft.Call();
58 CHECK_EQ(reinterpret_cast<intptr_t>(&test),
59 reinterpret_cast<intptr_t>(*result.ToHandleChecked()));
60}
61
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000062TEST(SimpleDoubleReturn) {
63 Isolate* isolate(CcTest::InitIsolateOnce());
64 VoidDescriptor descriptor(isolate);
Ben Murdoch61f157c2016-09-16 13:49:30 +010065 CodeAssemblerTester m(isolate, descriptor);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000066 m.Return(m.NumberConstant(0.5));
67 Handle<Code> code = m.GenerateCode();
68 FunctionTester ft(descriptor, code);
69 MaybeHandle<Object> result = ft.Call();
70 CHECK_EQ(0.5, Handle<HeapNumber>::cast(result.ToHandleChecked())->value());
71}
72
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000073TEST(SimpleCallRuntime1Arg) {
74 Isolate* isolate(CcTest::InitIsolateOnce());
75 VoidDescriptor descriptor(isolate);
Ben Murdoch61f157c2016-09-16 13:49:30 +010076 CodeAssemblerTester m(isolate, descriptor);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000077 Node* context = m.HeapConstant(Handle<Context>(isolate->native_context()));
Ben Murdoch61f157c2016-09-16 13:49:30 +010078 Node* b = SmiTag(m, m.Int32Constant(0));
Ben Murdochda12d292016-06-02 14:46:10 +010079 m.Return(m.CallRuntime(Runtime::kNumberToSmi, context, b));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000080 Handle<Code> code = m.GenerateCode();
81 FunctionTester ft(descriptor, code);
82 MaybeHandle<Object> result = ft.Call();
Ben Murdochda12d292016-06-02 14:46:10 +010083 CHECK_EQ(0, Handle<Smi>::cast(result.ToHandleChecked())->value());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000084}
85
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000086TEST(SimpleTailCallRuntime1Arg) {
87 Isolate* isolate(CcTest::InitIsolateOnce());
88 VoidDescriptor descriptor(isolate);
Ben Murdoch61f157c2016-09-16 13:49:30 +010089 CodeAssemblerTester m(isolate, descriptor);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000090 Node* context = m.HeapConstant(Handle<Context>(isolate->native_context()));
Ben Murdoch61f157c2016-09-16 13:49:30 +010091 Node* b = SmiTag(m, m.Int32Constant(0));
Ben Murdochda12d292016-06-02 14:46:10 +010092 m.TailCallRuntime(Runtime::kNumberToSmi, context, b);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000093 Handle<Code> code = m.GenerateCode();
94 FunctionTester ft(descriptor, code);
95 MaybeHandle<Object> result = ft.Call();
Ben Murdochda12d292016-06-02 14:46:10 +010096 CHECK_EQ(0, Handle<Smi>::cast(result.ToHandleChecked())->value());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000097}
98
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000099TEST(SimpleCallRuntime2Arg) {
100 Isolate* isolate(CcTest::InitIsolateOnce());
101 VoidDescriptor descriptor(isolate);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100102 CodeAssemblerTester m(isolate, descriptor);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000103 Node* context = m.HeapConstant(Handle<Context>(isolate->native_context()));
Ben Murdoch61f157c2016-09-16 13:49:30 +0100104 Node* a = SmiTag(m, m.Int32Constant(2));
105 Node* b = SmiTag(m, m.Int32Constant(4));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000106 m.Return(m.CallRuntime(Runtime::kMathPow, context, a, b));
107 Handle<Code> code = m.GenerateCode();
108 FunctionTester ft(descriptor, code);
109 MaybeHandle<Object> result = ft.Call();
110 CHECK_EQ(16, Handle<Smi>::cast(result.ToHandleChecked())->value());
111}
112
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000113TEST(SimpleTailCallRuntime2Arg) {
114 Isolate* isolate(CcTest::InitIsolateOnce());
115 VoidDescriptor descriptor(isolate);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100116 CodeAssemblerTester m(isolate, descriptor);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000117 Node* context = m.HeapConstant(Handle<Context>(isolate->native_context()));
Ben Murdoch61f157c2016-09-16 13:49:30 +0100118 Node* a = SmiTag(m, m.Int32Constant(2));
119 Node* b = SmiTag(m, m.Int32Constant(4));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000120 m.TailCallRuntime(Runtime::kMathPow, context, a, b);
121 Handle<Code> code = m.GenerateCode();
122 FunctionTester ft(descriptor, code);
123 MaybeHandle<Object> result = ft.Call();
124 CHECK_EQ(16, Handle<Smi>::cast(result.ToHandleChecked())->value());
125}
126
Ben Murdoch61f157c2016-09-16 13:49:30 +0100127namespace {
128
129Handle<JSFunction> CreateSumAllArgumentsFunction(FunctionTester& ft) {
130 const char* source =
131 "(function() {\n"
132 " var sum = 0 + this;\n"
133 " for (var i = 0; i < arguments.length; i++) {\n"
134 " sum += arguments[i];\n"
135 " }\n"
136 " return sum;\n"
137 "})";
138 return ft.NewFunction(source);
139}
140
141} // namespace
142
143TEST(SimpleCallJSFunction0Arg) {
144 Isolate* isolate(CcTest::InitIsolateOnce());
145 const int kNumParams = 1;
146 CodeAssemblerTester m(isolate, kNumParams);
147 {
148 Node* function = m.Parameter(0);
149 Node* context = m.Parameter(kNumParams + 2);
150
151 Node* receiver = SmiTag(m, m.Int32Constant(42));
152
153 Callable callable = CodeFactory::Call(isolate);
154 Node* result = m.CallJS(callable, context, function, receiver);
155 m.Return(result);
156 }
157 Handle<Code> code = m.GenerateCode();
158 FunctionTester ft(code, kNumParams);
159
160 Handle<JSFunction> sum = CreateSumAllArgumentsFunction(ft);
161 MaybeHandle<Object> result = ft.Call(sum);
162 CHECK_EQ(Smi::FromInt(42), *result.ToHandleChecked());
163}
164
165TEST(SimpleCallJSFunction1Arg) {
166 Isolate* isolate(CcTest::InitIsolateOnce());
167 const int kNumParams = 2;
168 CodeAssemblerTester m(isolate, kNumParams);
169 {
170 Node* function = m.Parameter(0);
171 Node* context = m.Parameter(1);
172
173 Node* receiver = SmiTag(m, m.Int32Constant(42));
174 Node* a = SmiTag(m, m.Int32Constant(13));
175
176 Callable callable = CodeFactory::Call(isolate);
177 Node* result = m.CallJS(callable, context, function, receiver, a);
178 m.Return(result);
179 }
180 Handle<Code> code = m.GenerateCode();
181 FunctionTester ft(code, kNumParams);
182
183 Handle<JSFunction> sum = CreateSumAllArgumentsFunction(ft);
184 MaybeHandle<Object> result = ft.Call(sum);
185 CHECK_EQ(Smi::FromInt(55), *result.ToHandleChecked());
186}
187
188TEST(SimpleCallJSFunction2Arg) {
189 Isolate* isolate(CcTest::InitIsolateOnce());
190 const int kNumParams = 2;
191 CodeAssemblerTester m(isolate, kNumParams);
192 {
193 Node* function = m.Parameter(0);
194 Node* context = m.Parameter(1);
195
196 Node* receiver = SmiTag(m, m.Int32Constant(42));
197 Node* a = SmiTag(m, m.Int32Constant(13));
198 Node* b = SmiTag(m, m.Int32Constant(153));
199
200 Callable callable = CodeFactory::Call(isolate);
201 Node* result = m.CallJS(callable, context, function, receiver, a, b);
202 m.Return(result);
203 }
204 Handle<Code> code = m.GenerateCode();
205 FunctionTester ft(code, kNumParams);
206
207 Handle<JSFunction> sum = CreateSumAllArgumentsFunction(ft);
208 MaybeHandle<Object> result = ft.Call(sum);
209 CHECK_EQ(Smi::FromInt(208), *result.ToHandleChecked());
210}
211
Ben Murdoch097c5b22016-05-18 11:27:45 +0100212TEST(VariableMerge1) {
213 Isolate* isolate(CcTest::InitIsolateOnce());
214 VoidDescriptor descriptor(isolate);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100215 CodeAssemblerTester m(isolate, descriptor);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100216 CodeStubAssembler::Variable var1(&m, MachineRepresentation::kTagged);
217 CodeStubAssembler::Label l1(&m), l2(&m), merge(&m);
218 Node* temp = m.Int32Constant(0);
219 var1.Bind(temp);
220 m.Branch(m.Int32Constant(1), &l1, &l2);
221 m.Bind(&l1);
222 CHECK_EQ(var1.value(), temp);
223 m.Goto(&merge);
224 m.Bind(&l2);
225 CHECK_EQ(var1.value(), temp);
226 m.Goto(&merge);
227 m.Bind(&merge);
228 CHECK_EQ(var1.value(), temp);
229}
230
231TEST(VariableMerge2) {
232 Isolate* isolate(CcTest::InitIsolateOnce());
233 VoidDescriptor descriptor(isolate);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100234 CodeAssemblerTester m(isolate, descriptor);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100235 CodeStubAssembler::Variable var1(&m, MachineRepresentation::kTagged);
236 CodeStubAssembler::Label l1(&m), l2(&m), merge(&m);
237 Node* temp = m.Int32Constant(0);
238 var1.Bind(temp);
239 m.Branch(m.Int32Constant(1), &l1, &l2);
240 m.Bind(&l1);
241 CHECK_EQ(var1.value(), temp);
242 m.Goto(&merge);
243 m.Bind(&l2);
244 Node* temp2 = m.Int32Constant(2);
245 var1.Bind(temp2);
246 CHECK_EQ(var1.value(), temp2);
247 m.Goto(&merge);
248 m.Bind(&merge);
249 CHECK_NE(var1.value(), temp);
250}
251
252TEST(VariableMerge3) {
253 Isolate* isolate(CcTest::InitIsolateOnce());
254 VoidDescriptor descriptor(isolate);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100255 CodeAssemblerTester m(isolate, descriptor);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100256 CodeStubAssembler::Variable var1(&m, MachineRepresentation::kTagged);
257 CodeStubAssembler::Variable var2(&m, MachineRepresentation::kTagged);
258 CodeStubAssembler::Label l1(&m), l2(&m), merge(&m);
259 Node* temp = m.Int32Constant(0);
260 var1.Bind(temp);
261 var2.Bind(temp);
262 m.Branch(m.Int32Constant(1), &l1, &l2);
263 m.Bind(&l1);
264 CHECK_EQ(var1.value(), temp);
265 m.Goto(&merge);
266 m.Bind(&l2);
267 Node* temp2 = m.Int32Constant(2);
268 var1.Bind(temp2);
269 CHECK_EQ(var1.value(), temp2);
270 m.Goto(&merge);
271 m.Bind(&merge);
272 CHECK_NE(var1.value(), temp);
273 CHECK_NE(var1.value(), temp2);
274 CHECK_EQ(var2.value(), temp);
275}
276
277TEST(VariableMergeBindFirst) {
278 Isolate* isolate(CcTest::InitIsolateOnce());
279 VoidDescriptor descriptor(isolate);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100280 CodeAssemblerTester m(isolate, descriptor);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100281 CodeStubAssembler::Variable var1(&m, MachineRepresentation::kTagged);
282 CodeStubAssembler::Label l1(&m), l2(&m), merge(&m, &var1), end(&m);
283 Node* temp = m.Int32Constant(0);
284 var1.Bind(temp);
285 m.Branch(m.Int32Constant(1), &l1, &l2);
286 m.Bind(&l1);
287 CHECK_EQ(var1.value(), temp);
288 m.Goto(&merge);
289 m.Bind(&merge);
290 CHECK(var1.value() != temp);
291 CHECK(var1.value() != nullptr);
292 m.Goto(&end);
293 m.Bind(&l2);
294 Node* temp2 = m.Int32Constant(2);
295 var1.Bind(temp2);
296 CHECK_EQ(var1.value(), temp2);
297 m.Goto(&merge);
298 m.Bind(&end);
299 CHECK(var1.value() != temp);
300 CHECK(var1.value() != nullptr);
301}
302
303TEST(VariableMergeSwitch) {
304 Isolate* isolate(CcTest::InitIsolateOnce());
305 VoidDescriptor descriptor(isolate);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100306 CodeAssemblerTester m(isolate, descriptor);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100307 CodeStubAssembler::Variable var1(&m, MachineRepresentation::kTagged);
308 CodeStubAssembler::Label l1(&m), l2(&m), default_label(&m);
309 CodeStubAssembler::Label* labels[] = {&l1, &l2};
310 int32_t values[] = {1, 2};
311 Node* temp = m.Int32Constant(0);
312 var1.Bind(temp);
313 m.Switch(m.Int32Constant(2), &default_label, values, labels, 2);
314 m.Bind(&l1);
315 DCHECK_EQ(temp, var1.value());
316 m.Return(temp);
317 m.Bind(&l2);
318 DCHECK_EQ(temp, var1.value());
319 m.Return(temp);
320 m.Bind(&default_label);
321 DCHECK_EQ(temp, var1.value());
322 m.Return(temp);
323}
324
Ben Murdochda12d292016-06-02 14:46:10 +0100325TEST(SplitEdgeBranchMerge) {
326 Isolate* isolate(CcTest::InitIsolateOnce());
327 VoidDescriptor descriptor(isolate);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100328 CodeAssemblerTester m(isolate, descriptor);
Ben Murdochda12d292016-06-02 14:46:10 +0100329 CodeStubAssembler::Label l1(&m), merge(&m);
330 m.Branch(m.Int32Constant(1), &l1, &merge);
331 m.Bind(&l1);
332 m.Goto(&merge);
333 m.Bind(&merge);
334 USE(m.GenerateCode());
335}
336
337TEST(SplitEdgeSwitchMerge) {
338 Isolate* isolate(CcTest::InitIsolateOnce());
339 VoidDescriptor descriptor(isolate);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100340 CodeAssemblerTester m(isolate, descriptor);
Ben Murdochda12d292016-06-02 14:46:10 +0100341 CodeStubAssembler::Label l1(&m), l2(&m), l3(&m), default_label(&m);
342 CodeStubAssembler::Label* labels[] = {&l1, &l2};
343 int32_t values[] = {1, 2};
344 m.Branch(m.Int32Constant(1), &l3, &l1);
345 m.Bind(&l3);
346 m.Switch(m.Int32Constant(2), &default_label, values, labels, 2);
347 m.Bind(&l1);
348 m.Goto(&l2);
349 m.Bind(&l2);
350 m.Goto(&default_label);
351 m.Bind(&default_label);
352 USE(m.GenerateCode());
353}
354
Ben Murdochc5610432016-08-08 18:44:38 +0100355TEST(TestToConstant) {
356 Isolate* isolate(CcTest::InitIsolateOnce());
357 VoidDescriptor descriptor(isolate);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100358 CodeAssemblerTester m(isolate, descriptor);
Ben Murdochc5610432016-08-08 18:44:38 +0100359 int32_t value32;
360 int64_t value64;
361 Node* a = m.Int32Constant(5);
362 CHECK(m.ToInt32Constant(a, value32));
363 CHECK(m.ToInt64Constant(a, value64));
364
365 a = m.Int64Constant(static_cast<int64_t>(1) << 32);
366 CHECK(!m.ToInt32Constant(a, value32));
367 CHECK(m.ToInt64Constant(a, value64));
368
369 a = m.Int64Constant(13);
370 CHECK(m.ToInt32Constant(a, value32));
371 CHECK(m.ToInt64Constant(a, value64));
372
Ben Murdoch61f157c2016-09-16 13:49:30 +0100373 a = UndefinedConstant(m);
Ben Murdochc5610432016-08-08 18:44:38 +0100374 CHECK(!m.ToInt32Constant(a, value32));
375 CHECK(!m.ToInt64Constant(a, value64));
376
Ben Murdoch61f157c2016-09-16 13:49:30 +0100377 a = UndefinedConstant(m);
Ben Murdochc5610432016-08-08 18:44:38 +0100378 CHECK(!m.ToInt32Constant(a, value32));
379 CHECK(!m.ToInt64Constant(a, value64));
380}
381
Ben Murdoch61f157c2016-09-16 13:49:30 +0100382TEST(DeferredCodePhiHints) {
383 typedef compiler::Node Node;
384 typedef CodeStubAssembler::Label Label;
385 typedef CodeStubAssembler::Variable Variable;
386 Isolate* isolate(CcTest::InitIsolateOnce());
387 VoidDescriptor descriptor(isolate);
388 CodeAssemblerTester m(isolate, descriptor);
389 Label block1(&m, Label::kDeferred);
390 m.Goto(&block1);
391 m.Bind(&block1);
392 {
393 Variable var_object(&m, MachineRepresentation::kTagged);
394 Label loop(&m, &var_object);
395 var_object.Bind(m.IntPtrConstant(0));
396 m.Goto(&loop);
397 m.Bind(&loop);
398 {
399 Node* map = LoadObjectField(m, var_object.value(), JSObject::kMapOffset);
400 var_object.Bind(map);
401 m.Goto(&loop);
402 }
403 }
404 CHECK(!m.GenerateCode().is_null());
405}
406
407TEST(TestOutOfScopeVariable) {
408 typedef CodeStubAssembler::Label Label;
409 typedef CodeStubAssembler::Variable Variable;
410 Isolate* isolate(CcTest::InitIsolateOnce());
411 VoidDescriptor descriptor(isolate);
412 CodeAssemblerTester m(isolate, descriptor);
413 Label block1(&m);
414 Label block2(&m);
415 Label block3(&m);
416 Label block4(&m);
417 m.Branch(m.WordEqual(m.Parameter(0), m.IntPtrConstant(0)), &block1, &block4);
418 m.Bind(&block4);
419 {
420 Variable var_object(&m, MachineRepresentation::kTagged);
421 m.Branch(m.WordEqual(m.Parameter(0), m.IntPtrConstant(0)), &block2,
422 &block3);
423
424 m.Bind(&block2);
425 var_object.Bind(m.IntPtrConstant(55));
426 m.Goto(&block1);
427
428 m.Bind(&block3);
429 var_object.Bind(m.IntPtrConstant(66));
430 m.Goto(&block1);
431 }
432 m.Bind(&block1);
433 CHECK(!m.GenerateCode().is_null());
434}
435
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000436} // namespace compiler
437} // namespace internal
438} // namespace v8