LCOV - code coverage report
Current view: top level - test/cctest/compiler - test-run-retpoline.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 113 113 100.0 %
Date: 2019-04-19 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         128 : Handle<Code> BuildCallee(Isolate* isolate, CallDescriptor* call_descriptor) {
      25         256 :   CodeAssemblerTester tester(isolate, call_descriptor, "callee");
      26         128 :   CodeStubAssembler assembler(tester.state());
      27         128 :   int param_count = static_cast<int>(call_descriptor->StackParameterCount());
      28         256 :   Node* sum = __ IntPtrConstant(0);
      29         576 :   for (int i = 0; i < param_count; ++i) {
      30         896 :     Node* product = __ IntPtrMul(__ Parameter(i), __ IntPtrConstant(i + 1));
      31         448 :     sum = __ IntPtrAdd(sum, product);
      32             :   }
      33         128 :   __ Return(sum);
      34         128 :   return tester.GenerateCodeCloseAndEscape();
      35             : }
      36             : 
      37             : // Function that tail-calls another function with a number of pointer-sized
      38             : // integer arguments.
      39         128 : Handle<Code> BuildCaller(Isolate* isolate, CallDescriptor* call_descriptor,
      40             :                          CallDescriptor* callee_descriptor, bool tail) {
      41         256 :   CodeAssemblerTester tester(isolate, call_descriptor, "caller");
      42         128 :   CodeStubAssembler assembler(tester.state());
      43             :   std::vector<Node*> params;
      44             :   // The first parameter is always the callee.
      45         128 :   Handle<Code> callee = BuildCallee(isolate, callee_descriptor);
      46             :   // defeat the instruction selector.
      47             :   CodeStubAssembler::Variable target_var(&assembler,
      48         256 :                                          MachineRepresentation::kTagged);
      49         128 :   CodeStubAssembler::Label t(&assembler), f(&assembler),
      50         128 :       end(&assembler, &target_var);
      51         256 :   __ Branch(__ Int32Constant(0), &t, &f);
      52         128 :   __ BIND(&t);
      53         128 :   target_var.Bind(__ HeapConstant(callee));
      54         128 :   __ Goto(&end);
      55         128 :   __ BIND(&f);
      56         128 :   target_var.Bind(__ HeapConstant(callee));
      57         128 :   __ Goto(&end);
      58         128 :   __ BIND(&end);
      59         256 :   params.push_back(target_var.value());
      60             : 
      61         128 :   int param_count = static_cast<int>(callee_descriptor->StackParameterCount());
      62         576 :   for (int i = 0; i < param_count; ++i) {
      63         672 :     params.push_back(__ IntPtrConstant(i));
      64             :   }
      65             :   DCHECK_EQ(param_count + 1, params.size());
      66         128 :   if (tail) {
      67          64 :     tester.raw_assembler_for_testing()->TailCallN(
      68          64 :         callee_descriptor, param_count + 1, params.data());
      69             :   } else {
      70          64 :     Node* result = tester.raw_assembler_for_testing()->CallN(
      71          64 :         callee_descriptor, param_count + 1, params.data());
      72          64 :     __ Return(result);
      73             :   }
      74         128 :   return tester.GenerateCodeCloseAndEscape();
      75             : }
      76             : 
      77             : // Setup function, which calls "caller".
      78         128 : Handle<Code> BuildSetupFunction(Isolate* isolate,
      79             :                                 CallDescriptor* caller_descriptor,
      80             :                                 CallDescriptor* callee_descriptor, bool tail) {
      81         256 :   CodeAssemblerTester tester(isolate, 0);
      82         128 :   CodeStubAssembler assembler(tester.state());
      83             :   std::vector<Node*> params;
      84             :   // The first parameter is always the callee.
      85         256 :   params.push_back(__ HeapConstant(
      86         128 :       BuildCaller(isolate, caller_descriptor, callee_descriptor, tail)));
      87             :   // Set up arguments for "Caller".
      88         128 :   int param_count = static_cast<int>(caller_descriptor->StackParameterCount());
      89         512 :   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         576 :     params.push_back(__ IntPtrConstant(i + 42));
      93             :   }
      94             :   DCHECK_EQ(param_count + 1, params.size());
      95         128 :   Node* raw_result = tester.raw_assembler_for_testing()->CallN(
      96         128 :       caller_descriptor, param_count + 1, params.data());
      97         256 :   __ Return(__ SmiTag(raw_result));
      98         128 :   return tester.GenerateCodeCloseAndEscape();
      99             : }
     100             : 
     101         256 : CallDescriptor* CreateDescriptorForStackArguments(Zone* zone,
     102             :                                                   int stack_param_count) {
     103             :   LocationSignature::Builder locations(zone, 1,
     104         256 :                                        static_cast<size_t>(stack_param_count));
     105             : 
     106             :   locations.AddReturn(LinkageLocation::ForRegister(kReturnRegister0.code(),
     107             :                                                    MachineType::IntPtr()));
     108             : 
     109        1088 :   for (int i = 0; i < stack_param_count; ++i) {
     110         416 :     locations.AddParam(LinkageLocation::ForCallerFrameSlot(
     111             :         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         256 :                      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         128 : void TestHelper(int n, int m, bool tail) {
     130         256 :   HandleAndZoneScope scope;
     131             :   Isolate* isolate = scope.main_isolate();
     132         256 :   CanonicalHandleScope canonical(isolate);
     133             :   Zone* zone = scope.main_zone();
     134             :   CallDescriptor* caller_descriptor =
     135         128 :       CreateDescriptorForStackArguments(zone, n);
     136             :   CallDescriptor* callee_descriptor =
     137         128 :       CreateDescriptorForStackArguments(zone, m);
     138             :   Handle<Code> setup =
     139         128 :       BuildSetupFunction(isolate, caller_descriptor, callee_descriptor, tail);
     140         128 :   FunctionTester ft(setup, 0);
     141         256 :   Handle<Object> result = ft.Call().ToHandleChecked();
     142             :   int expected = 0;
     143         352 :   for (int i = 0; i < m; ++i) expected += (i + 1) * i;
     144         128 :   CHECK_EQ(expected, Handle<Smi>::cast(result)->value());
     145         128 : }
     146             : 
     147             : }  // namespace
     148             : 
     149             : #undef __
     150             : 
     151       26660 : TEST(RetpolineOddEven) {
     152           4 :   TestHelper(1, 0, false);
     153           4 :   TestHelper(1, 2, false);
     154           4 :   TestHelper(3, 2, false);
     155           4 :   TestHelper(3, 4, false);
     156           4 : }
     157             : 
     158       26660 : TEST(RetpolineOddEvenTail) {
     159           4 :   TestHelper(1, 0, true);
     160           4 :   TestHelper(1, 2, true);
     161           4 :   TestHelper(3, 2, true);
     162           4 :   TestHelper(3, 4, true);
     163           4 : }
     164             : 
     165       26660 : TEST(RetpolineOddOdd) {
     166           4 :   TestHelper(1, 1, false);
     167           4 :   TestHelper(1, 3, false);
     168           4 :   TestHelper(3, 1, false);
     169           4 :   TestHelper(3, 3, false);
     170           4 : }
     171             : 
     172       26660 : TEST(RetpolineOddOddTail) {
     173           4 :   TestHelper(1, 1, true);
     174           4 :   TestHelper(1, 3, true);
     175           4 :   TestHelper(3, 1, true);
     176           4 :   TestHelper(3, 3, true);
     177           4 : }
     178             : 
     179       26660 : TEST(RetpolineEvenEven) {
     180           4 :   TestHelper(0, 0, false);
     181           4 :   TestHelper(0, 2, false);
     182           4 :   TestHelper(2, 0, false);
     183           4 :   TestHelper(2, 2, false);
     184           4 : }
     185             : 
     186       26660 : TEST(RetpolineEvenEvenTail) {
     187           4 :   TestHelper(0, 0, true);
     188           4 :   TestHelper(0, 2, true);
     189           4 :   TestHelper(2, 0, true);
     190           4 :   TestHelper(2, 2, true);
     191           4 : }
     192             : 
     193       26660 : TEST(RetpolineEvenOdd) {
     194           4 :   TestHelper(0, 1, false);
     195           4 :   TestHelper(0, 3, false);
     196           4 :   TestHelper(2, 1, false);
     197           4 :   TestHelper(2, 3, false);
     198           4 : }
     199             : 
     200       26660 : TEST(RetpolineEvenOddTail) {
     201           4 :   TestHelper(0, 1, true);
     202           4 :   TestHelper(0, 3, true);
     203           4 :   TestHelper(2, 1, true);
     204           4 :   TestHelper(2, 3, true);
     205           4 : }
     206             : 
     207             : }  // namespace test_run_retpoline
     208             : }  // namespace compiler
     209             : }  // namespace internal
     210       79968 : }  // namespace v8

Generated by: LCOV version 1.10