Home | History | Annotate | Download | only in builtins
      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 
      5 #include "src/builtins/builtins.h"
      6 #include "src/builtins/builtins-utils.h"
      7 
      8 #include "src/code-factory.h"
      9 
     10 namespace v8 {
     11 namespace internal {
     12 
     13 // -----------------------------------------------------------------------------
     14 // ES6 section 20.2.2 Function Properties of the Math Object
     15 
     16 // ES6 section - 20.2.2.1 Math.abs ( x )
     17 void Builtins::Generate_MathAbs(CodeStubAssembler* assembler) {
     18   typedef CodeStubAssembler::Label Label;
     19   typedef compiler::Node Node;
     20   typedef CodeStubAssembler::Variable Variable;
     21 
     22   Node* context = assembler->Parameter(4);
     23 
     24   // We might need to loop once for ToNumber conversion.
     25   Variable var_x(assembler, MachineRepresentation::kTagged);
     26   Label loop(assembler, &var_x);
     27   var_x.Bind(assembler->Parameter(1));
     28   assembler->Goto(&loop);
     29   assembler->Bind(&loop);
     30   {
     31     // Load the current {x} value.
     32     Node* x = var_x.value();
     33 
     34     // Check if {x} is a Smi or a HeapObject.
     35     Label if_xissmi(assembler), if_xisnotsmi(assembler);
     36     assembler->Branch(assembler->TaggedIsSmi(x), &if_xissmi, &if_xisnotsmi);
     37 
     38     assembler->Bind(&if_xissmi);
     39     {
     40       // Check if {x} is already positive.
     41       Label if_xispositive(assembler), if_xisnotpositive(assembler);
     42       assembler->BranchIfSmiLessThanOrEqual(
     43           assembler->SmiConstant(Smi::FromInt(0)), x, &if_xispositive,
     44           &if_xisnotpositive);
     45 
     46       assembler->Bind(&if_xispositive);
     47       {
     48         // Just return the input {x}.
     49         assembler->Return(x);
     50       }
     51 
     52       assembler->Bind(&if_xisnotpositive);
     53       {
     54         // Try to negate the {x} value.
     55         Node* pair = assembler->IntPtrSubWithOverflow(
     56             assembler->IntPtrConstant(0), assembler->BitcastTaggedToWord(x));
     57         Node* overflow = assembler->Projection(1, pair);
     58         Label if_overflow(assembler, Label::kDeferred),
     59             if_notoverflow(assembler);
     60         assembler->Branch(overflow, &if_overflow, &if_notoverflow);
     61 
     62         assembler->Bind(&if_notoverflow);
     63         {
     64           // There is a Smi representation for negated {x}.
     65           Node* result = assembler->Projection(0, pair);
     66           result = assembler->BitcastWordToTagged(result);
     67           assembler->Return(result);
     68         }
     69 
     70         assembler->Bind(&if_overflow);
     71         {
     72           Node* result = assembler->NumberConstant(0.0 - Smi::kMinValue);
     73           assembler->Return(result);
     74         }
     75       }
     76     }
     77 
     78     assembler->Bind(&if_xisnotsmi);
     79     {
     80       // Check if {x} is a HeapNumber.
     81       Label if_xisheapnumber(assembler),
     82           if_xisnotheapnumber(assembler, Label::kDeferred);
     83       assembler->Branch(
     84           assembler->WordEqual(assembler->LoadMap(x),
     85                                assembler->HeapNumberMapConstant()),
     86           &if_xisheapnumber, &if_xisnotheapnumber);
     87 
     88       assembler->Bind(&if_xisheapnumber);
     89       {
     90         Node* x_value = assembler->LoadHeapNumberValue(x);
     91         Node* value = assembler->Float64Abs(x_value);
     92         Node* result = assembler->AllocateHeapNumberWithValue(value);
     93         assembler->Return(result);
     94       }
     95 
     96       assembler->Bind(&if_xisnotheapnumber);
     97       {
     98         // Need to convert {x} to a Number first.
     99         Callable callable =
    100             CodeFactory::NonNumberToNumber(assembler->isolate());
    101         var_x.Bind(assembler->CallStub(callable, context, x));
    102         assembler->Goto(&loop);
    103       }
    104     }
    105   }
    106 }
    107 
    108 namespace {
    109 
    110 void Generate_MathRoundingOperation(
    111     CodeStubAssembler* assembler,
    112     compiler::Node* (CodeStubAssembler::*float64op)(compiler::Node*)) {
    113   typedef CodeStubAssembler::Label Label;
    114   typedef compiler::Node Node;
    115   typedef CodeStubAssembler::Variable Variable;
    116 
    117   Node* context = assembler->Parameter(4);
    118 
    119   // We might need to loop once for ToNumber conversion.
    120   Variable var_x(assembler, MachineRepresentation::kTagged);
    121   Label loop(assembler, &var_x);
    122   var_x.Bind(assembler->Parameter(1));
    123   assembler->Goto(&loop);
    124   assembler->Bind(&loop);
    125   {
    126     // Load the current {x} value.
    127     Node* x = var_x.value();
    128 
    129     // Check if {x} is a Smi or a HeapObject.
    130     Label if_xissmi(assembler), if_xisnotsmi(assembler);
    131     assembler->Branch(assembler->TaggedIsSmi(x), &if_xissmi, &if_xisnotsmi);
    132 
    133     assembler->Bind(&if_xissmi);
    134     {
    135       // Nothing to do when {x} is a Smi.
    136       assembler->Return(x);
    137     }
    138 
    139     assembler->Bind(&if_xisnotsmi);
    140     {
    141       // Check if {x} is a HeapNumber.
    142       Label if_xisheapnumber(assembler),
    143           if_xisnotheapnumber(assembler, Label::kDeferred);
    144       assembler->Branch(
    145           assembler->WordEqual(assembler->LoadMap(x),
    146                                assembler->HeapNumberMapConstant()),
    147           &if_xisheapnumber, &if_xisnotheapnumber);
    148 
    149       assembler->Bind(&if_xisheapnumber);
    150       {
    151         Node* x_value = assembler->LoadHeapNumberValue(x);
    152         Node* value = (assembler->*float64op)(x_value);
    153         Node* result = assembler->ChangeFloat64ToTagged(value);
    154         assembler->Return(result);
    155       }
    156 
    157       assembler->Bind(&if_xisnotheapnumber);
    158       {
    159         // Need to convert {x} to a Number first.
    160         Callable callable =
    161             CodeFactory::NonNumberToNumber(assembler->isolate());
    162         var_x.Bind(assembler->CallStub(callable, context, x));
    163         assembler->Goto(&loop);
    164       }
    165     }
    166   }
    167 }
    168 
    169 void Generate_MathUnaryOperation(
    170     CodeStubAssembler* assembler,
    171     compiler::Node* (CodeStubAssembler::*float64op)(compiler::Node*)) {
    172   typedef compiler::Node Node;
    173 
    174   Node* x = assembler->Parameter(1);
    175   Node* context = assembler->Parameter(4);
    176   Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
    177   Node* value = (assembler->*float64op)(x_value);
    178   Node* result = assembler->AllocateHeapNumberWithValue(value);
    179   assembler->Return(result);
    180 }
    181 
    182 }  // namespace
    183 
    184 // ES6 section 20.2.2.2 Math.acos ( x )
    185 void Builtins::Generate_MathAcos(CodeStubAssembler* assembler) {
    186   Generate_MathUnaryOperation(assembler, &CodeStubAssembler::Float64Acos);
    187 }
    188 
    189 // ES6 section 20.2.2.3 Math.acosh ( x )
    190 void Builtins::Generate_MathAcosh(CodeStubAssembler* assembler) {
    191   Generate_MathUnaryOperation(assembler, &CodeStubAssembler::Float64Acosh);
    192 }
    193 
    194 // ES6 section 20.2.2.4 Math.asin ( x )
    195 void Builtins::Generate_MathAsin(CodeStubAssembler* assembler) {
    196   Generate_MathUnaryOperation(assembler, &CodeStubAssembler::Float64Asin);
    197 }
    198 
    199 // ES6 section 20.2.2.5 Math.asinh ( x )
    200 void Builtins::Generate_MathAsinh(CodeStubAssembler* assembler) {
    201   Generate_MathUnaryOperation(assembler, &CodeStubAssembler::Float64Asinh);
    202 }
    203 
    204 // ES6 section 20.2.2.6 Math.atan ( x )
    205 void Builtins::Generate_MathAtan(CodeStubAssembler* assembler) {
    206   Generate_MathUnaryOperation(assembler, &CodeStubAssembler::Float64Atan);
    207 }
    208 
    209 // ES6 section 20.2.2.7 Math.atanh ( x )
    210 void Builtins::Generate_MathAtanh(CodeStubAssembler* assembler) {
    211   Generate_MathUnaryOperation(assembler, &CodeStubAssembler::Float64Atanh);
    212 }
    213 
    214 // ES6 section 20.2.2.8 Math.atan2 ( y, x )
    215 void Builtins::Generate_MathAtan2(CodeStubAssembler* assembler) {
    216   using compiler::Node;
    217 
    218   Node* y = assembler->Parameter(1);
    219   Node* x = assembler->Parameter(2);
    220   Node* context = assembler->Parameter(5);
    221   Node* y_value = assembler->TruncateTaggedToFloat64(context, y);
    222   Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
    223   Node* value = assembler->Float64Atan2(y_value, x_value);
    224   Node* result = assembler->AllocateHeapNumberWithValue(value);
    225   assembler->Return(result);
    226 }
    227 
    228 // ES6 section 20.2.2.10 Math.ceil ( x )
    229 void Builtins::Generate_MathCeil(CodeStubAssembler* assembler) {
    230   Generate_MathRoundingOperation(assembler, &CodeStubAssembler::Float64Ceil);
    231 }
    232 
    233 // ES6 section 20.2.2.9 Math.cbrt ( x )
    234 void Builtins::Generate_MathCbrt(CodeStubAssembler* assembler) {
    235   Generate_MathUnaryOperation(assembler, &CodeStubAssembler::Float64Cbrt);
    236 }
    237 
    238 // ES6 section 20.2.2.11 Math.clz32 ( x )
    239 void Builtins::Generate_MathClz32(CodeStubAssembler* assembler) {
    240   typedef CodeStubAssembler::Label Label;
    241   typedef compiler::Node Node;
    242   typedef CodeStubAssembler::Variable Variable;
    243 
    244   Node* context = assembler->Parameter(4);
    245 
    246   // Shared entry point for the clz32 operation.
    247   Variable var_clz32_x(assembler, MachineRepresentation::kWord32);
    248   Label do_clz32(assembler);
    249 
    250   // We might need to loop once for ToNumber conversion.
    251   Variable var_x(assembler, MachineRepresentation::kTagged);
    252   Label loop(assembler, &var_x);
    253   var_x.Bind(assembler->Parameter(1));
    254   assembler->Goto(&loop);
    255   assembler->Bind(&loop);
    256   {
    257     // Load the current {x} value.
    258     Node* x = var_x.value();
    259 
    260     // Check if {x} is a Smi or a HeapObject.
    261     Label if_xissmi(assembler), if_xisnotsmi(assembler);
    262     assembler->Branch(assembler->TaggedIsSmi(x), &if_xissmi, &if_xisnotsmi);
    263 
    264     assembler->Bind(&if_xissmi);
    265     {
    266       var_clz32_x.Bind(assembler->SmiToWord32(x));
    267       assembler->Goto(&do_clz32);
    268     }
    269 
    270     assembler->Bind(&if_xisnotsmi);
    271     {
    272       // Check if {x} is a HeapNumber.
    273       Label if_xisheapnumber(assembler),
    274           if_xisnotheapnumber(assembler, Label::kDeferred);
    275       assembler->Branch(
    276           assembler->WordEqual(assembler->LoadMap(x),
    277                                assembler->HeapNumberMapConstant()),
    278           &if_xisheapnumber, &if_xisnotheapnumber);
    279 
    280       assembler->Bind(&if_xisheapnumber);
    281       {
    282         var_clz32_x.Bind(assembler->TruncateHeapNumberValueToWord32(x));
    283         assembler->Goto(&do_clz32);
    284       }
    285 
    286       assembler->Bind(&if_xisnotheapnumber);
    287       {
    288         // Need to convert {x} to a Number first.
    289         Callable callable =
    290             CodeFactory::NonNumberToNumber(assembler->isolate());
    291         var_x.Bind(assembler->CallStub(callable, context, x));
    292         assembler->Goto(&loop);
    293       }
    294     }
    295   }
    296 
    297   assembler->Bind(&do_clz32);
    298   {
    299     Node* x_value = var_clz32_x.value();
    300     Node* value = assembler->Word32Clz(x_value);
    301     Node* result = assembler->ChangeInt32ToTagged(value);
    302     assembler->Return(result);
    303   }
    304 }
    305 
    306 // ES6 section 20.2.2.12 Math.cos ( x )
    307 void Builtins::Generate_MathCos(CodeStubAssembler* assembler) {
    308   Generate_MathUnaryOperation(assembler, &CodeStubAssembler::Float64Cos);
    309 }
    310 
    311 // ES6 section 20.2.2.13 Math.cosh ( x )
    312 void Builtins::Generate_MathCosh(CodeStubAssembler* assembler) {
    313   Generate_MathUnaryOperation(assembler, &CodeStubAssembler::Float64Cosh);
    314 }
    315 
    316 // ES6 section 20.2.2.14 Math.exp ( x )
    317 void Builtins::Generate_MathExp(CodeStubAssembler* assembler) {
    318   Generate_MathUnaryOperation(assembler, &CodeStubAssembler::Float64Exp);
    319 }
    320 
    321 // ES6 section 20.2.2.15 Math.expm1 ( x )
    322 void Builtins::Generate_MathExpm1(CodeStubAssembler* assembler) {
    323   Generate_MathUnaryOperation(assembler, &CodeStubAssembler::Float64Expm1);
    324 }
    325 
    326 // ES6 section 20.2.2.16 Math.floor ( x )
    327 void Builtins::Generate_MathFloor(CodeStubAssembler* assembler) {
    328   Generate_MathRoundingOperation(assembler, &CodeStubAssembler::Float64Floor);
    329 }
    330 
    331 // ES6 section 20.2.2.17 Math.fround ( x )
    332 void Builtins::Generate_MathFround(CodeStubAssembler* assembler) {
    333   using compiler::Node;
    334 
    335   Node* x = assembler->Parameter(1);
    336   Node* context = assembler->Parameter(4);
    337   Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
    338   Node* value32 = assembler->TruncateFloat64ToFloat32(x_value);
    339   Node* value = assembler->ChangeFloat32ToFloat64(value32);
    340   Node* result = assembler->AllocateHeapNumberWithValue(value);
    341   assembler->Return(result);
    342 }
    343 
    344 // ES6 section 20.2.2.18 Math.hypot ( value1, value2, ...values )
    345 BUILTIN(MathHypot) {
    346   HandleScope scope(isolate);
    347   int const length = args.length() - 1;
    348   if (length == 0) return Smi::kZero;
    349   DCHECK_LT(0, length);
    350   double max = 0;
    351   bool one_arg_is_nan = false;
    352   List<double> abs_values(length);
    353   for (int i = 0; i < length; i++) {
    354     Handle<Object> x = args.at<Object>(i + 1);
    355     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, x, Object::ToNumber(x));
    356     double abs_value = std::abs(x->Number());
    357 
    358     if (std::isnan(abs_value)) {
    359       one_arg_is_nan = true;
    360     } else {
    361       abs_values.Add(abs_value);
    362       if (max < abs_value) {
    363         max = abs_value;
    364       }
    365     }
    366   }
    367 
    368   if (max == V8_INFINITY) {
    369     return *isolate->factory()->NewNumber(V8_INFINITY);
    370   }
    371 
    372   if (one_arg_is_nan) {
    373     return isolate->heap()->nan_value();
    374   }
    375 
    376   if (max == 0) {
    377     return Smi::kZero;
    378   }
    379   DCHECK_GT(max, 0);
    380 
    381   // Kahan summation to avoid rounding errors.
    382   // Normalize the numbers to the largest one to avoid overflow.
    383   double sum = 0;
    384   double compensation = 0;
    385   for (int i = 0; i < length; i++) {
    386     double n = abs_values.at(i) / max;
    387     double summand = n * n - compensation;
    388     double preliminary = sum + summand;
    389     compensation = (preliminary - sum) - summand;
    390     sum = preliminary;
    391   }
    392 
    393   return *isolate->factory()->NewNumber(std::sqrt(sum) * max);
    394 }
    395 
    396 // ES6 section 20.2.2.19 Math.imul ( x, y )
    397 void Builtins::Generate_MathImul(CodeStubAssembler* assembler) {
    398   using compiler::Node;
    399 
    400   Node* x = assembler->Parameter(1);
    401   Node* y = assembler->Parameter(2);
    402   Node* context = assembler->Parameter(5);
    403   Node* x_value = assembler->TruncateTaggedToWord32(context, x);
    404   Node* y_value = assembler->TruncateTaggedToWord32(context, y);
    405   Node* value = assembler->Int32Mul(x_value, y_value);
    406   Node* result = assembler->ChangeInt32ToTagged(value);
    407   assembler->Return(result);
    408 }
    409 
    410 // ES6 section 20.2.2.20 Math.log ( x )
    411 void Builtins::Generate_MathLog(CodeStubAssembler* assembler) {
    412   Generate_MathUnaryOperation(assembler, &CodeStubAssembler::Float64Log);
    413 }
    414 
    415 // ES6 section 20.2.2.21 Math.log1p ( x )
    416 void Builtins::Generate_MathLog1p(CodeStubAssembler* assembler) {
    417   Generate_MathUnaryOperation(assembler, &CodeStubAssembler::Float64Log1p);
    418 }
    419 
    420 // ES6 section 20.2.2.22 Math.log10 ( x )
    421 void Builtins::Generate_MathLog10(CodeStubAssembler* assembler) {
    422   Generate_MathUnaryOperation(assembler, &CodeStubAssembler::Float64Log10);
    423 }
    424 
    425 // ES6 section 20.2.2.23 Math.log2 ( x )
    426 void Builtins::Generate_MathLog2(CodeStubAssembler* assembler) {
    427   Generate_MathUnaryOperation(assembler, &CodeStubAssembler::Float64Log2);
    428 }
    429 
    430 // ES6 section 20.2.2.26 Math.pow ( x, y )
    431 void Builtins::Generate_MathPow(CodeStubAssembler* assembler) {
    432   using compiler::Node;
    433 
    434   Node* x = assembler->Parameter(1);
    435   Node* y = assembler->Parameter(2);
    436   Node* context = assembler->Parameter(5);
    437   Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
    438   Node* y_value = assembler->TruncateTaggedToFloat64(context, y);
    439   Node* value = assembler->Float64Pow(x_value, y_value);
    440   Node* result = assembler->ChangeFloat64ToTagged(value);
    441   assembler->Return(result);
    442 }
    443 
    444 // ES6 section 20.2.2.27 Math.random ( )
    445 void Builtins::Generate_MathRandom(CodeStubAssembler* assembler) {
    446   using compiler::Node;
    447 
    448   Node* context = assembler->Parameter(3);
    449   Node* native_context = assembler->LoadNativeContext(context);
    450 
    451   // Load cache index.
    452   CodeStubAssembler::Variable smi_index(assembler,
    453                                         MachineRepresentation::kTagged);
    454   smi_index.Bind(assembler->LoadContextElement(
    455       native_context, Context::MATH_RANDOM_INDEX_INDEX));
    456 
    457   // Cached random numbers are exhausted if index is 0. Go to slow path.
    458   CodeStubAssembler::Label if_cached(assembler);
    459   assembler->GotoIf(assembler->SmiAbove(smi_index.value(),
    460                                         assembler->SmiConstant(Smi::kZero)),
    461                     &if_cached);
    462 
    463   // Cache exhausted, populate the cache. Return value is the new index.
    464   smi_index.Bind(
    465       assembler->CallRuntime(Runtime::kGenerateRandomNumbers, context));
    466   assembler->Goto(&if_cached);
    467 
    468   // Compute next index by decrement.
    469   assembler->Bind(&if_cached);
    470   Node* new_smi_index = assembler->SmiSub(
    471       smi_index.value(), assembler->SmiConstant(Smi::FromInt(1)));
    472   assembler->StoreContextElement(
    473       native_context, Context::MATH_RANDOM_INDEX_INDEX, new_smi_index);
    474 
    475   // Load and return next cached random number.
    476   Node* array = assembler->LoadContextElement(native_context,
    477                                               Context::MATH_RANDOM_CACHE_INDEX);
    478   Node* random = assembler->LoadFixedDoubleArrayElement(
    479       array, new_smi_index, MachineType::Float64(), 0,
    480       CodeStubAssembler::SMI_PARAMETERS);
    481   assembler->Return(assembler->AllocateHeapNumberWithValue(random));
    482 }
    483 
    484 // ES6 section 20.2.2.28 Math.round ( x )
    485 void Builtins::Generate_MathRound(CodeStubAssembler* assembler) {
    486   Generate_MathRoundingOperation(assembler, &CodeStubAssembler::Float64Round);
    487 }
    488 
    489 // ES6 section 20.2.2.29 Math.sign ( x )
    490 void Builtins::Generate_MathSign(CodeStubAssembler* assembler) {
    491   typedef CodeStubAssembler::Label Label;
    492   using compiler::Node;
    493 
    494   // Convert the {x} value to a Number.
    495   Node* x = assembler->Parameter(1);
    496   Node* context = assembler->Parameter(4);
    497   Node* x_value = assembler->TruncateTaggedToFloat64(context, x);
    498 
    499   // Return -1 if {x} is negative, 1 if {x} is positive, or {x} itself.
    500   Label if_xisnegative(assembler), if_xispositive(assembler);
    501   assembler->GotoIf(
    502       assembler->Float64LessThan(x_value, assembler->Float64Constant(0.0)),
    503       &if_xisnegative);
    504   assembler->GotoIf(
    505       assembler->Float64LessThan(assembler->Float64Constant(0.0), x_value),
    506       &if_xispositive);
    507   assembler->Return(assembler->ChangeFloat64ToTagged(x_value));
    508 
    509   assembler->Bind(&if_xisnegative);
    510   assembler->Return(assembler->SmiConstant(Smi::FromInt(-1)));
    511 
    512   assembler->Bind(&if_xispositive);
    513   assembler->Return(assembler->SmiConstant(Smi::FromInt(1)));
    514 }
    515 
    516 // ES6 section 20.2.2.30 Math.sin ( x )
    517 void Builtins::Generate_MathSin(CodeStubAssembler* assembler) {
    518   Generate_MathUnaryOperation(assembler, &CodeStubAssembler::Float64Sin);
    519 }
    520 
    521 // ES6 section 20.2.2.31 Math.sinh ( x )
    522 void Builtins::Generate_MathSinh(CodeStubAssembler* assembler) {
    523   Generate_MathUnaryOperation(assembler, &CodeStubAssembler::Float64Sinh);
    524 }
    525 
    526 // ES6 section 20.2.2.32 Math.sqrt ( x )
    527 void Builtins::Generate_MathSqrt(CodeStubAssembler* assembler) {
    528   Generate_MathUnaryOperation(assembler, &CodeStubAssembler::Float64Sqrt);
    529 }
    530 
    531 // ES6 section 20.2.2.33 Math.tan ( x )
    532 void Builtins::Generate_MathTan(CodeStubAssembler* assembler) {
    533   Generate_MathUnaryOperation(assembler, &CodeStubAssembler::Float64Tan);
    534 }
    535 
    536 // ES6 section 20.2.2.34 Math.tanh ( x )
    537 void Builtins::Generate_MathTanh(CodeStubAssembler* assembler) {
    538   Generate_MathUnaryOperation(assembler, &CodeStubAssembler::Float64Tanh);
    539 }
    540 
    541 // ES6 section 20.2.2.35 Math.trunc ( x )
    542 void Builtins::Generate_MathTrunc(CodeStubAssembler* assembler) {
    543   Generate_MathRoundingOperation(assembler, &CodeStubAssembler::Float64Trunc);
    544 }
    545 
    546 void Builtins::Generate_MathMax(MacroAssembler* masm) {
    547   Generate_MathMaxMin(masm, MathMaxMinKind::kMax);
    548 }
    549 
    550 void Builtins::Generate_MathMin(MacroAssembler* masm) {
    551   Generate_MathMaxMin(masm, MathMaxMinKind::kMin);
    552 }
    553 
    554 }  // namespace internal
    555 }  // namespace v8
    556