LCOV - code coverage report
Current view: top level - test/cctest/compiler - test-run-retpoline.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 112 112 100.0 %
Date: 2019-01-20 Functions: 15 15 100.0 %

          Line data    Source code
       1             : // Copyright 2018 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/assembler-inl.h"
       6             : #include "src/code-stub-assembler.h"
       7             : #include "src/macro-assembler.h"
       8             : 
       9             : #include "test/cctest/cctest.h"
      10             : #include "test/cctest/compiler/code-assembler-tester.h"
      11             : #include "test/cctest/compiler/function-tester.h"
      12             : 
      13             : namespace v8 {
      14             : namespace internal {
      15             : namespace compiler {
      16             : namespace test_run_retpoline {
      17             : 
      18             : #define __ assembler.
      19             : 
      20             : namespace {
      21             : 
      22             : // Function that takes a number of pointer-sized integer arguments, calculates a
      23             : // weighted sum of them and returns it.
      24         320 : Handle<Code> BuildCallee(Isolate* isolate, CallDescriptor* call_descriptor) {
      25         160 :   CodeAssemblerTester tester(isolate, call_descriptor, "callee");
      26         160 :   CodeStubAssembler assembler(tester.state());
      27         160 :   int param_count = static_cast<int>(call_descriptor->StackParameterCount());
      28         320 :   Node* sum = __ IntPtrConstant(0);
      29         600 :   for (int i = 0; i < param_count; ++i) {
      30        1120 :     Node* product = __ IntPtrMul(__ Parameter(i), __ IntPtrConstant(i + 1));
      31         560 :     sum = __ IntPtrAdd(sum, product);
      32             :   }
      33         160 :   __ Return(sum);
      34         320 :   return tester.GenerateCodeCloseAndEscape();
      35             : }
      36             : 
      37             : // Function that tail-calls another function with a number of pointer-sized
      38             : // integer arguments.
      39         160 : Handle<Code> BuildCaller(Isolate* isolate, CallDescriptor* call_descriptor,
      40         160 :                          CallDescriptor* callee_descriptor, bool tail) {
      41         160 :   CodeAssemblerTester tester(isolate, call_descriptor, "caller");
      42         160 :   CodeStubAssembler assembler(tester.state());
      43             :   std::vector<Node*> params;
      44             :   // The first parameter is always the callee.
      45         160 :   Handle<Code> callee = BuildCallee(isolate, callee_descriptor);
      46             :   // defeat the instruction selector.
      47             :   CodeStubAssembler::Variable target_var(&assembler,
      48         320 :                                          MachineRepresentation::kTagged);
      49         160 :   CodeStubAssembler::Label t(&assembler), f(&assembler),
      50         160 :       end(&assembler, &target_var);
      51         320 :   __ Branch(__ Int32Constant(0), &t, &f);
      52         160 :   __ BIND(&t);
      53         160 :   target_var.Bind(__ HeapConstant(callee));
      54         160 :   __ Goto(&end);
      55         160 :   __ BIND(&f);
      56         160 :   target_var.Bind(__ HeapConstant(callee));
      57         160 :   __ Goto(&end);
      58         160 :   __ BIND(&end);
      59         320 :   params.push_back(target_var.value());
      60             : 
      61         160 :   int param_count = static_cast<int>(callee_descriptor->StackParameterCount());
      62         440 :   for (int i = 0; i < param_count; ++i) {
      63         840 :     params.push_back(__ IntPtrConstant(i));
      64             :   }
      65             :   DCHECK_EQ(param_count + 1, params.size());
      66         160 :   if (tail) {
      67             :     tester.raw_assembler_for_testing()->TailCallN(
      68         160 :         callee_descriptor, param_count + 1, params.data());
      69             :   } else {
      70             :     Node* result = tester.raw_assembler_for_testing()->CallN(
      71         160 :         callee_descriptor, param_count + 1, params.data());
      72          80 :     __ Return(result);
      73             :   }
      74         320 :   return tester.GenerateCodeCloseAndEscape();
      75             : }
      76             : 
      77             : // Setup function, which calls "caller".
      78         160 : Handle<Code> BuildSetupFunction(Isolate* isolate,
      79         160 :                                 CallDescriptor* caller_descriptor,
      80             :                                 CallDescriptor* callee_descriptor, bool tail) {
      81         160 :   CodeAssemblerTester tester(isolate, 0);
      82         160 :   CodeStubAssembler assembler(tester.state());
      83             :   std::vector<Node*> params;
      84             :   // The first parameter is always the callee.
      85             :   params.push_back(__ HeapConstant(
      86         480 :       BuildCaller(isolate, caller_descriptor, callee_descriptor, tail)));
      87             :   // Set up arguments for "Caller".
      88         160 :   int param_count = static_cast<int>(caller_descriptor->StackParameterCount());
      89         400 :   for (int i = 0; i < param_count; ++i) {
      90             :     // Use values that are different from the ones we will pass to this
      91             :     // function's callee later.
      92         720 :     params.push_back(__ IntPtrConstant(i + 42));
      93             :   }
      94             :   DCHECK_EQ(param_count + 1, params.size());
      95             :   Node* raw_result = tester.raw_assembler_for_testing()->CallN(
      96         320 :       caller_descriptor, param_count + 1, params.data());
      97         320 :   __ Return(__ SmiTag(raw_result));
      98         320 :   return tester.GenerateCodeCloseAndEscape();
      99             : }
     100             : 
     101         320 : CallDescriptor* CreateDescriptorForStackArguments(Zone* zone,
     102             :                                                   int stack_param_count) {
     103             :   LocationSignature::Builder locations(zone, 1,
     104         320 :                                        static_cast<size_t>(stack_param_count));
     105             : 
     106             :   locations.AddReturn(LinkageLocation::ForRegister(kReturnRegister0.code(),
     107             :                                                    MachineType::IntPtr()));
     108             : 
     109         840 :   for (int i = 0; i < stack_param_count; ++i) {
     110             :     locations.AddParam(LinkageLocation::ForCallerFrameSlot(
     111         520 :         i - stack_param_count, MachineType::IntPtr()));
     112             :   }
     113             : 
     114             :   return new (zone)
     115             :       CallDescriptor(CallDescriptor::kCallCodeObject,  // kind
     116             :                      MachineType::AnyTagged(),         // target MachineType
     117             :                      LinkageLocation::ForAnyRegister(
     118             :                          MachineType::AnyTagged()),  // target location
     119             :                      locations.Build(),              // location_sig
     120             :                      stack_param_count,              // stack_parameter_count
     121             :                      Operator::kNoProperties,        // properties
     122             :                      kNoCalleeSaved,                 // callee-saved registers
     123             :                      kNoCalleeSaved,                 // callee-saved fp
     124         640 :                      CallDescriptor::kRetpoline);    // flags
     125             : }
     126             : 
     127             : // Test a tail call from a caller with n parameters to a callee with m
     128             : // parameters. All parameters are pointer-sized.
     129         160 : void TestHelper(int n, int m, bool tail) {
     130         160 :   HandleAndZoneScope scope;
     131         160 :   Isolate* isolate = scope.main_isolate();
     132         320 :   CanonicalHandleScope canonical(isolate);
     133             :   Zone* zone = scope.main_zone();
     134             :   CallDescriptor* caller_descriptor =
     135         160 :       CreateDescriptorForStackArguments(zone, n);
     136             :   CallDescriptor* callee_descriptor =
     137         160 :       CreateDescriptorForStackArguments(zone, m);
     138             :   Handle<Code> setup =
     139         160 :       BuildSetupFunction(isolate, caller_descriptor, callee_descriptor, tail);
     140         160 :   FunctionTester ft(setup, 0);
     141         320 :   Handle<Object> result = ft.Call().ToHandleChecked();
     142             :   int expected = 0;
     143         160 :   for (int i = 0; i < m; ++i) expected += (i + 1) * i;
     144         480 :   CHECK_EQ(expected, Handle<Smi>::cast(result)->value());
     145         160 : }
     146             : 
     147             : }  // namespace
     148             : 
     149             : #undef __
     150             : 
     151       28342 : TEST(RetpolineOddEven) {
     152           5 :   TestHelper(1, 0, false);
     153           5 :   TestHelper(1, 2, false);
     154           5 :   TestHelper(3, 2, false);
     155           5 :   TestHelper(3, 4, false);
     156           5 : }
     157             : 
     158       28342 : TEST(RetpolineOddEvenTail) {
     159           5 :   TestHelper(1, 0, true);
     160           5 :   TestHelper(1, 2, true);
     161           5 :   TestHelper(3, 2, true);
     162           5 :   TestHelper(3, 4, true);
     163           5 : }
     164             : 
     165       28342 : TEST(RetpolineOddOdd) {
     166           5 :   TestHelper(1, 1, false);
     167           5 :   TestHelper(1, 3, false);
     168           5 :   TestHelper(3, 1, false);
     169           5 :   TestHelper(3, 3, false);
     170           5 : }
     171             : 
     172       28342 : TEST(RetpolineOddOddTail) {
     173           5 :   TestHelper(1, 1, true);
     174           5 :   TestHelper(1, 3, true);
     175           5 :   TestHelper(3, 1, true);
     176           5 :   TestHelper(3, 3, true);
     177           5 : }
     178             : 
     179       28342 : TEST(RetpolineEvenEven) {
     180           5 :   TestHelper(0, 0, false);
     181           5 :   TestHelper(0, 2, false);
     182           5 :   TestHelper(2, 0, false);
     183           5 :   TestHelper(2, 2, false);
     184           5 : }
     185             : 
     186       28342 : TEST(RetpolineEvenEvenTail) {
     187           5 :   TestHelper(0, 0, true);
     188           5 :   TestHelper(0, 2, true);
     189           5 :   TestHelper(2, 0, true);
     190           5 :   TestHelper(2, 2, true);
     191           5 : }
     192             : 
     193       28342 : TEST(RetpolineEvenOdd) {
     194           5 :   TestHelper(0, 1, false);
     195           5 :   TestHelper(0, 3, false);
     196           5 :   TestHelper(2, 1, false);
     197           5 :   TestHelper(2, 3, false);
     198           5 : }
     199             : 
     200       28342 : TEST(RetpolineEvenOddTail) {
     201           5 :   TestHelper(0, 1, true);
     202           5 :   TestHelper(0, 3, true);
     203           5 :   TestHelper(2, 1, true);
     204           5 :   TestHelper(2, 3, true);
     205           5 : }
     206             : 
     207             : }  // namespace test_run_retpoline
     208             : }  // namespace compiler
     209             : }  // namespace internal
     210       85011 : }  // namespace v8

Generated by: LCOV version 1.10