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

Generated by: LCOV version 1.10