LCOV - code coverage report
Current view: top level - test/cctest/compiler - test-code-assembler.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 403 404 99.8 %
Date: 2019-04-17 Functions: 29 29 100.0 %

          Line data    Source code
       1             : // 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             : 
       5             : #include "src/code-factory.h"
       6             : #include "src/compiler/code-assembler.h"
       7             : #include "src/compiler/node-properties.h"
       8             : #include "src/compiler/opcodes.h"
       9             : #include "src/isolate.h"
      10             : #include "src/objects-inl.h"
      11             : #include "src/objects/heap-number-inl.h"
      12             : #include "test/cctest/compiler/code-assembler-tester.h"
      13             : #include "test/cctest/compiler/function-tester.h"
      14             : 
      15             : namespace v8 {
      16             : namespace internal {
      17             : namespace compiler {
      18             : 
      19             : namespace {
      20             : 
      21             : typedef CodeAssemblerLabel Label;
      22             : typedef CodeAssemblerVariable Variable;
      23             : 
      24          52 : Node* SmiTag(CodeAssembler& m, Node* value) {
      25             :   int32_t constant_value;
      26          52 :   if (m.ToInt32Constant(value, constant_value) &&
      27             :       Smi::IsValid(constant_value)) {
      28         156 :     return m.SmiConstant(Smi::FromInt(constant_value));
      29             :   }
      30           0 :   return m.WordShl(value, m.IntPtrConstant(kSmiShiftSize + kSmiTagSize));
      31             : }
      32             : 
      33             : Node* UndefinedConstant(CodeAssembler& m) {
      34          32 :   return m.LoadRoot(RootIndex::kUndefinedValue);
      35             : }
      36             : 
      37           8 : Node* SmiFromInt32(CodeAssembler& m, Node* value) {
      38          16 :   value = m.ChangeInt32ToIntPtr(value);
      39          16 :   return m.BitcastWordToTaggedSigned(
      40          16 :       m.WordShl(value, kSmiShiftSize + kSmiTagSize));
      41             : }
      42             : 
      43           4 : Node* LoadObjectField(CodeAssembler& m, Node* object, int offset,
      44             :                       MachineType rep = MachineType::AnyTagged()) {
      45           8 :   return m.Load(rep, object, m.IntPtrConstant(offset - kHeapObjectTag));
      46             : }
      47             : 
      48             : Node* LoadMap(CodeAssembler& m, Node* object) {
      49           4 :   return LoadObjectField(m, object, JSObject::kMapOffset);
      50             : }
      51             : 
      52             : }  // namespace
      53             : 
      54       26643 : TEST(SimpleSmiReturn) {
      55             :   Isolate* isolate(CcTest::InitIsolateOnce());
      56           8 :   CodeAssemblerTester asm_tester(isolate);
      57           4 :   CodeAssembler m(asm_tester.state());
      58          12 :   m.Return(SmiTag(m, m.Int32Constant(37)));
      59           4 :   FunctionTester ft(asm_tester.GenerateCode());
      60           8 :   CHECK_EQ(37, ft.CallChecked<Smi>()->value());
      61           4 : }
      62             : 
      63       26643 : TEST(SimpleIntPtrReturn) {
      64             :   Isolate* isolate(CcTest::InitIsolateOnce());
      65           8 :   CodeAssemblerTester asm_tester(isolate);
      66           4 :   CodeAssembler m(asm_tester.state());
      67             :   int test;
      68           8 :   m.Return(m.BitcastWordToTagged(
      69          12 :       m.IntPtrConstant(reinterpret_cast<intptr_t>(&test))));
      70           4 :   FunctionTester ft(asm_tester.GenerateCode());
      71           4 :   MaybeHandle<Object> result = ft.Call();
      72           4 :   CHECK_EQ(reinterpret_cast<Address>(&test), result.ToHandleChecked()->ptr());
      73           4 : }
      74             : 
      75       26643 : TEST(SimpleDoubleReturn) {
      76             :   Isolate* isolate(CcTest::InitIsolateOnce());
      77           8 :   CodeAssemblerTester asm_tester(isolate);
      78           4 :   CodeAssembler m(asm_tester.state());
      79           8 :   m.Return(m.NumberConstant(0.5));
      80           4 :   FunctionTester ft(asm_tester.GenerateCode());
      81           8 :   CHECK_EQ(0.5, ft.CallChecked<HeapNumber>()->value());
      82           4 : }
      83             : 
      84       26643 : TEST(SimpleCallRuntime1Arg) {
      85             :   Isolate* isolate(CcTest::InitIsolateOnce());
      86           8 :   CodeAssemblerTester asm_tester(isolate);
      87           4 :   CodeAssembler m(asm_tester.state());
      88           4 :   Node* context = m.HeapConstant(Handle<Context>(isolate->native_context()));
      89           8 :   Node* b = SmiTag(m, m.Int32Constant(0));
      90           4 :   m.Return(m.CallRuntime(Runtime::kIsSmi, context, b));
      91           4 :   FunctionTester ft(asm_tester.GenerateCode());
      92           8 :   CHECK(ft.CallChecked<Oddball>().is_identical_to(
      93             :       isolate->factory()->true_value()));
      94           4 : }
      95             : 
      96       26643 : TEST(SimpleTailCallRuntime1Arg) {
      97             :   Isolate* isolate(CcTest::InitIsolateOnce());
      98           8 :   CodeAssemblerTester asm_tester(isolate);
      99           4 :   CodeAssembler m(asm_tester.state());
     100           4 :   Node* context = m.HeapConstant(Handle<Context>(isolate->native_context()));
     101           8 :   Node* b = SmiTag(m, m.Int32Constant(0));
     102           4 :   m.TailCallRuntime(Runtime::kIsSmi, context, b);
     103           4 :   FunctionTester ft(asm_tester.GenerateCode());
     104           8 :   CHECK(ft.CallChecked<Oddball>().is_identical_to(
     105             :       isolate->factory()->true_value()));
     106           4 : }
     107             : 
     108       26643 : TEST(SimpleCallRuntime2Arg) {
     109             :   Isolate* isolate(CcTest::InitIsolateOnce());
     110           8 :   CodeAssemblerTester asm_tester(isolate);
     111           4 :   CodeAssembler m(asm_tester.state());
     112           4 :   Node* context = m.HeapConstant(Handle<Context>(isolate->native_context()));
     113           8 :   Node* a = SmiTag(m, m.Int32Constant(2));
     114           8 :   Node* b = SmiTag(m, m.Int32Constant(4));
     115           4 :   m.Return(m.CallRuntime(Runtime::kAdd, context, a, b));
     116           4 :   FunctionTester ft(asm_tester.GenerateCode());
     117           8 :   CHECK_EQ(6, ft.CallChecked<Smi>()->value());
     118           4 : }
     119             : 
     120       26643 : TEST(SimpleTailCallRuntime2Arg) {
     121             :   Isolate* isolate(CcTest::InitIsolateOnce());
     122           8 :   CodeAssemblerTester asm_tester(isolate);
     123           4 :   CodeAssembler m(asm_tester.state());
     124           4 :   Node* context = m.HeapConstant(Handle<Context>(isolate->native_context()));
     125           8 :   Node* a = SmiTag(m, m.Int32Constant(2));
     126           8 :   Node* b = SmiTag(m, m.Int32Constant(4));
     127           4 :   m.TailCallRuntime(Runtime::kAdd, context, a, b);
     128           4 :   FunctionTester ft(asm_tester.GenerateCode());
     129           8 :   CHECK_EQ(6, ft.CallChecked<Smi>()->value());
     130           4 : }
     131             : 
     132             : namespace {
     133             : 
     134             : Handle<JSFunction> CreateSumAllArgumentsFunction(FunctionTester& ft) {
     135             :   const char* source =
     136             :       "(function() {\n"
     137             :       "  var sum = 0 + this;\n"
     138             :       "  for (var i = 0; i < arguments.length; i++) {\n"
     139             :       "    sum += arguments[i];\n"
     140             :       "  }\n"
     141             :       "  return sum;\n"
     142             :       "})";
     143          12 :   return ft.NewFunction(source);
     144             : }
     145             : 
     146             : }  // namespace
     147             : 
     148       26643 : TEST(SimpleCallJSFunction0Arg) {
     149             :   Isolate* isolate(CcTest::InitIsolateOnce());
     150             :   const int kNumParams = 1;
     151           8 :   CodeAssemblerTester asm_tester(isolate, kNumParams);
     152           4 :   CodeAssembler m(asm_tester.state());
     153             :   {
     154           4 :     Node* function = m.Parameter(0);
     155           4 :     Node* context = m.Parameter(kNumParams + 2);
     156             : 
     157           8 :     Node* receiver = SmiTag(m, m.Int32Constant(42));
     158             : 
     159           4 :     Callable callable = CodeFactory::Call(isolate);
     160           4 :     Node* result = m.CallJS(callable, context, function, receiver);
     161           4 :     m.Return(result);
     162             :   }
     163           4 :   FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
     164             : 
     165           4 :   Handle<JSFunction> sum = CreateSumAllArgumentsFunction(ft);
     166           4 :   MaybeHandle<Object> result = ft.Call(sum);
     167           4 :   CHECK_EQ(Smi::FromInt(42), *result.ToHandleChecked());
     168           4 : }
     169             : 
     170       26643 : TEST(SimpleCallJSFunction1Arg) {
     171             :   Isolate* isolate(CcTest::InitIsolateOnce());
     172             :   const int kNumParams = 2;
     173           8 :   CodeAssemblerTester asm_tester(isolate, kNumParams);
     174           4 :   CodeAssembler m(asm_tester.state());
     175             :   {
     176           4 :     Node* function = m.Parameter(0);
     177           4 :     Node* context = m.Parameter(1);
     178             : 
     179           8 :     Node* receiver = SmiTag(m, m.Int32Constant(42));
     180           8 :     Node* a = SmiTag(m, m.Int32Constant(13));
     181             : 
     182           4 :     Callable callable = CodeFactory::Call(isolate);
     183           4 :     Node* result = m.CallJS(callable, context, function, receiver, a);
     184           4 :     m.Return(result);
     185             :   }
     186           4 :   FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
     187             : 
     188           4 :   Handle<JSFunction> sum = CreateSumAllArgumentsFunction(ft);
     189           4 :   MaybeHandle<Object> result = ft.Call(sum);
     190           4 :   CHECK_EQ(Smi::FromInt(55), *result.ToHandleChecked());
     191           4 : }
     192             : 
     193       26643 : TEST(SimpleCallJSFunction2Arg) {
     194             :   Isolate* isolate(CcTest::InitIsolateOnce());
     195             :   const int kNumParams = 2;
     196           8 :   CodeAssemblerTester asm_tester(isolate, kNumParams);
     197           4 :   CodeAssembler m(asm_tester.state());
     198             :   {
     199           4 :     Node* function = m.Parameter(0);
     200           4 :     Node* context = m.Parameter(1);
     201             : 
     202           8 :     Node* receiver = SmiTag(m, m.Int32Constant(42));
     203           8 :     Node* a = SmiTag(m, m.Int32Constant(13));
     204           8 :     Node* b = SmiTag(m, m.Int32Constant(153));
     205             : 
     206           4 :     Callable callable = CodeFactory::Call(isolate);
     207           4 :     Node* result = m.CallJS(callable, context, function, receiver, a, b);
     208           4 :     m.Return(result);
     209             :   }
     210           4 :   FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
     211             : 
     212           4 :   Handle<JSFunction> sum = CreateSumAllArgumentsFunction(ft);
     213           4 :   MaybeHandle<Object> result = ft.Call(sum);
     214           4 :   CHECK_EQ(Smi::FromInt(208), *result.ToHandleChecked());
     215           4 : }
     216             : 
     217       26643 : TEST(VariableMerge1) {
     218             :   Isolate* isolate(CcTest::InitIsolateOnce());
     219           8 :   CodeAssemblerTester asm_tester(isolate);
     220           4 :   CodeAssembler m(asm_tester.state());
     221           8 :   Variable var1(&m, MachineRepresentation::kTagged);
     222           4 :   Label l1(&m), l2(&m), merge(&m);
     223           8 :   Node* temp = m.Int32Constant(0);
     224           4 :   var1.Bind(temp);
     225           8 :   m.Branch(m.Int32Constant(1), &l1, &l2);
     226           4 :   m.Bind(&l1);
     227           4 :   CHECK_EQ(var1.value(), temp);
     228           4 :   m.Goto(&merge);
     229           4 :   m.Bind(&l2);
     230           4 :   CHECK_EQ(var1.value(), temp);
     231           4 :   m.Goto(&merge);
     232           4 :   m.Bind(&merge);
     233           4 :   CHECK_EQ(var1.value(), temp);
     234           4 : }
     235             : 
     236       26643 : TEST(VariableMerge2) {
     237             :   Isolate* isolate(CcTest::InitIsolateOnce());
     238           8 :   CodeAssemblerTester asm_tester(isolate);
     239           4 :   CodeAssembler m(asm_tester.state());
     240           8 :   Variable var1(&m, MachineRepresentation::kTagged);
     241           4 :   Label l1(&m), l2(&m), merge(&m);
     242           8 :   Node* temp = m.Int32Constant(0);
     243           4 :   var1.Bind(temp);
     244           8 :   m.Branch(m.Int32Constant(1), &l1, &l2);
     245           4 :   m.Bind(&l1);
     246           4 :   CHECK_EQ(var1.value(), temp);
     247           4 :   m.Goto(&merge);
     248           4 :   m.Bind(&l2);
     249           8 :   Node* temp2 = m.Int32Constant(2);
     250           4 :   var1.Bind(temp2);
     251           4 :   CHECK_EQ(var1.value(), temp2);
     252           4 :   m.Goto(&merge);
     253           4 :   m.Bind(&merge);
     254           4 :   CHECK_NE(var1.value(), temp);
     255           4 : }
     256             : 
     257       26643 : TEST(VariableMerge3) {
     258             :   Isolate* isolate(CcTest::InitIsolateOnce());
     259           8 :   CodeAssemblerTester asm_tester(isolate);
     260           4 :   CodeAssembler m(asm_tester.state());
     261           8 :   Variable var1(&m, MachineRepresentation::kTagged);
     262           8 :   Variable var2(&m, MachineRepresentation::kTagged);
     263           4 :   Label l1(&m), l2(&m), merge(&m);
     264           8 :   Node* temp = m.Int32Constant(0);
     265           4 :   var1.Bind(temp);
     266           4 :   var2.Bind(temp);
     267           8 :   m.Branch(m.Int32Constant(1), &l1, &l2);
     268           4 :   m.Bind(&l1);
     269           4 :   CHECK_EQ(var1.value(), temp);
     270           4 :   m.Goto(&merge);
     271           4 :   m.Bind(&l2);
     272           8 :   Node* temp2 = m.Int32Constant(2);
     273           4 :   var1.Bind(temp2);
     274           4 :   CHECK_EQ(var1.value(), temp2);
     275           4 :   m.Goto(&merge);
     276           4 :   m.Bind(&merge);
     277           4 :   CHECK_NE(var1.value(), temp);
     278           4 :   CHECK_NE(var1.value(), temp2);
     279           4 :   CHECK_EQ(var2.value(), temp);
     280           4 : }
     281             : 
     282       26643 : TEST(VariableMergeBindFirst) {
     283             :   Isolate* isolate(CcTest::InitIsolateOnce());
     284           8 :   CodeAssemblerTester asm_tester(isolate);
     285           4 :   CodeAssembler m(asm_tester.state());
     286           8 :   Variable var1(&m, MachineRepresentation::kTagged);
     287           4 :   Label l1(&m), l2(&m), merge(&m, &var1), end(&m);
     288           8 :   Node* temp = m.Int32Constant(0);
     289           4 :   var1.Bind(temp);
     290           8 :   m.Branch(m.Int32Constant(1), &l1, &l2);
     291           4 :   m.Bind(&l1);
     292           4 :   CHECK_EQ(var1.value(), temp);
     293           4 :   m.Goto(&merge);
     294           4 :   m.Bind(&merge);
     295           4 :   CHECK(var1.value() != temp);
     296           4 :   CHECK_NOT_NULL(var1.value());
     297           4 :   m.Goto(&end);
     298           4 :   m.Bind(&l2);
     299           8 :   Node* temp2 = m.Int32Constant(2);
     300           4 :   var1.Bind(temp2);
     301           4 :   CHECK_EQ(var1.value(), temp2);
     302           4 :   m.Goto(&merge);
     303           4 :   m.Bind(&end);
     304           4 :   CHECK(var1.value() != temp);
     305           4 :   CHECK_NOT_NULL(var1.value());
     306           4 : }
     307             : 
     308       26643 : TEST(VariableMergeSwitch) {
     309             :   Isolate* isolate(CcTest::InitIsolateOnce());
     310           8 :   CodeAssemblerTester asm_tester(isolate);
     311           4 :   CodeAssembler m(asm_tester.state());
     312           8 :   Variable var1(&m, MachineRepresentation::kTagged);
     313           4 :   Label l1(&m), l2(&m), default_label(&m);
     314           4 :   Label* labels[] = {&l1, &l2};
     315           4 :   int32_t values[] = {1, 2};
     316           8 :   Node* temp1 = m.Int32Constant(0);
     317           4 :   var1.Bind(temp1);
     318           8 :   m.Switch(m.Int32Constant(2), &default_label, values, labels, 2);
     319           4 :   m.Bind(&l1);
     320           4 :   CHECK_EQ(temp1, var1.value());
     321           4 :   m.Return(temp1);
     322           4 :   m.Bind(&l2);
     323           4 :   CHECK_EQ(temp1, var1.value());
     324           8 :   Node* temp2 = m.Int32Constant(7);
     325           4 :   var1.Bind(temp2);
     326           4 :   m.Goto(&default_label);
     327           4 :   m.Bind(&default_label);
     328           8 :   CHECK_EQ(IrOpcode::kPhi, var1.value()->opcode());
     329           8 :   CHECK_EQ(2, var1.value()->op()->ValueInputCount());
     330           4 :   CHECK_EQ(temp1, NodeProperties::GetValueInput(var1.value(), 0));
     331           4 :   CHECK_EQ(temp2, NodeProperties::GetValueInput(var1.value(), 1));
     332           4 :   m.Return(temp1);
     333           4 : }
     334             : 
     335       26643 : TEST(SplitEdgeBranchMerge) {
     336             :   Isolate* isolate(CcTest::InitIsolateOnce());
     337           8 :   CodeAssemblerTester asm_tester(isolate);
     338           4 :   CodeAssembler m(asm_tester.state());
     339           4 :   Label l1(&m), merge(&m);
     340           8 :   m.Branch(m.Int32Constant(1), &l1, &merge);
     341           4 :   m.Bind(&l1);
     342           4 :   m.Goto(&merge);
     343           4 :   m.Bind(&merge);
     344           4 :   USE(asm_tester.GenerateCode());
     345           4 : }
     346             : 
     347       26643 : TEST(SplitEdgeSwitchMerge) {
     348             :   Isolate* isolate(CcTest::InitIsolateOnce());
     349           8 :   CodeAssemblerTester asm_tester(isolate);
     350           4 :   CodeAssembler m(asm_tester.state());
     351           4 :   Label l1(&m), l2(&m), l3(&m), default_label(&m);
     352           4 :   Label* labels[] = {&l1, &l2};
     353           4 :   int32_t values[] = {1, 2};
     354           8 :   m.Branch(m.Int32Constant(1), &l3, &l1);
     355           4 :   m.Bind(&l3);
     356           8 :   m.Switch(m.Int32Constant(2), &default_label, values, labels, 2);
     357           4 :   m.Bind(&l1);
     358           4 :   m.Goto(&l2);
     359           4 :   m.Bind(&l2);
     360           4 :   m.Goto(&default_label);
     361           4 :   m.Bind(&default_label);
     362           4 :   USE(asm_tester.GenerateCode());
     363           4 : }
     364             : 
     365       26643 : TEST(TestToConstant) {
     366             :   Isolate* isolate(CcTest::InitIsolateOnce());
     367           8 :   CodeAssemblerTester asm_tester(isolate);
     368           4 :   CodeAssembler m(asm_tester.state());
     369             :   int32_t value32;
     370             :   int64_t value64;
     371           8 :   Node* a = m.Int32Constant(5);
     372           4 :   CHECK(m.ToInt32Constant(a, value32));
     373           4 :   CHECK(m.ToInt64Constant(a, value64));
     374             : 
     375           8 :   a = m.Int64Constant(static_cast<int64_t>(1) << 32);
     376           4 :   CHECK(!m.ToInt32Constant(a, value32));
     377           4 :   CHECK(m.ToInt64Constant(a, value64));
     378             : 
     379           8 :   a = m.Int64Constant(13);
     380           4 :   CHECK(m.ToInt32Constant(a, value32));
     381           4 :   CHECK(m.ToInt64Constant(a, value64));
     382             : 
     383             :   a = UndefinedConstant(m);
     384           4 :   CHECK(!m.ToInt32Constant(a, value32));
     385           4 :   CHECK(!m.ToInt64Constant(a, value64));
     386             : 
     387             :   a = UndefinedConstant(m);
     388           4 :   CHECK(!m.ToInt32Constant(a, value32));
     389           4 :   CHECK(!m.ToInt64Constant(a, value64));
     390           4 : }
     391             : 
     392       26643 : TEST(DeferredCodePhiHints) {
     393             :   Isolate* isolate(CcTest::InitIsolateOnce());
     394           8 :   CodeAssemblerTester asm_tester(isolate);
     395           4 :   CodeAssembler m(asm_tester.state());
     396           4 :   Label block1(&m, Label::kDeferred);
     397           4 :   m.Goto(&block1);
     398           4 :   m.Bind(&block1);
     399             :   {
     400           8 :     Variable var_object(&m, MachineRepresentation::kTagged);
     401           4 :     Label loop(&m, &var_object);
     402           8 :     var_object.Bind(m.SmiConstant(0));
     403           4 :     m.Goto(&loop);
     404           4 :     m.Bind(&loop);
     405             :     {
     406           4 :       Node* map = LoadMap(m, var_object.value());
     407           4 :       var_object.Bind(map);
     408           4 :       m.Goto(&loop);
     409             :     }
     410             :   }
     411           8 :   CHECK(!asm_tester.GenerateCode().is_null());
     412           4 : }
     413             : 
     414       26643 : TEST(TestOutOfScopeVariable) {
     415             :   Isolate* isolate(CcTest::InitIsolateOnce());
     416           8 :   CodeAssemblerTester asm_tester(isolate);
     417           4 :   CodeAssembler m(asm_tester.state());
     418           4 :   Label block1(&m);
     419           4 :   Label block2(&m);
     420           4 :   Label block3(&m);
     421           4 :   Label block4(&m);
     422          12 :   m.Branch(m.WordEqual(m.UncheckedCast<IntPtrT>(m.Parameter(0)),
     423           8 :                        m.IntPtrConstant(0)),
     424           4 :            &block1, &block4);
     425           4 :   m.Bind(&block4);
     426             :   {
     427           8 :     Variable var_object(&m, MachineRepresentation::kTagged);
     428          12 :     m.Branch(m.WordEqual(m.UncheckedCast<IntPtrT>(m.Parameter(0)),
     429           8 :                          m.IntPtrConstant(0)),
     430           4 :              &block2, &block3);
     431             : 
     432           4 :     m.Bind(&block2);
     433           8 :     var_object.Bind(m.IntPtrConstant(55));
     434           4 :     m.Goto(&block1);
     435             : 
     436           4 :     m.Bind(&block3);
     437           8 :     var_object.Bind(m.IntPtrConstant(66));
     438           4 :     m.Goto(&block1);
     439             :   }
     440           4 :   m.Bind(&block1);
     441           8 :   CHECK(!asm_tester.GenerateCode().is_null());
     442           4 : }
     443             : 
     444       26643 : TEST(GotoIfException) {
     445             :   Isolate* isolate(CcTest::InitIsolateOnce());
     446             : 
     447             :   const int kNumParams = 1;
     448           8 :   CodeAssemblerTester asm_tester(isolate, kNumParams);
     449           4 :   CodeAssembler m(asm_tester.state());
     450             : 
     451           4 :   Node* context = m.HeapConstant(Handle<Context>(isolate->native_context()));
     452             :   Node* to_string_tag =
     453             :       m.HeapConstant(isolate->factory()->to_string_tag_symbol());
     454           8 :   Variable exception(&m, MachineRepresentation::kTagged);
     455             : 
     456           4 :   Label exception_handler(&m);
     457           4 :   Callable to_string = Builtins::CallableFor(isolate, Builtins::kToString);
     458           8 :   Node* string = m.CallStub(to_string, context, to_string_tag);
     459           4 :   m.GotoIfException(string, &exception_handler, &exception);
     460           4 :   m.Return(string);
     461             : 
     462           4 :   m.Bind(&exception_handler);
     463           8 :   m.Return(exception.value());
     464             : 
     465           4 :   FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
     466           8 :   Handle<Object> result = ft.Call().ToHandleChecked();
     467             : 
     468             :   // Should be a TypeError.
     469           4 :   CHECK(result->IsJSObject());
     470             : 
     471             :   Handle<Object> constructor =
     472           8 :       Object::GetPropertyOrElement(isolate, result,
     473           4 :                                    isolate->factory()->constructor_string())
     474             :           .ToHandleChecked();
     475          12 :   CHECK(constructor->SameValue(*isolate->type_error_function()));
     476           4 : }
     477             : 
     478       26643 : TEST(GotoIfExceptionMultiple) {
     479             :   Isolate* isolate(CcTest::InitIsolateOnce());
     480             : 
     481             :   const int kNumParams = 4;  // receiver, first, second, third
     482           8 :   CodeAssemblerTester asm_tester(isolate, kNumParams);
     483           4 :   CodeAssembler m(asm_tester.state());
     484             : 
     485           4 :   Node* context = m.HeapConstant(Handle<Context>(isolate->native_context()));
     486           4 :   Node* first_value = m.Parameter(0);
     487           4 :   Node* second_value = m.Parameter(1);
     488           4 :   Node* third_value = m.Parameter(2);
     489             : 
     490           4 :   Label exception_handler1(&m);
     491           4 :   Label exception_handler2(&m);
     492           4 :   Label exception_handler3(&m);
     493           8 :   Variable return_value(&m, MachineRepresentation::kWord32);
     494           8 :   Variable error(&m, MachineRepresentation::kTagged);
     495             : 
     496           8 :   return_value.Bind(m.Int32Constant(0));
     497             : 
     498             :   // try { return ToString(param1) } catch (e) { ... }
     499           4 :   Callable to_string = Builtins::CallableFor(isolate, Builtins::kToString);
     500           8 :   Node* string = m.CallStub(to_string, context, first_value);
     501           4 :   m.GotoIfException(string, &exception_handler1, &error);
     502           4 :   m.Return(string);
     503             : 
     504             :   // try { ToString(param2); return 7 } catch (e) { ... }
     505           4 :   m.Bind(&exception_handler1);
     506           8 :   return_value.Bind(m.Int32Constant(7));
     507           4 :   error.Bind(UndefinedConstant(m));
     508           8 :   string = m.CallStub(to_string, context, second_value);
     509           4 :   m.GotoIfException(string, &exception_handler2, &error);
     510           8 :   m.Return(SmiFromInt32(m, return_value.value()));
     511             : 
     512             :   // try { ToString(param3); return 7 & ~2; } catch (e) { return e; }
     513           4 :   m.Bind(&exception_handler2);
     514             :   // Return returnValue & ~2
     515           4 :   error.Bind(UndefinedConstant(m));
     516           8 :   string = m.CallStub(to_string, context, third_value);
     517           4 :   m.GotoIfException(string, &exception_handler3, &error);
     518           8 :   m.Return(SmiFromInt32(
     519           8 :       m, m.Word32And(return_value.value(),
     520          24 :                      m.Word32Xor(m.Int32Constant(2), m.Int32Constant(-1)))));
     521             : 
     522           4 :   m.Bind(&exception_handler3);
     523           8 :   m.Return(error.value());
     524             : 
     525           4 :   FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
     526             : 
     527             :   Handle<Object> result;
     528             :   // First handler does not throw, returns result of first value.
     529           8 :   result = ft.Call(isolate->factory()->undefined_value(),
     530             :                    isolate->factory()->to_string_tag_symbol())
     531             :                .ToHandleChecked();
     532           4 :   CHECK(String::cast(*result)->IsOneByteEqualTo(OneByteVector("undefined")));
     533             : 
     534             :   // First handler returns a number.
     535           8 :   result = ft.Call(isolate->factory()->to_string_tag_symbol(),
     536             :                    isolate->factory()->undefined_value())
     537             :                .ToHandleChecked();
     538           4 :   CHECK_EQ(7, Smi::ToInt(*result));
     539             : 
     540             :   // First handler throws, second handler returns a number.
     541           8 :   result = ft.Call(isolate->factory()->to_string_tag_symbol(),
     542             :                    isolate->factory()->to_primitive_symbol())
     543             :                .ToHandleChecked();
     544           4 :   CHECK_EQ(7 & ~2, Smi::ToInt(*result));
     545             : 
     546             :   // First handler throws, second handler throws, third handler returns thrown
     547             :   // value.
     548           8 :   result = ft.Call(isolate->factory()->to_string_tag_symbol(),
     549             :                    isolate->factory()->to_primitive_symbol(),
     550             :                    isolate->factory()->unscopables_symbol())
     551             :                .ToHandleChecked();
     552             : 
     553             :   // Should be a TypeError.
     554           4 :   CHECK(result->IsJSObject());
     555             : 
     556             :   Handle<Object> constructor =
     557           8 :       Object::GetPropertyOrElement(isolate, result,
     558           4 :                                    isolate->factory()->constructor_string())
     559             :           .ToHandleChecked();
     560          12 :   CHECK(constructor->SameValue(*isolate->type_error_function()));
     561           4 : }
     562             : 
     563       26643 : TEST(ExceptionHandler) {
     564             :   Isolate* isolate(CcTest::InitIsolateOnce());
     565             :   const int kNumParams = 0;
     566           8 :   CodeAssemblerTester asm_tester(isolate, kNumParams);
     567           4 :   CodeAssembler m(asm_tester.state());
     568             : 
     569           8 :   CodeAssembler::TVariable<Object> var(m.SmiConstant(0), &m);
     570          12 :   Label exception(&m, {&var}, Label::kDeferred);
     571             :   {
     572           8 :     CodeAssemblerScopedExceptionHandler handler(&m, &exception, &var);
     573           4 :     Node* context = m.HeapConstant(Handle<Context>(isolate->native_context()));
     574           4 :     m.CallRuntime(Runtime::kThrow, context, m.SmiConstant(2));
     575             :   }
     576           8 :   m.Return(m.SmiConstant(1));
     577             : 
     578           4 :   m.Bind(&exception);
     579           4 :   m.Return(var.value());
     580             : 
     581           4 :   FunctionTester ft(asm_tester.GenerateCode(), kNumParams);
     582           8 :   CHECK_EQ(2, ft.CallChecked<Smi>()->value());
     583           4 : }
     584             : 
     585       26643 : TEST(TestCodeAssemblerCodeComment) {
     586           4 :   i::FLAG_code_comments = true;
     587             :   Isolate* isolate(CcTest::InitIsolateOnce());
     588             :   const int kNumParams = 0;
     589           8 :   CodeAssemblerTester asm_tester(isolate, kNumParams);
     590           4 :   CodeAssembler m(asm_tester.state());
     591             : 
     592           4 :   m.Comment("Comment1");
     593           8 :   m.Return(m.SmiConstant(1));
     594             : 
     595           4 :   Handle<Code> code = asm_tester.GenerateCode();
     596           4 :   CHECK_NE(code->code_comments(), kNullAddress);
     597           8 :   CodeCommentsIterator it(code->code_comments(), code->code_comments_size());
     598           4 :   CHECK(it.HasCurrent());
     599             :   bool found_comment = false;
     600          16 :   while (it.HasCurrent()) {
     601          16 :     if (strcmp(it.GetComment(), "Comment1") == 0) found_comment = true;
     602          16 :     it.Next();
     603             :   }
     604           4 :   CHECK(found_comment);
     605           4 : }
     606             : 
     607             : }  // namespace compiler
     608             : }  // namespace internal
     609       79917 : }  // namespace v8

Generated by: LCOV version 1.10