Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(37)

Side by Side Diff: test/cctest/compiler/test-run-native-calls.cc

Issue 1263033004: [turbofan] Various fixes to allow unboxed doubles as arguments in registers and on the stack. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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 "src/codegen.h"
6 #include "src/compiler/linkage.h"
7 #include "src/compiler/machine-type.h"
8 #include "src/compiler/raw-machine-assembler.h"
9
10 #include "test/cctest/cctest.h"
11 #include "test/cctest/compiler/codegen-tester.h"
12 #include "test/cctest/compiler/graph-builder-tester.h"
13 #include "test/cctest/compiler/value-helper.h"
14
15 using namespace v8::base;
16 using namespace v8::internal;
17 using namespace v8::internal::compiler;
18
19 typedef RawMachineAssembler::Label MLabel;
20
21
22 #if V8_TURBOFAN_TARGET
23
24 namespace {
25 // Helper for allocating either an GP or FP reg, or the next stack slot.
26 struct Allocator {
27 Allocator(int* gp, int gpc, int* fp, int fpc)
28 : gp_count(gpc),
29 gp_offset(0),
30 gp_regs(gp),
31 fp_count(fpc),
32 fp_offset(0),
33 fp_regs(fp),
34 stack_offset(0) {}
35
36 int gp_count;
37 int gp_offset;
38 int* gp_regs;
39
40 int fp_count;
41 int fp_offset;
42 int* fp_regs;
43
44 int stack_offset;
45
46 LinkageLocation Next(MachineType type) {
47 if (IsFloatingPoint(type)) {
48 // Allocate a floating point register/stack location.
49 if (fp_offset < fp_count) {
50 return LinkageLocation::ForRegister(fp_regs[fp_offset++]);
51 } else {
52 int offset = -1 - stack_offset;
53 stack_offset += Words(type);
54 return LinkageLocation::ForCallerFrameSlot(offset);
55 }
56 } else {
57 // Allocate a general purpose register/stack location.
58 if (gp_offset < gp_count) {
59 return LinkageLocation::ForRegister(gp_regs[gp_offset++]);
60 } else {
61 int offset = -1 - stack_offset;
62 stack_offset += Words(type);
63 return LinkageLocation::ForCallerFrameSlot(offset);
64 }
65 }
66 }
67 bool IsFloatingPoint(MachineType type) {
68 return RepresentationOf(type) == kRepFloat32 ||
69 RepresentationOf(type) == kRepFloat64;
70 }
71 int Words(MachineType type) {
72 int size = ElementSizeOf(type);
73 return size <= kPointerSize ? 1 : size / kPointerSize;
74 }
75 void Reset() {
76 fp_offset = 0;
77 gp_offset = 0;
78 stack_offset = 0;
79 }
80 };
81
82
83 class RegisterConfig {
84 public:
85 RegisterConfig(Allocator& p, Allocator& r) : params(p), rets(r) {}
86
87 CallDescriptor* Create(Zone* zone, MachineSignature* msig) {
88 rets.Reset();
89 params.Reset();
90
91 LocationSignature::Builder locations(zone, msig->return_count(),
92 msig->parameter_count());
93 // Add return location(s).
94 const int return_count = static_cast<int>(locations.return_count_);
95 for (int i = 0; i < return_count; i++) {
96 locations.AddReturn(rets.Next(msig->GetReturn(i)));
97 }
98
99 // Add register and/or stack parameter(s).
100 const int parameter_count = static_cast<int>(msig->parameter_count());
101 for (int i = 0; i < parameter_count; i++) {
102 locations.AddParam(params.Next(msig->GetParam(i)));
103 }
104
105 const RegList kCalleeSaveRegisters = 0;
106 const RegList kCalleeSaveFPRegisters = 0;
107
108 MachineType target_type = compiler::kMachAnyTagged;
109 LinkageLocation target_loc = LinkageLocation::ForAnyRegister();
110 int stack_param_count = params.stack_offset;
111 return new (zone) CallDescriptor( // --
112 CallDescriptor::kCallCodeObject, // kind
113 target_type, // target MachineType
114 target_loc, // target location
115 msig, // machine_sig
116 locations.Build(), // location_sig
117 stack_param_count, // stack_parameter_count
118 compiler::Operator::kNoProperties, // properties
119 kCalleeSaveRegisters, // callee-saved registers
120 kCalleeSaveFPRegisters, // callee-saved fp regs
121 CallDescriptor::kNoFlags, // flags
122 "c-call");
123 }
124
125 private:
126 Allocator& params;
127 Allocator& rets;
128 };
129
130 } // namespace
131
132
133 static Handle<Code> CompileGraph(const char* name, CallDescriptor* desc,
134 Graph* graph, Schedule* schedule = nullptr) {
135 Isolate* isolate = CcTest::InitIsolateOnce();
136 Handle<Code> code =
137 Pipeline::GenerateCodeForTesting(isolate, desc, graph, schedule);
138 CHECK(!code.is_null());
139 #ifdef ENABLE_DISASSEMBLER
140 if (FLAG_print_opt_code) {
141 OFStream os(stdout);
142 code->Disassemble(name, os);
143 }
144 #endif
145 return code;
146 }
147
148
149 static Handle<Code> WrapWithCFunction(Handle<Code> inner,
150 CallDescriptor* desc) {
151 Zone zone;
152 MachineSignature* msig =
153 const_cast<MachineSignature*>(desc->GetMachineSignature());
154 int param_count = static_cast<int>(msig->parameter_count());
155 GraphAndBuilders caller(&zone);
156 {
157 GraphAndBuilders& b = caller;
158 Node* start = b.graph()->NewNode(b.common()->Start(param_count + 3));
159 b.graph()->SetStart(start);
160 Unique<HeapObject> unique = Unique<HeapObject>::CreateUninitialized(inner);
161 Node* target = b.graph()->NewNode(b.common()->HeapConstant(unique));
162
163 // Add arguments to the call.
164 Node** args = zone.NewArray<Node*>(param_count + 3);
165 int index = 0;
166 args[index++] = target;
167 for (int i = 0; i < param_count; i++) {
168 args[index] = b.graph()->NewNode(b.common()->Parameter(i), start);
169 index++;
170 }
171 args[index++] = start; // effect.
172 args[index++] = start; // control.
173
174 // Build the call and return nodes.
175 Node* call =
176 b.graph()->NewNode(b.common()->Call(desc), param_count + 3, args);
177 Node* ret = b.graph()->NewNode(b.common()->Return(), call, call, start);
178 b.graph()->SetEnd(ret);
179 }
180
181 CallDescriptor* cdesc = Linkage::GetSimplifiedCDescriptor(&zone, msig);
182
183 return CompileGraph("wrapper", cdesc, caller.graph());
184 }
185
186
187 static void TestInt32Sub(CallDescriptor* desc) {
188 Isolate* isolate = CcTest::InitIsolateOnce();
189 HandleScope scope(isolate);
190 Zone zone;
191 GraphAndBuilders inner(&zone);
192 {
193 // Build the add function.
194 GraphAndBuilders& b = inner;
195 Node* start = b.graph()->NewNode(b.common()->Start(5));
196 b.graph()->SetStart(start);
197 Node* p0 = b.graph()->NewNode(b.common()->Parameter(0), start);
198 Node* p1 = b.graph()->NewNode(b.common()->Parameter(1), start);
199 Node* add = b.graph()->NewNode(b.machine()->Int32Sub(), p0, p1);
200 Node* ret = b.graph()->NewNode(b.common()->Return(), add, start, start);
201 b.graph()->SetEnd(ret);
202 }
203
204 Handle<Code> inner_code = CompileGraph("Int32Sub", desc, inner.graph());
205 Handle<Code> wrapper = WrapWithCFunction(inner_code, desc);
206 MachineSignature* msig =
207 const_cast<MachineSignature*>(desc->GetMachineSignature());
208 CodeRunner<int32_t> runnable(isolate, wrapper,
209 CSignature::FromMachine(&zone, msig));
210
211 FOR_INT32_INPUTS(i) {
212 FOR_INT32_INPUTS(j) {
213 int32_t expected = static_cast<int32_t>(static_cast<uint32_t>(*i) -
214 static_cast<uint32_t>(*j));
215 int32_t result = runnable.Call(*i, *j);
216 CHECK_EQ(expected, result);
217 }
218 }
219 }
220
221
222 static void CopyTwentyInt32(CallDescriptor* desc) {
223 const int kNumParams = 20;
224 int32_t input[kNumParams];
225 int32_t output[kNumParams];
226 Isolate* isolate = CcTest::InitIsolateOnce();
227 HandleScope scope(isolate);
228 Handle<Code> inner = Handle<Code>::null();
229 {
230 // Writes all parameters into the output buffer.
231 Zone zone;
232 Graph graph(&zone);
233 RawMachineAssembler raw(isolate, &graph, desc);
234 Node* base = raw.PointerConstant(output);
235 for (int i = 0; i < kNumParams; i++) {
236 Node* offset = raw.Int32Constant(i * sizeof(int32_t));
237 raw.Store(kMachInt32, base, offset, raw.Parameter(i));
238 }
239 raw.Return(raw.Int32Constant(42));
240 inner = CompileGraph("CopyTwentyInt32", desc, &graph, raw.Export());
241 }
242
243 CSignature0<int32_t> csig;
244 Handle<Code> wrapper = Handle<Code>::null();
245 {
246 // Loads parameters from the input buffer and calls the above code.
247 Zone zone;
248 Graph graph(&zone);
249 CallDescriptor* cdesc = Linkage::GetSimplifiedCDescriptor(&zone, &csig);
250 RawMachineAssembler raw(isolate, &graph, cdesc);
251 Node* base = raw.PointerConstant(input);
252 Unique<HeapObject> unique = Unique<HeapObject>::CreateUninitialized(inner);
253 Node* target = raw.HeapConstant(unique);
254 Node** args = zone.NewArray<Node*>(kNumParams);
255 for (int i = 0; i < kNumParams; i++) {
256 Node* offset = raw.Int32Constant(i * sizeof(int32_t));
257 args[i] = raw.Load(kMachInt32, base, offset);
258 }
259
260 Node* call = raw.CallN(desc, target, args);
261 raw.Return(call);
262 wrapper =
263 CompileGraph("CopyTwentyInt32-wrapper", cdesc, &graph, raw.Export());
264 }
265
266 CodeRunner<int32_t> runnable(isolate, wrapper, &csig);
267
268 // Run the code, checking it correctly implements the memcpy.
269 for (int i = 0; i < 5; i++) {
270 uint32_t base = 1111111111u * i;
271 for (int j = 0; j < kNumParams; j++) {
272 input[j] = static_cast<int32_t>(base + 13 * j);
273 }
274
275 memset(output, 0, sizeof(output));
276 CHECK_EQ(42, runnable.Call());
277
278 for (int j = 0; j < kNumParams; j++) {
279 CHECK_EQ(input[j], output[j]);
280 }
281 }
282 }
283
284
285 TEST(Run_Int32Sub_all_allocatable_pairs) {
286 MachineType types[] = {kMachInt32, kMachInt32, kMachInt32};
287 MachineSignature sig(1, 2, types);
288 for (int r = 0; r < Register::kMaxNumAllocatableRegisters; r++) {
289 Zone zone;
290 for (int p0 = 0; p0 < Register::kMaxNumAllocatableRegisters; p0++) {
291 for (int p1 = 0; p1 < Register::kMaxNumAllocatableRegisters; p1++) {
292 if (p0 == p1) continue;
293 int parray[] = {p0, p1};
294 int rarray[] = {r};
295 Allocator params(parray, 2, nullptr, 0);
296 Allocator rets(rarray, 1, nullptr, 0);
297 RegisterConfig config(params, rets);
298 CallDescriptor* desc = config.Create(&zone, &sig);
299 TestInt32Sub(desc);
300 }
301 }
302 }
303 }
304
305
306 TEST(Run_Int32Sub_all_allocatable_single) {
307 MachineType types[] = {kMachInt32, kMachInt32, kMachInt32};
308 MachineSignature sig(1, 2, types);
309 for (int r = 0; r < Register::kMaxNumAllocatableRegisters; r++) {
310 Zone zone;
311 for (int p0 = 0; p0 < Register::kMaxNumAllocatableRegisters; p0++) {
312 int parray[] = {p0};
313 int rarray[] = {r};
314 Allocator params(parray, 1, nullptr, 0);
315 Allocator rets(rarray, 1, nullptr, 0);
316 RegisterConfig config(params, rets);
317 CallDescriptor* desc = config.Create(&zone, &sig);
318 TestInt32Sub(desc);
319 }
320 }
321 }
322
323
324 TEST(Run_CopyTwentyInt32_all_allocatable_pairs) {
325 MachineType types[] = {
326 kMachInt32, kMachInt32, kMachInt32, kMachInt32, kMachInt32, kMachInt32,
327 kMachInt32, kMachInt32, kMachInt32, kMachInt32, kMachInt32, kMachInt32,
328 kMachInt32, kMachInt32, kMachInt32, kMachInt32, kMachInt32, kMachInt32,
329 kMachInt32, kMachInt32, kMachInt32};
330 MachineSignature sig(1, 20, types);
331 for (int p0 = 0; p0 < Register::kMaxNumAllocatableRegisters; p0++) {
332 Zone zone;
333 for (int p1 = 0; p1 < Register::kMaxNumAllocatableRegisters; p1++) {
334 if (p0 == p1) continue;
335 int parray[] = {p0, p1};
336 int rarray[] = {0};
337 Allocator params(parray, 2, nullptr, 0);
338 Allocator rets(rarray, 1, nullptr, 0);
339 RegisterConfig config(params, rets);
340 CallDescriptor* desc = config.Create(&zone, &sig);
341 CopyTwentyInt32(desc);
342 }
343 }
344 }
345
346
347 #endif // V8_TURBOFAN_TARGET
OLDNEW
« src/compiler/raw-machine-assembler.h ('K') | « test/cctest/compiler/graph-builder-tester.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698