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

Generated by: LCOV version 1.10