Home | History | Annotate | Download | only in src
      1 // Copyright 2016 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 #include "src/code-stub-assembler.h"
      5 #include "src/code-factory.h"
      6 #include "src/frames-inl.h"
      7 #include "src/frames.h"
      8 
      9 namespace v8 {
     10 namespace internal {
     11 
     12 using compiler::Node;
     13 
     14 CodeStubAssembler::CodeStubAssembler(compiler::CodeAssemblerState* state)
     15     : compiler::CodeAssembler(state) {
     16   if (DEBUG_BOOL && FLAG_csa_trap_on_node != nullptr) {
     17     HandleBreakOnNode();
     18   }
     19 }
     20 
     21 void CodeStubAssembler::HandleBreakOnNode() {
     22   // FLAG_csa_trap_on_node should be in a form "STUB,NODE" where STUB is a
     23   // string specifying the name of a stub and NODE is number specifying node id.
     24   const char* name = state()->name();
     25   size_t name_length = strlen(name);
     26   if (strncmp(FLAG_csa_trap_on_node, name, name_length) != 0) {
     27     // Different name.
     28     return;
     29   }
     30   size_t option_length = strlen(FLAG_csa_trap_on_node);
     31   if (option_length < name_length + 2 ||
     32       FLAG_csa_trap_on_node[name_length] != ',') {
     33     // Option is too short.
     34     return;
     35   }
     36   const char* start = &FLAG_csa_trap_on_node[name_length + 1];
     37   char* end;
     38   int node_id = static_cast<int>(strtol(start, &end, 10));
     39   if (start == end) {
     40     // Bad node id.
     41     return;
     42   }
     43   BreakOnNode(node_id);
     44 }
     45 
     46 void CodeStubAssembler::Assert(const NodeGenerator& codition_body,
     47                                const char* message, const char* file,
     48                                int line) {
     49 #if defined(DEBUG)
     50   if (FLAG_debug_code) {
     51     Label ok(this);
     52     Label not_ok(this, Label::kDeferred);
     53     if (message != nullptr && FLAG_code_comments) {
     54       Comment("[ Assert: %s", message);
     55     } else {
     56       Comment("[ Assert");
     57     }
     58     Node* condition = codition_body();
     59     DCHECK_NOT_NULL(condition);
     60     Branch(condition, &ok, &not_ok);
     61     Bind(&not_ok);
     62     if (message != nullptr) {
     63       char chars[1024];
     64       Vector<char> buffer(chars);
     65       if (file != nullptr) {
     66         SNPrintF(buffer, "CSA_ASSERT failed: %s [%s:%d]\n", message, file,
     67                  line);
     68       } else {
     69         SNPrintF(buffer, "CSA_ASSERT failed: %s\n", message);
     70       }
     71       CallRuntime(
     72           Runtime::kGlobalPrint, SmiConstant(Smi::kZero),
     73           HeapConstant(factory()->NewStringFromAsciiChecked(&(buffer[0]))));
     74     }
     75     DebugBreak();
     76     Goto(&ok);
     77     Bind(&ok);
     78     Comment("] Assert");
     79   }
     80 #endif
     81 }
     82 
     83 Node* CodeStubAssembler::Select(Node* condition, const NodeGenerator& true_body,
     84                                 const NodeGenerator& false_body,
     85                                 MachineRepresentation rep) {
     86   Variable value(this, rep);
     87   Label vtrue(this), vfalse(this), end(this);
     88   Branch(condition, &vtrue, &vfalse);
     89 
     90   Bind(&vtrue);
     91   {
     92     value.Bind(true_body());
     93     Goto(&end);
     94   }
     95   Bind(&vfalse);
     96   {
     97     value.Bind(false_body());
     98     Goto(&end);
     99   }
    100 
    101   Bind(&end);
    102   return value.value();
    103 }
    104 
    105 Node* CodeStubAssembler::SelectConstant(Node* condition, Node* true_value,
    106                                         Node* false_value,
    107                                         MachineRepresentation rep) {
    108   return Select(condition, [=] { return true_value; },
    109                 [=] { return false_value; }, rep);
    110 }
    111 
    112 Node* CodeStubAssembler::SelectInt32Constant(Node* condition, int true_value,
    113                                              int false_value) {
    114   return SelectConstant(condition, Int32Constant(true_value),
    115                         Int32Constant(false_value),
    116                         MachineRepresentation::kWord32);
    117 }
    118 
    119 Node* CodeStubAssembler::SelectIntPtrConstant(Node* condition, int true_value,
    120                                               int false_value) {
    121   return SelectConstant(condition, IntPtrConstant(true_value),
    122                         IntPtrConstant(false_value),
    123                         MachineType::PointerRepresentation());
    124 }
    125 
    126 Node* CodeStubAssembler::SelectBooleanConstant(Node* condition) {
    127   return SelectConstant(condition, TrueConstant(), FalseConstant(),
    128                         MachineRepresentation::kTagged);
    129 }
    130 
    131 Node* CodeStubAssembler::SelectTaggedConstant(Node* condition, Node* true_value,
    132                                               Node* false_value) {
    133   return SelectConstant(condition, true_value, false_value,
    134                         MachineRepresentation::kTagged);
    135 }
    136 
    137 Node* CodeStubAssembler::SelectSmiConstant(Node* condition, Smi* true_value,
    138                                            Smi* false_value) {
    139   return SelectConstant(condition, SmiConstant(true_value),
    140                         SmiConstant(false_value),
    141                         MachineRepresentation::kTaggedSigned);
    142 }
    143 
    144 Node* CodeStubAssembler::NoContextConstant() { return NumberConstant(0); }
    145 
    146 #define HEAP_CONSTANT_ACCESSOR(rootName, name)     \
    147   Node* CodeStubAssembler::name##Constant() {      \
    148     return LoadRoot(Heap::k##rootName##RootIndex); \
    149   }
    150 HEAP_CONSTANT_LIST(HEAP_CONSTANT_ACCESSOR);
    151 #undef HEAP_CONSTANT_ACCESSOR
    152 
    153 #define HEAP_CONSTANT_TEST(rootName, name)         \
    154   Node* CodeStubAssembler::Is##name(Node* value) { \
    155     return WordEqual(value, name##Constant());     \
    156   }
    157 HEAP_CONSTANT_LIST(HEAP_CONSTANT_TEST);
    158 #undef HEAP_CONSTANT_TEST
    159 
    160 Node* CodeStubAssembler::HashSeed() {
    161   return LoadAndUntagToWord32Root(Heap::kHashSeedRootIndex);
    162 }
    163 
    164 Node* CodeStubAssembler::StaleRegisterConstant() {
    165   return LoadRoot(Heap::kStaleRegisterRootIndex);
    166 }
    167 
    168 Node* CodeStubAssembler::IntPtrOrSmiConstant(int value, ParameterMode mode) {
    169   if (mode == SMI_PARAMETERS) {
    170     return SmiConstant(Smi::FromInt(value));
    171   } else {
    172     DCHECK_EQ(INTPTR_PARAMETERS, mode);
    173     return IntPtrConstant(value);
    174   }
    175 }
    176 
    177 bool CodeStubAssembler::IsIntPtrOrSmiConstantZero(Node* test) {
    178   int32_t constant_test;
    179   Smi* smi_test;
    180   if ((ToInt32Constant(test, constant_test) && constant_test == 0) ||
    181       (ToSmiConstant(test, smi_test) && smi_test->value() == 0)) {
    182     return true;
    183   }
    184   return false;
    185 }
    186 
    187 Node* CodeStubAssembler::IntPtrRoundUpToPowerOfTwo32(Node* value) {
    188   Comment("IntPtrRoundUpToPowerOfTwo32");
    189   CSA_ASSERT(this, UintPtrLessThanOrEqual(value, IntPtrConstant(0x80000000u)));
    190   value = IntPtrSub(value, IntPtrConstant(1));
    191   for (int i = 1; i <= 16; i *= 2) {
    192     value = WordOr(value, WordShr(value, IntPtrConstant(i)));
    193   }
    194   return IntPtrAdd(value, IntPtrConstant(1));
    195 }
    196 
    197 Node* CodeStubAssembler::WordIsPowerOfTwo(Node* value) {
    198   // value && !(value & (value - 1))
    199   return WordEqual(
    200       Select(
    201           WordEqual(value, IntPtrConstant(0)),
    202           [=] { return IntPtrConstant(1); },
    203           [=] { return WordAnd(value, IntPtrSub(value, IntPtrConstant(1))); },
    204           MachineType::PointerRepresentation()),
    205       IntPtrConstant(0));
    206 }
    207 
    208 Node* CodeStubAssembler::Float64Round(Node* x) {
    209   Node* one = Float64Constant(1.0);
    210   Node* one_half = Float64Constant(0.5);
    211 
    212   Label return_x(this);
    213 
    214   // Round up {x} towards Infinity.
    215   Variable var_x(this, MachineRepresentation::kFloat64, Float64Ceil(x));
    216 
    217   GotoIf(Float64LessThanOrEqual(Float64Sub(var_x.value(), one_half), x),
    218          &return_x);
    219   var_x.Bind(Float64Sub(var_x.value(), one));
    220   Goto(&return_x);
    221 
    222   Bind(&return_x);
    223   return var_x.value();
    224 }
    225 
    226 Node* CodeStubAssembler::Float64Ceil(Node* x) {
    227   if (IsFloat64RoundUpSupported()) {
    228     return Float64RoundUp(x);
    229   }
    230 
    231   Node* one = Float64Constant(1.0);
    232   Node* zero = Float64Constant(0.0);
    233   Node* two_52 = Float64Constant(4503599627370496.0E0);
    234   Node* minus_two_52 = Float64Constant(-4503599627370496.0E0);
    235 
    236   Variable var_x(this, MachineRepresentation::kFloat64, x);
    237   Label return_x(this), return_minus_x(this);
    238 
    239   // Check if {x} is greater than zero.
    240   Label if_xgreaterthanzero(this), if_xnotgreaterthanzero(this);
    241   Branch(Float64GreaterThan(x, zero), &if_xgreaterthanzero,
    242          &if_xnotgreaterthanzero);
    243 
    244   Bind(&if_xgreaterthanzero);
    245   {
    246     // Just return {x} unless it's in the range ]0,2^52[.
    247     GotoIf(Float64GreaterThanOrEqual(x, two_52), &return_x);
    248 
    249     // Round positive {x} towards Infinity.
    250     var_x.Bind(Float64Sub(Float64Add(two_52, x), two_52));
    251     GotoIfNot(Float64LessThan(var_x.value(), x), &return_x);
    252     var_x.Bind(Float64Add(var_x.value(), one));
    253     Goto(&return_x);
    254   }
    255 
    256   Bind(&if_xnotgreaterthanzero);
    257   {
    258     // Just return {x} unless it's in the range ]-2^52,0[
    259     GotoIf(Float64LessThanOrEqual(x, minus_two_52), &return_x);
    260     GotoIfNot(Float64LessThan(x, zero), &return_x);
    261 
    262     // Round negated {x} towards Infinity and return the result negated.
    263     Node* minus_x = Float64Neg(x);
    264     var_x.Bind(Float64Sub(Float64Add(two_52, minus_x), two_52));
    265     GotoIfNot(Float64GreaterThan(var_x.value(), minus_x), &return_minus_x);
    266     var_x.Bind(Float64Sub(var_x.value(), one));
    267     Goto(&return_minus_x);
    268   }
    269 
    270   Bind(&return_minus_x);
    271   var_x.Bind(Float64Neg(var_x.value()));
    272   Goto(&return_x);
    273 
    274   Bind(&return_x);
    275   return var_x.value();
    276 }
    277 
    278 Node* CodeStubAssembler::Float64Floor(Node* x) {
    279   if (IsFloat64RoundDownSupported()) {
    280     return Float64RoundDown(x);
    281   }
    282 
    283   Node* one = Float64Constant(1.0);
    284   Node* zero = Float64Constant(0.0);
    285   Node* two_52 = Float64Constant(4503599627370496.0E0);
    286   Node* minus_two_52 = Float64Constant(-4503599627370496.0E0);
    287 
    288   Variable var_x(this, MachineRepresentation::kFloat64, x);
    289   Label return_x(this), return_minus_x(this);
    290 
    291   // Check if {x} is greater than zero.
    292   Label if_xgreaterthanzero(this), if_xnotgreaterthanzero(this);
    293   Branch(Float64GreaterThan(x, zero), &if_xgreaterthanzero,
    294          &if_xnotgreaterthanzero);
    295 
    296   Bind(&if_xgreaterthanzero);
    297   {
    298     // Just return {x} unless it's in the range ]0,2^52[.
    299     GotoIf(Float64GreaterThanOrEqual(x, two_52), &return_x);
    300 
    301     // Round positive {x} towards -Infinity.
    302     var_x.Bind(Float64Sub(Float64Add(two_52, x), two_52));
    303     GotoIfNot(Float64GreaterThan(var_x.value(), x), &return_x);
    304     var_x.Bind(Float64Sub(var_x.value(), one));
    305     Goto(&return_x);
    306   }
    307 
    308   Bind(&if_xnotgreaterthanzero);
    309   {
    310     // Just return {x} unless it's in the range ]-2^52,0[
    311     GotoIf(Float64LessThanOrEqual(x, minus_two_52), &return_x);
    312     GotoIfNot(Float64LessThan(x, zero), &return_x);
    313 
    314     // Round negated {x} towards -Infinity and return the result negated.
    315     Node* minus_x = Float64Neg(x);
    316     var_x.Bind(Float64Sub(Float64Add(two_52, minus_x), two_52));
    317     GotoIfNot(Float64LessThan(var_x.value(), minus_x), &return_minus_x);
    318     var_x.Bind(Float64Add(var_x.value(), one));
    319     Goto(&return_minus_x);
    320   }
    321 
    322   Bind(&return_minus_x);
    323   var_x.Bind(Float64Neg(var_x.value()));
    324   Goto(&return_x);
    325 
    326   Bind(&return_x);
    327   return var_x.value();
    328 }
    329 
    330 Node* CodeStubAssembler::Float64RoundToEven(Node* x) {
    331   if (IsFloat64RoundTiesEvenSupported()) {
    332     return Float64RoundTiesEven(x);
    333   }
    334   // See ES#sec-touint8clamp for details.
    335   Node* f = Float64Floor(x);
    336   Node* f_and_half = Float64Add(f, Float64Constant(0.5));
    337 
    338   Variable var_result(this, MachineRepresentation::kFloat64);
    339   Label return_f(this), return_f_plus_one(this), done(this);
    340 
    341   GotoIf(Float64LessThan(f_and_half, x), &return_f_plus_one);
    342   GotoIf(Float64LessThan(x, f_and_half), &return_f);
    343   {
    344     Node* f_mod_2 = Float64Mod(f, Float64Constant(2.0));
    345     Branch(Float64Equal(f_mod_2, Float64Constant(0.0)), &return_f,
    346            &return_f_plus_one);
    347   }
    348 
    349   Bind(&return_f);
    350   var_result.Bind(f);
    351   Goto(&done);
    352 
    353   Bind(&return_f_plus_one);
    354   var_result.Bind(Float64Add(f, Float64Constant(1.0)));
    355   Goto(&done);
    356 
    357   Bind(&done);
    358   return var_result.value();
    359 }
    360 
    361 Node* CodeStubAssembler::Float64Trunc(Node* x) {
    362   if (IsFloat64RoundTruncateSupported()) {
    363     return Float64RoundTruncate(x);
    364   }
    365 
    366   Node* one = Float64Constant(1.0);
    367   Node* zero = Float64Constant(0.0);
    368   Node* two_52 = Float64Constant(4503599627370496.0E0);
    369   Node* minus_two_52 = Float64Constant(-4503599627370496.0E0);
    370 
    371   Variable var_x(this, MachineRepresentation::kFloat64, x);
    372   Label return_x(this), return_minus_x(this);
    373 
    374   // Check if {x} is greater than 0.
    375   Label if_xgreaterthanzero(this), if_xnotgreaterthanzero(this);
    376   Branch(Float64GreaterThan(x, zero), &if_xgreaterthanzero,
    377          &if_xnotgreaterthanzero);
    378 
    379   Bind(&if_xgreaterthanzero);
    380   {
    381     if (IsFloat64RoundDownSupported()) {
    382       var_x.Bind(Float64RoundDown(x));
    383     } else {
    384       // Just return {x} unless it's in the range ]0,2^52[.
    385       GotoIf(Float64GreaterThanOrEqual(x, two_52), &return_x);
    386 
    387       // Round positive {x} towards -Infinity.
    388       var_x.Bind(Float64Sub(Float64Add(two_52, x), two_52));
    389       GotoIfNot(Float64GreaterThan(var_x.value(), x), &return_x);
    390       var_x.Bind(Float64Sub(var_x.value(), one));
    391     }
    392     Goto(&return_x);
    393   }
    394 
    395   Bind(&if_xnotgreaterthanzero);
    396   {
    397     if (IsFloat64RoundUpSupported()) {
    398       var_x.Bind(Float64RoundUp(x));
    399       Goto(&return_x);
    400     } else {
    401       // Just return {x} unless its in the range ]-2^52,0[.
    402       GotoIf(Float64LessThanOrEqual(x, minus_two_52), &return_x);
    403       GotoIfNot(Float64LessThan(x, zero), &return_x);
    404 
    405       // Round negated {x} towards -Infinity and return result negated.
    406       Node* minus_x = Float64Neg(x);
    407       var_x.Bind(Float64Sub(Float64Add(two_52, minus_x), two_52));
    408       GotoIfNot(Float64GreaterThan(var_x.value(), minus_x), &return_minus_x);
    409       var_x.Bind(Float64Sub(var_x.value(), one));
    410       Goto(&return_minus_x);
    411     }
    412   }
    413 
    414   Bind(&return_minus_x);
    415   var_x.Bind(Float64Neg(var_x.value()));
    416   Goto(&return_x);
    417 
    418   Bind(&return_x);
    419   return var_x.value();
    420 }
    421 
    422 Node* CodeStubAssembler::SmiShiftBitsConstant() {
    423   return IntPtrConstant(kSmiShiftSize + kSmiTagSize);
    424 }
    425 
    426 Node* CodeStubAssembler::SmiFromWord32(Node* value) {
    427   value = ChangeInt32ToIntPtr(value);
    428   return BitcastWordToTaggedSigned(WordShl(value, SmiShiftBitsConstant()));
    429 }
    430 
    431 Node* CodeStubAssembler::SmiTag(Node* value) {
    432   int32_t constant_value;
    433   if (ToInt32Constant(value, constant_value) && Smi::IsValid(constant_value)) {
    434     return SmiConstant(Smi::FromInt(constant_value));
    435   }
    436   return BitcastWordToTaggedSigned(WordShl(value, SmiShiftBitsConstant()));
    437 }
    438 
    439 Node* CodeStubAssembler::SmiUntag(Node* value) {
    440   return WordSar(BitcastTaggedToWord(value), SmiShiftBitsConstant());
    441 }
    442 
    443 Node* CodeStubAssembler::SmiToWord32(Node* value) {
    444   Node* result = SmiUntag(value);
    445   return TruncateWordToWord32(result);
    446 }
    447 
    448 Node* CodeStubAssembler::SmiToFloat64(Node* value) {
    449   return ChangeInt32ToFloat64(SmiToWord32(value));
    450 }
    451 
    452 Node* CodeStubAssembler::SmiMax(Node* a, Node* b) {
    453   return SelectTaggedConstant(SmiLessThan(a, b), b, a);
    454 }
    455 
    456 Node* CodeStubAssembler::SmiMin(Node* a, Node* b) {
    457   return SelectTaggedConstant(SmiLessThan(a, b), a, b);
    458 }
    459 
    460 Node* CodeStubAssembler::SmiMod(Node* a, Node* b) {
    461   Variable var_result(this, MachineRepresentation::kTagged);
    462   Label return_result(this, &var_result),
    463       return_minuszero(this, Label::kDeferred),
    464       return_nan(this, Label::kDeferred);
    465 
    466   // Untag {a} and {b}.
    467   a = SmiToWord32(a);
    468   b = SmiToWord32(b);
    469 
    470   // Return NaN if {b} is zero.
    471   GotoIf(Word32Equal(b, Int32Constant(0)), &return_nan);
    472 
    473   // Check if {a} is non-negative.
    474   Label if_aisnotnegative(this), if_aisnegative(this, Label::kDeferred);
    475   Branch(Int32LessThanOrEqual(Int32Constant(0), a), &if_aisnotnegative,
    476          &if_aisnegative);
    477 
    478   Bind(&if_aisnotnegative);
    479   {
    480     // Fast case, don't need to check any other edge cases.
    481     Node* r = Int32Mod(a, b);
    482     var_result.Bind(SmiFromWord32(r));
    483     Goto(&return_result);
    484   }
    485 
    486   Bind(&if_aisnegative);
    487   {
    488     if (SmiValuesAre32Bits()) {
    489       // Check if {a} is kMinInt and {b} is -1 (only relevant if the
    490       // kMinInt is actually representable as a Smi).
    491       Label join(this);
    492       GotoIfNot(Word32Equal(a, Int32Constant(kMinInt)), &join);
    493       GotoIf(Word32Equal(b, Int32Constant(-1)), &return_minuszero);
    494       Goto(&join);
    495       Bind(&join);
    496     }
    497 
    498     // Perform the integer modulus operation.
    499     Node* r = Int32Mod(a, b);
    500 
    501     // Check if {r} is zero, and if so return -0, because we have to
    502     // take the sign of the left hand side {a}, which is negative.
    503     GotoIf(Word32Equal(r, Int32Constant(0)), &return_minuszero);
    504 
    505     // The remainder {r} can be outside the valid Smi range on 32bit
    506     // architectures, so we cannot just say SmiFromWord32(r) here.
    507     var_result.Bind(ChangeInt32ToTagged(r));
    508     Goto(&return_result);
    509   }
    510 
    511   Bind(&return_minuszero);
    512   var_result.Bind(MinusZeroConstant());
    513   Goto(&return_result);
    514 
    515   Bind(&return_nan);
    516   var_result.Bind(NanConstant());
    517   Goto(&return_result);
    518 
    519   Bind(&return_result);
    520   return var_result.value();
    521 }
    522 
    523 Node* CodeStubAssembler::SmiMul(Node* a, Node* b) {
    524   Variable var_result(this, MachineRepresentation::kTagged);
    525   Variable var_lhs_float64(this, MachineRepresentation::kFloat64),
    526       var_rhs_float64(this, MachineRepresentation::kFloat64);
    527   Label return_result(this, &var_result);
    528 
    529   // Both {a} and {b} are Smis. Convert them to integers and multiply.
    530   Node* lhs32 = SmiToWord32(a);
    531   Node* rhs32 = SmiToWord32(b);
    532   Node* pair = Int32MulWithOverflow(lhs32, rhs32);
    533 
    534   Node* overflow = Projection(1, pair);
    535 
    536   // Check if the multiplication overflowed.
    537   Label if_overflow(this, Label::kDeferred), if_notoverflow(this);
    538   Branch(overflow, &if_overflow, &if_notoverflow);
    539   Bind(&if_notoverflow);
    540   {
    541     // If the answer is zero, we may need to return -0.0, depending on the
    542     // input.
    543     Label answer_zero(this), answer_not_zero(this);
    544     Node* answer = Projection(0, pair);
    545     Node* zero = Int32Constant(0);
    546     Branch(Word32Equal(answer, zero), &answer_zero, &answer_not_zero);
    547     Bind(&answer_not_zero);
    548     {
    549       var_result.Bind(ChangeInt32ToTagged(answer));
    550       Goto(&return_result);
    551     }
    552     Bind(&answer_zero);
    553     {
    554       Node* or_result = Word32Or(lhs32, rhs32);
    555       Label if_should_be_negative_zero(this), if_should_be_zero(this);
    556       Branch(Int32LessThan(or_result, zero), &if_should_be_negative_zero,
    557              &if_should_be_zero);
    558       Bind(&if_should_be_negative_zero);
    559       {
    560         var_result.Bind(MinusZeroConstant());
    561         Goto(&return_result);
    562       }
    563       Bind(&if_should_be_zero);
    564       {
    565         var_result.Bind(SmiConstant(0));
    566         Goto(&return_result);
    567       }
    568     }
    569   }
    570   Bind(&if_overflow);
    571   {
    572     var_lhs_float64.Bind(SmiToFloat64(a));
    573     var_rhs_float64.Bind(SmiToFloat64(b));
    574     Node* value = Float64Mul(var_lhs_float64.value(), var_rhs_float64.value());
    575     Node* result = AllocateHeapNumberWithValue(value);
    576     var_result.Bind(result);
    577     Goto(&return_result);
    578   }
    579 
    580   Bind(&return_result);
    581   return var_result.value();
    582 }
    583 
    584 Node* CodeStubAssembler::TruncateWordToWord32(Node* value) {
    585   if (Is64()) {
    586     return TruncateInt64ToInt32(value);
    587   }
    588   return value;
    589 }
    590 
    591 Node* CodeStubAssembler::TaggedIsSmi(Node* a) {
    592   return WordEqual(WordAnd(BitcastTaggedToWord(a), IntPtrConstant(kSmiTagMask)),
    593                    IntPtrConstant(0));
    594 }
    595 
    596 Node* CodeStubAssembler::TaggedIsNotSmi(Node* a) {
    597   return WordNotEqual(
    598       WordAnd(BitcastTaggedToWord(a), IntPtrConstant(kSmiTagMask)),
    599       IntPtrConstant(0));
    600 }
    601 
    602 Node* CodeStubAssembler::TaggedIsPositiveSmi(Node* a) {
    603   return WordEqual(WordAnd(BitcastTaggedToWord(a),
    604                            IntPtrConstant(kSmiTagMask | kSmiSignMask)),
    605                    IntPtrConstant(0));
    606 }
    607 
    608 Node* CodeStubAssembler::WordIsWordAligned(Node* word) {
    609   return WordEqual(IntPtrConstant(0),
    610                    WordAnd(word, IntPtrConstant((1 << kPointerSizeLog2) - 1)));
    611 }
    612 
    613 void CodeStubAssembler::BranchIfPrototypesHaveNoElements(
    614     Node* receiver_map, Label* definitely_no_elements,
    615     Label* possibly_elements) {
    616   Variable var_map(this, MachineRepresentation::kTagged, receiver_map);
    617   Label loop_body(this, &var_map);
    618   Node* empty_elements = LoadRoot(Heap::kEmptyFixedArrayRootIndex);
    619   Goto(&loop_body);
    620 
    621   Bind(&loop_body);
    622   {
    623     Node* map = var_map.value();
    624     Node* prototype = LoadMapPrototype(map);
    625     GotoIf(WordEqual(prototype, NullConstant()), definitely_no_elements);
    626     Node* prototype_map = LoadMap(prototype);
    627     // Pessimistically assume elements if a Proxy, Special API Object,
    628     // or JSValue wrapper is found on the prototype chain. After this
    629     // instance type check, it's not necessary to check for interceptors or
    630     // access checks.
    631     GotoIf(Int32LessThanOrEqual(LoadMapInstanceType(prototype_map),
    632                                 Int32Constant(LAST_CUSTOM_ELEMENTS_RECEIVER)),
    633            possibly_elements);
    634     GotoIf(WordNotEqual(LoadElements(prototype), empty_elements),
    635            possibly_elements);
    636     var_map.Bind(prototype_map);
    637     Goto(&loop_body);
    638   }
    639 }
    640 
    641 void CodeStubAssembler::BranchIfJSReceiver(Node* object, Label* if_true,
    642                                            Label* if_false) {
    643   GotoIf(TaggedIsSmi(object), if_false);
    644   STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
    645   Branch(Int32GreaterThanOrEqual(LoadInstanceType(object),
    646                                  Int32Constant(FIRST_JS_RECEIVER_TYPE)),
    647          if_true, if_false);
    648 }
    649 
    650 void CodeStubAssembler::BranchIfJSObject(Node* object, Label* if_true,
    651                                          Label* if_false) {
    652   GotoIf(TaggedIsSmi(object), if_false);
    653   STATIC_ASSERT(LAST_JS_OBJECT_TYPE == LAST_TYPE);
    654   Branch(Int32GreaterThanOrEqual(LoadInstanceType(object),
    655                                  Int32Constant(FIRST_JS_OBJECT_TYPE)),
    656          if_true, if_false);
    657 }
    658 
    659 void CodeStubAssembler::BranchIfFastJSArray(
    660     Node* object, Node* context, CodeStubAssembler::FastJSArrayAccessMode mode,
    661     Label* if_true, Label* if_false) {
    662   // Bailout if receiver is a Smi.
    663   GotoIf(TaggedIsSmi(object), if_false);
    664 
    665   Node* map = LoadMap(object);
    666 
    667   // Bailout if instance type is not JS_ARRAY_TYPE.
    668   GotoIf(Word32NotEqual(LoadMapInstanceType(map), Int32Constant(JS_ARRAY_TYPE)),
    669          if_false);
    670 
    671   Node* elements_kind = LoadMapElementsKind(map);
    672 
    673   // Bailout if receiver has slow elements.
    674   GotoIfNot(IsFastElementsKind(elements_kind), if_false);
    675 
    676   // Check prototype chain if receiver does not have packed elements.
    677   if (mode == FastJSArrayAccessMode::INBOUNDS_READ) {
    678     GotoIfNot(IsHoleyFastElementsKind(elements_kind), if_true);
    679   }
    680   BranchIfPrototypesHaveNoElements(map, if_true, if_false);
    681 }
    682 
    683 Node* CodeStubAssembler::AllocateRawUnaligned(Node* size_in_bytes,
    684                                               AllocationFlags flags,
    685                                               Node* top_address,
    686                                               Node* limit_address) {
    687   Node* top = Load(MachineType::Pointer(), top_address);
    688   Node* limit = Load(MachineType::Pointer(), limit_address);
    689 
    690   // If there's not enough space, call the runtime.
    691   Variable result(this, MachineRepresentation::kTagged);
    692   Label runtime_call(this, Label::kDeferred), no_runtime_call(this);
    693   Label merge_runtime(this, &result);
    694 
    695   if (flags & kAllowLargeObjectAllocation) {
    696     Label next(this);
    697     GotoIf(IsRegularHeapObjectSize(size_in_bytes), &next);
    698 
    699     Node* runtime_flags = SmiConstant(
    700         Smi::FromInt(AllocateDoubleAlignFlag::encode(false) |
    701                      AllocateTargetSpace::encode(AllocationSpace::LO_SPACE)));
    702     Node* const runtime_result =
    703         CallRuntime(Runtime::kAllocateInTargetSpace, NoContextConstant(),
    704                     SmiTag(size_in_bytes), runtime_flags);
    705     result.Bind(runtime_result);
    706     Goto(&merge_runtime);
    707 
    708     Bind(&next);
    709   }
    710 
    711   Node* new_top = IntPtrAdd(top, size_in_bytes);
    712   Branch(UintPtrGreaterThanOrEqual(new_top, limit), &runtime_call,
    713          &no_runtime_call);
    714 
    715   Bind(&runtime_call);
    716   Node* runtime_result;
    717   if (flags & kPretenured) {
    718     Node* runtime_flags = SmiConstant(
    719         Smi::FromInt(AllocateDoubleAlignFlag::encode(false) |
    720                      AllocateTargetSpace::encode(AllocationSpace::OLD_SPACE)));
    721     runtime_result =
    722         CallRuntime(Runtime::kAllocateInTargetSpace, NoContextConstant(),
    723                     SmiTag(size_in_bytes), runtime_flags);
    724   } else {
    725     runtime_result = CallRuntime(Runtime::kAllocateInNewSpace,
    726                                  NoContextConstant(), SmiTag(size_in_bytes));
    727   }
    728   result.Bind(runtime_result);
    729   Goto(&merge_runtime);
    730 
    731   // When there is enough space, return `top' and bump it up.
    732   Bind(&no_runtime_call);
    733   Node* no_runtime_result = top;
    734   StoreNoWriteBarrier(MachineType::PointerRepresentation(), top_address,
    735                       new_top);
    736   no_runtime_result = BitcastWordToTagged(
    737       IntPtrAdd(no_runtime_result, IntPtrConstant(kHeapObjectTag)));
    738   result.Bind(no_runtime_result);
    739   Goto(&merge_runtime);
    740 
    741   Bind(&merge_runtime);
    742   return result.value();
    743 }
    744 
    745 Node* CodeStubAssembler::AllocateRawAligned(Node* size_in_bytes,
    746                                             AllocationFlags flags,
    747                                             Node* top_address,
    748                                             Node* limit_address) {
    749   Node* top = Load(MachineType::Pointer(), top_address);
    750   Node* limit = Load(MachineType::Pointer(), limit_address);
    751   Variable adjusted_size(this, MachineType::PointerRepresentation(),
    752                          size_in_bytes);
    753   if (flags & kDoubleAlignment) {
    754     Label aligned(this), not_aligned(this), merge(this, &adjusted_size);
    755     Branch(WordAnd(top, IntPtrConstant(kDoubleAlignmentMask)), &not_aligned,
    756            &aligned);
    757 
    758     Bind(&not_aligned);
    759     Node* not_aligned_size =
    760         IntPtrAdd(size_in_bytes, IntPtrConstant(kPointerSize));
    761     adjusted_size.Bind(not_aligned_size);
    762     Goto(&merge);
    763 
    764     Bind(&aligned);
    765     Goto(&merge);
    766 
    767     Bind(&merge);
    768   }
    769 
    770   Variable address(
    771       this, MachineRepresentation::kTagged,
    772       AllocateRawUnaligned(adjusted_size.value(), kNone, top, limit));
    773 
    774   Label needs_filler(this), doesnt_need_filler(this),
    775       merge_address(this, &address);
    776   Branch(IntPtrEqual(adjusted_size.value(), size_in_bytes), &doesnt_need_filler,
    777          &needs_filler);
    778 
    779   Bind(&needs_filler);
    780   // Store a filler and increase the address by kPointerSize.
    781   StoreNoWriteBarrier(MachineType::PointerRepresentation(), top,
    782                       LoadRoot(Heap::kOnePointerFillerMapRootIndex));
    783   address.Bind(BitcastWordToTagged(
    784       IntPtrAdd(address.value(), IntPtrConstant(kPointerSize))));
    785   Goto(&merge_address);
    786 
    787   Bind(&doesnt_need_filler);
    788   Goto(&merge_address);
    789 
    790   Bind(&merge_address);
    791   // Update the top.
    792   StoreNoWriteBarrier(MachineType::PointerRepresentation(), top_address,
    793                       IntPtrAdd(top, adjusted_size.value()));
    794   return address.value();
    795 }
    796 
    797 Node* CodeStubAssembler::Allocate(Node* size_in_bytes, AllocationFlags flags) {
    798   Comment("Allocate");
    799   bool const new_space = !(flags & kPretenured);
    800   Node* top_address = ExternalConstant(
    801       new_space
    802           ? ExternalReference::new_space_allocation_top_address(isolate())
    803           : ExternalReference::old_space_allocation_top_address(isolate()));
    804   DCHECK_EQ(kPointerSize,
    805             ExternalReference::new_space_allocation_limit_address(isolate())
    806                     .address() -
    807                 ExternalReference::new_space_allocation_top_address(isolate())
    808                     .address());
    809   DCHECK_EQ(kPointerSize,
    810             ExternalReference::old_space_allocation_limit_address(isolate())
    811                     .address() -
    812                 ExternalReference::old_space_allocation_top_address(isolate())
    813                     .address());
    814   Node* limit_address = IntPtrAdd(top_address, IntPtrConstant(kPointerSize));
    815 
    816 #ifdef V8_HOST_ARCH_32_BIT
    817   if (flags & kDoubleAlignment) {
    818     return AllocateRawAligned(size_in_bytes, flags, top_address, limit_address);
    819   }
    820 #endif
    821 
    822   return AllocateRawUnaligned(size_in_bytes, flags, top_address, limit_address);
    823 }
    824 
    825 Node* CodeStubAssembler::Allocate(int size_in_bytes, AllocationFlags flags) {
    826   return CodeStubAssembler::Allocate(IntPtrConstant(size_in_bytes), flags);
    827 }
    828 
    829 Node* CodeStubAssembler::InnerAllocate(Node* previous, Node* offset) {
    830   return BitcastWordToTagged(IntPtrAdd(BitcastTaggedToWord(previous), offset));
    831 }
    832 
    833 Node* CodeStubAssembler::InnerAllocate(Node* previous, int offset) {
    834   return InnerAllocate(previous, IntPtrConstant(offset));
    835 }
    836 
    837 Node* CodeStubAssembler::IsRegularHeapObjectSize(Node* size) {
    838   return UintPtrLessThanOrEqual(size,
    839                                 IntPtrConstant(kMaxRegularHeapObjectSize));
    840 }
    841 
    842 void CodeStubAssembler::BranchIfToBooleanIsTrue(Node* value, Label* if_true,
    843                                                 Label* if_false) {
    844   Label if_valueissmi(this), if_valueisnotsmi(this),
    845       if_valueisheapnumber(this, Label::kDeferred);
    846 
    847   // Rule out false {value}.
    848   GotoIf(WordEqual(value, BooleanConstant(false)), if_false);
    849 
    850   // Check if {value} is a Smi or a HeapObject.
    851   Branch(TaggedIsSmi(value), &if_valueissmi, &if_valueisnotsmi);
    852 
    853   Bind(&if_valueissmi);
    854   {
    855     // The {value} is a Smi, only need to check against zero.
    856     BranchIfSmiEqual(value, SmiConstant(0), if_false, if_true);
    857   }
    858 
    859   Bind(&if_valueisnotsmi);
    860   {
    861     // Check if {value} is the empty string.
    862     GotoIf(IsEmptyString(value), if_false);
    863 
    864     // The {value} is a HeapObject, load its map.
    865     Node* value_map = LoadMap(value);
    866 
    867     // Only null, undefined and document.all have the undetectable bit set,
    868     // so we can return false immediately when that bit is set.
    869     Node* value_map_bitfield = LoadMapBitField(value_map);
    870     Node* value_map_undetectable =
    871         Word32And(value_map_bitfield, Int32Constant(1 << Map::kIsUndetectable));
    872 
    873     // Check if the {value} is undetectable.
    874     GotoIfNot(Word32Equal(value_map_undetectable, Int32Constant(0)), if_false);
    875 
    876     // We still need to handle numbers specially, but all other {value}s
    877     // that make it here yield true.
    878     Branch(IsHeapNumberMap(value_map), &if_valueisheapnumber, if_true);
    879 
    880     Bind(&if_valueisheapnumber);
    881     {
    882       // Load the floating point value of {value}.
    883       Node* value_value = LoadObjectField(value, HeapNumber::kValueOffset,
    884                                           MachineType::Float64());
    885 
    886       // Check if the floating point {value} is neither 0.0, -0.0 nor NaN.
    887       Branch(Float64LessThan(Float64Constant(0.0), Float64Abs(value_value)),
    888              if_true, if_false);
    889     }
    890   }
    891 }
    892 
    893 Node* CodeStubAssembler::LoadFromFrame(int offset, MachineType rep) {
    894   Node* frame_pointer = LoadFramePointer();
    895   return Load(rep, frame_pointer, IntPtrConstant(offset));
    896 }
    897 
    898 Node* CodeStubAssembler::LoadFromParentFrame(int offset, MachineType rep) {
    899   Node* frame_pointer = LoadParentFramePointer();
    900   return Load(rep, frame_pointer, IntPtrConstant(offset));
    901 }
    902 
    903 Node* CodeStubAssembler::LoadBufferObject(Node* buffer, int offset,
    904                                           MachineType rep) {
    905   return Load(rep, buffer, IntPtrConstant(offset));
    906 }
    907 
    908 Node* CodeStubAssembler::LoadObjectField(Node* object, int offset,
    909                                          MachineType rep) {
    910   return Load(rep, object, IntPtrConstant(offset - kHeapObjectTag));
    911 }
    912 
    913 Node* CodeStubAssembler::LoadObjectField(Node* object, Node* offset,
    914                                          MachineType rep) {
    915   return Load(rep, object, IntPtrSub(offset, IntPtrConstant(kHeapObjectTag)));
    916 }
    917 
    918 Node* CodeStubAssembler::LoadAndUntagObjectField(Node* object, int offset) {
    919   if (Is64()) {
    920 #if V8_TARGET_LITTLE_ENDIAN
    921     offset += kPointerSize / 2;
    922 #endif
    923     return ChangeInt32ToInt64(
    924         LoadObjectField(object, offset, MachineType::Int32()));
    925   } else {
    926     return SmiToWord(LoadObjectField(object, offset, MachineType::AnyTagged()));
    927   }
    928 }
    929 
    930 Node* CodeStubAssembler::LoadAndUntagToWord32ObjectField(Node* object,
    931                                                          int offset) {
    932   if (Is64()) {
    933 #if V8_TARGET_LITTLE_ENDIAN
    934     offset += kPointerSize / 2;
    935 #endif
    936     return LoadObjectField(object, offset, MachineType::Int32());
    937   } else {
    938     return SmiToWord32(
    939         LoadObjectField(object, offset, MachineType::AnyTagged()));
    940   }
    941 }
    942 
    943 Node* CodeStubAssembler::LoadAndUntagSmi(Node* base, int index) {
    944   if (Is64()) {
    945 #if V8_TARGET_LITTLE_ENDIAN
    946     index += kPointerSize / 2;
    947 #endif
    948     return ChangeInt32ToInt64(
    949         Load(MachineType::Int32(), base, IntPtrConstant(index)));
    950   } else {
    951     return SmiToWord(
    952         Load(MachineType::AnyTagged(), base, IntPtrConstant(index)));
    953   }
    954 }
    955 
    956 Node* CodeStubAssembler::LoadAndUntagToWord32Root(
    957     Heap::RootListIndex root_index) {
    958   Node* roots_array_start =
    959       ExternalConstant(ExternalReference::roots_array_start(isolate()));
    960   int index = root_index * kPointerSize;
    961   if (Is64()) {
    962 #if V8_TARGET_LITTLE_ENDIAN
    963     index += kPointerSize / 2;
    964 #endif
    965     return Load(MachineType::Int32(), roots_array_start, IntPtrConstant(index));
    966   } else {
    967     return SmiToWord32(Load(MachineType::AnyTagged(), roots_array_start,
    968                             IntPtrConstant(index)));
    969   }
    970 }
    971 
    972 Node* CodeStubAssembler::StoreAndTagSmi(Node* base, int offset, Node* value) {
    973   if (Is64()) {
    974     int zero_offset = offset + kPointerSize / 2;
    975     int payload_offset = offset;
    976 #if V8_TARGET_LITTLE_ENDIAN
    977     std::swap(zero_offset, payload_offset);
    978 #endif
    979     StoreNoWriteBarrier(MachineRepresentation::kWord32, base,
    980                         IntPtrConstant(zero_offset), Int32Constant(0));
    981     return StoreNoWriteBarrier(MachineRepresentation::kWord32, base,
    982                                IntPtrConstant(payload_offset),
    983                                TruncateInt64ToInt32(value));
    984   } else {
    985     return StoreNoWriteBarrier(MachineRepresentation::kTaggedSigned, base,
    986                                IntPtrConstant(offset), SmiTag(value));
    987   }
    988 }
    989 
    990 Node* CodeStubAssembler::LoadHeapNumberValue(Node* object) {
    991   return LoadObjectField(object, HeapNumber::kValueOffset,
    992                          MachineType::Float64());
    993 }
    994 
    995 Node* CodeStubAssembler::LoadMap(Node* object) {
    996   return LoadObjectField(object, HeapObject::kMapOffset);
    997 }
    998 
    999 Node* CodeStubAssembler::LoadInstanceType(Node* object) {
   1000   return LoadMapInstanceType(LoadMap(object));
   1001 }
   1002 
   1003 Node* CodeStubAssembler::HasInstanceType(Node* object,
   1004                                          InstanceType instance_type) {
   1005   return Word32Equal(LoadInstanceType(object), Int32Constant(instance_type));
   1006 }
   1007 
   1008 Node* CodeStubAssembler::DoesntHaveInstanceType(Node* object,
   1009                                                 InstanceType instance_type) {
   1010   return Word32NotEqual(LoadInstanceType(object), Int32Constant(instance_type));
   1011 }
   1012 
   1013 Node* CodeStubAssembler::LoadProperties(Node* object) {
   1014   return LoadObjectField(object, JSObject::kPropertiesOffset);
   1015 }
   1016 
   1017 Node* CodeStubAssembler::LoadElements(Node* object) {
   1018   return LoadObjectField(object, JSObject::kElementsOffset);
   1019 }
   1020 
   1021 Node* CodeStubAssembler::LoadJSArrayLength(Node* array) {
   1022   CSA_ASSERT(this, IsJSArray(array));
   1023   return LoadObjectField(array, JSArray::kLengthOffset);
   1024 }
   1025 
   1026 Node* CodeStubAssembler::LoadFixedArrayBaseLength(Node* array) {
   1027   return LoadObjectField(array, FixedArrayBase::kLengthOffset);
   1028 }
   1029 
   1030 Node* CodeStubAssembler::LoadAndUntagFixedArrayBaseLength(Node* array) {
   1031   return LoadAndUntagObjectField(array, FixedArrayBase::kLengthOffset);
   1032 }
   1033 
   1034 Node* CodeStubAssembler::LoadMapBitField(Node* map) {
   1035   CSA_SLOW_ASSERT(this, IsMap(map));
   1036   return LoadObjectField(map, Map::kBitFieldOffset, MachineType::Uint8());
   1037 }
   1038 
   1039 Node* CodeStubAssembler::LoadMapBitField2(Node* map) {
   1040   CSA_SLOW_ASSERT(this, IsMap(map));
   1041   return LoadObjectField(map, Map::kBitField2Offset, MachineType::Uint8());
   1042 }
   1043 
   1044 Node* CodeStubAssembler::LoadMapBitField3(Node* map) {
   1045   CSA_SLOW_ASSERT(this, IsMap(map));
   1046   return LoadObjectField(map, Map::kBitField3Offset, MachineType::Uint32());
   1047 }
   1048 
   1049 Node* CodeStubAssembler::LoadMapInstanceType(Node* map) {
   1050   return LoadObjectField(map, Map::kInstanceTypeOffset, MachineType::Uint8());
   1051 }
   1052 
   1053 Node* CodeStubAssembler::LoadMapElementsKind(Node* map) {
   1054   CSA_SLOW_ASSERT(this, IsMap(map));
   1055   Node* bit_field2 = LoadMapBitField2(map);
   1056   return DecodeWord32<Map::ElementsKindBits>(bit_field2);
   1057 }
   1058 
   1059 Node* CodeStubAssembler::LoadMapDescriptors(Node* map) {
   1060   CSA_SLOW_ASSERT(this, IsMap(map));
   1061   return LoadObjectField(map, Map::kDescriptorsOffset);
   1062 }
   1063 
   1064 Node* CodeStubAssembler::LoadMapPrototype(Node* map) {
   1065   CSA_SLOW_ASSERT(this, IsMap(map));
   1066   return LoadObjectField(map, Map::kPrototypeOffset);
   1067 }
   1068 
   1069 Node* CodeStubAssembler::LoadMapPrototypeInfo(Node* map,
   1070                                               Label* if_no_proto_info) {
   1071   CSA_ASSERT(this, IsMap(map));
   1072   Node* prototype_info =
   1073       LoadObjectField(map, Map::kTransitionsOrPrototypeInfoOffset);
   1074   GotoIf(TaggedIsSmi(prototype_info), if_no_proto_info);
   1075   GotoIfNot(WordEqual(LoadMap(prototype_info),
   1076                       LoadRoot(Heap::kPrototypeInfoMapRootIndex)),
   1077             if_no_proto_info);
   1078   return prototype_info;
   1079 }
   1080 
   1081 Node* CodeStubAssembler::LoadMapInstanceSize(Node* map) {
   1082   CSA_SLOW_ASSERT(this, IsMap(map));
   1083   return ChangeUint32ToWord(
   1084       LoadObjectField(map, Map::kInstanceSizeOffset, MachineType::Uint8()));
   1085 }
   1086 
   1087 Node* CodeStubAssembler::LoadMapInobjectProperties(Node* map) {
   1088   CSA_SLOW_ASSERT(this, IsMap(map));
   1089   // See Map::GetInObjectProperties() for details.
   1090   STATIC_ASSERT(LAST_JS_OBJECT_TYPE == LAST_TYPE);
   1091   CSA_ASSERT(this,
   1092              Int32GreaterThanOrEqual(LoadMapInstanceType(map),
   1093                                      Int32Constant(FIRST_JS_OBJECT_TYPE)));
   1094   return ChangeUint32ToWord(LoadObjectField(
   1095       map, Map::kInObjectPropertiesOrConstructorFunctionIndexOffset,
   1096       MachineType::Uint8()));
   1097 }
   1098 
   1099 Node* CodeStubAssembler::LoadMapConstructorFunctionIndex(Node* map) {
   1100   CSA_SLOW_ASSERT(this, IsMap(map));
   1101   // See Map::GetConstructorFunctionIndex() for details.
   1102   STATIC_ASSERT(FIRST_PRIMITIVE_TYPE == FIRST_TYPE);
   1103   CSA_ASSERT(this, Int32LessThanOrEqual(LoadMapInstanceType(map),
   1104                                         Int32Constant(LAST_PRIMITIVE_TYPE)));
   1105   return ChangeUint32ToWord(LoadObjectField(
   1106       map, Map::kInObjectPropertiesOrConstructorFunctionIndexOffset,
   1107       MachineType::Uint8()));
   1108 }
   1109 
   1110 Node* CodeStubAssembler::LoadMapConstructor(Node* map) {
   1111   CSA_SLOW_ASSERT(this, IsMap(map));
   1112   Variable result(this, MachineRepresentation::kTagged,
   1113                   LoadObjectField(map, Map::kConstructorOrBackPointerOffset));
   1114 
   1115   Label done(this), loop(this, &result);
   1116   Goto(&loop);
   1117   Bind(&loop);
   1118   {
   1119     GotoIf(TaggedIsSmi(result.value()), &done);
   1120     Node* is_map_type =
   1121         Word32Equal(LoadInstanceType(result.value()), Int32Constant(MAP_TYPE));
   1122     GotoIfNot(is_map_type, &done);
   1123     result.Bind(
   1124         LoadObjectField(result.value(), Map::kConstructorOrBackPointerOffset));
   1125     Goto(&loop);
   1126   }
   1127   Bind(&done);
   1128   return result.value();
   1129 }
   1130 
   1131 Node* CodeStubAssembler::LoadSharedFunctionInfoSpecialField(
   1132     Node* shared, int offset, ParameterMode mode) {
   1133   if (Is64()) {
   1134     Node* result = LoadObjectField(shared, offset, MachineType::Int32());
   1135     if (mode == SMI_PARAMETERS) {
   1136       result = SmiTag(result);
   1137     } else {
   1138       result = ChangeUint32ToWord(result);
   1139     }
   1140     return result;
   1141   } else {
   1142     Node* result = LoadObjectField(shared, offset);
   1143     if (mode != SMI_PARAMETERS) {
   1144       result = SmiUntag(result);
   1145     }
   1146     return result;
   1147   }
   1148 }
   1149 
   1150 Node* CodeStubAssembler::LoadNameHashField(Node* name) {
   1151   CSA_ASSERT(this, IsName(name));
   1152   return LoadObjectField(name, Name::kHashFieldOffset, MachineType::Uint32());
   1153 }
   1154 
   1155 Node* CodeStubAssembler::LoadNameHash(Node* name, Label* if_hash_not_computed) {
   1156   Node* hash_field = LoadNameHashField(name);
   1157   if (if_hash_not_computed != nullptr) {
   1158     GotoIf(Word32Equal(
   1159                Word32And(hash_field, Int32Constant(Name::kHashNotComputedMask)),
   1160                Int32Constant(0)),
   1161            if_hash_not_computed);
   1162   }
   1163   return Word32Shr(hash_field, Int32Constant(Name::kHashShift));
   1164 }
   1165 
   1166 Node* CodeStubAssembler::LoadStringLength(Node* object) {
   1167   CSA_ASSERT(this, IsString(object));
   1168   return LoadObjectField(object, String::kLengthOffset);
   1169 }
   1170 
   1171 Node* CodeStubAssembler::LoadJSValueValue(Node* object) {
   1172   CSA_ASSERT(this, IsJSValue(object));
   1173   return LoadObjectField(object, JSValue::kValueOffset);
   1174 }
   1175 
   1176 Node* CodeStubAssembler::LoadWeakCellValueUnchecked(Node* weak_cell) {
   1177   // TODO(ishell): fix callers.
   1178   return LoadObjectField(weak_cell, WeakCell::kValueOffset);
   1179 }
   1180 
   1181 Node* CodeStubAssembler::LoadWeakCellValue(Node* weak_cell, Label* if_cleared) {
   1182   CSA_ASSERT(this, IsWeakCell(weak_cell));
   1183   Node* value = LoadWeakCellValueUnchecked(weak_cell);
   1184   if (if_cleared != nullptr) {
   1185     GotoIf(WordEqual(value, IntPtrConstant(0)), if_cleared);
   1186   }
   1187   return value;
   1188 }
   1189 
   1190 Node* CodeStubAssembler::LoadFixedArrayElement(Node* object, Node* index_node,
   1191                                                int additional_offset,
   1192                                                ParameterMode parameter_mode) {
   1193   int32_t header_size =
   1194       FixedArray::kHeaderSize + additional_offset - kHeapObjectTag;
   1195   Node* offset = ElementOffsetFromIndex(index_node, FAST_HOLEY_ELEMENTS,
   1196                                         parameter_mode, header_size);
   1197   return Load(MachineType::AnyTagged(), object, offset);
   1198 }
   1199 
   1200 Node* CodeStubAssembler::LoadFixedTypedArrayElement(
   1201     Node* data_pointer, Node* index_node, ElementsKind elements_kind,
   1202     ParameterMode parameter_mode) {
   1203   Node* offset =
   1204       ElementOffsetFromIndex(index_node, elements_kind, parameter_mode, 0);
   1205   MachineType type;
   1206   switch (elements_kind) {
   1207     case UINT8_ELEMENTS: /* fall through */
   1208     case UINT8_CLAMPED_ELEMENTS:
   1209       type = MachineType::Uint8();
   1210       break;
   1211     case INT8_ELEMENTS:
   1212       type = MachineType::Int8();
   1213       break;
   1214     case UINT16_ELEMENTS:
   1215       type = MachineType::Uint16();
   1216       break;
   1217     case INT16_ELEMENTS:
   1218       type = MachineType::Int16();
   1219       break;
   1220     case UINT32_ELEMENTS:
   1221       type = MachineType::Uint32();
   1222       break;
   1223     case INT32_ELEMENTS:
   1224       type = MachineType::Int32();
   1225       break;
   1226     case FLOAT32_ELEMENTS:
   1227       type = MachineType::Float32();
   1228       break;
   1229     case FLOAT64_ELEMENTS:
   1230       type = MachineType::Float64();
   1231       break;
   1232     default:
   1233       UNREACHABLE();
   1234   }
   1235   return Load(type, data_pointer, offset);
   1236 }
   1237 
   1238 Node* CodeStubAssembler::LoadAndUntagToWord32FixedArrayElement(
   1239     Node* object, Node* index_node, int additional_offset,
   1240     ParameterMode parameter_mode) {
   1241   int32_t header_size =
   1242       FixedArray::kHeaderSize + additional_offset - kHeapObjectTag;
   1243 #if V8_TARGET_LITTLE_ENDIAN
   1244   if (Is64()) {
   1245     header_size += kPointerSize / 2;
   1246   }
   1247 #endif
   1248   Node* offset = ElementOffsetFromIndex(index_node, FAST_HOLEY_ELEMENTS,
   1249                                         parameter_mode, header_size);
   1250   if (Is64()) {
   1251     return Load(MachineType::Int32(), object, offset);
   1252   } else {
   1253     return SmiToWord32(Load(MachineType::AnyTagged(), object, offset));
   1254   }
   1255 }
   1256 
   1257 Node* CodeStubAssembler::LoadFixedDoubleArrayElement(
   1258     Node* object, Node* index_node, MachineType machine_type,
   1259     int additional_offset, ParameterMode parameter_mode, Label* if_hole) {
   1260   CSA_ASSERT(this, IsFixedDoubleArray(object));
   1261   int32_t header_size =
   1262       FixedDoubleArray::kHeaderSize + additional_offset - kHeapObjectTag;
   1263   Node* offset = ElementOffsetFromIndex(index_node, FAST_HOLEY_DOUBLE_ELEMENTS,
   1264                                         parameter_mode, header_size);
   1265   return LoadDoubleWithHoleCheck(object, offset, if_hole, machine_type);
   1266 }
   1267 
   1268 Node* CodeStubAssembler::LoadDoubleWithHoleCheck(Node* base, Node* offset,
   1269                                                  Label* if_hole,
   1270                                                  MachineType machine_type) {
   1271   if (if_hole) {
   1272     // TODO(ishell): Compare only the upper part for the hole once the
   1273     // compiler is able to fold addition of already complex |offset| with
   1274     // |kIeeeDoubleExponentWordOffset| into one addressing mode.
   1275     if (Is64()) {
   1276       Node* element = Load(MachineType::Uint64(), base, offset);
   1277       GotoIf(Word64Equal(element, Int64Constant(kHoleNanInt64)), if_hole);
   1278     } else {
   1279       Node* element_upper = Load(
   1280           MachineType::Uint32(), base,
   1281           IntPtrAdd(offset, IntPtrConstant(kIeeeDoubleExponentWordOffset)));
   1282       GotoIf(Word32Equal(element_upper, Int32Constant(kHoleNanUpper32)),
   1283              if_hole);
   1284     }
   1285   }
   1286   if (machine_type.IsNone()) {
   1287     // This means the actual value is not needed.
   1288     return nullptr;
   1289   }
   1290   return Load(machine_type, base, offset);
   1291 }
   1292 
   1293 Node* CodeStubAssembler::LoadContextElement(Node* context, int slot_index) {
   1294   int offset = Context::SlotOffset(slot_index);
   1295   return Load(MachineType::AnyTagged(), context, IntPtrConstant(offset));
   1296 }
   1297 
   1298 Node* CodeStubAssembler::LoadContextElement(Node* context, Node* slot_index) {
   1299   Node* offset =
   1300       IntPtrAdd(WordShl(slot_index, kPointerSizeLog2),
   1301                 IntPtrConstant(Context::kHeaderSize - kHeapObjectTag));
   1302   return Load(MachineType::AnyTagged(), context, offset);
   1303 }
   1304 
   1305 Node* CodeStubAssembler::StoreContextElement(Node* context, int slot_index,
   1306                                              Node* value) {
   1307   int offset = Context::SlotOffset(slot_index);
   1308   return Store(context, IntPtrConstant(offset), value);
   1309 }
   1310 
   1311 Node* CodeStubAssembler::StoreContextElement(Node* context, Node* slot_index,
   1312                                              Node* value) {
   1313   Node* offset =
   1314       IntPtrAdd(WordShl(slot_index, kPointerSizeLog2),
   1315                 IntPtrConstant(Context::kHeaderSize - kHeapObjectTag));
   1316   return Store(context, offset, value);
   1317 }
   1318 
   1319 Node* CodeStubAssembler::StoreContextElementNoWriteBarrier(Node* context,
   1320                                                            int slot_index,
   1321                                                            Node* value) {
   1322   int offset = Context::SlotOffset(slot_index);
   1323   return StoreNoWriteBarrier(MachineRepresentation::kTagged, context,
   1324                              IntPtrConstant(offset), value);
   1325 }
   1326 
   1327 Node* CodeStubAssembler::LoadNativeContext(Node* context) {
   1328   return LoadContextElement(context, Context::NATIVE_CONTEXT_INDEX);
   1329 }
   1330 
   1331 Node* CodeStubAssembler::LoadJSArrayElementsMap(ElementsKind kind,
   1332                                                 Node* native_context) {
   1333   CSA_ASSERT(this, IsNativeContext(native_context));
   1334   return LoadContextElement(native_context, Context::ArrayMapIndex(kind));
   1335 }
   1336 
   1337 Node* CodeStubAssembler::StoreHeapNumberValue(Node* object, Node* value) {
   1338   return StoreObjectFieldNoWriteBarrier(object, HeapNumber::kValueOffset, value,
   1339                                         MachineRepresentation::kFloat64);
   1340 }
   1341 
   1342 Node* CodeStubAssembler::StoreObjectField(
   1343     Node* object, int offset, Node* value) {
   1344   DCHECK_NE(HeapObject::kMapOffset, offset);  // Use StoreMap instead.
   1345   return Store(object, IntPtrConstant(offset - kHeapObjectTag), value);
   1346 }
   1347 
   1348 Node* CodeStubAssembler::StoreObjectField(Node* object, Node* offset,
   1349                                           Node* value) {
   1350   int const_offset;
   1351   if (ToInt32Constant(offset, const_offset)) {
   1352     return StoreObjectField(object, const_offset, value);
   1353   }
   1354   return Store(object, IntPtrSub(offset, IntPtrConstant(kHeapObjectTag)),
   1355                value);
   1356 }
   1357 
   1358 Node* CodeStubAssembler::StoreObjectFieldNoWriteBarrier(
   1359     Node* object, int offset, Node* value, MachineRepresentation rep) {
   1360   return StoreNoWriteBarrier(rep, object,
   1361                              IntPtrConstant(offset - kHeapObjectTag), value);
   1362 }
   1363 
   1364 Node* CodeStubAssembler::StoreObjectFieldNoWriteBarrier(
   1365     Node* object, Node* offset, Node* value, MachineRepresentation rep) {
   1366   int const_offset;
   1367   if (ToInt32Constant(offset, const_offset)) {
   1368     return StoreObjectFieldNoWriteBarrier(object, const_offset, value, rep);
   1369   }
   1370   return StoreNoWriteBarrier(
   1371       rep, object, IntPtrSub(offset, IntPtrConstant(kHeapObjectTag)), value);
   1372 }
   1373 
   1374 Node* CodeStubAssembler::StoreMap(Node* object, Node* map) {
   1375   CSA_SLOW_ASSERT(this, IsMap(map));
   1376   return StoreWithMapWriteBarrier(
   1377       object, IntPtrConstant(HeapObject::kMapOffset - kHeapObjectTag), map);
   1378 }
   1379 
   1380 Node* CodeStubAssembler::StoreMapNoWriteBarrier(
   1381     Node* object, Heap::RootListIndex map_root_index) {
   1382   return StoreMapNoWriteBarrier(object, LoadRoot(map_root_index));
   1383 }
   1384 
   1385 Node* CodeStubAssembler::StoreMapNoWriteBarrier(Node* object, Node* map) {
   1386   CSA_SLOW_ASSERT(this, IsMap(map));
   1387   return StoreNoWriteBarrier(
   1388       MachineRepresentation::kTagged, object,
   1389       IntPtrConstant(HeapObject::kMapOffset - kHeapObjectTag), map);
   1390 }
   1391 
   1392 Node* CodeStubAssembler::StoreObjectFieldRoot(Node* object, int offset,
   1393                                               Heap::RootListIndex root_index) {
   1394   if (Heap::RootIsImmortalImmovable(root_index)) {
   1395     return StoreObjectFieldNoWriteBarrier(object, offset, LoadRoot(root_index));
   1396   } else {
   1397     return StoreObjectField(object, offset, LoadRoot(root_index));
   1398   }
   1399 }
   1400 
   1401 Node* CodeStubAssembler::StoreFixedArrayElement(Node* object, Node* index_node,
   1402                                                 Node* value,
   1403                                                 WriteBarrierMode barrier_mode,
   1404                                                 int additional_offset,
   1405                                                 ParameterMode parameter_mode) {
   1406   DCHECK(barrier_mode == SKIP_WRITE_BARRIER ||
   1407          barrier_mode == UPDATE_WRITE_BARRIER);
   1408   int header_size =
   1409       FixedArray::kHeaderSize + additional_offset - kHeapObjectTag;
   1410   Node* offset = ElementOffsetFromIndex(index_node, FAST_HOLEY_ELEMENTS,
   1411                                         parameter_mode, header_size);
   1412   if (barrier_mode == SKIP_WRITE_BARRIER) {
   1413     return StoreNoWriteBarrier(MachineRepresentation::kTagged, object, offset,
   1414                                value);
   1415   } else {
   1416     return Store(object, offset, value);
   1417   }
   1418 }
   1419 
   1420 Node* CodeStubAssembler::StoreFixedDoubleArrayElement(
   1421     Node* object, Node* index_node, Node* value, ParameterMode parameter_mode) {
   1422   CSA_ASSERT(this, IsFixedDoubleArray(object));
   1423   Node* offset =
   1424       ElementOffsetFromIndex(index_node, FAST_DOUBLE_ELEMENTS, parameter_mode,
   1425                              FixedArray::kHeaderSize - kHeapObjectTag);
   1426   MachineRepresentation rep = MachineRepresentation::kFloat64;
   1427   return StoreNoWriteBarrier(rep, object, offset, value);
   1428 }
   1429 
   1430 Node* CodeStubAssembler::BuildAppendJSArray(ElementsKind kind, Node* context,
   1431                                             Node* array,
   1432                                             CodeStubArguments& args,
   1433                                             Variable& arg_index,
   1434                                             Label* bailout) {
   1435   Comment("BuildAppendJSArray: %s", ElementsKindToString(kind));
   1436   Label pre_bailout(this);
   1437   Label success(this);
   1438   Variable var_tagged_length(this, MachineRepresentation::kTagged);
   1439   ParameterMode mode = OptimalParameterMode();
   1440   Variable var_length(this, OptimalParameterRepresentation(),
   1441                       TaggedToParameter(LoadJSArrayLength(array), mode));
   1442   Variable var_elements(this, MachineRepresentation::kTagged,
   1443                         LoadElements(array));
   1444   Node* capacity =
   1445       TaggedToParameter(LoadFixedArrayBaseLength(var_elements.value()), mode);
   1446 
   1447   // Resize the capacity of the fixed array if it doesn't fit.
   1448   Label fits(this, &var_elements);
   1449   Node* first = arg_index.value();
   1450   Node* growth = IntPtrSub(args.GetLength(), first);
   1451   Node* new_length =
   1452       IntPtrOrSmiAdd(WordToParameter(growth, mode), var_length.value(), mode);
   1453   GotoIfNot(IntPtrOrSmiGreaterThan(new_length, capacity, mode), &fits);
   1454   Node* new_capacity = CalculateNewElementsCapacity(new_length, mode);
   1455   var_elements.Bind(GrowElementsCapacity(array, var_elements.value(), kind,
   1456                                          kind, capacity, new_capacity, mode,
   1457                                          &pre_bailout));
   1458   Goto(&fits);
   1459   Bind(&fits);
   1460   Node* elements = var_elements.value();
   1461 
   1462   // Push each argument onto the end of the array now that there is enough
   1463   // capacity.
   1464   CodeStubAssembler::VariableList push_vars({&var_length}, zone());
   1465   args.ForEach(
   1466       push_vars,
   1467       [this, kind, mode, elements, &var_length, &pre_bailout](Node* arg) {
   1468         if (IsFastSmiElementsKind(kind)) {
   1469           GotoIf(TaggedIsNotSmi(arg), &pre_bailout);
   1470         } else if (IsFastDoubleElementsKind(kind)) {
   1471           GotoIfNotNumber(arg, &pre_bailout);
   1472         }
   1473         if (IsFastDoubleElementsKind(kind)) {
   1474           Node* double_value = ChangeNumberToFloat64(arg);
   1475           StoreFixedDoubleArrayElement(elements, var_length.value(),
   1476                                        Float64SilenceNaN(double_value), mode);
   1477         } else {
   1478           WriteBarrierMode barrier_mode = IsFastSmiElementsKind(kind)
   1479                                               ? SKIP_WRITE_BARRIER
   1480                                               : UPDATE_WRITE_BARRIER;
   1481           StoreFixedArrayElement(elements, var_length.value(), arg,
   1482                                  barrier_mode, 0, mode);
   1483         }
   1484         Increment(var_length, 1, mode);
   1485       },
   1486       first, nullptr);
   1487   {
   1488     Node* length = ParameterToTagged(var_length.value(), mode);
   1489     var_tagged_length.Bind(length);
   1490     StoreObjectFieldNoWriteBarrier(array, JSArray::kLengthOffset, length);
   1491     Goto(&success);
   1492   }
   1493 
   1494   Bind(&pre_bailout);
   1495   {
   1496     Node* length = ParameterToTagged(var_length.value(), mode);
   1497     var_tagged_length.Bind(length);
   1498     Node* diff = SmiSub(length, LoadJSArrayLength(array));
   1499     StoreObjectFieldNoWriteBarrier(array, JSArray::kLengthOffset, length);
   1500     arg_index.Bind(IntPtrAdd(arg_index.value(), SmiUntag(diff)));
   1501     Goto(bailout);
   1502   }
   1503 
   1504   Bind(&success);
   1505   return var_tagged_length.value();
   1506 }
   1507 
   1508 Node* CodeStubAssembler::AllocateHeapNumber(MutableMode mode) {
   1509   Node* result = Allocate(HeapNumber::kSize, kNone);
   1510   Heap::RootListIndex heap_map_index =
   1511       mode == IMMUTABLE ? Heap::kHeapNumberMapRootIndex
   1512                         : Heap::kMutableHeapNumberMapRootIndex;
   1513   StoreMapNoWriteBarrier(result, heap_map_index);
   1514   return result;
   1515 }
   1516 
   1517 Node* CodeStubAssembler::AllocateHeapNumberWithValue(Node* value,
   1518                                                      MutableMode mode) {
   1519   Node* result = AllocateHeapNumber(mode);
   1520   StoreHeapNumberValue(result, value);
   1521   return result;
   1522 }
   1523 
   1524 Node* CodeStubAssembler::AllocateSeqOneByteString(int length,
   1525                                                   AllocationFlags flags) {
   1526   Comment("AllocateSeqOneByteString");
   1527   if (length == 0) {
   1528     return LoadRoot(Heap::kempty_stringRootIndex);
   1529   }
   1530   Node* result = Allocate(SeqOneByteString::SizeFor(length), flags);
   1531   DCHECK(Heap::RootIsImmortalImmovable(Heap::kOneByteStringMapRootIndex));
   1532   StoreMapNoWriteBarrier(result, Heap::kOneByteStringMapRootIndex);
   1533   StoreObjectFieldNoWriteBarrier(result, SeqOneByteString::kLengthOffset,
   1534                                  SmiConstant(Smi::FromInt(length)));
   1535   // Initialize both used and unused parts of hash field slot at once.
   1536   StoreObjectFieldNoWriteBarrier(result, SeqOneByteString::kHashFieldSlot,
   1537                                  IntPtrConstant(String::kEmptyHashField),
   1538                                  MachineType::PointerRepresentation());
   1539   return result;
   1540 }
   1541 
   1542 Node* CodeStubAssembler::AllocateSeqOneByteString(Node* context, Node* length,
   1543                                                   ParameterMode mode,
   1544                                                   AllocationFlags flags) {
   1545   Comment("AllocateSeqOneByteString");
   1546   Variable var_result(this, MachineRepresentation::kTagged);
   1547 
   1548   // Compute the SeqOneByteString size and check if it fits into new space.
   1549   Label if_lengthiszero(this), if_sizeissmall(this),
   1550       if_notsizeissmall(this, Label::kDeferred), if_join(this);
   1551   GotoIf(WordEqual(length, IntPtrOrSmiConstant(0, mode)), &if_lengthiszero);
   1552 
   1553   Node* raw_size = GetArrayAllocationSize(
   1554       length, UINT8_ELEMENTS, mode,
   1555       SeqOneByteString::kHeaderSize + kObjectAlignmentMask);
   1556   Node* size = WordAnd(raw_size, IntPtrConstant(~kObjectAlignmentMask));
   1557   Branch(IntPtrLessThanOrEqual(size, IntPtrConstant(kMaxRegularHeapObjectSize)),
   1558          &if_sizeissmall, &if_notsizeissmall);
   1559 
   1560   Bind(&if_sizeissmall);
   1561   {
   1562     // Just allocate the SeqOneByteString in new space.
   1563     Node* result = Allocate(size, flags);
   1564     DCHECK(Heap::RootIsImmortalImmovable(Heap::kOneByteStringMapRootIndex));
   1565     StoreMapNoWriteBarrier(result, Heap::kOneByteStringMapRootIndex);
   1566     StoreObjectFieldNoWriteBarrier(result, SeqOneByteString::kLengthOffset,
   1567                                    ParameterToTagged(length, mode));
   1568     // Initialize both used and unused parts of hash field slot at once.
   1569     StoreObjectFieldNoWriteBarrier(result, SeqOneByteString::kHashFieldSlot,
   1570                                    IntPtrConstant(String::kEmptyHashField),
   1571                                    MachineType::PointerRepresentation());
   1572     var_result.Bind(result);
   1573     Goto(&if_join);
   1574   }
   1575 
   1576   Bind(&if_notsizeissmall);
   1577   {
   1578     // We might need to allocate in large object space, go to the runtime.
   1579     Node* result = CallRuntime(Runtime::kAllocateSeqOneByteString, context,
   1580                                ParameterToTagged(length, mode));
   1581     var_result.Bind(result);
   1582     Goto(&if_join);
   1583   }
   1584 
   1585   Bind(&if_lengthiszero);
   1586   {
   1587     var_result.Bind(LoadRoot(Heap::kempty_stringRootIndex));
   1588     Goto(&if_join);
   1589   }
   1590 
   1591   Bind(&if_join);
   1592   return var_result.value();
   1593 }
   1594 
   1595 Node* CodeStubAssembler::AllocateSeqTwoByteString(int length,
   1596                                                   AllocationFlags flags) {
   1597   Comment("AllocateSeqTwoByteString");
   1598   if (length == 0) {
   1599     return LoadRoot(Heap::kempty_stringRootIndex);
   1600   }
   1601   Node* result = Allocate(SeqTwoByteString::SizeFor(length), flags);
   1602   DCHECK(Heap::RootIsImmortalImmovable(Heap::kStringMapRootIndex));
   1603   StoreMapNoWriteBarrier(result, Heap::kStringMapRootIndex);
   1604   StoreObjectFieldNoWriteBarrier(result, SeqTwoByteString::kLengthOffset,
   1605                                  SmiConstant(Smi::FromInt(length)));
   1606   // Initialize both used and unused parts of hash field slot at once.
   1607   StoreObjectFieldNoWriteBarrier(result, SeqTwoByteString::kHashFieldSlot,
   1608                                  IntPtrConstant(String::kEmptyHashField),
   1609                                  MachineType::PointerRepresentation());
   1610   return result;
   1611 }
   1612 
   1613 Node* CodeStubAssembler::AllocateSeqTwoByteString(Node* context, Node* length,
   1614                                                   ParameterMode mode,
   1615                                                   AllocationFlags flags) {
   1616   Comment("AllocateSeqTwoByteString");
   1617   Variable var_result(this, MachineRepresentation::kTagged);
   1618 
   1619   // Compute the SeqTwoByteString size and check if it fits into new space.
   1620   Label if_lengthiszero(this), if_sizeissmall(this),
   1621       if_notsizeissmall(this, Label::kDeferred), if_join(this);
   1622   GotoIf(WordEqual(length, IntPtrOrSmiConstant(0, mode)), &if_lengthiszero);
   1623 
   1624   Node* raw_size = GetArrayAllocationSize(
   1625       length, UINT16_ELEMENTS, mode,
   1626       SeqOneByteString::kHeaderSize + kObjectAlignmentMask);
   1627   Node* size = WordAnd(raw_size, IntPtrConstant(~kObjectAlignmentMask));
   1628   Branch(IntPtrLessThanOrEqual(size, IntPtrConstant(kMaxRegularHeapObjectSize)),
   1629          &if_sizeissmall, &if_notsizeissmall);
   1630 
   1631   Bind(&if_sizeissmall);
   1632   {
   1633     // Just allocate the SeqTwoByteString in new space.
   1634     Node* result = Allocate(size, flags);
   1635     DCHECK(Heap::RootIsImmortalImmovable(Heap::kStringMapRootIndex));
   1636     StoreMapNoWriteBarrier(result, Heap::kStringMapRootIndex);
   1637     StoreObjectFieldNoWriteBarrier(
   1638         result, SeqTwoByteString::kLengthOffset,
   1639         mode == SMI_PARAMETERS ? length : SmiFromWord(length));
   1640     // Initialize both used and unused parts of hash field slot at once.
   1641     StoreObjectFieldNoWriteBarrier(result, SeqTwoByteString::kHashFieldSlot,
   1642                                    IntPtrConstant(String::kEmptyHashField),
   1643                                    MachineType::PointerRepresentation());
   1644     var_result.Bind(result);
   1645     Goto(&if_join);
   1646   }
   1647 
   1648   Bind(&if_notsizeissmall);
   1649   {
   1650     // We might need to allocate in large object space, go to the runtime.
   1651     Node* result =
   1652         CallRuntime(Runtime::kAllocateSeqTwoByteString, context,
   1653                     mode == SMI_PARAMETERS ? length : SmiFromWord(length));
   1654     var_result.Bind(result);
   1655     Goto(&if_join);
   1656   }
   1657 
   1658   Bind(&if_lengthiszero);
   1659   {
   1660     var_result.Bind(LoadRoot(Heap::kempty_stringRootIndex));
   1661     Goto(&if_join);
   1662   }
   1663 
   1664   Bind(&if_join);
   1665   return var_result.value();
   1666 }
   1667 
   1668 Node* CodeStubAssembler::AllocateSlicedString(
   1669     Heap::RootListIndex map_root_index, Node* length, Node* parent,
   1670     Node* offset) {
   1671   CSA_ASSERT(this, TaggedIsSmi(length));
   1672   Node* result = Allocate(SlicedString::kSize);
   1673   DCHECK(Heap::RootIsImmortalImmovable(map_root_index));
   1674   StoreMapNoWriteBarrier(result, map_root_index);
   1675   StoreObjectFieldNoWriteBarrier(result, SlicedString::kLengthOffset, length,
   1676                                  MachineRepresentation::kTagged);
   1677   // Initialize both used and unused parts of hash field slot at once.
   1678   StoreObjectFieldNoWriteBarrier(result, SlicedString::kHashFieldSlot,
   1679                                  IntPtrConstant(String::kEmptyHashField),
   1680                                  MachineType::PointerRepresentation());
   1681   StoreObjectFieldNoWriteBarrier(result, SlicedString::kParentOffset, parent,
   1682                                  MachineRepresentation::kTagged);
   1683   StoreObjectFieldNoWriteBarrier(result, SlicedString::kOffsetOffset, offset,
   1684                                  MachineRepresentation::kTagged);
   1685   return result;
   1686 }
   1687 
   1688 Node* CodeStubAssembler::AllocateSlicedOneByteString(Node* length, Node* parent,
   1689                                                      Node* offset) {
   1690   return AllocateSlicedString(Heap::kSlicedOneByteStringMapRootIndex, length,
   1691                               parent, offset);
   1692 }
   1693 
   1694 Node* CodeStubAssembler::AllocateSlicedTwoByteString(Node* length, Node* parent,
   1695                                                      Node* offset) {
   1696   return AllocateSlicedString(Heap::kSlicedStringMapRootIndex, length, parent,
   1697                               offset);
   1698 }
   1699 
   1700 Node* CodeStubAssembler::AllocateConsString(Heap::RootListIndex map_root_index,
   1701                                             Node* length, Node* first,
   1702                                             Node* second,
   1703                                             AllocationFlags flags) {
   1704   CSA_ASSERT(this, TaggedIsSmi(length));
   1705   Node* result = Allocate(ConsString::kSize, flags);
   1706   DCHECK(Heap::RootIsImmortalImmovable(map_root_index));
   1707   StoreMapNoWriteBarrier(result, map_root_index);
   1708   StoreObjectFieldNoWriteBarrier(result, ConsString::kLengthOffset, length,
   1709                                  MachineRepresentation::kTagged);
   1710   // Initialize both used and unused parts of hash field slot at once.
   1711   StoreObjectFieldNoWriteBarrier(result, ConsString::kHashFieldSlot,
   1712                                  IntPtrConstant(String::kEmptyHashField),
   1713                                  MachineType::PointerRepresentation());
   1714   bool const new_space = !(flags & kPretenured);
   1715   if (new_space) {
   1716     StoreObjectFieldNoWriteBarrier(result, ConsString::kFirstOffset, first,
   1717                                    MachineRepresentation::kTagged);
   1718     StoreObjectFieldNoWriteBarrier(result, ConsString::kSecondOffset, second,
   1719                                    MachineRepresentation::kTagged);
   1720   } else {
   1721     StoreObjectField(result, ConsString::kFirstOffset, first);
   1722     StoreObjectField(result, ConsString::kSecondOffset, second);
   1723   }
   1724   return result;
   1725 }
   1726 
   1727 Node* CodeStubAssembler::AllocateOneByteConsString(Node* length, Node* first,
   1728                                                    Node* second,
   1729                                                    AllocationFlags flags) {
   1730   return AllocateConsString(Heap::kConsOneByteStringMapRootIndex, length, first,
   1731                             second, flags);
   1732 }
   1733 
   1734 Node* CodeStubAssembler::AllocateTwoByteConsString(Node* length, Node* first,
   1735                                                    Node* second,
   1736                                                    AllocationFlags flags) {
   1737   return AllocateConsString(Heap::kConsStringMapRootIndex, length, first,
   1738                             second, flags);
   1739 }
   1740 
   1741 Node* CodeStubAssembler::NewConsString(Node* context, Node* length, Node* left,
   1742                                        Node* right, AllocationFlags flags) {
   1743   CSA_ASSERT(this, TaggedIsSmi(length));
   1744   // Added string can be a cons string.
   1745   Comment("Allocating ConsString");
   1746   Node* left_instance_type = LoadInstanceType(left);
   1747   Node* right_instance_type = LoadInstanceType(right);
   1748 
   1749   // Compute intersection and difference of instance types.
   1750   Node* anded_instance_types =
   1751       Word32And(left_instance_type, right_instance_type);
   1752   Node* xored_instance_types =
   1753       Word32Xor(left_instance_type, right_instance_type);
   1754 
   1755   // We create a one-byte cons string if
   1756   // 1. both strings are one-byte, or
   1757   // 2. at least one of the strings is two-byte, but happens to contain only
   1758   //    one-byte characters.
   1759   // To do this, we check
   1760   // 1. if both strings are one-byte, or if the one-byte data hint is set in
   1761   //    both strings, or
   1762   // 2. if one of the strings has the one-byte data hint set and the other
   1763   //    string is one-byte.
   1764   STATIC_ASSERT(kOneByteStringTag != 0);
   1765   STATIC_ASSERT(kOneByteDataHintTag != 0);
   1766   Label one_byte_map(this);
   1767   Label two_byte_map(this);
   1768   Variable result(this, MachineRepresentation::kTagged);
   1769   Label done(this, &result);
   1770   GotoIf(Word32NotEqual(Word32And(anded_instance_types,
   1771                                   Int32Constant(kStringEncodingMask |
   1772                                                 kOneByteDataHintTag)),
   1773                         Int32Constant(0)),
   1774          &one_byte_map);
   1775   Branch(Word32NotEqual(Word32And(xored_instance_types,
   1776                                   Int32Constant(kStringEncodingMask |
   1777                                                 kOneByteDataHintMask)),
   1778                         Int32Constant(kOneByteStringTag | kOneByteDataHintTag)),
   1779          &two_byte_map, &one_byte_map);
   1780 
   1781   Bind(&one_byte_map);
   1782   Comment("One-byte ConsString");
   1783   result.Bind(AllocateOneByteConsString(length, left, right, flags));
   1784   Goto(&done);
   1785 
   1786   Bind(&two_byte_map);
   1787   Comment("Two-byte ConsString");
   1788   result.Bind(AllocateTwoByteConsString(length, left, right, flags));
   1789   Goto(&done);
   1790 
   1791   Bind(&done);
   1792 
   1793   return result.value();
   1794 }
   1795 
   1796 Node* CodeStubAssembler::AllocateRegExpResult(Node* context, Node* length,
   1797                                               Node* index, Node* input) {
   1798   Node* const max_length =
   1799       SmiConstant(Smi::FromInt(JSArray::kInitialMaxFastElementArray));
   1800   CSA_ASSERT(this, SmiLessThanOrEqual(length, max_length));
   1801   USE(max_length);
   1802 
   1803   // Allocate the JSRegExpResult.
   1804   // TODO(jgruber): Fold JSArray and FixedArray allocations, then remove
   1805   // unneeded store of elements.
   1806   Node* const result = Allocate(JSRegExpResult::kSize);
   1807 
   1808   // TODO(jgruber): Store map as Heap constant?
   1809   Node* const native_context = LoadNativeContext(context);
   1810   Node* const map =
   1811       LoadContextElement(native_context, Context::REGEXP_RESULT_MAP_INDEX);
   1812   StoreMapNoWriteBarrier(result, map);
   1813 
   1814   // Initialize the header before allocating the elements.
   1815   Node* const empty_array = EmptyFixedArrayConstant();
   1816   DCHECK(Heap::RootIsImmortalImmovable(Heap::kEmptyFixedArrayRootIndex));
   1817   StoreObjectFieldNoWriteBarrier(result, JSArray::kPropertiesOffset,
   1818                                  empty_array);
   1819   StoreObjectFieldNoWriteBarrier(result, JSArray::kElementsOffset, empty_array);
   1820   StoreObjectFieldNoWriteBarrier(result, JSArray::kLengthOffset, length);
   1821 
   1822   StoreObjectFieldNoWriteBarrier(result, JSRegExpResult::kIndexOffset, index);
   1823   StoreObjectField(result, JSRegExpResult::kInputOffset, input);
   1824 
   1825   Node* const zero = IntPtrConstant(0);
   1826   Node* const length_intptr = SmiUntag(length);
   1827   const ElementsKind elements_kind = FAST_ELEMENTS;
   1828 
   1829   Node* const elements = AllocateFixedArray(elements_kind, length_intptr);
   1830   StoreObjectField(result, JSArray::kElementsOffset, elements);
   1831 
   1832   // Fill in the elements with undefined.
   1833   FillFixedArrayWithValue(elements_kind, elements, zero, length_intptr,
   1834                           Heap::kUndefinedValueRootIndex);
   1835 
   1836   return result;
   1837 }
   1838 
   1839 Node* CodeStubAssembler::AllocateNameDictionary(int at_least_space_for) {
   1840   return AllocateNameDictionary(IntPtrConstant(at_least_space_for));
   1841 }
   1842 
   1843 Node* CodeStubAssembler::AllocateNameDictionary(Node* at_least_space_for) {
   1844   CSA_ASSERT(this, UintPtrLessThanOrEqual(
   1845                        at_least_space_for,
   1846                        IntPtrConstant(NameDictionary::kMaxCapacity)));
   1847 
   1848   Node* capacity = HashTableComputeCapacity(at_least_space_for);
   1849   CSA_ASSERT(this, WordIsPowerOfTwo(capacity));
   1850 
   1851   Node* length = EntryToIndex<NameDictionary>(capacity);
   1852   Node* store_size =
   1853       IntPtrAdd(WordShl(length, IntPtrConstant(kPointerSizeLog2)),
   1854                 IntPtrConstant(NameDictionary::kHeaderSize));
   1855 
   1856   Node* result = Allocate(store_size);
   1857   Comment("Initialize NameDictionary");
   1858   // Initialize FixedArray fields.
   1859   DCHECK(Heap::RootIsImmortalImmovable(Heap::kHashTableMapRootIndex));
   1860   StoreMapNoWriteBarrier(result, Heap::kHashTableMapRootIndex);
   1861   StoreObjectFieldNoWriteBarrier(result, FixedArray::kLengthOffset,
   1862                                  SmiFromWord(length));
   1863   // Initialized HashTable fields.
   1864   Node* zero = SmiConstant(0);
   1865   StoreFixedArrayElement(result, NameDictionary::kNumberOfElementsIndex, zero,
   1866                          SKIP_WRITE_BARRIER);
   1867   StoreFixedArrayElement(result, NameDictionary::kNumberOfDeletedElementsIndex,
   1868                          zero, SKIP_WRITE_BARRIER);
   1869   StoreFixedArrayElement(result, NameDictionary::kCapacityIndex,
   1870                          SmiTag(capacity), SKIP_WRITE_BARRIER);
   1871   // Initialize Dictionary fields.
   1872   Node* filler = LoadRoot(Heap::kUndefinedValueRootIndex);
   1873   StoreFixedArrayElement(result, NameDictionary::kMaxNumberKeyIndex, filler,
   1874                          SKIP_WRITE_BARRIER);
   1875   StoreFixedArrayElement(result, NameDictionary::kNextEnumerationIndexIndex,
   1876                          SmiConstant(PropertyDetails::kInitialIndex),
   1877                          SKIP_WRITE_BARRIER);
   1878 
   1879   // Initialize NameDictionary elements.
   1880   Node* result_word = BitcastTaggedToWord(result);
   1881   Node* start_address = IntPtrAdd(
   1882       result_word, IntPtrConstant(NameDictionary::OffsetOfElementAt(
   1883                                       NameDictionary::kElementsStartIndex) -
   1884                                   kHeapObjectTag));
   1885   Node* end_address = IntPtrAdd(
   1886       result_word, IntPtrSub(store_size, IntPtrConstant(kHeapObjectTag)));
   1887   StoreFieldsNoWriteBarrier(start_address, end_address, filler);
   1888   return result;
   1889 }
   1890 
   1891 Node* CodeStubAssembler::AllocateJSObjectFromMap(Node* map, Node* properties,
   1892                                                  Node* elements,
   1893                                                  AllocationFlags flags) {
   1894   CSA_ASSERT(this, IsMap(map));
   1895   Node* size =
   1896       IntPtrMul(LoadMapInstanceSize(map), IntPtrConstant(kPointerSize));
   1897   CSA_ASSERT(this, IsRegularHeapObjectSize(size));
   1898   Node* object = Allocate(size, flags);
   1899   StoreMapNoWriteBarrier(object, map);
   1900   InitializeJSObjectFromMap(object, map, size, properties, elements);
   1901   return object;
   1902 }
   1903 
   1904 void CodeStubAssembler::InitializeJSObjectFromMap(Node* object, Node* map,
   1905                                                   Node* size, Node* properties,
   1906                                                   Node* elements) {
   1907   // This helper assumes that the object is in new-space, as guarded by the
   1908   // check in AllocatedJSObjectFromMap.
   1909   if (properties == nullptr) {
   1910     CSA_ASSERT(this, Word32BinaryNot(IsDictionaryMap((map))));
   1911     StoreObjectFieldRoot(object, JSObject::kPropertiesOffset,
   1912                          Heap::kEmptyFixedArrayRootIndex);
   1913   } else {
   1914     StoreObjectFieldNoWriteBarrier(object, JSObject::kPropertiesOffset,
   1915                                    properties);
   1916   }
   1917   if (elements == nullptr) {
   1918     StoreObjectFieldRoot(object, JSObject::kElementsOffset,
   1919                          Heap::kEmptyFixedArrayRootIndex);
   1920   } else {
   1921     StoreObjectFieldNoWriteBarrier(object, JSObject::kElementsOffset, elements);
   1922   }
   1923   InitializeJSObjectBody(object, map, size, JSObject::kHeaderSize);
   1924 }
   1925 
   1926 void CodeStubAssembler::InitializeJSObjectBody(Node* object, Node* map,
   1927                                                Node* size, int start_offset) {
   1928   // TODO(cbruni): activate in-object slack tracking machinery.
   1929   Comment("InitializeJSObjectBody");
   1930   Node* filler = LoadRoot(Heap::kUndefinedValueRootIndex);
   1931   // Calculate the untagged field addresses.
   1932   object = BitcastTaggedToWord(object);
   1933   Node* start_address =
   1934       IntPtrAdd(object, IntPtrConstant(start_offset - kHeapObjectTag));
   1935   Node* end_address =
   1936       IntPtrSub(IntPtrAdd(object, size), IntPtrConstant(kHeapObjectTag));
   1937   StoreFieldsNoWriteBarrier(start_address, end_address, filler);
   1938 }
   1939 
   1940 void CodeStubAssembler::StoreFieldsNoWriteBarrier(Node* start_address,
   1941                                                   Node* end_address,
   1942                                                   Node* value) {
   1943   Comment("StoreFieldsNoWriteBarrier");
   1944   CSA_ASSERT(this, WordIsWordAligned(start_address));
   1945   CSA_ASSERT(this, WordIsWordAligned(end_address));
   1946   BuildFastLoop(start_address, end_address,
   1947                 [this, value](Node* current) {
   1948                   StoreNoWriteBarrier(MachineRepresentation::kTagged, current,
   1949                                       value);
   1950                 },
   1951                 kPointerSize, INTPTR_PARAMETERS, IndexAdvanceMode::kPost);
   1952 }
   1953 
   1954 Node* CodeStubAssembler::AllocateUninitializedJSArrayWithoutElements(
   1955     ElementsKind kind, Node* array_map, Node* length, Node* allocation_site) {
   1956   Comment("begin allocation of JSArray without elements");
   1957   int base_size = JSArray::kSize;
   1958   if (allocation_site != nullptr) {
   1959     base_size += AllocationMemento::kSize;
   1960   }
   1961 
   1962   Node* size = IntPtrConstant(base_size);
   1963   Node* array = AllocateUninitializedJSArray(kind, array_map, length,
   1964                                              allocation_site, size);
   1965   return array;
   1966 }
   1967 
   1968 std::pair<Node*, Node*>
   1969 CodeStubAssembler::AllocateUninitializedJSArrayWithElements(
   1970     ElementsKind kind, Node* array_map, Node* length, Node* allocation_site,
   1971     Node* capacity, ParameterMode capacity_mode) {
   1972   Comment("begin allocation of JSArray with elements");
   1973   int base_size = JSArray::kSize;
   1974 
   1975   if (allocation_site != nullptr) {
   1976     base_size += AllocationMemento::kSize;
   1977   }
   1978 
   1979   int elements_offset = base_size;
   1980 
   1981   // Compute space for elements
   1982   base_size += FixedArray::kHeaderSize;
   1983   Node* size = ElementOffsetFromIndex(capacity, kind, capacity_mode, base_size);
   1984 
   1985   Node* array = AllocateUninitializedJSArray(kind, array_map, length,
   1986                                              allocation_site, size);
   1987 
   1988   Node* elements = InnerAllocate(array, elements_offset);
   1989   StoreObjectFieldNoWriteBarrier(array, JSObject::kElementsOffset, elements);
   1990 
   1991   return {array, elements};
   1992 }
   1993 
   1994 Node* CodeStubAssembler::AllocateUninitializedJSArray(ElementsKind kind,
   1995                                                       Node* array_map,
   1996                                                       Node* length,
   1997                                                       Node* allocation_site,
   1998                                                       Node* size_in_bytes) {
   1999   Node* array = Allocate(size_in_bytes);
   2000 
   2001   Comment("write JSArray headers");
   2002   StoreMapNoWriteBarrier(array, array_map);
   2003 
   2004   CSA_ASSERT(this, TaggedIsSmi(length));
   2005   StoreObjectFieldNoWriteBarrier(array, JSArray::kLengthOffset, length);
   2006 
   2007   StoreObjectFieldRoot(array, JSArray::kPropertiesOffset,
   2008                        Heap::kEmptyFixedArrayRootIndex);
   2009 
   2010   if (allocation_site != nullptr) {
   2011     InitializeAllocationMemento(array, JSArray::kSize, allocation_site);
   2012   }
   2013   return array;
   2014 }
   2015 
   2016 Node* CodeStubAssembler::AllocateJSArray(ElementsKind kind, Node* array_map,
   2017                                          Node* capacity, Node* length,
   2018                                          Node* allocation_site,
   2019                                          ParameterMode capacity_mode) {
   2020   Node *array = nullptr, *elements = nullptr;
   2021   if (IsIntPtrOrSmiConstantZero(capacity)) {
   2022     // Array is empty. Use the shared empty fixed array instead of allocating a
   2023     // new one.
   2024     array = AllocateUninitializedJSArrayWithoutElements(kind, array_map, length,
   2025                                                         nullptr);
   2026     StoreObjectFieldRoot(array, JSArray::kElementsOffset,
   2027                          Heap::kEmptyFixedArrayRootIndex);
   2028   } else {
   2029     // Allocate both array and elements object, and initialize the JSArray.
   2030     std::tie(array, elements) = AllocateUninitializedJSArrayWithElements(
   2031         kind, array_map, length, allocation_site, capacity, capacity_mode);
   2032     // Setup elements object.
   2033     Heap::RootListIndex elements_map_index =
   2034         IsFastDoubleElementsKind(kind) ? Heap::kFixedDoubleArrayMapRootIndex
   2035                                        : Heap::kFixedArrayMapRootIndex;
   2036     DCHECK(Heap::RootIsImmortalImmovable(elements_map_index));
   2037     StoreMapNoWriteBarrier(elements, elements_map_index);
   2038     StoreObjectFieldNoWriteBarrier(elements, FixedArray::kLengthOffset,
   2039                                    ParameterToTagged(capacity, capacity_mode));
   2040     // Fill in the elements with holes.
   2041     FillFixedArrayWithValue(kind, elements,
   2042                             IntPtrOrSmiConstant(0, capacity_mode), capacity,
   2043                             Heap::kTheHoleValueRootIndex, capacity_mode);
   2044   }
   2045 
   2046   return array;
   2047 }
   2048 
   2049 Node* CodeStubAssembler::AllocateFixedArray(ElementsKind kind,
   2050                                             Node* capacity_node,
   2051                                             ParameterMode mode,
   2052                                             AllocationFlags flags) {
   2053   CSA_ASSERT(this, IntPtrOrSmiGreaterThan(capacity_node,
   2054                                           IntPtrOrSmiConstant(0, mode), mode));
   2055   Node* total_size = GetFixedArrayAllocationSize(capacity_node, kind, mode);
   2056 
   2057   // Allocate both array and elements object, and initialize the JSArray.
   2058   Node* array = Allocate(total_size, flags);
   2059   Heap::RootListIndex map_index = IsFastDoubleElementsKind(kind)
   2060                                       ? Heap::kFixedDoubleArrayMapRootIndex
   2061                                       : Heap::kFixedArrayMapRootIndex;
   2062   DCHECK(Heap::RootIsImmortalImmovable(map_index));
   2063   StoreMapNoWriteBarrier(array, map_index);
   2064   StoreObjectFieldNoWriteBarrier(array, FixedArray::kLengthOffset,
   2065                                  ParameterToTagged(capacity_node, mode));
   2066   return array;
   2067 }
   2068 
   2069 void CodeStubAssembler::FillFixedArrayWithValue(
   2070     ElementsKind kind, Node* array, Node* from_node, Node* to_node,
   2071     Heap::RootListIndex value_root_index, ParameterMode mode) {
   2072   bool is_double = IsFastDoubleElementsKind(kind);
   2073   DCHECK(value_root_index == Heap::kTheHoleValueRootIndex ||
   2074          value_root_index == Heap::kUndefinedValueRootIndex);
   2075   DCHECK_IMPLIES(is_double, value_root_index == Heap::kTheHoleValueRootIndex);
   2076   STATIC_ASSERT(kHoleNanLower32 == kHoleNanUpper32);
   2077   Node* double_hole =
   2078       Is64() ? Int64Constant(kHoleNanInt64) : Int32Constant(kHoleNanLower32);
   2079   Node* value = LoadRoot(value_root_index);
   2080 
   2081   BuildFastFixedArrayForEach(
   2082       array, kind, from_node, to_node,
   2083       [this, value, is_double, double_hole](Node* array, Node* offset) {
   2084         if (is_double) {
   2085           // Don't use doubles to store the hole double, since manipulating the
   2086           // signaling NaN used for the hole in C++, e.g. with bit_cast, will
   2087           // change its value on ia32 (the x87 stack is used to return values
   2088           // and stores to the stack silently clear the signalling bit).
   2089           //
   2090           // TODO(danno): When we have a Float32/Float64 wrapper class that
   2091           // preserves double bits during manipulation, remove this code/change
   2092           // this to an indexed Float64 store.
   2093           if (Is64()) {
   2094             StoreNoWriteBarrier(MachineRepresentation::kWord64, array, offset,
   2095                                 double_hole);
   2096           } else {
   2097             StoreNoWriteBarrier(MachineRepresentation::kWord32, array, offset,
   2098                                 double_hole);
   2099             StoreNoWriteBarrier(MachineRepresentation::kWord32, array,
   2100                                 IntPtrAdd(offset, IntPtrConstant(kPointerSize)),
   2101                                 double_hole);
   2102           }
   2103         } else {
   2104           StoreNoWriteBarrier(MachineRepresentation::kTagged, array, offset,
   2105                               value);
   2106         }
   2107       },
   2108       mode);
   2109 }
   2110 
   2111 void CodeStubAssembler::CopyFixedArrayElements(
   2112     ElementsKind from_kind, Node* from_array, ElementsKind to_kind,
   2113     Node* to_array, Node* element_count, Node* capacity,
   2114     WriteBarrierMode barrier_mode, ParameterMode mode) {
   2115   STATIC_ASSERT(FixedArray::kHeaderSize == FixedDoubleArray::kHeaderSize);
   2116   const int first_element_offset = FixedArray::kHeaderSize - kHeapObjectTag;
   2117   Comment("[ CopyFixedArrayElements");
   2118 
   2119   // Typed array elements are not supported.
   2120   DCHECK(!IsFixedTypedArrayElementsKind(from_kind));
   2121   DCHECK(!IsFixedTypedArrayElementsKind(to_kind));
   2122 
   2123   Label done(this);
   2124   bool from_double_elements = IsFastDoubleElementsKind(from_kind);
   2125   bool to_double_elements = IsFastDoubleElementsKind(to_kind);
   2126   bool element_size_matches =
   2127       Is64() ||
   2128       IsFastDoubleElementsKind(from_kind) == IsFastDoubleElementsKind(to_kind);
   2129   bool doubles_to_objects_conversion =
   2130       IsFastDoubleElementsKind(from_kind) && IsFastObjectElementsKind(to_kind);
   2131   bool needs_write_barrier =
   2132       doubles_to_objects_conversion || (barrier_mode == UPDATE_WRITE_BARRIER &&
   2133                                         IsFastObjectElementsKind(to_kind));
   2134   Node* double_hole =
   2135       Is64() ? Int64Constant(kHoleNanInt64) : Int32Constant(kHoleNanLower32);
   2136 
   2137   if (doubles_to_objects_conversion) {
   2138     // If the copy might trigger a GC, make sure that the FixedArray is
   2139     // pre-initialized with holes to make sure that it's always in a
   2140     // consistent state.
   2141     FillFixedArrayWithValue(to_kind, to_array, IntPtrOrSmiConstant(0, mode),
   2142                             capacity, Heap::kTheHoleValueRootIndex, mode);
   2143   } else if (element_count != capacity) {
   2144     FillFixedArrayWithValue(to_kind, to_array, element_count, capacity,
   2145                             Heap::kTheHoleValueRootIndex, mode);
   2146   }
   2147 
   2148   Node* limit_offset = ElementOffsetFromIndex(
   2149       IntPtrOrSmiConstant(0, mode), from_kind, mode, first_element_offset);
   2150   Variable var_from_offset(this, MachineType::PointerRepresentation(),
   2151                            ElementOffsetFromIndex(element_count, from_kind,
   2152                                                   mode, first_element_offset));
   2153   // This second variable is used only when the element sizes of source and
   2154   // destination arrays do not match.
   2155   Variable var_to_offset(this, MachineType::PointerRepresentation());
   2156   if (element_size_matches) {
   2157     var_to_offset.Bind(var_from_offset.value());
   2158   } else {
   2159     var_to_offset.Bind(ElementOffsetFromIndex(element_count, to_kind, mode,
   2160                                               first_element_offset));
   2161   }
   2162 
   2163   Variable* vars[] = {&var_from_offset, &var_to_offset};
   2164   Label decrement(this, 2, vars);
   2165 
   2166   Branch(WordEqual(var_from_offset.value(), limit_offset), &done, &decrement);
   2167 
   2168   Bind(&decrement);
   2169   {
   2170     Node* from_offset = IntPtrSub(
   2171         var_from_offset.value(),
   2172         IntPtrConstant(from_double_elements ? kDoubleSize : kPointerSize));
   2173     var_from_offset.Bind(from_offset);
   2174 
   2175     Node* to_offset;
   2176     if (element_size_matches) {
   2177       to_offset = from_offset;
   2178     } else {
   2179       to_offset = IntPtrSub(
   2180           var_to_offset.value(),
   2181           IntPtrConstant(to_double_elements ? kDoubleSize : kPointerSize));
   2182       var_to_offset.Bind(to_offset);
   2183     }
   2184 
   2185     Label next_iter(this), store_double_hole(this);
   2186     Label* if_hole;
   2187     if (doubles_to_objects_conversion) {
   2188       // The target elements array is already preinitialized with holes, so we
   2189       // can just proceed with the next iteration.
   2190       if_hole = &next_iter;
   2191     } else if (IsFastDoubleElementsKind(to_kind)) {
   2192       if_hole = &store_double_hole;
   2193     } else {
   2194       // In all the other cases don't check for holes and copy the data as is.
   2195       if_hole = nullptr;
   2196     }
   2197 
   2198     Node* value = LoadElementAndPrepareForStore(
   2199         from_array, var_from_offset.value(), from_kind, to_kind, if_hole);
   2200 
   2201     if (needs_write_barrier) {
   2202       Store(to_array, to_offset, value);
   2203     } else if (to_double_elements) {
   2204       StoreNoWriteBarrier(MachineRepresentation::kFloat64, to_array, to_offset,
   2205                           value);
   2206     } else {
   2207       StoreNoWriteBarrier(MachineRepresentation::kTagged, to_array, to_offset,
   2208                           value);
   2209     }
   2210     Goto(&next_iter);
   2211 
   2212     if (if_hole == &store_double_hole) {
   2213       Bind(&store_double_hole);
   2214       // Don't use doubles to store the hole double, since manipulating the
   2215       // signaling NaN used for the hole in C++, e.g. with bit_cast, will
   2216       // change its value on ia32 (the x87 stack is used to return values
   2217       // and stores to the stack silently clear the signalling bit).
   2218       //
   2219       // TODO(danno): When we have a Float32/Float64 wrapper class that
   2220       // preserves double bits during manipulation, remove this code/change
   2221       // this to an indexed Float64 store.
   2222       if (Is64()) {
   2223         StoreNoWriteBarrier(MachineRepresentation::kWord64, to_array, to_offset,
   2224                             double_hole);
   2225       } else {
   2226         StoreNoWriteBarrier(MachineRepresentation::kWord32, to_array, to_offset,
   2227                             double_hole);
   2228         StoreNoWriteBarrier(MachineRepresentation::kWord32, to_array,
   2229                             IntPtrAdd(to_offset, IntPtrConstant(kPointerSize)),
   2230                             double_hole);
   2231       }
   2232       Goto(&next_iter);
   2233     }
   2234 
   2235     Bind(&next_iter);
   2236     Node* compare = WordNotEqual(from_offset, limit_offset);
   2237     Branch(compare, &decrement, &done);
   2238   }
   2239 
   2240   Bind(&done);
   2241   IncrementCounter(isolate()->counters()->inlined_copied_elements(), 1);
   2242   Comment("] CopyFixedArrayElements");
   2243 }
   2244 
   2245 void CodeStubAssembler::CopyStringCharacters(Node* from_string, Node* to_string,
   2246                                              Node* from_index, Node* to_index,
   2247                                              Node* character_count,
   2248                                              String::Encoding from_encoding,
   2249                                              String::Encoding to_encoding,
   2250                                              ParameterMode mode) {
   2251   bool from_one_byte = from_encoding == String::ONE_BYTE_ENCODING;
   2252   bool to_one_byte = to_encoding == String::ONE_BYTE_ENCODING;
   2253   DCHECK_IMPLIES(to_one_byte, from_one_byte);
   2254   Comment("CopyStringCharacters %s -> %s",
   2255           from_one_byte ? "ONE_BYTE_ENCODING" : "TWO_BYTE_ENCODING",
   2256           to_one_byte ? "ONE_BYTE_ENCODING" : "TWO_BYTE_ENCODING");
   2257 
   2258   ElementsKind from_kind = from_one_byte ? UINT8_ELEMENTS : UINT16_ELEMENTS;
   2259   ElementsKind to_kind = to_one_byte ? UINT8_ELEMENTS : UINT16_ELEMENTS;
   2260   STATIC_ASSERT(SeqOneByteString::kHeaderSize == SeqTwoByteString::kHeaderSize);
   2261   int header_size = SeqOneByteString::kHeaderSize - kHeapObjectTag;
   2262   Node* from_offset =
   2263       ElementOffsetFromIndex(from_index, from_kind, mode, header_size);
   2264   Node* to_offset =
   2265       ElementOffsetFromIndex(to_index, to_kind, mode, header_size);
   2266   Node* byte_count = ElementOffsetFromIndex(character_count, from_kind, mode);
   2267   Node* limit_offset = IntPtrAdd(from_offset, byte_count);
   2268 
   2269   // Prepare the fast loop
   2270   MachineType type =
   2271       from_one_byte ? MachineType::Uint8() : MachineType::Uint16();
   2272   MachineRepresentation rep = to_one_byte ? MachineRepresentation::kWord8
   2273                                           : MachineRepresentation::kWord16;
   2274   int from_increment = 1 << ElementsKindToShiftSize(from_kind);
   2275   int to_increment = 1 << ElementsKindToShiftSize(to_kind);
   2276 
   2277   Variable current_to_offset(this, MachineType::PointerRepresentation(),
   2278                              to_offset);
   2279   VariableList vars({&current_to_offset}, zone());
   2280   int to_index_constant = 0, from_index_constant = 0;
   2281   Smi* to_index_smi = nullptr;
   2282   Smi* from_index_smi = nullptr;
   2283   bool index_same = (from_encoding == to_encoding) &&
   2284                     (from_index == to_index ||
   2285                      (ToInt32Constant(from_index, from_index_constant) &&
   2286                       ToInt32Constant(to_index, to_index_constant) &&
   2287                       from_index_constant == to_index_constant) ||
   2288                      (ToSmiConstant(from_index, from_index_smi) &&
   2289                       ToSmiConstant(to_index, to_index_smi) &&
   2290                       to_index_smi == from_index_smi));
   2291   BuildFastLoop(vars, from_offset, limit_offset,
   2292                 [this, from_string, to_string, &current_to_offset, to_increment,
   2293                  type, rep, index_same](Node* offset) {
   2294                   Node* value = Load(type, from_string, offset);
   2295                   StoreNoWriteBarrier(
   2296                       rep, to_string,
   2297                       index_same ? offset : current_to_offset.value(), value);
   2298                   if (!index_same) {
   2299                     Increment(current_to_offset, to_increment);
   2300                   }
   2301                 },
   2302                 from_increment, INTPTR_PARAMETERS, IndexAdvanceMode::kPost);
   2303 }
   2304 
   2305 Node* CodeStubAssembler::LoadElementAndPrepareForStore(Node* array,
   2306                                                        Node* offset,
   2307                                                        ElementsKind from_kind,
   2308                                                        ElementsKind to_kind,
   2309                                                        Label* if_hole) {
   2310   if (IsFastDoubleElementsKind(from_kind)) {
   2311     Node* value =
   2312         LoadDoubleWithHoleCheck(array, offset, if_hole, MachineType::Float64());
   2313     if (!IsFastDoubleElementsKind(to_kind)) {
   2314       value = AllocateHeapNumberWithValue(value);
   2315     }
   2316     return value;
   2317 
   2318   } else {
   2319     Node* value = Load(MachineType::AnyTagged(), array, offset);
   2320     if (if_hole) {
   2321       GotoIf(WordEqual(value, TheHoleConstant()), if_hole);
   2322     }
   2323     if (IsFastDoubleElementsKind(to_kind)) {
   2324       if (IsFastSmiElementsKind(from_kind)) {
   2325         value = SmiToFloat64(value);
   2326       } else {
   2327         value = LoadHeapNumberValue(value);
   2328       }
   2329     }
   2330     return value;
   2331   }
   2332 }
   2333 
   2334 Node* CodeStubAssembler::CalculateNewElementsCapacity(Node* old_capacity,
   2335                                                       ParameterMode mode) {
   2336   Node* half_old_capacity = WordOrSmiShr(old_capacity, 1, mode);
   2337   Node* new_capacity = IntPtrOrSmiAdd(half_old_capacity, old_capacity, mode);
   2338   Node* padding = IntPtrOrSmiConstant(16, mode);
   2339   return IntPtrOrSmiAdd(new_capacity, padding, mode);
   2340 }
   2341 
   2342 Node* CodeStubAssembler::TryGrowElementsCapacity(Node* object, Node* elements,
   2343                                                  ElementsKind kind, Node* key,
   2344                                                  Label* bailout) {
   2345   Node* capacity = LoadFixedArrayBaseLength(elements);
   2346 
   2347   ParameterMode mode = OptimalParameterMode();
   2348   capacity = TaggedToParameter(capacity, mode);
   2349   key = TaggedToParameter(key, mode);
   2350 
   2351   return TryGrowElementsCapacity(object, elements, kind, key, capacity, mode,
   2352                                  bailout);
   2353 }
   2354 
   2355 Node* CodeStubAssembler::TryGrowElementsCapacity(Node* object, Node* elements,
   2356                                                  ElementsKind kind, Node* key,
   2357                                                  Node* capacity,
   2358                                                  ParameterMode mode,
   2359                                                  Label* bailout) {
   2360   Comment("TryGrowElementsCapacity");
   2361 
   2362   // If the gap growth is too big, fall back to the runtime.
   2363   Node* max_gap = IntPtrOrSmiConstant(JSObject::kMaxGap, mode);
   2364   Node* max_capacity = IntPtrOrSmiAdd(capacity, max_gap, mode);
   2365   GotoIf(UintPtrOrSmiGreaterThanOrEqual(key, max_capacity, mode), bailout);
   2366 
   2367   // Calculate the capacity of the new backing store.
   2368   Node* new_capacity = CalculateNewElementsCapacity(
   2369       IntPtrOrSmiAdd(key, IntPtrOrSmiConstant(1, mode), mode), mode);
   2370   return GrowElementsCapacity(object, elements, kind, kind, capacity,
   2371                               new_capacity, mode, bailout);
   2372 }
   2373 
   2374 Node* CodeStubAssembler::GrowElementsCapacity(
   2375     Node* object, Node* elements, ElementsKind from_kind, ElementsKind to_kind,
   2376     Node* capacity, Node* new_capacity, ParameterMode mode, Label* bailout) {
   2377   Comment("[ GrowElementsCapacity");
   2378   // If size of the allocation for the new capacity doesn't fit in a page
   2379   // that we can bump-pointer allocate from, fall back to the runtime.
   2380   int max_size = FixedArrayBase::GetMaxLengthForNewSpaceAllocation(to_kind);
   2381   GotoIf(UintPtrOrSmiGreaterThanOrEqual(
   2382              new_capacity, IntPtrOrSmiConstant(max_size, mode), mode),
   2383          bailout);
   2384 
   2385   // Allocate the new backing store.
   2386   Node* new_elements = AllocateFixedArray(to_kind, new_capacity, mode);
   2387 
   2388   // Copy the elements from the old elements store to the new.
   2389   // The size-check above guarantees that the |new_elements| is allocated
   2390   // in new space so we can skip the write barrier.
   2391   CopyFixedArrayElements(from_kind, elements, to_kind, new_elements, capacity,
   2392                          new_capacity, SKIP_WRITE_BARRIER, mode);
   2393 
   2394   StoreObjectField(object, JSObject::kElementsOffset, new_elements);
   2395   Comment("] GrowElementsCapacity");
   2396   return new_elements;
   2397 }
   2398 
   2399 void CodeStubAssembler::InitializeAllocationMemento(Node* base_allocation,
   2400                                                     int base_allocation_size,
   2401                                                     Node* allocation_site) {
   2402   StoreObjectFieldNoWriteBarrier(
   2403       base_allocation, AllocationMemento::kMapOffset + base_allocation_size,
   2404       HeapConstant(Handle<Map>(isolate()->heap()->allocation_memento_map())));
   2405   StoreObjectFieldNoWriteBarrier(
   2406       base_allocation,
   2407       AllocationMemento::kAllocationSiteOffset + base_allocation_size,
   2408       allocation_site);
   2409   if (FLAG_allocation_site_pretenuring) {
   2410     Node* count = LoadObjectField(allocation_site,
   2411                                   AllocationSite::kPretenureCreateCountOffset);
   2412     Node* incremented_count = SmiAdd(count, SmiConstant(Smi::FromInt(1)));
   2413     StoreObjectFieldNoWriteBarrier(allocation_site,
   2414                                    AllocationSite::kPretenureCreateCountOffset,
   2415                                    incremented_count);
   2416   }
   2417 }
   2418 
   2419 Node* CodeStubAssembler::TryTaggedToFloat64(Node* value,
   2420                                             Label* if_valueisnotnumber) {
   2421   Label out(this);
   2422   Variable var_result(this, MachineRepresentation::kFloat64);
   2423 
   2424   // Check if the {value} is a Smi or a HeapObject.
   2425   Label if_valueissmi(this), if_valueisnotsmi(this);
   2426   Branch(TaggedIsSmi(value), &if_valueissmi, &if_valueisnotsmi);
   2427 
   2428   Bind(&if_valueissmi);
   2429   {
   2430     // Convert the Smi {value}.
   2431     var_result.Bind(SmiToFloat64(value));
   2432     Goto(&out);
   2433   }
   2434 
   2435   Bind(&if_valueisnotsmi);
   2436   {
   2437     // Check if {value} is a HeapNumber.
   2438     Label if_valueisheapnumber(this);
   2439     Branch(IsHeapNumberMap(LoadMap(value)), &if_valueisheapnumber,
   2440            if_valueisnotnumber);
   2441 
   2442     Bind(&if_valueisheapnumber);
   2443     {
   2444       // Load the floating point value.
   2445       var_result.Bind(LoadHeapNumberValue(value));
   2446       Goto(&out);
   2447     }
   2448   }
   2449   Bind(&out);
   2450   return var_result.value();
   2451 }
   2452 
   2453 Node* CodeStubAssembler::TruncateTaggedToFloat64(Node* context, Node* value) {
   2454   // We might need to loop once due to ToNumber conversion.
   2455   Variable var_value(this, MachineRepresentation::kTagged),
   2456       var_result(this, MachineRepresentation::kFloat64);
   2457   Label loop(this, &var_value), done_loop(this, &var_result);
   2458   var_value.Bind(value);
   2459   Goto(&loop);
   2460   Bind(&loop);
   2461   {
   2462     Label if_valueisnotnumber(this, Label::kDeferred);
   2463 
   2464     // Load the current {value}.
   2465     value = var_value.value();
   2466 
   2467     // Convert {value} to Float64 if it is a number and convert it to a number
   2468     // otherwise.
   2469     Node* const result = TryTaggedToFloat64(value, &if_valueisnotnumber);
   2470     var_result.Bind(result);
   2471     Goto(&done_loop);
   2472 
   2473     Bind(&if_valueisnotnumber);
   2474     {
   2475       // Convert the {value} to a Number first.
   2476       Callable callable = CodeFactory::NonNumberToNumber(isolate());
   2477       var_value.Bind(CallStub(callable, context, value));
   2478       Goto(&loop);
   2479     }
   2480   }
   2481   Bind(&done_loop);
   2482   return var_result.value();
   2483 }
   2484 
   2485 Node* CodeStubAssembler::TruncateTaggedToWord32(Node* context, Node* value) {
   2486   // We might need to loop once due to ToNumber conversion.
   2487   Variable var_value(this, MachineRepresentation::kTagged, value),
   2488       var_result(this, MachineRepresentation::kWord32);
   2489   Label loop(this, &var_value), done_loop(this, &var_result);
   2490   Goto(&loop);
   2491   Bind(&loop);
   2492   {
   2493     // Load the current {value}.
   2494     value = var_value.value();
   2495 
   2496     // Check if the {value} is a Smi or a HeapObject.
   2497     Label if_valueissmi(this), if_valueisnotsmi(this);
   2498     Branch(TaggedIsSmi(value), &if_valueissmi, &if_valueisnotsmi);
   2499 
   2500     Bind(&if_valueissmi);
   2501     {
   2502       // Convert the Smi {value}.
   2503       var_result.Bind(SmiToWord32(value));
   2504       Goto(&done_loop);
   2505     }
   2506 
   2507     Bind(&if_valueisnotsmi);
   2508     {
   2509       // Check if {value} is a HeapNumber.
   2510       Label if_valueisheapnumber(this),
   2511           if_valueisnotheapnumber(this, Label::kDeferred);
   2512       Branch(IsHeapNumberMap(LoadMap(value)), &if_valueisheapnumber,
   2513              &if_valueisnotheapnumber);
   2514 
   2515       Bind(&if_valueisheapnumber);
   2516       {
   2517         // Truncate the floating point value.
   2518         var_result.Bind(TruncateHeapNumberValueToWord32(value));
   2519         Goto(&done_loop);
   2520       }
   2521 
   2522       Bind(&if_valueisnotheapnumber);
   2523       {
   2524         // Convert the {value} to a Number first.
   2525         Callable callable = CodeFactory::NonNumberToNumber(isolate());
   2526         var_value.Bind(CallStub(callable, context, value));
   2527         Goto(&loop);
   2528       }
   2529     }
   2530   }
   2531   Bind(&done_loop);
   2532   return var_result.value();
   2533 }
   2534 
   2535 Node* CodeStubAssembler::TruncateHeapNumberValueToWord32(Node* object) {
   2536   Node* value = LoadHeapNumberValue(object);
   2537   return TruncateFloat64ToWord32(value);
   2538 }
   2539 
   2540 Node* CodeStubAssembler::ChangeFloat64ToTagged(Node* value) {
   2541   Node* value32 = RoundFloat64ToInt32(value);
   2542   Node* value64 = ChangeInt32ToFloat64(value32);
   2543 
   2544   Label if_valueisint32(this), if_valueisheapnumber(this), if_join(this);
   2545 
   2546   Label if_valueisequal(this), if_valueisnotequal(this);
   2547   Branch(Float64Equal(value, value64), &if_valueisequal, &if_valueisnotequal);
   2548   Bind(&if_valueisequal);
   2549   {
   2550     GotoIfNot(Word32Equal(value32, Int32Constant(0)), &if_valueisint32);
   2551     Branch(Int32LessThan(Float64ExtractHighWord32(value), Int32Constant(0)),
   2552            &if_valueisheapnumber, &if_valueisint32);
   2553   }
   2554   Bind(&if_valueisnotequal);
   2555   Goto(&if_valueisheapnumber);
   2556 
   2557   Variable var_result(this, MachineRepresentation::kTagged);
   2558   Bind(&if_valueisint32);
   2559   {
   2560     if (Is64()) {
   2561       Node* result = SmiTag(ChangeInt32ToInt64(value32));
   2562       var_result.Bind(result);
   2563       Goto(&if_join);
   2564     } else {
   2565       Node* pair = Int32AddWithOverflow(value32, value32);
   2566       Node* overflow = Projection(1, pair);
   2567       Label if_overflow(this, Label::kDeferred), if_notoverflow(this);
   2568       Branch(overflow, &if_overflow, &if_notoverflow);
   2569       Bind(&if_overflow);
   2570       Goto(&if_valueisheapnumber);
   2571       Bind(&if_notoverflow);
   2572       {
   2573         Node* result = BitcastWordToTaggedSigned(Projection(0, pair));
   2574         var_result.Bind(result);
   2575         Goto(&if_join);
   2576       }
   2577     }
   2578   }
   2579   Bind(&if_valueisheapnumber);
   2580   {
   2581     Node* result = AllocateHeapNumberWithValue(value);
   2582     var_result.Bind(result);
   2583     Goto(&if_join);
   2584   }
   2585   Bind(&if_join);
   2586   return var_result.value();
   2587 }
   2588 
   2589 Node* CodeStubAssembler::ChangeInt32ToTagged(Node* value) {
   2590   if (Is64()) {
   2591     return SmiTag(ChangeInt32ToInt64(value));
   2592   }
   2593   Variable var_result(this, MachineRepresentation::kTagged);
   2594   Node* pair = Int32AddWithOverflow(value, value);
   2595   Node* overflow = Projection(1, pair);
   2596   Label if_overflow(this, Label::kDeferred), if_notoverflow(this),
   2597       if_join(this);
   2598   Branch(overflow, &if_overflow, &if_notoverflow);
   2599   Bind(&if_overflow);
   2600   {
   2601     Node* value64 = ChangeInt32ToFloat64(value);
   2602     Node* result = AllocateHeapNumberWithValue(value64);
   2603     var_result.Bind(result);
   2604   }
   2605   Goto(&if_join);
   2606   Bind(&if_notoverflow);
   2607   {
   2608     Node* result = BitcastWordToTaggedSigned(Projection(0, pair));
   2609     var_result.Bind(result);
   2610   }
   2611   Goto(&if_join);
   2612   Bind(&if_join);
   2613   return var_result.value();
   2614 }
   2615 
   2616 Node* CodeStubAssembler::ChangeUint32ToTagged(Node* value) {
   2617   Label if_overflow(this, Label::kDeferred), if_not_overflow(this),
   2618       if_join(this);
   2619   Variable var_result(this, MachineRepresentation::kTagged);
   2620   // If {value} > 2^31 - 1, we need to store it in a HeapNumber.
   2621   Branch(Uint32LessThan(Int32Constant(Smi::kMaxValue), value), &if_overflow,
   2622          &if_not_overflow);
   2623 
   2624   Bind(&if_not_overflow);
   2625   {
   2626     if (Is64()) {
   2627       var_result.Bind(SmiTag(ChangeUint32ToUint64(value)));
   2628     } else {
   2629       // If tagging {value} results in an overflow, we need to use a HeapNumber
   2630       // to represent it.
   2631       Node* pair = Int32AddWithOverflow(value, value);
   2632       Node* overflow = Projection(1, pair);
   2633       GotoIf(overflow, &if_overflow);
   2634 
   2635       Node* result = BitcastWordToTaggedSigned(Projection(0, pair));
   2636       var_result.Bind(result);
   2637     }
   2638   }
   2639   Goto(&if_join);
   2640 
   2641   Bind(&if_overflow);
   2642   {
   2643     Node* float64_value = ChangeUint32ToFloat64(value);
   2644     var_result.Bind(AllocateHeapNumberWithValue(float64_value));
   2645   }
   2646   Goto(&if_join);
   2647 
   2648   Bind(&if_join);
   2649   return var_result.value();
   2650 }
   2651 
   2652 Node* CodeStubAssembler::ToThisString(Node* context, Node* value,
   2653                                       char const* method_name) {
   2654   Variable var_value(this, MachineRepresentation::kTagged, value);
   2655 
   2656   // Check if the {value} is a Smi or a HeapObject.
   2657   Label if_valueissmi(this, Label::kDeferred), if_valueisnotsmi(this),
   2658       if_valueisstring(this);
   2659   Branch(TaggedIsSmi(value), &if_valueissmi, &if_valueisnotsmi);
   2660   Bind(&if_valueisnotsmi);
   2661   {
   2662     // Load the instance type of the {value}.
   2663     Node* value_instance_type = LoadInstanceType(value);
   2664 
   2665     // Check if the {value} is already String.
   2666     Label if_valueisnotstring(this, Label::kDeferred);
   2667     Branch(IsStringInstanceType(value_instance_type), &if_valueisstring,
   2668            &if_valueisnotstring);
   2669     Bind(&if_valueisnotstring);
   2670     {
   2671       // Check if the {value} is null.
   2672       Label if_valueisnullorundefined(this, Label::kDeferred),
   2673           if_valueisnotnullorundefined(this, Label::kDeferred),
   2674           if_valueisnotnull(this, Label::kDeferred);
   2675       Branch(WordEqual(value, NullConstant()), &if_valueisnullorundefined,
   2676              &if_valueisnotnull);
   2677       Bind(&if_valueisnotnull);
   2678       {
   2679         // Check if the {value} is undefined.
   2680         Branch(WordEqual(value, UndefinedConstant()),
   2681                &if_valueisnullorundefined, &if_valueisnotnullorundefined);
   2682         Bind(&if_valueisnotnullorundefined);
   2683         {
   2684           // Convert the {value} to a String.
   2685           Callable callable = CodeFactory::ToString(isolate());
   2686           var_value.Bind(CallStub(callable, context, value));
   2687           Goto(&if_valueisstring);
   2688         }
   2689       }
   2690 
   2691       Bind(&if_valueisnullorundefined);
   2692       {
   2693         // The {value} is either null or undefined.
   2694         CallRuntime(Runtime::kThrowCalledOnNullOrUndefined, context,
   2695                     HeapConstant(factory()->NewStringFromAsciiChecked(
   2696                         method_name, TENURED)));
   2697         Unreachable();
   2698       }
   2699     }
   2700   }
   2701   Bind(&if_valueissmi);
   2702   {
   2703     // The {value} is a Smi, convert it to a String.
   2704     Callable callable = CodeFactory::NumberToString(isolate());
   2705     var_value.Bind(CallStub(callable, context, value));
   2706     Goto(&if_valueisstring);
   2707   }
   2708   Bind(&if_valueisstring);
   2709   return var_value.value();
   2710 }
   2711 
   2712 Node* CodeStubAssembler::ChangeNumberToFloat64(compiler::Node* value) {
   2713   Variable result(this, MachineRepresentation::kFloat64);
   2714   Label smi(this);
   2715   Label done(this, &result);
   2716   GotoIf(TaggedIsSmi(value), &smi);
   2717   result.Bind(
   2718       LoadObjectField(value, HeapNumber::kValueOffset, MachineType::Float64()));
   2719   Goto(&done);
   2720 
   2721   Bind(&smi);
   2722   {
   2723     result.Bind(SmiToFloat64(value));
   2724     Goto(&done);
   2725   }
   2726 
   2727   Bind(&done);
   2728   return result.value();
   2729 }
   2730 
   2731 Node* CodeStubAssembler::ToThisValue(Node* context, Node* value,
   2732                                      PrimitiveType primitive_type,
   2733                                      char const* method_name) {
   2734   // We might need to loop once due to JSValue unboxing.
   2735   Variable var_value(this, MachineRepresentation::kTagged, value);
   2736   Label loop(this, &var_value), done_loop(this),
   2737       done_throw(this, Label::kDeferred);
   2738   Goto(&loop);
   2739   Bind(&loop);
   2740   {
   2741     // Load the current {value}.
   2742     value = var_value.value();
   2743 
   2744     // Check if the {value} is a Smi or a HeapObject.
   2745     GotoIf(TaggedIsSmi(value), (primitive_type == PrimitiveType::kNumber)
   2746                                    ? &done_loop
   2747                                    : &done_throw);
   2748 
   2749     // Load the mape of the {value}.
   2750     Node* value_map = LoadMap(value);
   2751 
   2752     // Load the instance type of the {value}.
   2753     Node* value_instance_type = LoadMapInstanceType(value_map);
   2754 
   2755     // Check if {value} is a JSValue.
   2756     Label if_valueisvalue(this, Label::kDeferred), if_valueisnotvalue(this);
   2757     Branch(Word32Equal(value_instance_type, Int32Constant(JS_VALUE_TYPE)),
   2758            &if_valueisvalue, &if_valueisnotvalue);
   2759 
   2760     Bind(&if_valueisvalue);
   2761     {
   2762       // Load the actual value from the {value}.
   2763       var_value.Bind(LoadObjectField(value, JSValue::kValueOffset));
   2764       Goto(&loop);
   2765     }
   2766 
   2767     Bind(&if_valueisnotvalue);
   2768     {
   2769       switch (primitive_type) {
   2770         case PrimitiveType::kBoolean:
   2771           GotoIf(WordEqual(value_map, BooleanMapConstant()), &done_loop);
   2772           break;
   2773         case PrimitiveType::kNumber:
   2774           GotoIf(
   2775               Word32Equal(value_instance_type, Int32Constant(HEAP_NUMBER_TYPE)),
   2776               &done_loop);
   2777           break;
   2778         case PrimitiveType::kString:
   2779           GotoIf(IsStringInstanceType(value_instance_type), &done_loop);
   2780           break;
   2781         case PrimitiveType::kSymbol:
   2782           GotoIf(Word32Equal(value_instance_type, Int32Constant(SYMBOL_TYPE)),
   2783                  &done_loop);
   2784           break;
   2785       }
   2786       Goto(&done_throw);
   2787     }
   2788   }
   2789 
   2790   Bind(&done_throw);
   2791   {
   2792     // The {value} is not a compatible receiver for this method.
   2793     CallRuntime(Runtime::kThrowNotGeneric, context,
   2794                 HeapConstant(factory()->NewStringFromAsciiChecked(method_name,
   2795                                                                   TENURED)));
   2796     Unreachable();
   2797   }
   2798 
   2799   Bind(&done_loop);
   2800   return var_value.value();
   2801 }
   2802 
   2803 Node* CodeStubAssembler::ThrowIfNotInstanceType(Node* context, Node* value,
   2804                                                 InstanceType instance_type,
   2805                                                 char const* method_name) {
   2806   Label out(this), throw_exception(this, Label::kDeferred);
   2807   Variable var_value_map(this, MachineRepresentation::kTagged);
   2808 
   2809   GotoIf(TaggedIsSmi(value), &throw_exception);
   2810 
   2811   // Load the instance type of the {value}.
   2812   var_value_map.Bind(LoadMap(value));
   2813   Node* const value_instance_type = LoadMapInstanceType(var_value_map.value());
   2814 
   2815   Branch(Word32Equal(value_instance_type, Int32Constant(instance_type)), &out,
   2816          &throw_exception);
   2817 
   2818   // The {value} is not a compatible receiver for this method.
   2819   Bind(&throw_exception);
   2820   CallRuntime(
   2821       Runtime::kThrowIncompatibleMethodReceiver, context,
   2822       HeapConstant(factory()->NewStringFromAsciiChecked(method_name, TENURED)),
   2823       value);
   2824   Unreachable();
   2825 
   2826   Bind(&out);
   2827   return var_value_map.value();
   2828 }
   2829 
   2830 Node* CodeStubAssembler::InstanceTypeEqual(Node* instance_type, int type) {
   2831   return Word32Equal(instance_type, Int32Constant(type));
   2832 }
   2833 
   2834 Node* CodeStubAssembler::IsSpecialReceiverMap(Node* map) {
   2835   Node* is_special = IsSpecialReceiverInstanceType(LoadMapInstanceType(map));
   2836   uint32_t mask =
   2837       1 << Map::kHasNamedInterceptor | 1 << Map::kIsAccessCheckNeeded;
   2838   USE(mask);
   2839   // Interceptors or access checks imply special receiver.
   2840   CSA_ASSERT(this,
   2841              SelectConstant(IsSetWord32(LoadMapBitField(map), mask), is_special,
   2842                             Int32Constant(1), MachineRepresentation::kWord32));
   2843   return is_special;
   2844 }
   2845 
   2846 Node* CodeStubAssembler::IsDictionaryMap(Node* map) {
   2847   CSA_SLOW_ASSERT(this, IsMap(map));
   2848   Node* bit_field3 = LoadMapBitField3(map);
   2849   return Word32NotEqual(IsSetWord32<Map::DictionaryMap>(bit_field3),
   2850                         Int32Constant(0));
   2851 }
   2852 
   2853 Node* CodeStubAssembler::IsCallableMap(Node* map) {
   2854   CSA_ASSERT(this, IsMap(map));
   2855   return Word32NotEqual(
   2856       Word32And(LoadMapBitField(map), Int32Constant(1 << Map::kIsCallable)),
   2857       Int32Constant(0));
   2858 }
   2859 
   2860 Node* CodeStubAssembler::IsCallable(Node* object) {
   2861   return IsCallableMap(LoadMap(object));
   2862 }
   2863 
   2864 Node* CodeStubAssembler::IsConstructorMap(Node* map) {
   2865   CSA_ASSERT(this, IsMap(map));
   2866   return Word32NotEqual(
   2867       Word32And(LoadMapBitField(map), Int32Constant(1 << Map::kIsConstructor)),
   2868       Int32Constant(0));
   2869 }
   2870 
   2871 Node* CodeStubAssembler::IsSpecialReceiverInstanceType(Node* instance_type) {
   2872   STATIC_ASSERT(JS_GLOBAL_OBJECT_TYPE <= LAST_SPECIAL_RECEIVER_TYPE);
   2873   return Int32LessThanOrEqual(instance_type,
   2874                               Int32Constant(LAST_SPECIAL_RECEIVER_TYPE));
   2875 }
   2876 
   2877 Node* CodeStubAssembler::IsStringInstanceType(Node* instance_type) {
   2878   STATIC_ASSERT(INTERNALIZED_STRING_TYPE == FIRST_TYPE);
   2879   return Int32LessThan(instance_type, Int32Constant(FIRST_NONSTRING_TYPE));
   2880 }
   2881 
   2882 Node* CodeStubAssembler::IsJSReceiverInstanceType(Node* instance_type) {
   2883   STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
   2884   return Int32GreaterThanOrEqual(instance_type,
   2885                                  Int32Constant(FIRST_JS_RECEIVER_TYPE));
   2886 }
   2887 
   2888 Node* CodeStubAssembler::IsJSReceiver(Node* object) {
   2889   STATIC_ASSERT(LAST_JS_OBJECT_TYPE == LAST_TYPE);
   2890   return IsJSReceiverInstanceType(LoadInstanceType(object));
   2891 }
   2892 
   2893 Node* CodeStubAssembler::IsJSReceiverMap(Node* map) {
   2894   STATIC_ASSERT(LAST_JS_OBJECT_TYPE == LAST_TYPE);
   2895   return IsJSReceiverInstanceType(LoadMapInstanceType(map));
   2896 }
   2897 
   2898 Node* CodeStubAssembler::IsJSObject(Node* object) {
   2899   STATIC_ASSERT(LAST_JS_OBJECT_TYPE == LAST_TYPE);
   2900   return Int32GreaterThanOrEqual(LoadInstanceType(object),
   2901                                  Int32Constant(FIRST_JS_RECEIVER_TYPE));
   2902 }
   2903 
   2904 Node* CodeStubAssembler::IsJSGlobalProxy(Node* object) {
   2905   return Word32Equal(LoadInstanceType(object),
   2906                      Int32Constant(JS_GLOBAL_PROXY_TYPE));
   2907 }
   2908 
   2909 Node* CodeStubAssembler::IsMap(Node* map) {
   2910   return HasInstanceType(map, MAP_TYPE);
   2911 }
   2912 
   2913 Node* CodeStubAssembler::IsJSValue(Node* map) {
   2914   return HasInstanceType(map, JS_VALUE_TYPE);
   2915 }
   2916 
   2917 Node* CodeStubAssembler::IsJSArray(Node* object) {
   2918   return HasInstanceType(object, JS_ARRAY_TYPE);
   2919 }
   2920 
   2921 Node* CodeStubAssembler::IsWeakCell(Node* object) {
   2922   return HasInstanceType(object, WEAK_CELL_TYPE);
   2923 }
   2924 
   2925 Node* CodeStubAssembler::IsBoolean(Node* object) {
   2926   return IsBooleanMap(LoadMap(object));
   2927 }
   2928 
   2929 Node* CodeStubAssembler::IsHeapNumber(Node* object) {
   2930   return IsHeapNumberMap(LoadMap(object));
   2931 }
   2932 
   2933 Node* CodeStubAssembler::IsName(Node* object) {
   2934   return Int32LessThanOrEqual(LoadInstanceType(object),
   2935                               Int32Constant(LAST_NAME_TYPE));
   2936 }
   2937 
   2938 Node* CodeStubAssembler::IsString(Node* object) {
   2939   return Int32LessThanOrEqual(LoadInstanceType(object),
   2940                               Int32Constant(FIRST_NONSTRING_TYPE));
   2941 }
   2942 
   2943 Node* CodeStubAssembler::IsSymbol(Node* object) {
   2944   return IsSymbolMap(LoadMap(object));
   2945 }
   2946 
   2947 Node* CodeStubAssembler::IsPrivateSymbol(Node* object) {
   2948   return Select(
   2949       IsSymbol(object),
   2950       [=] {
   2951         Node* const flags =
   2952             SmiToWord32(LoadObjectField(object, Symbol::kFlagsOffset));
   2953         const int kPrivateMask = 1 << Symbol::kPrivateBit;
   2954         return IsSetWord32(flags, kPrivateMask);
   2955       },
   2956       [=] { return Int32Constant(0); }, MachineRepresentation::kWord32);
   2957 }
   2958 
   2959 Node* CodeStubAssembler::IsNativeContext(Node* object) {
   2960   return WordEqual(LoadMap(object), LoadRoot(Heap::kNativeContextMapRootIndex));
   2961 }
   2962 
   2963 Node* CodeStubAssembler::IsFixedDoubleArray(Node* object) {
   2964   return WordEqual(LoadMap(object), FixedDoubleArrayMapConstant());
   2965 }
   2966 
   2967 Node* CodeStubAssembler::IsHashTable(Node* object) {
   2968   return WordEqual(LoadMap(object), LoadRoot(Heap::kHashTableMapRootIndex));
   2969 }
   2970 
   2971 Node* CodeStubAssembler::IsDictionary(Node* object) {
   2972   return Word32Or(IsHashTable(object), IsUnseededNumberDictionary(object));
   2973 }
   2974 
   2975 Node* CodeStubAssembler::IsUnseededNumberDictionary(Node* object) {
   2976   return WordEqual(LoadMap(object),
   2977                    LoadRoot(Heap::kUnseededNumberDictionaryMapRootIndex));
   2978 }
   2979 
   2980 Node* CodeStubAssembler::IsJSFunction(Node* object) {
   2981   return HasInstanceType(object, JS_FUNCTION_TYPE);
   2982 }
   2983 
   2984 Node* CodeStubAssembler::StringCharCodeAt(Node* string, Node* index,
   2985                                           ParameterMode parameter_mode) {
   2986   CSA_ASSERT(this, IsString(string));
   2987   // Translate the {index} into a Word.
   2988   index = ParameterToWord(index, parameter_mode);
   2989 
   2990   // We may need to loop in case of cons, thin, or sliced strings.
   2991   Variable var_index(this, MachineType::PointerRepresentation(), index);
   2992   Variable var_string(this, MachineRepresentation::kTagged, string);
   2993   Variable var_result(this, MachineRepresentation::kWord32);
   2994   Variable* loop_vars[] = {&var_index, &var_string};
   2995   Label done_loop(this, &var_result), loop(this, 2, loop_vars);
   2996   Goto(&loop);
   2997   Bind(&loop);
   2998   {
   2999     // Load the current {index}.
   3000     index = var_index.value();
   3001 
   3002     // Load the current {string}.
   3003     string = var_string.value();
   3004 
   3005     // Load the instance type of the {string}.
   3006     Node* string_instance_type = LoadInstanceType(string);
   3007 
   3008     // Check if the {string} is a SeqString.
   3009     Label if_stringissequential(this), if_stringisnotsequential(this);
   3010     Branch(Word32Equal(Word32And(string_instance_type,
   3011                                  Int32Constant(kStringRepresentationMask)),
   3012                        Int32Constant(kSeqStringTag)),
   3013            &if_stringissequential, &if_stringisnotsequential);
   3014 
   3015     Bind(&if_stringissequential);
   3016     {
   3017       // Check if the {string} is a TwoByteSeqString or a OneByteSeqString.
   3018       Label if_stringistwobyte(this), if_stringisonebyte(this);
   3019       Branch(Word32Equal(Word32And(string_instance_type,
   3020                                    Int32Constant(kStringEncodingMask)),
   3021                          Int32Constant(kTwoByteStringTag)),
   3022              &if_stringistwobyte, &if_stringisonebyte);
   3023 
   3024       Bind(&if_stringisonebyte);
   3025       {
   3026         var_result.Bind(
   3027             Load(MachineType::Uint8(), string,
   3028                  IntPtrAdd(index, IntPtrConstant(SeqOneByteString::kHeaderSize -
   3029                                                  kHeapObjectTag))));
   3030         Goto(&done_loop);
   3031       }
   3032 
   3033       Bind(&if_stringistwobyte);
   3034       {
   3035         var_result.Bind(
   3036             Load(MachineType::Uint16(), string,
   3037                  IntPtrAdd(WordShl(index, IntPtrConstant(1)),
   3038                            IntPtrConstant(SeqTwoByteString::kHeaderSize -
   3039                                           kHeapObjectTag))));
   3040         Goto(&done_loop);
   3041       }
   3042     }
   3043 
   3044     Bind(&if_stringisnotsequential);
   3045     {
   3046       // Check if the {string} is a ConsString.
   3047       Label if_stringiscons(this), if_stringisnotcons(this);
   3048       Branch(Word32Equal(Word32And(string_instance_type,
   3049                                    Int32Constant(kStringRepresentationMask)),
   3050                          Int32Constant(kConsStringTag)),
   3051              &if_stringiscons, &if_stringisnotcons);
   3052 
   3053       Bind(&if_stringiscons);
   3054       {
   3055         // Check whether the right hand side is the empty string (i.e. if
   3056         // this is really a flat string in a cons string). If that is not
   3057         // the case we flatten the string first.
   3058         Label if_rhsisempty(this), if_rhsisnotempty(this, Label::kDeferred);
   3059         Node* rhs = LoadObjectField(string, ConsString::kSecondOffset);
   3060         Branch(WordEqual(rhs, EmptyStringConstant()), &if_rhsisempty,
   3061                &if_rhsisnotempty);
   3062 
   3063         Bind(&if_rhsisempty);
   3064         {
   3065           // Just operate on the left hand side of the {string}.
   3066           var_string.Bind(LoadObjectField(string, ConsString::kFirstOffset));
   3067           Goto(&loop);
   3068         }
   3069 
   3070         Bind(&if_rhsisnotempty);
   3071         {
   3072           // Flatten the {string} and lookup in the resulting string.
   3073           var_string.Bind(CallRuntime(Runtime::kFlattenString,
   3074                                       NoContextConstant(), string));
   3075           Goto(&loop);
   3076         }
   3077       }
   3078 
   3079       Bind(&if_stringisnotcons);
   3080       {
   3081         // Check if the {string} is an ExternalString.
   3082         Label if_stringisexternal(this), if_stringisnotexternal(this);
   3083         Branch(Word32Equal(Word32And(string_instance_type,
   3084                                      Int32Constant(kStringRepresentationMask)),
   3085                            Int32Constant(kExternalStringTag)),
   3086                &if_stringisexternal, &if_stringisnotexternal);
   3087 
   3088         Bind(&if_stringisexternal);
   3089         {
   3090           // Check if the {string} is a short external string.
   3091           Label if_stringisnotshort(this),
   3092               if_stringisshort(this, Label::kDeferred);
   3093           Branch(Word32Equal(Word32And(string_instance_type,
   3094                                        Int32Constant(kShortExternalStringMask)),
   3095                              Int32Constant(0)),
   3096                  &if_stringisnotshort, &if_stringisshort);
   3097 
   3098           Bind(&if_stringisnotshort);
   3099           {
   3100             // Load the actual resource data from the {string}.
   3101             Node* string_resource_data =
   3102                 LoadObjectField(string, ExternalString::kResourceDataOffset,
   3103                                 MachineType::Pointer());
   3104 
   3105             // Check if the {string} is a TwoByteExternalString or a
   3106             // OneByteExternalString.
   3107             Label if_stringistwobyte(this), if_stringisonebyte(this);
   3108             Branch(Word32Equal(Word32And(string_instance_type,
   3109                                          Int32Constant(kStringEncodingMask)),
   3110                                Int32Constant(kTwoByteStringTag)),
   3111                    &if_stringistwobyte, &if_stringisonebyte);
   3112 
   3113             Bind(&if_stringisonebyte);
   3114             {
   3115               var_result.Bind(
   3116                   Load(MachineType::Uint8(), string_resource_data, index));
   3117               Goto(&done_loop);
   3118             }
   3119 
   3120             Bind(&if_stringistwobyte);
   3121             {
   3122               var_result.Bind(Load(MachineType::Uint16(), string_resource_data,
   3123                                    WordShl(index, IntPtrConstant(1))));
   3124               Goto(&done_loop);
   3125             }
   3126           }
   3127 
   3128           Bind(&if_stringisshort);
   3129           {
   3130             // The {string} might be compressed, call the runtime.
   3131             var_result.Bind(SmiToWord32(
   3132                 CallRuntime(Runtime::kExternalStringGetChar,
   3133                             NoContextConstant(), string, SmiTag(index))));
   3134             Goto(&done_loop);
   3135           }
   3136         }
   3137 
   3138         Bind(&if_stringisnotexternal);
   3139         {
   3140           Label if_stringissliced(this), if_stringisthin(this);
   3141           Branch(
   3142               Word32Equal(Word32And(string_instance_type,
   3143                                     Int32Constant(kStringRepresentationMask)),
   3144                           Int32Constant(kSlicedStringTag)),
   3145               &if_stringissliced, &if_stringisthin);
   3146           Bind(&if_stringissliced);
   3147           {
   3148             // The {string} is a SlicedString, continue with its parent.
   3149             Node* string_offset =
   3150                 LoadAndUntagObjectField(string, SlicedString::kOffsetOffset);
   3151             Node* string_parent =
   3152                 LoadObjectField(string, SlicedString::kParentOffset);
   3153             var_index.Bind(IntPtrAdd(index, string_offset));
   3154             var_string.Bind(string_parent);
   3155             Goto(&loop);
   3156           }
   3157           Bind(&if_stringisthin);
   3158           {
   3159             // The {string} is a ThinString, continue with its actual value.
   3160             var_string.Bind(LoadObjectField(string, ThinString::kActualOffset));
   3161             Goto(&loop);
   3162           }
   3163         }
   3164       }
   3165     }
   3166   }
   3167 
   3168   Bind(&done_loop);
   3169   return var_result.value();
   3170 }
   3171 
   3172 Node* CodeStubAssembler::StringFromCharCode(Node* code) {
   3173   Variable var_result(this, MachineRepresentation::kTagged);
   3174 
   3175   // Check if the {code} is a one-byte char code.
   3176   Label if_codeisonebyte(this), if_codeistwobyte(this, Label::kDeferred),
   3177       if_done(this);
   3178   Branch(Int32LessThanOrEqual(code, Int32Constant(String::kMaxOneByteCharCode)),
   3179          &if_codeisonebyte, &if_codeistwobyte);
   3180   Bind(&if_codeisonebyte);
   3181   {
   3182     // Load the isolate wide single character string cache.
   3183     Node* cache = LoadRoot(Heap::kSingleCharacterStringCacheRootIndex);
   3184     Node* code_index = ChangeUint32ToWord(code);
   3185 
   3186     // Check if we have an entry for the {code} in the single character string
   3187     // cache already.
   3188     Label if_entryisundefined(this, Label::kDeferred),
   3189         if_entryisnotundefined(this);
   3190     Node* entry = LoadFixedArrayElement(cache, code_index);
   3191     Branch(WordEqual(entry, UndefinedConstant()), &if_entryisundefined,
   3192            &if_entryisnotundefined);
   3193 
   3194     Bind(&if_entryisundefined);
   3195     {
   3196       // Allocate a new SeqOneByteString for {code} and store it in the {cache}.
   3197       Node* result = AllocateSeqOneByteString(1);
   3198       StoreNoWriteBarrier(
   3199           MachineRepresentation::kWord8, result,
   3200           IntPtrConstant(SeqOneByteString::kHeaderSize - kHeapObjectTag), code);
   3201       StoreFixedArrayElement(cache, code_index, result);
   3202       var_result.Bind(result);
   3203       Goto(&if_done);
   3204     }
   3205 
   3206     Bind(&if_entryisnotundefined);
   3207     {
   3208       // Return the entry from the {cache}.
   3209       var_result.Bind(entry);
   3210       Goto(&if_done);
   3211     }
   3212   }
   3213 
   3214   Bind(&if_codeistwobyte);
   3215   {
   3216     // Allocate a new SeqTwoByteString for {code}.
   3217     Node* result = AllocateSeqTwoByteString(1);
   3218     StoreNoWriteBarrier(
   3219         MachineRepresentation::kWord16, result,
   3220         IntPtrConstant(SeqTwoByteString::kHeaderSize - kHeapObjectTag), code);
   3221     var_result.Bind(result);
   3222     Goto(&if_done);
   3223   }
   3224 
   3225   Bind(&if_done);
   3226   return var_result.value();
   3227 }
   3228 
   3229 namespace {
   3230 
   3231 // A wrapper around CopyStringCharacters which determines the correct string
   3232 // encoding, allocates a corresponding sequential string, and then copies the
   3233 // given character range using CopyStringCharacters.
   3234 // |from_string| must be a sequential string. |from_index| and
   3235 // |character_count| must be Smis s.t.
   3236 // 0 <= |from_index| <= |from_index| + |character_count| < from_string.length.
   3237 Node* AllocAndCopyStringCharacters(CodeStubAssembler* a, Node* context,
   3238                                    Node* from, Node* from_instance_type,
   3239                                    Node* from_index, Node* character_count) {
   3240   typedef CodeStubAssembler::Label Label;
   3241   typedef CodeStubAssembler::Variable Variable;
   3242 
   3243   Label end(a), two_byte_sequential(a);
   3244   Variable var_result(a, MachineRepresentation::kTagged);
   3245 
   3246   Node* const smi_zero = a->SmiConstant(Smi::kZero);
   3247 
   3248   STATIC_ASSERT((kOneByteStringTag & kStringEncodingMask) != 0);
   3249   a->GotoIf(a->Word32Equal(a->Word32And(from_instance_type,
   3250                                         a->Int32Constant(kStringEncodingMask)),
   3251                            a->Int32Constant(0)),
   3252             &two_byte_sequential);
   3253 
   3254   // The subject string is a sequential one-byte string.
   3255   {
   3256     Node* result =
   3257         a->AllocateSeqOneByteString(context, a->SmiToWord(character_count));
   3258     a->CopyStringCharacters(from, result, from_index, smi_zero, character_count,
   3259                             String::ONE_BYTE_ENCODING,
   3260                             String::ONE_BYTE_ENCODING,
   3261                             CodeStubAssembler::SMI_PARAMETERS);
   3262     var_result.Bind(result);
   3263 
   3264     a->Goto(&end);
   3265   }
   3266 
   3267   // The subject string is a sequential two-byte string.
   3268   a->Bind(&two_byte_sequential);
   3269   {
   3270     Node* result =
   3271         a->AllocateSeqTwoByteString(context, a->SmiToWord(character_count));
   3272     a->CopyStringCharacters(from, result, from_index, smi_zero, character_count,
   3273                             String::TWO_BYTE_ENCODING,
   3274                             String::TWO_BYTE_ENCODING,
   3275                             CodeStubAssembler::SMI_PARAMETERS);
   3276     var_result.Bind(result);
   3277 
   3278     a->Goto(&end);
   3279   }
   3280 
   3281   a->Bind(&end);
   3282   return var_result.value();
   3283 }
   3284 
   3285 }  // namespace
   3286 
   3287 Node* CodeStubAssembler::SubString(Node* context, Node* string, Node* from,
   3288                                    Node* to) {
   3289   Label end(this);
   3290   Label runtime(this);
   3291 
   3292   Node* const int_zero = Int32Constant(0);
   3293 
   3294   // Int32 variables.
   3295   Variable var_instance_type(this, MachineRepresentation::kWord32, int_zero);
   3296   Variable var_representation(this, MachineRepresentation::kWord32, int_zero);
   3297 
   3298   Variable var_from(this, MachineRepresentation::kTagged, from);      // Smi.
   3299   Variable var_string(this, MachineRepresentation::kTagged, string);  // String.
   3300   Variable var_result(this, MachineRepresentation::kTagged);          // String.
   3301 
   3302   // Make sure first argument is a string.
   3303   CSA_ASSERT(this, TaggedIsNotSmi(string));
   3304   CSA_ASSERT(this, IsString(string));
   3305 
   3306   // Load the instance type of the {string}.
   3307   Node* const instance_type = LoadInstanceType(string);
   3308   var_instance_type.Bind(instance_type);
   3309 
   3310   // Make sure that both from and to are non-negative smis.
   3311 
   3312   GotoIfNot(TaggedIsPositiveSmi(from), &runtime);
   3313   GotoIfNot(TaggedIsPositiveSmi(to), &runtime);
   3314 
   3315   Node* const substr_length = SmiSub(to, from);
   3316   Node* const string_length = LoadStringLength(string);
   3317 
   3318   // Begin dispatching based on substring length.
   3319 
   3320   Label original_string_or_invalid_length(this);
   3321   GotoIf(SmiAboveOrEqual(substr_length, string_length),
   3322          &original_string_or_invalid_length);
   3323 
   3324   // A real substring (substr_length < string_length).
   3325 
   3326   Label single_char(this);
   3327   GotoIf(SmiEqual(substr_length, SmiConstant(Smi::FromInt(1))), &single_char);
   3328 
   3329   // TODO(jgruber): Add an additional case for substring of length == 0?
   3330 
   3331   // Deal with different string types: update the index if necessary
   3332   // and put the underlying string into var_string.
   3333 
   3334   // If the string is not indirect, it can only be sequential or external.
   3335   STATIC_ASSERT(kIsIndirectStringMask ==
   3336                 (kSlicedStringTag & kConsStringTag & kThinStringTag));
   3337   STATIC_ASSERT(kIsIndirectStringMask != 0);
   3338   Label underlying_unpacked(this);
   3339   GotoIf(Word32Equal(
   3340              Word32And(instance_type, Int32Constant(kIsIndirectStringMask)),
   3341              Int32Constant(0)),
   3342          &underlying_unpacked);
   3343 
   3344   // The subject string is a sliced, cons, or thin string.
   3345 
   3346   Label thin_string(this), thin_or_sliced(this);
   3347   var_representation.Bind(
   3348       Word32And(instance_type, Int32Constant(kStringRepresentationMask)));
   3349   GotoIf(
   3350       Word32NotEqual(var_representation.value(), Int32Constant(kConsStringTag)),
   3351       &thin_or_sliced);
   3352 
   3353   // Cons string.  Check whether it is flat, then fetch first part.
   3354   // Flat cons strings have an empty second part.
   3355   {
   3356     GotoIf(WordNotEqual(LoadObjectField(string, ConsString::kSecondOffset),
   3357                         EmptyStringConstant()),
   3358            &runtime);
   3359 
   3360     Node* first_string_part = LoadObjectField(string, ConsString::kFirstOffset);
   3361     var_string.Bind(first_string_part);
   3362     var_instance_type.Bind(LoadInstanceType(first_string_part));
   3363     var_representation.Bind(Word32And(
   3364         var_instance_type.value(), Int32Constant(kStringRepresentationMask)));
   3365 
   3366     // The loaded first part might be a thin string.
   3367     Branch(Word32Equal(Word32And(var_instance_type.value(),
   3368                                  Int32Constant(kIsIndirectStringMask)),
   3369                        Int32Constant(0)),
   3370            &underlying_unpacked, &thin_string);
   3371   }
   3372 
   3373   Bind(&thin_or_sliced);
   3374   {
   3375     GotoIf(
   3376         Word32Equal(var_representation.value(), Int32Constant(kThinStringTag)),
   3377         &thin_string);
   3378     // Otherwise it's a sliced string.
   3379     // Fetch parent and correct start index by offset.
   3380     Node* sliced_offset =
   3381         LoadObjectField(var_string.value(), SlicedString::kOffsetOffset);
   3382     var_from.Bind(SmiAdd(from, sliced_offset));
   3383 
   3384     Node* slice_parent = LoadObjectField(string, SlicedString::kParentOffset);
   3385     var_string.Bind(slice_parent);
   3386 
   3387     Node* slice_parent_instance_type = LoadInstanceType(slice_parent);
   3388     var_instance_type.Bind(slice_parent_instance_type);
   3389 
   3390     // The loaded parent might be a thin string.
   3391     Branch(Word32Equal(Word32And(var_instance_type.value(),
   3392                                  Int32Constant(kIsIndirectStringMask)),
   3393                        Int32Constant(0)),
   3394            &underlying_unpacked, &thin_string);
   3395   }
   3396 
   3397   Bind(&thin_string);
   3398   {
   3399     Node* actual_string =
   3400         LoadObjectField(var_string.value(), ThinString::kActualOffset);
   3401     var_string.Bind(actual_string);
   3402     var_instance_type.Bind(LoadInstanceType(actual_string));
   3403     Goto(&underlying_unpacked);
   3404   }
   3405 
   3406   // The subject string can only be external or sequential string of either
   3407   // encoding at this point.
   3408   Label external_string(this);
   3409   Bind(&underlying_unpacked);
   3410   {
   3411     if (FLAG_string_slices) {
   3412       Label copy_routine(this);
   3413 
   3414       // Short slice.  Copy instead of slicing.
   3415       GotoIf(SmiLessThan(substr_length,
   3416                          SmiConstant(Smi::FromInt(SlicedString::kMinLength))),
   3417              &copy_routine);
   3418 
   3419       // Allocate new sliced string.
   3420 
   3421       Label two_byte_slice(this);
   3422       STATIC_ASSERT((kStringEncodingMask & kOneByteStringTag) != 0);
   3423       STATIC_ASSERT((kStringEncodingMask & kTwoByteStringTag) == 0);
   3424 
   3425       Counters* counters = isolate()->counters();
   3426       IncrementCounter(counters->sub_string_native(), 1);
   3427 
   3428       GotoIf(Word32Equal(Word32And(var_instance_type.value(),
   3429                                    Int32Constant(kStringEncodingMask)),
   3430                          Int32Constant(0)),
   3431              &two_byte_slice);
   3432 
   3433       var_result.Bind(AllocateSlicedOneByteString(
   3434           substr_length, var_string.value(), var_from.value()));
   3435       Goto(&end);
   3436 
   3437       Bind(&two_byte_slice);
   3438 
   3439       var_result.Bind(AllocateSlicedTwoByteString(
   3440           substr_length, var_string.value(), var_from.value()));
   3441       Goto(&end);
   3442 
   3443       Bind(&copy_routine);
   3444     }
   3445 
   3446     // The subject string can only be external or sequential string of either
   3447     // encoding at this point.
   3448     STATIC_ASSERT(kExternalStringTag != 0);
   3449     STATIC_ASSERT(kSeqStringTag == 0);
   3450     GotoIfNot(Word32Equal(Word32And(var_instance_type.value(),
   3451                                     Int32Constant(kExternalStringTag)),
   3452                           Int32Constant(0)),
   3453               &external_string);
   3454 
   3455     var_result.Bind(AllocAndCopyStringCharacters(
   3456         this, context, var_string.value(), var_instance_type.value(),
   3457         var_from.value(), substr_length));
   3458 
   3459     Counters* counters = isolate()->counters();
   3460     IncrementCounter(counters->sub_string_native(), 1);
   3461 
   3462     Goto(&end);
   3463   }
   3464 
   3465   // Handle external string.
   3466   Bind(&external_string);
   3467   {
   3468     Node* const fake_sequential_string = TryDerefExternalString(
   3469         var_string.value(), var_instance_type.value(), &runtime);
   3470 
   3471     var_result.Bind(AllocAndCopyStringCharacters(
   3472         this, context, fake_sequential_string, var_instance_type.value(),
   3473         var_from.value(), substr_length));
   3474 
   3475     Counters* counters = isolate()->counters();
   3476     IncrementCounter(counters->sub_string_native(), 1);
   3477 
   3478     Goto(&end);
   3479   }
   3480 
   3481   // Substrings of length 1 are generated through CharCodeAt and FromCharCode.
   3482   Bind(&single_char);
   3483   {
   3484     Node* char_code = StringCharCodeAt(var_string.value(), var_from.value());
   3485     var_result.Bind(StringFromCharCode(char_code));
   3486     Goto(&end);
   3487   }
   3488 
   3489   Bind(&original_string_or_invalid_length);
   3490   {
   3491     // Longer than original string's length or negative: unsafe arguments.
   3492     GotoIf(SmiAbove(substr_length, string_length), &runtime);
   3493 
   3494     // Equal length - check if {from, to} == {0, str.length}.
   3495     GotoIf(SmiAbove(from, SmiConstant(Smi::kZero)), &runtime);
   3496 
   3497     // Return the original string (substr_length == string_length).
   3498 
   3499     Counters* counters = isolate()->counters();
   3500     IncrementCounter(counters->sub_string_native(), 1);
   3501 
   3502     var_result.Bind(string);
   3503     Goto(&end);
   3504   }
   3505 
   3506   // Fall back to a runtime call.
   3507   Bind(&runtime);
   3508   {
   3509     var_result.Bind(
   3510         CallRuntime(Runtime::kSubString, context, string, from, to));
   3511     Goto(&end);
   3512   }
   3513 
   3514   Bind(&end);
   3515   return var_result.value();
   3516 }
   3517 
   3518 namespace {
   3519 
   3520 Node* IsExternalStringInstanceType(CodeStubAssembler* a,
   3521                                    Node* const instance_type) {
   3522   CSA_ASSERT(a, a->IsStringInstanceType(instance_type));
   3523   return a->Word32Equal(
   3524       a->Word32And(instance_type, a->Int32Constant(kStringRepresentationMask)),
   3525       a->Int32Constant(kExternalStringTag));
   3526 }
   3527 
   3528 Node* IsShortExternalStringInstanceType(CodeStubAssembler* a,
   3529                                         Node* const instance_type) {
   3530   CSA_ASSERT(a, a->IsStringInstanceType(instance_type));
   3531   STATIC_ASSERT(kShortExternalStringTag != 0);
   3532   return a->Word32NotEqual(
   3533       a->Word32And(instance_type, a->Int32Constant(kShortExternalStringMask)),
   3534       a->Int32Constant(0));
   3535 }
   3536 
   3537 }  // namespace
   3538 
   3539 Node* CodeStubAssembler::TryDerefExternalString(Node* const string,
   3540                                                 Node* const instance_type,
   3541                                                 Label* if_bailout) {
   3542   Label out(this);
   3543 
   3544   USE(IsExternalStringInstanceType);
   3545   CSA_ASSERT(this, IsExternalStringInstanceType(this, instance_type));
   3546   GotoIf(IsShortExternalStringInstanceType(this, instance_type), if_bailout);
   3547 
   3548   // Move the pointer so that offset-wise, it looks like a sequential string.
   3549   STATIC_ASSERT(SeqTwoByteString::kHeaderSize == SeqOneByteString::kHeaderSize);
   3550 
   3551   Node* resource_data = LoadObjectField(
   3552       string, ExternalString::kResourceDataOffset, MachineType::Pointer());
   3553   Node* const fake_sequential_string =
   3554       IntPtrSub(resource_data,
   3555                 IntPtrConstant(SeqTwoByteString::kHeaderSize - kHeapObjectTag));
   3556 
   3557   return fake_sequential_string;
   3558 }
   3559 
   3560 void CodeStubAssembler::MaybeDerefIndirectString(Variable* var_string,
   3561                                                  Node* instance_type,
   3562                                                  Variable* var_did_something) {
   3563   Label deref(this), done(this, var_did_something);
   3564   Node* representation =
   3565       Word32And(instance_type, Int32Constant(kStringRepresentationMask));
   3566   GotoIf(Word32Equal(representation, Int32Constant(kThinStringTag)), &deref);
   3567   GotoIf(Word32NotEqual(representation, Int32Constant(kConsStringTag)), &done);
   3568   // Cons string.
   3569   Node* rhs = LoadObjectField(var_string->value(), ConsString::kSecondOffset);
   3570   GotoIf(WordEqual(rhs, EmptyStringConstant()), &deref);
   3571   Goto(&done);
   3572 
   3573   Bind(&deref);
   3574   STATIC_ASSERT(ThinString::kActualOffset == ConsString::kFirstOffset);
   3575   var_string->Bind(
   3576       LoadObjectField(var_string->value(), ThinString::kActualOffset));
   3577   var_did_something->Bind(IntPtrConstant(1));
   3578   Goto(&done);
   3579 
   3580   Bind(&done);
   3581 }
   3582 
   3583 void CodeStubAssembler::MaybeDerefIndirectStrings(Variable* var_left,
   3584                                                   Node* left_instance_type,
   3585                                                   Variable* var_right,
   3586                                                   Node* right_instance_type,
   3587                                                   Label* did_something) {
   3588   Variable var_did_something(this, MachineType::PointerRepresentation(),
   3589                              IntPtrConstant(0));
   3590   MaybeDerefIndirectString(var_left, left_instance_type, &var_did_something);
   3591   MaybeDerefIndirectString(var_right, right_instance_type, &var_did_something);
   3592 
   3593   GotoIf(WordNotEqual(var_did_something.value(), IntPtrConstant(0)),
   3594          did_something);
   3595   // Fall through if neither string was an indirect string.
   3596 }
   3597 
   3598 Node* CodeStubAssembler::StringAdd(Node* context, Node* left, Node* right,
   3599                                    AllocationFlags flags) {
   3600   Label check_right(this);
   3601   Label runtime(this, Label::kDeferred);
   3602   Label cons(this);
   3603   Variable result(this, MachineRepresentation::kTagged);
   3604   Label done(this, &result);
   3605   Label done_native(this, &result);
   3606   Counters* counters = isolate()->counters();
   3607 
   3608   Node* left_length = LoadStringLength(left);
   3609   GotoIf(WordNotEqual(IntPtrConstant(0), left_length), &check_right);
   3610   result.Bind(right);
   3611   Goto(&done_native);
   3612 
   3613   Bind(&check_right);
   3614   Node* right_length = LoadStringLength(right);
   3615   GotoIf(WordNotEqual(IntPtrConstant(0), right_length), &cons);
   3616   result.Bind(left);
   3617   Goto(&done_native);
   3618 
   3619   Bind(&cons);
   3620   {
   3621     CSA_ASSERT(this, TaggedIsSmi(left_length));
   3622     CSA_ASSERT(this, TaggedIsSmi(right_length));
   3623     Node* new_length = SmiAdd(left_length, right_length);
   3624     GotoIf(SmiAboveOrEqual(new_length, SmiConstant(String::kMaxLength)),
   3625            &runtime);
   3626 
   3627     Variable var_left(this, MachineRepresentation::kTagged, left);
   3628     Variable var_right(this, MachineRepresentation::kTagged, right);
   3629     Variable* input_vars[2] = {&var_left, &var_right};
   3630     Label non_cons(this, 2, input_vars);
   3631     Label slow(this, Label::kDeferred);
   3632     GotoIf(SmiLessThan(new_length, SmiConstant(ConsString::kMinLength)),
   3633            &non_cons);
   3634 
   3635     result.Bind(NewConsString(context, new_length, var_left.value(),
   3636                               var_right.value(), flags));
   3637     Goto(&done_native);
   3638 
   3639     Bind(&non_cons);
   3640 
   3641     Comment("Full string concatenate");
   3642     Node* left_instance_type = LoadInstanceType(var_left.value());
   3643     Node* right_instance_type = LoadInstanceType(var_right.value());
   3644     // Compute intersection and difference of instance types.
   3645 
   3646     Node* ored_instance_types =
   3647         Word32Or(left_instance_type, right_instance_type);
   3648     Node* xored_instance_types =
   3649         Word32Xor(left_instance_type, right_instance_type);
   3650 
   3651     // Check if both strings have the same encoding and both are sequential.
   3652     GotoIf(Word32NotEqual(Word32And(xored_instance_types,
   3653                                     Int32Constant(kStringEncodingMask)),
   3654                           Int32Constant(0)),
   3655            &runtime);
   3656     GotoIf(Word32NotEqual(Word32And(ored_instance_types,
   3657                                     Int32Constant(kStringRepresentationMask)),
   3658                           Int32Constant(0)),
   3659            &slow);
   3660 
   3661     Label two_byte(this);
   3662     GotoIf(Word32Equal(Word32And(ored_instance_types,
   3663                                  Int32Constant(kStringEncodingMask)),
   3664                        Int32Constant(kTwoByteStringTag)),
   3665            &two_byte);
   3666     // One-byte sequential string case
   3667     Node* new_string =
   3668         AllocateSeqOneByteString(context, new_length, SMI_PARAMETERS);
   3669     CopyStringCharacters(var_left.value(), new_string, SmiConstant(Smi::kZero),
   3670                          SmiConstant(Smi::kZero), left_length,
   3671                          String::ONE_BYTE_ENCODING, String::ONE_BYTE_ENCODING,
   3672                          SMI_PARAMETERS);
   3673     CopyStringCharacters(var_right.value(), new_string, SmiConstant(Smi::kZero),
   3674                          left_length, right_length, String::ONE_BYTE_ENCODING,
   3675                          String::ONE_BYTE_ENCODING, SMI_PARAMETERS);
   3676     result.Bind(new_string);
   3677     Goto(&done_native);
   3678 
   3679     Bind(&two_byte);
   3680     {
   3681       // Two-byte sequential string case
   3682       new_string =
   3683           AllocateSeqTwoByteString(context, new_length, SMI_PARAMETERS);
   3684       CopyStringCharacters(var_left.value(), new_string,
   3685                            SmiConstant(Smi::kZero), SmiConstant(Smi::kZero),
   3686                            left_length, String::TWO_BYTE_ENCODING,
   3687                            String::TWO_BYTE_ENCODING, SMI_PARAMETERS);
   3688       CopyStringCharacters(var_right.value(), new_string,
   3689                            SmiConstant(Smi::kZero), left_length, right_length,
   3690                            String::TWO_BYTE_ENCODING, String::TWO_BYTE_ENCODING,
   3691                            SMI_PARAMETERS);
   3692       result.Bind(new_string);
   3693       Goto(&done_native);
   3694     }
   3695 
   3696     Bind(&slow);
   3697     {
   3698       // Try to unwrap indirect strings, restart the above attempt on success.
   3699       MaybeDerefIndirectStrings(&var_left, left_instance_type, &var_right,
   3700                                 right_instance_type, &non_cons);
   3701       Goto(&runtime);
   3702     }
   3703   }
   3704   Bind(&runtime);
   3705   {
   3706     result.Bind(CallRuntime(Runtime::kStringAdd, context, left, right));
   3707     Goto(&done);
   3708   }
   3709 
   3710   Bind(&done_native);
   3711   {
   3712     IncrementCounter(counters->string_add_native(), 1);
   3713     Goto(&done);
   3714   }
   3715 
   3716   Bind(&done);
   3717   return result.value();
   3718 }
   3719 
   3720 Node* CodeStubAssembler::StringFromCodePoint(Node* codepoint,
   3721                                              UnicodeEncoding encoding) {
   3722   Variable var_result(this, MachineRepresentation::kTagged,
   3723                       EmptyStringConstant());
   3724 
   3725   Label if_isword16(this), if_isword32(this), return_result(this);
   3726 
   3727   Branch(Uint32LessThan(codepoint, Int32Constant(0x10000)), &if_isword16,
   3728          &if_isword32);
   3729 
   3730   Bind(&if_isword16);
   3731   {
   3732     var_result.Bind(StringFromCharCode(codepoint));
   3733     Goto(&return_result);
   3734   }
   3735 
   3736   Bind(&if_isword32);
   3737   {
   3738     switch (encoding) {
   3739       case UnicodeEncoding::UTF16:
   3740         break;
   3741       case UnicodeEncoding::UTF32: {
   3742         // Convert UTF32 to UTF16 code units, and store as a 32 bit word.
   3743         Node* lead_offset = Int32Constant(0xD800 - (0x10000 >> 10));
   3744 
   3745         // lead = (codepoint >> 10) + LEAD_OFFSET
   3746         Node* lead =
   3747             Int32Add(WordShr(codepoint, Int32Constant(10)), lead_offset);
   3748 
   3749         // trail = (codepoint & 0x3FF) + 0xDC00;
   3750         Node* trail = Int32Add(Word32And(codepoint, Int32Constant(0x3FF)),
   3751                                Int32Constant(0xDC00));
   3752 
   3753         // codpoint = (trail << 16) | lead;
   3754         codepoint = Word32Or(WordShl(trail, Int32Constant(16)), lead);
   3755         break;
   3756       }
   3757     }
   3758 
   3759     Node* value = AllocateSeqTwoByteString(2);
   3760     StoreNoWriteBarrier(
   3761         MachineRepresentation::kWord32, value,
   3762         IntPtrConstant(SeqTwoByteString::kHeaderSize - kHeapObjectTag),
   3763         codepoint);
   3764     var_result.Bind(value);
   3765     Goto(&return_result);
   3766   }
   3767 
   3768   Bind(&return_result);
   3769   return var_result.value();
   3770 }
   3771 
   3772 Node* CodeStubAssembler::StringToNumber(Node* context, Node* input) {
   3773   Label runtime(this, Label::kDeferred);
   3774   Label end(this);
   3775 
   3776   Variable var_result(this, MachineRepresentation::kTagged);
   3777 
   3778   // Check if string has a cached array index.
   3779   Node* hash = LoadNameHashField(input);
   3780   Node* bit =
   3781       Word32And(hash, Int32Constant(String::kContainsCachedArrayIndexMask));
   3782   GotoIf(Word32NotEqual(bit, Int32Constant(0)), &runtime);
   3783 
   3784   var_result.Bind(
   3785       SmiTag(DecodeWordFromWord32<String::ArrayIndexValueBits>(hash)));
   3786   Goto(&end);
   3787 
   3788   Bind(&runtime);
   3789   {
   3790     var_result.Bind(CallRuntime(Runtime::kStringToNumber, context, input));
   3791     Goto(&end);
   3792   }
   3793 
   3794   Bind(&end);
   3795   return var_result.value();
   3796 }
   3797 
   3798 Node* CodeStubAssembler::NumberToString(Node* context, Node* argument) {
   3799   Variable result(this, MachineRepresentation::kTagged);
   3800   Label runtime(this, Label::kDeferred);
   3801   Label smi(this);
   3802   Label done(this, &result);
   3803 
   3804   // Load the number string cache.
   3805   Node* number_string_cache = LoadRoot(Heap::kNumberStringCacheRootIndex);
   3806 
   3807   // Make the hash mask from the length of the number string cache. It
   3808   // contains two elements (number and string) for each cache entry.
   3809   // TODO(ishell): cleanup mask handling.
   3810   Node* mask =
   3811       BitcastTaggedToWord(LoadFixedArrayBaseLength(number_string_cache));
   3812   Node* one = IntPtrConstant(1);
   3813   mask = IntPtrSub(mask, one);
   3814 
   3815   GotoIf(TaggedIsSmi(argument), &smi);
   3816 
   3817   // Argument isn't smi, check to see if it's a heap-number.
   3818   Node* map = LoadMap(argument);
   3819   GotoIfNot(IsHeapNumberMap(map), &runtime);
   3820 
   3821   // Make a hash from the two 32-bit values of the double.
   3822   Node* low =
   3823       LoadObjectField(argument, HeapNumber::kValueOffset, MachineType::Int32());
   3824   Node* high = LoadObjectField(argument, HeapNumber::kValueOffset + kIntSize,
   3825                                MachineType::Int32());
   3826   Node* hash = Word32Xor(low, high);
   3827   hash = ChangeInt32ToIntPtr(hash);
   3828   hash = WordShl(hash, one);
   3829   Node* index = WordAnd(hash, SmiUntag(BitcastWordToTagged(mask)));
   3830 
   3831   // Cache entry's key must be a heap number
   3832   Node* number_key = LoadFixedArrayElement(number_string_cache, index);
   3833   GotoIf(TaggedIsSmi(number_key), &runtime);
   3834   map = LoadMap(number_key);
   3835   GotoIfNot(IsHeapNumberMap(map), &runtime);
   3836 
   3837   // Cache entry's key must match the heap number value we're looking for.
   3838   Node* low_compare = LoadObjectField(number_key, HeapNumber::kValueOffset,
   3839                                       MachineType::Int32());
   3840   Node* high_compare = LoadObjectField(
   3841       number_key, HeapNumber::kValueOffset + kIntSize, MachineType::Int32());
   3842   GotoIfNot(Word32Equal(low, low_compare), &runtime);
   3843   GotoIfNot(Word32Equal(high, high_compare), &runtime);
   3844 
   3845   // Heap number match, return value from cache entry.
   3846   IncrementCounter(isolate()->counters()->number_to_string_native(), 1);
   3847   result.Bind(LoadFixedArrayElement(number_string_cache, index, kPointerSize));
   3848   Goto(&done);
   3849 
   3850   Bind(&runtime);
   3851   {
   3852     // No cache entry, go to the runtime.
   3853     result.Bind(CallRuntime(Runtime::kNumberToString, context, argument));
   3854   }
   3855   Goto(&done);
   3856 
   3857   Bind(&smi);
   3858   {
   3859     // Load the smi key, make sure it matches the smi we're looking for.
   3860     Node* smi_index = BitcastWordToTagged(
   3861         WordAnd(WordShl(BitcastTaggedToWord(argument), one), mask));
   3862     Node* smi_key = LoadFixedArrayElement(number_string_cache, smi_index, 0,
   3863                                           SMI_PARAMETERS);
   3864     GotoIf(WordNotEqual(smi_key, argument), &runtime);
   3865 
   3866     // Smi match, return value from cache entry.
   3867     IncrementCounter(isolate()->counters()->number_to_string_native(), 1);
   3868     result.Bind(LoadFixedArrayElement(number_string_cache, smi_index,
   3869                                       kPointerSize, SMI_PARAMETERS));
   3870     Goto(&done);
   3871   }
   3872 
   3873   Bind(&done);
   3874   return result.value();
   3875 }
   3876 
   3877 Node* CodeStubAssembler::ToName(Node* context, Node* value) {
   3878   Label end(this);
   3879   Variable var_result(this, MachineRepresentation::kTagged);
   3880 
   3881   Label is_number(this);
   3882   GotoIf(TaggedIsSmi(value), &is_number);
   3883 
   3884   Label not_name(this);
   3885   Node* value_instance_type = LoadInstanceType(value);
   3886   STATIC_ASSERT(FIRST_NAME_TYPE == FIRST_TYPE);
   3887   GotoIf(Int32GreaterThan(value_instance_type, Int32Constant(LAST_NAME_TYPE)),
   3888          &not_name);
   3889 
   3890   var_result.Bind(value);
   3891   Goto(&end);
   3892 
   3893   Bind(&is_number);
   3894   {
   3895     Callable callable = CodeFactory::NumberToString(isolate());
   3896     var_result.Bind(CallStub(callable, context, value));
   3897     Goto(&end);
   3898   }
   3899 
   3900   Bind(&not_name);
   3901   {
   3902     GotoIf(Word32Equal(value_instance_type, Int32Constant(HEAP_NUMBER_TYPE)),
   3903            &is_number);
   3904 
   3905     Label not_oddball(this);
   3906     GotoIf(Word32NotEqual(value_instance_type, Int32Constant(ODDBALL_TYPE)),
   3907            &not_oddball);
   3908 
   3909     var_result.Bind(LoadObjectField(value, Oddball::kToStringOffset));
   3910     Goto(&end);
   3911 
   3912     Bind(&not_oddball);
   3913     {
   3914       var_result.Bind(CallRuntime(Runtime::kToName, context, value));
   3915       Goto(&end);
   3916     }
   3917   }
   3918 
   3919   Bind(&end);
   3920   return var_result.value();
   3921 }
   3922 
   3923 Node* CodeStubAssembler::NonNumberToNumber(Node* context, Node* input) {
   3924   // Assert input is a HeapObject (not smi or heap number)
   3925   CSA_ASSERT(this, Word32BinaryNot(TaggedIsSmi(input)));
   3926   CSA_ASSERT(this, Word32BinaryNot(IsHeapNumberMap(LoadMap(input))));
   3927 
   3928   // We might need to loop once here due to ToPrimitive conversions.
   3929   Variable var_input(this, MachineRepresentation::kTagged, input);
   3930   Variable var_result(this, MachineRepresentation::kTagged);
   3931   Label loop(this, &var_input);
   3932   Label end(this);
   3933   Goto(&loop);
   3934   Bind(&loop);
   3935   {
   3936     // Load the current {input} value (known to be a HeapObject).
   3937     Node* input = var_input.value();
   3938 
   3939     // Dispatch on the {input} instance type.
   3940     Node* input_instance_type = LoadInstanceType(input);
   3941     Label if_inputisstring(this), if_inputisoddball(this),
   3942         if_inputisreceiver(this, Label::kDeferred),
   3943         if_inputisother(this, Label::kDeferred);
   3944     GotoIf(IsStringInstanceType(input_instance_type), &if_inputisstring);
   3945     GotoIf(Word32Equal(input_instance_type, Int32Constant(ODDBALL_TYPE)),
   3946            &if_inputisoddball);
   3947     Branch(IsJSReceiverInstanceType(input_instance_type), &if_inputisreceiver,
   3948            &if_inputisother);
   3949 
   3950     Bind(&if_inputisstring);
   3951     {
   3952       // The {input} is a String, use the fast stub to convert it to a Number.
   3953       var_result.Bind(StringToNumber(context, input));
   3954       Goto(&end);
   3955     }
   3956 
   3957     Bind(&if_inputisoddball);
   3958     {
   3959       // The {input} is an Oddball, we just need to load the Number value of it.
   3960       var_result.Bind(LoadObjectField(input, Oddball::kToNumberOffset));
   3961       Goto(&end);
   3962     }
   3963 
   3964     Bind(&if_inputisreceiver);
   3965     {
   3966       // The {input} is a JSReceiver, we need to convert it to a Primitive first
   3967       // using the ToPrimitive type conversion, preferably yielding a Number.
   3968       Callable callable = CodeFactory::NonPrimitiveToPrimitive(
   3969           isolate(), ToPrimitiveHint::kNumber);
   3970       Node* result = CallStub(callable, context, input);
   3971 
   3972       // Check if the {result} is already a Number.
   3973       Label if_resultisnumber(this), if_resultisnotnumber(this);
   3974       GotoIf(TaggedIsSmi(result), &if_resultisnumber);
   3975       Node* result_map = LoadMap(result);
   3976       Branch(IsHeapNumberMap(result_map), &if_resultisnumber,
   3977              &if_resultisnotnumber);
   3978 
   3979       Bind(&if_resultisnumber);
   3980       {
   3981         // The ToPrimitive conversion already gave us a Number, so we're done.
   3982         var_result.Bind(result);
   3983         Goto(&end);
   3984       }
   3985 
   3986       Bind(&if_resultisnotnumber);
   3987       {
   3988         // We now have a Primitive {result}, but it's not yet a Number.
   3989         var_input.Bind(result);
   3990         Goto(&loop);
   3991       }
   3992     }
   3993 
   3994     Bind(&if_inputisother);
   3995     {
   3996       // The {input} is something else (e.g. Symbol), let the runtime figure
   3997       // out the correct exception.
   3998       // Note: We cannot tail call to the runtime here, as js-to-wasm
   3999       // trampolines also use this code currently, and they declare all
   4000       // outgoing parameters as untagged, while we would push a tagged
   4001       // object here.
   4002       var_result.Bind(CallRuntime(Runtime::kToNumber, context, input));
   4003       Goto(&end);
   4004     }
   4005   }
   4006 
   4007   Bind(&end);
   4008   return var_result.value();
   4009 }
   4010 
   4011 Node* CodeStubAssembler::ToNumber(Node* context, Node* input) {
   4012   Variable var_result(this, MachineRepresentation::kTagged);
   4013   Label end(this);
   4014 
   4015   Label not_smi(this, Label::kDeferred);
   4016   GotoIfNot(TaggedIsSmi(input), &not_smi);
   4017   var_result.Bind(input);
   4018   Goto(&end);
   4019 
   4020   Bind(&not_smi);
   4021   {
   4022     Label not_heap_number(this, Label::kDeferred);
   4023     Node* input_map = LoadMap(input);
   4024     GotoIfNot(IsHeapNumberMap(input_map), &not_heap_number);
   4025 
   4026     var_result.Bind(input);
   4027     Goto(&end);
   4028 
   4029     Bind(&not_heap_number);
   4030     {
   4031       var_result.Bind(NonNumberToNumber(context, input));
   4032       Goto(&end);
   4033     }
   4034   }
   4035 
   4036   Bind(&end);
   4037   return var_result.value();
   4038 }
   4039 
   4040 Node* CodeStubAssembler::ToUint32(Node* context, Node* input) {
   4041   Node* const float_zero = Float64Constant(0.0);
   4042   Node* const float_two_32 = Float64Constant(static_cast<double>(1ULL << 32));
   4043 
   4044   Label out(this);
   4045 
   4046   Variable var_result(this, MachineRepresentation::kTagged, input);
   4047 
   4048   // Early exit for positive smis.
   4049   {
   4050     // TODO(jgruber): This branch and the recheck below can be removed once we
   4051     // have a ToNumber with multiple exits.
   4052     Label next(this, Label::kDeferred);
   4053     Branch(TaggedIsPositiveSmi(input), &out, &next);
   4054     Bind(&next);
   4055   }
   4056 
   4057   Node* const number = ToNumber(context, input);
   4058   var_result.Bind(number);
   4059 
   4060   // Perhaps we have a positive smi now.
   4061   {
   4062     Label next(this, Label::kDeferred);
   4063     Branch(TaggedIsPositiveSmi(number), &out, &next);
   4064     Bind(&next);
   4065   }
   4066 
   4067   Label if_isnegativesmi(this), if_isheapnumber(this);
   4068   Branch(TaggedIsSmi(number), &if_isnegativesmi, &if_isheapnumber);
   4069 
   4070   Bind(&if_isnegativesmi);
   4071   {
   4072     // floor({input}) mod 2^32 === {input} + 2^32.
   4073     Node* const float_number = SmiToFloat64(number);
   4074     Node* const float_result = Float64Add(float_number, float_two_32);
   4075     Node* const result = ChangeFloat64ToTagged(float_result);
   4076     var_result.Bind(result);
   4077     Goto(&out);
   4078   }
   4079 
   4080   Bind(&if_isheapnumber);
   4081   {
   4082     Label return_zero(this);
   4083     Node* const value = LoadHeapNumberValue(number);
   4084 
   4085     {
   4086       // +-0.
   4087       Label next(this);
   4088       Branch(Float64Equal(value, float_zero), &return_zero, &next);
   4089       Bind(&next);
   4090     }
   4091 
   4092     {
   4093       // NaN.
   4094       Label next(this);
   4095       Branch(Float64Equal(value, value), &next, &return_zero);
   4096       Bind(&next);
   4097     }
   4098 
   4099     {
   4100       // +Infinity.
   4101       Label next(this);
   4102       Node* const positive_infinity =
   4103           Float64Constant(std::numeric_limits<double>::infinity());
   4104       Branch(Float64Equal(value, positive_infinity), &return_zero, &next);
   4105       Bind(&next);
   4106     }
   4107 
   4108     {
   4109       // -Infinity.
   4110       Label next(this);
   4111       Node* const negative_infinity =
   4112           Float64Constant(-1.0 * std::numeric_limits<double>::infinity());
   4113       Branch(Float64Equal(value, negative_infinity), &return_zero, &next);
   4114       Bind(&next);
   4115     }
   4116 
   4117     // Return floor({input}) mod 2^32 (assuming mod semantics that always return
   4118     // positive results).
   4119     {
   4120       Node* x = Float64Floor(value);
   4121       x = Float64Mod(x, float_two_32);
   4122       x = Float64Add(x, float_two_32);
   4123       x = Float64Mod(x, float_two_32);
   4124 
   4125       Node* const result = ChangeFloat64ToTagged(x);
   4126       var_result.Bind(result);
   4127       Goto(&out);
   4128     }
   4129 
   4130     Bind(&return_zero);
   4131     {
   4132       var_result.Bind(SmiConstant(Smi::kZero));
   4133       Goto(&out);
   4134     }
   4135   }
   4136 
   4137   Bind(&out);
   4138   return var_result.value();
   4139 }
   4140 
   4141 Node* CodeStubAssembler::ToString(Node* context, Node* input) {
   4142   Label is_number(this);
   4143   Label runtime(this, Label::kDeferred);
   4144   Variable result(this, MachineRepresentation::kTagged);
   4145   Label done(this, &result);
   4146 
   4147   GotoIf(TaggedIsSmi(input), &is_number);
   4148 
   4149   Node* input_map = LoadMap(input);
   4150   Node* input_instance_type = LoadMapInstanceType(input_map);
   4151 
   4152   result.Bind(input);
   4153   GotoIf(IsStringInstanceType(input_instance_type), &done);
   4154 
   4155   Label not_heap_number(this);
   4156   Branch(IsHeapNumberMap(input_map), &is_number, &not_heap_number);
   4157 
   4158   Bind(&is_number);
   4159   result.Bind(NumberToString(context, input));
   4160   Goto(&done);
   4161 
   4162   Bind(&not_heap_number);
   4163   {
   4164     GotoIf(Word32NotEqual(input_instance_type, Int32Constant(ODDBALL_TYPE)),
   4165            &runtime);
   4166     result.Bind(LoadObjectField(input, Oddball::kToStringOffset));
   4167     Goto(&done);
   4168   }
   4169 
   4170   Bind(&runtime);
   4171   {
   4172     result.Bind(CallRuntime(Runtime::kToString, context, input));
   4173     Goto(&done);
   4174   }
   4175 
   4176   Bind(&done);
   4177   return result.value();
   4178 }
   4179 
   4180 Node* CodeStubAssembler::JSReceiverToPrimitive(Node* context, Node* input) {
   4181   Label if_isreceiver(this, Label::kDeferred), if_isnotreceiver(this);
   4182   Variable result(this, MachineRepresentation::kTagged);
   4183   Label done(this, &result);
   4184 
   4185   BranchIfJSReceiver(input, &if_isreceiver, &if_isnotreceiver);
   4186 
   4187   Bind(&if_isreceiver);
   4188   {
   4189     // Convert {input} to a primitive first passing Number hint.
   4190     Callable callable = CodeFactory::NonPrimitiveToPrimitive(isolate());
   4191     result.Bind(CallStub(callable, context, input));
   4192     Goto(&done);
   4193   }
   4194 
   4195   Bind(&if_isnotreceiver);
   4196   {
   4197     result.Bind(input);
   4198     Goto(&done);
   4199   }
   4200 
   4201   Bind(&done);
   4202   return result.value();
   4203 }
   4204 
   4205 Node* CodeStubAssembler::ToInteger(Node* context, Node* input,
   4206                                    ToIntegerTruncationMode mode) {
   4207   // We might need to loop once for ToNumber conversion.
   4208   Variable var_arg(this, MachineRepresentation::kTagged, input);
   4209   Label loop(this, &var_arg), out(this);
   4210   Goto(&loop);
   4211   Bind(&loop);
   4212   {
   4213     // Shared entry points.
   4214     Label return_zero(this, Label::kDeferred);
   4215 
   4216     // Load the current {arg} value.
   4217     Node* arg = var_arg.value();
   4218 
   4219     // Check if {arg} is a Smi.
   4220     GotoIf(TaggedIsSmi(arg), &out);
   4221 
   4222     // Check if {arg} is a HeapNumber.
   4223     Label if_argisheapnumber(this),
   4224         if_argisnotheapnumber(this, Label::kDeferred);
   4225     Branch(IsHeapNumberMap(LoadMap(arg)), &if_argisheapnumber,
   4226            &if_argisnotheapnumber);
   4227 
   4228     Bind(&if_argisheapnumber);
   4229     {
   4230       // Load the floating-point value of {arg}.
   4231       Node* arg_value = LoadHeapNumberValue(arg);
   4232 
   4233       // Check if {arg} is NaN.
   4234       GotoIfNot(Float64Equal(arg_value, arg_value), &return_zero);
   4235 
   4236       // Truncate {arg} towards zero.
   4237       Node* value = Float64Trunc(arg_value);
   4238 
   4239       if (mode == kTruncateMinusZero) {
   4240         // Truncate -0.0 to 0.
   4241         GotoIf(Float64Equal(value, Float64Constant(0.0)), &return_zero);
   4242       }
   4243 
   4244       var_arg.Bind(ChangeFloat64ToTagged(value));
   4245       Goto(&out);
   4246     }
   4247 
   4248     Bind(&if_argisnotheapnumber);
   4249     {
   4250       // Need to convert {arg} to a Number first.
   4251       Callable callable = CodeFactory::NonNumberToNumber(isolate());
   4252       var_arg.Bind(CallStub(callable, context, arg));
   4253       Goto(&loop);
   4254     }
   4255 
   4256     Bind(&return_zero);
   4257     var_arg.Bind(SmiConstant(Smi::kZero));
   4258     Goto(&out);
   4259   }
   4260 
   4261   Bind(&out);
   4262   return var_arg.value();
   4263 }
   4264 
   4265 Node* CodeStubAssembler::DecodeWord32(Node* word32, uint32_t shift,
   4266                                       uint32_t mask) {
   4267   return Word32Shr(Word32And(word32, Int32Constant(mask)),
   4268                    static_cast<int>(shift));
   4269 }
   4270 
   4271 Node* CodeStubAssembler::DecodeWord(Node* word, uint32_t shift, uint32_t mask) {
   4272   return WordShr(WordAnd(word, IntPtrConstant(mask)), static_cast<int>(shift));
   4273 }
   4274 
   4275 void CodeStubAssembler::SetCounter(StatsCounter* counter, int value) {
   4276   if (FLAG_native_code_counters && counter->Enabled()) {
   4277     Node* counter_address = ExternalConstant(ExternalReference(counter));
   4278     StoreNoWriteBarrier(MachineRepresentation::kWord32, counter_address,
   4279                         Int32Constant(value));
   4280   }
   4281 }
   4282 
   4283 void CodeStubAssembler::IncrementCounter(StatsCounter* counter, int delta) {
   4284   DCHECK(delta > 0);
   4285   if (FLAG_native_code_counters && counter->Enabled()) {
   4286     Node* counter_address = ExternalConstant(ExternalReference(counter));
   4287     Node* value = Load(MachineType::Int32(), counter_address);
   4288     value = Int32Add(value, Int32Constant(delta));
   4289     StoreNoWriteBarrier(MachineRepresentation::kWord32, counter_address, value);
   4290   }
   4291 }
   4292 
   4293 void CodeStubAssembler::DecrementCounter(StatsCounter* counter, int delta) {
   4294   DCHECK(delta > 0);
   4295   if (FLAG_native_code_counters && counter->Enabled()) {
   4296     Node* counter_address = ExternalConstant(ExternalReference(counter));
   4297     Node* value = Load(MachineType::Int32(), counter_address);
   4298     value = Int32Sub(value, Int32Constant(delta));
   4299     StoreNoWriteBarrier(MachineRepresentation::kWord32, counter_address, value);
   4300   }
   4301 }
   4302 
   4303 void CodeStubAssembler::Increment(Variable& variable, int value,
   4304                                   ParameterMode mode) {
   4305   DCHECK_IMPLIES(mode == INTPTR_PARAMETERS,
   4306                  variable.rep() == MachineType::PointerRepresentation());
   4307   DCHECK_IMPLIES(mode == SMI_PARAMETERS,
   4308                  variable.rep() == MachineRepresentation::kTagged ||
   4309                      variable.rep() == MachineRepresentation::kTaggedSigned);
   4310   variable.Bind(
   4311       IntPtrOrSmiAdd(variable.value(), IntPtrOrSmiConstant(value, mode), mode));
   4312 }
   4313 
   4314 void CodeStubAssembler::Use(Label* label) {
   4315   GotoIf(Word32Equal(Int32Constant(0), Int32Constant(1)), label);
   4316 }
   4317 
   4318 void CodeStubAssembler::TryToName(Node* key, Label* if_keyisindex,
   4319                                   Variable* var_index, Label* if_keyisunique,
   4320                                   Variable* var_unique, Label* if_bailout) {
   4321   DCHECK_EQ(MachineType::PointerRepresentation(), var_index->rep());
   4322   DCHECK_EQ(MachineRepresentation::kTagged, var_unique->rep());
   4323   Comment("TryToName");
   4324 
   4325   Label if_hascachedindex(this), if_keyisnotindex(this), if_thinstring(this);
   4326   // Handle Smi and HeapNumber keys.
   4327   var_index->Bind(TryToIntptr(key, &if_keyisnotindex));
   4328   Goto(if_keyisindex);
   4329 
   4330   Bind(&if_keyisnotindex);
   4331   Node* key_map = LoadMap(key);
   4332   var_unique->Bind(key);
   4333   // Symbols are unique.
   4334   GotoIf(IsSymbolMap(key_map), if_keyisunique);
   4335   Node* key_instance_type = LoadMapInstanceType(key_map);
   4336   // Miss if |key| is not a String.
   4337   STATIC_ASSERT(FIRST_NAME_TYPE == FIRST_TYPE);
   4338   GotoIfNot(IsStringInstanceType(key_instance_type), if_bailout);
   4339   // |key| is a String. Check if it has a cached array index.
   4340   Node* hash = LoadNameHashField(key);
   4341   Node* contains_index =
   4342       Word32And(hash, Int32Constant(Name::kContainsCachedArrayIndexMask));
   4343   GotoIf(Word32Equal(contains_index, Int32Constant(0)), &if_hascachedindex);
   4344   // No cached array index. If the string knows that it contains an index,
   4345   // then it must be an uncacheable index. Handle this case in the runtime.
   4346   Node* not_an_index =
   4347       Word32And(hash, Int32Constant(Name::kIsNotArrayIndexMask));
   4348   GotoIf(Word32Equal(not_an_index, Int32Constant(0)), if_bailout);
   4349   // Check if we have a ThinString.
   4350   GotoIf(Word32Equal(key_instance_type, Int32Constant(THIN_STRING_TYPE)),
   4351          &if_thinstring);
   4352   GotoIf(
   4353       Word32Equal(key_instance_type, Int32Constant(THIN_ONE_BYTE_STRING_TYPE)),
   4354       &if_thinstring);
   4355   // Finally, check if |key| is internalized.
   4356   STATIC_ASSERT(kNotInternalizedTag != 0);
   4357   Node* not_internalized =
   4358       Word32And(key_instance_type, Int32Constant(kIsNotInternalizedMask));
   4359   GotoIf(Word32NotEqual(not_internalized, Int32Constant(0)), if_bailout);
   4360   Goto(if_keyisunique);
   4361 
   4362   Bind(&if_thinstring);
   4363   var_unique->Bind(LoadObjectField(key, ThinString::kActualOffset));
   4364   Goto(if_keyisunique);
   4365 
   4366   Bind(&if_hascachedindex);
   4367   var_index->Bind(DecodeWordFromWord32<Name::ArrayIndexValueBits>(hash));
   4368   Goto(if_keyisindex);
   4369 }
   4370 
   4371 template <typename Dictionary>
   4372 Node* CodeStubAssembler::EntryToIndex(Node* entry, int field_index) {
   4373   Node* entry_index = IntPtrMul(entry, IntPtrConstant(Dictionary::kEntrySize));
   4374   return IntPtrAdd(entry_index, IntPtrConstant(Dictionary::kElementsStartIndex +
   4375                                                field_index));
   4376 }
   4377 
   4378 template Node* CodeStubAssembler::EntryToIndex<NameDictionary>(Node*, int);
   4379 template Node* CodeStubAssembler::EntryToIndex<GlobalDictionary>(Node*, int);
   4380 template Node* CodeStubAssembler::EntryToIndex<SeededNumberDictionary>(Node*,
   4381                                                                        int);
   4382 
   4383 Node* CodeStubAssembler::HashTableComputeCapacity(Node* at_least_space_for) {
   4384   Node* capacity = IntPtrRoundUpToPowerOfTwo32(
   4385       WordShl(at_least_space_for, IntPtrConstant(1)));
   4386   return IntPtrMax(capacity, IntPtrConstant(HashTableBase::kMinCapacity));
   4387 }
   4388 
   4389 Node* CodeStubAssembler::IntPtrMax(Node* left, Node* right) {
   4390   return SelectConstant(IntPtrGreaterThanOrEqual(left, right), left, right,
   4391                         MachineType::PointerRepresentation());
   4392 }
   4393 
   4394 Node* CodeStubAssembler::IntPtrMin(Node* left, Node* right) {
   4395   return SelectConstant(IntPtrLessThanOrEqual(left, right), left, right,
   4396                         MachineType::PointerRepresentation());
   4397 }
   4398 
   4399 template <class Dictionary>
   4400 Node* CodeStubAssembler::GetNumberOfElements(Node* dictionary) {
   4401   return LoadFixedArrayElement(dictionary, Dictionary::kNumberOfElementsIndex);
   4402 }
   4403 
   4404 template <class Dictionary>
   4405 void CodeStubAssembler::SetNumberOfElements(Node* dictionary,
   4406                                             Node* num_elements_smi) {
   4407   StoreFixedArrayElement(dictionary, Dictionary::kNumberOfElementsIndex,
   4408                          num_elements_smi, SKIP_WRITE_BARRIER);
   4409 }
   4410 
   4411 template <class Dictionary>
   4412 Node* CodeStubAssembler::GetNumberOfDeletedElements(Node* dictionary) {
   4413   return LoadFixedArrayElement(dictionary,
   4414                                Dictionary::kNumberOfDeletedElementsIndex);
   4415 }
   4416 
   4417 template <class Dictionary>
   4418 Node* CodeStubAssembler::GetCapacity(Node* dictionary) {
   4419   return LoadFixedArrayElement(dictionary, Dictionary::kCapacityIndex);
   4420 }
   4421 
   4422 template <class Dictionary>
   4423 Node* CodeStubAssembler::GetNextEnumerationIndex(Node* dictionary) {
   4424   return LoadFixedArrayElement(dictionary,
   4425                                Dictionary::kNextEnumerationIndexIndex);
   4426 }
   4427 
   4428 template <class Dictionary>
   4429 void CodeStubAssembler::SetNextEnumerationIndex(Node* dictionary,
   4430                                                 Node* next_enum_index_smi) {
   4431   StoreFixedArrayElement(dictionary, Dictionary::kNextEnumerationIndexIndex,
   4432                          next_enum_index_smi, SKIP_WRITE_BARRIER);
   4433 }
   4434 
   4435 template <typename Dictionary>
   4436 void CodeStubAssembler::NameDictionaryLookup(Node* dictionary,
   4437                                              Node* unique_name, Label* if_found,
   4438                                              Variable* var_name_index,
   4439                                              Label* if_not_found,
   4440                                              int inlined_probes,
   4441                                              LookupMode mode) {
   4442   CSA_ASSERT(this, IsDictionary(dictionary));
   4443   DCHECK_EQ(MachineType::PointerRepresentation(), var_name_index->rep());
   4444   DCHECK_IMPLIES(mode == kFindInsertionIndex,
   4445                  inlined_probes == 0 && if_found == nullptr);
   4446   Comment("NameDictionaryLookup");
   4447 
   4448   Node* capacity = SmiUntag(GetCapacity<Dictionary>(dictionary));
   4449   Node* mask = IntPtrSub(capacity, IntPtrConstant(1));
   4450   Node* hash = ChangeUint32ToWord(LoadNameHash(unique_name));
   4451 
   4452   // See Dictionary::FirstProbe().
   4453   Node* count = IntPtrConstant(0);
   4454   Node* entry = WordAnd(hash, mask);
   4455 
   4456   for (int i = 0; i < inlined_probes; i++) {
   4457     Node* index = EntryToIndex<Dictionary>(entry);
   4458     var_name_index->Bind(index);
   4459 
   4460     Node* current = LoadFixedArrayElement(dictionary, index);
   4461     GotoIf(WordEqual(current, unique_name), if_found);
   4462 
   4463     // See Dictionary::NextProbe().
   4464     count = IntPtrConstant(i + 1);
   4465     entry = WordAnd(IntPtrAdd(entry, count), mask);
   4466   }
   4467   if (mode == kFindInsertionIndex) {
   4468     // Appease the variable merging algorithm for "Goto(&loop)" below.
   4469     var_name_index->Bind(IntPtrConstant(0));
   4470   }
   4471 
   4472   Node* undefined = UndefinedConstant();
   4473   Node* the_hole = mode == kFindExisting ? nullptr : TheHoleConstant();
   4474 
   4475   Variable var_count(this, MachineType::PointerRepresentation(), count);
   4476   Variable var_entry(this, MachineType::PointerRepresentation(), entry);
   4477   Variable* loop_vars[] = {&var_count, &var_entry, var_name_index};
   4478   Label loop(this, 3, loop_vars);
   4479   Goto(&loop);
   4480   Bind(&loop);
   4481   {
   4482     Node* entry = var_entry.value();
   4483 
   4484     Node* index = EntryToIndex<Dictionary>(entry);
   4485     var_name_index->Bind(index);
   4486 
   4487     Node* current = LoadFixedArrayElement(dictionary, index);
   4488     GotoIf(WordEqual(current, undefined), if_not_found);
   4489     if (mode == kFindExisting) {
   4490       GotoIf(WordEqual(current, unique_name), if_found);
   4491     } else {
   4492       DCHECK_EQ(kFindInsertionIndex, mode);
   4493       GotoIf(WordEqual(current, the_hole), if_not_found);
   4494     }
   4495 
   4496     // See Dictionary::NextProbe().
   4497     Increment(var_count);
   4498     entry = WordAnd(IntPtrAdd(entry, var_count.value()), mask);
   4499 
   4500     var_entry.Bind(entry);
   4501     Goto(&loop);
   4502   }
   4503 }
   4504 
   4505 // Instantiate template methods to workaround GCC compilation issue.
   4506 template void CodeStubAssembler::NameDictionaryLookup<NameDictionary>(
   4507     Node*, Node*, Label*, Variable*, Label*, int, LookupMode);
   4508 template void CodeStubAssembler::NameDictionaryLookup<GlobalDictionary>(
   4509     Node*, Node*, Label*, Variable*, Label*, int, LookupMode);
   4510 
   4511 Node* CodeStubAssembler::ComputeIntegerHash(Node* key, Node* seed) {
   4512   // See v8::internal::ComputeIntegerHash()
   4513   Node* hash = TruncateWordToWord32(key);
   4514   hash = Word32Xor(hash, seed);
   4515   hash = Int32Add(Word32Xor(hash, Int32Constant(0xffffffff)),
   4516                   Word32Shl(hash, Int32Constant(15)));
   4517   hash = Word32Xor(hash, Word32Shr(hash, Int32Constant(12)));
   4518   hash = Int32Add(hash, Word32Shl(hash, Int32Constant(2)));
   4519   hash = Word32Xor(hash, Word32Shr(hash, Int32Constant(4)));
   4520   hash = Int32Mul(hash, Int32Constant(2057));
   4521   hash = Word32Xor(hash, Word32Shr(hash, Int32Constant(16)));
   4522   return Word32And(hash, Int32Constant(0x3fffffff));
   4523 }
   4524 
   4525 template <typename Dictionary>
   4526 void CodeStubAssembler::NumberDictionaryLookup(Node* dictionary,
   4527                                                Node* intptr_index,
   4528                                                Label* if_found,
   4529                                                Variable* var_entry,
   4530                                                Label* if_not_found) {
   4531   CSA_ASSERT(this, IsDictionary(dictionary));
   4532   DCHECK_EQ(MachineType::PointerRepresentation(), var_entry->rep());
   4533   Comment("NumberDictionaryLookup");
   4534 
   4535   Node* capacity = SmiUntag(GetCapacity<Dictionary>(dictionary));
   4536   Node* mask = IntPtrSub(capacity, IntPtrConstant(1));
   4537 
   4538   Node* int32_seed;
   4539   if (Dictionary::ShapeT::UsesSeed) {
   4540     int32_seed = HashSeed();
   4541   } else {
   4542     int32_seed = Int32Constant(kZeroHashSeed);
   4543   }
   4544   Node* hash = ChangeUint32ToWord(ComputeIntegerHash(intptr_index, int32_seed));
   4545   Node* key_as_float64 = RoundIntPtrToFloat64(intptr_index);
   4546 
   4547   // See Dictionary::FirstProbe().
   4548   Node* count = IntPtrConstant(0);
   4549   Node* entry = WordAnd(hash, mask);
   4550 
   4551   Node* undefined = UndefinedConstant();
   4552   Node* the_hole = TheHoleConstant();
   4553 
   4554   Variable var_count(this, MachineType::PointerRepresentation(), count);
   4555   Variable* loop_vars[] = {&var_count, var_entry};
   4556   Label loop(this, 2, loop_vars);
   4557   var_entry->Bind(entry);
   4558   Goto(&loop);
   4559   Bind(&loop);
   4560   {
   4561     Node* entry = var_entry->value();
   4562 
   4563     Node* index = EntryToIndex<Dictionary>(entry);
   4564     Node* current = LoadFixedArrayElement(dictionary, index);
   4565     GotoIf(WordEqual(current, undefined), if_not_found);
   4566     Label next_probe(this);
   4567     {
   4568       Label if_currentissmi(this), if_currentisnotsmi(this);
   4569       Branch(TaggedIsSmi(current), &if_currentissmi, &if_currentisnotsmi);
   4570       Bind(&if_currentissmi);
   4571       {
   4572         Node* current_value = SmiUntag(current);
   4573         Branch(WordEqual(current_value, intptr_index), if_found, &next_probe);
   4574       }
   4575       Bind(&if_currentisnotsmi);
   4576       {
   4577         GotoIf(WordEqual(current, the_hole), &next_probe);
   4578         // Current must be the Number.
   4579         Node* current_value = LoadHeapNumberValue(current);
   4580         Branch(Float64Equal(current_value, key_as_float64), if_found,
   4581                &next_probe);
   4582       }
   4583     }
   4584 
   4585     Bind(&next_probe);
   4586     // See Dictionary::NextProbe().
   4587     Increment(var_count);
   4588     entry = WordAnd(IntPtrAdd(entry, var_count.value()), mask);
   4589 
   4590     var_entry->Bind(entry);
   4591     Goto(&loop);
   4592   }
   4593 }
   4594 
   4595 template <class Dictionary>
   4596 void CodeStubAssembler::FindInsertionEntry(Node* dictionary, Node* key,
   4597                                            Variable* var_key_index) {
   4598   UNREACHABLE();
   4599 }
   4600 
   4601 template <>
   4602 void CodeStubAssembler::FindInsertionEntry<NameDictionary>(
   4603     Node* dictionary, Node* key, Variable* var_key_index) {
   4604   Label done(this);
   4605   NameDictionaryLookup<NameDictionary>(dictionary, key, nullptr, var_key_index,
   4606                                        &done, 0, kFindInsertionIndex);
   4607   Bind(&done);
   4608 }
   4609 
   4610 template <class Dictionary>
   4611 void CodeStubAssembler::InsertEntry(Node* dictionary, Node* key, Node* value,
   4612                                     Node* index, Node* enum_index) {
   4613   UNREACHABLE();  // Use specializations instead.
   4614 }
   4615 
   4616 template <>
   4617 void CodeStubAssembler::InsertEntry<NameDictionary>(Node* dictionary,
   4618                                                     Node* name, Node* value,
   4619                                                     Node* index,
   4620                                                     Node* enum_index) {
   4621   // Store name and value.
   4622   StoreFixedArrayElement(dictionary, index, name);
   4623   StoreValueByKeyIndex<NameDictionary>(dictionary, index, value);
   4624 
   4625   // Prepare details of the new property.
   4626   const int kInitialIndex = 0;
   4627   PropertyDetails d(kData, NONE, kInitialIndex, PropertyCellType::kNoCell);
   4628   enum_index =
   4629       SmiShl(enum_index, PropertyDetails::DictionaryStorageField::kShift);
   4630   STATIC_ASSERT(kInitialIndex == 0);
   4631   Variable var_details(this, MachineRepresentation::kTaggedSigned,
   4632                        SmiOr(SmiConstant(d.AsSmi()), enum_index));
   4633 
   4634   // Private names must be marked non-enumerable.
   4635   Label not_private(this, &var_details);
   4636   GotoIfNot(IsSymbolMap(LoadMap(name)), &not_private);
   4637   Node* flags = SmiToWord32(LoadObjectField(name, Symbol::kFlagsOffset));
   4638   const int kPrivateMask = 1 << Symbol::kPrivateBit;
   4639   GotoIfNot(IsSetWord32(flags, kPrivateMask), &not_private);
   4640   Node* dont_enum =
   4641       SmiShl(SmiConstant(DONT_ENUM), PropertyDetails::AttributesField::kShift);
   4642   var_details.Bind(SmiOr(var_details.value(), dont_enum));
   4643   Goto(&not_private);
   4644   Bind(&not_private);
   4645 
   4646   // Finally, store the details.
   4647   StoreDetailsByKeyIndex<NameDictionary>(dictionary, index,
   4648                                          var_details.value());
   4649 }
   4650 
   4651 template <>
   4652 void CodeStubAssembler::InsertEntry<GlobalDictionary>(Node* dictionary,
   4653                                                       Node* key, Node* value,
   4654                                                       Node* index,
   4655                                                       Node* enum_index) {
   4656   UNIMPLEMENTED();
   4657 }
   4658 
   4659 template <class Dictionary>
   4660 void CodeStubAssembler::Add(Node* dictionary, Node* key, Node* value,
   4661                             Label* bailout) {
   4662   Node* capacity = GetCapacity<Dictionary>(dictionary);
   4663   Node* nof = GetNumberOfElements<Dictionary>(dictionary);
   4664   Node* new_nof = SmiAdd(nof, SmiConstant(1));
   4665   // Require 33% to still be free after adding additional_elements.
   4666   // Computing "x + (x >> 1)" on a Smi x does not return a valid Smi!
   4667   // But that's OK here because it's only used for a comparison.
   4668   Node* required_capacity_pseudo_smi = SmiAdd(new_nof, SmiShr(new_nof, 1));
   4669   GotoIf(SmiBelow(capacity, required_capacity_pseudo_smi), bailout);
   4670   // Require rehashing if more than 50% of free elements are deleted elements.
   4671   Node* deleted = GetNumberOfDeletedElements<Dictionary>(dictionary);
   4672   CSA_ASSERT(this, SmiAbove(capacity, new_nof));
   4673   Node* half_of_free_elements = SmiShr(SmiSub(capacity, new_nof), 1);
   4674   GotoIf(SmiAbove(deleted, half_of_free_elements), bailout);
   4675   Node* enum_index = nullptr;
   4676   if (Dictionary::kIsEnumerable) {
   4677     enum_index = GetNextEnumerationIndex<Dictionary>(dictionary);
   4678     Node* new_enum_index = SmiAdd(enum_index, SmiConstant(1));
   4679     Node* max_enum_index =
   4680         SmiConstant(PropertyDetails::DictionaryStorageField::kMax);
   4681     GotoIf(SmiAbove(new_enum_index, max_enum_index), bailout);
   4682 
   4683     // No more bailouts after this point.
   4684     // Operations from here on can have side effects.
   4685 
   4686     SetNextEnumerationIndex<Dictionary>(dictionary, new_enum_index);
   4687   } else {
   4688     USE(enum_index);
   4689   }
   4690   SetNumberOfElements<Dictionary>(dictionary, new_nof);
   4691 
   4692   Variable var_key_index(this, MachineType::PointerRepresentation());
   4693   FindInsertionEntry<Dictionary>(dictionary, key, &var_key_index);
   4694   InsertEntry<Dictionary>(dictionary, key, value, var_key_index.value(),
   4695                           enum_index);
   4696 }
   4697 
   4698 template void CodeStubAssembler::Add<NameDictionary>(Node*, Node*, Node*,
   4699                                                      Label*);
   4700 
   4701 void CodeStubAssembler::DescriptorLookupLinear(Node* unique_name,
   4702                                                Node* descriptors, Node* nof,
   4703                                                Label* if_found,
   4704                                                Variable* var_name_index,
   4705                                                Label* if_not_found) {
   4706   Comment("DescriptorLookupLinear");
   4707   Node* first_inclusive = IntPtrConstant(DescriptorArray::ToKeyIndex(0));
   4708   Node* factor = IntPtrConstant(DescriptorArray::kEntrySize);
   4709   Node* last_exclusive = IntPtrAdd(first_inclusive, IntPtrMul(nof, factor));
   4710 
   4711   BuildFastLoop(last_exclusive, first_inclusive,
   4712                 [this, descriptors, unique_name, if_found,
   4713                  var_name_index](Node* name_index) {
   4714                   Node* candidate_name =
   4715                       LoadFixedArrayElement(descriptors, name_index);
   4716                   var_name_index->Bind(name_index);
   4717                   GotoIf(WordEqual(candidate_name, unique_name), if_found);
   4718                 },
   4719                 -DescriptorArray::kEntrySize, INTPTR_PARAMETERS,
   4720                 IndexAdvanceMode::kPre);
   4721   Goto(if_not_found);
   4722 }
   4723 
   4724 Node* CodeStubAssembler::DescriptorArrayNumberOfEntries(Node* descriptors) {
   4725   return LoadAndUntagToWord32FixedArrayElement(
   4726       descriptors, IntPtrConstant(DescriptorArray::kDescriptorLengthIndex));
   4727 }
   4728 
   4729 namespace {
   4730 
   4731 Node* DescriptorNumberToIndex(CodeStubAssembler* a, Node* descriptor_number) {
   4732   Node* descriptor_size = a->Int32Constant(DescriptorArray::kEntrySize);
   4733   Node* index = a->Int32Mul(descriptor_number, descriptor_size);
   4734   return a->ChangeInt32ToIntPtr(index);
   4735 }
   4736 
   4737 }  // namespace
   4738 
   4739 Node* CodeStubAssembler::DescriptorArrayToKeyIndex(Node* descriptor_number) {
   4740   return IntPtrAdd(IntPtrConstant(DescriptorArray::ToKeyIndex(0)),
   4741                    DescriptorNumberToIndex(this, descriptor_number));
   4742 }
   4743 
   4744 Node* CodeStubAssembler::DescriptorArrayGetSortedKeyIndex(
   4745     Node* descriptors, Node* descriptor_number) {
   4746   const int details_offset = DescriptorArray::ToDetailsIndex(0) * kPointerSize;
   4747   Node* details = LoadAndUntagToWord32FixedArrayElement(
   4748       descriptors, DescriptorNumberToIndex(this, descriptor_number),
   4749       details_offset);
   4750   return DecodeWord32<PropertyDetails::DescriptorPointer>(details);
   4751 }
   4752 
   4753 Node* CodeStubAssembler::DescriptorArrayGetKey(Node* descriptors,
   4754                                                Node* descriptor_number) {
   4755   const int key_offset = DescriptorArray::ToKeyIndex(0) * kPointerSize;
   4756   return LoadFixedArrayElement(descriptors,
   4757                                DescriptorNumberToIndex(this, descriptor_number),
   4758                                key_offset);
   4759 }
   4760 
   4761 void CodeStubAssembler::DescriptorLookupBinary(Node* unique_name,
   4762                                                Node* descriptors, Node* nof,
   4763                                                Label* if_found,
   4764                                                Variable* var_name_index,
   4765                                                Label* if_not_found) {
   4766   Comment("DescriptorLookupBinary");
   4767   Variable var_low(this, MachineRepresentation::kWord32, Int32Constant(0));
   4768   Node* limit =
   4769       Int32Sub(DescriptorArrayNumberOfEntries(descriptors), Int32Constant(1));
   4770   Variable var_high(this, MachineRepresentation::kWord32, limit);
   4771   Node* hash = LoadNameHashField(unique_name);
   4772   CSA_ASSERT(this, Word32NotEqual(hash, Int32Constant(0)));
   4773 
   4774   // Assume non-empty array.
   4775   CSA_ASSERT(this, Uint32LessThanOrEqual(var_low.value(), var_high.value()));
   4776 
   4777   Variable* loop_vars[] = {&var_high, &var_low};
   4778   Label binary_loop(this, 2, loop_vars);
   4779   Goto(&binary_loop);
   4780   Bind(&binary_loop);
   4781   {
   4782     // mid = low + (high - low) / 2 (to avoid overflow in "(low + high) / 2").
   4783     Node* mid =
   4784         Int32Add(var_low.value(),
   4785                  Word32Shr(Int32Sub(var_high.value(), var_low.value()), 1));
   4786     // mid_name = descriptors->GetSortedKey(mid).
   4787     Node* sorted_key_index = DescriptorArrayGetSortedKeyIndex(descriptors, mid);
   4788     Node* mid_name = DescriptorArrayGetKey(descriptors, sorted_key_index);
   4789 
   4790     Node* mid_hash = LoadNameHashField(mid_name);
   4791 
   4792     Label mid_greater(this), mid_less(this), merge(this);
   4793     Branch(Uint32GreaterThanOrEqual(mid_hash, hash), &mid_greater, &mid_less);
   4794     Bind(&mid_greater);
   4795     {
   4796       var_high.Bind(mid);
   4797       Goto(&merge);
   4798     }
   4799     Bind(&mid_less);
   4800     {
   4801       var_low.Bind(Int32Add(mid, Int32Constant(1)));
   4802       Goto(&merge);
   4803     }
   4804     Bind(&merge);
   4805     GotoIf(Word32NotEqual(var_low.value(), var_high.value()), &binary_loop);
   4806   }
   4807 
   4808   Label scan_loop(this, &var_low);
   4809   Goto(&scan_loop);
   4810   Bind(&scan_loop);
   4811   {
   4812     GotoIf(Int32GreaterThan(var_low.value(), limit), if_not_found);
   4813 
   4814     Node* sort_index =
   4815         DescriptorArrayGetSortedKeyIndex(descriptors, var_low.value());
   4816     Node* current_name = DescriptorArrayGetKey(descriptors, sort_index);
   4817     Node* current_hash = LoadNameHashField(current_name);
   4818     GotoIf(Word32NotEqual(current_hash, hash), if_not_found);
   4819     Label next(this);
   4820     GotoIf(WordNotEqual(current_name, unique_name), &next);
   4821     GotoIf(Int32GreaterThanOrEqual(sort_index, nof), if_not_found);
   4822     var_name_index->Bind(DescriptorArrayToKeyIndex(sort_index));
   4823     Goto(if_found);
   4824 
   4825     Bind(&next);
   4826     var_low.Bind(Int32Add(var_low.value(), Int32Constant(1)));
   4827     Goto(&scan_loop);
   4828   }
   4829 }
   4830 
   4831 void CodeStubAssembler::DescriptorLookup(Node* unique_name, Node* descriptors,
   4832                                          Node* bitfield3, Label* if_found,
   4833                                          Variable* var_name_index,
   4834                                          Label* if_not_found) {
   4835   Comment("DescriptorArrayLookup");
   4836   Node* nof = DecodeWord32<Map::NumberOfOwnDescriptorsBits>(bitfield3);
   4837   GotoIf(Word32Equal(nof, Int32Constant(0)), if_not_found);
   4838   Label linear_search(this), binary_search(this);
   4839   const int kMaxElementsForLinearSearch = 32;
   4840   Branch(Int32LessThanOrEqual(nof, Int32Constant(kMaxElementsForLinearSearch)),
   4841          &linear_search, &binary_search);
   4842   Bind(&linear_search);
   4843   {
   4844     DescriptorLookupLinear(unique_name, descriptors, ChangeInt32ToIntPtr(nof),
   4845                            if_found, var_name_index, if_not_found);
   4846   }
   4847   Bind(&binary_search);
   4848   {
   4849     DescriptorLookupBinary(unique_name, descriptors, nof, if_found,
   4850                            var_name_index, if_not_found);
   4851   }
   4852 }
   4853 
   4854 void CodeStubAssembler::TryLookupProperty(
   4855     Node* object, Node* map, Node* instance_type, Node* unique_name,
   4856     Label* if_found_fast, Label* if_found_dict, Label* if_found_global,
   4857     Variable* var_meta_storage, Variable* var_name_index, Label* if_not_found,
   4858     Label* if_bailout) {
   4859   DCHECK_EQ(MachineRepresentation::kTagged, var_meta_storage->rep());
   4860   DCHECK_EQ(MachineType::PointerRepresentation(), var_name_index->rep());
   4861 
   4862   Label if_objectisspecial(this);
   4863   STATIC_ASSERT(JS_GLOBAL_OBJECT_TYPE <= LAST_SPECIAL_RECEIVER_TYPE);
   4864   GotoIf(Int32LessThanOrEqual(instance_type,
   4865                               Int32Constant(LAST_SPECIAL_RECEIVER_TYPE)),
   4866          &if_objectisspecial);
   4867 
   4868   uint32_t mask =
   4869       1 << Map::kHasNamedInterceptor | 1 << Map::kIsAccessCheckNeeded;
   4870   CSA_ASSERT(this, Word32BinaryNot(IsSetWord32(LoadMapBitField(map), mask)));
   4871   USE(mask);
   4872 
   4873   Node* bit_field3 = LoadMapBitField3(map);
   4874   Label if_isfastmap(this), if_isslowmap(this);
   4875   Branch(IsSetWord32<Map::DictionaryMap>(bit_field3), &if_isslowmap,
   4876          &if_isfastmap);
   4877   Bind(&if_isfastmap);
   4878   {
   4879     Node* descriptors = LoadMapDescriptors(map);
   4880     var_meta_storage->Bind(descriptors);
   4881 
   4882     DescriptorLookup(unique_name, descriptors, bit_field3, if_found_fast,
   4883                      var_name_index, if_not_found);
   4884   }
   4885   Bind(&if_isslowmap);
   4886   {
   4887     Node* dictionary = LoadProperties(object);
   4888     var_meta_storage->Bind(dictionary);
   4889 
   4890     NameDictionaryLookup<NameDictionary>(dictionary, unique_name, if_found_dict,
   4891                                          var_name_index, if_not_found);
   4892   }
   4893   Bind(&if_objectisspecial);
   4894   {
   4895     // Handle global object here and other special objects in runtime.
   4896     GotoIfNot(Word32Equal(instance_type, Int32Constant(JS_GLOBAL_OBJECT_TYPE)),
   4897               if_bailout);
   4898 
   4899     // Handle interceptors and access checks in runtime.
   4900     Node* bit_field = LoadMapBitField(map);
   4901     Node* mask = Int32Constant(1 << Map::kHasNamedInterceptor |
   4902                                1 << Map::kIsAccessCheckNeeded);
   4903     GotoIf(Word32NotEqual(Word32And(bit_field, mask), Int32Constant(0)),
   4904            if_bailout);
   4905 
   4906     Node* dictionary = LoadProperties(object);
   4907     var_meta_storage->Bind(dictionary);
   4908 
   4909     NameDictionaryLookup<GlobalDictionary>(
   4910         dictionary, unique_name, if_found_global, var_name_index, if_not_found);
   4911   }
   4912 }
   4913 
   4914 void CodeStubAssembler::TryHasOwnProperty(Node* object, Node* map,
   4915                                           Node* instance_type,
   4916                                           Node* unique_name, Label* if_found,
   4917                                           Label* if_not_found,
   4918                                           Label* if_bailout) {
   4919   Comment("TryHasOwnProperty");
   4920   Variable var_meta_storage(this, MachineRepresentation::kTagged);
   4921   Variable var_name_index(this, MachineType::PointerRepresentation());
   4922 
   4923   Label if_found_global(this);
   4924   TryLookupProperty(object, map, instance_type, unique_name, if_found, if_found,
   4925                     &if_found_global, &var_meta_storage, &var_name_index,
   4926                     if_not_found, if_bailout);
   4927   Bind(&if_found_global);
   4928   {
   4929     Variable var_value(this, MachineRepresentation::kTagged);
   4930     Variable var_details(this, MachineRepresentation::kWord32);
   4931     // Check if the property cell is not deleted.
   4932     LoadPropertyFromGlobalDictionary(var_meta_storage.value(),
   4933                                      var_name_index.value(), &var_value,
   4934                                      &var_details, if_not_found);
   4935     Goto(if_found);
   4936   }
   4937 }
   4938 
   4939 void CodeStubAssembler::LoadPropertyFromFastObject(Node* object, Node* map,
   4940                                                    Node* descriptors,
   4941                                                    Node* name_index,
   4942                                                    Variable* var_details,
   4943                                                    Variable* var_value) {
   4944   DCHECK_EQ(MachineRepresentation::kWord32, var_details->rep());
   4945   DCHECK_EQ(MachineRepresentation::kTagged, var_value->rep());
   4946   Comment("[ LoadPropertyFromFastObject");
   4947 
   4948   Node* details =
   4949       LoadDetailsByKeyIndex<DescriptorArray>(descriptors, name_index);
   4950   var_details->Bind(details);
   4951 
   4952   Node* location = DecodeWord32<PropertyDetails::LocationField>(details);
   4953 
   4954   Label if_in_field(this), if_in_descriptor(this), done(this);
   4955   Branch(Word32Equal(location, Int32Constant(kField)), &if_in_field,
   4956          &if_in_descriptor);
   4957   Bind(&if_in_field);
   4958   {
   4959     Node* field_index =
   4960         DecodeWordFromWord32<PropertyDetails::FieldIndexField>(details);
   4961     Node* representation =
   4962         DecodeWord32<PropertyDetails::RepresentationField>(details);
   4963 
   4964     Node* inobject_properties = LoadMapInobjectProperties(map);
   4965 
   4966     Label if_inobject(this), if_backing_store(this);
   4967     Variable var_double_value(this, MachineRepresentation::kFloat64);
   4968     Label rebox_double(this, &var_double_value);
   4969     Branch(UintPtrLessThan(field_index, inobject_properties), &if_inobject,
   4970            &if_backing_store);
   4971     Bind(&if_inobject);
   4972     {
   4973       Comment("if_inobject");
   4974       Node* field_offset =
   4975           IntPtrMul(IntPtrSub(LoadMapInstanceSize(map),
   4976                               IntPtrSub(inobject_properties, field_index)),
   4977                     IntPtrConstant(kPointerSize));
   4978 
   4979       Label if_double(this), if_tagged(this);
   4980       Branch(Word32NotEqual(representation,
   4981                             Int32Constant(Representation::kDouble)),
   4982              &if_tagged, &if_double);
   4983       Bind(&if_tagged);
   4984       {
   4985         var_value->Bind(LoadObjectField(object, field_offset));
   4986         Goto(&done);
   4987       }
   4988       Bind(&if_double);
   4989       {
   4990         if (FLAG_unbox_double_fields) {
   4991           var_double_value.Bind(
   4992               LoadObjectField(object, field_offset, MachineType::Float64()));
   4993         } else {
   4994           Node* mutable_heap_number = LoadObjectField(object, field_offset);
   4995           var_double_value.Bind(LoadHeapNumberValue(mutable_heap_number));
   4996         }
   4997         Goto(&rebox_double);
   4998       }
   4999     }
   5000     Bind(&if_backing_store);
   5001     {
   5002       Comment("if_backing_store");
   5003       Node* properties = LoadProperties(object);
   5004       field_index = IntPtrSub(field_index, inobject_properties);
   5005       Node* value = LoadFixedArrayElement(properties, field_index);
   5006 
   5007       Label if_double(this), if_tagged(this);
   5008       Branch(Word32NotEqual(representation,
   5009                             Int32Constant(Representation::kDouble)),
   5010              &if_tagged, &if_double);
   5011       Bind(&if_tagged);
   5012       {
   5013         var_value->Bind(value);
   5014         Goto(&done);
   5015       }
   5016       Bind(&if_double);
   5017       {
   5018         var_double_value.Bind(LoadHeapNumberValue(value));
   5019         Goto(&rebox_double);
   5020       }
   5021     }
   5022     Bind(&rebox_double);
   5023     {
   5024       Comment("rebox_double");
   5025       Node* heap_number = AllocateHeapNumberWithValue(var_double_value.value());
   5026       var_value->Bind(heap_number);
   5027       Goto(&done);
   5028     }
   5029   }
   5030   Bind(&if_in_descriptor);
   5031   {
   5032     var_value->Bind(
   5033         LoadValueByKeyIndex<DescriptorArray>(descriptors, name_index));
   5034     Goto(&done);
   5035   }
   5036   Bind(&done);
   5037 
   5038   Comment("] LoadPropertyFromFastObject");
   5039 }
   5040 
   5041 void CodeStubAssembler::LoadPropertyFromNameDictionary(Node* dictionary,
   5042                                                        Node* name_index,
   5043                                                        Variable* var_details,
   5044                                                        Variable* var_value) {
   5045   Comment("LoadPropertyFromNameDictionary");
   5046   CSA_ASSERT(this, IsDictionary(dictionary));
   5047 
   5048   var_details->Bind(
   5049       LoadDetailsByKeyIndex<NameDictionary>(dictionary, name_index));
   5050   var_value->Bind(LoadValueByKeyIndex<NameDictionary>(dictionary, name_index));
   5051 
   5052   Comment("] LoadPropertyFromNameDictionary");
   5053 }
   5054 
   5055 void CodeStubAssembler::LoadPropertyFromGlobalDictionary(Node* dictionary,
   5056                                                          Node* name_index,
   5057                                                          Variable* var_details,
   5058                                                          Variable* var_value,
   5059                                                          Label* if_deleted) {
   5060   Comment("[ LoadPropertyFromGlobalDictionary");
   5061   CSA_ASSERT(this, IsDictionary(dictionary));
   5062 
   5063   Node* property_cell =
   5064       LoadValueByKeyIndex<GlobalDictionary>(dictionary, name_index);
   5065 
   5066   Node* value = LoadObjectField(property_cell, PropertyCell::kValueOffset);
   5067   GotoIf(WordEqual(value, TheHoleConstant()), if_deleted);
   5068 
   5069   var_value->Bind(value);
   5070 
   5071   Node* details = LoadAndUntagToWord32ObjectField(property_cell,
   5072                                                   PropertyCell::kDetailsOffset);
   5073   var_details->Bind(details);
   5074 
   5075   Comment("] LoadPropertyFromGlobalDictionary");
   5076 }
   5077 
   5078 // |value| is the property backing store's contents, which is either a value
   5079 // or an accessor pair, as specified by |details|.
   5080 // Returns either the original value, or the result of the getter call.
   5081 Node* CodeStubAssembler::CallGetterIfAccessor(Node* value, Node* details,
   5082                                               Node* context, Node* receiver,
   5083                                               Label* if_bailout) {
   5084   Variable var_value(this, MachineRepresentation::kTagged, value);
   5085   Label done(this);
   5086 
   5087   Node* kind = DecodeWord32<PropertyDetails::KindField>(details);
   5088   GotoIf(Word32Equal(kind, Int32Constant(kData)), &done);
   5089 
   5090   // Accessor case.
   5091   {
   5092     Node* accessor_pair = value;
   5093     GotoIf(Word32Equal(LoadInstanceType(accessor_pair),
   5094                        Int32Constant(ACCESSOR_INFO_TYPE)),
   5095            if_bailout);
   5096     CSA_ASSERT(this, HasInstanceType(accessor_pair, ACCESSOR_PAIR_TYPE));
   5097     Node* getter = LoadObjectField(accessor_pair, AccessorPair::kGetterOffset);
   5098     Node* getter_map = LoadMap(getter);
   5099     Node* instance_type = LoadMapInstanceType(getter_map);
   5100     // FunctionTemplateInfo getters are not supported yet.
   5101     GotoIf(
   5102         Word32Equal(instance_type, Int32Constant(FUNCTION_TEMPLATE_INFO_TYPE)),
   5103         if_bailout);
   5104 
   5105     // Return undefined if the {getter} is not callable.
   5106     var_value.Bind(UndefinedConstant());
   5107     GotoIfNot(IsCallableMap(getter_map), &done);
   5108 
   5109     // Call the accessor.
   5110     Callable callable = CodeFactory::Call(isolate());
   5111     Node* result = CallJS(callable, context, getter, receiver);
   5112     var_value.Bind(result);
   5113     Goto(&done);
   5114   }
   5115 
   5116   Bind(&done);
   5117   return var_value.value();
   5118 }
   5119 
   5120 void CodeStubAssembler::TryGetOwnProperty(
   5121     Node* context, Node* receiver, Node* object, Node* map, Node* instance_type,
   5122     Node* unique_name, Label* if_found_value, Variable* var_value,
   5123     Label* if_not_found, Label* if_bailout) {
   5124   DCHECK_EQ(MachineRepresentation::kTagged, var_value->rep());
   5125   Comment("TryGetOwnProperty");
   5126 
   5127   Variable var_meta_storage(this, MachineRepresentation::kTagged);
   5128   Variable var_entry(this, MachineType::PointerRepresentation());
   5129 
   5130   Label if_found_fast(this), if_found_dict(this), if_found_global(this);
   5131 
   5132   Variable var_details(this, MachineRepresentation::kWord32);
   5133   Variable* vars[] = {var_value, &var_details};
   5134   Label if_found(this, 2, vars);
   5135 
   5136   TryLookupProperty(object, map, instance_type, unique_name, &if_found_fast,
   5137                     &if_found_dict, &if_found_global, &var_meta_storage,
   5138                     &var_entry, if_not_found, if_bailout);
   5139   Bind(&if_found_fast);
   5140   {
   5141     Node* descriptors = var_meta_storage.value();
   5142     Node* name_index = var_entry.value();
   5143 
   5144     LoadPropertyFromFastObject(object, map, descriptors, name_index,
   5145                                &var_details, var_value);
   5146     Goto(&if_found);
   5147   }
   5148   Bind(&if_found_dict);
   5149   {
   5150     Node* dictionary = var_meta_storage.value();
   5151     Node* entry = var_entry.value();
   5152     LoadPropertyFromNameDictionary(dictionary, entry, &var_details, var_value);
   5153     Goto(&if_found);
   5154   }
   5155   Bind(&if_found_global);
   5156   {
   5157     Node* dictionary = var_meta_storage.value();
   5158     Node* entry = var_entry.value();
   5159 
   5160     LoadPropertyFromGlobalDictionary(dictionary, entry, &var_details, var_value,
   5161                                      if_not_found);
   5162     Goto(&if_found);
   5163   }
   5164   // Here we have details and value which could be an accessor.
   5165   Bind(&if_found);
   5166   {
   5167     Node* value = CallGetterIfAccessor(var_value->value(), var_details.value(),
   5168                                        context, receiver, if_bailout);
   5169     var_value->Bind(value);
   5170     Goto(if_found_value);
   5171   }
   5172 }
   5173 
   5174 void CodeStubAssembler::TryLookupElement(Node* object, Node* map,
   5175                                          Node* instance_type,
   5176                                          Node* intptr_index, Label* if_found,
   5177                                          Label* if_not_found,
   5178                                          Label* if_bailout) {
   5179   // Handle special objects in runtime.
   5180   GotoIf(Int32LessThanOrEqual(instance_type,
   5181                               Int32Constant(LAST_SPECIAL_RECEIVER_TYPE)),
   5182          if_bailout);
   5183 
   5184   Node* elements_kind = LoadMapElementsKind(map);
   5185 
   5186   // TODO(verwaest): Support other elements kinds as well.
   5187   Label if_isobjectorsmi(this), if_isdouble(this), if_isdictionary(this),
   5188       if_isfaststringwrapper(this), if_isslowstringwrapper(this), if_oob(this);
   5189   // clang-format off
   5190   int32_t values[] = {
   5191       // Handled by {if_isobjectorsmi}.
   5192       FAST_SMI_ELEMENTS, FAST_HOLEY_SMI_ELEMENTS, FAST_ELEMENTS,
   5193           FAST_HOLEY_ELEMENTS,
   5194       // Handled by {if_isdouble}.
   5195       FAST_DOUBLE_ELEMENTS, FAST_HOLEY_DOUBLE_ELEMENTS,
   5196       // Handled by {if_isdictionary}.
   5197       DICTIONARY_ELEMENTS,
   5198       // Handled by {if_isfaststringwrapper}.
   5199       FAST_STRING_WRAPPER_ELEMENTS,
   5200       // Handled by {if_isslowstringwrapper}.
   5201       SLOW_STRING_WRAPPER_ELEMENTS,
   5202       // Handled by {if_not_found}.
   5203       NO_ELEMENTS,
   5204   };
   5205   Label* labels[] = {
   5206       &if_isobjectorsmi, &if_isobjectorsmi, &if_isobjectorsmi,
   5207           &if_isobjectorsmi,
   5208       &if_isdouble, &if_isdouble,
   5209       &if_isdictionary,
   5210       &if_isfaststringwrapper,
   5211       &if_isslowstringwrapper,
   5212       if_not_found,
   5213   };
   5214   // clang-format on
   5215   STATIC_ASSERT(arraysize(values) == arraysize(labels));
   5216   Switch(elements_kind, if_bailout, values, labels, arraysize(values));
   5217 
   5218   Bind(&if_isobjectorsmi);
   5219   {
   5220     Node* elements = LoadElements(object);
   5221     Node* length = LoadAndUntagFixedArrayBaseLength(elements);
   5222 
   5223     GotoIfNot(UintPtrLessThan(intptr_index, length), &if_oob);
   5224 
   5225     Node* element = LoadFixedArrayElement(elements, intptr_index);
   5226     Node* the_hole = TheHoleConstant();
   5227     Branch(WordEqual(element, the_hole), if_not_found, if_found);
   5228   }
   5229   Bind(&if_isdouble);
   5230   {
   5231     Node* elements = LoadElements(object);
   5232     Node* length = LoadAndUntagFixedArrayBaseLength(elements);
   5233 
   5234     GotoIfNot(UintPtrLessThan(intptr_index, length), &if_oob);
   5235 
   5236     // Check if the element is a double hole, but don't load it.
   5237     LoadFixedDoubleArrayElement(elements, intptr_index, MachineType::None(), 0,
   5238                                 INTPTR_PARAMETERS, if_not_found);
   5239     Goto(if_found);
   5240   }
   5241   Bind(&if_isdictionary);
   5242   {
   5243     // Negative keys must be converted to property names.
   5244     GotoIf(IntPtrLessThan(intptr_index, IntPtrConstant(0)), if_bailout);
   5245 
   5246     Variable var_entry(this, MachineType::PointerRepresentation());
   5247     Node* elements = LoadElements(object);
   5248     NumberDictionaryLookup<SeededNumberDictionary>(
   5249         elements, intptr_index, if_found, &var_entry, if_not_found);
   5250   }
   5251   Bind(&if_isfaststringwrapper);
   5252   {
   5253     CSA_ASSERT(this, HasInstanceType(object, JS_VALUE_TYPE));
   5254     Node* string = LoadJSValueValue(object);
   5255     CSA_ASSERT(this, IsStringInstanceType(LoadInstanceType(string)));
   5256     Node* length = LoadStringLength(string);
   5257     GotoIf(UintPtrLessThan(intptr_index, SmiUntag(length)), if_found);
   5258     Goto(&if_isobjectorsmi);
   5259   }
   5260   Bind(&if_isslowstringwrapper);
   5261   {
   5262     CSA_ASSERT(this, HasInstanceType(object, JS_VALUE_TYPE));
   5263     Node* string = LoadJSValueValue(object);
   5264     CSA_ASSERT(this, IsStringInstanceType(LoadInstanceType(string)));
   5265     Node* length = LoadStringLength(string);
   5266     GotoIf(UintPtrLessThan(intptr_index, SmiUntag(length)), if_found);
   5267     Goto(&if_isdictionary);
   5268   }
   5269   Bind(&if_oob);
   5270   {
   5271     // Positive OOB indices mean "not found", negative indices must be
   5272     // converted to property names.
   5273     GotoIf(IntPtrLessThan(intptr_index, IntPtrConstant(0)), if_bailout);
   5274     Goto(if_not_found);
   5275   }
   5276 }
   5277 
   5278 // Instantiate template methods to workaround GCC compilation issue.
   5279 template void CodeStubAssembler::NumberDictionaryLookup<SeededNumberDictionary>(
   5280     Node*, Node*, Label*, Variable*, Label*);
   5281 template void CodeStubAssembler::NumberDictionaryLookup<
   5282     UnseededNumberDictionary>(Node*, Node*, Label*, Variable*, Label*);
   5283 
   5284 void CodeStubAssembler::TryPrototypeChainLookup(
   5285     Node* receiver, Node* key, const LookupInHolder& lookup_property_in_holder,
   5286     const LookupInHolder& lookup_element_in_holder, Label* if_end,
   5287     Label* if_bailout) {
   5288   // Ensure receiver is JSReceiver, otherwise bailout.
   5289   Label if_objectisnotsmi(this);
   5290   Branch(TaggedIsSmi(receiver), if_bailout, &if_objectisnotsmi);
   5291   Bind(&if_objectisnotsmi);
   5292 
   5293   Node* map = LoadMap(receiver);
   5294   Node* instance_type = LoadMapInstanceType(map);
   5295   {
   5296     Label if_objectisreceiver(this);
   5297     STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
   5298     STATIC_ASSERT(FIRST_JS_RECEIVER_TYPE == JS_PROXY_TYPE);
   5299     Branch(
   5300         Int32GreaterThan(instance_type, Int32Constant(FIRST_JS_RECEIVER_TYPE)),
   5301         &if_objectisreceiver, if_bailout);
   5302     Bind(&if_objectisreceiver);
   5303   }
   5304 
   5305   Variable var_index(this, MachineType::PointerRepresentation());
   5306   Variable var_unique(this, MachineRepresentation::kTagged);
   5307 
   5308   Label if_keyisindex(this), if_iskeyunique(this);
   5309   TryToName(key, &if_keyisindex, &var_index, &if_iskeyunique, &var_unique,
   5310             if_bailout);
   5311 
   5312   Bind(&if_iskeyunique);
   5313   {
   5314     Variable var_holder(this, MachineRepresentation::kTagged, receiver);
   5315     Variable var_holder_map(this, MachineRepresentation::kTagged, map);
   5316     Variable var_holder_instance_type(this, MachineRepresentation::kWord32,
   5317                                       instance_type);
   5318 
   5319     Variable* merged_variables[] = {&var_holder, &var_holder_map,
   5320                                     &var_holder_instance_type};
   5321     Label loop(this, arraysize(merged_variables), merged_variables);
   5322     Goto(&loop);
   5323     Bind(&loop);
   5324     {
   5325       Node* holder_map = var_holder_map.value();
   5326       Node* holder_instance_type = var_holder_instance_type.value();
   5327 
   5328       Label next_proto(this);
   5329       lookup_property_in_holder(receiver, var_holder.value(), holder_map,
   5330                                 holder_instance_type, var_unique.value(),
   5331                                 &next_proto, if_bailout);
   5332       Bind(&next_proto);
   5333 
   5334       // Bailout if it can be an integer indexed exotic case.
   5335       GotoIf(
   5336           Word32Equal(holder_instance_type, Int32Constant(JS_TYPED_ARRAY_TYPE)),
   5337           if_bailout);
   5338 
   5339       Node* proto = LoadMapPrototype(holder_map);
   5340 
   5341       Label if_not_null(this);
   5342       Branch(WordEqual(proto, NullConstant()), if_end, &if_not_null);
   5343       Bind(&if_not_null);
   5344 
   5345       Node* map = LoadMap(proto);
   5346       Node* instance_type = LoadMapInstanceType(map);
   5347 
   5348       var_holder.Bind(proto);
   5349       var_holder_map.Bind(map);
   5350       var_holder_instance_type.Bind(instance_type);
   5351       Goto(&loop);
   5352     }
   5353   }
   5354   Bind(&if_keyisindex);
   5355   {
   5356     Variable var_holder(this, MachineRepresentation::kTagged, receiver);
   5357     Variable var_holder_map(this, MachineRepresentation::kTagged, map);
   5358     Variable var_holder_instance_type(this, MachineRepresentation::kWord32,
   5359                                       instance_type);
   5360 
   5361     Variable* merged_variables[] = {&var_holder, &var_holder_map,
   5362                                     &var_holder_instance_type};
   5363     Label loop(this, arraysize(merged_variables), merged_variables);
   5364     Goto(&loop);
   5365     Bind(&loop);
   5366     {
   5367       Label next_proto(this);
   5368       lookup_element_in_holder(receiver, var_holder.value(),
   5369                                var_holder_map.value(),
   5370                                var_holder_instance_type.value(),
   5371                                var_index.value(), &next_proto, if_bailout);
   5372       Bind(&next_proto);
   5373 
   5374       Node* proto = LoadMapPrototype(var_holder_map.value());
   5375 
   5376       Label if_not_null(this);
   5377       Branch(WordEqual(proto, NullConstant()), if_end, &if_not_null);
   5378       Bind(&if_not_null);
   5379 
   5380       Node* map = LoadMap(proto);
   5381       Node* instance_type = LoadMapInstanceType(map);
   5382 
   5383       var_holder.Bind(proto);
   5384       var_holder_map.Bind(map);
   5385       var_holder_instance_type.Bind(instance_type);
   5386       Goto(&loop);
   5387     }
   5388   }
   5389 }
   5390 
   5391 Node* CodeStubAssembler::OrdinaryHasInstance(Node* context, Node* callable,
   5392                                              Node* object) {
   5393   Variable var_result(this, MachineRepresentation::kTagged);
   5394   Label return_false(this), return_true(this),
   5395       return_runtime(this, Label::kDeferred), return_result(this);
   5396 
   5397   // Goto runtime if {object} is a Smi.
   5398   GotoIf(TaggedIsSmi(object), &return_runtime);
   5399 
   5400   // Load map of {object}.
   5401   Node* object_map = LoadMap(object);
   5402 
   5403   // Lookup the {callable} and {object} map in the global instanceof cache.
   5404   // Note: This is safe because we clear the global instanceof cache whenever
   5405   // we change the prototype of any object.
   5406   Node* instanceof_cache_function =
   5407       LoadRoot(Heap::kInstanceofCacheFunctionRootIndex);
   5408   Node* instanceof_cache_map = LoadRoot(Heap::kInstanceofCacheMapRootIndex);
   5409   {
   5410     Label instanceof_cache_miss(this);
   5411     GotoIfNot(WordEqual(instanceof_cache_function, callable),
   5412               &instanceof_cache_miss);
   5413     GotoIfNot(WordEqual(instanceof_cache_map, object_map),
   5414               &instanceof_cache_miss);
   5415     var_result.Bind(LoadRoot(Heap::kInstanceofCacheAnswerRootIndex));
   5416     Goto(&return_result);
   5417     Bind(&instanceof_cache_miss);
   5418   }
   5419 
   5420   // Goto runtime if {callable} is a Smi.
   5421   GotoIf(TaggedIsSmi(callable), &return_runtime);
   5422 
   5423   // Load map of {callable}.
   5424   Node* callable_map = LoadMap(callable);
   5425 
   5426   // Goto runtime if {callable} is not a JSFunction.
   5427   Node* callable_instance_type = LoadMapInstanceType(callable_map);
   5428   GotoIfNot(
   5429       Word32Equal(callable_instance_type, Int32Constant(JS_FUNCTION_TYPE)),
   5430       &return_runtime);
   5431 
   5432   // Goto runtime if {callable} is not a constructor or has
   5433   // a non-instance "prototype".
   5434   Node* callable_bitfield = LoadMapBitField(callable_map);
   5435   GotoIfNot(
   5436       Word32Equal(Word32And(callable_bitfield,
   5437                             Int32Constant((1 << Map::kHasNonInstancePrototype) |
   5438                                           (1 << Map::kIsConstructor))),
   5439                   Int32Constant(1 << Map::kIsConstructor)),
   5440       &return_runtime);
   5441 
   5442   // Get the "prototype" (or initial map) of the {callable}.
   5443   Node* callable_prototype =
   5444       LoadObjectField(callable, JSFunction::kPrototypeOrInitialMapOffset);
   5445   {
   5446     Label callable_prototype_valid(this);
   5447     Variable var_callable_prototype(this, MachineRepresentation::kTagged,
   5448                                     callable_prototype);
   5449 
   5450     // Resolve the "prototype" if the {callable} has an initial map.  Afterwards
   5451     // the {callable_prototype} will be either the JSReceiver prototype object
   5452     // or the hole value, which means that no instances of the {callable} were
   5453     // created so far and hence we should return false.
   5454     Node* callable_prototype_instance_type =
   5455         LoadInstanceType(callable_prototype);
   5456     GotoIfNot(
   5457         Word32Equal(callable_prototype_instance_type, Int32Constant(MAP_TYPE)),
   5458         &callable_prototype_valid);
   5459     var_callable_prototype.Bind(
   5460         LoadObjectField(callable_prototype, Map::kPrototypeOffset));
   5461     Goto(&callable_prototype_valid);
   5462     Bind(&callable_prototype_valid);
   5463     callable_prototype = var_callable_prototype.value();
   5464   }
   5465 
   5466   // Update the global instanceof cache with the current {object} map and
   5467   // {callable}.  The cached answer will be set when it is known below.
   5468   StoreRoot(Heap::kInstanceofCacheFunctionRootIndex, callable);
   5469   StoreRoot(Heap::kInstanceofCacheMapRootIndex, object_map);
   5470 
   5471   // Loop through the prototype chain looking for the {callable} prototype.
   5472   Variable var_object_map(this, MachineRepresentation::kTagged, object_map);
   5473   Label loop(this, &var_object_map);
   5474   Goto(&loop);
   5475   Bind(&loop);
   5476   {
   5477     Node* object_map = var_object_map.value();
   5478 
   5479     // Check if the current {object} needs to be access checked.
   5480     Node* object_bitfield = LoadMapBitField(object_map);
   5481     GotoIfNot(
   5482         Word32Equal(Word32And(object_bitfield,
   5483                               Int32Constant(1 << Map::kIsAccessCheckNeeded)),
   5484                     Int32Constant(0)),
   5485         &return_runtime);
   5486 
   5487     // Check if the current {object} is a proxy.
   5488     Node* object_instance_type = LoadMapInstanceType(object_map);
   5489     GotoIf(Word32Equal(object_instance_type, Int32Constant(JS_PROXY_TYPE)),
   5490            &return_runtime);
   5491 
   5492     // Check the current {object} prototype.
   5493     Node* object_prototype = LoadMapPrototype(object_map);
   5494     GotoIf(WordEqual(object_prototype, NullConstant()), &return_false);
   5495     GotoIf(WordEqual(object_prototype, callable_prototype), &return_true);
   5496 
   5497     // Continue with the prototype.
   5498     var_object_map.Bind(LoadMap(object_prototype));
   5499     Goto(&loop);
   5500   }
   5501 
   5502   Bind(&return_true);
   5503   StoreRoot(Heap::kInstanceofCacheAnswerRootIndex, BooleanConstant(true));
   5504   var_result.Bind(BooleanConstant(true));
   5505   Goto(&return_result);
   5506 
   5507   Bind(&return_false);
   5508   StoreRoot(Heap::kInstanceofCacheAnswerRootIndex, BooleanConstant(false));
   5509   var_result.Bind(BooleanConstant(false));
   5510   Goto(&return_result);
   5511 
   5512   Bind(&return_runtime);
   5513   {
   5514     // Invalidate the global instanceof cache.
   5515     StoreRoot(Heap::kInstanceofCacheFunctionRootIndex, SmiConstant(0));
   5516     // Fallback to the runtime implementation.
   5517     var_result.Bind(
   5518         CallRuntime(Runtime::kOrdinaryHasInstance, context, callable, object));
   5519   }
   5520   Goto(&return_result);
   5521 
   5522   Bind(&return_result);
   5523   return var_result.value();
   5524 }
   5525 
   5526 Node* CodeStubAssembler::ElementOffsetFromIndex(Node* index_node,
   5527                                                 ElementsKind kind,
   5528                                                 ParameterMode mode,
   5529                                                 int base_size) {
   5530   int element_size_shift = ElementsKindToShiftSize(kind);
   5531   int element_size = 1 << element_size_shift;
   5532   int const kSmiShiftBits = kSmiShiftSize + kSmiTagSize;
   5533   intptr_t index = 0;
   5534   bool constant_index = false;
   5535   if (mode == SMI_PARAMETERS) {
   5536     element_size_shift -= kSmiShiftBits;
   5537     Smi* smi_index;
   5538     constant_index = ToSmiConstant(index_node, smi_index);
   5539     if (constant_index) index = smi_index->value();
   5540     index_node = BitcastTaggedToWord(index_node);
   5541   } else {
   5542     DCHECK(mode == INTPTR_PARAMETERS);
   5543     constant_index = ToIntPtrConstant(index_node, index);
   5544   }
   5545   if (constant_index) {
   5546     return IntPtrConstant(base_size + element_size * index);
   5547   }
   5548 
   5549   Node* shifted_index =
   5550       (element_size_shift == 0)
   5551           ? index_node
   5552           : ((element_size_shift > 0)
   5553                  ? WordShl(index_node, IntPtrConstant(element_size_shift))
   5554                  : WordShr(index_node, IntPtrConstant(-element_size_shift)));
   5555   return IntPtrAdd(IntPtrConstant(base_size), shifted_index);
   5556 }
   5557 
   5558 Node* CodeStubAssembler::LoadFeedbackVectorForStub() {
   5559   Node* function =
   5560       LoadFromParentFrame(JavaScriptFrameConstants::kFunctionOffset);
   5561   Node* cell = LoadObjectField(function, JSFunction::kFeedbackVectorOffset);
   5562   return LoadObjectField(cell, Cell::kValueOffset);
   5563 }
   5564 
   5565 void CodeStubAssembler::UpdateFeedback(Node* feedback, Node* feedback_vector,
   5566                                        Node* slot_id) {
   5567   // This method is used for binary op and compare feedback. These
   5568   // vector nodes are initialized with a smi 0, so we can simply OR
   5569   // our new feedback in place.
   5570   Node* previous_feedback = LoadFixedArrayElement(feedback_vector, slot_id);
   5571   Node* combined_feedback = SmiOr(previous_feedback, feedback);
   5572   StoreFixedArrayElement(feedback_vector, slot_id, combined_feedback,
   5573                          SKIP_WRITE_BARRIER);
   5574 }
   5575 
   5576 Node* CodeStubAssembler::LoadReceiverMap(Node* receiver) {
   5577   Variable var_receiver_map(this, MachineRepresentation::kTagged);
   5578   Label load_smi_map(this, Label::kDeferred), load_receiver_map(this),
   5579       if_result(this);
   5580 
   5581   Branch(TaggedIsSmi(receiver), &load_smi_map, &load_receiver_map);
   5582   Bind(&load_smi_map);
   5583   {
   5584     var_receiver_map.Bind(LoadRoot(Heap::kHeapNumberMapRootIndex));
   5585     Goto(&if_result);
   5586   }
   5587   Bind(&load_receiver_map);
   5588   {
   5589     var_receiver_map.Bind(LoadMap(receiver));
   5590     Goto(&if_result);
   5591   }
   5592   Bind(&if_result);
   5593   return var_receiver_map.value();
   5594 }
   5595 
   5596 Node* CodeStubAssembler::TryToIntptr(Node* key, Label* miss) {
   5597   Variable var_intptr_key(this, MachineType::PointerRepresentation());
   5598   Label done(this, &var_intptr_key), key_is_smi(this);
   5599   GotoIf(TaggedIsSmi(key), &key_is_smi);
   5600   // Try to convert a heap number to a Smi.
   5601   GotoIfNot(IsHeapNumberMap(LoadMap(key)), miss);
   5602   {
   5603     Node* value = LoadHeapNumberValue(key);
   5604     Node* int_value = RoundFloat64ToInt32(value);
   5605     GotoIfNot(Float64Equal(value, ChangeInt32ToFloat64(int_value)), miss);
   5606     var_intptr_key.Bind(ChangeInt32ToIntPtr(int_value));
   5607     Goto(&done);
   5608   }
   5609 
   5610   Bind(&key_is_smi);
   5611   {
   5612     var_intptr_key.Bind(SmiUntag(key));
   5613     Goto(&done);
   5614   }
   5615 
   5616   Bind(&done);
   5617   return var_intptr_key.value();
   5618 }
   5619 
   5620 Node* CodeStubAssembler::EmitKeyedSloppyArguments(Node* receiver, Node* key,
   5621                                                   Node* value, Label* bailout) {
   5622   // Mapped arguments are actual arguments. Unmapped arguments are values added
   5623   // to the arguments object after it was created for the call. Mapped arguments
   5624   // are stored in the context at indexes given by elements[key + 2]. Unmapped
   5625   // arguments are stored as regular indexed properties in the arguments array,
   5626   // held at elements[1]. See NewSloppyArguments() in runtime.cc for a detailed
   5627   // look at argument object construction.
   5628   //
   5629   // The sloppy arguments elements array has a special format:
   5630   //
   5631   // 0: context
   5632   // 1: unmapped arguments array
   5633   // 2: mapped_index0,
   5634   // 3: mapped_index1,
   5635   // ...
   5636   //
   5637   // length is 2 + min(number_of_actual_arguments, number_of_formal_arguments).
   5638   // If key + 2 >= elements.length then attempt to look in the unmapped
   5639   // arguments array (given by elements[1]) and return the value at key, missing
   5640   // to the runtime if the unmapped arguments array is not a fixed array or if
   5641   // key >= unmapped_arguments_array.length.
   5642   //
   5643   // Otherwise, t = elements[key + 2]. If t is the hole, then look up the value
   5644   // in the unmapped arguments array, as described above. Otherwise, t is a Smi
   5645   // index into the context array given at elements[0]. Return the value at
   5646   // context[t].
   5647 
   5648   bool is_load = value == nullptr;
   5649 
   5650   GotoIfNot(TaggedIsSmi(key), bailout);
   5651   key = SmiUntag(key);
   5652   GotoIf(IntPtrLessThan(key, IntPtrConstant(0)), bailout);
   5653 
   5654   Node* elements = LoadElements(receiver);
   5655   Node* elements_length = LoadAndUntagFixedArrayBaseLength(elements);
   5656 
   5657   Variable var_result(this, MachineRepresentation::kTagged);
   5658   if (!is_load) {
   5659     var_result.Bind(value);
   5660   }
   5661   Label if_mapped(this), if_unmapped(this), end(this, &var_result);
   5662   Node* intptr_two = IntPtrConstant(2);
   5663   Node* adjusted_length = IntPtrSub(elements_length, intptr_two);
   5664 
   5665   GotoIf(UintPtrGreaterThanOrEqual(key, adjusted_length), &if_unmapped);
   5666 
   5667   Node* mapped_index =
   5668       LoadFixedArrayElement(elements, IntPtrAdd(key, intptr_two));
   5669   Branch(WordEqual(mapped_index, TheHoleConstant()), &if_unmapped, &if_mapped);
   5670 
   5671   Bind(&if_mapped);
   5672   {
   5673     CSA_ASSERT(this, TaggedIsSmi(mapped_index));
   5674     mapped_index = SmiUntag(mapped_index);
   5675     Node* the_context = LoadFixedArrayElement(elements, 0);
   5676     // Assert that we can use LoadFixedArrayElement/StoreFixedArrayElement
   5677     // methods for accessing Context.
   5678     STATIC_ASSERT(Context::kHeaderSize == FixedArray::kHeaderSize);
   5679     DCHECK_EQ(Context::SlotOffset(0) + kHeapObjectTag,
   5680               FixedArray::OffsetOfElementAt(0));
   5681     if (is_load) {
   5682       Node* result = LoadFixedArrayElement(the_context, mapped_index);
   5683       CSA_ASSERT(this, WordNotEqual(result, TheHoleConstant()));
   5684       var_result.Bind(result);
   5685     } else {
   5686       StoreFixedArrayElement(the_context, mapped_index, value);
   5687     }
   5688     Goto(&end);
   5689   }
   5690 
   5691   Bind(&if_unmapped);
   5692   {
   5693     Node* backing_store = LoadFixedArrayElement(elements, 1);
   5694     GotoIf(WordNotEqual(LoadMap(backing_store), FixedArrayMapConstant()),
   5695            bailout);
   5696 
   5697     Node* backing_store_length =
   5698         LoadAndUntagFixedArrayBaseLength(backing_store);
   5699     GotoIf(UintPtrGreaterThanOrEqual(key, backing_store_length), bailout);
   5700 
   5701     // The key falls into unmapped range.
   5702     if (is_load) {
   5703       Node* result = LoadFixedArrayElement(backing_store, key);
   5704       GotoIf(WordEqual(result, TheHoleConstant()), bailout);
   5705       var_result.Bind(result);
   5706     } else {
   5707       StoreFixedArrayElement(backing_store, key, value);
   5708     }
   5709     Goto(&end);
   5710   }
   5711 
   5712   Bind(&end);
   5713   return var_result.value();
   5714 }
   5715 
   5716 Node* CodeStubAssembler::LoadScriptContext(Node* context, int context_index) {
   5717   Node* native_context = LoadNativeContext(context);
   5718   Node* script_context_table =
   5719       LoadContextElement(native_context, Context::SCRIPT_CONTEXT_TABLE_INDEX);
   5720 
   5721   int offset =
   5722       ScriptContextTable::GetContextOffset(context_index) - kHeapObjectTag;
   5723   return Load(MachineType::AnyTagged(), script_context_table,
   5724               IntPtrConstant(offset));
   5725 }
   5726 
   5727 namespace {
   5728 
   5729 // Converts typed array elements kind to a machine representations.
   5730 MachineRepresentation ElementsKindToMachineRepresentation(ElementsKind kind) {
   5731   switch (kind) {
   5732     case UINT8_CLAMPED_ELEMENTS:
   5733     case UINT8_ELEMENTS:
   5734     case INT8_ELEMENTS:
   5735       return MachineRepresentation::kWord8;
   5736     case UINT16_ELEMENTS:
   5737     case INT16_ELEMENTS:
   5738       return MachineRepresentation::kWord16;
   5739     case UINT32_ELEMENTS:
   5740     case INT32_ELEMENTS:
   5741       return MachineRepresentation::kWord32;
   5742     case FLOAT32_ELEMENTS:
   5743       return MachineRepresentation::kFloat32;
   5744     case FLOAT64_ELEMENTS:
   5745       return MachineRepresentation::kFloat64;
   5746     default:
   5747       UNREACHABLE();
   5748       return MachineRepresentation::kNone;
   5749   }
   5750 }
   5751 
   5752 }  // namespace
   5753 
   5754 void CodeStubAssembler::StoreElement(Node* elements, ElementsKind kind,
   5755                                      Node* index, Node* value,
   5756                                      ParameterMode mode) {
   5757   if (IsFixedTypedArrayElementsKind(kind)) {
   5758     if (kind == UINT8_CLAMPED_ELEMENTS) {
   5759       CSA_ASSERT(this,
   5760                  Word32Equal(value, Word32And(Int32Constant(0xff), value)));
   5761     }
   5762     Node* offset = ElementOffsetFromIndex(index, kind, mode, 0);
   5763     MachineRepresentation rep = ElementsKindToMachineRepresentation(kind);
   5764     StoreNoWriteBarrier(rep, elements, offset, value);
   5765     return;
   5766   }
   5767 
   5768   WriteBarrierMode barrier_mode =
   5769       IsFastSmiElementsKind(kind) ? SKIP_WRITE_BARRIER : UPDATE_WRITE_BARRIER;
   5770   if (IsFastDoubleElementsKind(kind)) {
   5771     // Make sure we do not store signalling NaNs into double arrays.
   5772     value = Float64SilenceNaN(value);
   5773     StoreFixedDoubleArrayElement(elements, index, value, mode);
   5774   } else {
   5775     StoreFixedArrayElement(elements, index, value, barrier_mode, 0, mode);
   5776   }
   5777 }
   5778 
   5779 Node* CodeStubAssembler::Int32ToUint8Clamped(Node* int32_value) {
   5780   Label done(this);
   5781   Node* int32_zero = Int32Constant(0);
   5782   Node* int32_255 = Int32Constant(255);
   5783   Variable var_value(this, MachineRepresentation::kWord32, int32_value);
   5784   GotoIf(Uint32LessThanOrEqual(int32_value, int32_255), &done);
   5785   var_value.Bind(int32_zero);
   5786   GotoIf(Int32LessThan(int32_value, int32_zero), &done);
   5787   var_value.Bind(int32_255);
   5788   Goto(&done);
   5789   Bind(&done);
   5790   return var_value.value();
   5791 }
   5792 
   5793 Node* CodeStubAssembler::Float64ToUint8Clamped(Node* float64_value) {
   5794   Label done(this);
   5795   Variable var_value(this, MachineRepresentation::kWord32, Int32Constant(0));
   5796   GotoIf(Float64LessThanOrEqual(float64_value, Float64Constant(0.0)), &done);
   5797   var_value.Bind(Int32Constant(255));
   5798   GotoIf(Float64LessThanOrEqual(Float64Constant(255.0), float64_value), &done);
   5799   {
   5800     Node* rounded_value = Float64RoundToEven(float64_value);
   5801     var_value.Bind(TruncateFloat64ToWord32(rounded_value));
   5802     Goto(&done);
   5803   }
   5804   Bind(&done);
   5805   return var_value.value();
   5806 }
   5807 
   5808 Node* CodeStubAssembler::PrepareValueForWriteToTypedArray(
   5809     Node* input, ElementsKind elements_kind, Label* bailout) {
   5810   DCHECK(IsFixedTypedArrayElementsKind(elements_kind));
   5811 
   5812   MachineRepresentation rep;
   5813   switch (elements_kind) {
   5814     case UINT8_ELEMENTS:
   5815     case INT8_ELEMENTS:
   5816     case UINT16_ELEMENTS:
   5817     case INT16_ELEMENTS:
   5818     case UINT32_ELEMENTS:
   5819     case INT32_ELEMENTS:
   5820     case UINT8_CLAMPED_ELEMENTS:
   5821       rep = MachineRepresentation::kWord32;
   5822       break;
   5823     case FLOAT32_ELEMENTS:
   5824       rep = MachineRepresentation::kFloat32;
   5825       break;
   5826     case FLOAT64_ELEMENTS:
   5827       rep = MachineRepresentation::kFloat64;
   5828       break;
   5829     default:
   5830       UNREACHABLE();
   5831       return nullptr;
   5832   }
   5833 
   5834   Variable var_result(this, rep);
   5835   Label done(this, &var_result), if_smi(this);
   5836   GotoIf(TaggedIsSmi(input), &if_smi);
   5837   // Try to convert a heap number to a Smi.
   5838   GotoIfNot(IsHeapNumberMap(LoadMap(input)), bailout);
   5839   {
   5840     Node* value = LoadHeapNumberValue(input);
   5841     if (rep == MachineRepresentation::kWord32) {
   5842       if (elements_kind == UINT8_CLAMPED_ELEMENTS) {
   5843         value = Float64ToUint8Clamped(value);
   5844       } else {
   5845         value = TruncateFloat64ToWord32(value);
   5846       }
   5847     } else if (rep == MachineRepresentation::kFloat32) {
   5848       value = TruncateFloat64ToFloat32(value);
   5849     } else {
   5850       DCHECK_EQ(MachineRepresentation::kFloat64, rep);
   5851     }
   5852     var_result.Bind(value);
   5853     Goto(&done);
   5854   }
   5855 
   5856   Bind(&if_smi);
   5857   {
   5858     Node* value = SmiToWord32(input);
   5859     if (rep == MachineRepresentation::kFloat32) {
   5860       value = RoundInt32ToFloat32(value);
   5861     } else if (rep == MachineRepresentation::kFloat64) {
   5862       value = ChangeInt32ToFloat64(value);
   5863     } else {
   5864       DCHECK_EQ(MachineRepresentation::kWord32, rep);
   5865       if (elements_kind == UINT8_CLAMPED_ELEMENTS) {
   5866         value = Int32ToUint8Clamped(value);
   5867       }
   5868     }
   5869     var_result.Bind(value);
   5870     Goto(&done);
   5871   }
   5872 
   5873   Bind(&done);
   5874   return var_result.value();
   5875 }
   5876 
   5877 void CodeStubAssembler::EmitElementStore(Node* object, Node* key, Node* value,
   5878                                          bool is_jsarray,
   5879                                          ElementsKind elements_kind,
   5880                                          KeyedAccessStoreMode store_mode,
   5881                                          Label* bailout) {
   5882   Node* elements = LoadElements(object);
   5883   if (IsFastSmiOrObjectElementsKind(elements_kind) &&
   5884       store_mode != STORE_NO_TRANSITION_HANDLE_COW) {
   5885     // Bailout in case of COW elements.
   5886     GotoIf(WordNotEqual(LoadMap(elements),
   5887                         LoadRoot(Heap::kFixedArrayMapRootIndex)),
   5888            bailout);
   5889   }
   5890   // TODO(ishell): introduce TryToIntPtrOrSmi() and use OptimalParameterMode().
   5891   ParameterMode parameter_mode = INTPTR_PARAMETERS;
   5892   key = TryToIntptr(key, bailout);
   5893 
   5894   if (IsFixedTypedArrayElementsKind(elements_kind)) {
   5895     Label done(this);
   5896     // TODO(ishell): call ToNumber() on value and don't bailout but be careful
   5897     // to call it only once if we decide to bailout because of bounds checks.
   5898 
   5899     value = PrepareValueForWriteToTypedArray(value, elements_kind, bailout);
   5900 
   5901     // There must be no allocations between the buffer load and
   5902     // and the actual store to backing store, because GC may decide that
   5903     // the buffer is not alive or move the elements.
   5904     // TODO(ishell): introduce DisallowHeapAllocationCode scope here.
   5905 
   5906     // Check if buffer has been neutered.
   5907     Node* buffer = LoadObjectField(object, JSArrayBufferView::kBufferOffset);
   5908     GotoIf(IsDetachedBuffer(buffer), bailout);
   5909 
   5910     // Bounds check.
   5911     Node* length = TaggedToParameter(
   5912         LoadObjectField(object, JSTypedArray::kLengthOffset), parameter_mode);
   5913 
   5914     if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) {
   5915       // Skip the store if we write beyond the length.
   5916       GotoIfNot(IntPtrLessThan(key, length), &done);
   5917       // ... but bailout if the key is negative.
   5918     } else {
   5919       DCHECK_EQ(STANDARD_STORE, store_mode);
   5920     }
   5921     GotoIfNot(UintPtrLessThan(key, length), bailout);
   5922 
   5923     // Backing store = external_pointer + base_pointer.
   5924     Node* external_pointer =
   5925         LoadObjectField(elements, FixedTypedArrayBase::kExternalPointerOffset,
   5926                         MachineType::Pointer());
   5927     Node* base_pointer =
   5928         LoadObjectField(elements, FixedTypedArrayBase::kBasePointerOffset);
   5929     Node* backing_store =
   5930         IntPtrAdd(external_pointer, BitcastTaggedToWord(base_pointer));
   5931     StoreElement(backing_store, elements_kind, key, value, parameter_mode);
   5932     Goto(&done);
   5933 
   5934     Bind(&done);
   5935     return;
   5936   }
   5937   DCHECK(IsFastSmiOrObjectElementsKind(elements_kind) ||
   5938          IsFastDoubleElementsKind(elements_kind));
   5939 
   5940   Node* length = is_jsarray ? LoadObjectField(object, JSArray::kLengthOffset)
   5941                             : LoadFixedArrayBaseLength(elements);
   5942   length = TaggedToParameter(length, parameter_mode);
   5943 
   5944   // In case value is stored into a fast smi array, assure that the value is
   5945   // a smi before manipulating the backing store. Otherwise the backing store
   5946   // may be left in an invalid state.
   5947   if (IsFastSmiElementsKind(elements_kind)) {
   5948     GotoIfNot(TaggedIsSmi(value), bailout);
   5949   } else if (IsFastDoubleElementsKind(elements_kind)) {
   5950     value = TryTaggedToFloat64(value, bailout);
   5951   }
   5952 
   5953   if (IsGrowStoreMode(store_mode)) {
   5954     elements = CheckForCapacityGrow(object, elements, elements_kind, length,
   5955                                     key, parameter_mode, is_jsarray, bailout);
   5956   } else {
   5957     GotoIfNot(UintPtrLessThan(key, length), bailout);
   5958 
   5959     if ((store_mode == STORE_NO_TRANSITION_HANDLE_COW) &&
   5960         IsFastSmiOrObjectElementsKind(elements_kind)) {
   5961       elements = CopyElementsOnWrite(object, elements, elements_kind, length,
   5962                                      parameter_mode, bailout);
   5963     }
   5964   }
   5965   StoreElement(elements, elements_kind, key, value, parameter_mode);
   5966 }
   5967 
   5968 Node* CodeStubAssembler::CheckForCapacityGrow(Node* object, Node* elements,
   5969                                               ElementsKind kind, Node* length,
   5970                                               Node* key, ParameterMode mode,
   5971                                               bool is_js_array,
   5972                                               Label* bailout) {
   5973   Variable checked_elements(this, MachineRepresentation::kTagged);
   5974   Label grow_case(this), no_grow_case(this), done(this);
   5975 
   5976   Node* condition;
   5977   if (IsHoleyElementsKind(kind)) {
   5978     condition = UintPtrGreaterThanOrEqual(key, length);
   5979   } else {
   5980     condition = WordEqual(key, length);
   5981   }
   5982   Branch(condition, &grow_case, &no_grow_case);
   5983 
   5984   Bind(&grow_case);
   5985   {
   5986     Node* current_capacity =
   5987         TaggedToParameter(LoadFixedArrayBaseLength(elements), mode);
   5988 
   5989     checked_elements.Bind(elements);
   5990 
   5991     Label fits_capacity(this);
   5992     GotoIf(UintPtrLessThan(key, current_capacity), &fits_capacity);
   5993     {
   5994       Node* new_elements = TryGrowElementsCapacity(
   5995           object, elements, kind, key, current_capacity, mode, bailout);
   5996 
   5997       checked_elements.Bind(new_elements);
   5998       Goto(&fits_capacity);
   5999     }
   6000     Bind(&fits_capacity);
   6001 
   6002     if (is_js_array) {
   6003       Node* new_length = IntPtrAdd(key, IntPtrOrSmiConstant(1, mode));
   6004       StoreObjectFieldNoWriteBarrier(object, JSArray::kLengthOffset,
   6005                                      ParameterToTagged(new_length, mode));
   6006     }
   6007     Goto(&done);
   6008   }
   6009 
   6010   Bind(&no_grow_case);
   6011   {
   6012     GotoIfNot(UintPtrLessThan(key, length), bailout);
   6013     checked_elements.Bind(elements);
   6014     Goto(&done);
   6015   }
   6016 
   6017   Bind(&done);
   6018   return checked_elements.value();
   6019 }
   6020 
   6021 Node* CodeStubAssembler::CopyElementsOnWrite(Node* object, Node* elements,
   6022                                              ElementsKind kind, Node* length,
   6023                                              ParameterMode mode,
   6024                                              Label* bailout) {
   6025   Variable new_elements_var(this, MachineRepresentation::kTagged, elements);
   6026   Label done(this);
   6027 
   6028   GotoIfNot(
   6029       WordEqual(LoadMap(elements), LoadRoot(Heap::kFixedCOWArrayMapRootIndex)),
   6030       &done);
   6031   {
   6032     Node* capacity =
   6033         TaggedToParameter(LoadFixedArrayBaseLength(elements), mode);
   6034     Node* new_elements = GrowElementsCapacity(object, elements, kind, kind,
   6035                                               length, capacity, mode, bailout);
   6036 
   6037     new_elements_var.Bind(new_elements);
   6038     Goto(&done);
   6039   }
   6040 
   6041   Bind(&done);
   6042   return new_elements_var.value();
   6043 }
   6044 
   6045 void CodeStubAssembler::TransitionElementsKind(Node* object, Node* map,
   6046                                                ElementsKind from_kind,
   6047                                                ElementsKind to_kind,
   6048                                                bool is_jsarray,
   6049                                                Label* bailout) {
   6050   DCHECK(!IsFastHoleyElementsKind(from_kind) ||
   6051          IsFastHoleyElementsKind(to_kind));
   6052   if (AllocationSite::GetMode(from_kind, to_kind) == TRACK_ALLOCATION_SITE) {
   6053     TrapAllocationMemento(object, bailout);
   6054   }
   6055 
   6056   if (!IsSimpleMapChangeTransition(from_kind, to_kind)) {
   6057     Comment("Non-simple map transition");
   6058     Node* elements = LoadElements(object);
   6059 
   6060     Node* empty_fixed_array =
   6061         HeapConstant(isolate()->factory()->empty_fixed_array());
   6062 
   6063     Label done(this);
   6064     GotoIf(WordEqual(elements, empty_fixed_array), &done);
   6065 
   6066     // TODO(ishell): Use OptimalParameterMode().
   6067     ParameterMode mode = INTPTR_PARAMETERS;
   6068     Node* elements_length = SmiUntag(LoadFixedArrayBaseLength(elements));
   6069     Node* array_length =
   6070         is_jsarray ? SmiUntag(LoadObjectField(object, JSArray::kLengthOffset))
   6071                    : elements_length;
   6072 
   6073     GrowElementsCapacity(object, elements, from_kind, to_kind, array_length,
   6074                          elements_length, mode, bailout);
   6075     Goto(&done);
   6076     Bind(&done);
   6077   }
   6078 
   6079   StoreMap(object, map);
   6080 }
   6081 
   6082 void CodeStubAssembler::TrapAllocationMemento(Node* object,
   6083                                               Label* memento_found) {
   6084   Comment("[ TrapAllocationMemento");
   6085   Label no_memento_found(this);
   6086   Label top_check(this), map_check(this);
   6087 
   6088   Node* new_space_top_address = ExternalConstant(
   6089       ExternalReference::new_space_allocation_top_address(isolate()));
   6090   const int kMementoMapOffset = JSArray::kSize;
   6091   const int kMementoLastWordOffset =
   6092       kMementoMapOffset + AllocationMemento::kSize - kPointerSize;
   6093 
   6094   // Bail out if the object is not in new space.
   6095   Node* object_word = BitcastTaggedToWord(object);
   6096   Node* object_page = PageFromAddress(object_word);
   6097   {
   6098     Node* page_flags = Load(MachineType::IntPtr(), object_page,
   6099                             IntPtrConstant(Page::kFlagsOffset));
   6100     GotoIf(WordEqual(WordAnd(page_flags,
   6101                              IntPtrConstant(MemoryChunk::kIsInNewSpaceMask)),
   6102                      IntPtrConstant(0)),
   6103            &no_memento_found);
   6104   }
   6105 
   6106   Node* memento_last_word = IntPtrAdd(
   6107       object_word, IntPtrConstant(kMementoLastWordOffset - kHeapObjectTag));
   6108   Node* memento_last_word_page = PageFromAddress(memento_last_word);
   6109 
   6110   Node* new_space_top = Load(MachineType::Pointer(), new_space_top_address);
   6111   Node* new_space_top_page = PageFromAddress(new_space_top);
   6112 
   6113   // If the object is in new space, we need to check whether respective
   6114   // potential memento object is on the same page as the current top.
   6115   GotoIf(WordEqual(memento_last_word_page, new_space_top_page), &top_check);
   6116 
   6117   // The object is on a different page than allocation top. Bail out if the
   6118   // object sits on the page boundary as no memento can follow and we cannot
   6119   // touch the memory following it.
   6120   Branch(WordEqual(object_page, memento_last_word_page), &map_check,
   6121          &no_memento_found);
   6122 
   6123   // If top is on the same page as the current object, we need to check whether
   6124   // we are below top.
   6125   Bind(&top_check);
   6126   {
   6127     Branch(UintPtrGreaterThanOrEqual(memento_last_word, new_space_top),
   6128            &no_memento_found, &map_check);
   6129   }
   6130 
   6131   // Memento map check.
   6132   Bind(&map_check);
   6133   {
   6134     Node* memento_map = LoadObjectField(object, kMementoMapOffset);
   6135     Branch(
   6136         WordEqual(memento_map, LoadRoot(Heap::kAllocationMementoMapRootIndex)),
   6137         memento_found, &no_memento_found);
   6138   }
   6139   Bind(&no_memento_found);
   6140   Comment("] TrapAllocationMemento");
   6141 }
   6142 
   6143 Node* CodeStubAssembler::PageFromAddress(Node* address) {
   6144   return WordAnd(address, IntPtrConstant(~Page::kPageAlignmentMask));
   6145 }
   6146 
   6147 Node* CodeStubAssembler::EnumLength(Node* map) {
   6148   CSA_ASSERT(this, IsMap(map));
   6149   Node* bitfield_3 = LoadMapBitField3(map);
   6150   Node* enum_length = DecodeWordFromWord32<Map::EnumLengthBits>(bitfield_3);
   6151   return SmiTag(enum_length);
   6152 }
   6153 
   6154 void CodeStubAssembler::CheckEnumCache(Node* receiver, Label* use_cache,
   6155                                        Label* use_runtime) {
   6156   Variable current_js_object(this, MachineRepresentation::kTagged, receiver);
   6157 
   6158   Variable current_map(this, MachineRepresentation::kTagged,
   6159                        LoadMap(current_js_object.value()));
   6160 
   6161   // These variables are updated in the loop below.
   6162   Variable* loop_vars[2] = {&current_js_object, &current_map};
   6163   Label loop(this, 2, loop_vars), next(this);
   6164 
   6165   // Check if the enum length field is properly initialized, indicating that
   6166   // there is an enum cache.
   6167   {
   6168     Node* invalid_enum_cache_sentinel =
   6169         SmiConstant(Smi::FromInt(kInvalidEnumCacheSentinel));
   6170     Node* enum_length = EnumLength(current_map.value());
   6171     Branch(WordEqual(enum_length, invalid_enum_cache_sentinel), use_runtime,
   6172            &loop);
   6173   }
   6174 
   6175   // Check that there are no elements. |current_js_object| contains
   6176   // the current JS object we've reached through the prototype chain.
   6177   Bind(&loop);
   6178   {
   6179     Label if_elements(this), if_no_elements(this);
   6180     Node* elements = LoadElements(current_js_object.value());
   6181     Node* empty_fixed_array = LoadRoot(Heap::kEmptyFixedArrayRootIndex);
   6182     // Check that there are no elements.
   6183     Branch(WordEqual(elements, empty_fixed_array), &if_no_elements,
   6184            &if_elements);
   6185     Bind(&if_elements);
   6186     {
   6187       // Second chance, the object may be using the empty slow element
   6188       // dictionary.
   6189       Node* slow_empty_dictionary =
   6190           LoadRoot(Heap::kEmptySlowElementDictionaryRootIndex);
   6191       Branch(WordNotEqual(elements, slow_empty_dictionary), use_runtime,
   6192              &if_no_elements);
   6193     }
   6194 
   6195     Bind(&if_no_elements);
   6196     {
   6197       // Update map prototype.
   6198       current_js_object.Bind(LoadMapPrototype(current_map.value()));
   6199       Branch(WordEqual(current_js_object.value(), NullConstant()), use_cache,
   6200              &next);
   6201     }
   6202   }
   6203 
   6204   Bind(&next);
   6205   {
   6206     // For all objects but the receiver, check that the cache is empty.
   6207     current_map.Bind(LoadMap(current_js_object.value()));
   6208     Node* enum_length = EnumLength(current_map.value());
   6209     Node* zero_constant = SmiConstant(Smi::kZero);
   6210     Branch(WordEqual(enum_length, zero_constant), &loop, use_runtime);
   6211   }
   6212 }
   6213 
   6214 Node* CodeStubAssembler::CreateAllocationSiteInFeedbackVector(
   6215     Node* feedback_vector, Node* slot) {
   6216   Node* size = IntPtrConstant(AllocationSite::kSize);
   6217   Node* site = Allocate(size, CodeStubAssembler::kPretenured);
   6218 
   6219   StoreMap(site, AllocationSiteMapConstant());
   6220   Node* kind = SmiConstant(GetInitialFastElementsKind());
   6221   StoreObjectFieldNoWriteBarrier(site, AllocationSite::kTransitionInfoOffset,
   6222                                  kind);
   6223 
   6224   // Unlike literals, constructed arrays don't have nested sites
   6225   Node* zero = SmiConstant(0);
   6226   StoreObjectFieldNoWriteBarrier(site, AllocationSite::kNestedSiteOffset, zero);
   6227 
   6228   // Pretenuring calculation field.
   6229   StoreObjectFieldNoWriteBarrier(site, AllocationSite::kPretenureDataOffset,
   6230                                  zero);
   6231 
   6232   // Pretenuring memento creation count field.
   6233   StoreObjectFieldNoWriteBarrier(
   6234       site, AllocationSite::kPretenureCreateCountOffset, zero);
   6235 
   6236   // Store an empty fixed array for the code dependency.
   6237   StoreObjectFieldRoot(site, AllocationSite::kDependentCodeOffset,
   6238                        Heap::kEmptyFixedArrayRootIndex);
   6239 
   6240   // Link the object to the allocation site list
   6241   Node* site_list = ExternalConstant(
   6242       ExternalReference::allocation_sites_list_address(isolate()));
   6243   Node* next_site = LoadBufferObject(site_list, 0);
   6244 
   6245   // TODO(mvstanton): This is a store to a weak pointer, which we may want to
   6246   // mark as such in order to skip the write barrier, once we have a unified
   6247   // system for weakness. For now we decided to keep it like this because having
   6248   // an initial write barrier backed store makes this pointer strong until the
   6249   // next GC, and allocation sites are designed to survive several GCs anyway.
   6250   StoreObjectField(site, AllocationSite::kWeakNextOffset, next_site);
   6251   StoreNoWriteBarrier(MachineRepresentation::kTagged, site_list, site);
   6252 
   6253   StoreFixedArrayElement(feedback_vector, slot, site, UPDATE_WRITE_BARRIER, 0,
   6254                          CodeStubAssembler::SMI_PARAMETERS);
   6255   return site;
   6256 }
   6257 
   6258 Node* CodeStubAssembler::CreateWeakCellInFeedbackVector(Node* feedback_vector,
   6259                                                         Node* slot,
   6260                                                         Node* value) {
   6261   Node* size = IntPtrConstant(WeakCell::kSize);
   6262   Node* cell = Allocate(size, CodeStubAssembler::kPretenured);
   6263 
   6264   // Initialize the WeakCell.
   6265   DCHECK(Heap::RootIsImmortalImmovable(Heap::kWeakCellMapRootIndex));
   6266   StoreMapNoWriteBarrier(cell, Heap::kWeakCellMapRootIndex);
   6267   StoreObjectField(cell, WeakCell::kValueOffset, value);
   6268   StoreObjectFieldRoot(cell, WeakCell::kNextOffset,
   6269                        Heap::kTheHoleValueRootIndex);
   6270 
   6271   // Store the WeakCell in the feedback vector.
   6272   StoreFixedArrayElement(feedback_vector, slot, cell, UPDATE_WRITE_BARRIER, 0,
   6273                          CodeStubAssembler::SMI_PARAMETERS);
   6274   return cell;
   6275 }
   6276 
   6277 Node* CodeStubAssembler::BuildFastLoop(
   6278     const CodeStubAssembler::VariableList& vars, Node* start_index,
   6279     Node* end_index, const FastLoopBody& body, int increment,
   6280     ParameterMode parameter_mode, IndexAdvanceMode advance_mode) {
   6281   MachineRepresentation index_rep = (parameter_mode == INTPTR_PARAMETERS)
   6282                                         ? MachineType::PointerRepresentation()
   6283                                         : MachineRepresentation::kTaggedSigned;
   6284   Variable var(this, index_rep, start_index);
   6285   VariableList vars_copy(vars, zone());
   6286   vars_copy.Add(&var, zone());
   6287   Label loop(this, vars_copy);
   6288   Label after_loop(this);
   6289   // Introduce an explicit second check of the termination condition before the
   6290   // loop that helps turbofan generate better code. If there's only a single
   6291   // check, then the CodeStubAssembler forces it to be at the beginning of the
   6292   // loop requiring a backwards branch at the end of the loop (it's not possible
   6293   // to force the loop header check at the end of the loop and branch forward to
   6294   // it from the pre-header). The extra branch is slower in the case that the
   6295   // loop actually iterates.
   6296   Branch(WordEqual(var.value(), end_index), &after_loop, &loop);
   6297   Bind(&loop);
   6298   {
   6299     if (advance_mode == IndexAdvanceMode::kPre) {
   6300       Increment(var, increment, parameter_mode);
   6301     }
   6302     body(var.value());
   6303     if (advance_mode == IndexAdvanceMode::kPost) {
   6304       Increment(var, increment, parameter_mode);
   6305     }
   6306     Branch(WordNotEqual(var.value(), end_index), &loop, &after_loop);
   6307   }
   6308   Bind(&after_loop);
   6309   return var.value();
   6310 }
   6311 
   6312 void CodeStubAssembler::BuildFastFixedArrayForEach(
   6313     const CodeStubAssembler::VariableList& vars, Node* fixed_array,
   6314     ElementsKind kind, Node* first_element_inclusive,
   6315     Node* last_element_exclusive, const FastFixedArrayForEachBody& body,
   6316     ParameterMode mode, ForEachDirection direction) {
   6317   STATIC_ASSERT(FixedArray::kHeaderSize == FixedDoubleArray::kHeaderSize);
   6318   int32_t first_val;
   6319   bool constant_first = ToInt32Constant(first_element_inclusive, first_val);
   6320   int32_t last_val;
   6321   bool constent_last = ToInt32Constant(last_element_exclusive, last_val);
   6322   if (constant_first && constent_last) {
   6323     int delta = last_val - first_val;
   6324     DCHECK(delta >= 0);
   6325     if (delta <= kElementLoopUnrollThreshold) {
   6326       if (direction == ForEachDirection::kForward) {
   6327         for (int i = first_val; i < last_val; ++i) {
   6328           Node* index = IntPtrConstant(i);
   6329           Node* offset =
   6330               ElementOffsetFromIndex(index, kind, INTPTR_PARAMETERS,
   6331                                      FixedArray::kHeaderSize - kHeapObjectTag);
   6332           body(fixed_array, offset);
   6333         }
   6334       } else {
   6335         for (int i = last_val - 1; i >= first_val; --i) {
   6336           Node* index = IntPtrConstant(i);
   6337           Node* offset =
   6338               ElementOffsetFromIndex(index, kind, INTPTR_PARAMETERS,
   6339                                      FixedArray::kHeaderSize - kHeapObjectTag);
   6340           body(fixed_array, offset);
   6341         }
   6342       }
   6343       return;
   6344     }
   6345   }
   6346 
   6347   Node* start =
   6348       ElementOffsetFromIndex(first_element_inclusive, kind, mode,
   6349                              FixedArray::kHeaderSize - kHeapObjectTag);
   6350   Node* limit =
   6351       ElementOffsetFromIndex(last_element_exclusive, kind, mode,
   6352                              FixedArray::kHeaderSize - kHeapObjectTag);
   6353   if (direction == ForEachDirection::kReverse) std::swap(start, limit);
   6354 
   6355   int increment = IsFastDoubleElementsKind(kind) ? kDoubleSize : kPointerSize;
   6356   BuildFastLoop(
   6357       vars, start, limit,
   6358       [fixed_array, &body](Node* offset) { body(fixed_array, offset); },
   6359       direction == ForEachDirection::kReverse ? -increment : increment,
   6360       INTPTR_PARAMETERS,
   6361       direction == ForEachDirection::kReverse ? IndexAdvanceMode::kPre
   6362                                               : IndexAdvanceMode::kPost);
   6363 }
   6364 
   6365 void CodeStubAssembler::GotoIfFixedArraySizeDoesntFitInNewSpace(
   6366     Node* element_count, Label* doesnt_fit, int base_size, ParameterMode mode) {
   6367   int max_newspace_parameters =
   6368       (kMaxRegularHeapObjectSize - base_size) / kPointerSize;
   6369   GotoIf(IntPtrOrSmiGreaterThan(
   6370              element_count, IntPtrOrSmiConstant(max_newspace_parameters, mode),
   6371              mode),
   6372          doesnt_fit);
   6373 }
   6374 
   6375 void CodeStubAssembler::InitializeFieldsWithRoot(
   6376     Node* object, Node* start_offset, Node* end_offset,
   6377     Heap::RootListIndex root_index) {
   6378   start_offset = IntPtrAdd(start_offset, IntPtrConstant(-kHeapObjectTag));
   6379   end_offset = IntPtrAdd(end_offset, IntPtrConstant(-kHeapObjectTag));
   6380   Node* root_value = LoadRoot(root_index);
   6381   BuildFastLoop(end_offset, start_offset,
   6382                 [this, object, root_value](Node* current) {
   6383                   StoreNoWriteBarrier(MachineRepresentation::kTagged, object,
   6384                                       current, root_value);
   6385                 },
   6386                 -kPointerSize, INTPTR_PARAMETERS,
   6387                 CodeStubAssembler::IndexAdvanceMode::kPre);
   6388 }
   6389 
   6390 void CodeStubAssembler::BranchIfNumericRelationalComparison(
   6391     RelationalComparisonMode mode, Node* lhs, Node* rhs, Label* if_true,
   6392     Label* if_false) {
   6393   Label end(this);
   6394   Variable result(this, MachineRepresentation::kTagged);
   6395 
   6396   // Shared entry for floating point comparison.
   6397   Label do_fcmp(this);
   6398   Variable var_fcmp_lhs(this, MachineRepresentation::kFloat64),
   6399       var_fcmp_rhs(this, MachineRepresentation::kFloat64);
   6400 
   6401   // Check if the {lhs} is a Smi or a HeapObject.
   6402   Label if_lhsissmi(this), if_lhsisnotsmi(this);
   6403   Branch(TaggedIsSmi(lhs), &if_lhsissmi, &if_lhsisnotsmi);
   6404 
   6405   Bind(&if_lhsissmi);
   6406   {
   6407     // Check if {rhs} is a Smi or a HeapObject.
   6408     Label if_rhsissmi(this), if_rhsisnotsmi(this);
   6409     Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi);
   6410 
   6411     Bind(&if_rhsissmi);
   6412     {
   6413       // Both {lhs} and {rhs} are Smi, so just perform a fast Smi comparison.
   6414       switch (mode) {
   6415         case kLessThan:
   6416           BranchIfSmiLessThan(lhs, rhs, if_true, if_false);
   6417           break;
   6418         case kLessThanOrEqual:
   6419           BranchIfSmiLessThanOrEqual(lhs, rhs, if_true, if_false);
   6420           break;
   6421         case kGreaterThan:
   6422           BranchIfSmiLessThan(rhs, lhs, if_true, if_false);
   6423           break;
   6424         case kGreaterThanOrEqual:
   6425           BranchIfSmiLessThanOrEqual(rhs, lhs, if_true, if_false);
   6426           break;
   6427       }
   6428     }
   6429 
   6430     Bind(&if_rhsisnotsmi);
   6431     {
   6432       CSA_ASSERT(this, IsHeapNumberMap(LoadMap(rhs)));
   6433       // Convert the {lhs} and {rhs} to floating point values, and
   6434       // perform a floating point comparison.
   6435       var_fcmp_lhs.Bind(SmiToFloat64(lhs));
   6436       var_fcmp_rhs.Bind(LoadHeapNumberValue(rhs));
   6437       Goto(&do_fcmp);
   6438     }
   6439   }
   6440 
   6441   Bind(&if_lhsisnotsmi);
   6442   {
   6443     CSA_ASSERT(this, IsHeapNumberMap(LoadMap(lhs)));
   6444 
   6445     // Check if {rhs} is a Smi or a HeapObject.
   6446     Label if_rhsissmi(this), if_rhsisnotsmi(this);
   6447     Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi);
   6448 
   6449     Bind(&if_rhsissmi);
   6450     {
   6451       // Convert the {lhs} and {rhs} to floating point values, and
   6452       // perform a floating point comparison.
   6453       var_fcmp_lhs.Bind(LoadHeapNumberValue(lhs));
   6454       var_fcmp_rhs.Bind(SmiToFloat64(rhs));
   6455       Goto(&do_fcmp);
   6456     }
   6457 
   6458     Bind(&if_rhsisnotsmi);
   6459     {
   6460       CSA_ASSERT(this, IsHeapNumberMap(LoadMap(rhs)));
   6461 
   6462       // Convert the {lhs} and {rhs} to floating point values, and
   6463       // perform a floating point comparison.
   6464       var_fcmp_lhs.Bind(LoadHeapNumberValue(lhs));
   6465       var_fcmp_rhs.Bind(LoadHeapNumberValue(rhs));
   6466       Goto(&do_fcmp);
   6467     }
   6468   }
   6469 
   6470   Bind(&do_fcmp);
   6471   {
   6472     // Load the {lhs} and {rhs} floating point values.
   6473     Node* lhs = var_fcmp_lhs.value();
   6474     Node* rhs = var_fcmp_rhs.value();
   6475 
   6476     // Perform a fast floating point comparison.
   6477     switch (mode) {
   6478       case kLessThan:
   6479         Branch(Float64LessThan(lhs, rhs), if_true, if_false);
   6480         break;
   6481       case kLessThanOrEqual:
   6482         Branch(Float64LessThanOrEqual(lhs, rhs), if_true, if_false);
   6483         break;
   6484       case kGreaterThan:
   6485         Branch(Float64GreaterThan(lhs, rhs), if_true, if_false);
   6486         break;
   6487       case kGreaterThanOrEqual:
   6488         Branch(Float64GreaterThanOrEqual(lhs, rhs), if_true, if_false);
   6489         break;
   6490     }
   6491   }
   6492 }
   6493 
   6494 void CodeStubAssembler::GotoUnlessNumberLessThan(Node* lhs, Node* rhs,
   6495                                                  Label* if_false) {
   6496   Label if_true(this);
   6497   BranchIfNumericRelationalComparison(kLessThan, lhs, rhs, &if_true, if_false);
   6498   Bind(&if_true);
   6499 }
   6500 
   6501 Node* CodeStubAssembler::RelationalComparison(RelationalComparisonMode mode,
   6502                                               Node* lhs, Node* rhs,
   6503                                               Node* context) {
   6504   Label return_true(this), return_false(this), end(this);
   6505   Variable result(this, MachineRepresentation::kTagged);
   6506 
   6507   // Shared entry for floating point comparison.
   6508   Label do_fcmp(this);
   6509   Variable var_fcmp_lhs(this, MachineRepresentation::kFloat64),
   6510       var_fcmp_rhs(this, MachineRepresentation::kFloat64);
   6511 
   6512   // We might need to loop several times due to ToPrimitive and/or ToNumber
   6513   // conversions.
   6514   Variable var_lhs(this, MachineRepresentation::kTagged, lhs),
   6515       var_rhs(this, MachineRepresentation::kTagged, rhs);
   6516   Variable* loop_vars[2] = {&var_lhs, &var_rhs};
   6517   Label loop(this, 2, loop_vars);
   6518   Goto(&loop);
   6519   Bind(&loop);
   6520   {
   6521     // Load the current {lhs} and {rhs} values.
   6522     lhs = var_lhs.value();
   6523     rhs = var_rhs.value();
   6524 
   6525     // Check if the {lhs} is a Smi or a HeapObject.
   6526     Label if_lhsissmi(this), if_lhsisnotsmi(this);
   6527     Branch(TaggedIsSmi(lhs), &if_lhsissmi, &if_lhsisnotsmi);
   6528 
   6529     Bind(&if_lhsissmi);
   6530     {
   6531       // Check if {rhs} is a Smi or a HeapObject.
   6532       Label if_rhsissmi(this), if_rhsisnotsmi(this);
   6533       Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi);
   6534 
   6535       Bind(&if_rhsissmi);
   6536       {
   6537         // Both {lhs} and {rhs} are Smi, so just perform a fast Smi comparison.
   6538         switch (mode) {
   6539           case kLessThan:
   6540             BranchIfSmiLessThan(lhs, rhs, &return_true, &return_false);
   6541             break;
   6542           case kLessThanOrEqual:
   6543             BranchIfSmiLessThanOrEqual(lhs, rhs, &return_true, &return_false);
   6544             break;
   6545           case kGreaterThan:
   6546             BranchIfSmiLessThan(rhs, lhs, &return_true, &return_false);
   6547             break;
   6548           case kGreaterThanOrEqual:
   6549             BranchIfSmiLessThanOrEqual(rhs, lhs, &return_true, &return_false);
   6550             break;
   6551         }
   6552       }
   6553 
   6554       Bind(&if_rhsisnotsmi);
   6555       {
   6556         // Load the map of {rhs}.
   6557         Node* rhs_map = LoadMap(rhs);
   6558 
   6559         // Check if the {rhs} is a HeapNumber.
   6560         Label if_rhsisnumber(this), if_rhsisnotnumber(this, Label::kDeferred);
   6561         Branch(IsHeapNumberMap(rhs_map), &if_rhsisnumber, &if_rhsisnotnumber);
   6562 
   6563         Bind(&if_rhsisnumber);
   6564         {
   6565           // Convert the {lhs} and {rhs} to floating point values, and
   6566           // perform a floating point comparison.
   6567           var_fcmp_lhs.Bind(SmiToFloat64(lhs));
   6568           var_fcmp_rhs.Bind(LoadHeapNumberValue(rhs));
   6569           Goto(&do_fcmp);
   6570         }
   6571 
   6572         Bind(&if_rhsisnotnumber);
   6573         {
   6574           // Convert the {rhs} to a Number; we don't need to perform the
   6575           // dedicated ToPrimitive(rhs, hint Number) operation, as the
   6576           // ToNumber(rhs) will by itself already invoke ToPrimitive with
   6577           // a Number hint.
   6578           Callable callable = CodeFactory::NonNumberToNumber(isolate());
   6579           var_rhs.Bind(CallStub(callable, context, rhs));
   6580           Goto(&loop);
   6581         }
   6582       }
   6583     }
   6584 
   6585     Bind(&if_lhsisnotsmi);
   6586     {
   6587       // Load the map of {lhs}.
   6588       Node* lhs_map = LoadMap(lhs);
   6589 
   6590       // Check if {rhs} is a Smi or a HeapObject.
   6591       Label if_rhsissmi(this), if_rhsisnotsmi(this);
   6592       Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi);
   6593 
   6594       Bind(&if_rhsissmi);
   6595       {
   6596         // Check if the {lhs} is a HeapNumber.
   6597         Label if_lhsisnumber(this), if_lhsisnotnumber(this, Label::kDeferred);
   6598         Branch(IsHeapNumberMap(lhs_map), &if_lhsisnumber, &if_lhsisnotnumber);
   6599 
   6600         Bind(&if_lhsisnumber);
   6601         {
   6602           // Convert the {lhs} and {rhs} to floating point values, and
   6603           // perform a floating point comparison.
   6604           var_fcmp_lhs.Bind(LoadHeapNumberValue(lhs));
   6605           var_fcmp_rhs.Bind(SmiToFloat64(rhs));
   6606           Goto(&do_fcmp);
   6607         }
   6608 
   6609         Bind(&if_lhsisnotnumber);
   6610         {
   6611           // Convert the {lhs} to a Number; we don't need to perform the
   6612           // dedicated ToPrimitive(lhs, hint Number) operation, as the
   6613           // ToNumber(lhs) will by itself already invoke ToPrimitive with
   6614           // a Number hint.
   6615           Callable callable = CodeFactory::NonNumberToNumber(isolate());
   6616           var_lhs.Bind(CallStub(callable, context, lhs));
   6617           Goto(&loop);
   6618         }
   6619       }
   6620 
   6621       Bind(&if_rhsisnotsmi);
   6622       {
   6623         // Load the map of {rhs}.
   6624         Node* rhs_map = LoadMap(rhs);
   6625 
   6626         // Check if {lhs} is a HeapNumber.
   6627         Label if_lhsisnumber(this), if_lhsisnotnumber(this);
   6628         Branch(IsHeapNumberMap(lhs_map), &if_lhsisnumber, &if_lhsisnotnumber);
   6629 
   6630         Bind(&if_lhsisnumber);
   6631         {
   6632           // Check if {rhs} is also a HeapNumber.
   6633           Label if_rhsisnumber(this), if_rhsisnotnumber(this, Label::kDeferred);
   6634           Branch(WordEqual(lhs_map, rhs_map), &if_rhsisnumber,
   6635                  &if_rhsisnotnumber);
   6636 
   6637           Bind(&if_rhsisnumber);
   6638           {
   6639             // Convert the {lhs} and {rhs} to floating point values, and
   6640             // perform a floating point comparison.
   6641             var_fcmp_lhs.Bind(LoadHeapNumberValue(lhs));
   6642             var_fcmp_rhs.Bind(LoadHeapNumberValue(rhs));
   6643             Goto(&do_fcmp);
   6644           }
   6645 
   6646           Bind(&if_rhsisnotnumber);
   6647           {
   6648             // Convert the {rhs} to a Number; we don't need to perform
   6649             // dedicated ToPrimitive(rhs, hint Number) operation, as the
   6650             // ToNumber(rhs) will by itself already invoke ToPrimitive with
   6651             // a Number hint.
   6652             Callable callable = CodeFactory::NonNumberToNumber(isolate());
   6653             var_rhs.Bind(CallStub(callable, context, rhs));
   6654             Goto(&loop);
   6655           }
   6656         }
   6657 
   6658         Bind(&if_lhsisnotnumber);
   6659         {
   6660           // Load the instance type of {lhs}.
   6661           Node* lhs_instance_type = LoadMapInstanceType(lhs_map);
   6662 
   6663           // Check if {lhs} is a String.
   6664           Label if_lhsisstring(this), if_lhsisnotstring(this, Label::kDeferred);
   6665           Branch(IsStringInstanceType(lhs_instance_type), &if_lhsisstring,
   6666                  &if_lhsisnotstring);
   6667 
   6668           Bind(&if_lhsisstring);
   6669           {
   6670             // Load the instance type of {rhs}.
   6671             Node* rhs_instance_type = LoadMapInstanceType(rhs_map);
   6672 
   6673             // Check if {rhs} is also a String.
   6674             Label if_rhsisstring(this, Label::kDeferred),
   6675                 if_rhsisnotstring(this, Label::kDeferred);
   6676             Branch(IsStringInstanceType(rhs_instance_type), &if_rhsisstring,
   6677                    &if_rhsisnotstring);
   6678 
   6679             Bind(&if_rhsisstring);
   6680             {
   6681               // Both {lhs} and {rhs} are strings.
   6682               switch (mode) {
   6683                 case kLessThan:
   6684                   result.Bind(CallStub(CodeFactory::StringLessThan(isolate()),
   6685                                        context, lhs, rhs));
   6686                   Goto(&end);
   6687                   break;
   6688                 case kLessThanOrEqual:
   6689                   result.Bind(
   6690                       CallStub(CodeFactory::StringLessThanOrEqual(isolate()),
   6691                                context, lhs, rhs));
   6692                   Goto(&end);
   6693                   break;
   6694                 case kGreaterThan:
   6695                   result.Bind(
   6696                       CallStub(CodeFactory::StringGreaterThan(isolate()),
   6697                                context, lhs, rhs));
   6698                   Goto(&end);
   6699                   break;
   6700                 case kGreaterThanOrEqual:
   6701                   result.Bind(
   6702                       CallStub(CodeFactory::StringGreaterThanOrEqual(isolate()),
   6703                                context, lhs, rhs));
   6704                   Goto(&end);
   6705                   break;
   6706               }
   6707             }
   6708 
   6709             Bind(&if_rhsisnotstring);
   6710             {
   6711               // The {lhs} is a String, while {rhs} is neither a Number nor a
   6712               // String, so we need to call ToPrimitive(rhs, hint Number) if
   6713               // {rhs} is a receiver or ToNumber(lhs) and ToNumber(rhs) in the
   6714               // other cases.
   6715               STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
   6716               Label if_rhsisreceiver(this, Label::kDeferred),
   6717                   if_rhsisnotreceiver(this, Label::kDeferred);
   6718               Branch(IsJSReceiverInstanceType(rhs_instance_type),
   6719                      &if_rhsisreceiver, &if_rhsisnotreceiver);
   6720 
   6721               Bind(&if_rhsisreceiver);
   6722               {
   6723                 // Convert {rhs} to a primitive first passing Number hint.
   6724                 Callable callable = CodeFactory::NonPrimitiveToPrimitive(
   6725                     isolate(), ToPrimitiveHint::kNumber);
   6726                 var_rhs.Bind(CallStub(callable, context, rhs));
   6727                 Goto(&loop);
   6728               }
   6729 
   6730               Bind(&if_rhsisnotreceiver);
   6731               {
   6732                 // Convert both {lhs} and {rhs} to Number.
   6733                 Callable callable = CodeFactory::ToNumber(isolate());
   6734                 var_lhs.Bind(CallStub(callable, context, lhs));
   6735                 var_rhs.Bind(CallStub(callable, context, rhs));
   6736                 Goto(&loop);
   6737               }
   6738             }
   6739           }
   6740 
   6741           Bind(&if_lhsisnotstring);
   6742           {
   6743             // The {lhs} is neither a Number nor a String, so we need to call
   6744             // ToPrimitive(lhs, hint Number) if {lhs} is a receiver or
   6745             // ToNumber(lhs) and ToNumber(rhs) in the other cases.
   6746             STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
   6747             Label if_lhsisreceiver(this, Label::kDeferred),
   6748                 if_lhsisnotreceiver(this, Label::kDeferred);
   6749             Branch(IsJSReceiverInstanceType(lhs_instance_type),
   6750                    &if_lhsisreceiver, &if_lhsisnotreceiver);
   6751 
   6752             Bind(&if_lhsisreceiver);
   6753             {
   6754               // Convert {lhs} to a primitive first passing Number hint.
   6755               Callable callable = CodeFactory::NonPrimitiveToPrimitive(
   6756                   isolate(), ToPrimitiveHint::kNumber);
   6757               var_lhs.Bind(CallStub(callable, context, lhs));
   6758               Goto(&loop);
   6759             }
   6760 
   6761             Bind(&if_lhsisnotreceiver);
   6762             {
   6763               // Convert both {lhs} and {rhs} to Number.
   6764               Callable callable = CodeFactory::ToNumber(isolate());
   6765               var_lhs.Bind(CallStub(callable, context, lhs));
   6766               var_rhs.Bind(CallStub(callable, context, rhs));
   6767               Goto(&loop);
   6768             }
   6769           }
   6770         }
   6771       }
   6772     }
   6773   }
   6774 
   6775   Bind(&do_fcmp);
   6776   {
   6777     // Load the {lhs} and {rhs} floating point values.
   6778     Node* lhs = var_fcmp_lhs.value();
   6779     Node* rhs = var_fcmp_rhs.value();
   6780 
   6781     // Perform a fast floating point comparison.
   6782     switch (mode) {
   6783       case kLessThan:
   6784         Branch(Float64LessThan(lhs, rhs), &return_true, &return_false);
   6785         break;
   6786       case kLessThanOrEqual:
   6787         Branch(Float64LessThanOrEqual(lhs, rhs), &return_true, &return_false);
   6788         break;
   6789       case kGreaterThan:
   6790         Branch(Float64GreaterThan(lhs, rhs), &return_true, &return_false);
   6791         break;
   6792       case kGreaterThanOrEqual:
   6793         Branch(Float64GreaterThanOrEqual(lhs, rhs), &return_true,
   6794                &return_false);
   6795         break;
   6796     }
   6797   }
   6798 
   6799   Bind(&return_true);
   6800   {
   6801     result.Bind(BooleanConstant(true));
   6802     Goto(&end);
   6803   }
   6804 
   6805   Bind(&return_false);
   6806   {
   6807     result.Bind(BooleanConstant(false));
   6808     Goto(&end);
   6809   }
   6810 
   6811   Bind(&end);
   6812   return result.value();
   6813 }
   6814 
   6815 namespace {
   6816 
   6817 void GenerateEqual_Same(CodeStubAssembler* assembler, Node* value,
   6818                         CodeStubAssembler::Label* if_equal,
   6819                         CodeStubAssembler::Label* if_notequal) {
   6820   // In case of abstract or strict equality checks, we need additional checks
   6821   // for NaN values because they are not considered equal, even if both the
   6822   // left and the right hand side reference exactly the same value.
   6823 
   6824   typedef CodeStubAssembler::Label Label;
   6825 
   6826   // Check if {value} is a Smi or a HeapObject.
   6827   Label if_valueissmi(assembler), if_valueisnotsmi(assembler);
   6828   assembler->Branch(assembler->TaggedIsSmi(value), &if_valueissmi,
   6829                     &if_valueisnotsmi);
   6830 
   6831   assembler->Bind(&if_valueisnotsmi);
   6832   {
   6833     // Load the map of {value}.
   6834     Node* value_map = assembler->LoadMap(value);
   6835 
   6836     // Check if {value} (and therefore {rhs}) is a HeapNumber.
   6837     Label if_valueisnumber(assembler), if_valueisnotnumber(assembler);
   6838     assembler->Branch(assembler->IsHeapNumberMap(value_map), &if_valueisnumber,
   6839                       &if_valueisnotnumber);
   6840 
   6841     assembler->Bind(&if_valueisnumber);
   6842     {
   6843       // Convert {value} (and therefore {rhs}) to floating point value.
   6844       Node* value_value = assembler->LoadHeapNumberValue(value);
   6845 
   6846       // Check if the HeapNumber value is a NaN.
   6847       assembler->BranchIfFloat64IsNaN(value_value, if_notequal, if_equal);
   6848     }
   6849 
   6850     assembler->Bind(&if_valueisnotnumber);
   6851     assembler->Goto(if_equal);
   6852   }
   6853 
   6854   assembler->Bind(&if_valueissmi);
   6855   assembler->Goto(if_equal);
   6856 }
   6857 }  // namespace
   6858 
   6859 // ES6 section 7.2.12 Abstract Equality Comparison
   6860 Node* CodeStubAssembler::Equal(ResultMode mode, Node* lhs, Node* rhs,
   6861                                Node* context) {
   6862   // This is a slightly optimized version of Object::Equals represented as
   6863   // scheduled TurboFan graph utilizing the CodeStubAssembler. Whenever you
   6864   // change something functionality wise in here, remember to update the
   6865   // Object::Equals method as well.
   6866 
   6867   Label if_equal(this), if_notequal(this),
   6868       do_rhsstringtonumber(this, Label::kDeferred), end(this);
   6869   Variable result(this, MachineRepresentation::kTagged);
   6870 
   6871   // Shared entry for floating point comparison.
   6872   Label do_fcmp(this);
   6873   Variable var_fcmp_lhs(this, MachineRepresentation::kFloat64),
   6874       var_fcmp_rhs(this, MachineRepresentation::kFloat64);
   6875 
   6876   // We might need to loop several times due to ToPrimitive and/or ToNumber
   6877   // conversions.
   6878   Variable var_lhs(this, MachineRepresentation::kTagged, lhs),
   6879       var_rhs(this, MachineRepresentation::kTagged, rhs);
   6880   Variable* loop_vars[2] = {&var_lhs, &var_rhs};
   6881   Label loop(this, 2, loop_vars);
   6882   Goto(&loop);
   6883   Bind(&loop);
   6884   {
   6885     // Load the current {lhs} and {rhs} values.
   6886     lhs = var_lhs.value();
   6887     rhs = var_rhs.value();
   6888 
   6889     // Check if {lhs} and {rhs} refer to the same object.
   6890     Label if_same(this), if_notsame(this);
   6891     Branch(WordEqual(lhs, rhs), &if_same, &if_notsame);
   6892 
   6893     Bind(&if_same);
   6894     {
   6895       // The {lhs} and {rhs} reference the exact same value, yet we need special
   6896       // treatment for HeapNumber, as NaN is not equal to NaN.
   6897       GenerateEqual_Same(this, lhs, &if_equal, &if_notequal);
   6898     }
   6899 
   6900     Bind(&if_notsame);
   6901     {
   6902       // Check if {lhs} is a Smi or a HeapObject.
   6903       Label if_lhsissmi(this), if_lhsisnotsmi(this);
   6904       Branch(TaggedIsSmi(lhs), &if_lhsissmi, &if_lhsisnotsmi);
   6905 
   6906       Bind(&if_lhsissmi);
   6907       {
   6908         // Check if {rhs} is a Smi or a HeapObject.
   6909         Label if_rhsissmi(this), if_rhsisnotsmi(this);
   6910         Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi);
   6911 
   6912         Bind(&if_rhsissmi);
   6913         // We have already checked for {lhs} and {rhs} being the same value, so
   6914         // if both are Smis when we get here they must not be equal.
   6915         Goto(&if_notequal);
   6916 
   6917         Bind(&if_rhsisnotsmi);
   6918         {
   6919           // Load the map of {rhs}.
   6920           Node* rhs_map = LoadMap(rhs);
   6921 
   6922           // Check if {rhs} is a HeapNumber.
   6923           Label if_rhsisnumber(this), if_rhsisnotnumber(this);
   6924           Branch(IsHeapNumberMap(rhs_map), &if_rhsisnumber, &if_rhsisnotnumber);
   6925 
   6926           Bind(&if_rhsisnumber);
   6927           {
   6928             // Convert {lhs} and {rhs} to floating point values, and
   6929             // perform a floating point comparison.
   6930             var_fcmp_lhs.Bind(SmiToFloat64(lhs));
   6931             var_fcmp_rhs.Bind(LoadHeapNumberValue(rhs));
   6932             Goto(&do_fcmp);
   6933           }
   6934 
   6935           Bind(&if_rhsisnotnumber);
   6936           {
   6937             // Load the instance type of the {rhs}.
   6938             Node* rhs_instance_type = LoadMapInstanceType(rhs_map);
   6939 
   6940             // Check if the {rhs} is a String.
   6941             Label if_rhsisstring(this, Label::kDeferred),
   6942                 if_rhsisnotstring(this);
   6943             Branch(IsStringInstanceType(rhs_instance_type), &if_rhsisstring,
   6944                    &if_rhsisnotstring);
   6945 
   6946             Bind(&if_rhsisstring);
   6947             {
   6948               // The {rhs} is a String and the {lhs} is a Smi; we need
   6949               // to convert the {rhs} to a Number and compare the output to
   6950               // the Number on the {lhs}.
   6951               Goto(&do_rhsstringtonumber);
   6952             }
   6953 
   6954             Bind(&if_rhsisnotstring);
   6955             {
   6956               // Check if the {rhs} is a Boolean.
   6957               Label if_rhsisboolean(this), if_rhsisnotboolean(this);
   6958               Branch(IsBooleanMap(rhs_map), &if_rhsisboolean,
   6959                      &if_rhsisnotboolean);
   6960 
   6961               Bind(&if_rhsisboolean);
   6962               {
   6963                 // The {rhs} is a Boolean, load its number value.
   6964                 var_rhs.Bind(LoadObjectField(rhs, Oddball::kToNumberOffset));
   6965                 Goto(&loop);
   6966               }
   6967 
   6968               Bind(&if_rhsisnotboolean);
   6969               {
   6970                 // Check if the {rhs} is a Receiver.
   6971                 STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE);
   6972                 Label if_rhsisreceiver(this, Label::kDeferred),
   6973                     if_rhsisnotreceiver(this);
   6974                 Branch(IsJSReceiverInstanceType(rhs_instance_type),
   6975                        &if_rhsisreceiver, &if_rhsisnotreceiver);
   6976 
   6977                 Bind(&if_rhsisreceiver);
   6978                 {
   6979                   // Convert {rhs} to a primitive first (passing no hint).
   6980                   Callable callable =
   6981                       CodeFactory::NonPrimitiveToPrimitive(isolate());
   6982                   var_rhs.Bind(CallStub(callable, context, rhs));
   6983                   Goto(&loop);
   6984                 }
   6985 
   6986                 Bind(&if_rhsisnotreceiver);
   6987                 Goto(&if_notequal);
   6988               }
   6989             }
   6990           }
   6991         }
   6992       }
   6993 
   6994       Bind(&if_lhsisnotsmi);
   6995       {
   6996         // Check if {rhs} is a Smi or a HeapObject.
   6997         Label if_rhsissmi(this), if_rhsisnotsmi(this);
   6998         Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi);
   6999 
   7000         Bind(&if_rhsissmi);
   7001         {
   7002           // The {lhs} is a HeapObject and the {rhs} is a Smi; swapping {lhs}
   7003           // and {rhs} is not observable and doesn't matter for the result, so
   7004           // we can just swap them and use the Smi handling above (for {lhs}
   7005           // being a Smi).
   7006           var_lhs.Bind(rhs);
   7007           var_rhs.Bind(lhs);
   7008           Goto(&loop);
   7009         }
   7010 
   7011         Bind(&if_rhsisnotsmi);
   7012         {
   7013           Label if_lhsisstring(this), if_lhsisnumber(this),
   7014               if_lhsissymbol(this), if_lhsisoddball(this),
   7015               if_lhsisreceiver(this);
   7016 
   7017           // Both {lhs} and {rhs} are HeapObjects, load their maps
   7018           // and their instance types.
   7019           Node* lhs_map = LoadMap(lhs);
   7020           Node* rhs_map = LoadMap(rhs);
   7021 
   7022           // Load the instance types of {lhs} and {rhs}.
   7023           Node* lhs_instance_type = LoadMapInstanceType(lhs_map);
   7024           Node* rhs_instance_type = LoadMapInstanceType(rhs_map);
   7025 
   7026           // Dispatch based on the instance type of {lhs}.
   7027           size_t const kNumCases = FIRST_NONSTRING_TYPE + 3;
   7028           Label* case_labels[kNumCases];
   7029           int32_t case_values[kNumCases];
   7030           for (int32_t i = 0; i < FIRST_NONSTRING_TYPE; ++i) {
   7031             case_labels[i] = new Label(this);
   7032             case_values[i] = i;
   7033           }
   7034           case_labels[FIRST_NONSTRING_TYPE + 0] = &if_lhsisnumber;
   7035           case_values[FIRST_NONSTRING_TYPE + 0] = HEAP_NUMBER_TYPE;
   7036           case_labels[FIRST_NONSTRING_TYPE + 1] = &if_lhsissymbol;
   7037           case_values[FIRST_NONSTRING_TYPE + 1] = SYMBOL_TYPE;
   7038           case_labels[FIRST_NONSTRING_TYPE + 2] = &if_lhsisoddball;
   7039           case_values[FIRST_NONSTRING_TYPE + 2] = ODDBALL_TYPE;
   7040           Switch(lhs_instance_type, &if_lhsisreceiver, case_values, case_labels,
   7041                  arraysize(case_values));
   7042           for (int32_t i = 0; i < FIRST_NONSTRING_TYPE; ++i) {
   7043             Bind(case_labels[i]);
   7044             Goto(&if_lhsisstring);
   7045             delete case_labels[i];
   7046           }
   7047 
   7048           Bind(&if_lhsisstring);
   7049           {
   7050             // Check if {rhs} is also a String.
   7051             Label if_rhsisstring(this, Label::kDeferred),
   7052                 if_rhsisnotstring(this);
   7053             Branch(IsStringInstanceType(rhs_instance_type), &if_rhsisstring,
   7054                    &if_rhsisnotstring);
   7055 
   7056             Bind(&if_rhsisstring);
   7057             {
   7058               // Both {lhs} and {rhs} are of type String, just do the
   7059               // string comparison then.
   7060               Callable callable = (mode == kDontNegateResult)
   7061                                       ? CodeFactory::StringEqual(isolate())
   7062                                       : CodeFactory::StringNotEqual(isolate());
   7063               result.Bind(CallStub(callable, context, lhs, rhs));
   7064               Goto(&end);
   7065             }
   7066 
   7067             Bind(&if_rhsisnotstring);
   7068             {
   7069               // The {lhs} is a String and the {rhs} is some other HeapObject.
   7070               // Swapping {lhs} and {rhs} is not observable and doesn't matter
   7071               // for the result, so we can just swap them and use the String
   7072               // handling below (for {rhs} being a String).
   7073               var_lhs.Bind(rhs);
   7074               var_rhs.Bind(lhs);
   7075               Goto(&loop);
   7076             }
   7077           }
   7078 
   7079           Bind(&if_lhsisnumber);
   7080           {
   7081             // Check if {rhs} is also a HeapNumber.
   7082             Label if_rhsisnumber(this), if_rhsisnotnumber(this);
   7083             Branch(Word32Equal(lhs_instance_type, rhs_instance_type),
   7084                    &if_rhsisnumber, &if_rhsisnotnumber);
   7085 
   7086             Bind(&if_rhsisnumber);
   7087             {
   7088               // Convert {lhs} and {rhs} to floating point values, and
   7089               // perform a floating point comparison.
   7090               var_fcmp_lhs.Bind(LoadHeapNumberValue(lhs));
   7091               var_fcmp_rhs.Bind(LoadHeapNumberValue(rhs));
   7092               Goto(&do_fcmp);
   7093             }
   7094 
   7095             Bind(&if_rhsisnotnumber);
   7096             {
   7097               // The {lhs} is a Number, the {rhs} is some other HeapObject.
   7098               Label if_rhsisstring(this, Label::kDeferred),
   7099                   if_rhsisnotstring(this);
   7100               Branch(IsStringInstanceType(rhs_instance_type), &if_rhsisstring,
   7101                      &if_rhsisnotstring);
   7102 
   7103               Bind(&if_rhsisstring);
   7104               {
   7105                 // The {rhs} is a String and the {lhs} is a HeapNumber; we need
   7106                 // to convert the {rhs} to a Number and compare the output to
   7107                 // the Number on the {lhs}.
   7108                 Goto(&do_rhsstringtonumber);
   7109               }
   7110 
   7111               Bind(&if_rhsisnotstring);
   7112               {
   7113                 // Check if the {rhs} is a JSReceiver.
   7114                 Label if_rhsisreceiver(this), if_rhsisnotreceiver(this);
   7115                 STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE);
   7116                 Branch(IsJSReceiverInstanceType(rhs_instance_type),
   7117                        &if_rhsisreceiver, &if_rhsisnotreceiver);
   7118 
   7119                 Bind(&if_rhsisreceiver);
   7120                 {
   7121                   // The {lhs} is a Primitive and the {rhs} is a JSReceiver.
   7122                   // Swapping {lhs} and {rhs} is not observable and doesn't
   7123                   // matter for the result, so we can just swap them and use
   7124                   // the JSReceiver handling below (for {lhs} being a
   7125                   // JSReceiver).
   7126                   var_lhs.Bind(rhs);
   7127                   var_rhs.Bind(lhs);
   7128                   Goto(&loop);
   7129                 }
   7130 
   7131                 Bind(&if_rhsisnotreceiver);
   7132                 {
   7133                   // Check if {rhs} is a Boolean.
   7134                   Label if_rhsisboolean(this), if_rhsisnotboolean(this);
   7135                   Branch(IsBooleanMap(rhs_map), &if_rhsisboolean,
   7136                          &if_rhsisnotboolean);
   7137 
   7138                   Bind(&if_rhsisboolean);
   7139                   {
   7140                     // The {rhs} is a Boolean, convert it to a Smi first.
   7141                     var_rhs.Bind(
   7142                         LoadObjectField(rhs, Oddball::kToNumberOffset));
   7143                     Goto(&loop);
   7144                   }
   7145 
   7146                   Bind(&if_rhsisnotboolean);
   7147                   Goto(&if_notequal);
   7148                 }
   7149               }
   7150             }
   7151           }
   7152 
   7153           Bind(&if_lhsisoddball);
   7154           {
   7155             // The {lhs} is an Oddball and {rhs} is some other HeapObject.
   7156             Label if_lhsisboolean(this), if_lhsisnotboolean(this);
   7157             Node* boolean_map = BooleanMapConstant();
   7158             Branch(WordEqual(lhs_map, boolean_map), &if_lhsisboolean,
   7159                    &if_lhsisnotboolean);
   7160 
   7161             Bind(&if_lhsisboolean);
   7162             {
   7163               // The {lhs} is a Boolean, check if {rhs} is also a Boolean.
   7164               Label if_rhsisboolean(this), if_rhsisnotboolean(this);
   7165               Branch(WordEqual(rhs_map, boolean_map), &if_rhsisboolean,
   7166                      &if_rhsisnotboolean);
   7167 
   7168               Bind(&if_rhsisboolean);
   7169               {
   7170                 // Both {lhs} and {rhs} are distinct Boolean values.
   7171                 Goto(&if_notequal);
   7172               }
   7173 
   7174               Bind(&if_rhsisnotboolean);
   7175               {
   7176                 // Convert the {lhs} to a Number first.
   7177                 var_lhs.Bind(LoadObjectField(lhs, Oddball::kToNumberOffset));
   7178                 Goto(&loop);
   7179               }
   7180             }
   7181 
   7182             Bind(&if_lhsisnotboolean);
   7183             {
   7184               // The {lhs} is either Null or Undefined; check if the {rhs} is
   7185               // undetectable (i.e. either also Null or Undefined or some
   7186               // undetectable JSReceiver).
   7187               Node* rhs_bitfield = LoadMapBitField(rhs_map);
   7188               Branch(Word32Equal(
   7189                          Word32And(rhs_bitfield,
   7190                                    Int32Constant(1 << Map::kIsUndetectable)),
   7191                          Int32Constant(0)),
   7192                      &if_notequal, &if_equal);
   7193             }
   7194           }
   7195 
   7196           Bind(&if_lhsissymbol);
   7197           {
   7198             // Check if the {rhs} is a JSReceiver.
   7199             Label if_rhsisreceiver(this), if_rhsisnotreceiver(this);
   7200             STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE);
   7201             Branch(IsJSReceiverInstanceType(rhs_instance_type),
   7202                    &if_rhsisreceiver, &if_rhsisnotreceiver);
   7203 
   7204             Bind(&if_rhsisreceiver);
   7205             {
   7206               // The {lhs} is a Primitive and the {rhs} is a JSReceiver.
   7207               // Swapping {lhs} and {rhs} is not observable and doesn't
   7208               // matter for the result, so we can just swap them and use
   7209               // the JSReceiver handling below (for {lhs} being a JSReceiver).
   7210               var_lhs.Bind(rhs);
   7211               var_rhs.Bind(lhs);
   7212               Goto(&loop);
   7213             }
   7214 
   7215             Bind(&if_rhsisnotreceiver);
   7216             {
   7217               // The {rhs} is not a JSReceiver and also not the same Symbol
   7218               // as the {lhs}, so this is equality check is considered false.
   7219               Goto(&if_notequal);
   7220             }
   7221           }
   7222 
   7223           Bind(&if_lhsisreceiver);
   7224           {
   7225             // Check if the {rhs} is also a JSReceiver.
   7226             Label if_rhsisreceiver(this), if_rhsisnotreceiver(this);
   7227             STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE);
   7228             Branch(IsJSReceiverInstanceType(rhs_instance_type),
   7229                    &if_rhsisreceiver, &if_rhsisnotreceiver);
   7230 
   7231             Bind(&if_rhsisreceiver);
   7232             {
   7233               // Both {lhs} and {rhs} are different JSReceiver references, so
   7234               // this cannot be considered equal.
   7235               Goto(&if_notequal);
   7236             }
   7237 
   7238             Bind(&if_rhsisnotreceiver);
   7239             {
   7240               // Check if {rhs} is Null or Undefined (an undetectable check
   7241               // is sufficient here, since we already know that {rhs} is not
   7242               // a JSReceiver).
   7243               Label if_rhsisundetectable(this),
   7244                   if_rhsisnotundetectable(this, Label::kDeferred);
   7245               Node* rhs_bitfield = LoadMapBitField(rhs_map);
   7246               Branch(Word32Equal(
   7247                          Word32And(rhs_bitfield,
   7248                                    Int32Constant(1 << Map::kIsUndetectable)),
   7249                          Int32Constant(0)),
   7250                      &if_rhsisnotundetectable, &if_rhsisundetectable);
   7251 
   7252               Bind(&if_rhsisundetectable);
   7253               {
   7254                 // Check if {lhs} is an undetectable JSReceiver.
   7255                 Node* lhs_bitfield = LoadMapBitField(lhs_map);
   7256                 Branch(Word32Equal(
   7257                            Word32And(lhs_bitfield,
   7258                                      Int32Constant(1 << Map::kIsUndetectable)),
   7259                            Int32Constant(0)),
   7260                        &if_notequal, &if_equal);
   7261               }
   7262 
   7263               Bind(&if_rhsisnotundetectable);
   7264               {
   7265                 // The {rhs} is some Primitive different from Null and
   7266                 // Undefined, need to convert {lhs} to Primitive first.
   7267                 Callable callable =
   7268                     CodeFactory::NonPrimitiveToPrimitive(isolate());
   7269                 var_lhs.Bind(CallStub(callable, context, lhs));
   7270                 Goto(&loop);
   7271               }
   7272             }
   7273           }
   7274         }
   7275       }
   7276     }
   7277 
   7278     Bind(&do_rhsstringtonumber);
   7279     {
   7280       Callable callable = CodeFactory::StringToNumber(isolate());
   7281       var_rhs.Bind(CallStub(callable, context, rhs));
   7282       Goto(&loop);
   7283     }
   7284   }
   7285 
   7286   Bind(&do_fcmp);
   7287   {
   7288     // Load the {lhs} and {rhs} floating point values.
   7289     Node* lhs = var_fcmp_lhs.value();
   7290     Node* rhs = var_fcmp_rhs.value();
   7291 
   7292     // Perform a fast floating point comparison.
   7293     Branch(Float64Equal(lhs, rhs), &if_equal, &if_notequal);
   7294   }
   7295 
   7296   Bind(&if_equal);
   7297   {
   7298     result.Bind(BooleanConstant(mode == kDontNegateResult));
   7299     Goto(&end);
   7300   }
   7301 
   7302   Bind(&if_notequal);
   7303   {
   7304     result.Bind(BooleanConstant(mode == kNegateResult));
   7305     Goto(&end);
   7306   }
   7307 
   7308   Bind(&end);
   7309   return result.value();
   7310 }
   7311 
   7312 Node* CodeStubAssembler::StrictEqual(ResultMode mode, Node* lhs, Node* rhs,
   7313                                      Node* context) {
   7314   // Here's pseudo-code for the algorithm below in case of kDontNegateResult
   7315   // mode; for kNegateResult mode we properly negate the result.
   7316   //
   7317   // if (lhs == rhs) {
   7318   //   if (lhs->IsHeapNumber()) return HeapNumber::cast(lhs)->value() != NaN;
   7319   //   return true;
   7320   // }
   7321   // if (!lhs->IsSmi()) {
   7322   //   if (lhs->IsHeapNumber()) {
   7323   //     if (rhs->IsSmi()) {
   7324   //       return Smi::cast(rhs)->value() == HeapNumber::cast(lhs)->value();
   7325   //     } else if (rhs->IsHeapNumber()) {
   7326   //       return HeapNumber::cast(rhs)->value() ==
   7327   //       HeapNumber::cast(lhs)->value();
   7328   //     } else {
   7329   //       return false;
   7330   //     }
   7331   //   } else {
   7332   //     if (rhs->IsSmi()) {
   7333   //       return false;
   7334   //     } else {
   7335   //       if (lhs->IsString()) {
   7336   //         if (rhs->IsString()) {
   7337   //           return %StringEqual(lhs, rhs);
   7338   //         } else {
   7339   //           return false;
   7340   //         }
   7341   //       } else {
   7342   //         return false;
   7343   //       }
   7344   //     }
   7345   //   }
   7346   // } else {
   7347   //   if (rhs->IsSmi()) {
   7348   //     return false;
   7349   //   } else {
   7350   //     if (rhs->IsHeapNumber()) {
   7351   //       return Smi::cast(lhs)->value() == HeapNumber::cast(rhs)->value();
   7352   //     } else {
   7353   //       return false;
   7354   //     }
   7355   //   }
   7356   // }
   7357 
   7358   Label if_equal(this), if_notequal(this), end(this);
   7359   Variable result(this, MachineRepresentation::kTagged);
   7360 
   7361   // Check if {lhs} and {rhs} refer to the same object.
   7362   Label if_same(this), if_notsame(this);
   7363   Branch(WordEqual(lhs, rhs), &if_same, &if_notsame);
   7364 
   7365   Bind(&if_same);
   7366   {
   7367     // The {lhs} and {rhs} reference the exact same value, yet we need special
   7368     // treatment for HeapNumber, as NaN is not equal to NaN.
   7369     GenerateEqual_Same(this, lhs, &if_equal, &if_notequal);
   7370   }
   7371 
   7372   Bind(&if_notsame);
   7373   {
   7374     // The {lhs} and {rhs} reference different objects, yet for Smi, HeapNumber
   7375     // and String they can still be considered equal.
   7376 
   7377     // Check if {lhs} is a Smi or a HeapObject.
   7378     Label if_lhsissmi(this), if_lhsisnotsmi(this);
   7379     Branch(TaggedIsSmi(lhs), &if_lhsissmi, &if_lhsisnotsmi);
   7380 
   7381     Bind(&if_lhsisnotsmi);
   7382     {
   7383       // Load the map of {lhs}.
   7384       Node* lhs_map = LoadMap(lhs);
   7385 
   7386       // Check if {lhs} is a HeapNumber.
   7387       Label if_lhsisnumber(this), if_lhsisnotnumber(this);
   7388       Branch(IsHeapNumberMap(lhs_map), &if_lhsisnumber, &if_lhsisnotnumber);
   7389 
   7390       Bind(&if_lhsisnumber);
   7391       {
   7392         // Check if {rhs} is a Smi or a HeapObject.
   7393         Label if_rhsissmi(this), if_rhsisnotsmi(this);
   7394         Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi);
   7395 
   7396         Bind(&if_rhsissmi);
   7397         {
   7398           // Convert {lhs} and {rhs} to floating point values.
   7399           Node* lhs_value = LoadHeapNumberValue(lhs);
   7400           Node* rhs_value = SmiToFloat64(rhs);
   7401 
   7402           // Perform a floating point comparison of {lhs} and {rhs}.
   7403           Branch(Float64Equal(lhs_value, rhs_value), &if_equal, &if_notequal);
   7404         }
   7405 
   7406         Bind(&if_rhsisnotsmi);
   7407         {
   7408           // Load the map of {rhs}.
   7409           Node* rhs_map = LoadMap(rhs);
   7410 
   7411           // Check if {rhs} is also a HeapNumber.
   7412           Label if_rhsisnumber(this), if_rhsisnotnumber(this);
   7413           Branch(IsHeapNumberMap(rhs_map), &if_rhsisnumber, &if_rhsisnotnumber);
   7414 
   7415           Bind(&if_rhsisnumber);
   7416           {
   7417             // Convert {lhs} and {rhs} to floating point values.
   7418             Node* lhs_value = LoadHeapNumberValue(lhs);
   7419             Node* rhs_value = LoadHeapNumberValue(rhs);
   7420 
   7421             // Perform a floating point comparison of {lhs} and {rhs}.
   7422             Branch(Float64Equal(lhs_value, rhs_value), &if_equal, &if_notequal);
   7423           }
   7424 
   7425           Bind(&if_rhsisnotnumber);
   7426           Goto(&if_notequal);
   7427         }
   7428       }
   7429 
   7430       Bind(&if_lhsisnotnumber);
   7431       {
   7432         // Check if {rhs} is a Smi or a HeapObject.
   7433         Label if_rhsissmi(this), if_rhsisnotsmi(this);
   7434         Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi);
   7435 
   7436         Bind(&if_rhsissmi);
   7437         Goto(&if_notequal);
   7438 
   7439         Bind(&if_rhsisnotsmi);
   7440         {
   7441           // Load the instance type of {lhs}.
   7442           Node* lhs_instance_type = LoadMapInstanceType(lhs_map);
   7443 
   7444           // Check if {lhs} is a String.
   7445           Label if_lhsisstring(this), if_lhsisnotstring(this);
   7446           Branch(IsStringInstanceType(lhs_instance_type), &if_lhsisstring,
   7447                  &if_lhsisnotstring);
   7448 
   7449           Bind(&if_lhsisstring);
   7450           {
   7451             // Load the instance type of {rhs}.
   7452             Node* rhs_instance_type = LoadInstanceType(rhs);
   7453 
   7454             // Check if {rhs} is also a String.
   7455             Label if_rhsisstring(this, Label::kDeferred),
   7456                 if_rhsisnotstring(this);
   7457             Branch(IsStringInstanceType(rhs_instance_type), &if_rhsisstring,
   7458                    &if_rhsisnotstring);
   7459 
   7460             Bind(&if_rhsisstring);
   7461             {
   7462               Callable callable = (mode == kDontNegateResult)
   7463                                       ? CodeFactory::StringEqual(isolate())
   7464                                       : CodeFactory::StringNotEqual(isolate());
   7465               result.Bind(CallStub(callable, context, lhs, rhs));
   7466               Goto(&end);
   7467             }
   7468 
   7469             Bind(&if_rhsisnotstring);
   7470             Goto(&if_notequal);
   7471           }
   7472 
   7473           Bind(&if_lhsisnotstring);
   7474           Goto(&if_notequal);
   7475         }
   7476       }
   7477     }
   7478 
   7479     Bind(&if_lhsissmi);
   7480     {
   7481       // We already know that {lhs} and {rhs} are not reference equal, and {lhs}
   7482       // is a Smi; so {lhs} and {rhs} can only be strictly equal if {rhs} is a
   7483       // HeapNumber with an equal floating point value.
   7484 
   7485       // Check if {rhs} is a Smi or a HeapObject.
   7486       Label if_rhsissmi(this), if_rhsisnotsmi(this);
   7487       Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi);
   7488 
   7489       Bind(&if_rhsissmi);
   7490       Goto(&if_notequal);
   7491 
   7492       Bind(&if_rhsisnotsmi);
   7493       {
   7494         // Load the map of the {rhs}.
   7495         Node* rhs_map = LoadMap(rhs);
   7496 
   7497         // The {rhs} could be a HeapNumber with the same value as {lhs}.
   7498         Label if_rhsisnumber(this), if_rhsisnotnumber(this);
   7499         Branch(IsHeapNumberMap(rhs_map), &if_rhsisnumber, &if_rhsisnotnumber);
   7500 
   7501         Bind(&if_rhsisnumber);
   7502         {
   7503           // Convert {lhs} and {rhs} to floating point values.
   7504           Node* lhs_value = SmiToFloat64(lhs);
   7505           Node* rhs_value = LoadHeapNumberValue(rhs);
   7506 
   7507           // Perform a floating point comparison of {lhs} and {rhs}.
   7508           Branch(Float64Equal(lhs_value, rhs_value), &if_equal, &if_notequal);
   7509         }
   7510 
   7511         Bind(&if_rhsisnotnumber);
   7512         Goto(&if_notequal);
   7513       }
   7514     }
   7515   }
   7516 
   7517   Bind(&if_equal);
   7518   {
   7519     result.Bind(BooleanConstant(mode == kDontNegateResult));
   7520     Goto(&end);
   7521   }
   7522 
   7523   Bind(&if_notequal);
   7524   {
   7525     result.Bind(BooleanConstant(mode == kNegateResult));
   7526     Goto(&end);
   7527   }
   7528 
   7529   Bind(&end);
   7530   return result.value();
   7531 }
   7532 
   7533 // ECMA#sec-samevalue
   7534 // This algorithm differs from the Strict Equality Comparison Algorithm in its
   7535 // treatment of signed zeroes and NaNs.
   7536 Node* CodeStubAssembler::SameValue(Node* lhs, Node* rhs, Node* context) {
   7537   Variable var_result(this, MachineRepresentation::kWord32);
   7538   Label strict_equal(this), out(this);
   7539 
   7540   Node* const int_false = Int32Constant(0);
   7541   Node* const int_true = Int32Constant(1);
   7542 
   7543   Label if_equal(this), if_notequal(this);
   7544   Branch(WordEqual(lhs, rhs), &if_equal, &if_notequal);
   7545 
   7546   Bind(&if_equal);
   7547   {
   7548     // This covers the case when {lhs} == {rhs}. We can simply return true
   7549     // because SameValue considers two NaNs to be equal.
   7550 
   7551     var_result.Bind(int_true);
   7552     Goto(&out);
   7553   }
   7554 
   7555   Bind(&if_notequal);
   7556   {
   7557     // This covers the case when {lhs} != {rhs}. We only handle numbers here
   7558     // and defer to StrictEqual for the rest.
   7559 
   7560     Node* const lhs_float = TryTaggedToFloat64(lhs, &strict_equal);
   7561     Node* const rhs_float = TryTaggedToFloat64(rhs, &strict_equal);
   7562 
   7563     Label if_lhsisnan(this), if_lhsnotnan(this);
   7564     BranchIfFloat64IsNaN(lhs_float, &if_lhsisnan, &if_lhsnotnan);
   7565 
   7566     Bind(&if_lhsisnan);
   7567     {
   7568       // Return true iff {rhs} is NaN.
   7569 
   7570       Node* const result =
   7571           SelectConstant(Float64Equal(rhs_float, rhs_float), int_false,
   7572                          int_true, MachineRepresentation::kWord32);
   7573       var_result.Bind(result);
   7574       Goto(&out);
   7575     }
   7576 
   7577     Bind(&if_lhsnotnan);
   7578     {
   7579       Label if_floatisequal(this), if_floatnotequal(this);
   7580       Branch(Float64Equal(lhs_float, rhs_float), &if_floatisequal,
   7581              &if_floatnotequal);
   7582 
   7583       Bind(&if_floatisequal);
   7584       {
   7585         // We still need to handle the case when {lhs} and {rhs} are -0.0 and
   7586         // 0.0 (or vice versa). Compare the high word to
   7587         // distinguish between the two.
   7588 
   7589         Node* const lhs_hi_word = Float64ExtractHighWord32(lhs_float);
   7590         Node* const rhs_hi_word = Float64ExtractHighWord32(rhs_float);
   7591 
   7592         // If x is +0 and y is -0, return false.
   7593         // If x is -0 and y is +0, return false.
   7594 
   7595         Node* const result = Word32Equal(lhs_hi_word, rhs_hi_word);
   7596         var_result.Bind(result);
   7597         Goto(&out);
   7598       }
   7599 
   7600       Bind(&if_floatnotequal);
   7601       {
   7602         var_result.Bind(int_false);
   7603         Goto(&out);
   7604       }
   7605     }
   7606   }
   7607 
   7608   Bind(&strict_equal);
   7609   {
   7610     Node* const is_equal = StrictEqual(kDontNegateResult, lhs, rhs, context);
   7611     Node* const result = WordEqual(is_equal, TrueConstant());
   7612     var_result.Bind(result);
   7613     Goto(&out);
   7614   }
   7615 
   7616   Bind(&out);
   7617   return var_result.value();
   7618 }
   7619 
   7620 Node* CodeStubAssembler::ForInFilter(Node* key, Node* object, Node* context) {
   7621   Label return_undefined(this, Label::kDeferred), return_to_name(this),
   7622       end(this);
   7623 
   7624   Variable var_result(this, MachineRepresentation::kTagged);
   7625 
   7626   Node* has_property =
   7627       HasProperty(object, key, context, Runtime::kForInHasProperty);
   7628 
   7629   Branch(WordEqual(has_property, BooleanConstant(true)), &return_to_name,
   7630          &return_undefined);
   7631 
   7632   Bind(&return_to_name);
   7633   {
   7634     var_result.Bind(ToName(context, key));
   7635     Goto(&end);
   7636   }
   7637 
   7638   Bind(&return_undefined);
   7639   {
   7640     var_result.Bind(UndefinedConstant());
   7641     Goto(&end);
   7642   }
   7643 
   7644   Bind(&end);
   7645   return var_result.value();
   7646 }
   7647 
   7648 Node* CodeStubAssembler::HasProperty(
   7649     Node* object, Node* key, Node* context,
   7650     Runtime::FunctionId fallback_runtime_function_id) {
   7651   Label call_runtime(this, Label::kDeferred), return_true(this),
   7652       return_false(this), end(this);
   7653 
   7654   CodeStubAssembler::LookupInHolder lookup_property_in_holder =
   7655       [this, &return_true](Node* receiver, Node* holder, Node* holder_map,
   7656                            Node* holder_instance_type, Node* unique_name,
   7657                            Label* next_holder, Label* if_bailout) {
   7658         TryHasOwnProperty(holder, holder_map, holder_instance_type, unique_name,
   7659                           &return_true, next_holder, if_bailout);
   7660       };
   7661 
   7662   CodeStubAssembler::LookupInHolder lookup_element_in_holder =
   7663       [this, &return_true](Node* receiver, Node* holder, Node* holder_map,
   7664                            Node* holder_instance_type, Node* index,
   7665                            Label* next_holder, Label* if_bailout) {
   7666         TryLookupElement(holder, holder_map, holder_instance_type, index,
   7667                          &return_true, next_holder, if_bailout);
   7668       };
   7669 
   7670   TryPrototypeChainLookup(object, key, lookup_property_in_holder,
   7671                           lookup_element_in_holder, &return_false,
   7672                           &call_runtime);
   7673 
   7674   Variable result(this, MachineRepresentation::kTagged);
   7675   Bind(&return_true);
   7676   {
   7677     result.Bind(BooleanConstant(true));
   7678     Goto(&end);
   7679   }
   7680 
   7681   Bind(&return_false);
   7682   {
   7683     result.Bind(BooleanConstant(false));
   7684     Goto(&end);
   7685   }
   7686 
   7687   Bind(&call_runtime);
   7688   {
   7689     result.Bind(
   7690         CallRuntime(fallback_runtime_function_id, context, object, key));
   7691     Goto(&end);
   7692   }
   7693 
   7694   Bind(&end);
   7695   return result.value();
   7696 }
   7697 
   7698 Node* CodeStubAssembler::ClassOf(Node* value) {
   7699   Variable var_result(this, MachineRepresentation::kTaggedPointer);
   7700   Label if_function(this, Label::kDeferred), if_object(this, Label::kDeferred),
   7701       if_primitive(this, Label::kDeferred), return_result(this);
   7702 
   7703   // Check if {value} is a Smi.
   7704   GotoIf(TaggedIsSmi(value), &if_primitive);
   7705 
   7706   Node* value_map = LoadMap(value);
   7707   Node* value_instance_type = LoadMapInstanceType(value_map);
   7708 
   7709   // Check if {value} is a JSFunction or JSBoundFunction.
   7710   STATIC_ASSERT(LAST_TYPE == LAST_FUNCTION_TYPE);
   7711   GotoIf(Uint32LessThanOrEqual(Int32Constant(FIRST_FUNCTION_TYPE),
   7712                                value_instance_type),
   7713          &if_function);
   7714 
   7715   // Check if {value} is a primitive HeapObject.
   7716   STATIC_ASSERT(LAST_TYPE == LAST_JS_RECEIVER_TYPE);
   7717   GotoIf(Uint32LessThan(value_instance_type,
   7718                         Int32Constant(FIRST_JS_RECEIVER_TYPE)),
   7719          &if_primitive);
   7720 
   7721   // Load the {value}s constructor, and check that it's a JSFunction.
   7722   Node* constructor = LoadMapConstructor(value_map);
   7723   GotoIfNot(IsJSFunction(constructor), &if_object);
   7724 
   7725   // Return the instance class name for the {constructor}.
   7726   Node* shared_info =
   7727       LoadObjectField(constructor, JSFunction::kSharedFunctionInfoOffset);
   7728   Node* instance_class_name = LoadObjectField(
   7729       shared_info, SharedFunctionInfo::kInstanceClassNameOffset);
   7730   var_result.Bind(instance_class_name);
   7731   Goto(&return_result);
   7732 
   7733   Bind(&if_function);
   7734   var_result.Bind(LoadRoot(Heap::kFunction_stringRootIndex));
   7735   Goto(&return_result);
   7736 
   7737   Bind(&if_object);
   7738   var_result.Bind(LoadRoot(Heap::kObject_stringRootIndex));
   7739   Goto(&return_result);
   7740 
   7741   Bind(&if_primitive);
   7742   var_result.Bind(NullConstant());
   7743   Goto(&return_result);
   7744 
   7745   Bind(&return_result);
   7746   return var_result.value();
   7747 }
   7748 
   7749 Node* CodeStubAssembler::Typeof(Node* value, Node* context) {
   7750   Variable result_var(this, MachineRepresentation::kTagged);
   7751 
   7752   Label return_number(this, Label::kDeferred), if_oddball(this),
   7753       return_function(this), return_undefined(this), return_object(this),
   7754       return_string(this), return_result(this);
   7755 
   7756   GotoIf(TaggedIsSmi(value), &return_number);
   7757 
   7758   Node* map = LoadMap(value);
   7759 
   7760   GotoIf(IsHeapNumberMap(map), &return_number);
   7761 
   7762   Node* instance_type = LoadMapInstanceType(map);
   7763 
   7764   GotoIf(Word32Equal(instance_type, Int32Constant(ODDBALL_TYPE)), &if_oddball);
   7765 
   7766   Node* callable_or_undetectable_mask = Word32And(
   7767       LoadMapBitField(map),
   7768       Int32Constant(1 << Map::kIsCallable | 1 << Map::kIsUndetectable));
   7769 
   7770   GotoIf(Word32Equal(callable_or_undetectable_mask,
   7771                      Int32Constant(1 << Map::kIsCallable)),
   7772          &return_function);
   7773 
   7774   GotoIfNot(Word32Equal(callable_or_undetectable_mask, Int32Constant(0)),
   7775             &return_undefined);
   7776 
   7777   GotoIf(IsJSReceiverInstanceType(instance_type), &return_object);
   7778 
   7779   GotoIf(IsStringInstanceType(instance_type), &return_string);
   7780 
   7781   CSA_ASSERT(this, Word32Equal(instance_type, Int32Constant(SYMBOL_TYPE)));
   7782   result_var.Bind(HeapConstant(isolate()->factory()->symbol_string()));
   7783   Goto(&return_result);
   7784 
   7785   Bind(&return_number);
   7786   {
   7787     result_var.Bind(HeapConstant(isolate()->factory()->number_string()));
   7788     Goto(&return_result);
   7789   }
   7790 
   7791   Bind(&if_oddball);
   7792   {
   7793     Node* type = LoadObjectField(value, Oddball::kTypeOfOffset);
   7794     result_var.Bind(type);
   7795     Goto(&return_result);
   7796   }
   7797 
   7798   Bind(&return_function);
   7799   {
   7800     result_var.Bind(HeapConstant(isolate()->factory()->function_string()));
   7801     Goto(&return_result);
   7802   }
   7803 
   7804   Bind(&return_undefined);
   7805   {
   7806     result_var.Bind(HeapConstant(isolate()->factory()->undefined_string()));
   7807     Goto(&return_result);
   7808   }
   7809 
   7810   Bind(&return_object);
   7811   {
   7812     result_var.Bind(HeapConstant(isolate()->factory()->object_string()));
   7813     Goto(&return_result);
   7814   }
   7815 
   7816   Bind(&return_string);
   7817   {
   7818     result_var.Bind(HeapConstant(isolate()->factory()->string_string()));
   7819     Goto(&return_result);
   7820   }
   7821 
   7822   Bind(&return_result);
   7823   return result_var.value();
   7824 }
   7825 
   7826 Node* CodeStubAssembler::GetSuperConstructor(Node* active_function,
   7827                                              Node* context) {
   7828   CSA_ASSERT(this, IsJSFunction(active_function));
   7829 
   7830   Label is_not_constructor(this, Label::kDeferred), out(this);
   7831   Variable result(this, MachineRepresentation::kTagged);
   7832 
   7833   Node* map = LoadMap(active_function);
   7834   Node* prototype = LoadMapPrototype(map);
   7835   Node* prototype_map = LoadMap(prototype);
   7836   GotoIfNot(IsConstructorMap(prototype_map), &is_not_constructor);
   7837 
   7838   result.Bind(prototype);
   7839   Goto(&out);
   7840 
   7841   Bind(&is_not_constructor);
   7842   {
   7843     CallRuntime(Runtime::kThrowNotSuperConstructor, context, prototype,
   7844                 active_function);
   7845     Unreachable();
   7846   }
   7847 
   7848   Bind(&out);
   7849   return result.value();
   7850 }
   7851 
   7852 Node* CodeStubAssembler::InstanceOf(Node* object, Node* callable,
   7853                                     Node* context) {
   7854   Variable var_result(this, MachineRepresentation::kTagged);
   7855   Label if_notcallable(this, Label::kDeferred),
   7856       if_notreceiver(this, Label::kDeferred), if_otherhandler(this),
   7857       if_nohandler(this, Label::kDeferred), return_true(this),
   7858       return_false(this), return_result(this, &var_result);
   7859 
   7860   // Ensure that the {callable} is actually a JSReceiver.
   7861   GotoIf(TaggedIsSmi(callable), &if_notreceiver);
   7862   GotoIfNot(IsJSReceiver(callable), &if_notreceiver);
   7863 
   7864   // Load the @@hasInstance property from {callable}.
   7865   Node* inst_of_handler = CallStub(CodeFactory::GetProperty(isolate()), context,
   7866                                    callable, HasInstanceSymbolConstant());
   7867 
   7868   // Optimize for the likely case where {inst_of_handler} is the builtin
   7869   // Function.prototype[@@hasInstance] method, and emit a direct call in
   7870   // that case without any additional checking.
   7871   Node* native_context = LoadNativeContext(context);
   7872   Node* function_has_instance =
   7873       LoadContextElement(native_context, Context::FUNCTION_HAS_INSTANCE_INDEX);
   7874   GotoIfNot(WordEqual(inst_of_handler, function_has_instance),
   7875             &if_otherhandler);
   7876   {
   7877     // Call to Function.prototype[@@hasInstance] directly.
   7878     Callable builtin(isolate()->builtins()->FunctionPrototypeHasInstance(),
   7879                      CallTrampolineDescriptor(isolate()));
   7880     Node* result = CallJS(builtin, context, inst_of_handler, callable, object);
   7881     var_result.Bind(result);
   7882     Goto(&return_result);
   7883   }
   7884 
   7885   Bind(&if_otherhandler);
   7886   {
   7887     // Check if there's actually an {inst_of_handler}.
   7888     GotoIf(IsNull(inst_of_handler), &if_nohandler);
   7889     GotoIf(IsUndefined(inst_of_handler), &if_nohandler);
   7890 
   7891     // Call the {inst_of_handler} for {callable} and {object}.
   7892     Node* result = CallJS(
   7893         CodeFactory::Call(isolate(), ConvertReceiverMode::kNotNullOrUndefined),
   7894         context, inst_of_handler, callable, object);
   7895 
   7896     // Convert the {result} to a Boolean.
   7897     BranchIfToBooleanIsTrue(result, &return_true, &return_false);
   7898   }
   7899 
   7900   Bind(&if_nohandler);
   7901   {
   7902     // Ensure that the {callable} is actually Callable.
   7903     GotoIfNot(IsCallable(callable), &if_notcallable);
   7904 
   7905     // Use the OrdinaryHasInstance algorithm.
   7906     Node* result = CallStub(CodeFactory::OrdinaryHasInstance(isolate()),
   7907                             context, callable, object);
   7908     var_result.Bind(result);
   7909     Goto(&return_result);
   7910   }
   7911 
   7912   Bind(&if_notcallable);
   7913   {
   7914     CallRuntime(Runtime::kThrowNonCallableInInstanceOfCheck, context);
   7915     Unreachable();
   7916   }
   7917 
   7918   Bind(&if_notreceiver);
   7919   {
   7920     CallRuntime(Runtime::kThrowNonObjectInInstanceOfCheck, context);
   7921     Unreachable();
   7922   }
   7923 
   7924   Bind(&return_true);
   7925   var_result.Bind(TrueConstant());
   7926   Goto(&return_result);
   7927 
   7928   Bind(&return_false);
   7929   var_result.Bind(FalseConstant());
   7930   Goto(&return_result);
   7931 
   7932   Bind(&return_result);
   7933   return var_result.value();
   7934 }
   7935 
   7936 Node* CodeStubAssembler::NumberInc(Node* value) {
   7937   Variable var_result(this, MachineRepresentation::kTagged),
   7938       var_finc_value(this, MachineRepresentation::kFloat64);
   7939   Label if_issmi(this), if_isnotsmi(this), do_finc(this), end(this);
   7940   Branch(TaggedIsSmi(value), &if_issmi, &if_isnotsmi);
   7941 
   7942   Bind(&if_issmi);
   7943   {
   7944     // Try fast Smi addition first.
   7945     Node* one = SmiConstant(Smi::FromInt(1));
   7946     Node* pair = IntPtrAddWithOverflow(BitcastTaggedToWord(value),
   7947                                        BitcastTaggedToWord(one));
   7948     Node* overflow = Projection(1, pair);
   7949 
   7950     // Check if the Smi addition overflowed.
   7951     Label if_overflow(this), if_notoverflow(this);
   7952     Branch(overflow, &if_overflow, &if_notoverflow);
   7953 
   7954     Bind(&if_notoverflow);
   7955     var_result.Bind(BitcastWordToTaggedSigned(Projection(0, pair)));
   7956     Goto(&end);
   7957 
   7958     Bind(&if_overflow);
   7959     {
   7960       var_finc_value.Bind(SmiToFloat64(value));
   7961       Goto(&do_finc);
   7962     }
   7963   }
   7964 
   7965   Bind(&if_isnotsmi);
   7966   {
   7967     // Check if the value is a HeapNumber.
   7968     CSA_ASSERT(this, IsHeapNumberMap(LoadMap(value)));
   7969 
   7970     // Load the HeapNumber value.
   7971     var_finc_value.Bind(LoadHeapNumberValue(value));
   7972     Goto(&do_finc);
   7973   }
   7974 
   7975   Bind(&do_finc);
   7976   {
   7977     Node* finc_value = var_finc_value.value();
   7978     Node* one = Float64Constant(1.0);
   7979     Node* finc_result = Float64Add(finc_value, one);
   7980     var_result.Bind(AllocateHeapNumberWithValue(finc_result));
   7981     Goto(&end);
   7982   }
   7983 
   7984   Bind(&end);
   7985   return var_result.value();
   7986 }
   7987 
   7988 void CodeStubAssembler::GotoIfNotNumber(Node* input, Label* is_not_number) {
   7989   Label is_number(this);
   7990   GotoIf(TaggedIsSmi(input), &is_number);
   7991   Node* input_map = LoadMap(input);
   7992   Branch(IsHeapNumberMap(input_map), &is_number, is_not_number);
   7993   Bind(&is_number);
   7994 }
   7995 
   7996 void CodeStubAssembler::GotoIfNumber(Node* input, Label* is_number) {
   7997   GotoIf(TaggedIsSmi(input), is_number);
   7998   Node* input_map = LoadMap(input);
   7999   GotoIf(IsHeapNumberMap(input_map), is_number);
   8000 }
   8001 
   8002 Node* CodeStubAssembler::CreateArrayIterator(Node* array, Node* array_map,
   8003                                              Node* array_type, Node* context,
   8004                                              IterationKind mode) {
   8005   int kBaseMapIndex = 0;
   8006   switch (mode) {
   8007     case IterationKind::kKeys:
   8008       kBaseMapIndex = Context::TYPED_ARRAY_KEY_ITERATOR_MAP_INDEX;
   8009       break;
   8010     case IterationKind::kValues:
   8011       kBaseMapIndex = Context::UINT8_ARRAY_VALUE_ITERATOR_MAP_INDEX;
   8012       break;
   8013     case IterationKind::kEntries:
   8014       kBaseMapIndex = Context::UINT8_ARRAY_KEY_VALUE_ITERATOR_MAP_INDEX;
   8015       break;
   8016   }
   8017 
   8018   // Fast Array iterator map index:
   8019   // (kBaseIndex + kFastIteratorOffset) + ElementsKind (for JSArrays)
   8020   // kBaseIndex + (ElementsKind - UINT8_ELEMENTS) (for JSTypedArrays)
   8021   const int kFastIteratorOffset =
   8022       Context::FAST_SMI_ARRAY_VALUE_ITERATOR_MAP_INDEX -
   8023       Context::UINT8_ARRAY_VALUE_ITERATOR_MAP_INDEX;
   8024   STATIC_ASSERT(kFastIteratorOffset ==
   8025                 (Context::FAST_SMI_ARRAY_KEY_VALUE_ITERATOR_MAP_INDEX -
   8026                  Context::UINT8_ARRAY_KEY_VALUE_ITERATOR_MAP_INDEX));
   8027 
   8028   // Slow Array iterator map index: (kBaseIndex + kSlowIteratorOffset)
   8029   const int kSlowIteratorOffset =
   8030       Context::GENERIC_ARRAY_VALUE_ITERATOR_MAP_INDEX -
   8031       Context::UINT8_ARRAY_VALUE_ITERATOR_MAP_INDEX;
   8032   STATIC_ASSERT(kSlowIteratorOffset ==
   8033                 (Context::GENERIC_ARRAY_KEY_VALUE_ITERATOR_MAP_INDEX -
   8034                  Context::UINT8_ARRAY_KEY_VALUE_ITERATOR_MAP_INDEX));
   8035 
   8036   // Assert: Type(array) is Object
   8037   CSA_ASSERT(this, IsJSReceiverInstanceType(array_type));
   8038 
   8039   Variable var_result(this, MachineRepresentation::kTagged);
   8040   Variable var_map_index(this, MachineType::PointerRepresentation());
   8041   Variable var_array_map(this, MachineRepresentation::kTagged);
   8042 
   8043   Label return_result(this);
   8044   Label allocate_iterator(this);
   8045 
   8046   if (mode == IterationKind::kKeys) {
   8047     // There are only two key iterator maps, branch depending on whether or not
   8048     // the receiver is a TypedArray or not.
   8049 
   8050     Label if_istypedarray(this), if_isgeneric(this);
   8051 
   8052     Branch(Word32Equal(array_type, Int32Constant(JS_TYPED_ARRAY_TYPE)),
   8053            &if_istypedarray, &if_isgeneric);
   8054 
   8055     Bind(&if_isgeneric);
   8056     {
   8057       Label if_isfast(this), if_isslow(this);
   8058       BranchIfFastJSArray(array, context, FastJSArrayAccessMode::INBOUNDS_READ,
   8059                           &if_isfast, &if_isslow);
   8060 
   8061       Bind(&if_isfast);
   8062       {
   8063         var_map_index.Bind(
   8064             IntPtrConstant(Context::FAST_ARRAY_KEY_ITERATOR_MAP_INDEX));
   8065         var_array_map.Bind(array_map);
   8066         Goto(&allocate_iterator);
   8067       }
   8068 
   8069       Bind(&if_isslow);
   8070       {
   8071         var_map_index.Bind(
   8072             IntPtrConstant(Context::GENERIC_ARRAY_KEY_ITERATOR_MAP_INDEX));
   8073         var_array_map.Bind(UndefinedConstant());
   8074         Goto(&allocate_iterator);
   8075       }
   8076     }
   8077 
   8078     Bind(&if_istypedarray);
   8079     {
   8080       var_map_index.Bind(
   8081           IntPtrConstant(Context::TYPED_ARRAY_KEY_ITERATOR_MAP_INDEX));
   8082       var_array_map.Bind(UndefinedConstant());
   8083       Goto(&allocate_iterator);
   8084     }
   8085   } else {
   8086     Label if_istypedarray(this), if_isgeneric(this);
   8087     Branch(Word32Equal(array_type, Int32Constant(JS_TYPED_ARRAY_TYPE)),
   8088            &if_istypedarray, &if_isgeneric);
   8089 
   8090     Bind(&if_isgeneric);
   8091     {
   8092       Label if_isfast(this), if_isslow(this);
   8093       BranchIfFastJSArray(array, context, FastJSArrayAccessMode::INBOUNDS_READ,
   8094                           &if_isfast, &if_isslow);
   8095 
   8096       Bind(&if_isfast);
   8097       {
   8098         Label if_ispacked(this), if_isholey(this);
   8099         Node* elements_kind = LoadMapElementsKind(array_map);
   8100         Branch(IsHoleyFastElementsKind(elements_kind), &if_isholey,
   8101                &if_ispacked);
   8102 
   8103         Bind(&if_isholey);
   8104         {
   8105           // Fast holey JSArrays can treat the hole as undefined if the
   8106           // protector cell is valid, and the prototype chain is unchanged from
   8107           // its initial state (because the protector cell is only tracked for
   8108           // initial the Array and Object prototypes). Check these conditions
   8109           // here, and take the slow path if any fail.
   8110           Node* protector_cell = LoadRoot(Heap::kArrayProtectorRootIndex);
   8111           DCHECK(isolate()->heap()->array_protector()->IsPropertyCell());
   8112           GotoIfNot(
   8113               WordEqual(
   8114                   LoadObjectField(protector_cell, PropertyCell::kValueOffset),
   8115                   SmiConstant(Smi::FromInt(Isolate::kProtectorValid))),
   8116               &if_isslow);
   8117 
   8118           Node* native_context = LoadNativeContext(context);
   8119 
   8120           Node* prototype = LoadMapPrototype(array_map);
   8121           Node* array_prototype = LoadContextElement(
   8122               native_context, Context::INITIAL_ARRAY_PROTOTYPE_INDEX);
   8123           GotoIfNot(WordEqual(prototype, array_prototype), &if_isslow);
   8124 
   8125           Node* map = LoadMap(prototype);
   8126           prototype = LoadMapPrototype(map);
   8127           Node* object_prototype = LoadContextElement(
   8128               native_context, Context::INITIAL_OBJECT_PROTOTYPE_INDEX);
   8129           GotoIfNot(WordEqual(prototype, object_prototype), &if_isslow);
   8130 
   8131           map = LoadMap(prototype);
   8132           prototype = LoadMapPrototype(map);
   8133           Branch(IsNull(prototype), &if_ispacked, &if_isslow);
   8134         }
   8135         Bind(&if_ispacked);
   8136         {
   8137           Node* map_index =
   8138               IntPtrAdd(IntPtrConstant(kBaseMapIndex + kFastIteratorOffset),
   8139                         ChangeUint32ToWord(LoadMapElementsKind(array_map)));
   8140           CSA_ASSERT(this, IntPtrGreaterThanOrEqual(
   8141                                map_index, IntPtrConstant(kBaseMapIndex +
   8142                                                          kFastIteratorOffset)));
   8143           CSA_ASSERT(this, IntPtrLessThan(map_index,
   8144                                           IntPtrConstant(kBaseMapIndex +
   8145                                                          kSlowIteratorOffset)));
   8146 
   8147           var_map_index.Bind(map_index);
   8148           var_array_map.Bind(array_map);
   8149           Goto(&allocate_iterator);
   8150         }
   8151       }
   8152 
   8153       Bind(&if_isslow);
   8154       {
   8155         Node* map_index = IntPtrAdd(IntPtrConstant(kBaseMapIndex),
   8156                                     IntPtrConstant(kSlowIteratorOffset));
   8157         var_map_index.Bind(map_index);
   8158         var_array_map.Bind(UndefinedConstant());
   8159         Goto(&allocate_iterator);
   8160       }
   8161     }
   8162 
   8163     Bind(&if_istypedarray);
   8164     {
   8165       Node* map_index =
   8166           IntPtrAdd(IntPtrConstant(kBaseMapIndex - UINT8_ELEMENTS),
   8167                     ChangeUint32ToWord(LoadMapElementsKind(array_map)));
   8168       CSA_ASSERT(
   8169           this, IntPtrLessThan(map_index, IntPtrConstant(kBaseMapIndex +
   8170                                                          kFastIteratorOffset)));
   8171       CSA_ASSERT(this, IntPtrGreaterThanOrEqual(map_index,
   8172                                                 IntPtrConstant(kBaseMapIndex)));
   8173       var_map_index.Bind(map_index);
   8174       var_array_map.Bind(UndefinedConstant());
   8175       Goto(&allocate_iterator);
   8176     }
   8177   }
   8178 
   8179   Bind(&allocate_iterator);
   8180   {
   8181     Node* map = LoadFixedArrayElement(LoadNativeContext(context),
   8182                                       var_map_index.value());
   8183     var_result.Bind(AllocateJSArrayIterator(array, var_array_map.value(), map));
   8184     Goto(&return_result);
   8185   }
   8186 
   8187   Bind(&return_result);
   8188   return var_result.value();
   8189 }
   8190 
   8191 Node* CodeStubAssembler::AllocateJSArrayIterator(Node* array, Node* array_map,
   8192                                                  Node* map) {
   8193   Node* iterator = Allocate(JSArrayIterator::kSize);
   8194   StoreMapNoWriteBarrier(iterator, map);
   8195   StoreObjectFieldRoot(iterator, JSArrayIterator::kPropertiesOffset,
   8196                        Heap::kEmptyFixedArrayRootIndex);
   8197   StoreObjectFieldRoot(iterator, JSArrayIterator::kElementsOffset,
   8198                        Heap::kEmptyFixedArrayRootIndex);
   8199   StoreObjectFieldNoWriteBarrier(iterator,
   8200                                  JSArrayIterator::kIteratedObjectOffset, array);
   8201   StoreObjectFieldNoWriteBarrier(iterator, JSArrayIterator::kNextIndexOffset,
   8202                                  SmiConstant(Smi::FromInt(0)));
   8203   StoreObjectFieldNoWriteBarrier(
   8204       iterator, JSArrayIterator::kIteratedObjectMapOffset, array_map);
   8205   return iterator;
   8206 }
   8207 
   8208 Node* CodeStubAssembler::IsDetachedBuffer(Node* buffer) {
   8209   CSA_ASSERT(this, HasInstanceType(buffer, JS_ARRAY_BUFFER_TYPE));
   8210 
   8211   Node* buffer_bit_field = LoadObjectField(
   8212       buffer, JSArrayBuffer::kBitFieldOffset, MachineType::Uint32());
   8213   return IsSetWord32<JSArrayBuffer::WasNeutered>(buffer_bit_field);
   8214 }
   8215 
   8216 CodeStubArguments::CodeStubArguments(CodeStubAssembler* assembler, Node* argc,
   8217                                      Node* fp,
   8218                                      CodeStubAssembler::ParameterMode mode)
   8219     : assembler_(assembler),
   8220       argc_mode_(mode),
   8221       argc_(argc),
   8222       arguments_(nullptr),
   8223       fp_(fp != nullptr ? fp : assembler->LoadFramePointer()) {
   8224   Node* offset = assembler->ElementOffsetFromIndex(
   8225       argc_, FAST_ELEMENTS, mode,
   8226       (StandardFrameConstants::kFixedSlotCountAboveFp - 1) * kPointerSize);
   8227   arguments_ = assembler_->IntPtrAdd(fp_, offset);
   8228 }
   8229 
   8230 Node* CodeStubArguments::GetReceiver() const {
   8231   return assembler_->Load(MachineType::AnyTagged(), arguments_,
   8232                           assembler_->IntPtrConstant(kPointerSize));
   8233 }
   8234 
   8235 Node* CodeStubArguments::AtIndexPtr(
   8236     Node* index, CodeStubAssembler::ParameterMode mode) const {
   8237   typedef compiler::Node Node;
   8238   Node* negated_index = assembler_->IntPtrOrSmiSub(
   8239       assembler_->IntPtrOrSmiConstant(0, mode), index, mode);
   8240   Node* offset =
   8241       assembler_->ElementOffsetFromIndex(negated_index, FAST_ELEMENTS, mode, 0);
   8242   return assembler_->IntPtrAdd(arguments_, offset);
   8243 }
   8244 
   8245 Node* CodeStubArguments::AtIndex(Node* index,
   8246                                  CodeStubAssembler::ParameterMode mode) const {
   8247   DCHECK_EQ(argc_mode_, mode);
   8248   CSA_ASSERT(assembler_,
   8249              assembler_->UintPtrOrSmiLessThan(index, GetLength(), mode));
   8250   return assembler_->Load(MachineType::AnyTagged(), AtIndexPtr(index, mode));
   8251 }
   8252 
   8253 Node* CodeStubArguments::AtIndex(int index) const {
   8254   return AtIndex(assembler_->IntPtrConstant(index));
   8255 }
   8256 
   8257 void CodeStubArguments::ForEach(
   8258     const CodeStubAssembler::VariableList& vars,
   8259     const CodeStubArguments::ForEachBodyFunction& body, Node* first, Node* last,
   8260     CodeStubAssembler::ParameterMode mode) {
   8261   assembler_->Comment("CodeStubArguments::ForEach");
   8262   if (first == nullptr) {
   8263     first = assembler_->IntPtrOrSmiConstant(0, mode);
   8264   }
   8265   if (last == nullptr) {
   8266     DCHECK_EQ(mode, argc_mode_);
   8267     last = argc_;
   8268   }
   8269   Node* start = assembler_->IntPtrSub(
   8270       arguments_,
   8271       assembler_->ElementOffsetFromIndex(first, FAST_ELEMENTS, mode));
   8272   Node* end = assembler_->IntPtrSub(
   8273       arguments_,
   8274       assembler_->ElementOffsetFromIndex(last, FAST_ELEMENTS, mode));
   8275   assembler_->BuildFastLoop(vars, start, end,
   8276                             [this, &body](Node* current) {
   8277                               Node* arg = assembler_->Load(
   8278                                   MachineType::AnyTagged(), current);
   8279                               body(arg);
   8280                             },
   8281                             -kPointerSize, CodeStubAssembler::INTPTR_PARAMETERS,
   8282                             CodeStubAssembler::IndexAdvanceMode::kPost);
   8283 }
   8284 
   8285 void CodeStubArguments::PopAndReturn(Node* value) {
   8286   assembler_->PopAndReturn(
   8287       assembler_->IntPtrAdd(argc_, assembler_->IntPtrConstant(1)), value);
   8288 }
   8289 
   8290 Node* CodeStubAssembler::IsFastElementsKind(Node* elements_kind) {
   8291   return Uint32LessThanOrEqual(elements_kind,
   8292                                Int32Constant(LAST_FAST_ELEMENTS_KIND));
   8293 }
   8294 
   8295 Node* CodeStubAssembler::IsHoleyFastElementsKind(Node* elements_kind) {
   8296   CSA_ASSERT(this, IsFastElementsKind(elements_kind));
   8297 
   8298   STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == (FAST_SMI_ELEMENTS | 1));
   8299   STATIC_ASSERT(FAST_HOLEY_ELEMENTS == (FAST_ELEMENTS | 1));
   8300   STATIC_ASSERT(FAST_HOLEY_DOUBLE_ELEMENTS == (FAST_DOUBLE_ELEMENTS | 1));
   8301 
   8302   // Check prototype chain if receiver does not have packed elements.
   8303   Node* holey_elements = Word32And(elements_kind, Int32Constant(1));
   8304   return Word32Equal(holey_elements, Int32Constant(1));
   8305 }
   8306 
   8307 Node* CodeStubAssembler::IsDebugActive() {
   8308   Node* is_debug_active = Load(
   8309       MachineType::Uint8(),
   8310       ExternalConstant(ExternalReference::debug_is_active_address(isolate())));
   8311   return Word32NotEqual(is_debug_active, Int32Constant(0));
   8312 }
   8313 
   8314 Node* CodeStubAssembler::IsPromiseHookEnabledOrDebugIsActive() {
   8315   Node* const promise_hook_or_debug_is_active =
   8316       Load(MachineType::Uint8(),
   8317            ExternalConstant(
   8318                ExternalReference::promise_hook_or_debug_is_active_address(
   8319                    isolate())));
   8320   return Word32NotEqual(promise_hook_or_debug_is_active, Int32Constant(0));
   8321 }
   8322 
   8323 Node* CodeStubAssembler::AllocateFunctionWithMapAndContext(Node* map,
   8324                                                            Node* shared_info,
   8325                                                            Node* context) {
   8326   Node* const code = BitcastTaggedToWord(
   8327       LoadObjectField(shared_info, SharedFunctionInfo::kCodeOffset));
   8328   Node* const code_entry =
   8329       IntPtrAdd(code, IntPtrConstant(Code::kHeaderSize - kHeapObjectTag));
   8330 
   8331   Node* const fun = Allocate(JSFunction::kSize);
   8332   StoreMapNoWriteBarrier(fun, map);
   8333   StoreObjectFieldRoot(fun, JSObject::kPropertiesOffset,
   8334                        Heap::kEmptyFixedArrayRootIndex);
   8335   StoreObjectFieldRoot(fun, JSObject::kElementsOffset,
   8336                        Heap::kEmptyFixedArrayRootIndex);
   8337   StoreObjectFieldRoot(fun, JSFunction::kFeedbackVectorOffset,
   8338                        Heap::kUndefinedCellRootIndex);
   8339   StoreObjectFieldRoot(fun, JSFunction::kPrototypeOrInitialMapOffset,
   8340                        Heap::kTheHoleValueRootIndex);
   8341   StoreObjectFieldNoWriteBarrier(fun, JSFunction::kSharedFunctionInfoOffset,
   8342                                  shared_info);
   8343   StoreObjectFieldNoWriteBarrier(fun, JSFunction::kContextOffset, context);
   8344   StoreObjectFieldNoWriteBarrier(fun, JSFunction::kCodeEntryOffset, code_entry,
   8345                                  MachineType::PointerRepresentation());
   8346   StoreObjectFieldRoot(fun, JSFunction::kNextFunctionLinkOffset,
   8347                        Heap::kUndefinedValueRootIndex);
   8348 
   8349   return fun;
   8350 }
   8351 
   8352 Node* CodeStubAssembler::AllocatePromiseReactionJobInfo(
   8353     Node* value, Node* tasks, Node* deferred_promise, Node* deferred_on_resolve,
   8354     Node* deferred_on_reject, Node* context) {
   8355   Node* const result = Allocate(PromiseReactionJobInfo::kSize);
   8356   StoreMapNoWriteBarrier(result, Heap::kPromiseReactionJobInfoMapRootIndex);
   8357   StoreObjectFieldNoWriteBarrier(result, PromiseReactionJobInfo::kValueOffset,
   8358                                  value);
   8359   StoreObjectFieldNoWriteBarrier(result, PromiseReactionJobInfo::kTasksOffset,
   8360                                  tasks);
   8361   StoreObjectFieldNoWriteBarrier(
   8362       result, PromiseReactionJobInfo::kDeferredPromiseOffset, deferred_promise);
   8363   StoreObjectFieldNoWriteBarrier(
   8364       result, PromiseReactionJobInfo::kDeferredOnResolveOffset,
   8365       deferred_on_resolve);
   8366   StoreObjectFieldNoWriteBarrier(
   8367       result, PromiseReactionJobInfo::kDeferredOnRejectOffset,
   8368       deferred_on_reject);
   8369   StoreObjectFieldNoWriteBarrier(result, PromiseReactionJobInfo::kContextOffset,
   8370                                  context);
   8371   return result;
   8372 }
   8373 
   8374 Node* CodeStubAssembler::MarkerIsFrameType(Node* marker_or_function,
   8375                                            StackFrame::Type frame_type) {
   8376   return WordEqual(
   8377       marker_or_function,
   8378       IntPtrConstant(StackFrame::TypeToMarker(StackFrame::ARGUMENTS_ADAPTOR)));
   8379 }
   8380 
   8381 Node* CodeStubAssembler::MarkerIsNotFrameType(Node* marker_or_function,
   8382                                               StackFrame::Type frame_type) {
   8383   return WordNotEqual(
   8384       marker_or_function,
   8385       IntPtrConstant(StackFrame::TypeToMarker(StackFrame::ARGUMENTS_ADAPTOR)));
   8386 }
   8387 
   8388 void CodeStubAssembler::Print(const char* s) {
   8389 #ifdef DEBUG
   8390   std::string formatted(s);
   8391   formatted += "\n";
   8392   Handle<String> string = isolate()->factory()->NewStringFromAsciiChecked(
   8393       formatted.c_str(), TENURED);
   8394   CallRuntime(Runtime::kGlobalPrint, NoContextConstant(), HeapConstant(string));
   8395 #endif
   8396 }
   8397 
   8398 void CodeStubAssembler::Print(const char* prefix, Node* tagged_value) {
   8399 #ifdef DEBUG
   8400   if (prefix != nullptr) {
   8401     std::string formatted(prefix);
   8402     formatted += ": ";
   8403     Handle<String> string = isolate()->factory()->NewStringFromAsciiChecked(
   8404         formatted.c_str(), TENURED);
   8405     CallRuntime(Runtime::kGlobalPrint, NoContextConstant(),
   8406                 HeapConstant(string));
   8407   }
   8408   CallRuntime(Runtime::kDebugPrint, NoContextConstant(), tagged_value);
   8409 #endif
   8410 }
   8411 
   8412 }  // namespace internal
   8413 }  // namespace v8
   8414