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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: test/cctest/compiler/test-run-native-calls.cc
diff --git a/test/cctest/compiler/test-run-native-calls.cc b/test/cctest/compiler/test-run-native-calls.cc
new file mode 100644
index 0000000000000000000000000000000000000000..ac85c9bdf2c0922e6b5802ec164a94d78cfb7d53
--- /dev/null
+++ b/test/cctest/compiler/test-run-native-calls.cc
@@ -0,0 +1,347 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/codegen.h"
+#include "src/compiler/linkage.h"
+#include "src/compiler/machine-type.h"
+#include "src/compiler/raw-machine-assembler.h"
+
+#include "test/cctest/cctest.h"
+#include "test/cctest/compiler/codegen-tester.h"
+#include "test/cctest/compiler/graph-builder-tester.h"
+#include "test/cctest/compiler/value-helper.h"
+
+using namespace v8::base;
+using namespace v8::internal;
+using namespace v8::internal::compiler;
+
+typedef RawMachineAssembler::Label MLabel;
+
+
+#if V8_TURBOFAN_TARGET
+
+namespace {
+// Helper for allocating either an GP or FP reg, or the next stack slot.
+struct Allocator {
+ Allocator(int* gp, int gpc, int* fp, int fpc)
+ : gp_count(gpc),
+ gp_offset(0),
+ gp_regs(gp),
+ fp_count(fpc),
+ fp_offset(0),
+ fp_regs(fp),
+ stack_offset(0) {}
+
+ int gp_count;
+ int gp_offset;
+ int* gp_regs;
+
+ int fp_count;
+ int fp_offset;
+ int* fp_regs;
+
+ int stack_offset;
+
+ LinkageLocation Next(MachineType type) {
+ if (IsFloatingPoint(type)) {
+ // Allocate a floating point register/stack location.
+ if (fp_offset < fp_count) {
+ return LinkageLocation::ForRegister(fp_regs[fp_offset++]);
+ } else {
+ int offset = -1 - stack_offset;
+ stack_offset += Words(type);
+ return LinkageLocation::ForCallerFrameSlot(offset);
+ }
+ } else {
+ // Allocate a general purpose register/stack location.
+ if (gp_offset < gp_count) {
+ return LinkageLocation::ForRegister(gp_regs[gp_offset++]);
+ } else {
+ int offset = -1 - stack_offset;
+ stack_offset += Words(type);
+ return LinkageLocation::ForCallerFrameSlot(offset);
+ }
+ }
+ }
+ bool IsFloatingPoint(MachineType type) {
+ return RepresentationOf(type) == kRepFloat32 ||
+ RepresentationOf(type) == kRepFloat64;
+ }
+ int Words(MachineType type) {
+ int size = ElementSizeOf(type);
+ return size <= kPointerSize ? 1 : size / kPointerSize;
+ }
+ void Reset() {
+ fp_offset = 0;
+ gp_offset = 0;
+ stack_offset = 0;
+ }
+};
+
+
+class RegisterConfig {
+ public:
+ RegisterConfig(Allocator& p, Allocator& r) : params(p), rets(r) {}
+
+ CallDescriptor* Create(Zone* zone, MachineSignature* msig) {
+ rets.Reset();
+ params.Reset();
+
+ LocationSignature::Builder locations(zone, msig->return_count(),
+ msig->parameter_count());
+ // Add return location(s).
+ const int return_count = static_cast<int>(locations.return_count_);
+ for (int i = 0; i < return_count; i++) {
+ locations.AddReturn(rets.Next(msig->GetReturn(i)));
+ }
+
+ // Add register and/or stack parameter(s).
+ const int parameter_count = static_cast<int>(msig->parameter_count());
+ for (int i = 0; i < parameter_count; i++) {
+ locations.AddParam(params.Next(msig->GetParam(i)));
+ }
+
+ const RegList kCalleeSaveRegisters = 0;
+ const RegList kCalleeSaveFPRegisters = 0;
+
+ MachineType target_type = compiler::kMachAnyTagged;
+ LinkageLocation target_loc = LinkageLocation::ForAnyRegister();
+ int stack_param_count = params.stack_offset;
+ return new (zone) CallDescriptor( // --
+ CallDescriptor::kCallCodeObject, // kind
+ target_type, // target MachineType
+ target_loc, // target location
+ msig, // machine_sig
+ locations.Build(), // location_sig
+ stack_param_count, // stack_parameter_count
+ compiler::Operator::kNoProperties, // properties
+ kCalleeSaveRegisters, // callee-saved registers
+ kCalleeSaveFPRegisters, // callee-saved fp regs
+ CallDescriptor::kNoFlags, // flags
+ "c-call");
+ }
+
+ private:
+ Allocator& params;
+ Allocator& rets;
+};
+
+} // namespace
+
+
+static Handle<Code> CompileGraph(const char* name, CallDescriptor* desc,
+ Graph* graph, Schedule* schedule = nullptr) {
+ Isolate* isolate = CcTest::InitIsolateOnce();
+ Handle<Code> code =
+ Pipeline::GenerateCodeForTesting(isolate, desc, graph, schedule);
+ CHECK(!code.is_null());
+#ifdef ENABLE_DISASSEMBLER
+ if (FLAG_print_opt_code) {
+ OFStream os(stdout);
+ code->Disassemble(name, os);
+ }
+#endif
+ return code;
+}
+
+
+static Handle<Code> WrapWithCFunction(Handle<Code> inner,
+ CallDescriptor* desc) {
+ Zone zone;
+ MachineSignature* msig =
+ const_cast<MachineSignature*>(desc->GetMachineSignature());
+ int param_count = static_cast<int>(msig->parameter_count());
+ GraphAndBuilders caller(&zone);
+ {
+ GraphAndBuilders& b = caller;
+ Node* start = b.graph()->NewNode(b.common()->Start(param_count + 3));
+ b.graph()->SetStart(start);
+ Unique<HeapObject> unique = Unique<HeapObject>::CreateUninitialized(inner);
+ Node* target = b.graph()->NewNode(b.common()->HeapConstant(unique));
+
+ // Add arguments to the call.
+ Node** args = zone.NewArray<Node*>(param_count + 3);
+ int index = 0;
+ args[index++] = target;
+ for (int i = 0; i < param_count; i++) {
+ args[index] = b.graph()->NewNode(b.common()->Parameter(i), start);
+ index++;
+ }
+ args[index++] = start; // effect.
+ args[index++] = start; // control.
+
+ // Build the call and return nodes.
+ Node* call =
+ b.graph()->NewNode(b.common()->Call(desc), param_count + 3, args);
+ Node* ret = b.graph()->NewNode(b.common()->Return(), call, call, start);
+ b.graph()->SetEnd(ret);
+ }
+
+ CallDescriptor* cdesc = Linkage::GetSimplifiedCDescriptor(&zone, msig);
+
+ return CompileGraph("wrapper", cdesc, caller.graph());
+}
+
+
+static void TestInt32Sub(CallDescriptor* desc) {
+ Isolate* isolate = CcTest::InitIsolateOnce();
+ HandleScope scope(isolate);
+ Zone zone;
+ GraphAndBuilders inner(&zone);
+ {
+ // Build the add function.
+ GraphAndBuilders& b = inner;
+ Node* start = b.graph()->NewNode(b.common()->Start(5));
+ b.graph()->SetStart(start);
+ Node* p0 = b.graph()->NewNode(b.common()->Parameter(0), start);
+ Node* p1 = b.graph()->NewNode(b.common()->Parameter(1), start);
+ Node* add = b.graph()->NewNode(b.machine()->Int32Sub(), p0, p1);
+ Node* ret = b.graph()->NewNode(b.common()->Return(), add, start, start);
+ b.graph()->SetEnd(ret);
+ }
+
+ Handle<Code> inner_code = CompileGraph("Int32Sub", desc, inner.graph());
+ Handle<Code> wrapper = WrapWithCFunction(inner_code, desc);
+ MachineSignature* msig =
+ const_cast<MachineSignature*>(desc->GetMachineSignature());
+ CodeRunner<int32_t> runnable(isolate, wrapper,
+ CSignature::FromMachine(&zone, msig));
+
+ FOR_INT32_INPUTS(i) {
+ FOR_INT32_INPUTS(j) {
+ int32_t expected = static_cast<int32_t>(static_cast<uint32_t>(*i) -
+ static_cast<uint32_t>(*j));
+ int32_t result = runnable.Call(*i, *j);
+ CHECK_EQ(expected, result);
+ }
+ }
+}
+
+
+static void CopyTwentyInt32(CallDescriptor* desc) {
+ const int kNumParams = 20;
+ int32_t input[kNumParams];
+ int32_t output[kNumParams];
+ Isolate* isolate = CcTest::InitIsolateOnce();
+ HandleScope scope(isolate);
+ Handle<Code> inner = Handle<Code>::null();
+ {
+ // Writes all parameters into the output buffer.
+ Zone zone;
+ Graph graph(&zone);
+ RawMachineAssembler raw(isolate, &graph, desc);
+ Node* base = raw.PointerConstant(output);
+ for (int i = 0; i < kNumParams; i++) {
+ Node* offset = raw.Int32Constant(i * sizeof(int32_t));
+ raw.Store(kMachInt32, base, offset, raw.Parameter(i));
+ }
+ raw.Return(raw.Int32Constant(42));
+ inner = CompileGraph("CopyTwentyInt32", desc, &graph, raw.Export());
+ }
+
+ CSignature0<int32_t> csig;
+ Handle<Code> wrapper = Handle<Code>::null();
+ {
+ // Loads parameters from the input buffer and calls the above code.
+ Zone zone;
+ Graph graph(&zone);
+ CallDescriptor* cdesc = Linkage::GetSimplifiedCDescriptor(&zone, &csig);
+ RawMachineAssembler raw(isolate, &graph, cdesc);
+ Node* base = raw.PointerConstant(input);
+ Unique<HeapObject> unique = Unique<HeapObject>::CreateUninitialized(inner);
+ Node* target = raw.HeapConstant(unique);
+ Node** args = zone.NewArray<Node*>(kNumParams);
+ for (int i = 0; i < kNumParams; i++) {
+ Node* offset = raw.Int32Constant(i * sizeof(int32_t));
+ args[i] = raw.Load(kMachInt32, base, offset);
+ }
+
+ Node* call = raw.CallN(desc, target, args);
+ raw.Return(call);
+ wrapper =
+ CompileGraph("CopyTwentyInt32-wrapper", cdesc, &graph, raw.Export());
+ }
+
+ CodeRunner<int32_t> runnable(isolate, wrapper, &csig);
+
+ // Run the code, checking it correctly implements the memcpy.
+ for (int i = 0; i < 5; i++) {
+ uint32_t base = 1111111111u * i;
+ for (int j = 0; j < kNumParams; j++) {
+ input[j] = static_cast<int32_t>(base + 13 * j);
+ }
+
+ memset(output, 0, sizeof(output));
+ CHECK_EQ(42, runnable.Call());
+
+ for (int j = 0; j < kNumParams; j++) {
+ CHECK_EQ(input[j], output[j]);
+ }
+ }
+}
+
+
+TEST(Run_Int32Sub_all_allocatable_pairs) {
+ MachineType types[] = {kMachInt32, kMachInt32, kMachInt32};
+ MachineSignature sig(1, 2, types);
+ for (int r = 0; r < Register::kMaxNumAllocatableRegisters; r++) {
+ Zone zone;
+ for (int p0 = 0; p0 < Register::kMaxNumAllocatableRegisters; p0++) {
+ for (int p1 = 0; p1 < Register::kMaxNumAllocatableRegisters; p1++) {
+ if (p0 == p1) continue;
+ int parray[] = {p0, p1};
+ int rarray[] = {r};
+ Allocator params(parray, 2, nullptr, 0);
+ Allocator rets(rarray, 1, nullptr, 0);
+ RegisterConfig config(params, rets);
+ CallDescriptor* desc = config.Create(&zone, &sig);
+ TestInt32Sub(desc);
+ }
+ }
+ }
+}
+
+
+TEST(Run_Int32Sub_all_allocatable_single) {
+ MachineType types[] = {kMachInt32, kMachInt32, kMachInt32};
+ MachineSignature sig(1, 2, types);
+ for (int r = 0; r < Register::kMaxNumAllocatableRegisters; r++) {
+ Zone zone;
+ for (int p0 = 0; p0 < Register::kMaxNumAllocatableRegisters; p0++) {
+ int parray[] = {p0};
+ int rarray[] = {r};
+ Allocator params(parray, 1, nullptr, 0);
+ Allocator rets(rarray, 1, nullptr, 0);
+ RegisterConfig config(params, rets);
+ CallDescriptor* desc = config.Create(&zone, &sig);
+ TestInt32Sub(desc);
+ }
+ }
+}
+
+
+TEST(Run_CopyTwentyInt32_all_allocatable_pairs) {
+ MachineType types[] = {
+ kMachInt32, kMachInt32, kMachInt32, kMachInt32, kMachInt32, kMachInt32,
+ kMachInt32, kMachInt32, kMachInt32, kMachInt32, kMachInt32, kMachInt32,
+ kMachInt32, kMachInt32, kMachInt32, kMachInt32, kMachInt32, kMachInt32,
+ kMachInt32, kMachInt32, kMachInt32};
+ MachineSignature sig(1, 20, types);
+ for (int p0 = 0; p0 < Register::kMaxNumAllocatableRegisters; p0++) {
+ Zone zone;
+ for (int p1 = 0; p1 < Register::kMaxNumAllocatableRegisters; p1++) {
+ if (p0 == p1) continue;
+ int parray[] = {p0, p1};
+ int rarray[] = {0};
+ Allocator params(parray, 2, nullptr, 0);
+ Allocator rets(rarray, 1, nullptr, 0);
+ RegisterConfig config(params, rets);
+ CallDescriptor* desc = config.Create(&zone, &sig);
+ CopyTwentyInt32(desc);
+ }
+ }
+}
+
+
+#endif // V8_TURBOFAN_TARGET
« 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