Home | History | Annotate | Download | only in src
      1 // Copyright 2015 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "src/objects.h"
      6 
      7 #include <cmath>
      8 #include <iomanip>
      9 #include <memory>
     10 #include <sstream>
     11 #include <vector>
     12 
     13 #include "src/objects-inl.h"
     14 
     15 #include "src/accessors.h"
     16 #include "src/allocation-site-scopes.h"
     17 #include "src/api-arguments-inl.h"
     18 #include "src/api-natives.h"
     19 #include "src/api.h"
     20 #include "src/arguments.h"
     21 #include "src/ast/ast.h"
     22 #include "src/ast/scopes.h"
     23 #include "src/base/bits.h"
     24 #include "src/base/utils/random-number-generator.h"
     25 #include "src/bootstrapper.h"
     26 #include "src/builtins/builtins.h"
     27 #include "src/code-stubs.h"
     28 #include "src/compiler.h"
     29 #include "src/counters-inl.h"
     30 #include "src/counters.h"
     31 #include "src/date.h"
     32 #include "src/debug/debug.h"
     33 #include "src/deoptimizer.h"
     34 #include "src/elements.h"
     35 #include "src/execution.h"
     36 #include "src/field-index-inl.h"
     37 #include "src/field-index.h"
     38 #include "src/field-type.h"
     39 #include "src/frames-inl.h"
     40 #include "src/globals.h"
     41 #include "src/ic/ic.h"
     42 #include "src/identity-map.h"
     43 #include "src/interpreter/bytecode-array-iterator.h"
     44 #include "src/interpreter/bytecode-decoder.h"
     45 #include "src/interpreter/interpreter.h"
     46 #include "src/isolate-inl.h"
     47 #include "src/keys.h"
     48 #include "src/log.h"
     49 #include "src/lookup-inl.h"
     50 #include "src/macro-assembler.h"
     51 #include "src/map-updater.h"
     52 #include "src/messages.h"
     53 #include "src/objects-body-descriptors-inl.h"
     54 #include "src/objects/api-callbacks.h"
     55 #include "src/objects/arguments-inl.h"
     56 #include "src/objects/bigint.h"
     57 #include "src/objects/code-inl.h"
     58 #include "src/objects/compilation-cache-inl.h"
     59 #include "src/objects/debug-objects-inl.h"
     60 #include "src/objects/frame-array-inl.h"
     61 #include "src/objects/hash-table-inl.h"
     62 #include "src/objects/js-array-inl.h"
     63 #ifdef V8_INTL_SUPPORT
     64 #include "src/objects/js-collator.h"
     65 #endif  // V8_INTL_SUPPORT
     66 #include "src/objects/js-collection-inl.h"
     67 #include "src/objects/js-generator-inl.h"
     68 #ifdef V8_INTL_SUPPORT
     69 #include "src/objects/js-list-format.h"
     70 #include "src/objects/js-locale.h"
     71 #endif  // V8_INTL_SUPPORT
     72 #include "src/objects/js-regexp-inl.h"
     73 #include "src/objects/js-regexp-string-iterator.h"
     74 #ifdef V8_INTL_SUPPORT
     75 #include "src/objects/js-plural-rules.h"
     76 #include "src/objects/js-relative-time-format.h"
     77 #endif  // V8_INTL_SUPPORT
     78 #include "src/objects/literal-objects-inl.h"
     79 #include "src/objects/map.h"
     80 #include "src/objects/microtask-inl.h"
     81 #include "src/objects/module-inl.h"
     82 #include "src/objects/promise-inl.h"
     83 #include "src/parsing/preparsed-scope-data.h"
     84 #include "src/property-descriptor.h"
     85 #include "src/prototype.h"
     86 #include "src/regexp/jsregexp.h"
     87 #include "src/safepoint-table.h"
     88 #include "src/snapshot/code-serializer.h"
     89 #include "src/snapshot/snapshot.h"
     90 #include "src/source-position-table.h"
     91 #include "src/string-builder-inl.h"
     92 #include "src/string-search.h"
     93 #include "src/string-stream.h"
     94 #include "src/unicode-cache-inl.h"
     95 #include "src/unicode-decoder.h"
     96 #include "src/utils-inl.h"
     97 #include "src/wasm/wasm-engine.h"
     98 #include "src/wasm/wasm-objects.h"
     99 #include "src/zone/zone.h"
    100 
    101 #ifdef ENABLE_DISASSEMBLER
    102 #include "src/disasm.h"
    103 #include "src/disassembler.h"
    104 #include "src/eh-frame.h"
    105 #endif
    106 
    107 namespace v8 {
    108 namespace internal {
    109 
    110 bool ComparisonResultToBool(Operation op, ComparisonResult result) {
    111   switch (op) {
    112     case Operation::kLessThan:
    113       return result == ComparisonResult::kLessThan;
    114     case Operation::kLessThanOrEqual:
    115       return result == ComparisonResult::kLessThan ||
    116              result == ComparisonResult::kEqual;
    117     case Operation::kGreaterThan:
    118       return result == ComparisonResult::kGreaterThan;
    119     case Operation::kGreaterThanOrEqual:
    120       return result == ComparisonResult::kGreaterThan ||
    121              result == ComparisonResult::kEqual;
    122     default:
    123       break;
    124   }
    125   UNREACHABLE();
    126 }
    127 
    128 std::ostream& operator<<(std::ostream& os, InstanceType instance_type) {
    129   switch (instance_type) {
    130 #define WRITE_TYPE(TYPE) \
    131   case TYPE:             \
    132     return os << #TYPE;
    133     INSTANCE_TYPE_LIST(WRITE_TYPE)
    134 #undef WRITE_TYPE
    135   }
    136   UNREACHABLE();
    137 }
    138 
    139 Handle<FieldType> Object::OptimalType(Isolate* isolate,
    140                                       Representation representation) {
    141   if (representation.IsNone()) return FieldType::None(isolate);
    142   if (FLAG_track_field_types) {
    143     if (representation.IsHeapObject() && IsHeapObject()) {
    144       // We can track only JavaScript objects with stable maps.
    145       Handle<Map> map(HeapObject::cast(this)->map(), isolate);
    146       if (map->is_stable() && map->IsJSReceiverMap()) {
    147         return FieldType::Class(map, isolate);
    148       }
    149     }
    150   }
    151   return FieldType::Any(isolate);
    152 }
    153 
    154 MaybeHandle<JSReceiver> Object::ToObject(Isolate* isolate,
    155                                          Handle<Object> object,
    156                                          Handle<Context> native_context,
    157                                          const char* method_name) {
    158   if (object->IsJSReceiver()) return Handle<JSReceiver>::cast(object);
    159   Handle<JSFunction> constructor;
    160   if (object->IsSmi()) {
    161     constructor = handle(native_context->number_function(), isolate);
    162   } else {
    163     int constructor_function_index =
    164         Handle<HeapObject>::cast(object)->map()->GetConstructorFunctionIndex();
    165     if (constructor_function_index == Map::kNoConstructorFunctionIndex) {
    166       if (method_name != nullptr) {
    167         THROW_NEW_ERROR(
    168             isolate,
    169             NewTypeError(
    170                 MessageTemplate::kCalledOnNullOrUndefined,
    171                 isolate->factory()->NewStringFromAsciiChecked(method_name)),
    172             JSReceiver);
    173       }
    174       THROW_NEW_ERROR(isolate,
    175                       NewTypeError(MessageTemplate::kUndefinedOrNullToObject),
    176                       JSReceiver);
    177     }
    178     constructor = handle(
    179         JSFunction::cast(native_context->get(constructor_function_index)),
    180         isolate);
    181   }
    182   Handle<JSObject> result = isolate->factory()->NewJSObject(constructor);
    183   Handle<JSValue>::cast(result)->set_value(*object);
    184   return result;
    185 }
    186 
    187 // ES6 section 9.2.1.2, OrdinaryCallBindThis for sloppy callee.
    188 // static
    189 MaybeHandle<JSReceiver> Object::ConvertReceiver(Isolate* isolate,
    190                                                 Handle<Object> object) {
    191   if (object->IsJSReceiver()) return Handle<JSReceiver>::cast(object);
    192   if (object->IsNullOrUndefined(isolate)) {
    193     return isolate->global_proxy();
    194   }
    195   return Object::ToObject(isolate, object);
    196 }
    197 
    198 // static
    199 MaybeHandle<Object> Object::ConvertToNumberOrNumeric(Isolate* isolate,
    200                                                      Handle<Object> input,
    201                                                      Conversion mode) {
    202   while (true) {
    203     if (input->IsNumber()) {
    204       return input;
    205     }
    206     if (input->IsString()) {
    207       return String::ToNumber(isolate, Handle<String>::cast(input));
    208     }
    209     if (input->IsOddball()) {
    210       return Oddball::ToNumber(isolate, Handle<Oddball>::cast(input));
    211     }
    212     if (input->IsSymbol()) {
    213       THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kSymbolToNumber),
    214                       Object);
    215     }
    216     if (input->IsBigInt()) {
    217       if (mode == Conversion::kToNumeric) return input;
    218       DCHECK_EQ(mode, Conversion::kToNumber);
    219       THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kBigIntToNumber),
    220                       Object);
    221     }
    222     ASSIGN_RETURN_ON_EXCEPTION(
    223         isolate, input, JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(input),
    224                                                 ToPrimitiveHint::kNumber),
    225         Object);
    226   }
    227 }
    228 
    229 // static
    230 MaybeHandle<Object> Object::ConvertToInteger(Isolate* isolate,
    231                                              Handle<Object> input) {
    232   ASSIGN_RETURN_ON_EXCEPTION(
    233       isolate, input,
    234       ConvertToNumberOrNumeric(isolate, input, Conversion::kToNumber), Object);
    235   if (input->IsSmi()) return input;
    236   return isolate->factory()->NewNumber(DoubleToInteger(input->Number()));
    237 }
    238 
    239 // static
    240 MaybeHandle<Object> Object::ConvertToInt32(Isolate* isolate,
    241                                            Handle<Object> input) {
    242   ASSIGN_RETURN_ON_EXCEPTION(
    243       isolate, input,
    244       ConvertToNumberOrNumeric(isolate, input, Conversion::kToNumber), Object);
    245   if (input->IsSmi()) return input;
    246   return isolate->factory()->NewNumberFromInt(DoubleToInt32(input->Number()));
    247 }
    248 
    249 // static
    250 MaybeHandle<Object> Object::ConvertToUint32(Isolate* isolate,
    251                                             Handle<Object> input) {
    252   ASSIGN_RETURN_ON_EXCEPTION(
    253       isolate, input,
    254       ConvertToNumberOrNumeric(isolate, input, Conversion::kToNumber), Object);
    255   if (input->IsSmi()) return handle(Smi::cast(*input)->ToUint32Smi(), isolate);
    256   return isolate->factory()->NewNumberFromUint(DoubleToUint32(input->Number()));
    257 }
    258 
    259 // static
    260 MaybeHandle<Name> Object::ConvertToName(Isolate* isolate,
    261                                         Handle<Object> input) {
    262   ASSIGN_RETURN_ON_EXCEPTION(
    263       isolate, input, Object::ToPrimitive(input, ToPrimitiveHint::kString),
    264       Name);
    265   if (input->IsName()) return Handle<Name>::cast(input);
    266   return ToString(isolate, input);
    267 }
    268 
    269 // ES6 7.1.14
    270 // static
    271 MaybeHandle<Object> Object::ConvertToPropertyKey(Isolate* isolate,
    272                                                  Handle<Object> value) {
    273   // 1. Let key be ToPrimitive(argument, hint String).
    274   MaybeHandle<Object> maybe_key =
    275       Object::ToPrimitive(value, ToPrimitiveHint::kString);
    276   // 2. ReturnIfAbrupt(key).
    277   Handle<Object> key;
    278   if (!maybe_key.ToHandle(&key)) return key;
    279   // 3. If Type(key) is Symbol, then return key.
    280   if (key->IsSymbol()) return key;
    281   // 4. Return ToString(key).
    282   // Extending spec'ed behavior, we'd be happy to return an element index.
    283   if (key->IsSmi()) return key;
    284   if (key->IsHeapNumber()) {
    285     uint32_t uint_value;
    286     if (value->ToArrayLength(&uint_value) &&
    287         uint_value <= static_cast<uint32_t>(Smi::kMaxValue)) {
    288       return handle(Smi::FromInt(static_cast<int>(uint_value)), isolate);
    289     }
    290   }
    291   return Object::ToString(isolate, key);
    292 }
    293 
    294 // static
    295 MaybeHandle<String> Object::ConvertToString(Isolate* isolate,
    296                                             Handle<Object> input) {
    297   while (true) {
    298     if (input->IsOddball()) {
    299       return handle(Handle<Oddball>::cast(input)->to_string(), isolate);
    300     }
    301     if (input->IsNumber()) {
    302       return isolate->factory()->NumberToString(input);
    303     }
    304     if (input->IsSymbol()) {
    305       THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kSymbolToString),
    306                       String);
    307     }
    308     if (input->IsBigInt()) {
    309       return BigInt::ToString(isolate, Handle<BigInt>::cast(input));
    310     }
    311     ASSIGN_RETURN_ON_EXCEPTION(
    312         isolate, input, JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(input),
    313                                                 ToPrimitiveHint::kString),
    314         String);
    315     // The previous isString() check happened in Object::ToString and thus we
    316     // put it at the end of the loop in this helper.
    317     if (input->IsString()) {
    318       return Handle<String>::cast(input);
    319     }
    320   }
    321 }
    322 
    323 namespace {
    324 
    325 bool IsErrorObject(Isolate* isolate, Handle<Object> object) {
    326   if (!object->IsJSReceiver()) return false;
    327   Handle<Symbol> symbol = isolate->factory()->stack_trace_symbol();
    328   return JSReceiver::HasOwnProperty(Handle<JSReceiver>::cast(object), symbol)
    329       .FromMaybe(false);
    330 }
    331 
    332 Handle<String> AsStringOrEmpty(Isolate* isolate, Handle<Object> object) {
    333   return object->IsString() ? Handle<String>::cast(object)
    334                             : isolate->factory()->empty_string();
    335 }
    336 
    337 Handle<String> NoSideEffectsErrorToString(Isolate* isolate,
    338                                           Handle<Object> input) {
    339   Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(input);
    340 
    341   Handle<Name> name_key = isolate->factory()->name_string();
    342   Handle<Object> name = JSReceiver::GetDataProperty(receiver, name_key);
    343   Handle<String> name_str = AsStringOrEmpty(isolate, name);
    344 
    345   Handle<Name> msg_key = isolate->factory()->message_string();
    346   Handle<Object> msg = JSReceiver::GetDataProperty(receiver, msg_key);
    347   Handle<String> msg_str = AsStringOrEmpty(isolate, msg);
    348 
    349   if (name_str->length() == 0) return msg_str;
    350   if (msg_str->length() == 0) return name_str;
    351 
    352   IncrementalStringBuilder builder(isolate);
    353   builder.AppendString(name_str);
    354   builder.AppendCString(": ");
    355   builder.AppendString(msg_str);
    356 
    357   return builder.Finish().ToHandleChecked();
    358 }
    359 
    360 }  // namespace
    361 
    362 // static
    363 Handle<String> Object::NoSideEffectsToString(Isolate* isolate,
    364                                              Handle<Object> input) {
    365   DisallowJavascriptExecution no_js(isolate);
    366 
    367   if (input->IsString() || input->IsNumeric() || input->IsOddball()) {
    368     return Object::ToString(isolate, input).ToHandleChecked();
    369   } else if (input->IsFunction()) {
    370     // -- F u n c t i o n
    371     Handle<String> fun_str;
    372     if (input->IsJSBoundFunction()) {
    373       fun_str = JSBoundFunction::ToString(Handle<JSBoundFunction>::cast(input));
    374     } else {
    375       DCHECK(input->IsJSFunction());
    376       fun_str = JSFunction::ToString(Handle<JSFunction>::cast(input));
    377     }
    378 
    379     if (fun_str->length() > 128) {
    380       IncrementalStringBuilder builder(isolate);
    381       builder.AppendString(isolate->factory()->NewSubString(fun_str, 0, 111));
    382       builder.AppendCString("...<omitted>...");
    383       builder.AppendString(isolate->factory()->NewSubString(
    384           fun_str, fun_str->length() - 2, fun_str->length()));
    385 
    386       return builder.Finish().ToHandleChecked();
    387     }
    388     return fun_str;
    389   } else if (input->IsSymbol()) {
    390     // -- S y m b o l
    391     Handle<Symbol> symbol = Handle<Symbol>::cast(input);
    392 
    393     IncrementalStringBuilder builder(isolate);
    394     builder.AppendCString("Symbol(");
    395     if (symbol->name()->IsString()) {
    396       builder.AppendString(handle(String::cast(symbol->name()), isolate));
    397     }
    398     builder.AppendCharacter(')');
    399 
    400     return builder.Finish().ToHandleChecked();
    401   } else if (input->IsJSReceiver()) {
    402     // -- J S R e c e i v e r
    403     Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(input);
    404     Handle<Object> to_string = JSReceiver::GetDataProperty(
    405         receiver, isolate->factory()->toString_string());
    406 
    407     if (IsErrorObject(isolate, input) ||
    408         *to_string == *isolate->error_to_string()) {
    409       // When internally formatting error objects, use a side-effects-free
    410       // version of Error.prototype.toString independent of the actually
    411       // installed toString method.
    412       return NoSideEffectsErrorToString(isolate, input);
    413     } else if (*to_string == *isolate->object_to_string()) {
    414       Handle<Object> ctor = JSReceiver::GetDataProperty(
    415           receiver, isolate->factory()->constructor_string());
    416       if (ctor->IsFunction()) {
    417         Handle<String> ctor_name;
    418         if (ctor->IsJSBoundFunction()) {
    419           ctor_name = JSBoundFunction::GetName(
    420                           isolate, Handle<JSBoundFunction>::cast(ctor))
    421                           .ToHandleChecked();
    422         } else if (ctor->IsJSFunction()) {
    423           Handle<Object> ctor_name_obj =
    424               JSFunction::GetName(isolate, Handle<JSFunction>::cast(ctor));
    425           ctor_name = AsStringOrEmpty(isolate, ctor_name_obj);
    426         }
    427 
    428         if (ctor_name->length() != 0) {
    429           IncrementalStringBuilder builder(isolate);
    430           builder.AppendCString("#<");
    431           builder.AppendString(ctor_name);
    432           builder.AppendCString(">");
    433 
    434           return builder.Finish().ToHandleChecked();
    435         }
    436       }
    437     }
    438   }
    439 
    440   // At this point, input is either none of the above or a JSReceiver.
    441 
    442   Handle<JSReceiver> receiver;
    443   if (input->IsJSReceiver()) {
    444     receiver = Handle<JSReceiver>::cast(input);
    445   } else {
    446     // This is the only case where Object::ToObject throws.
    447     DCHECK(!input->IsSmi());
    448     int constructor_function_index =
    449         Handle<HeapObject>::cast(input)->map()->GetConstructorFunctionIndex();
    450     if (constructor_function_index == Map::kNoConstructorFunctionIndex) {
    451       return isolate->factory()->NewStringFromAsciiChecked("[object Unknown]");
    452     }
    453 
    454     receiver = Object::ToObject(isolate, input, isolate->native_context())
    455                    .ToHandleChecked();
    456   }
    457 
    458   Handle<String> builtin_tag = handle(receiver->class_name(), isolate);
    459   Handle<Object> tag_obj = JSReceiver::GetDataProperty(
    460       receiver, isolate->factory()->to_string_tag_symbol());
    461   Handle<String> tag =
    462       tag_obj->IsString() ? Handle<String>::cast(tag_obj) : builtin_tag;
    463 
    464   IncrementalStringBuilder builder(isolate);
    465   builder.AppendCString("[object ");
    466   builder.AppendString(tag);
    467   builder.AppendCString("]");
    468 
    469   return builder.Finish().ToHandleChecked();
    470 }
    471 
    472 // static
    473 MaybeHandle<Object> Object::ConvertToLength(Isolate* isolate,
    474                                             Handle<Object> input) {
    475   ASSIGN_RETURN_ON_EXCEPTION(isolate, input, ToNumber(isolate, input), Object);
    476   if (input->IsSmi()) {
    477     int value = std::max(Smi::ToInt(*input), 0);
    478     return handle(Smi::FromInt(value), isolate);
    479   }
    480   double len = DoubleToInteger(input->Number());
    481   if (len <= 0.0) {
    482     return handle(Smi::kZero, isolate);
    483   } else if (len >= kMaxSafeInteger) {
    484     len = kMaxSafeInteger;
    485   }
    486   return isolate->factory()->NewNumber(len);
    487 }
    488 
    489 // static
    490 MaybeHandle<Object> Object::ConvertToIndex(
    491     Isolate* isolate, Handle<Object> input,
    492     MessageTemplate::Template error_index) {
    493   if (input->IsUndefined(isolate)) return handle(Smi::kZero, isolate);
    494   ASSIGN_RETURN_ON_EXCEPTION(isolate, input, ToNumber(isolate, input), Object);
    495   if (input->IsSmi() && Smi::ToInt(*input) >= 0) return input;
    496   double len = DoubleToInteger(input->Number()) + 0.0;
    497   auto js_len = isolate->factory()->NewNumber(len);
    498   if (len < 0.0 || len > kMaxSafeInteger) {
    499     THROW_NEW_ERROR(isolate, NewRangeError(error_index, js_len), Object);
    500   }
    501   return js_len;
    502 }
    503 
    504 bool Object::BooleanValue(Isolate* isolate) {
    505   if (IsSmi()) return Smi::ToInt(this) != 0;
    506   DCHECK(IsHeapObject());
    507   if (IsBoolean()) return IsTrue(isolate);
    508   if (IsNullOrUndefined(isolate)) return false;
    509   if (IsUndetectable()) return false;  // Undetectable object is false.
    510   if (IsString()) return String::cast(this)->length() != 0;
    511   if (IsHeapNumber()) return DoubleToBoolean(HeapNumber::cast(this)->value());
    512   if (IsBigInt()) return BigInt::cast(this)->ToBoolean();
    513   return true;
    514 }
    515 
    516 
    517 namespace {
    518 
    519 // TODO(bmeurer): Maybe we should introduce a marker interface Number,
    520 // where we put all these methods at some point?
    521 ComparisonResult NumberCompare(double x, double y) {
    522   if (std::isnan(x) || std::isnan(y)) {
    523     return ComparisonResult::kUndefined;
    524   } else if (x < y) {
    525     return ComparisonResult::kLessThan;
    526   } else if (x > y) {
    527     return ComparisonResult::kGreaterThan;
    528   } else {
    529     return ComparisonResult::kEqual;
    530   }
    531 }
    532 
    533 bool NumberEquals(double x, double y) {
    534   // Must check explicitly for NaN's on Windows, but -0 works fine.
    535   if (std::isnan(x)) return false;
    536   if (std::isnan(y)) return false;
    537   return x == y;
    538 }
    539 
    540 bool NumberEquals(const Object* x, const Object* y) {
    541   return NumberEquals(x->Number(), y->Number());
    542 }
    543 
    544 bool NumberEquals(Handle<Object> x, Handle<Object> y) {
    545   return NumberEquals(*x, *y);
    546 }
    547 
    548 ComparisonResult Reverse(ComparisonResult result) {
    549   if (result == ComparisonResult::kLessThan) {
    550     return ComparisonResult::kGreaterThan;
    551   }
    552   if (result == ComparisonResult::kGreaterThan) {
    553     return ComparisonResult::kLessThan;
    554   }
    555   return result;
    556 }
    557 
    558 }  // anonymous namespace
    559 
    560 // static
    561 Maybe<ComparisonResult> Object::Compare(Isolate* isolate, Handle<Object> x,
    562                                         Handle<Object> y) {
    563   // ES6 section 7.2.11 Abstract Relational Comparison step 3 and 4.
    564   if (!Object::ToPrimitive(x, ToPrimitiveHint::kNumber).ToHandle(&x) ||
    565       !Object::ToPrimitive(y, ToPrimitiveHint::kNumber).ToHandle(&y)) {
    566     return Nothing<ComparisonResult>();
    567   }
    568   if (x->IsString() && y->IsString()) {
    569     // ES6 section 7.2.11 Abstract Relational Comparison step 5.
    570     return Just(String::Compare(isolate, Handle<String>::cast(x),
    571                                 Handle<String>::cast(y)));
    572   }
    573   if (x->IsBigInt() && y->IsString()) {
    574     return Just(BigInt::CompareToString(isolate, Handle<BigInt>::cast(x),
    575                                         Handle<String>::cast(y)));
    576   }
    577   if (x->IsString() && y->IsBigInt()) {
    578     return Just(Reverse(BigInt::CompareToString(
    579         isolate, Handle<BigInt>::cast(y), Handle<String>::cast(x))));
    580   }
    581   // ES6 section 7.2.11 Abstract Relational Comparison step 6.
    582   if (!Object::ToNumeric(isolate, x).ToHandle(&x) ||
    583       !Object::ToNumeric(isolate, y).ToHandle(&y)) {
    584     return Nothing<ComparisonResult>();
    585   }
    586 
    587   bool x_is_number = x->IsNumber();
    588   bool y_is_number = y->IsNumber();
    589   if (x_is_number && y_is_number) {
    590     return Just(NumberCompare(x->Number(), y->Number()));
    591   } else if (!x_is_number && !y_is_number) {
    592     return Just(BigInt::CompareToBigInt(Handle<BigInt>::cast(x),
    593                                         Handle<BigInt>::cast(y)));
    594   } else if (x_is_number) {
    595     return Just(Reverse(BigInt::CompareToNumber(Handle<BigInt>::cast(y), x)));
    596   } else {
    597     return Just(BigInt::CompareToNumber(Handle<BigInt>::cast(x), y));
    598   }
    599 }
    600 
    601 
    602 // static
    603 Maybe<bool> Object::Equals(Isolate* isolate, Handle<Object> x,
    604                            Handle<Object> y) {
    605   // This is the generic version of Abstract Equality Comparison. Must be in
    606   // sync with CodeStubAssembler::Equal.
    607   while (true) {
    608     if (x->IsNumber()) {
    609       if (y->IsNumber()) {
    610         return Just(NumberEquals(x, y));
    611       } else if (y->IsBoolean()) {
    612         return Just(NumberEquals(*x, Handle<Oddball>::cast(y)->to_number()));
    613       } else if (y->IsString()) {
    614         return Just(NumberEquals(
    615             x, String::ToNumber(isolate, Handle<String>::cast(y))));
    616       } else if (y->IsBigInt()) {
    617         return Just(BigInt::EqualToNumber(Handle<BigInt>::cast(y), x));
    618       } else if (y->IsJSReceiver()) {
    619         if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(y))
    620                  .ToHandle(&y)) {
    621           return Nothing<bool>();
    622         }
    623       } else {
    624         return Just(false);
    625       }
    626     } else if (x->IsString()) {
    627       if (y->IsString()) {
    628         return Just(String::Equals(isolate, Handle<String>::cast(x),
    629                                    Handle<String>::cast(y)));
    630       } else if (y->IsNumber()) {
    631         x = String::ToNumber(isolate, Handle<String>::cast(x));
    632         return Just(NumberEquals(x, y));
    633       } else if (y->IsBoolean()) {
    634         x = String::ToNumber(isolate, Handle<String>::cast(x));
    635         return Just(NumberEquals(*x, Handle<Oddball>::cast(y)->to_number()));
    636       } else if (y->IsBigInt()) {
    637         return Just(BigInt::EqualToString(isolate, Handle<BigInt>::cast(y),
    638                                           Handle<String>::cast(x)));
    639       } else if (y->IsJSReceiver()) {
    640         if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(y))
    641                  .ToHandle(&y)) {
    642           return Nothing<bool>();
    643         }
    644       } else {
    645         return Just(false);
    646       }
    647     } else if (x->IsBoolean()) {
    648       if (y->IsOddball()) {
    649         return Just(x.is_identical_to(y));
    650       } else if (y->IsNumber()) {
    651         return Just(NumberEquals(Handle<Oddball>::cast(x)->to_number(), *y));
    652       } else if (y->IsString()) {
    653         y = String::ToNumber(isolate, Handle<String>::cast(y));
    654         return Just(NumberEquals(Handle<Oddball>::cast(x)->to_number(), *y));
    655       } else if (y->IsBigInt()) {
    656         x = Oddball::ToNumber(isolate, Handle<Oddball>::cast(x));
    657         return Just(BigInt::EqualToNumber(Handle<BigInt>::cast(y), x));
    658       } else if (y->IsJSReceiver()) {
    659         if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(y))
    660                  .ToHandle(&y)) {
    661           return Nothing<bool>();
    662         }
    663         x = Oddball::ToNumber(isolate, Handle<Oddball>::cast(x));
    664       } else {
    665         return Just(false);
    666       }
    667     } else if (x->IsSymbol()) {
    668       if (y->IsSymbol()) {
    669         return Just(x.is_identical_to(y));
    670       } else if (y->IsJSReceiver()) {
    671         if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(y))
    672                  .ToHandle(&y)) {
    673           return Nothing<bool>();
    674         }
    675       } else {
    676         return Just(false);
    677       }
    678     } else if (x->IsBigInt()) {
    679       if (y->IsBigInt()) {
    680         return Just(BigInt::EqualToBigInt(BigInt::cast(*x), BigInt::cast(*y)));
    681       }
    682       return Equals(isolate, y, x);
    683     } else if (x->IsJSReceiver()) {
    684       if (y->IsJSReceiver()) {
    685         return Just(x.is_identical_to(y));
    686       } else if (y->IsUndetectable()) {
    687         return Just(x->IsUndetectable());
    688       } else if (y->IsBoolean()) {
    689         y = Oddball::ToNumber(isolate, Handle<Oddball>::cast(y));
    690       } else if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(x))
    691                       .ToHandle(&x)) {
    692         return Nothing<bool>();
    693       }
    694     } else {
    695       return Just(x->IsUndetectable() && y->IsUndetectable());
    696     }
    697   }
    698 }
    699 
    700 
    701 bool Object::StrictEquals(Object* that) {
    702   if (this->IsNumber()) {
    703     if (!that->IsNumber()) return false;
    704     return NumberEquals(this, that);
    705   } else if (this->IsString()) {
    706     if (!that->IsString()) return false;
    707     return String::cast(this)->Equals(String::cast(that));
    708   } else if (this->IsBigInt()) {
    709     if (!that->IsBigInt()) return false;
    710     return BigInt::EqualToBigInt(BigInt::cast(this), BigInt::cast(that));
    711   }
    712   return this == that;
    713 }
    714 
    715 
    716 // static
    717 Handle<String> Object::TypeOf(Isolate* isolate, Handle<Object> object) {
    718   if (object->IsNumber()) return isolate->factory()->number_string();
    719   if (object->IsOddball())
    720     return handle(Oddball::cast(*object)->type_of(), isolate);
    721   if (object->IsUndetectable()) {
    722     return isolate->factory()->undefined_string();
    723   }
    724   if (object->IsString()) return isolate->factory()->string_string();
    725   if (object->IsSymbol()) return isolate->factory()->symbol_string();
    726   if (object->IsBigInt()) return isolate->factory()->bigint_string();
    727   if (object->IsCallable()) return isolate->factory()->function_string();
    728   return isolate->factory()->object_string();
    729 }
    730 
    731 
    732 // static
    733 MaybeHandle<Object> Object::Add(Isolate* isolate, Handle<Object> lhs,
    734                                 Handle<Object> rhs) {
    735   if (lhs->IsNumber() && rhs->IsNumber()) {
    736     return isolate->factory()->NewNumber(lhs->Number() + rhs->Number());
    737   } else if (lhs->IsString() && rhs->IsString()) {
    738     return isolate->factory()->NewConsString(Handle<String>::cast(lhs),
    739                                              Handle<String>::cast(rhs));
    740   }
    741   ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToPrimitive(lhs), Object);
    742   ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToPrimitive(rhs), Object);
    743   if (lhs->IsString() || rhs->IsString()) {
    744     ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToString(isolate, rhs),
    745                                Object);
    746     ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToString(isolate, lhs),
    747                                Object);
    748     return isolate->factory()->NewConsString(Handle<String>::cast(lhs),
    749                                              Handle<String>::cast(rhs));
    750   }
    751   ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(isolate, rhs),
    752                              Object);
    753   ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(isolate, lhs),
    754                              Object);
    755   return isolate->factory()->NewNumber(lhs->Number() + rhs->Number());
    756 }
    757 
    758 
    759 // static
    760 MaybeHandle<Object> Object::OrdinaryHasInstance(Isolate* isolate,
    761                                                 Handle<Object> callable,
    762                                                 Handle<Object> object) {
    763   // The {callable} must have a [[Call]] internal method.
    764   if (!callable->IsCallable()) return isolate->factory()->false_value();
    765 
    766   // Check if {callable} is a bound function, and if so retrieve its
    767   // [[BoundTargetFunction]] and use that instead of {callable}.
    768   if (callable->IsJSBoundFunction()) {
    769     Handle<Object> bound_callable(
    770         Handle<JSBoundFunction>::cast(callable)->bound_target_function(),
    771         isolate);
    772     return Object::InstanceOf(isolate, object, bound_callable);
    773   }
    774 
    775   // If {object} is not a receiver, return false.
    776   if (!object->IsJSReceiver()) return isolate->factory()->false_value();
    777 
    778   // Get the "prototype" of {callable}; raise an error if it's not a receiver.
    779   Handle<Object> prototype;
    780   ASSIGN_RETURN_ON_EXCEPTION(
    781       isolate, prototype,
    782       Object::GetProperty(isolate, callable,
    783                           isolate->factory()->prototype_string()),
    784       Object);
    785   if (!prototype->IsJSReceiver()) {
    786     THROW_NEW_ERROR(
    787         isolate,
    788         NewTypeError(MessageTemplate::kInstanceofNonobjectProto, prototype),
    789         Object);
    790   }
    791 
    792   // Return whether or not {prototype} is in the prototype chain of {object}.
    793   Maybe<bool> result = JSReceiver::HasInPrototypeChain(
    794       isolate, Handle<JSReceiver>::cast(object), prototype);
    795   if (result.IsNothing()) return MaybeHandle<Object>();
    796   return isolate->factory()->ToBoolean(result.FromJust());
    797 }
    798 
    799 // static
    800 MaybeHandle<Object> Object::InstanceOf(Isolate* isolate, Handle<Object> object,
    801                                        Handle<Object> callable) {
    802   // The {callable} must be a receiver.
    803   if (!callable->IsJSReceiver()) {
    804     THROW_NEW_ERROR(isolate,
    805                     NewTypeError(MessageTemplate::kNonObjectInInstanceOfCheck),
    806                     Object);
    807   }
    808 
    809   // Lookup the @@hasInstance method on {callable}.
    810   Handle<Object> inst_of_handler;
    811   ASSIGN_RETURN_ON_EXCEPTION(
    812       isolate, inst_of_handler,
    813       JSReceiver::GetMethod(Handle<JSReceiver>::cast(callable),
    814                             isolate->factory()->has_instance_symbol()),
    815       Object);
    816   if (!inst_of_handler->IsUndefined(isolate)) {
    817     // Call the {inst_of_handler} on the {callable}.
    818     Handle<Object> result;
    819     ASSIGN_RETURN_ON_EXCEPTION(
    820         isolate, result,
    821         Execution::Call(isolate, inst_of_handler, callable, 1, &object),
    822         Object);
    823     return isolate->factory()->ToBoolean(result->BooleanValue(isolate));
    824   }
    825 
    826   // The {callable} must have a [[Call]] internal method.
    827   if (!callable->IsCallable()) {
    828     THROW_NEW_ERROR(
    829         isolate, NewTypeError(MessageTemplate::kNonCallableInInstanceOfCheck),
    830         Object);
    831   }
    832 
    833   // Fall back to OrdinaryHasInstance with {callable} and {object}.
    834   Handle<Object> result;
    835   ASSIGN_RETURN_ON_EXCEPTION(
    836       isolate, result,
    837       JSReceiver::OrdinaryHasInstance(isolate, callable, object), Object);
    838   return result;
    839 }
    840 
    841 // static
    842 MaybeHandle<Object> Object::GetMethod(Handle<JSReceiver> receiver,
    843                                       Handle<Name> name) {
    844   Handle<Object> func;
    845   Isolate* isolate = receiver->GetIsolate();
    846   ASSIGN_RETURN_ON_EXCEPTION(
    847       isolate, func, JSReceiver::GetProperty(isolate, receiver, name), Object);
    848   if (func->IsNullOrUndefined(isolate)) {
    849     return isolate->factory()->undefined_value();
    850   }
    851   if (!func->IsCallable()) {
    852     THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kPropertyNotFunction,
    853                                           func, name, receiver),
    854                     Object);
    855   }
    856   return func;
    857 }
    858 
    859 namespace {
    860 
    861 MaybeHandle<FixedArray> CreateListFromArrayLikeFastPath(
    862     Isolate* isolate, Handle<Object> object, ElementTypes element_types) {
    863   if (element_types == ElementTypes::kAll) {
    864     if (object->IsJSArray()) {
    865       Handle<JSArray> array = Handle<JSArray>::cast(object);
    866       uint32_t length;
    867       if (!array->HasArrayPrototype(isolate) ||
    868           !array->length()->ToUint32(&length) || !array->HasFastElements() ||
    869           !JSObject::PrototypeHasNoElements(isolate, *array)) {
    870         return MaybeHandle<FixedArray>();
    871       }
    872       return array->GetElementsAccessor()->CreateListFromArrayLike(
    873           isolate, array, length);
    874     } else if (object->IsJSTypedArray()) {
    875       Handle<JSTypedArray> array = Handle<JSTypedArray>::cast(object);
    876       size_t length = array->length_value();
    877       if (array->WasNeutered() ||
    878           length > static_cast<size_t>(FixedArray::kMaxLength)) {
    879         return MaybeHandle<FixedArray>();
    880       }
    881       return array->GetElementsAccessor()->CreateListFromArrayLike(
    882           isolate, array, static_cast<uint32_t>(length));
    883     }
    884   }
    885   return MaybeHandle<FixedArray>();
    886 }
    887 
    888 }  // namespace
    889 
    890 // static
    891 MaybeHandle<FixedArray> Object::CreateListFromArrayLike(
    892     Isolate* isolate, Handle<Object> object, ElementTypes element_types) {
    893   // Fast-path for JSArray and JSTypedArray.
    894   MaybeHandle<FixedArray> fast_result =
    895       CreateListFromArrayLikeFastPath(isolate, object, element_types);
    896   if (!fast_result.is_null()) return fast_result;
    897   // 1. ReturnIfAbrupt(object).
    898   // 2. (default elementTypes -- not applicable.)
    899   // 3. If Type(obj) is not Object, throw a TypeError exception.
    900   if (!object->IsJSReceiver()) {
    901     THROW_NEW_ERROR(isolate,
    902                     NewTypeError(MessageTemplate::kCalledOnNonObject,
    903                                  isolate->factory()->NewStringFromAsciiChecked(
    904                                      "CreateListFromArrayLike")),
    905                     FixedArray);
    906   }
    907 
    908   // 4. Let len be ? ToLength(? Get(obj, "length")).
    909   Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(object);
    910   Handle<Object> raw_length_number;
    911   ASSIGN_RETURN_ON_EXCEPTION(isolate, raw_length_number,
    912                              Object::GetLengthFromArrayLike(isolate, receiver),
    913                              FixedArray);
    914   uint32_t len;
    915   if (!raw_length_number->ToUint32(&len) ||
    916       len > static_cast<uint32_t>(FixedArray::kMaxLength)) {
    917     THROW_NEW_ERROR(isolate,
    918                     NewRangeError(MessageTemplate::kInvalidArrayLength),
    919                     FixedArray);
    920   }
    921   // 5. Let list be an empty List.
    922   Handle<FixedArray> list = isolate->factory()->NewFixedArray(len);
    923   // 6. Let index be 0.
    924   // 7. Repeat while index < len:
    925   for (uint32_t index = 0; index < len; ++index) {
    926     // 7a. Let indexName be ToString(index).
    927     // 7b. Let next be ? Get(obj, indexName).
    928     Handle<Object> next;
    929     ASSIGN_RETURN_ON_EXCEPTION(isolate, next,
    930                                JSReceiver::GetElement(isolate, receiver, index),
    931                                FixedArray);
    932     switch (element_types) {
    933       case ElementTypes::kAll:
    934         // Nothing to do.
    935         break;
    936       case ElementTypes::kStringAndSymbol: {
    937         // 7c. If Type(next) is not an element of elementTypes, throw a
    938         //     TypeError exception.
    939         if (!next->IsName()) {
    940           THROW_NEW_ERROR(isolate,
    941                           NewTypeError(MessageTemplate::kNotPropertyName, next),
    942                           FixedArray);
    943         }
    944         // 7d. Append next as the last element of list.
    945         // Internalize on the fly so we can use pointer identity later.
    946         next = isolate->factory()->InternalizeName(Handle<Name>::cast(next));
    947         break;
    948       }
    949     }
    950     list->set(index, *next);
    951     // 7e. Set index to index + 1. (See loop header.)
    952   }
    953   // 8. Return list.
    954   return list;
    955 }
    956 
    957 
    958 // static
    959 MaybeHandle<Object> Object::GetLengthFromArrayLike(Isolate* isolate,
    960                                                    Handle<JSReceiver> object) {
    961   Handle<Object> val;
    962   Handle<Name> key = isolate->factory()->length_string();
    963   ASSIGN_RETURN_ON_EXCEPTION(
    964       isolate, val, JSReceiver::GetProperty(isolate, object, key), Object);
    965   return Object::ToLength(isolate, val);
    966 }
    967 
    968 // static
    969 Maybe<bool> JSReceiver::HasProperty(LookupIterator* it) {
    970   for (; it->IsFound(); it->Next()) {
    971     switch (it->state()) {
    972       case LookupIterator::NOT_FOUND:
    973       case LookupIterator::TRANSITION:
    974         UNREACHABLE();
    975       case LookupIterator::JSPROXY:
    976         return JSProxy::HasProperty(it->isolate(), it->GetHolder<JSProxy>(),
    977                                     it->GetName());
    978       case LookupIterator::INTERCEPTOR: {
    979         Maybe<PropertyAttributes> result =
    980             JSObject::GetPropertyAttributesWithInterceptor(it);
    981         if (result.IsNothing()) return Nothing<bool>();
    982         if (result.FromJust() != ABSENT) return Just(true);
    983         break;
    984       }
    985       case LookupIterator::ACCESS_CHECK: {
    986         if (it->HasAccess()) break;
    987         Maybe<PropertyAttributes> result =
    988             JSObject::GetPropertyAttributesWithFailedAccessCheck(it);
    989         if (result.IsNothing()) return Nothing<bool>();
    990         return Just(result.FromJust() != ABSENT);
    991       }
    992       case LookupIterator::INTEGER_INDEXED_EXOTIC:
    993         // TypedArray out-of-bounds access.
    994         return Just(false);
    995       case LookupIterator::ACCESSOR:
    996       case LookupIterator::DATA:
    997         return Just(true);
    998     }
    999   }
   1000   return Just(false);
   1001 }
   1002 
   1003 // static
   1004 Maybe<bool> JSReceiver::HasOwnProperty(Handle<JSReceiver> object,
   1005                                        Handle<Name> name) {
   1006   if (object->IsJSModuleNamespace()) {
   1007     PropertyDescriptor desc;
   1008     return JSReceiver::GetOwnPropertyDescriptor(object->GetIsolate(), object,
   1009                                                 name, &desc);
   1010   }
   1011 
   1012   if (object->IsJSObject()) {  // Shortcut.
   1013     LookupIterator it = LookupIterator::PropertyOrElement(
   1014         object->GetIsolate(), object, name, object, LookupIterator::OWN);
   1015     return HasProperty(&it);
   1016   }
   1017 
   1018   Maybe<PropertyAttributes> attributes =
   1019       JSReceiver::GetOwnPropertyAttributes(object, name);
   1020   MAYBE_RETURN(attributes, Nothing<bool>());
   1021   return Just(attributes.FromJust() != ABSENT);
   1022 }
   1023 
   1024 // static
   1025 MaybeHandle<Object> Object::GetProperty(LookupIterator* it,
   1026                                         OnNonExistent on_non_existent) {
   1027   for (; it->IsFound(); it->Next()) {
   1028     switch (it->state()) {
   1029       case LookupIterator::NOT_FOUND:
   1030       case LookupIterator::TRANSITION:
   1031         UNREACHABLE();
   1032       case LookupIterator::JSPROXY: {
   1033         bool was_found;
   1034         MaybeHandle<Object> result =
   1035             JSProxy::GetProperty(it->isolate(), it->GetHolder<JSProxy>(),
   1036                                  it->GetName(), it->GetReceiver(), &was_found);
   1037         if (!was_found) it->NotFound();
   1038         return result;
   1039       }
   1040       case LookupIterator::INTERCEPTOR: {
   1041         bool done;
   1042         Handle<Object> result;
   1043         ASSIGN_RETURN_ON_EXCEPTION(
   1044             it->isolate(), result,
   1045             JSObject::GetPropertyWithInterceptor(it, &done), Object);
   1046         if (done) return result;
   1047         break;
   1048       }
   1049       case LookupIterator::ACCESS_CHECK:
   1050         if (it->HasAccess()) break;
   1051         return JSObject::GetPropertyWithFailedAccessCheck(it);
   1052       case LookupIterator::ACCESSOR:
   1053         return GetPropertyWithAccessor(it);
   1054       case LookupIterator::INTEGER_INDEXED_EXOTIC:
   1055         return it->isolate()->factory()->undefined_value();
   1056       case LookupIterator::DATA:
   1057         return it->GetDataValue();
   1058     }
   1059   }
   1060 
   1061   if (on_non_existent == OnNonExistent::kThrowReferenceError) {
   1062     THROW_NEW_ERROR(it->isolate(),
   1063                     NewReferenceError(MessageTemplate::kNotDefined, it->name()),
   1064                     Object);
   1065   }
   1066   return it->isolate()->factory()->undefined_value();
   1067 }
   1068 
   1069 
   1070 // static
   1071 MaybeHandle<Object> JSProxy::GetProperty(Isolate* isolate,
   1072                                          Handle<JSProxy> proxy,
   1073                                          Handle<Name> name,
   1074                                          Handle<Object> receiver,
   1075                                          bool* was_found) {
   1076   *was_found = true;
   1077 
   1078   DCHECK(!name->IsPrivate());
   1079   STACK_CHECK(isolate, MaybeHandle<Object>());
   1080   Handle<Name> trap_name = isolate->factory()->get_string();
   1081   // 1. Assert: IsPropertyKey(P) is true.
   1082   // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O.
   1083   Handle<Object> handler(proxy->handler(), isolate);
   1084   // 3. If handler is null, throw a TypeError exception.
   1085   // 4. Assert: Type(handler) is Object.
   1086   if (proxy->IsRevoked()) {
   1087     THROW_NEW_ERROR(isolate,
   1088                     NewTypeError(MessageTemplate::kProxyRevoked, trap_name),
   1089                     Object);
   1090   }
   1091   // 5. Let target be the value of the [[ProxyTarget]] internal slot of O.
   1092   Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate);
   1093   // 6. Let trap be ? GetMethod(handler, "get").
   1094   Handle<Object> trap;
   1095   ASSIGN_RETURN_ON_EXCEPTION(
   1096       isolate, trap,
   1097       Object::GetMethod(Handle<JSReceiver>::cast(handler), trap_name), Object);
   1098   // 7. If trap is undefined, then
   1099   if (trap->IsUndefined(isolate)) {
   1100     // 7.a Return target.[[Get]](P, Receiver).
   1101     LookupIterator it =
   1102         LookupIterator::PropertyOrElement(isolate, receiver, name, target);
   1103     MaybeHandle<Object> result = Object::GetProperty(&it);
   1104     *was_found = it.IsFound();
   1105     return result;
   1106   }
   1107   // 8. Let trapResult be ? Call(trap, handler, target, P, Receiver).
   1108   Handle<Object> trap_result;
   1109   Handle<Object> args[] = {target, name, receiver};
   1110   ASSIGN_RETURN_ON_EXCEPTION(
   1111       isolate, trap_result,
   1112       Execution::Call(isolate, trap, handler, arraysize(args), args), Object);
   1113 
   1114   MaybeHandle<Object> result =
   1115       JSProxy::CheckGetSetTrapResult(isolate, name, target, trap_result, kGet);
   1116   if (result.is_null()) {
   1117     return result;
   1118   }
   1119 
   1120   // 11. Return trap_result
   1121   return trap_result;
   1122 }
   1123 
   1124 // static
   1125 MaybeHandle<Object> JSProxy::CheckGetSetTrapResult(Isolate* isolate,
   1126                                                    Handle<Name> name,
   1127                                                    Handle<JSReceiver> target,
   1128                                                    Handle<Object> trap_result,
   1129                                                    AccessKind access_kind) {
   1130   // 9. Let targetDesc be ? target.[[GetOwnProperty]](P).
   1131   PropertyDescriptor target_desc;
   1132   Maybe<bool> target_found =
   1133       JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, &target_desc);
   1134   MAYBE_RETURN_NULL(target_found);
   1135   // 10. If targetDesc is not undefined, then
   1136   if (target_found.FromJust()) {
   1137     // 10.a. If IsDataDescriptor(targetDesc) and targetDesc.[[Configurable]] is
   1138     //       false and targetDesc.[[Writable]] is false, then
   1139     // 10.a.i. If SameValue(trapResult, targetDesc.[[Value]]) is false,
   1140     //        throw a TypeError exception.
   1141     bool inconsistent = PropertyDescriptor::IsDataDescriptor(&target_desc) &&
   1142                         !target_desc.configurable() &&
   1143                         !target_desc.writable() &&
   1144                         !trap_result->SameValue(*target_desc.value());
   1145     if (inconsistent) {
   1146       if (access_kind == kGet) {
   1147         THROW_NEW_ERROR(
   1148             isolate,
   1149             NewTypeError(MessageTemplate::kProxyGetNonConfigurableData, name,
   1150                          target_desc.value(), trap_result),
   1151             Object);
   1152       } else {
   1153         isolate->Throw(*isolate->factory()->NewTypeError(
   1154             MessageTemplate::kProxySetFrozenData, name));
   1155         return MaybeHandle<Object>();
   1156       }
   1157     }
   1158     // 10.b. If IsAccessorDescriptor(targetDesc) and targetDesc.[[Configurable]]
   1159     //       is false and targetDesc.[[Get]] is undefined, then
   1160     // 10.b.i. If trapResult is not undefined, throw a TypeError exception.
   1161     if (access_kind == kGet) {
   1162       inconsistent = PropertyDescriptor::IsAccessorDescriptor(&target_desc) &&
   1163                      !target_desc.configurable() &&
   1164                      target_desc.get()->IsUndefined(isolate) &&
   1165                      !trap_result->IsUndefined(isolate);
   1166     } else {
   1167       inconsistent = PropertyDescriptor::IsAccessorDescriptor(&target_desc) &&
   1168                      !target_desc.configurable() &&
   1169                      target_desc.set()->IsUndefined(isolate);
   1170     }
   1171     if (inconsistent) {
   1172       if (access_kind == kGet) {
   1173         THROW_NEW_ERROR(
   1174             isolate,
   1175             NewTypeError(MessageTemplate::kProxyGetNonConfigurableAccessor,
   1176                          name, trap_result),
   1177             Object);
   1178       } else {
   1179         isolate->Throw(*isolate->factory()->NewTypeError(
   1180             MessageTemplate::kProxySetFrozenAccessor, name));
   1181         return MaybeHandle<Object>();
   1182       }
   1183     }
   1184   }
   1185   return isolate->factory()->undefined_value();
   1186 }
   1187 
   1188 
   1189 Handle<Object> JSReceiver::GetDataProperty(LookupIterator* it) {
   1190   for (; it->IsFound(); it->Next()) {
   1191     switch (it->state()) {
   1192       case LookupIterator::INTERCEPTOR:
   1193       case LookupIterator::NOT_FOUND:
   1194       case LookupIterator::TRANSITION:
   1195         UNREACHABLE();
   1196       case LookupIterator::ACCESS_CHECK:
   1197         // Support calling this method without an active context, but refuse
   1198         // access to access-checked objects in that case.
   1199         if (it->isolate()->context() != nullptr && it->HasAccess()) continue;
   1200         V8_FALLTHROUGH;
   1201       case LookupIterator::JSPROXY:
   1202         it->NotFound();
   1203         return it->isolate()->factory()->undefined_value();
   1204       case LookupIterator::ACCESSOR:
   1205         // TODO(verwaest): For now this doesn't call into AccessorInfo, since
   1206         // clients don't need it. Update once relevant.
   1207         it->NotFound();
   1208         return it->isolate()->factory()->undefined_value();
   1209       case LookupIterator::INTEGER_INDEXED_EXOTIC:
   1210         return it->isolate()->factory()->undefined_value();
   1211       case LookupIterator::DATA:
   1212         return it->GetDataValue();
   1213     }
   1214   }
   1215   return it->isolate()->factory()->undefined_value();
   1216 }
   1217 
   1218 
   1219 bool Object::ToInt32(int32_t* value) {
   1220   if (IsSmi()) {
   1221     *value = Smi::ToInt(this);
   1222     return true;
   1223   }
   1224   if (IsHeapNumber()) {
   1225     double num = HeapNumber::cast(this)->value();
   1226     // Check range before conversion to avoid undefined behavior.
   1227     if (num >= kMinInt && num <= kMaxInt && FastI2D(FastD2I(num)) == num) {
   1228       *value = FastD2I(num);
   1229       return true;
   1230     }
   1231   }
   1232   return false;
   1233 }
   1234 
   1235 Handle<SharedFunctionInfo> FunctionTemplateInfo::GetOrCreateSharedFunctionInfo(
   1236     Isolate* isolate, Handle<FunctionTemplateInfo> info,
   1237     MaybeHandle<Name> maybe_name) {
   1238   Object* current_info = info->shared_function_info();
   1239   if (current_info->IsSharedFunctionInfo()) {
   1240     return handle(SharedFunctionInfo::cast(current_info), isolate);
   1241   }
   1242   Handle<Name> name;
   1243   Handle<String> name_string;
   1244   if (maybe_name.ToHandle(&name) && name->IsString()) {
   1245     name_string = Handle<String>::cast(name);
   1246   } else if (info->class_name()->IsString()) {
   1247     name_string = handle(String::cast(info->class_name()), isolate);
   1248   } else {
   1249     name_string = isolate->factory()->empty_string();
   1250   }
   1251   FunctionKind function_kind;
   1252   if (info->remove_prototype()) {
   1253     function_kind = kConciseMethod;
   1254   } else {
   1255     function_kind = kNormalFunction;
   1256   }
   1257   Handle<SharedFunctionInfo> result =
   1258       isolate->factory()->NewSharedFunctionInfoForApiFunction(name_string, info,
   1259                                                               function_kind);
   1260 
   1261   result->set_length(info->length());
   1262   result->DontAdaptArguments();
   1263   DCHECK(result->IsApiFunction());
   1264 
   1265   info->set_shared_function_info(*result);
   1266   return result;
   1267 }
   1268 
   1269 bool FunctionTemplateInfo::IsTemplateFor(Map* map) {
   1270   // There is a constraint on the object; check.
   1271   if (!map->IsJSObjectMap()) return false;
   1272   // Fetch the constructor function of the object.
   1273   Object* cons_obj = map->GetConstructor();
   1274   Object* type;
   1275   if (cons_obj->IsJSFunction()) {
   1276     JSFunction* fun = JSFunction::cast(cons_obj);
   1277     type = fun->shared()->function_data();
   1278   } else if (cons_obj->IsFunctionTemplateInfo()) {
   1279     type = FunctionTemplateInfo::cast(cons_obj);
   1280   } else {
   1281     return false;
   1282   }
   1283   // Iterate through the chain of inheriting function templates to
   1284   // see if the required one occurs.
   1285   while (type->IsFunctionTemplateInfo()) {
   1286     if (type == this) return true;
   1287     type = FunctionTemplateInfo::cast(type)->parent_template();
   1288   }
   1289   // Didn't find the required type in the inheritance chain.
   1290   return false;
   1291 }
   1292 
   1293 
   1294 // static
   1295 Handle<TemplateList> TemplateList::New(Isolate* isolate, int size) {
   1296   Handle<FixedArray> list =
   1297       isolate->factory()->NewFixedArray(kLengthIndex + size);
   1298   list->set(kLengthIndex, Smi::kZero);
   1299   return Handle<TemplateList>::cast(list);
   1300 }
   1301 
   1302 // static
   1303 Handle<TemplateList> TemplateList::Add(Isolate* isolate,
   1304                                        Handle<TemplateList> list,
   1305                                        Handle<i::Object> value) {
   1306   STATIC_ASSERT(kFirstElementIndex == 1);
   1307   int index = list->length() + 1;
   1308   Handle<i::FixedArray> fixed_array = Handle<FixedArray>::cast(list);
   1309   fixed_array = FixedArray::SetAndGrow(isolate, fixed_array, index, value);
   1310   fixed_array->set(kLengthIndex, Smi::FromInt(index));
   1311   return Handle<TemplateList>::cast(fixed_array);
   1312 }
   1313 
   1314 // static
   1315 MaybeHandle<JSObject> JSObject::New(Handle<JSFunction> constructor,
   1316                                     Handle<JSReceiver> new_target,
   1317                                     Handle<AllocationSite> site) {
   1318   // If called through new, new.target can be:
   1319   // - a subclass of constructor,
   1320   // - a proxy wrapper around constructor, or
   1321   // - the constructor itself.
   1322   // If called through Reflect.construct, it's guaranteed to be a constructor.
   1323   Isolate* const isolate = constructor->GetIsolate();
   1324   DCHECK(constructor->IsConstructor());
   1325   DCHECK(new_target->IsConstructor());
   1326   DCHECK(!constructor->has_initial_map() ||
   1327          constructor->initial_map()->instance_type() != JS_FUNCTION_TYPE);
   1328 
   1329   Handle<Map> initial_map;
   1330   ASSIGN_RETURN_ON_EXCEPTION(
   1331       isolate, initial_map,
   1332       JSFunction::GetDerivedMap(isolate, constructor, new_target), JSObject);
   1333   Handle<JSObject> result =
   1334       isolate->factory()->NewJSObjectFromMap(initial_map, NOT_TENURED, site);
   1335   if (initial_map->is_dictionary_map()) {
   1336     Handle<NameDictionary> dictionary =
   1337         NameDictionary::New(isolate, NameDictionary::kInitialCapacity);
   1338     result->SetProperties(*dictionary);
   1339   }
   1340   isolate->counters()->constructed_objects()->Increment();
   1341   isolate->counters()->constructed_objects_runtime()->Increment();
   1342   return result;
   1343 }
   1344 
   1345 // 9.1.12 ObjectCreate ( proto [ , internalSlotsList ] )
   1346 // Notice: This is NOT 19.1.2.2 Object.create ( O, Properties )
   1347 MaybeHandle<JSObject> JSObject::ObjectCreate(Isolate* isolate,
   1348                                              Handle<Object> prototype) {
   1349   // Generate the map with the specified {prototype} based on the Object
   1350   // function's initial map from the current native context.
   1351   // TODO(bmeurer): Use a dedicated cache for Object.create; think about
   1352   // slack tracking for Object.create.
   1353   Handle<Map> map =
   1354       Map::GetObjectCreateMap(isolate, Handle<HeapObject>::cast(prototype));
   1355 
   1356   // Actually allocate the object.
   1357   Handle<JSObject> object;
   1358   if (map->is_dictionary_map()) {
   1359     object = isolate->factory()->NewSlowJSObjectFromMap(map);
   1360   } else {
   1361     object = isolate->factory()->NewJSObjectFromMap(map);
   1362   }
   1363   return object;
   1364 }
   1365 
   1366 void JSObject::EnsureWritableFastElements(Handle<JSObject> object) {
   1367   DCHECK(object->HasSmiOrObjectElements() ||
   1368          object->HasFastStringWrapperElements());
   1369   FixedArray* raw_elems = FixedArray::cast(object->elements());
   1370   Heap* heap = object->GetHeap();
   1371   if (raw_elems->map() != ReadOnlyRoots(heap).fixed_cow_array_map()) return;
   1372   Isolate* isolate = heap->isolate();
   1373   Handle<FixedArray> elems(raw_elems, isolate);
   1374   Handle<FixedArray> writable_elems = isolate->factory()->CopyFixedArrayWithMap(
   1375       elems, isolate->factory()->fixed_array_map());
   1376   object->set_elements(*writable_elems);
   1377   isolate->counters()->cow_arrays_converted()->Increment();
   1378 }
   1379 
   1380 int JSObject::GetHeaderSize(InstanceType type,
   1381                             bool function_has_prototype_slot) {
   1382   switch (type) {
   1383     case JS_OBJECT_TYPE:
   1384     case JS_API_OBJECT_TYPE:
   1385     case JS_SPECIAL_API_OBJECT_TYPE:
   1386       return JSObject::kHeaderSize;
   1387     case JS_GENERATOR_OBJECT_TYPE:
   1388       return JSGeneratorObject::kSize;
   1389     case JS_ASYNC_GENERATOR_OBJECT_TYPE:
   1390       return JSAsyncGeneratorObject::kSize;
   1391     case JS_GLOBAL_PROXY_TYPE:
   1392       return JSGlobalProxy::kSize;
   1393     case JS_GLOBAL_OBJECT_TYPE:
   1394       return JSGlobalObject::kSize;
   1395     case JS_BOUND_FUNCTION_TYPE:
   1396       return JSBoundFunction::kSize;
   1397     case JS_FUNCTION_TYPE:
   1398       return JSFunction::GetHeaderSize(function_has_prototype_slot);
   1399     case JS_VALUE_TYPE:
   1400       return JSValue::kSize;
   1401     case JS_DATE_TYPE:
   1402       return JSDate::kSize;
   1403     case JS_ARRAY_TYPE:
   1404       return JSArray::kSize;
   1405     case JS_ARRAY_BUFFER_TYPE:
   1406       return JSArrayBuffer::kSize;
   1407     case JS_ARRAY_ITERATOR_TYPE:
   1408       return JSArrayIterator::kSize;
   1409     case JS_TYPED_ARRAY_TYPE:
   1410       return JSTypedArray::kSize;
   1411     case JS_DATA_VIEW_TYPE:
   1412       return JSDataView::kSize;
   1413     case JS_SET_TYPE:
   1414       return JSSet::kSize;
   1415     case JS_MAP_TYPE:
   1416       return JSMap::kSize;
   1417     case JS_SET_KEY_VALUE_ITERATOR_TYPE:
   1418     case JS_SET_VALUE_ITERATOR_TYPE:
   1419       return JSSetIterator::kSize;
   1420     case JS_MAP_KEY_ITERATOR_TYPE:
   1421     case JS_MAP_KEY_VALUE_ITERATOR_TYPE:
   1422     case JS_MAP_VALUE_ITERATOR_TYPE:
   1423       return JSMapIterator::kSize;
   1424     case JS_WEAK_MAP_TYPE:
   1425       return JSWeakMap::kSize;
   1426     case JS_WEAK_SET_TYPE:
   1427       return JSWeakSet::kSize;
   1428     case JS_PROMISE_TYPE:
   1429       return JSPromise::kSize;
   1430     case JS_REGEXP_TYPE:
   1431       return JSRegExp::kSize;
   1432     case JS_REGEXP_STRING_ITERATOR_TYPE:
   1433       return JSRegExpStringIterator::kSize;
   1434     case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
   1435       return JSObject::kHeaderSize;
   1436     case JS_MESSAGE_OBJECT_TYPE:
   1437       return JSMessageObject::kSize;
   1438     case JS_ARGUMENTS_TYPE:
   1439       return JSObject::kHeaderSize;
   1440     case JS_ERROR_TYPE:
   1441       return JSObject::kHeaderSize;
   1442     case JS_STRING_ITERATOR_TYPE:
   1443       return JSStringIterator::kSize;
   1444     case JS_MODULE_NAMESPACE_TYPE:
   1445       return JSModuleNamespace::kHeaderSize;
   1446 #ifdef V8_INTL_SUPPORT
   1447     case JS_INTL_COLLATOR_TYPE:
   1448       return JSCollator::kSize;
   1449     case JS_INTL_LIST_FORMAT_TYPE:
   1450       return JSListFormat::kSize;
   1451     case JS_INTL_LOCALE_TYPE:
   1452       return JSLocale::kSize;
   1453     case JS_INTL_PLURAL_RULES_TYPE:
   1454       return JSPluralRules::kSize;
   1455     case JS_INTL_RELATIVE_TIME_FORMAT_TYPE:
   1456       return JSRelativeTimeFormat::kSize;
   1457 #endif  // V8_INTL_SUPPORT
   1458     case WASM_GLOBAL_TYPE:
   1459       return WasmGlobalObject::kSize;
   1460     case WASM_INSTANCE_TYPE:
   1461       return WasmInstanceObject::kSize;
   1462     case WASM_MEMORY_TYPE:
   1463       return WasmMemoryObject::kSize;
   1464     case WASM_MODULE_TYPE:
   1465       return WasmModuleObject::kSize;
   1466     case WASM_TABLE_TYPE:
   1467       return WasmTableObject::kSize;
   1468     default:
   1469       UNREACHABLE();
   1470   }
   1471 }
   1472 
   1473 // ES6 9.5.1
   1474 // static
   1475 MaybeHandle<Object> JSProxy::GetPrototype(Handle<JSProxy> proxy) {
   1476   Isolate* isolate = proxy->GetIsolate();
   1477   Handle<String> trap_name = isolate->factory()->getPrototypeOf_string();
   1478 
   1479   STACK_CHECK(isolate, MaybeHandle<Object>());
   1480 
   1481   // 1. Let handler be the value of the [[ProxyHandler]] internal slot.
   1482   // 2. If handler is null, throw a TypeError exception.
   1483   // 3. Assert: Type(handler) is Object.
   1484   // 4. Let target be the value of the [[ProxyTarget]] internal slot.
   1485   if (proxy->IsRevoked()) {
   1486     THROW_NEW_ERROR(isolate,
   1487                     NewTypeError(MessageTemplate::kProxyRevoked, trap_name),
   1488                     Object);
   1489   }
   1490   Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate);
   1491   Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate);
   1492 
   1493   // 5. Let trap be ? GetMethod(handler, "getPrototypeOf").
   1494   Handle<Object> trap;
   1495   ASSIGN_RETURN_ON_EXCEPTION(isolate, trap, GetMethod(handler, trap_name),
   1496                              Object);
   1497   // 6. If trap is undefined, then return target.[[GetPrototypeOf]]().
   1498   if (trap->IsUndefined(isolate)) {
   1499     return JSReceiver::GetPrototype(isolate, target);
   1500   }
   1501   // 7. Let handlerProto be ? Call(trap, handler, target).
   1502   Handle<Object> argv[] = {target};
   1503   Handle<Object> handler_proto;
   1504   ASSIGN_RETURN_ON_EXCEPTION(
   1505       isolate, handler_proto,
   1506       Execution::Call(isolate, trap, handler, arraysize(argv), argv), Object);
   1507   // 8. If Type(handlerProto) is neither Object nor Null, throw a TypeError.
   1508   if (!(handler_proto->IsJSReceiver() || handler_proto->IsNull(isolate))) {
   1509     THROW_NEW_ERROR(isolate,
   1510                     NewTypeError(MessageTemplate::kProxyGetPrototypeOfInvalid),
   1511                     Object);
   1512   }
   1513   // 9. Let extensibleTarget be ? IsExtensible(target).
   1514   Maybe<bool> is_extensible = JSReceiver::IsExtensible(target);
   1515   MAYBE_RETURN_NULL(is_extensible);
   1516   // 10. If extensibleTarget is true, return handlerProto.
   1517   if (is_extensible.FromJust()) return handler_proto;
   1518   // 11. Let targetProto be ? target.[[GetPrototypeOf]]().
   1519   Handle<Object> target_proto;
   1520   ASSIGN_RETURN_ON_EXCEPTION(isolate, target_proto,
   1521                              JSReceiver::GetPrototype(isolate, target), Object);
   1522   // 12. If SameValue(handlerProto, targetProto) is false, throw a TypeError.
   1523   if (!handler_proto->SameValue(*target_proto)) {
   1524     THROW_NEW_ERROR(
   1525         isolate,
   1526         NewTypeError(MessageTemplate::kProxyGetPrototypeOfNonExtensible),
   1527         Object);
   1528   }
   1529   // 13. Return handlerProto.
   1530   return handler_proto;
   1531 }
   1532 
   1533 MaybeHandle<Object> Object::GetPropertyWithAccessor(LookupIterator* it) {
   1534   Isolate* isolate = it->isolate();
   1535   Handle<Object> structure = it->GetAccessors();
   1536   Handle<Object> receiver = it->GetReceiver();
   1537   // In case of global IC, the receiver is the global object. Replace by the
   1538   // global proxy.
   1539   if (receiver->IsJSGlobalObject()) {
   1540     receiver = handle(JSGlobalObject::cast(*receiver)->global_proxy(), isolate);
   1541   }
   1542 
   1543   // We should never get here to initialize a const with the hole value since a
   1544   // const declaration would conflict with the getter.
   1545   DCHECK(!structure->IsForeign());
   1546 
   1547   // API style callbacks.
   1548   Handle<JSObject> holder = it->GetHolder<JSObject>();
   1549   if (structure->IsAccessorInfo()) {
   1550     Handle<Name> name = it->GetName();
   1551     Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(structure);
   1552     if (!info->IsCompatibleReceiver(*receiver)) {
   1553       THROW_NEW_ERROR(isolate,
   1554                       NewTypeError(MessageTemplate::kIncompatibleMethodReceiver,
   1555                                    name, receiver),
   1556                       Object);
   1557     }
   1558 
   1559     if (!info->has_getter()) return isolate->factory()->undefined_value();
   1560 
   1561     if (info->is_sloppy() && !receiver->IsJSReceiver()) {
   1562       ASSIGN_RETURN_ON_EXCEPTION(isolate, receiver,
   1563                                  Object::ConvertReceiver(isolate, receiver),
   1564                                  Object);
   1565     }
   1566 
   1567     PropertyCallbackArguments args(isolate, info->data(), *receiver, *holder,
   1568                                    kDontThrow);
   1569     Handle<Object> result = args.CallAccessorGetter(info, name);
   1570     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
   1571     if (result.is_null()) return isolate->factory()->undefined_value();
   1572     Handle<Object> reboxed_result = handle(*result, isolate);
   1573     if (info->replace_on_access() && receiver->IsJSReceiver()) {
   1574       RETURN_ON_EXCEPTION(isolate,
   1575                           Accessors::ReplaceAccessorWithDataProperty(
   1576                               receiver, holder, name, result),
   1577                           Object);
   1578     }
   1579     return reboxed_result;
   1580   }
   1581 
   1582   // AccessorPair with 'cached' private property.
   1583   if (it->TryLookupCachedProperty()) {
   1584     return Object::GetProperty(it);
   1585   }
   1586 
   1587   // Regular accessor.
   1588   Handle<Object> getter(AccessorPair::cast(*structure)->getter(), isolate);
   1589   if (getter->IsFunctionTemplateInfo()) {
   1590     SaveContext save(isolate);
   1591     isolate->set_context(*holder->GetCreationContext());
   1592     return Builtins::InvokeApiFunction(
   1593         isolate, false, Handle<FunctionTemplateInfo>::cast(getter), receiver, 0,
   1594         nullptr, isolate->factory()->undefined_value());
   1595   } else if (getter->IsCallable()) {
   1596     // TODO(rossberg): nicer would be to cast to some JSCallable here...
   1597     return Object::GetPropertyWithDefinedGetter(
   1598         receiver, Handle<JSReceiver>::cast(getter));
   1599   }
   1600   // Getter is not a function.
   1601   return isolate->factory()->undefined_value();
   1602 }
   1603 
   1604 // static
   1605 Address AccessorInfo::redirect(Address address, AccessorComponent component) {
   1606   ApiFunction fun(address);
   1607   DCHECK_EQ(ACCESSOR_GETTER, component);
   1608   ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL;
   1609   return ExternalReference::Create(&fun, type).address();
   1610 }
   1611 
   1612 Address AccessorInfo::redirected_getter() const {
   1613   Address accessor = v8::ToCData<Address>(getter());
   1614   if (accessor == kNullAddress) return kNullAddress;
   1615   return redirect(accessor, ACCESSOR_GETTER);
   1616 }
   1617 
   1618 Address CallHandlerInfo::redirected_callback() const {
   1619   Address address = v8::ToCData<Address>(callback());
   1620   ApiFunction fun(address);
   1621   ExternalReference::Type type = ExternalReference::DIRECT_API_CALL;
   1622   return ExternalReference::Create(&fun, type).address();
   1623 }
   1624 
   1625 bool AccessorInfo::IsCompatibleReceiverMap(Handle<AccessorInfo> info,
   1626                                            Handle<Map> map) {
   1627   if (!info->HasExpectedReceiverType()) return true;
   1628   if (!map->IsJSObjectMap()) return false;
   1629   return FunctionTemplateInfo::cast(info->expected_receiver_type())
   1630       ->IsTemplateFor(*map);
   1631 }
   1632 
   1633 Maybe<bool> Object::SetPropertyWithAccessor(LookupIterator* it,
   1634                                             Handle<Object> value,
   1635                                             ShouldThrow should_throw) {
   1636   Isolate* isolate = it->isolate();
   1637   Handle<Object> structure = it->GetAccessors();
   1638   Handle<Object> receiver = it->GetReceiver();
   1639   // In case of global IC, the receiver is the global object. Replace by the
   1640   // global proxy.
   1641   if (receiver->IsJSGlobalObject()) {
   1642     receiver = handle(JSGlobalObject::cast(*receiver)->global_proxy(), isolate);
   1643   }
   1644 
   1645   // We should never get here to initialize a const with the hole value since a
   1646   // const declaration would conflict with the setter.
   1647   DCHECK(!structure->IsForeign());
   1648 
   1649   // API style callbacks.
   1650   Handle<JSObject> holder = it->GetHolder<JSObject>();
   1651   if (structure->IsAccessorInfo()) {
   1652     Handle<Name> name = it->GetName();
   1653     Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(structure);
   1654     if (!info->IsCompatibleReceiver(*receiver)) {
   1655       isolate->Throw(*isolate->factory()->NewTypeError(
   1656           MessageTemplate::kIncompatibleMethodReceiver, name, receiver));
   1657       return Nothing<bool>();
   1658     }
   1659 
   1660     if (!info->has_setter()) {
   1661       // TODO(verwaest): We should not get here anymore once all AccessorInfos
   1662       // are marked as special_data_property. They cannot both be writable and
   1663       // not have a setter.
   1664       return Just(true);
   1665     }
   1666 
   1667     if (info->is_sloppy() && !receiver->IsJSReceiver()) {
   1668       ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   1669           isolate, receiver, Object::ConvertReceiver(isolate, receiver),
   1670           Nothing<bool>());
   1671     }
   1672 
   1673     // The actual type of setter callback is either
   1674     // v8::AccessorNameSetterCallback or
   1675     // i::Accesors::AccessorNameBooleanSetterCallback, depending on whether the
   1676     // AccessorInfo was created by the API or internally (see accessors.cc).
   1677     // Here we handle both cases using GenericNamedPropertySetterCallback and
   1678     // its Call method.
   1679     PropertyCallbackArguments args(isolate, info->data(), *receiver, *holder,
   1680                                    should_throw);
   1681     Handle<Object> result = args.CallAccessorSetter(info, name, value);
   1682     // In the case of AccessorNameSetterCallback, we know that the result value
   1683     // cannot have been set, so the result of Call will be null.  In the case of
   1684     // AccessorNameBooleanSetterCallback, the result will either be null
   1685     // (signalling an exception) or a boolean Oddball.
   1686     RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
   1687     if (result.is_null()) return Just(true);
   1688     DCHECK(result->BooleanValue(isolate) || should_throw == kDontThrow);
   1689     return Just(result->BooleanValue(isolate));
   1690   }
   1691 
   1692   // Regular accessor.
   1693   Handle<Object> setter(AccessorPair::cast(*structure)->setter(), isolate);
   1694   if (setter->IsFunctionTemplateInfo()) {
   1695     SaveContext save(isolate);
   1696     isolate->set_context(*holder->GetCreationContext());
   1697     Handle<Object> argv[] = {value};
   1698     RETURN_ON_EXCEPTION_VALUE(
   1699         isolate, Builtins::InvokeApiFunction(
   1700                      isolate, false, Handle<FunctionTemplateInfo>::cast(setter),
   1701                      receiver, arraysize(argv), argv,
   1702                      isolate->factory()->undefined_value()),
   1703         Nothing<bool>());
   1704     return Just(true);
   1705   } else if (setter->IsCallable()) {
   1706     // TODO(rossberg): nicer would be to cast to some JSCallable here...
   1707     return SetPropertyWithDefinedSetter(
   1708         receiver, Handle<JSReceiver>::cast(setter), value, should_throw);
   1709   }
   1710 
   1711   RETURN_FAILURE(isolate, should_throw,
   1712                  NewTypeError(MessageTemplate::kNoSetterInCallback,
   1713                               it->GetName(), it->GetHolder<JSObject>()));
   1714 }
   1715 
   1716 
   1717 MaybeHandle<Object> Object::GetPropertyWithDefinedGetter(
   1718     Handle<Object> receiver,
   1719     Handle<JSReceiver> getter) {
   1720   Isolate* isolate = getter->GetIsolate();
   1721 
   1722   // Platforms with simulators like arm/arm64 expose a funny issue. If the
   1723   // simulator has a separate JS stack pointer from the C++ stack pointer, it
   1724   // can miss C++ stack overflows in the stack guard at the start of JavaScript
   1725   // functions. It would be very expensive to check the C++ stack pointer at
   1726   // that location. The best solution seems to be to break the impasse by
   1727   // adding checks at possible recursion points. What's more, we don't put
   1728   // this stack check behind the USE_SIMULATOR define in order to keep
   1729   // behavior the same between hardware and simulators.
   1730   StackLimitCheck check(isolate);
   1731   if (check.JsHasOverflowed()) {
   1732     isolate->StackOverflow();
   1733     return MaybeHandle<Object>();
   1734   }
   1735 
   1736   return Execution::Call(isolate, getter, receiver, 0, nullptr);
   1737 }
   1738 
   1739 
   1740 Maybe<bool> Object::SetPropertyWithDefinedSetter(Handle<Object> receiver,
   1741                                                  Handle<JSReceiver> setter,
   1742                                                  Handle<Object> value,
   1743                                                  ShouldThrow should_throw) {
   1744   Isolate* isolate = setter->GetIsolate();
   1745 
   1746   Handle<Object> argv[] = { value };
   1747   RETURN_ON_EXCEPTION_VALUE(isolate, Execution::Call(isolate, setter, receiver,
   1748                                                      arraysize(argv), argv),
   1749                             Nothing<bool>());
   1750   return Just(true);
   1751 }
   1752 
   1753 
   1754 // static
   1755 bool JSObject::AllCanRead(LookupIterator* it) {
   1756   // Skip current iteration, it's in state ACCESS_CHECK or INTERCEPTOR, both of
   1757   // which have already been checked.
   1758   DCHECK(it->state() == LookupIterator::ACCESS_CHECK ||
   1759          it->state() == LookupIterator::INTERCEPTOR);
   1760   for (it->Next(); it->IsFound(); it->Next()) {
   1761     if (it->state() == LookupIterator::ACCESSOR) {
   1762       auto accessors = it->GetAccessors();
   1763       if (accessors->IsAccessorInfo()) {
   1764         if (AccessorInfo::cast(*accessors)->all_can_read()) return true;
   1765       }
   1766     } else if (it->state() == LookupIterator::INTERCEPTOR) {
   1767       if (it->GetInterceptor()->all_can_read()) return true;
   1768     } else if (it->state() == LookupIterator::JSPROXY) {
   1769       // Stop lookupiterating. And no, AllCanNotRead.
   1770       return false;
   1771     }
   1772   }
   1773   return false;
   1774 }
   1775 
   1776 namespace {
   1777 
   1778 MaybeHandle<Object> GetPropertyWithInterceptorInternal(
   1779     LookupIterator* it, Handle<InterceptorInfo> interceptor, bool* done) {
   1780   *done = false;
   1781   Isolate* isolate = it->isolate();
   1782   // Make sure that the top context does not change when doing callbacks or
   1783   // interceptor calls.
   1784   AssertNoContextChange ncc(isolate);
   1785 
   1786   if (interceptor->getter()->IsUndefined(isolate)) {
   1787     return isolate->factory()->undefined_value();
   1788   }
   1789 
   1790   Handle<JSObject> holder = it->GetHolder<JSObject>();
   1791   Handle<Object> result;
   1792   Handle<Object> receiver = it->GetReceiver();
   1793   if (!receiver->IsJSReceiver()) {
   1794     ASSIGN_RETURN_ON_EXCEPTION(
   1795         isolate, receiver, Object::ConvertReceiver(isolate, receiver), Object);
   1796   }
   1797   PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
   1798                                  *holder, kDontThrow);
   1799 
   1800   if (it->IsElement()) {
   1801     result = args.CallIndexedGetter(interceptor, it->index());
   1802   } else {
   1803     result = args.CallNamedGetter(interceptor, it->name());
   1804   }
   1805 
   1806   RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
   1807   if (result.is_null()) return isolate->factory()->undefined_value();
   1808   *done = true;
   1809   // Rebox handle before return
   1810   return handle(*result, isolate);
   1811 }
   1812 
   1813 Maybe<PropertyAttributes> GetPropertyAttributesWithInterceptorInternal(
   1814     LookupIterator* it, Handle<InterceptorInfo> interceptor) {
   1815   Isolate* isolate = it->isolate();
   1816   // Make sure that the top context does not change when doing
   1817   // callbacks or interceptor calls.
   1818   AssertNoContextChange ncc(isolate);
   1819   HandleScope scope(isolate);
   1820 
   1821   Handle<JSObject> holder = it->GetHolder<JSObject>();
   1822   DCHECK_IMPLIES(!it->IsElement() && it->name()->IsSymbol(),
   1823                  interceptor->can_intercept_symbols());
   1824   Handle<Object> receiver = it->GetReceiver();
   1825   if (!receiver->IsJSReceiver()) {
   1826     ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, receiver,
   1827                                      Object::ConvertReceiver(isolate, receiver),
   1828                                      Nothing<PropertyAttributes>());
   1829   }
   1830   PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
   1831                                  *holder, kDontThrow);
   1832   if (!interceptor->query()->IsUndefined(isolate)) {
   1833     Handle<Object> result;
   1834     if (it->IsElement()) {
   1835       result = args.CallIndexedQuery(interceptor, it->index());
   1836     } else {
   1837       result = args.CallNamedQuery(interceptor, it->name());
   1838     }
   1839     if (!result.is_null()) {
   1840       int32_t value;
   1841       CHECK(result->ToInt32(&value));
   1842       return Just(static_cast<PropertyAttributes>(value));
   1843     }
   1844   } else if (!interceptor->getter()->IsUndefined(isolate)) {
   1845     // TODO(verwaest): Use GetPropertyWithInterceptor?
   1846     Handle<Object> result;
   1847     if (it->IsElement()) {
   1848       result = args.CallIndexedGetter(interceptor, it->index());
   1849     } else {
   1850       result = args.CallNamedGetter(interceptor, it->name());
   1851     }
   1852     if (!result.is_null()) return Just(DONT_ENUM);
   1853   }
   1854 
   1855   RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<PropertyAttributes>());
   1856   return Just(ABSENT);
   1857 }
   1858 
   1859 Maybe<bool> SetPropertyWithInterceptorInternal(
   1860     LookupIterator* it, Handle<InterceptorInfo> interceptor,
   1861     ShouldThrow should_throw, Handle<Object> value) {
   1862   Isolate* isolate = it->isolate();
   1863   // Make sure that the top context does not change when doing callbacks or
   1864   // interceptor calls.
   1865   AssertNoContextChange ncc(isolate);
   1866 
   1867   if (interceptor->setter()->IsUndefined(isolate)) return Just(false);
   1868 
   1869   Handle<JSObject> holder = it->GetHolder<JSObject>();
   1870   bool result;
   1871   Handle<Object> receiver = it->GetReceiver();
   1872   if (!receiver->IsJSReceiver()) {
   1873     ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, receiver,
   1874                                      Object::ConvertReceiver(isolate, receiver),
   1875                                      Nothing<bool>());
   1876   }
   1877   PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
   1878                                  *holder, should_throw);
   1879 
   1880   if (it->IsElement()) {
   1881     // TODO(neis): In the future, we may want to actually return the
   1882     // interceptor's result, which then should be a boolean.
   1883     result = !args.CallIndexedSetter(interceptor, it->index(), value).is_null();
   1884   } else {
   1885     result = !args.CallNamedSetter(interceptor, it->name(), value).is_null();
   1886   }
   1887 
   1888   RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(), Nothing<bool>());
   1889   return Just(result);
   1890 }
   1891 
   1892 Maybe<bool> DefinePropertyWithInterceptorInternal(
   1893     LookupIterator* it, Handle<InterceptorInfo> interceptor,
   1894     ShouldThrow should_throw, PropertyDescriptor& desc) {
   1895   Isolate* isolate = it->isolate();
   1896   // Make sure that the top context does not change when doing callbacks or
   1897   // interceptor calls.
   1898   AssertNoContextChange ncc(isolate);
   1899 
   1900   if (interceptor->definer()->IsUndefined(isolate)) return Just(false);
   1901 
   1902   Handle<JSObject> holder = it->GetHolder<JSObject>();
   1903   bool result;
   1904   Handle<Object> receiver = it->GetReceiver();
   1905   if (!receiver->IsJSReceiver()) {
   1906     ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, receiver,
   1907                                      Object::ConvertReceiver(isolate, receiver),
   1908                                      Nothing<bool>());
   1909   }
   1910   PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
   1911                                  *holder, should_throw);
   1912 
   1913   std::unique_ptr<v8::PropertyDescriptor> descriptor(
   1914       new v8::PropertyDescriptor());
   1915   if (PropertyDescriptor::IsAccessorDescriptor(&desc)) {
   1916     descriptor.reset(new v8::PropertyDescriptor(
   1917         v8::Utils::ToLocal(desc.get()), v8::Utils::ToLocal(desc.set())));
   1918   } else if (PropertyDescriptor::IsDataDescriptor(&desc)) {
   1919     if (desc.has_writable()) {
   1920       descriptor.reset(new v8::PropertyDescriptor(
   1921           v8::Utils::ToLocal(desc.value()), desc.writable()));
   1922     } else {
   1923       descriptor.reset(
   1924           new v8::PropertyDescriptor(v8::Utils::ToLocal(desc.value())));
   1925     }
   1926   }
   1927   if (desc.has_enumerable()) {
   1928     descriptor->set_enumerable(desc.enumerable());
   1929   }
   1930   if (desc.has_configurable()) {
   1931     descriptor->set_configurable(desc.configurable());
   1932   }
   1933 
   1934   if (it->IsElement()) {
   1935     result = !args.CallIndexedDefiner(interceptor, it->index(), *descriptor)
   1936                   .is_null();
   1937   } else {
   1938     result =
   1939         !args.CallNamedDefiner(interceptor, it->name(), *descriptor).is_null();
   1940   }
   1941 
   1942   RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(), Nothing<bool>());
   1943   return Just(result);
   1944 }
   1945 
   1946 }  // namespace
   1947 
   1948 MaybeHandle<Object> JSObject::GetPropertyWithFailedAccessCheck(
   1949     LookupIterator* it) {
   1950   Isolate* isolate = it->isolate();
   1951   Handle<JSObject> checked = it->GetHolder<JSObject>();
   1952   Handle<InterceptorInfo> interceptor =
   1953       it->GetInterceptorForFailedAccessCheck();
   1954   if (interceptor.is_null()) {
   1955     while (AllCanRead(it)) {
   1956       if (it->state() == LookupIterator::ACCESSOR) {
   1957         return GetPropertyWithAccessor(it);
   1958       }
   1959       DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
   1960       bool done;
   1961       Handle<Object> result;
   1962       ASSIGN_RETURN_ON_EXCEPTION(isolate, result,
   1963                                  GetPropertyWithInterceptor(it, &done), Object);
   1964       if (done) return result;
   1965     }
   1966 
   1967   } else {
   1968     Handle<Object> result;
   1969     bool done;
   1970     ASSIGN_RETURN_ON_EXCEPTION(
   1971         isolate, result,
   1972         GetPropertyWithInterceptorInternal(it, interceptor, &done), Object);
   1973     if (done) return result;
   1974   }
   1975 
   1976   // Cross-Origin [[Get]] of Well-Known Symbols does not throw, and returns
   1977   // undefined.
   1978   Handle<Name> name = it->GetName();
   1979   if (name->IsSymbol() && Symbol::cast(*name)->is_well_known_symbol()) {
   1980     return it->factory()->undefined_value();
   1981   }
   1982 
   1983   isolate->ReportFailedAccessCheck(checked);
   1984   RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
   1985   return it->factory()->undefined_value();
   1986 }
   1987 
   1988 
   1989 Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithFailedAccessCheck(
   1990     LookupIterator* it) {
   1991   Isolate* isolate = it->isolate();
   1992   Handle<JSObject> checked = it->GetHolder<JSObject>();
   1993   Handle<InterceptorInfo> interceptor =
   1994       it->GetInterceptorForFailedAccessCheck();
   1995   if (interceptor.is_null()) {
   1996     while (AllCanRead(it)) {
   1997       if (it->state() == LookupIterator::ACCESSOR) {
   1998         return Just(it->property_attributes());
   1999       }
   2000       DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
   2001       auto result = GetPropertyAttributesWithInterceptor(it);
   2002       if (isolate->has_scheduled_exception()) break;
   2003       if (result.IsJust() && result.FromJust() != ABSENT) return result;
   2004     }
   2005   } else {
   2006     Maybe<PropertyAttributes> result =
   2007         GetPropertyAttributesWithInterceptorInternal(it, interceptor);
   2008     if (isolate->has_pending_exception()) return Nothing<PropertyAttributes>();
   2009     if (result.FromMaybe(ABSENT) != ABSENT) return result;
   2010   }
   2011   isolate->ReportFailedAccessCheck(checked);
   2012   RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<PropertyAttributes>());
   2013   return Just(ABSENT);
   2014 }
   2015 
   2016 
   2017 // static
   2018 bool JSObject::AllCanWrite(LookupIterator* it) {
   2019   for (; it->IsFound() && it->state() != LookupIterator::JSPROXY; it->Next()) {
   2020     if (it->state() == LookupIterator::ACCESSOR) {
   2021       Handle<Object> accessors = it->GetAccessors();
   2022       if (accessors->IsAccessorInfo()) {
   2023         if (AccessorInfo::cast(*accessors)->all_can_write()) return true;
   2024       }
   2025     }
   2026   }
   2027   return false;
   2028 }
   2029 
   2030 
   2031 Maybe<bool> JSObject::SetPropertyWithFailedAccessCheck(
   2032     LookupIterator* it, Handle<Object> value, ShouldThrow should_throw) {
   2033   Isolate* isolate = it->isolate();
   2034   Handle<JSObject> checked = it->GetHolder<JSObject>();
   2035   Handle<InterceptorInfo> interceptor =
   2036       it->GetInterceptorForFailedAccessCheck();
   2037   if (interceptor.is_null()) {
   2038     if (AllCanWrite(it)) {
   2039       return SetPropertyWithAccessor(it, value, should_throw);
   2040     }
   2041   } else {
   2042     Maybe<bool> result = SetPropertyWithInterceptorInternal(
   2043         it, interceptor, should_throw, value);
   2044     if (isolate->has_pending_exception()) return Nothing<bool>();
   2045     if (result.IsJust()) return result;
   2046   }
   2047   isolate->ReportFailedAccessCheck(checked);
   2048   RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
   2049   return Just(true);
   2050 }
   2051 
   2052 
   2053 void JSObject::SetNormalizedProperty(Handle<JSObject> object,
   2054                                      Handle<Name> name,
   2055                                      Handle<Object> value,
   2056                                      PropertyDetails details) {
   2057   DCHECK(!object->HasFastProperties());
   2058   DCHECK(name->IsUniqueName());
   2059   Isolate* isolate = object->GetIsolate();
   2060 
   2061   uint32_t hash = name->Hash();
   2062 
   2063   if (object->IsJSGlobalObject()) {
   2064     Handle<JSGlobalObject> global_obj = Handle<JSGlobalObject>::cast(object);
   2065     Handle<GlobalDictionary> dictionary(global_obj->global_dictionary(),
   2066                                         isolate);
   2067     int entry = dictionary->FindEntry(ReadOnlyRoots(isolate), name, hash);
   2068 
   2069     if (entry == GlobalDictionary::kNotFound) {
   2070       DCHECK_IMPLIES(global_obj->map()->is_prototype_map(),
   2071                      Map::IsPrototypeChainInvalidated(global_obj->map()));
   2072       auto cell = isolate->factory()->NewPropertyCell(name);
   2073       cell->set_value(*value);
   2074       auto cell_type = value->IsUndefined(isolate)
   2075                            ? PropertyCellType::kUndefined
   2076                            : PropertyCellType::kConstant;
   2077       details = details.set_cell_type(cell_type);
   2078       value = cell;
   2079       dictionary =
   2080           GlobalDictionary::Add(isolate, dictionary, name, value, details);
   2081       global_obj->set_global_dictionary(*dictionary);
   2082     } else {
   2083       Handle<PropertyCell> cell = PropertyCell::PrepareForValue(
   2084           isolate, dictionary, entry, value, details);
   2085       cell->set_value(*value);
   2086     }
   2087   } else {
   2088     Handle<NameDictionary> dictionary(object->property_dictionary(), isolate);
   2089 
   2090     int entry = dictionary->FindEntry(isolate, name);
   2091     if (entry == NameDictionary::kNotFound) {
   2092       DCHECK_IMPLIES(object->map()->is_prototype_map(),
   2093                      Map::IsPrototypeChainInvalidated(object->map()));
   2094       dictionary =
   2095           NameDictionary::Add(isolate, dictionary, name, value, details);
   2096       object->SetProperties(*dictionary);
   2097     } else {
   2098       PropertyDetails original_details = dictionary->DetailsAt(entry);
   2099       int enumeration_index = original_details.dictionary_index();
   2100       DCHECK_GT(enumeration_index, 0);
   2101       details = details.set_index(enumeration_index);
   2102       dictionary->SetEntry(isolate, entry, *name, *value, details);
   2103     }
   2104   }
   2105 }
   2106 
   2107 // static
   2108 Maybe<bool> JSReceiver::HasInPrototypeChain(Isolate* isolate,
   2109                                             Handle<JSReceiver> object,
   2110                                             Handle<Object> proto) {
   2111   PrototypeIterator iter(isolate, object, kStartAtReceiver);
   2112   while (true) {
   2113     if (!iter.AdvanceFollowingProxies()) return Nothing<bool>();
   2114     if (iter.IsAtEnd()) return Just(false);
   2115     if (PrototypeIterator::GetCurrent(iter).is_identical_to(proto)) {
   2116       return Just(true);
   2117     }
   2118   }
   2119 }
   2120 
   2121 namespace {
   2122 
   2123 bool HasExcludedProperty(
   2124     const ScopedVector<Handle<Object>>* excluded_properties,
   2125     Handle<Object> search_element) {
   2126   // TODO(gsathya): Change this to be a hashtable.
   2127   for (int i = 0; i < excluded_properties->length(); i++) {
   2128     if (search_element->SameValue(*excluded_properties->at(i))) {
   2129       return true;
   2130     }
   2131   }
   2132 
   2133   return false;
   2134 }
   2135 
   2136 V8_WARN_UNUSED_RESULT Maybe<bool> FastAssign(
   2137     Handle<JSReceiver> target, Handle<Object> source,
   2138     const ScopedVector<Handle<Object>>* excluded_properties, bool use_set) {
   2139   // Non-empty strings are the only non-JSReceivers that need to be handled
   2140   // explicitly by Object.assign.
   2141   if (!source->IsJSReceiver()) {
   2142     return Just(!source->IsString() || String::cast(*source)->length() == 0);
   2143   }
   2144 
   2145   // If the target is deprecated, the object will be updated on first store. If
   2146   // the source for that store equals the target, this will invalidate the
   2147   // cached representation of the source. Preventively upgrade the target.
   2148   // Do this on each iteration since any property load could cause deprecation.
   2149   if (target->map()->is_deprecated()) {
   2150     JSObject::MigrateInstance(Handle<JSObject>::cast(target));
   2151   }
   2152 
   2153   Isolate* isolate = target->GetIsolate();
   2154   Handle<Map> map(JSReceiver::cast(*source)->map(), isolate);
   2155 
   2156   if (!map->IsJSObjectMap()) return Just(false);
   2157   if (!map->OnlyHasSimpleProperties()) return Just(false);
   2158 
   2159   Handle<JSObject> from = Handle<JSObject>::cast(source);
   2160   if (from->elements() != ReadOnlyRoots(isolate).empty_fixed_array()) {
   2161     return Just(false);
   2162   }
   2163 
   2164   Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate);
   2165   int length = map->NumberOfOwnDescriptors();
   2166 
   2167   bool stable = true;
   2168 
   2169   for (int i = 0; i < length; i++) {
   2170     Handle<Name> next_key(descriptors->GetKey(i), isolate);
   2171     Handle<Object> prop_value;
   2172     // Directly decode from the descriptor array if |from| did not change shape.
   2173     if (stable) {
   2174       PropertyDetails details = descriptors->GetDetails(i);
   2175       if (!details.IsEnumerable()) continue;
   2176       if (details.kind() == kData) {
   2177         if (details.location() == kDescriptor) {
   2178           prop_value = handle(descriptors->GetStrongValue(i), isolate);
   2179         } else {
   2180           Representation representation = details.representation();
   2181           FieldIndex index = FieldIndex::ForDescriptor(*map, i);
   2182           prop_value = JSObject::FastPropertyAt(from, representation, index);
   2183         }
   2184       } else {
   2185         ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   2186             isolate, prop_value,
   2187             JSReceiver::GetProperty(isolate, from, next_key), Nothing<bool>());
   2188         stable = from->map() == *map;
   2189       }
   2190     } else {
   2191       // If the map did change, do a slower lookup. We are still guaranteed that
   2192       // the object has a simple shape, and that the key is a name.
   2193       LookupIterator it(from, next_key, from,
   2194                         LookupIterator::OWN_SKIP_INTERCEPTOR);
   2195       if (!it.IsFound()) continue;
   2196       DCHECK(it.state() == LookupIterator::DATA ||
   2197              it.state() == LookupIterator::ACCESSOR);
   2198       if (!it.IsEnumerable()) continue;
   2199       ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   2200           isolate, prop_value, Object::GetProperty(&it), Nothing<bool>());
   2201     }
   2202 
   2203     if (use_set) {
   2204       LookupIterator it(target, next_key, target);
   2205       Maybe<bool> result =
   2206           Object::SetProperty(&it, prop_value, LanguageMode::kStrict,
   2207                               Object::CERTAINLY_NOT_STORE_FROM_KEYED);
   2208       if (result.IsNothing()) return result;
   2209       if (stable) stable = from->map() == *map;
   2210     } else {
   2211       if (excluded_properties != nullptr &&
   2212           HasExcludedProperty(excluded_properties, next_key)) {
   2213         continue;
   2214       }
   2215 
   2216       // 4a ii 2. Perform ? CreateDataProperty(target, nextKey, propValue).
   2217       bool success;
   2218       LookupIterator it = LookupIterator::PropertyOrElement(
   2219           isolate, target, next_key, &success, LookupIterator::OWN);
   2220       CHECK(success);
   2221       CHECK(JSObject::CreateDataProperty(&it, prop_value, kThrowOnError)
   2222                 .FromJust());
   2223     }
   2224   }
   2225 
   2226   return Just(true);
   2227 }
   2228 }  // namespace
   2229 
   2230 // static
   2231 Maybe<bool> JSReceiver::SetOrCopyDataProperties(
   2232     Isolate* isolate, Handle<JSReceiver> target, Handle<Object> source,
   2233     const ScopedVector<Handle<Object>>* excluded_properties, bool use_set) {
   2234   Maybe<bool> fast_assign =
   2235       FastAssign(target, source, excluded_properties, use_set);
   2236   if (fast_assign.IsNothing()) return Nothing<bool>();
   2237   if (fast_assign.FromJust()) return Just(true);
   2238 
   2239   Handle<JSReceiver> from = Object::ToObject(isolate, source).ToHandleChecked();
   2240   // 3b. Let keys be ? from.[[OwnPropertyKeys]]().
   2241   Handle<FixedArray> keys;
   2242   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   2243       isolate, keys,
   2244       KeyAccumulator::GetKeys(from, KeyCollectionMode::kOwnOnly, ALL_PROPERTIES,
   2245                               GetKeysConversion::kKeepNumbers),
   2246       Nothing<bool>());
   2247 
   2248   // 4. Repeat for each element nextKey of keys in List order,
   2249   for (int j = 0; j < keys->length(); ++j) {
   2250     Handle<Object> next_key(keys->get(j), isolate);
   2251     // 4a i. Let desc be ? from.[[GetOwnProperty]](nextKey).
   2252     PropertyDescriptor desc;
   2253     Maybe<bool> found =
   2254         JSReceiver::GetOwnPropertyDescriptor(isolate, from, next_key, &desc);
   2255     if (found.IsNothing()) return Nothing<bool>();
   2256     // 4a ii. If desc is not undefined and desc.[[Enumerable]] is true, then
   2257     if (found.FromJust() && desc.enumerable()) {
   2258       // 4a ii 1. Let propValue be ? Get(from, nextKey).
   2259       Handle<Object> prop_value;
   2260       ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   2261           isolate, prop_value,
   2262           Runtime::GetObjectProperty(isolate, from, next_key), Nothing<bool>());
   2263 
   2264       if (use_set) {
   2265         // 4c ii 2. Let status be ? Set(to, nextKey, propValue, true).
   2266         Handle<Object> status;
   2267         ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   2268             isolate, status,
   2269             Runtime::SetObjectProperty(isolate, target, next_key, prop_value,
   2270                                        LanguageMode::kStrict),
   2271             Nothing<bool>());
   2272       } else {
   2273         if (excluded_properties != nullptr &&
   2274             HasExcludedProperty(excluded_properties, next_key)) {
   2275           continue;
   2276         }
   2277 
   2278         // 4a ii 2. Perform ! CreateDataProperty(target, nextKey, propValue).
   2279         bool success;
   2280         LookupIterator it = LookupIterator::PropertyOrElement(
   2281             isolate, target, next_key, &success, LookupIterator::OWN);
   2282         CHECK(success);
   2283         CHECK(JSObject::CreateDataProperty(&it, prop_value, kThrowOnError)
   2284                   .FromJust());
   2285       }
   2286     }
   2287   }
   2288 
   2289   return Just(true);
   2290 }
   2291 
   2292 Map* Object::GetPrototypeChainRootMap(Isolate* isolate) const {
   2293   DisallowHeapAllocation no_alloc;
   2294   if (IsSmi()) {
   2295     Context* native_context = isolate->context()->native_context();
   2296     return native_context->number_function()->initial_map();
   2297   }
   2298 
   2299   const HeapObject* heap_object = HeapObject::cast(this);
   2300   return heap_object->map()->GetPrototypeChainRootMap(isolate);
   2301 }
   2302 
   2303 Map* Map::GetPrototypeChainRootMap(Isolate* isolate) const {
   2304   DisallowHeapAllocation no_alloc;
   2305   if (IsJSReceiverMap()) {
   2306     return const_cast<Map*>(this);
   2307   }
   2308   int constructor_function_index = GetConstructorFunctionIndex();
   2309   if (constructor_function_index != Map::kNoConstructorFunctionIndex) {
   2310     Context* native_context = isolate->context()->native_context();
   2311     JSFunction* constructor_function =
   2312         JSFunction::cast(native_context->get(constructor_function_index));
   2313     return constructor_function->initial_map();
   2314   }
   2315   return ReadOnlyRoots(isolate).null_value()->map();
   2316 }
   2317 
   2318 // static
   2319 Smi* Object::GetOrCreateHash(Isolate* isolate, Object* key) {
   2320   DisallowHeapAllocation no_gc;
   2321   return key->GetOrCreateHash(isolate);
   2322 }
   2323 
   2324 Smi* Object::GetOrCreateHash(Isolate* isolate) {
   2325   DisallowHeapAllocation no_gc;
   2326   Object* hash = Object::GetSimpleHash(this);
   2327   if (hash->IsSmi()) return Smi::cast(hash);
   2328 
   2329   DCHECK(IsJSReceiver());
   2330   return JSReceiver::cast(this)->GetOrCreateIdentityHash(isolate);
   2331 }
   2332 
   2333 
   2334 bool Object::SameValue(Object* other) {
   2335   if (other == this) return true;
   2336 
   2337   if (IsNumber() && other->IsNumber()) {
   2338     double this_value = Number();
   2339     double other_value = other->Number();
   2340     // SameValue(NaN, NaN) is true.
   2341     if (this_value != other_value) {
   2342       return std::isnan(this_value) && std::isnan(other_value);
   2343     }
   2344     // SameValue(0.0, -0.0) is false.
   2345     return (std::signbit(this_value) == std::signbit(other_value));
   2346   }
   2347   if (IsString() && other->IsString()) {
   2348     return String::cast(this)->Equals(String::cast(other));
   2349   }
   2350   if (IsBigInt() && other->IsBigInt()) {
   2351     return BigInt::EqualToBigInt(BigInt::cast(this), BigInt::cast(other));
   2352   }
   2353   return false;
   2354 }
   2355 
   2356 
   2357 bool Object::SameValueZero(Object* other) {
   2358   if (other == this) return true;
   2359 
   2360   if (IsNumber() && other->IsNumber()) {
   2361     double this_value = Number();
   2362     double other_value = other->Number();
   2363     // +0 == -0 is true
   2364     return this_value == other_value ||
   2365            (std::isnan(this_value) && std::isnan(other_value));
   2366   }
   2367   if (IsString() && other->IsString()) {
   2368     return String::cast(this)->Equals(String::cast(other));
   2369   }
   2370   if (IsBigInt() && other->IsBigInt()) {
   2371     return BigInt::EqualToBigInt(BigInt::cast(this), BigInt::cast(other));
   2372   }
   2373   return false;
   2374 }
   2375 
   2376 
   2377 MaybeHandle<Object> Object::ArraySpeciesConstructor(
   2378     Isolate* isolate, Handle<Object> original_array) {
   2379   Handle<Object> default_species = isolate->array_function();
   2380   if (original_array->IsJSArray() &&
   2381       Handle<JSArray>::cast(original_array)->HasArrayPrototype(isolate) &&
   2382       isolate->IsArraySpeciesLookupChainIntact()) {
   2383     return default_species;
   2384   }
   2385   Handle<Object> constructor = isolate->factory()->undefined_value();
   2386   Maybe<bool> is_array = Object::IsArray(original_array);
   2387   MAYBE_RETURN_NULL(is_array);
   2388   if (is_array.FromJust()) {
   2389     ASSIGN_RETURN_ON_EXCEPTION(
   2390         isolate, constructor,
   2391         Object::GetProperty(isolate, original_array,
   2392                             isolate->factory()->constructor_string()),
   2393         Object);
   2394     if (constructor->IsConstructor()) {
   2395       Handle<Context> constructor_context;
   2396       ASSIGN_RETURN_ON_EXCEPTION(
   2397           isolate, constructor_context,
   2398           JSReceiver::GetFunctionRealm(Handle<JSReceiver>::cast(constructor)),
   2399           Object);
   2400       if (*constructor_context != *isolate->native_context() &&
   2401           *constructor == constructor_context->array_function()) {
   2402         constructor = isolate->factory()->undefined_value();
   2403       }
   2404     }
   2405     if (constructor->IsJSReceiver()) {
   2406       ASSIGN_RETURN_ON_EXCEPTION(
   2407           isolate, constructor,
   2408           JSReceiver::GetProperty(isolate,
   2409                                   Handle<JSReceiver>::cast(constructor),
   2410                                   isolate->factory()->species_symbol()),
   2411           Object);
   2412       if (constructor->IsNull(isolate)) {
   2413         constructor = isolate->factory()->undefined_value();
   2414       }
   2415     }
   2416   }
   2417   if (constructor->IsUndefined(isolate)) {
   2418     return default_species;
   2419   } else {
   2420     if (!constructor->IsConstructor()) {
   2421       THROW_NEW_ERROR(isolate,
   2422           NewTypeError(MessageTemplate::kSpeciesNotConstructor),
   2423           Object);
   2424     }
   2425     return constructor;
   2426   }
   2427 }
   2428 
   2429 // ES6 section 7.3.20 SpeciesConstructor ( O, defaultConstructor )
   2430 V8_WARN_UNUSED_RESULT MaybeHandle<Object> Object::SpeciesConstructor(
   2431     Isolate* isolate, Handle<JSReceiver> recv,
   2432     Handle<JSFunction> default_ctor) {
   2433   Handle<Object> ctor_obj;
   2434   ASSIGN_RETURN_ON_EXCEPTION(
   2435       isolate, ctor_obj,
   2436       JSObject::GetProperty(isolate, recv,
   2437                             isolate->factory()->constructor_string()),
   2438       Object);
   2439 
   2440   if (ctor_obj->IsUndefined(isolate)) return default_ctor;
   2441 
   2442   if (!ctor_obj->IsJSReceiver()) {
   2443     THROW_NEW_ERROR(isolate,
   2444                     NewTypeError(MessageTemplate::kConstructorNotReceiver),
   2445                     Object);
   2446   }
   2447 
   2448   Handle<JSReceiver> ctor = Handle<JSReceiver>::cast(ctor_obj);
   2449 
   2450   Handle<Object> species;
   2451   ASSIGN_RETURN_ON_EXCEPTION(
   2452       isolate, species,
   2453       JSObject::GetProperty(isolate, ctor,
   2454                             isolate->factory()->species_symbol()),
   2455       Object);
   2456 
   2457   if (species->IsNullOrUndefined(isolate)) {
   2458     return default_ctor;
   2459   }
   2460 
   2461   if (species->IsConstructor()) return species;
   2462 
   2463   THROW_NEW_ERROR(
   2464       isolate, NewTypeError(MessageTemplate::kSpeciesNotConstructor), Object);
   2465 }
   2466 
   2467 bool Object::IterationHasObservableEffects() {
   2468   // Check that this object is an array.
   2469   if (!IsJSArray()) return true;
   2470   JSArray* array = JSArray::cast(this);
   2471   Isolate* isolate = array->GetIsolate();
   2472 
   2473 #ifdef V8_ENABLE_FORCE_SLOW_PATH
   2474   if (isolate->force_slow_path()) return true;
   2475 #endif
   2476 
   2477   // Check that we have the original ArrayPrototype.
   2478   if (!array->map()->prototype()->IsJSObject()) return true;
   2479   JSObject* array_proto = JSObject::cast(array->map()->prototype());
   2480   if (!isolate->is_initial_array_prototype(array_proto)) return true;
   2481 
   2482   // Check that the ArrayPrototype hasn't been modified in a way that would
   2483   // affect iteration.
   2484   if (!isolate->IsArrayIteratorLookupChainIntact()) return true;
   2485 
   2486   // For FastPacked kinds, iteration will have the same effect as simply
   2487   // accessing each property in order.
   2488   ElementsKind array_kind = array->GetElementsKind();
   2489   if (IsFastPackedElementsKind(array_kind)) return false;
   2490 
   2491   // For FastHoley kinds, an element access on a hole would cause a lookup on
   2492   // the prototype. This could have different results if the prototype has been
   2493   // changed.
   2494   if (IsHoleyElementsKind(array_kind) &&
   2495       isolate->IsNoElementsProtectorIntact()) {
   2496     return false;
   2497   }
   2498   return true;
   2499 }
   2500 
   2501 void Object::ShortPrint(FILE* out) {
   2502   OFStream os(out);
   2503   os << Brief(this);
   2504 }
   2505 
   2506 
   2507 void Object::ShortPrint(StringStream* accumulator) {
   2508   std::ostringstream os;
   2509   os << Brief(this);
   2510   accumulator->Add(os.str().c_str());
   2511 }
   2512 
   2513 
   2514 void Object::ShortPrint(std::ostream& os) { os << Brief(this); }
   2515 
   2516 void MaybeObject::ShortPrint(FILE* out) {
   2517   OFStream os(out);
   2518   os << Brief(this);
   2519 }
   2520 
   2521 void MaybeObject::ShortPrint(StringStream* accumulator) {
   2522   std::ostringstream os;
   2523   os << Brief(this);
   2524   accumulator->Add(os.str().c_str());
   2525 }
   2526 
   2527 void MaybeObject::ShortPrint(std::ostream& os) { os << Brief(this); }
   2528 
   2529 Brief::Brief(const Object* v)
   2530     : value(MaybeObject::FromObject(const_cast<Object*>(v))) {}
   2531 
   2532 std::ostream& operator<<(std::ostream& os, const Brief& v) {
   2533   // TODO(marja): const-correct HeapObjectShortPrint.
   2534   MaybeObject* maybe_object = const_cast<MaybeObject*>(v.value);
   2535   Smi* smi;
   2536   HeapObject* heap_object;
   2537   if (maybe_object->ToSmi(&smi)) {
   2538     smi->SmiPrint(os);
   2539   } else if (maybe_object->IsClearedWeakHeapObject()) {
   2540     os << "[cleared]";
   2541   } else if (maybe_object->ToWeakHeapObject(&heap_object)) {
   2542     os << "[weak] ";
   2543     heap_object->HeapObjectShortPrint(os);
   2544   } else if (maybe_object->ToStrongHeapObject(&heap_object)) {
   2545     heap_object->HeapObjectShortPrint(os);
   2546   } else {
   2547     UNREACHABLE();
   2548   }
   2549   return os;
   2550 }
   2551 
   2552 void Smi::SmiPrint(std::ostream& os) const {  // NOLINT
   2553   os << value();
   2554 }
   2555 
   2556 Handle<String> String::SlowFlatten(Isolate* isolate, Handle<ConsString> cons,
   2557                                    PretenureFlag pretenure) {
   2558   DCHECK_NE(cons->second()->length(), 0);
   2559 
   2560   // TurboFan can create cons strings with empty first parts.
   2561   while (cons->first()->length() == 0) {
   2562     // We do not want to call this function recursively. Therefore we call
   2563     // String::Flatten only in those cases where String::SlowFlatten is not
   2564     // called again.
   2565     if (cons->second()->IsConsString() && !cons->second()->IsFlat()) {
   2566       cons = handle(ConsString::cast(cons->second()), isolate);
   2567     } else {
   2568       return String::Flatten(isolate, handle(cons->second(), isolate));
   2569     }
   2570   }
   2571 
   2572   DCHECK(AllowHeapAllocation::IsAllowed());
   2573   int length = cons->length();
   2574   PretenureFlag tenure = Heap::InNewSpace(*cons) ? pretenure : TENURED;
   2575   Handle<SeqString> result;
   2576   if (cons->IsOneByteRepresentation()) {
   2577     Handle<SeqOneByteString> flat = isolate->factory()->NewRawOneByteString(
   2578         length, tenure).ToHandleChecked();
   2579     DisallowHeapAllocation no_gc;
   2580     WriteToFlat(*cons, flat->GetChars(), 0, length);
   2581     result = flat;
   2582   } else {
   2583     Handle<SeqTwoByteString> flat = isolate->factory()->NewRawTwoByteString(
   2584         length, tenure).ToHandleChecked();
   2585     DisallowHeapAllocation no_gc;
   2586     WriteToFlat(*cons, flat->GetChars(), 0, length);
   2587     result = flat;
   2588   }
   2589   cons->set_first(isolate, *result);
   2590   cons->set_second(isolate, ReadOnlyRoots(isolate).empty_string());
   2591   DCHECK(result->IsFlat());
   2592   return result;
   2593 }
   2594 
   2595 
   2596 
   2597 bool String::MakeExternal(v8::String::ExternalStringResource* resource) {
   2598   DisallowHeapAllocation no_allocation;
   2599   // Externalizing twice leaks the external resource, so it's
   2600   // prohibited by the API.
   2601   DCHECK(this->SupportsExternalization());
   2602   DCHECK(!resource->IsCompressible());
   2603 #ifdef ENABLE_SLOW_DCHECKS
   2604   if (FLAG_enable_slow_asserts) {
   2605     // Assert that the resource and the string are equivalent.
   2606     DCHECK(static_cast<size_t>(this->length()) == resource->length());
   2607     ScopedVector<uc16> smart_chars(this->length());
   2608     String::WriteToFlat(this, smart_chars.start(), 0, this->length());
   2609     DCHECK_EQ(0, memcmp(smart_chars.start(), resource->data(),
   2610                         resource->length() * sizeof(smart_chars[0])));
   2611   }
   2612 #endif  // DEBUG
   2613   int size = this->Size();  // Byte size of the original string.
   2614   // Abort if size does not allow in-place conversion.
   2615   if (size < ExternalString::kShortSize) return false;
   2616   Isolate* isolate;
   2617   // Read-only strings cannot be made external, since that would mutate the
   2618   // string.
   2619   if (!Isolate::FromWritableHeapObject(this, &isolate)) return false;
   2620   Heap* heap = isolate->heap();
   2621   bool is_one_byte = this->IsOneByteRepresentation();
   2622   bool is_internalized = this->IsInternalizedString();
   2623   bool has_pointers = StringShape(this).IsIndirect();
   2624   if (has_pointers) {
   2625     heap->NotifyObjectLayoutChange(this, size, no_allocation);
   2626   }
   2627   // Morph the string to an external string by replacing the map and
   2628   // reinitializing the fields.  This won't work if the space the existing
   2629   // string occupies is too small for a regular  external string.
   2630   // Instead, we resort to a short external string instead, omitting
   2631   // the field caching the address of the backing store.  When we encounter
   2632   // short external strings in generated code, we need to bailout to runtime.
   2633   Map* new_map;
   2634   ReadOnlyRoots roots(heap);
   2635   if (size < ExternalString::kSize) {
   2636     if (is_internalized) {
   2637       new_map =
   2638           is_one_byte
   2639               ? roots
   2640                     .short_external_internalized_string_with_one_byte_data_map()
   2641               : roots.short_external_internalized_string_map();
   2642     } else {
   2643       new_map = is_one_byte
   2644                     ? roots.short_external_string_with_one_byte_data_map()
   2645                     : roots.short_external_string_map();
   2646     }
   2647   } else {
   2648     new_map =
   2649         is_internalized
   2650             ? (is_one_byte
   2651                    ? roots.external_internalized_string_with_one_byte_data_map()
   2652                    : roots.external_internalized_string_map())
   2653             : (is_one_byte ? roots.external_string_with_one_byte_data_map()
   2654                            : roots.external_string_map());
   2655   }
   2656 
   2657   // Byte size of the external String object.
   2658   int new_size = this->SizeFromMap(new_map);
   2659   heap->CreateFillerObjectAt(this->address() + new_size, size - new_size,
   2660                              ClearRecordedSlots::kNo);
   2661   if (has_pointers) {
   2662     heap->ClearRecordedSlotRange(this->address(), this->address() + new_size);
   2663   }
   2664 
   2665   // We are storing the new map using release store after creating a filler for
   2666   // the left-over space to avoid races with the sweeper thread.
   2667   this->synchronized_set_map(new_map);
   2668 
   2669   ExternalTwoByteString* self = ExternalTwoByteString::cast(this);
   2670   self->SetResource(isolate, resource);
   2671   heap->RegisterExternalString(this);
   2672   if (is_internalized) self->Hash();  // Force regeneration of the hash value.
   2673   return true;
   2674 }
   2675 
   2676 
   2677 bool String::MakeExternal(v8::String::ExternalOneByteStringResource* resource) {
   2678   DisallowHeapAllocation no_allocation;
   2679   // Externalizing twice leaks the external resource, so it's
   2680   // prohibited by the API.
   2681   DCHECK(this->SupportsExternalization());
   2682   DCHECK(!resource->IsCompressible());
   2683 #ifdef ENABLE_SLOW_DCHECKS
   2684   if (FLAG_enable_slow_asserts) {
   2685     // Assert that the resource and the string are equivalent.
   2686     DCHECK(static_cast<size_t>(this->length()) == resource->length());
   2687     if (this->IsTwoByteRepresentation()) {
   2688       ScopedVector<uint16_t> smart_chars(this->length());
   2689       String::WriteToFlat(this, smart_chars.start(), 0, this->length());
   2690       DCHECK(String::IsOneByte(smart_chars.start(), this->length()));
   2691     }
   2692     ScopedVector<char> smart_chars(this->length());
   2693     String::WriteToFlat(this, smart_chars.start(), 0, this->length());
   2694     DCHECK_EQ(0, memcmp(smart_chars.start(), resource->data(),
   2695                         resource->length() * sizeof(smart_chars[0])));
   2696   }
   2697 #endif  // DEBUG
   2698   int size = this->Size();  // Byte size of the original string.
   2699   // Abort if size does not allow in-place conversion.
   2700   if (size < ExternalString::kShortSize) return false;
   2701   Isolate* isolate;
   2702   // Read-only strings cannot be made external, since that would mutate the
   2703   // string.
   2704   if (!Isolate::FromWritableHeapObject(this, &isolate)) return false;
   2705   Heap* heap = isolate->heap();
   2706   bool is_internalized = this->IsInternalizedString();
   2707   bool has_pointers = StringShape(this).IsIndirect();
   2708 
   2709   if (has_pointers) {
   2710     heap->NotifyObjectLayoutChange(this, size, no_allocation);
   2711   }
   2712 
   2713   // Morph the string to an external string by replacing the map and
   2714   // reinitializing the fields.  This won't work if the space the existing
   2715   // string occupies is too small for a regular  external string.
   2716   // Instead, we resort to a short external string instead, omitting
   2717   // the field caching the address of the backing store.  When we encounter
   2718   // short external strings in generated code, we need to bailout to runtime.
   2719   Map* new_map;
   2720   ReadOnlyRoots roots(heap);
   2721   if (size < ExternalString::kSize) {
   2722     new_map = is_internalized
   2723                   ? roots.short_external_one_byte_internalized_string_map()
   2724                   : roots.short_external_one_byte_string_map();
   2725   } else {
   2726     new_map = is_internalized
   2727                   ? roots.external_one_byte_internalized_string_map()
   2728                   : roots.external_one_byte_string_map();
   2729   }
   2730 
   2731   // Byte size of the external String object.
   2732   int new_size = this->SizeFromMap(new_map);
   2733   heap->CreateFillerObjectAt(this->address() + new_size, size - new_size,
   2734                              ClearRecordedSlots::kNo);
   2735   if (has_pointers) {
   2736     heap->ClearRecordedSlotRange(this->address(), this->address() + new_size);
   2737   }
   2738 
   2739   // We are storing the new map using release store after creating a filler for
   2740   // the left-over space to avoid races with the sweeper thread.
   2741   this->synchronized_set_map(new_map);
   2742 
   2743   ExternalOneByteString* self = ExternalOneByteString::cast(this);
   2744   self->SetResource(isolate, resource);
   2745   heap->RegisterExternalString(this);
   2746   if (is_internalized) self->Hash();  // Force regeneration of the hash value.
   2747   return true;
   2748 }
   2749 
   2750 bool String::SupportsExternalization() {
   2751   if (this->IsThinString()) {
   2752     return i::ThinString::cast(this)->actual()->SupportsExternalization();
   2753   }
   2754 
   2755   Isolate* isolate;
   2756   // RO_SPACE strings cannot be externalized.
   2757   if (!Isolate::FromWritableHeapObject(this, &isolate)) {
   2758     return false;
   2759   }
   2760 
   2761   // Already an external string.
   2762   if (StringShape(this).IsExternal()) {
   2763     return false;
   2764   }
   2765 
   2766   return !isolate->heap()->IsInGCPostProcessing();
   2767 }
   2768 
   2769 void String::StringShortPrint(StringStream* accumulator, bool show_details) {
   2770   int len = length();
   2771   if (len > kMaxShortPrintLength) {
   2772     accumulator->Add("<Very long string[%u]>", len);
   2773     return;
   2774   }
   2775 
   2776   if (!LooksValid()) {
   2777     accumulator->Add("<Invalid String>");
   2778     return;
   2779   }
   2780 
   2781   StringCharacterStream stream(this);
   2782 
   2783   bool truncated = false;
   2784   if (len > kMaxShortPrintLength) {
   2785     len = kMaxShortPrintLength;
   2786     truncated = true;
   2787   }
   2788   bool one_byte = true;
   2789   for (int i = 0; i < len; i++) {
   2790     uint16_t c = stream.GetNext();
   2791 
   2792     if (c < 32 || c >= 127) {
   2793       one_byte = false;
   2794     }
   2795   }
   2796   stream.Reset(this);
   2797   if (one_byte) {
   2798     if (show_details) accumulator->Add("<String[%u]: ", length());
   2799     for (int i = 0; i < len; i++) {
   2800       accumulator->Put(static_cast<char>(stream.GetNext()));
   2801     }
   2802     if (show_details) accumulator->Put('>');
   2803   } else {
   2804     // Backslash indicates that the string contains control
   2805     // characters and that backslashes are therefore escaped.
   2806     if (show_details) accumulator->Add("<String[%u]\\: ", length());
   2807     for (int i = 0; i < len; i++) {
   2808       uint16_t c = stream.GetNext();
   2809       if (c == '\n') {
   2810         accumulator->Add("\\n");
   2811       } else if (c == '\r') {
   2812         accumulator->Add("\\r");
   2813       } else if (c == '\\') {
   2814         accumulator->Add("\\\\");
   2815       } else if (c < 32 || c > 126) {
   2816         accumulator->Add("\\x%02x", c);
   2817       } else {
   2818         accumulator->Put(static_cast<char>(c));
   2819       }
   2820     }
   2821     if (truncated) {
   2822       accumulator->Put('.');
   2823       accumulator->Put('.');
   2824       accumulator->Put('.');
   2825     }
   2826     if (show_details) accumulator->Put('>');
   2827   }
   2828   return;
   2829 }
   2830 
   2831 
   2832 void String::PrintUC16(std::ostream& os, int start, int end) {  // NOLINT
   2833   if (end < 0) end = length();
   2834   StringCharacterStream stream(this, start);
   2835   for (int i = start; i < end && stream.HasMore(); i++) {
   2836     os << AsUC16(stream.GetNext());
   2837   }
   2838 }
   2839 
   2840 
   2841 void JSObject::JSObjectShortPrint(StringStream* accumulator) {
   2842   switch (map()->instance_type()) {
   2843     case JS_ARRAY_TYPE: {
   2844       double length = JSArray::cast(this)->length()->IsUndefined()
   2845                           ? 0
   2846                           : JSArray::cast(this)->length()->Number();
   2847       accumulator->Add("<JSArray[%u]>", static_cast<uint32_t>(length));
   2848       break;
   2849     }
   2850     case JS_BOUND_FUNCTION_TYPE: {
   2851       JSBoundFunction* bound_function = JSBoundFunction::cast(this);
   2852       accumulator->Add("<JSBoundFunction");
   2853       accumulator->Add(
   2854           " (BoundTargetFunction %p)>",
   2855           reinterpret_cast<void*>(bound_function->bound_target_function()));
   2856       break;
   2857     }
   2858     case JS_WEAK_MAP_TYPE: {
   2859       accumulator->Add("<JSWeakMap>");
   2860       break;
   2861     }
   2862     case JS_WEAK_SET_TYPE: {
   2863       accumulator->Add("<JSWeakSet>");
   2864       break;
   2865     }
   2866     case JS_REGEXP_TYPE: {
   2867       accumulator->Add("<JSRegExp");
   2868       JSRegExp* regexp = JSRegExp::cast(this);
   2869       if (regexp->source()->IsString()) {
   2870         accumulator->Add(" ");
   2871         String::cast(regexp->source())->StringShortPrint(accumulator);
   2872       }
   2873       accumulator->Add(">");
   2874 
   2875       break;
   2876     }
   2877     case JS_FUNCTION_TYPE: {
   2878       JSFunction* function = JSFunction::cast(this);
   2879       Object* fun_name = function->shared()->DebugName();
   2880       bool printed = false;
   2881       if (fun_name->IsString()) {
   2882         String* str = String::cast(fun_name);
   2883         if (str->length() > 0) {
   2884           accumulator->Add("<JSFunction ");
   2885           accumulator->Put(str);
   2886           printed = true;
   2887         }
   2888       }
   2889       if (!printed) {
   2890         accumulator->Add("<JSFunction");
   2891       }
   2892       if (FLAG_trace_file_names) {
   2893         Object* source_name =
   2894             Script::cast(function->shared()->script())->name();
   2895         if (source_name->IsString()) {
   2896           String* str = String::cast(source_name);
   2897           if (str->length() > 0) {
   2898             accumulator->Add(" <");
   2899             accumulator->Put(str);
   2900             accumulator->Add(">");
   2901           }
   2902         }
   2903       }
   2904       accumulator->Add(" (sfi = %p)",
   2905                        reinterpret_cast<void*>(function->shared()));
   2906       accumulator->Put('>');
   2907       break;
   2908     }
   2909     case JS_GENERATOR_OBJECT_TYPE: {
   2910       accumulator->Add("<JSGenerator>");
   2911       break;
   2912     }
   2913     case JS_ASYNC_GENERATOR_OBJECT_TYPE: {
   2914       accumulator->Add("<JS AsyncGenerator>");
   2915       break;
   2916     }
   2917 
   2918     // All other JSObjects are rather similar to each other (JSObject,
   2919     // JSGlobalProxy, JSGlobalObject, JSUndetectable, JSValue).
   2920     default: {
   2921       Map* map_of_this = map();
   2922       Heap* heap = GetHeap();
   2923       Object* constructor = map_of_this->GetConstructor();
   2924       bool printed = false;
   2925       if (constructor->IsHeapObject() &&
   2926           !heap->Contains(HeapObject::cast(constructor))) {
   2927         accumulator->Add("!!!INVALID CONSTRUCTOR!!!");
   2928       } else {
   2929         bool global_object = IsJSGlobalProxy();
   2930         if (constructor->IsJSFunction()) {
   2931           if (!heap->Contains(JSFunction::cast(constructor)->shared())) {
   2932             accumulator->Add("!!!INVALID SHARED ON CONSTRUCTOR!!!");
   2933           } else {
   2934             String* constructor_name =
   2935                 JSFunction::cast(constructor)->shared()->Name();
   2936             if (constructor_name->length() > 0) {
   2937               accumulator->Add(global_object ? "<GlobalObject " : "<");
   2938               accumulator->Put(constructor_name);
   2939               accumulator->Add(
   2940                   " %smap = %p",
   2941                   map_of_this->is_deprecated() ? "deprecated-" : "",
   2942                   map_of_this);
   2943               printed = true;
   2944             }
   2945           }
   2946         } else if (constructor->IsFunctionTemplateInfo()) {
   2947           accumulator->Add(global_object ? "<RemoteObject>" : "<RemoteObject>");
   2948           printed = true;
   2949         }
   2950         if (!printed) {
   2951           accumulator->Add("<JS%sObject", global_object ? "Global " : "");
   2952         }
   2953       }
   2954       if (IsJSValue()) {
   2955         accumulator->Add(" value = ");
   2956         JSValue::cast(this)->value()->ShortPrint(accumulator);
   2957       }
   2958       accumulator->Put('>');
   2959       break;
   2960     }
   2961   }
   2962 }
   2963 
   2964 
   2965 void JSObject::PrintElementsTransition(
   2966     FILE* file, Handle<JSObject> object,
   2967     ElementsKind from_kind, Handle<FixedArrayBase> from_elements,
   2968     ElementsKind to_kind, Handle<FixedArrayBase> to_elements) {
   2969   if (from_kind != to_kind) {
   2970     OFStream os(file);
   2971     os << "elements transition [" << ElementsKindToString(from_kind) << " -> "
   2972        << ElementsKindToString(to_kind) << "] in ";
   2973     JavaScriptFrame::PrintTop(object->GetIsolate(), file, false, true);
   2974     PrintF(file, " for ");
   2975     object->ShortPrint(file);
   2976     PrintF(file, " from ");
   2977     from_elements->ShortPrint(file);
   2978     PrintF(file, " to ");
   2979     to_elements->ShortPrint(file);
   2980     PrintF(file, "\n");
   2981   }
   2982 }
   2983 
   2984 
   2985 // static
   2986 MaybeHandle<JSFunction> Map::GetConstructorFunction(
   2987     Handle<Map> map, Handle<Context> native_context) {
   2988   if (map->IsPrimitiveMap()) {
   2989     int const constructor_function_index = map->GetConstructorFunctionIndex();
   2990     if (constructor_function_index != kNoConstructorFunctionIndex) {
   2991       return handle(
   2992           JSFunction::cast(native_context->get(constructor_function_index)),
   2993           native_context->GetIsolate());
   2994     }
   2995   }
   2996   return MaybeHandle<JSFunction>();
   2997 }
   2998 
   2999 void Map::PrintReconfiguration(Isolate* isolate, FILE* file, int modify_index,
   3000                                PropertyKind kind,
   3001                                PropertyAttributes attributes) {
   3002   OFStream os(file);
   3003   os << "[reconfiguring]";
   3004   Name* name = instance_descriptors()->GetKey(modify_index);
   3005   if (name->IsString()) {
   3006     String::cast(name)->PrintOn(file);
   3007   } else {
   3008     os << "{symbol " << static_cast<void*>(name) << "}";
   3009   }
   3010   os << ": " << (kind == kData ? "kData" : "ACCESSORS") << ", attrs: ";
   3011   os << attributes << " [";
   3012   JavaScriptFrame::PrintTop(isolate, file, false, true);
   3013   os << "]\n";
   3014 }
   3015 
   3016 VisitorId Map::GetVisitorId(Map* map) {
   3017   STATIC_ASSERT(kVisitorIdCount <= 256);
   3018 
   3019   const int instance_type = map->instance_type();
   3020   const bool has_unboxed_fields =
   3021       FLAG_unbox_double_fields && !map->HasFastPointerLayout();
   3022   if (instance_type < FIRST_NONSTRING_TYPE) {
   3023     switch (instance_type & kStringRepresentationMask) {
   3024       case kSeqStringTag:
   3025         if ((instance_type & kStringEncodingMask) == kOneByteStringTag) {
   3026           return kVisitSeqOneByteString;
   3027         } else {
   3028           return kVisitSeqTwoByteString;
   3029         }
   3030 
   3031       case kConsStringTag:
   3032         if (IsShortcutCandidate(instance_type)) {
   3033           return kVisitShortcutCandidate;
   3034         } else {
   3035           return kVisitConsString;
   3036         }
   3037 
   3038       case kSlicedStringTag:
   3039         return kVisitSlicedString;
   3040 
   3041       case kExternalStringTag:
   3042         return kVisitDataObject;
   3043 
   3044       case kThinStringTag:
   3045         return kVisitThinString;
   3046     }
   3047     UNREACHABLE();
   3048   }
   3049 
   3050   switch (instance_type) {
   3051     case BYTE_ARRAY_TYPE:
   3052       return kVisitByteArray;
   3053 
   3054     case BYTECODE_ARRAY_TYPE:
   3055       return kVisitBytecodeArray;
   3056 
   3057     case FREE_SPACE_TYPE:
   3058       return kVisitFreeSpace;
   3059 
   3060     case FIXED_ARRAY_TYPE:
   3061     case OBJECT_BOILERPLATE_DESCRIPTION_TYPE:
   3062     case HASH_TABLE_TYPE:
   3063     case ORDERED_HASH_MAP_TYPE:
   3064     case ORDERED_HASH_SET_TYPE:
   3065     case NAME_DICTIONARY_TYPE:
   3066     case GLOBAL_DICTIONARY_TYPE:
   3067     case NUMBER_DICTIONARY_TYPE:
   3068     case SIMPLE_NUMBER_DICTIONARY_TYPE:
   3069     case STRING_TABLE_TYPE:
   3070     case SCOPE_INFO_TYPE:
   3071     case SCRIPT_CONTEXT_TABLE_TYPE:
   3072     case BLOCK_CONTEXT_TYPE:
   3073     case CATCH_CONTEXT_TYPE:
   3074     case DEBUG_EVALUATE_CONTEXT_TYPE:
   3075     case EVAL_CONTEXT_TYPE:
   3076     case FUNCTION_CONTEXT_TYPE:
   3077     case MODULE_CONTEXT_TYPE:
   3078     case NATIVE_CONTEXT_TYPE:
   3079     case SCRIPT_CONTEXT_TYPE:
   3080     case WITH_CONTEXT_TYPE:
   3081       return kVisitFixedArray;
   3082 
   3083     case EPHEMERON_HASH_TABLE_TYPE:
   3084       return kVisitEphemeronHashTable;
   3085 
   3086     case WEAK_FIXED_ARRAY_TYPE:
   3087     case WEAK_ARRAY_LIST_TYPE:
   3088     case DESCRIPTOR_ARRAY_TYPE:
   3089       return kVisitWeakArray;
   3090 
   3091     case FIXED_DOUBLE_ARRAY_TYPE:
   3092       return kVisitFixedDoubleArray;
   3093 
   3094     case PROPERTY_ARRAY_TYPE:
   3095       return kVisitPropertyArray;
   3096 
   3097     case FEEDBACK_CELL_TYPE:
   3098       return kVisitFeedbackCell;
   3099 
   3100     case FEEDBACK_VECTOR_TYPE:
   3101       return kVisitFeedbackVector;
   3102 
   3103     case ODDBALL_TYPE:
   3104       return kVisitOddball;
   3105 
   3106     case MAP_TYPE:
   3107       return kVisitMap;
   3108 
   3109     case CODE_TYPE:
   3110       return kVisitCode;
   3111 
   3112     case CELL_TYPE:
   3113       return kVisitCell;
   3114 
   3115     case PROPERTY_CELL_TYPE:
   3116       return kVisitPropertyCell;
   3117 
   3118     case TRANSITION_ARRAY_TYPE:
   3119       return kVisitTransitionArray;
   3120 
   3121     case JS_WEAK_MAP_TYPE:
   3122     case JS_WEAK_SET_TYPE:
   3123       return kVisitJSWeakCollection;
   3124 
   3125     case CALL_HANDLER_INFO_TYPE:
   3126       return kVisitStruct;
   3127 
   3128     case SHARED_FUNCTION_INFO_TYPE:
   3129       return kVisitSharedFunctionInfo;
   3130 
   3131     case JS_PROXY_TYPE:
   3132       return kVisitStruct;
   3133 
   3134     case SYMBOL_TYPE:
   3135       return kVisitSymbol;
   3136 
   3137     case JS_ARRAY_BUFFER_TYPE:
   3138       return kVisitJSArrayBuffer;
   3139 
   3140     case SMALL_ORDERED_HASH_MAP_TYPE:
   3141       return kVisitSmallOrderedHashMap;
   3142 
   3143     case SMALL_ORDERED_HASH_SET_TYPE:
   3144       return kVisitSmallOrderedHashSet;
   3145 
   3146     case CODE_DATA_CONTAINER_TYPE:
   3147       return kVisitCodeDataContainer;
   3148 
   3149     case WASM_INSTANCE_TYPE:
   3150       return kVisitWasmInstanceObject;
   3151 
   3152     case PRE_PARSED_SCOPE_DATA_TYPE:
   3153       return kVisitPreParsedScopeData;
   3154 
   3155     case UNCOMPILED_DATA_WITHOUT_PRE_PARSED_SCOPE_TYPE:
   3156       return kVisitUncompiledDataWithoutPreParsedScope;
   3157 
   3158     case UNCOMPILED_DATA_WITH_PRE_PARSED_SCOPE_TYPE:
   3159       return kVisitUncompiledDataWithPreParsedScope;
   3160 
   3161     case JS_OBJECT_TYPE:
   3162     case JS_ERROR_TYPE:
   3163     case JS_ARGUMENTS_TYPE:
   3164     case JS_ASYNC_FROM_SYNC_ITERATOR_TYPE:
   3165     case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
   3166     case JS_GENERATOR_OBJECT_TYPE:
   3167     case JS_ASYNC_GENERATOR_OBJECT_TYPE:
   3168     case JS_MODULE_NAMESPACE_TYPE:
   3169     case JS_VALUE_TYPE:
   3170     case JS_DATE_TYPE:
   3171     case JS_ARRAY_ITERATOR_TYPE:
   3172     case JS_ARRAY_TYPE:
   3173     case JS_GLOBAL_PROXY_TYPE:
   3174     case JS_GLOBAL_OBJECT_TYPE:
   3175     case JS_MESSAGE_OBJECT_TYPE:
   3176     case JS_TYPED_ARRAY_TYPE:
   3177     case JS_DATA_VIEW_TYPE:
   3178     case JS_SET_TYPE:
   3179     case JS_MAP_TYPE:
   3180     case JS_SET_KEY_VALUE_ITERATOR_TYPE:
   3181     case JS_SET_VALUE_ITERATOR_TYPE:
   3182     case JS_MAP_KEY_ITERATOR_TYPE:
   3183     case JS_MAP_KEY_VALUE_ITERATOR_TYPE:
   3184     case JS_MAP_VALUE_ITERATOR_TYPE:
   3185     case JS_STRING_ITERATOR_TYPE:
   3186     case JS_PROMISE_TYPE:
   3187     case JS_REGEXP_TYPE:
   3188     case JS_REGEXP_STRING_ITERATOR_TYPE:
   3189 #ifdef V8_INTL_SUPPORT
   3190     case JS_INTL_COLLATOR_TYPE:
   3191     case JS_INTL_LIST_FORMAT_TYPE:
   3192     case JS_INTL_LOCALE_TYPE:
   3193     case JS_INTL_PLURAL_RULES_TYPE:
   3194     case JS_INTL_RELATIVE_TIME_FORMAT_TYPE:
   3195 #endif  // V8_INTL_SUPPORT
   3196     case WASM_GLOBAL_TYPE:
   3197     case WASM_MEMORY_TYPE:
   3198     case WASM_MODULE_TYPE:
   3199     case WASM_TABLE_TYPE:
   3200     case JS_BOUND_FUNCTION_TYPE:
   3201       return has_unboxed_fields ? kVisitJSObject : kVisitJSObjectFast;
   3202     case JS_API_OBJECT_TYPE:
   3203     case JS_SPECIAL_API_OBJECT_TYPE:
   3204       return kVisitJSApiObject;
   3205 
   3206     case JS_FUNCTION_TYPE:
   3207       return kVisitJSFunction;
   3208 
   3209     case FILLER_TYPE:
   3210     case FOREIGN_TYPE:
   3211     case HEAP_NUMBER_TYPE:
   3212     case MUTABLE_HEAP_NUMBER_TYPE:
   3213     case FEEDBACK_METADATA_TYPE:
   3214       return kVisitDataObject;
   3215 
   3216     case BIGINT_TYPE:
   3217       return kVisitBigInt;
   3218 
   3219     case FIXED_UINT8_ARRAY_TYPE:
   3220     case FIXED_INT8_ARRAY_TYPE:
   3221     case FIXED_UINT16_ARRAY_TYPE:
   3222     case FIXED_INT16_ARRAY_TYPE:
   3223     case FIXED_UINT32_ARRAY_TYPE:
   3224     case FIXED_INT32_ARRAY_TYPE:
   3225     case FIXED_FLOAT32_ARRAY_TYPE:
   3226     case FIXED_UINT8_CLAMPED_ARRAY_TYPE:
   3227     case FIXED_BIGUINT64_ARRAY_TYPE:
   3228     case FIXED_BIGINT64_ARRAY_TYPE:
   3229       return kVisitFixedTypedArrayBase;
   3230 
   3231     case FIXED_FLOAT64_ARRAY_TYPE:
   3232       return kVisitFixedFloat64Array;
   3233 
   3234     case ALLOCATION_SITE_TYPE:
   3235       return kVisitAllocationSite;
   3236 
   3237 #define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE:
   3238       STRUCT_LIST(MAKE_STRUCT_CASE)
   3239 #undef MAKE_STRUCT_CASE
   3240       if (instance_type == PROTOTYPE_INFO_TYPE) {
   3241         return kVisitPrototypeInfo;
   3242       }
   3243       return kVisitStruct;
   3244 
   3245     case LOAD_HANDLER_TYPE:
   3246     case STORE_HANDLER_TYPE:
   3247       return kVisitDataHandler;
   3248 
   3249     default:
   3250       UNREACHABLE();
   3251   }
   3252 }
   3253 
   3254 void Map::PrintGeneralization(
   3255     Isolate* isolate, FILE* file, const char* reason, int modify_index,
   3256     int split, int descriptors, bool descriptor_to_field,
   3257     Representation old_representation, Representation new_representation,
   3258     MaybeHandle<FieldType> old_field_type, MaybeHandle<Object> old_value,
   3259     MaybeHandle<FieldType> new_field_type, MaybeHandle<Object> new_value) {
   3260   OFStream os(file);
   3261   os << "[generalizing]";
   3262   Name* name = instance_descriptors()->GetKey(modify_index);
   3263   if (name->IsString()) {
   3264     String::cast(name)->PrintOn(file);
   3265   } else {
   3266     os << "{symbol " << static_cast<void*>(name) << "}";
   3267   }
   3268   os << ":";
   3269   if (descriptor_to_field) {
   3270     os << "c";
   3271   } else {
   3272     os << old_representation.Mnemonic() << "{";
   3273     if (old_field_type.is_null()) {
   3274       os << Brief(*(old_value.ToHandleChecked()));
   3275     } else {
   3276       old_field_type.ToHandleChecked()->PrintTo(os);
   3277     }
   3278     os << "}";
   3279   }
   3280   os << "->" << new_representation.Mnemonic() << "{";
   3281   if (new_field_type.is_null()) {
   3282     os << Brief(*(new_value.ToHandleChecked()));
   3283   } else {
   3284     new_field_type.ToHandleChecked()->PrintTo(os);
   3285   }
   3286   os << "} (";
   3287   if (strlen(reason) > 0) {
   3288     os << reason;
   3289   } else {
   3290     os << "+" << (descriptors - split) << " maps";
   3291   }
   3292   os << ") [";
   3293   JavaScriptFrame::PrintTop(isolate, file, false, true);
   3294   os << "]\n";
   3295 }
   3296 
   3297 
   3298 void JSObject::PrintInstanceMigration(FILE* file,
   3299                                       Map* original_map,
   3300                                       Map* new_map) {
   3301   if (new_map->is_dictionary_map()) {
   3302     PrintF(file, "[migrating to slow]\n");
   3303     return;
   3304   }
   3305   PrintF(file, "[migrating]");
   3306   DescriptorArray* o = original_map->instance_descriptors();
   3307   DescriptorArray* n = new_map->instance_descriptors();
   3308   for (int i = 0; i < original_map->NumberOfOwnDescriptors(); i++) {
   3309     Representation o_r = o->GetDetails(i).representation();
   3310     Representation n_r = n->GetDetails(i).representation();
   3311     if (!o_r.Equals(n_r)) {
   3312       String::cast(o->GetKey(i))->PrintOn(file);
   3313       PrintF(file, ":%s->%s ", o_r.Mnemonic(), n_r.Mnemonic());
   3314     } else if (o->GetDetails(i).location() == kDescriptor &&
   3315                n->GetDetails(i).location() == kField) {
   3316       Name* name = o->GetKey(i);
   3317       if (name->IsString()) {
   3318         String::cast(name)->PrintOn(file);
   3319       } else {
   3320         PrintF(file, "{symbol %p}", static_cast<void*>(name));
   3321       }
   3322       PrintF(file, " ");
   3323     }
   3324   }
   3325   if (original_map->elements_kind() != new_map->elements_kind()) {
   3326     PrintF(file, "elements_kind[%i->%i]", original_map->elements_kind(),
   3327            new_map->elements_kind());
   3328   }
   3329   PrintF(file, "\n");
   3330 }
   3331 
   3332 bool JSObject::IsUnmodifiedApiObject(Object** o) {
   3333   Object* object = *o;
   3334   if (object->IsSmi()) return false;
   3335   HeapObject* heap_object = HeapObject::cast(object);
   3336   if (!object->IsJSObject()) return false;
   3337   JSObject* js_object = JSObject::cast(object);
   3338   if (!js_object->IsApiWrapper()) return false;
   3339   Object* maybe_constructor = js_object->map()->GetConstructor();
   3340   if (!maybe_constructor->IsJSFunction()) return false;
   3341   JSFunction* constructor = JSFunction::cast(maybe_constructor);
   3342   if (js_object->elements()->length() != 0) return false;
   3343 
   3344   return constructor->initial_map() == heap_object->map();
   3345 }
   3346 
   3347 void HeapObject::HeapObjectShortPrint(std::ostream& os) {  // NOLINT
   3348   os << AsHex(reinterpret_cast<Address>(this), kPointerHexDigits, true) << " ";
   3349 
   3350   if (IsString()) {
   3351     HeapStringAllocator allocator;
   3352     StringStream accumulator(&allocator);
   3353     String::cast(this)->StringShortPrint(&accumulator);
   3354     os << accumulator.ToCString().get();
   3355     return;
   3356   }
   3357   if (IsJSObject()) {
   3358     HeapStringAllocator allocator;
   3359     StringStream accumulator(&allocator);
   3360     JSObject::cast(this)->JSObjectShortPrint(&accumulator);
   3361     os << accumulator.ToCString().get();
   3362     return;
   3363   }
   3364   switch (map()->instance_type()) {
   3365     case MAP_TYPE: {
   3366       os << "<Map";
   3367       Map* mapInstance = Map::cast(this);
   3368       if (mapInstance->IsJSObjectMap()) {
   3369         os << "(" << ElementsKindToString(mapInstance->elements_kind()) << ")";
   3370       } else if (mapInstance->instance_size() != kVariableSizeSentinel) {
   3371         os << "[" << mapInstance->instance_size() << "]";
   3372       }
   3373       os << ">";
   3374     } break;
   3375     case BLOCK_CONTEXT_TYPE:
   3376       os << "<BlockContext[" << FixedArray::cast(this)->length() << "]>";
   3377       break;
   3378     case CATCH_CONTEXT_TYPE:
   3379       os << "<CatchContext[" << FixedArray::cast(this)->length() << "]>";
   3380       break;
   3381     case DEBUG_EVALUATE_CONTEXT_TYPE:
   3382       os << "<DebugEvaluateContext[" << FixedArray::cast(this)->length()
   3383          << "]>";
   3384       break;
   3385     case EVAL_CONTEXT_TYPE:
   3386       os << "<EvalContext[" << FixedArray::cast(this)->length() << "]>";
   3387       break;
   3388     case FUNCTION_CONTEXT_TYPE:
   3389       os << "<FunctionContext[" << FixedArray::cast(this)->length() << "]>";
   3390       break;
   3391     case MODULE_CONTEXT_TYPE:
   3392       os << "<ModuleContext[" << FixedArray::cast(this)->length() << "]>";
   3393       break;
   3394     case NATIVE_CONTEXT_TYPE:
   3395       os << "<NativeContext[" << FixedArray::cast(this)->length() << "]>";
   3396       break;
   3397     case SCRIPT_CONTEXT_TYPE:
   3398       os << "<ScriptContext[" << FixedArray::cast(this)->length() << "]>";
   3399       break;
   3400     case WITH_CONTEXT_TYPE:
   3401       os << "<WithContext[" << FixedArray::cast(this)->length() << "]>";
   3402       break;
   3403     case SCRIPT_CONTEXT_TABLE_TYPE:
   3404       os << "<ScriptContextTable[" << FixedArray::cast(this)->length() << "]>";
   3405       break;
   3406     case HASH_TABLE_TYPE:
   3407       os << "<HashTable[" << FixedArray::cast(this)->length() << "]>";
   3408       break;
   3409     case ORDERED_HASH_MAP_TYPE:
   3410       os << "<OrderedHashMap[" << FixedArray::cast(this)->length() << "]>";
   3411       break;
   3412     case ORDERED_HASH_SET_TYPE:
   3413       os << "<OrderedHashSet[" << FixedArray::cast(this)->length() << "]>";
   3414       break;
   3415     case NAME_DICTIONARY_TYPE:
   3416       os << "<NameDictionary[" << FixedArray::cast(this)->length() << "]>";
   3417       break;
   3418     case GLOBAL_DICTIONARY_TYPE:
   3419       os << "<GlobalDictionary[" << FixedArray::cast(this)->length() << "]>";
   3420       break;
   3421     case NUMBER_DICTIONARY_TYPE:
   3422       os << "<NumberDictionary[" << FixedArray::cast(this)->length() << "]>";
   3423       break;
   3424     case SIMPLE_NUMBER_DICTIONARY_TYPE:
   3425       os << "<SimpleNumberDictionary[" << FixedArray::cast(this)->length()
   3426          << "]>";
   3427       break;
   3428     case STRING_TABLE_TYPE:
   3429       os << "<StringTable[" << FixedArray::cast(this)->length() << "]>";
   3430       break;
   3431     case FIXED_ARRAY_TYPE:
   3432       os << "<FixedArray[" << FixedArray::cast(this)->length() << "]>";
   3433       break;
   3434     case OBJECT_BOILERPLATE_DESCRIPTION_TYPE:
   3435       os << "<ObjectBoilerplateDescription[" << FixedArray::cast(this)->length()
   3436          << "]>";
   3437       break;
   3438     case FIXED_DOUBLE_ARRAY_TYPE:
   3439       os << "<FixedDoubleArray[" << FixedDoubleArray::cast(this)->length()
   3440          << "]>";
   3441       break;
   3442     case BYTE_ARRAY_TYPE:
   3443       os << "<ByteArray[" << ByteArray::cast(this)->length() << "]>";
   3444       break;
   3445     case BYTECODE_ARRAY_TYPE:
   3446       os << "<BytecodeArray[" << BytecodeArray::cast(this)->length() << "]>";
   3447       break;
   3448     case DESCRIPTOR_ARRAY_TYPE:
   3449       os << "<DescriptorArray[" << DescriptorArray::cast(this)->length()
   3450          << "]>";
   3451       break;
   3452     case TRANSITION_ARRAY_TYPE:
   3453       os << "<TransitionArray[" << TransitionArray::cast(this)->length()
   3454          << "]>";
   3455       break;
   3456     case PROPERTY_ARRAY_TYPE:
   3457       os << "<PropertyArray[" << PropertyArray::cast(this)->length() << "]>";
   3458       break;
   3459     case FEEDBACK_CELL_TYPE: {
   3460       {
   3461         ReadOnlyRoots roots = GetReadOnlyRoots();
   3462         os << "<FeedbackCell[";
   3463         if (map() == roots.no_closures_cell_map()) {
   3464           os << "no closures";
   3465         } else if (map() == roots.one_closure_cell_map()) {
   3466           os << "one closure";
   3467         } else if (map() == roots.many_closures_cell_map()) {
   3468           os << "many closures";
   3469         } else {
   3470           os << "!!!INVALID MAP!!!";
   3471         }
   3472         os << "]>";
   3473       }
   3474       break;
   3475     }
   3476     case FEEDBACK_VECTOR_TYPE:
   3477       os << "<FeedbackVector[" << FeedbackVector::cast(this)->length() << "]>";
   3478       break;
   3479     case FREE_SPACE_TYPE:
   3480       os << "<FreeSpace[" << FreeSpace::cast(this)->size() << "]>";
   3481       break;
   3482 #define TYPED_ARRAY_SHORT_PRINT(Type, type, TYPE, ctype)                      \
   3483   case FIXED_##TYPE##_ARRAY_TYPE:                                             \
   3484     os << "<Fixed" #Type "Array[" << Fixed##Type##Array::cast(this)->length() \
   3485        << "]>";                                                               \
   3486     break;
   3487 
   3488       TYPED_ARRAYS(TYPED_ARRAY_SHORT_PRINT)
   3489 #undef TYPED_ARRAY_SHORT_PRINT
   3490 
   3491     case PRE_PARSED_SCOPE_DATA_TYPE: {
   3492       PreParsedScopeData* data = PreParsedScopeData::cast(this);
   3493       os << "<PreParsedScopeData[" << data->length() << "]>";
   3494       break;
   3495     }
   3496 
   3497     case UNCOMPILED_DATA_WITHOUT_PRE_PARSED_SCOPE_TYPE: {
   3498       UncompiledDataWithoutPreParsedScope* data =
   3499           UncompiledDataWithoutPreParsedScope::cast(this);
   3500       os << "<UncompiledDataWithoutPreParsedScope (" << data->start_position()
   3501          << ", " << data->end_position() << ")]>";
   3502       break;
   3503     }
   3504 
   3505     case UNCOMPILED_DATA_WITH_PRE_PARSED_SCOPE_TYPE: {
   3506       UncompiledDataWithPreParsedScope* data =
   3507           UncompiledDataWithPreParsedScope::cast(this);
   3508       os << "<UncompiledDataWithPreParsedScope (" << data->start_position()
   3509          << ", " << data->end_position()
   3510          << ") preparsed=" << Brief(data->pre_parsed_scope_data()) << ">";
   3511       break;
   3512     }
   3513 
   3514     case SHARED_FUNCTION_INFO_TYPE: {
   3515       SharedFunctionInfo* shared = SharedFunctionInfo::cast(this);
   3516       std::unique_ptr<char[]> debug_name = shared->DebugName()->ToCString();
   3517       if (debug_name[0] != 0) {
   3518         os << "<SharedFunctionInfo " << debug_name.get() << ">";
   3519       } else {
   3520         os << "<SharedFunctionInfo>";
   3521       }
   3522       break;
   3523     }
   3524     case JS_MESSAGE_OBJECT_TYPE:
   3525       os << "<JSMessageObject>";
   3526       break;
   3527 #define MAKE_STRUCT_CASE(NAME, Name, name)   \
   3528   case NAME##_TYPE:                          \
   3529     os << "<" #Name;                         \
   3530     Name::cast(this)->BriefPrintDetails(os); \
   3531     os << ">";                               \
   3532     break;
   3533       STRUCT_LIST(MAKE_STRUCT_CASE)
   3534 #undef MAKE_STRUCT_CASE
   3535     case ALLOCATION_SITE_TYPE: {
   3536       os << "<AllocationSite";
   3537       AllocationSite::cast(this)->BriefPrintDetails(os);
   3538       os << ">";
   3539       break;
   3540     }
   3541     case SCOPE_INFO_TYPE: {
   3542       ScopeInfo* scope = ScopeInfo::cast(this);
   3543       os << "<ScopeInfo";
   3544       if (scope->length()) os << " " << scope->scope_type() << " ";
   3545       os << "[" << scope->length() << "]>";
   3546       break;
   3547     }
   3548     case CODE_TYPE: {
   3549       Code* code = Code::cast(this);
   3550       os << "<Code " << Code::Kind2String(code->kind());
   3551       if (code->is_stub()) {
   3552         os << " " << CodeStub::MajorName(CodeStub::GetMajorKey(code));
   3553       } else if (code->is_builtin()) {
   3554         os << " " << Builtins::name(code->builtin_index());
   3555       }
   3556       os << ">";
   3557       break;
   3558     }
   3559     case ODDBALL_TYPE: {
   3560       if (IsUndefined()) {
   3561         os << "<undefined>";
   3562       } else if (IsTheHole()) {
   3563         os << "<the_hole>";
   3564       } else if (IsNull()) {
   3565         os << "<null>";
   3566       } else if (IsTrue()) {
   3567         os << "<true>";
   3568       } else if (IsFalse()) {
   3569         os << "<false>";
   3570       } else {
   3571         os << "<Odd Oddball: ";
   3572         os << Oddball::cast(this)->to_string()->ToCString().get();
   3573         os << ">";
   3574       }
   3575       break;
   3576     }
   3577     case SYMBOL_TYPE: {
   3578       Symbol* symbol = Symbol::cast(this);
   3579       symbol->SymbolShortPrint(os);
   3580       break;
   3581     }
   3582     case HEAP_NUMBER_TYPE: {
   3583       os << "<HeapNumber ";
   3584       HeapNumber::cast(this)->HeapNumberPrint(os);
   3585       os << ">";
   3586       break;
   3587     }
   3588     case MUTABLE_HEAP_NUMBER_TYPE: {
   3589       os << "<MutableHeapNumber ";
   3590       MutableHeapNumber::cast(this)->MutableHeapNumberPrint(os);
   3591       os << '>';
   3592       break;
   3593     }
   3594     case BIGINT_TYPE: {
   3595       os << "<BigInt ";
   3596       BigInt::cast(this)->BigIntShortPrint(os);
   3597       os << ">";
   3598       break;
   3599     }
   3600     case JS_PROXY_TYPE:
   3601       os << "<JSProxy>";
   3602       break;
   3603     case FOREIGN_TYPE:
   3604       os << "<Foreign>";
   3605       break;
   3606     case CELL_TYPE: {
   3607       os << "<Cell value= ";
   3608       HeapStringAllocator allocator;
   3609       StringStream accumulator(&allocator);
   3610       Cell::cast(this)->value()->ShortPrint(&accumulator);
   3611       os << accumulator.ToCString().get();
   3612       os << '>';
   3613       break;
   3614     }
   3615     case PROPERTY_CELL_TYPE: {
   3616       PropertyCell* cell = PropertyCell::cast(this);
   3617       os << "<PropertyCell name=";
   3618       cell->name()->ShortPrint(os);
   3619       os << " value=";
   3620       HeapStringAllocator allocator;
   3621       StringStream accumulator(&allocator);
   3622       cell->value()->ShortPrint(&accumulator);
   3623       os << accumulator.ToCString().get();
   3624       os << '>';
   3625       break;
   3626     }
   3627     case CALL_HANDLER_INFO_TYPE: {
   3628       CallHandlerInfo* info = CallHandlerInfo::cast(this);
   3629       os << "<CallHandlerInfo ";
   3630       os << "callback= " << Brief(info->callback());
   3631       os << ", js_callback= " << Brief(info->js_callback());
   3632       os << ", data= " << Brief(info->data());
   3633       if (info->IsSideEffectFreeCallHandlerInfo()) {
   3634         os << ", side_effect_free= true>";
   3635       } else {
   3636         os << ", side_effect_free= false>";
   3637       }
   3638       break;
   3639     }
   3640     default:
   3641       os << "<Other heap object (" << map()->instance_type() << ")>";
   3642       break;
   3643   }
   3644 }
   3645 
   3646 void Struct::BriefPrintDetails(std::ostream& os) {}
   3647 
   3648 void Tuple2::BriefPrintDetails(std::ostream& os) {
   3649   os << " " << Brief(value1()) << ", " << Brief(value2());
   3650 }
   3651 
   3652 void Tuple3::BriefPrintDetails(std::ostream& os) {
   3653   os << " " << Brief(value1()) << ", " << Brief(value2()) << ", "
   3654      << Brief(value3());
   3655 }
   3656 
   3657 void ArrayBoilerplateDescription::BriefPrintDetails(std::ostream& os) {
   3658   os << " " << elements_kind() << ", " << Brief(constant_elements());
   3659 }
   3660 
   3661 void CallableTask::BriefPrintDetails(std::ostream& os) {
   3662   os << " callable=" << Brief(callable());
   3663 }
   3664 
   3665 void HeapObject::Iterate(ObjectVisitor* v) { IterateFast<ObjectVisitor>(v); }
   3666 
   3667 
   3668 void HeapObject::IterateBody(ObjectVisitor* v) {
   3669   Map* m = map();
   3670   IterateBodyFast<ObjectVisitor>(m, SizeFromMap(m), v);
   3671 }
   3672 
   3673 void HeapObject::IterateBody(Map* map, int object_size, ObjectVisitor* v) {
   3674   IterateBodyFast<ObjectVisitor>(map, object_size, v);
   3675 }
   3676 
   3677 
   3678 struct CallIsValidSlot {
   3679   template <typename BodyDescriptor>
   3680   static bool apply(Map* map, HeapObject* obj, int offset, int) {
   3681     return BodyDescriptor::IsValidSlot(map, obj, offset);
   3682   }
   3683 };
   3684 
   3685 bool HeapObject::IsValidSlot(Map* map, int offset) {
   3686   DCHECK_NE(0, offset);
   3687   return BodyDescriptorApply<CallIsValidSlot, bool>(map->instance_type(), map,
   3688                                                     this, offset, 0);
   3689 }
   3690 
   3691 String* JSReceiver::class_name() {
   3692   ReadOnlyRoots roots = GetReadOnlyRoots();
   3693   if (IsFunction()) return roots.Function_string();
   3694   if (IsJSArgumentsObject()) return roots.Arguments_string();
   3695   if (IsJSArray()) return roots.Array_string();
   3696   if (IsJSArrayBuffer()) {
   3697     if (JSArrayBuffer::cast(this)->is_shared()) {
   3698       return roots.SharedArrayBuffer_string();
   3699     }
   3700     return roots.ArrayBuffer_string();
   3701   }
   3702   if (IsJSArrayIterator()) return roots.ArrayIterator_string();
   3703   if (IsJSDate()) return roots.Date_string();
   3704   if (IsJSError()) return roots.Error_string();
   3705   if (IsJSGeneratorObject()) return roots.Generator_string();
   3706   if (IsJSMap()) return roots.Map_string();
   3707   if (IsJSMapIterator()) return roots.MapIterator_string();
   3708   if (IsJSProxy()) {
   3709     return map()->is_callable() ? roots.Function_string()
   3710                                 : roots.Object_string();
   3711   }
   3712   if (IsJSRegExp()) return roots.RegExp_string();
   3713   if (IsJSSet()) return roots.Set_string();
   3714   if (IsJSSetIterator()) return roots.SetIterator_string();
   3715   if (IsJSTypedArray()) {
   3716 #define SWITCH_KIND(Type, type, TYPE, ctype)       \
   3717   if (map()->elements_kind() == TYPE##_ELEMENTS) { \
   3718     return roots.Type##Array_string();             \
   3719   }
   3720     TYPED_ARRAYS(SWITCH_KIND)
   3721 #undef SWITCH_KIND
   3722   }
   3723   if (IsJSValue()) {
   3724     Object* value = JSValue::cast(this)->value();
   3725     if (value->IsBoolean()) return roots.Boolean_string();
   3726     if (value->IsString()) return roots.String_string();
   3727     if (value->IsNumber()) return roots.Number_string();
   3728     if (value->IsBigInt()) return roots.BigInt_string();
   3729     if (value->IsSymbol()) return roots.Symbol_string();
   3730     if (value->IsScript()) return roots.Script_string();
   3731     UNREACHABLE();
   3732   }
   3733   if (IsJSWeakMap()) return roots.WeakMap_string();
   3734   if (IsJSWeakSet()) return roots.WeakSet_string();
   3735   if (IsJSGlobalProxy()) return roots.global_string();
   3736 
   3737   Object* maybe_constructor = map()->GetConstructor();
   3738   if (maybe_constructor->IsJSFunction()) {
   3739     JSFunction* constructor = JSFunction::cast(maybe_constructor);
   3740     if (constructor->shared()->IsApiFunction()) {
   3741       maybe_constructor = constructor->shared()->get_api_func_data();
   3742     }
   3743   }
   3744 
   3745   if (maybe_constructor->IsFunctionTemplateInfo()) {
   3746     FunctionTemplateInfo* info = FunctionTemplateInfo::cast(maybe_constructor);
   3747     if (info->class_name()->IsString()) return String::cast(info->class_name());
   3748   }
   3749 
   3750   return roots.Object_string();
   3751 }
   3752 
   3753 bool HeapObject::CanBeRehashed() const {
   3754   DCHECK(NeedsRehashing());
   3755   switch (map()->instance_type()) {
   3756     case ORDERED_HASH_MAP_TYPE:
   3757     case ORDERED_HASH_SET_TYPE:
   3758       // TODO(yangguo): actually support rehashing OrderedHash{Map,Set}.
   3759       return false;
   3760     case NAME_DICTIONARY_TYPE:
   3761     case GLOBAL_DICTIONARY_TYPE:
   3762     case NUMBER_DICTIONARY_TYPE:
   3763     case SIMPLE_NUMBER_DICTIONARY_TYPE:
   3764     case STRING_TABLE_TYPE:
   3765       return true;
   3766     case DESCRIPTOR_ARRAY_TYPE:
   3767       return true;
   3768     case TRANSITION_ARRAY_TYPE:
   3769       return true;
   3770     case SMALL_ORDERED_HASH_MAP_TYPE:
   3771       return SmallOrderedHashMap::cast(this)->NumberOfElements() == 0;
   3772     case SMALL_ORDERED_HASH_SET_TYPE:
   3773       return SmallOrderedHashMap::cast(this)->NumberOfElements() == 0;
   3774     default:
   3775       return false;
   3776   }
   3777   return false;
   3778 }
   3779 
   3780 void HeapObject::RehashBasedOnMap(Isolate* isolate) {
   3781   switch (map()->instance_type()) {
   3782     case HASH_TABLE_TYPE:
   3783       UNREACHABLE();
   3784       break;
   3785     case NAME_DICTIONARY_TYPE:
   3786       NameDictionary::cast(this)->Rehash(isolate);
   3787       break;
   3788     case GLOBAL_DICTIONARY_TYPE:
   3789       GlobalDictionary::cast(this)->Rehash(isolate);
   3790       break;
   3791     case NUMBER_DICTIONARY_TYPE:
   3792       NumberDictionary::cast(this)->Rehash(isolate);
   3793       break;
   3794     case SIMPLE_NUMBER_DICTIONARY_TYPE:
   3795       SimpleNumberDictionary::cast(this)->Rehash(isolate);
   3796       break;
   3797     case STRING_TABLE_TYPE:
   3798       StringTable::cast(this)->Rehash(isolate);
   3799       break;
   3800     case DESCRIPTOR_ARRAY_TYPE:
   3801       DCHECK_LE(1, DescriptorArray::cast(this)->number_of_descriptors());
   3802       DescriptorArray::cast(this)->Sort();
   3803       break;
   3804     case TRANSITION_ARRAY_TYPE:
   3805       TransitionArray::cast(this)->Sort();
   3806       break;
   3807     case SMALL_ORDERED_HASH_MAP_TYPE:
   3808       DCHECK_EQ(0, SmallOrderedHashMap::cast(this)->NumberOfElements());
   3809       break;
   3810     case SMALL_ORDERED_HASH_SET_TYPE:
   3811       DCHECK_EQ(0, SmallOrderedHashSet::cast(this)->NumberOfElements());
   3812       break;
   3813     default:
   3814       break;
   3815   }
   3816 }
   3817 
   3818 namespace {
   3819 std::pair<MaybeHandle<JSFunction>, Handle<String>> GetConstructorHelper(
   3820     Handle<JSReceiver> receiver) {
   3821   Isolate* isolate = receiver->GetIsolate();
   3822 
   3823   // If the object was instantiated simply with base == new.target, the
   3824   // constructor on the map provides the most accurate name.
   3825   // Don't provide the info for prototypes, since their constructors are
   3826   // reclaimed and replaced by Object in OptimizeAsPrototype.
   3827   if (!receiver->IsJSProxy() && receiver->map()->new_target_is_base() &&
   3828       !receiver->map()->is_prototype_map()) {
   3829     Object* maybe_constructor = receiver->map()->GetConstructor();
   3830     if (maybe_constructor->IsJSFunction()) {
   3831       JSFunction* constructor = JSFunction::cast(maybe_constructor);
   3832       String* name = constructor->shared()->DebugName();
   3833       if (name->length() != 0 &&
   3834           !name->Equals(ReadOnlyRoots(isolate).Object_string())) {
   3835         return std::make_pair(handle(constructor, isolate),
   3836                               handle(name, isolate));
   3837       }
   3838     } else if (maybe_constructor->IsFunctionTemplateInfo()) {
   3839       FunctionTemplateInfo* info =
   3840           FunctionTemplateInfo::cast(maybe_constructor);
   3841       if (info->class_name()->IsString()) {
   3842         return std::make_pair(
   3843             MaybeHandle<JSFunction>(),
   3844             handle(String::cast(info->class_name()), isolate));
   3845       }
   3846     }
   3847   }
   3848 
   3849   Handle<Object> maybe_tag = JSReceiver::GetDataProperty(
   3850       receiver, isolate->factory()->to_string_tag_symbol());
   3851   if (maybe_tag->IsString())
   3852     return std::make_pair(MaybeHandle<JSFunction>(),
   3853                           Handle<String>::cast(maybe_tag));
   3854 
   3855   PrototypeIterator iter(isolate, receiver);
   3856   if (iter.IsAtEnd()) {
   3857     return std::make_pair(MaybeHandle<JSFunction>(),
   3858                           handle(receiver->class_name(), isolate));
   3859   }
   3860 
   3861   Handle<JSReceiver> start = PrototypeIterator::GetCurrent<JSReceiver>(iter);
   3862   LookupIterator it(receiver, isolate->factory()->constructor_string(), start,
   3863                     LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
   3864   Handle<Object> maybe_constructor = JSReceiver::GetDataProperty(&it);
   3865   if (maybe_constructor->IsJSFunction()) {
   3866     JSFunction* constructor = JSFunction::cast(*maybe_constructor);
   3867     String* name = constructor->shared()->DebugName();
   3868 
   3869     if (name->length() != 0 &&
   3870         !name->Equals(ReadOnlyRoots(isolate).Object_string())) {
   3871       return std::make_pair(handle(constructor, isolate),
   3872                             handle(name, isolate));
   3873     }
   3874   }
   3875 
   3876   return std::make_pair(MaybeHandle<JSFunction>(),
   3877                         handle(receiver->class_name(), isolate));
   3878 }
   3879 }  // anonymous namespace
   3880 
   3881 // static
   3882 MaybeHandle<JSFunction> JSReceiver::GetConstructor(
   3883     Handle<JSReceiver> receiver) {
   3884   return GetConstructorHelper(receiver).first;
   3885 }
   3886 
   3887 // static
   3888 Handle<String> JSReceiver::GetConstructorName(Handle<JSReceiver> receiver) {
   3889   return GetConstructorHelper(receiver).second;
   3890 }
   3891 
   3892 Handle<Context> JSReceiver::GetCreationContext() {
   3893   JSReceiver* receiver = this;
   3894   // Externals are JSObjects with null as a constructor.
   3895   DCHECK(!receiver->IsExternal(GetIsolate()));
   3896   Object* constructor = receiver->map()->GetConstructor();
   3897   JSFunction* function;
   3898   if (constructor->IsJSFunction()) {
   3899     function = JSFunction::cast(constructor);
   3900   } else if (constructor->IsFunctionTemplateInfo()) {
   3901     // Remote objects don't have a creation context.
   3902     return Handle<Context>::null();
   3903   } else {
   3904     // Functions have null as a constructor,
   3905     // but any JSFunction knows its context immediately.
   3906     CHECK(receiver->IsJSFunction());
   3907     function = JSFunction::cast(receiver);
   3908   }
   3909 
   3910   return function->has_context()
   3911              ? Handle<Context>(function->context()->native_context(),
   3912                                receiver->GetIsolate())
   3913              : Handle<Context>::null();
   3914 }
   3915 
   3916 // static
   3917 MaybeObjectHandle Map::WrapFieldType(Isolate* isolate, Handle<FieldType> type) {
   3918   if (type->IsClass()) {
   3919     return MaybeObjectHandle::Weak(type->AsClass(), isolate);
   3920   }
   3921   return MaybeObjectHandle(type);
   3922 }
   3923 
   3924 // static
   3925 FieldType* Map::UnwrapFieldType(MaybeObject* wrapped_type) {
   3926   if (wrapped_type->IsClearedWeakHeapObject()) {
   3927     return FieldType::None();
   3928   }
   3929   HeapObject* heap_object;
   3930   if (wrapped_type->ToWeakHeapObject(&heap_object)) {
   3931     return FieldType::cast(heap_object);
   3932   }
   3933   return FieldType::cast(wrapped_type->ToObject());
   3934 }
   3935 
   3936 MaybeHandle<Map> Map::CopyWithField(Isolate* isolate, Handle<Map> map,
   3937                                     Handle<Name> name, Handle<FieldType> type,
   3938                                     PropertyAttributes attributes,
   3939                                     PropertyConstness constness,
   3940                                     Representation representation,
   3941                                     TransitionFlag flag) {
   3942   DCHECK(DescriptorArray::kNotFound ==
   3943          map->instance_descriptors()->Search(
   3944              *name, map->NumberOfOwnDescriptors()));
   3945 
   3946   // Ensure the descriptor array does not get too big.
   3947   if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors) {
   3948     return MaybeHandle<Map>();
   3949   }
   3950 
   3951   // Compute the new index for new field.
   3952   int index = map->NextFreePropertyIndex();
   3953 
   3954   if (map->instance_type() == JS_CONTEXT_EXTENSION_OBJECT_TYPE) {
   3955     constness = PropertyConstness::kMutable;
   3956     representation = Representation::Tagged();
   3957     type = FieldType::Any(isolate);
   3958   } else {
   3959     Map::GeneralizeIfCanHaveTransitionableFastElementsKind(
   3960         isolate, map->instance_type(), &constness, &representation, &type);
   3961   }
   3962 
   3963   MaybeObjectHandle wrapped_type = WrapFieldType(isolate, type);
   3964 
   3965   DCHECK_IMPLIES(!FLAG_track_constant_fields,
   3966                  constness == PropertyConstness::kMutable);
   3967   Descriptor d = Descriptor::DataField(name, index, attributes, constness,
   3968                                        representation, wrapped_type);
   3969   Handle<Map> new_map = Map::CopyAddDescriptor(isolate, map, &d, flag);
   3970   new_map->AccountAddedPropertyField();
   3971   return new_map;
   3972 }
   3973 
   3974 MaybeHandle<Map> Map::CopyWithConstant(Isolate* isolate, Handle<Map> map,
   3975                                        Handle<Name> name,
   3976                                        Handle<Object> constant,
   3977                                        PropertyAttributes attributes,
   3978                                        TransitionFlag flag) {
   3979   // Ensure the descriptor array does not get too big.
   3980   if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors) {
   3981     return MaybeHandle<Map>();
   3982   }
   3983 
   3984   if (FLAG_track_constant_fields) {
   3985     Representation representation = constant->OptimalRepresentation();
   3986     Handle<FieldType> type = constant->OptimalType(isolate, representation);
   3987     return CopyWithField(isolate, map, name, type, attributes,
   3988                          PropertyConstness::kConst, representation, flag);
   3989   } else {
   3990     // Allocate new instance descriptors with (name, constant) added.
   3991     Descriptor d =
   3992         Descriptor::DataConstant(isolate, name, 0, constant, attributes);
   3993     Handle<Map> new_map = Map::CopyAddDescriptor(isolate, map, &d, flag);
   3994     return new_map;
   3995   }
   3996 }
   3997 
   3998 const char* Representation::Mnemonic() const {
   3999   switch (kind_) {
   4000     case kNone: return "v";
   4001     case kTagged: return "t";
   4002     case kSmi: return "s";
   4003     case kDouble: return "d";
   4004     case kInteger32: return "i";
   4005     case kHeapObject: return "h";
   4006     case kExternal: return "x";
   4007     default:
   4008       UNREACHABLE();
   4009   }
   4010 }
   4011 
   4012 bool Map::TransitionRemovesTaggedField(Map* target) const {
   4013   int inobject = NumberOfFields();
   4014   int target_inobject = target->NumberOfFields();
   4015   for (int i = target_inobject; i < inobject; i++) {
   4016     FieldIndex index = FieldIndex::ForPropertyIndex(this, i);
   4017     if (!IsUnboxedDoubleField(index)) return true;
   4018   }
   4019   return false;
   4020 }
   4021 
   4022 bool Map::TransitionChangesTaggedFieldToUntaggedField(Map* target) const {
   4023   int inobject = NumberOfFields();
   4024   int target_inobject = target->NumberOfFields();
   4025   int limit = Min(inobject, target_inobject);
   4026   for (int i = 0; i < limit; i++) {
   4027     FieldIndex index = FieldIndex::ForPropertyIndex(target, i);
   4028     if (!IsUnboxedDoubleField(index) && target->IsUnboxedDoubleField(index)) {
   4029       return true;
   4030     }
   4031   }
   4032   return false;
   4033 }
   4034 
   4035 bool Map::TransitionRequiresSynchronizationWithGC(Map* target) const {
   4036   return TransitionRemovesTaggedField(target) ||
   4037          TransitionChangesTaggedFieldToUntaggedField(target);
   4038 }
   4039 
   4040 bool Map::InstancesNeedRewriting(Map* target) const {
   4041   int target_number_of_fields = target->NumberOfFields();
   4042   int target_inobject = target->GetInObjectProperties();
   4043   int target_unused = target->UnusedPropertyFields();
   4044   int old_number_of_fields;
   4045 
   4046   return InstancesNeedRewriting(target, target_number_of_fields,
   4047                                 target_inobject, target_unused,
   4048                                 &old_number_of_fields);
   4049 }
   4050 
   4051 bool Map::InstancesNeedRewriting(Map* target, int target_number_of_fields,
   4052                                  int target_inobject, int target_unused,
   4053                                  int* old_number_of_fields) const {
   4054   // If fields were added (or removed), rewrite the instance.
   4055   *old_number_of_fields = NumberOfFields();
   4056   DCHECK(target_number_of_fields >= *old_number_of_fields);
   4057   if (target_number_of_fields != *old_number_of_fields) return true;
   4058 
   4059   // If smi descriptors were replaced by double descriptors, rewrite.
   4060   DescriptorArray* old_desc = instance_descriptors();
   4061   DescriptorArray* new_desc = target->instance_descriptors();
   4062   int limit = NumberOfOwnDescriptors();
   4063   for (int i = 0; i < limit; i++) {
   4064     if (new_desc->GetDetails(i).representation().IsDouble() !=
   4065         old_desc->GetDetails(i).representation().IsDouble()) {
   4066       return true;
   4067     }
   4068   }
   4069 
   4070   // If no fields were added, and no inobject properties were removed, setting
   4071   // the map is sufficient.
   4072   if (target_inobject == GetInObjectProperties()) return false;
   4073   // In-object slack tracking may have reduced the object size of the new map.
   4074   // In that case, succeed if all existing fields were inobject, and they still
   4075   // fit within the new inobject size.
   4076   DCHECK(target_inobject < GetInObjectProperties());
   4077   if (target_number_of_fields <= target_inobject) {
   4078     DCHECK(target_number_of_fields + target_unused == target_inobject);
   4079     return false;
   4080   }
   4081   // Otherwise, properties will need to be moved to the backing store.
   4082   return true;
   4083 }
   4084 
   4085 
   4086 // static
   4087 void JSObject::UpdatePrototypeUserRegistration(Handle<Map> old_map,
   4088                                                Handle<Map> new_map,
   4089                                                Isolate* isolate) {
   4090   DCHECK(old_map->is_prototype_map());
   4091   DCHECK(new_map->is_prototype_map());
   4092   bool was_registered = JSObject::UnregisterPrototypeUser(old_map, isolate);
   4093   new_map->set_prototype_info(old_map->prototype_info());
   4094   old_map->set_prototype_info(Smi::kZero);
   4095   if (FLAG_trace_prototype_users) {
   4096     PrintF("Moving prototype_info %p from map %p to map %p.\n",
   4097            reinterpret_cast<void*>(new_map->prototype_info()),
   4098            reinterpret_cast<void*>(*old_map),
   4099            reinterpret_cast<void*>(*new_map));
   4100   }
   4101   if (was_registered) {
   4102     if (new_map->prototype_info()->IsPrototypeInfo()) {
   4103       // The new map isn't registered with its prototype yet; reflect this fact
   4104       // in the PrototypeInfo it just inherited from the old map.
   4105       PrototypeInfo::cast(new_map->prototype_info())
   4106           ->set_registry_slot(PrototypeInfo::UNREGISTERED);
   4107     }
   4108     JSObject::LazyRegisterPrototypeUser(new_map, isolate);
   4109   }
   4110 }
   4111 
   4112 namespace {
   4113 // To migrate a fast instance to a fast map:
   4114 // - First check whether the instance needs to be rewritten. If not, simply
   4115 //   change the map.
   4116 // - Otherwise, allocate a fixed array large enough to hold all fields, in
   4117 //   addition to unused space.
   4118 // - Copy all existing properties in, in the following order: backing store
   4119 //   properties, unused fields, inobject properties.
   4120 // - If all allocation succeeded, commit the state atomically:
   4121 //   * Copy inobject properties from the backing store back into the object.
   4122 //   * Trim the difference in instance size of the object. This also cleanly
   4123 //     frees inobject properties that moved to the backing store.
   4124 //   * If there are properties left in the backing store, trim of the space used
   4125 //     to temporarily store the inobject properties.
   4126 //   * If there are properties left in the backing store, install the backing
   4127 //     store.
   4128 void MigrateFastToFast(Handle<JSObject> object, Handle<Map> new_map) {
   4129   Isolate* isolate = object->GetIsolate();
   4130   Handle<Map> old_map(object->map(), isolate);
   4131   // In case of a regular transition.
   4132   if (new_map->GetBackPointer() == *old_map) {
   4133     // If the map does not add named properties, simply set the map.
   4134     if (old_map->NumberOfOwnDescriptors() ==
   4135         new_map->NumberOfOwnDescriptors()) {
   4136       object->synchronized_set_map(*new_map);
   4137       return;
   4138     }
   4139 
   4140     PropertyDetails details = new_map->GetLastDescriptorDetails();
   4141     int target_index = details.field_index() - new_map->GetInObjectProperties();
   4142     int property_array_length = object->property_array()->length();
   4143     bool have_space = old_map->UnusedPropertyFields() > 0 ||
   4144                       (details.location() == kField && target_index >= 0 &&
   4145                        property_array_length > target_index);
   4146     // Either new_map adds an kDescriptor property, or a kField property for
   4147     // which there is still space, and which does not require a mutable double
   4148     // box (an out-of-object double).
   4149     if (details.location() == kDescriptor ||
   4150         (have_space && ((FLAG_unbox_double_fields && target_index < 0) ||
   4151                         !details.representation().IsDouble()))) {
   4152       object->synchronized_set_map(*new_map);
   4153       return;
   4154     }
   4155 
   4156     // If there is still space in the object, we need to allocate a mutable
   4157     // double box.
   4158     if (have_space) {
   4159       FieldIndex index =
   4160           FieldIndex::ForDescriptor(*new_map, new_map->LastAdded());
   4161       DCHECK(details.representation().IsDouble());
   4162       DCHECK(!new_map->IsUnboxedDoubleField(index));
   4163       auto value = isolate->factory()->NewMutableHeapNumberWithHoleNaN();
   4164       object->RawFastPropertyAtPut(index, *value);
   4165       object->synchronized_set_map(*new_map);
   4166       return;
   4167     }
   4168 
   4169     // This migration is a transition from a map that has run out of property
   4170     // space. Extend the backing store.
   4171     int grow_by = new_map->UnusedPropertyFields() + 1;
   4172     Handle<PropertyArray> old_storage(object->property_array(), isolate);
   4173     Handle<PropertyArray> new_storage =
   4174         isolate->factory()->CopyPropertyArrayAndGrow(old_storage, grow_by);
   4175 
   4176     // Properly initialize newly added property.
   4177     Handle<Object> value;
   4178     if (details.representation().IsDouble()) {
   4179       value = isolate->factory()->NewMutableHeapNumberWithHoleNaN();
   4180     } else {
   4181       value = isolate->factory()->uninitialized_value();
   4182     }
   4183     DCHECK_EQ(kField, details.location());
   4184     DCHECK_EQ(kData, details.kind());
   4185     DCHECK_GE(target_index, 0);  // Must be a backing store index.
   4186     new_storage->set(target_index, *value);
   4187 
   4188     // From here on we cannot fail and we shouldn't GC anymore.
   4189     DisallowHeapAllocation no_allocation;
   4190 
   4191     // Set the new property value and do the map transition.
   4192     object->SetProperties(*new_storage);
   4193     object->synchronized_set_map(*new_map);
   4194     return;
   4195   }
   4196 
   4197   int old_number_of_fields;
   4198   int number_of_fields = new_map->NumberOfFields();
   4199   int inobject = new_map->GetInObjectProperties();
   4200   int unused = new_map->UnusedPropertyFields();
   4201 
   4202   // Nothing to do if no functions were converted to fields and no smis were
   4203   // converted to doubles.
   4204   if (!old_map->InstancesNeedRewriting(*new_map, number_of_fields, inobject,
   4205                                        unused, &old_number_of_fields)) {
   4206     object->synchronized_set_map(*new_map);
   4207     return;
   4208   }
   4209 
   4210   int total_size = number_of_fields + unused;
   4211   int external = total_size - inobject;
   4212   Handle<PropertyArray> array = isolate->factory()->NewPropertyArray(external);
   4213 
   4214   // We use this array to temporarily store the inobject properties.
   4215   Handle<FixedArray> inobject_props =
   4216       isolate->factory()->NewFixedArray(inobject);
   4217 
   4218   Handle<DescriptorArray> old_descriptors(old_map->instance_descriptors(),
   4219                                           isolate);
   4220   Handle<DescriptorArray> new_descriptors(new_map->instance_descriptors(),
   4221                                           isolate);
   4222   int old_nof = old_map->NumberOfOwnDescriptors();
   4223   int new_nof = new_map->NumberOfOwnDescriptors();
   4224 
   4225   // This method only supports generalizing instances to at least the same
   4226   // number of properties.
   4227   DCHECK(old_nof <= new_nof);
   4228 
   4229   for (int i = 0; i < old_nof; i++) {
   4230     PropertyDetails details = new_descriptors->GetDetails(i);
   4231     if (details.location() != kField) continue;
   4232     DCHECK_EQ(kData, details.kind());
   4233     PropertyDetails old_details = old_descriptors->GetDetails(i);
   4234     Representation old_representation = old_details.representation();
   4235     Representation representation = details.representation();
   4236     Handle<Object> value;
   4237     if (old_details.location() == kDescriptor) {
   4238       if (old_details.kind() == kAccessor) {
   4239         // In case of kAccessor -> kData property reconfiguration, the property
   4240         // must already be prepared for data of certain type.
   4241         DCHECK(!details.representation().IsNone());
   4242         if (details.representation().IsDouble()) {
   4243           value = isolate->factory()->NewMutableHeapNumberWithHoleNaN();
   4244         } else {
   4245           value = isolate->factory()->uninitialized_value();
   4246         }
   4247       } else {
   4248         DCHECK_EQ(kData, old_details.kind());
   4249         value = handle(old_descriptors->GetStrongValue(i), isolate);
   4250         DCHECK(!old_representation.IsDouble() && !representation.IsDouble());
   4251       }
   4252     } else {
   4253       DCHECK_EQ(kField, old_details.location());
   4254       FieldIndex index = FieldIndex::ForDescriptor(*old_map, i);
   4255       if (object->IsUnboxedDoubleField(index)) {
   4256         uint64_t old_bits = object->RawFastDoublePropertyAsBitsAt(index);
   4257         if (representation.IsDouble()) {
   4258           value = isolate->factory()->NewMutableHeapNumberFromBits(old_bits);
   4259         } else {
   4260           value = isolate->factory()->NewHeapNumberFromBits(old_bits);
   4261         }
   4262       } else {
   4263         value = handle(object->RawFastPropertyAt(index), isolate);
   4264         if (!old_representation.IsDouble() && representation.IsDouble()) {
   4265           DCHECK_IMPLIES(old_representation.IsNone(),
   4266                          value->IsUninitialized(isolate));
   4267           value = Object::NewStorageFor(isolate, value, representation);
   4268         } else if (old_representation.IsDouble() &&
   4269                    !representation.IsDouble()) {
   4270           value = Object::WrapForRead(isolate, value, old_representation);
   4271         }
   4272       }
   4273     }
   4274     DCHECK(!(representation.IsDouble() && value->IsSmi()));
   4275     int target_index = new_descriptors->GetFieldIndex(i);
   4276     if (target_index < inobject) {
   4277       inobject_props->set(target_index, *value);
   4278     } else {
   4279       array->set(target_index - inobject, *value);
   4280     }
   4281   }
   4282 
   4283   for (int i = old_nof; i < new_nof; i++) {
   4284     PropertyDetails details = new_descriptors->GetDetails(i);
   4285     if (details.location() != kField) continue;
   4286     DCHECK_EQ(kData, details.kind());
   4287     Handle<Object> value;
   4288     if (details.representation().IsDouble()) {
   4289       value = isolate->factory()->NewMutableHeapNumberWithHoleNaN();
   4290     } else {
   4291       value = isolate->factory()->uninitialized_value();
   4292     }
   4293     int target_index = new_descriptors->GetFieldIndex(i);
   4294     if (target_index < inobject) {
   4295       inobject_props->set(target_index, *value);
   4296     } else {
   4297       array->set(target_index - inobject, *value);
   4298     }
   4299   }
   4300 
   4301   // From here on we cannot fail and we shouldn't GC anymore.
   4302   DisallowHeapAllocation no_allocation;
   4303 
   4304   Heap* heap = isolate->heap();
   4305 
   4306   int old_instance_size = old_map->instance_size();
   4307 
   4308   heap->NotifyObjectLayoutChange(*object, old_instance_size, no_allocation);
   4309 
   4310   // Copy (real) inobject properties. If necessary, stop at number_of_fields to
   4311   // avoid overwriting |one_pointer_filler_map|.
   4312   int limit = Min(inobject, number_of_fields);
   4313   for (int i = 0; i < limit; i++) {
   4314     FieldIndex index = FieldIndex::ForPropertyIndex(*new_map, i);
   4315     Object* value = inobject_props->get(i);
   4316     // Can't use JSObject::FastPropertyAtPut() because proper map was not set
   4317     // yet.
   4318     if (new_map->IsUnboxedDoubleField(index)) {
   4319       DCHECK(value->IsMutableHeapNumber());
   4320       // Ensure that all bits of the double value are preserved.
   4321       object->RawFastDoublePropertyAsBitsAtPut(
   4322           index, MutableHeapNumber::cast(value)->value_as_bits());
   4323       if (i < old_number_of_fields && !old_map->IsUnboxedDoubleField(index)) {
   4324         // Transition from tagged to untagged slot.
   4325         heap->ClearRecordedSlot(*object,
   4326                                 HeapObject::RawField(*object, index.offset()));
   4327       } else {
   4328         DCHECK(!heap->HasRecordedSlot(
   4329             *object, HeapObject::RawField(*object, index.offset())));
   4330       }
   4331     } else {
   4332       object->RawFastPropertyAtPut(index, value);
   4333     }
   4334   }
   4335 
   4336   object->SetProperties(*array);
   4337 
   4338   // Create filler object past the new instance size.
   4339   int new_instance_size = new_map->instance_size();
   4340   int instance_size_delta = old_instance_size - new_instance_size;
   4341   DCHECK_GE(instance_size_delta, 0);
   4342 
   4343   if (instance_size_delta > 0) {
   4344     Address address = object->address();
   4345     heap->CreateFillerObjectAt(address + new_instance_size, instance_size_delta,
   4346                                ClearRecordedSlots::kYes);
   4347   }
   4348 
   4349   // We are storing the new map using release store after creating a filler for
   4350   // the left-over space to avoid races with the sweeper thread.
   4351   object->synchronized_set_map(*new_map);
   4352 }
   4353 
   4354 void MigrateFastToSlow(Handle<JSObject> object, Handle<Map> new_map,
   4355                        int expected_additional_properties) {
   4356   // The global object is always normalized.
   4357   DCHECK(!object->IsJSGlobalObject());
   4358   // JSGlobalProxy must never be normalized
   4359   DCHECK(!object->IsJSGlobalProxy());
   4360 
   4361   DCHECK_IMPLIES(new_map->is_prototype_map(),
   4362                  Map::IsPrototypeChainInvalidated(*new_map));
   4363 
   4364   Isolate* isolate = object->GetIsolate();
   4365   HandleScope scope(isolate);
   4366   Handle<Map> map(object->map(), isolate);
   4367 
   4368   // Allocate new content.
   4369   int real_size = map->NumberOfOwnDescriptors();
   4370   int property_count = real_size;
   4371   if (expected_additional_properties > 0) {
   4372     property_count += expected_additional_properties;
   4373   } else {
   4374     // Make space for two more properties.
   4375     property_count += NameDictionary::kInitialCapacity;
   4376   }
   4377   Handle<NameDictionary> dictionary =
   4378       NameDictionary::New(isolate, property_count);
   4379 
   4380   Handle<DescriptorArray> descs(map->instance_descriptors(), isolate);
   4381   for (int i = 0; i < real_size; i++) {
   4382     PropertyDetails details = descs->GetDetails(i);
   4383     Handle<Name> key(descs->GetKey(i), isolate);
   4384     Handle<Object> value;
   4385     if (details.location() == kField) {
   4386       FieldIndex index = FieldIndex::ForDescriptor(*map, i);
   4387       if (details.kind() == kData) {
   4388         if (object->IsUnboxedDoubleField(index)) {
   4389           double old_value = object->RawFastDoublePropertyAt(index);
   4390           value = isolate->factory()->NewHeapNumber(old_value);
   4391         } else {
   4392           value = handle(object->RawFastPropertyAt(index), isolate);
   4393           if (details.representation().IsDouble()) {
   4394             DCHECK(value->IsMutableHeapNumber());
   4395             double old_value = Handle<MutableHeapNumber>::cast(value)->value();
   4396             value = isolate->factory()->NewHeapNumber(old_value);
   4397           }
   4398         }
   4399       } else {
   4400         DCHECK_EQ(kAccessor, details.kind());
   4401         value = handle(object->RawFastPropertyAt(index), isolate);
   4402       }
   4403 
   4404     } else {
   4405       DCHECK_EQ(kDescriptor, details.location());
   4406       value = handle(descs->GetStrongValue(i), isolate);
   4407     }
   4408     DCHECK(!value.is_null());
   4409     PropertyDetails d(details.kind(), details.attributes(),
   4410                       PropertyCellType::kNoCell);
   4411     dictionary = NameDictionary::Add(isolate, dictionary, key, value, d);
   4412   }
   4413 
   4414   // Copy the next enumeration index from instance descriptor.
   4415   dictionary->SetNextEnumerationIndex(real_size + 1);
   4416 
   4417   // From here on we cannot fail and we shouldn't GC anymore.
   4418   DisallowHeapAllocation no_allocation;
   4419 
   4420   Heap* heap = isolate->heap();
   4421   int old_instance_size = map->instance_size();
   4422   heap->NotifyObjectLayoutChange(*object, old_instance_size, no_allocation);
   4423 
   4424   // Resize the object in the heap if necessary.
   4425   int new_instance_size = new_map->instance_size();
   4426   int instance_size_delta = old_instance_size - new_instance_size;
   4427   DCHECK_GE(instance_size_delta, 0);
   4428 
   4429   if (instance_size_delta > 0) {
   4430     heap->CreateFillerObjectAt(object->address() + new_instance_size,
   4431                                instance_size_delta, ClearRecordedSlots::kYes);
   4432   }
   4433 
   4434   // We are storing the new map using release store after creating a filler for
   4435   // the left-over space to avoid races with the sweeper thread.
   4436   object->synchronized_set_map(*new_map);
   4437 
   4438   object->SetProperties(*dictionary);
   4439 
   4440   // Ensure that in-object space of slow-mode object does not contain random
   4441   // garbage.
   4442   int inobject_properties = new_map->GetInObjectProperties();
   4443   if (inobject_properties) {
   4444     Heap* heap = isolate->heap();
   4445     heap->ClearRecordedSlotRange(
   4446         object->address() + map->GetInObjectPropertyOffset(0),
   4447         object->address() + new_instance_size);
   4448 
   4449     for (int i = 0; i < inobject_properties; i++) {
   4450       FieldIndex index = FieldIndex::ForPropertyIndex(*new_map, i);
   4451       object->RawFastPropertyAtPut(index, Smi::kZero);
   4452     }
   4453   }
   4454 
   4455   isolate->counters()->props_to_dictionary()->Increment();
   4456 
   4457 #ifdef DEBUG
   4458   if (FLAG_trace_normalization) {
   4459     StdoutStream os;
   4460     os << "Object properties have been normalized:\n";
   4461     object->Print(os);
   4462   }
   4463 #endif
   4464 }
   4465 
   4466 }  // namespace
   4467 
   4468 // static
   4469 void JSObject::NotifyMapChange(Handle<Map> old_map, Handle<Map> new_map,
   4470                                Isolate* isolate) {
   4471   if (!old_map->is_prototype_map()) return;
   4472 
   4473   InvalidatePrototypeChains(*old_map);
   4474 
   4475   // If the map was registered with its prototype before, ensure that it
   4476   // registers with its new prototype now. This preserves the invariant that
   4477   // when a map on a prototype chain is registered with its prototype, then
   4478   // all prototypes further up the chain are also registered with their
   4479   // respective prototypes.
   4480   UpdatePrototypeUserRegistration(old_map, new_map, isolate);
   4481 }
   4482 
   4483 void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map,
   4484                             int expected_additional_properties) {
   4485   if (object->map() == *new_map) return;
   4486   Handle<Map> old_map(object->map(), object->GetIsolate());
   4487   NotifyMapChange(old_map, new_map, object->GetIsolate());
   4488 
   4489   if (old_map->is_dictionary_map()) {
   4490     // For slow-to-fast migrations JSObject::MigrateSlowToFast()
   4491     // must be used instead.
   4492     CHECK(new_map->is_dictionary_map());
   4493 
   4494     // Slow-to-slow migration is trivial.
   4495     object->synchronized_set_map(*new_map);
   4496   } else if (!new_map->is_dictionary_map()) {
   4497     MigrateFastToFast(object, new_map);
   4498     if (old_map->is_prototype_map()) {
   4499       DCHECK(!old_map->is_stable());
   4500       DCHECK(new_map->is_stable());
   4501       DCHECK(new_map->owns_descriptors());
   4502       DCHECK(old_map->owns_descriptors());
   4503       // Transfer ownership to the new map. Keep the descriptor pointer of the
   4504       // old map intact because the concurrent marker might be iterating the
   4505       // object with the old map.
   4506       old_map->set_owns_descriptors(false);
   4507       DCHECK(old_map->is_abandoned_prototype_map());
   4508       // Ensure that no transition was inserted for prototype migrations.
   4509       DCHECK_EQ(0, TransitionsAccessor(object->GetIsolate(), old_map)
   4510                        .NumberOfTransitions());
   4511       DCHECK(new_map->GetBackPointer()->IsUndefined());
   4512       DCHECK(object->map() != *old_map);
   4513     }
   4514   } else {
   4515     MigrateFastToSlow(object, new_map, expected_additional_properties);
   4516   }
   4517 
   4518   // Careful: Don't allocate here!
   4519   // For some callers of this method, |object| might be in an inconsistent
   4520   // state now: the new map might have a new elements_kind, but the object's
   4521   // elements pointer hasn't been updated yet. Callers will fix this, but in
   4522   // the meantime, (indirectly) calling JSObjectVerify() must be avoided.
   4523   // When adding code here, add a DisallowHeapAllocation too.
   4524 }
   4525 
   4526 void JSObject::ForceSetPrototype(Handle<JSObject> object,
   4527                                  Handle<Object> proto) {
   4528   // object.__proto__ = proto;
   4529   Handle<Map> old_map = Handle<Map>(object->map(), object->GetIsolate());
   4530   Handle<Map> new_map =
   4531       Map::Copy(object->GetIsolate(), old_map, "ForceSetPrototype");
   4532   Map::SetPrototype(object->GetIsolate(), new_map, proto);
   4533   JSObject::MigrateToMap(object, new_map);
   4534 }
   4535 
   4536 int Map::NumberOfFields() const {
   4537   DescriptorArray* descriptors = instance_descriptors();
   4538   int result = 0;
   4539   for (int i = 0; i < NumberOfOwnDescriptors(); i++) {
   4540     if (descriptors->GetDetails(i).location() == kField) result++;
   4541   }
   4542   return result;
   4543 }
   4544 
   4545 bool Map::HasOutOfObjectProperties() const {
   4546   return GetInObjectProperties() < NumberOfFields();
   4547 }
   4548 
   4549 void DescriptorArray::GeneralizeAllFields() {
   4550   int length = number_of_descriptors();
   4551   for (int i = 0; i < length; i++) {
   4552     PropertyDetails details = GetDetails(i);
   4553     details = details.CopyWithRepresentation(Representation::Tagged());
   4554     if (details.location() == kField) {
   4555       DCHECK_EQ(kData, details.kind());
   4556       details = details.CopyWithConstness(PropertyConstness::kMutable);
   4557       SetValue(i, FieldType::Any());
   4558     }
   4559     set(ToDetailsIndex(i), MaybeObject::FromObject(details.AsSmi()));
   4560   }
   4561 }
   4562 
   4563 Handle<Map> Map::CopyGeneralizeAllFields(Isolate* isolate, Handle<Map> map,
   4564                                          ElementsKind elements_kind,
   4565                                          int modify_index, PropertyKind kind,
   4566                                          PropertyAttributes attributes,
   4567                                          const char* reason) {
   4568   Handle<DescriptorArray> old_descriptors(map->instance_descriptors(), isolate);
   4569   int number_of_own_descriptors = map->NumberOfOwnDescriptors();
   4570   Handle<DescriptorArray> descriptors = DescriptorArray::CopyUpTo(
   4571       isolate, old_descriptors, number_of_own_descriptors);
   4572   descriptors->GeneralizeAllFields();
   4573 
   4574   Handle<LayoutDescriptor> new_layout_descriptor(
   4575       LayoutDescriptor::FastPointerLayout(), isolate);
   4576   Handle<Map> new_map = CopyReplaceDescriptors(
   4577       isolate, map, descriptors, new_layout_descriptor, OMIT_TRANSITION,
   4578       MaybeHandle<Name>(), reason, SPECIAL_TRANSITION);
   4579 
   4580   // Unless the instance is being migrated, ensure that modify_index is a field.
   4581   if (modify_index >= 0) {
   4582     PropertyDetails details = descriptors->GetDetails(modify_index);
   4583     if (details.constness() != PropertyConstness::kMutable ||
   4584         details.location() != kField || details.attributes() != attributes) {
   4585       int field_index = details.location() == kField
   4586                             ? details.field_index()
   4587                             : new_map->NumberOfFields();
   4588       Descriptor d = Descriptor::DataField(
   4589           isolate, handle(descriptors->GetKey(modify_index), isolate),
   4590           field_index, attributes, Representation::Tagged());
   4591       descriptors->Replace(modify_index, &d);
   4592       if (details.location() != kField) {
   4593         new_map->AccountAddedPropertyField();
   4594       }
   4595     } else {
   4596       DCHECK(details.attributes() == attributes);
   4597     }
   4598 
   4599     if (FLAG_trace_generalization) {
   4600       MaybeHandle<FieldType> field_type = FieldType::None(isolate);
   4601       if (details.location() == kField) {
   4602         field_type = handle(
   4603             map->instance_descriptors()->GetFieldType(modify_index), isolate);
   4604       }
   4605       map->PrintGeneralization(
   4606           isolate, stdout, reason, modify_index,
   4607           new_map->NumberOfOwnDescriptors(), new_map->NumberOfOwnDescriptors(),
   4608           details.location() == kDescriptor, details.representation(),
   4609           Representation::Tagged(), field_type, MaybeHandle<Object>(),
   4610           FieldType::Any(isolate), MaybeHandle<Object>());
   4611     }
   4612   }
   4613   new_map->set_elements_kind(elements_kind);
   4614   return new_map;
   4615 }
   4616 
   4617 void Map::DeprecateTransitionTree(Isolate* isolate) {
   4618   if (is_deprecated()) return;
   4619   DisallowHeapAllocation no_gc;
   4620   TransitionsAccessor transitions(isolate, this, &no_gc);
   4621   int num_transitions = transitions.NumberOfTransitions();
   4622   for (int i = 0; i < num_transitions; ++i) {
   4623     transitions.GetTarget(i)->DeprecateTransitionTree(isolate);
   4624   }
   4625   DCHECK(!constructor_or_backpointer()->IsFunctionTemplateInfo());
   4626   set_is_deprecated(true);
   4627   if (FLAG_trace_maps) {
   4628     LOG(isolate, MapEvent("Deprecate", this, nullptr));
   4629   }
   4630   dependent_code()->DeoptimizeDependentCodeGroup(
   4631       isolate, DependentCode::kTransitionGroup);
   4632   NotifyLeafMapLayoutChange(isolate);
   4633 }
   4634 
   4635 
   4636 // Installs |new_descriptors| over the current instance_descriptors to ensure
   4637 // proper sharing of descriptor arrays.
   4638 void Map::ReplaceDescriptors(Isolate* isolate, DescriptorArray* new_descriptors,
   4639                              LayoutDescriptor* new_layout_descriptor) {
   4640   // Don't overwrite the empty descriptor array or initial map's descriptors.
   4641   if (NumberOfOwnDescriptors() == 0 || GetBackPointer()->IsUndefined(isolate)) {
   4642     return;
   4643   }
   4644 
   4645   DescriptorArray* to_replace = instance_descriptors();
   4646   // Replace descriptors by new_descriptors in all maps that share it. The old
   4647   // descriptors will not be trimmed in the mark-compactor, we need to mark
   4648   // all its elements.
   4649   MarkingBarrierForElements(isolate->heap(), to_replace);
   4650   Map* current = this;
   4651   while (current->instance_descriptors() == to_replace) {
   4652     Object* next = current->GetBackPointer();
   4653     if (next->IsUndefined(isolate)) break;  // Stop overwriting at initial map.
   4654     current->SetEnumLength(kInvalidEnumCacheSentinel);
   4655     current->UpdateDescriptors(new_descriptors, new_layout_descriptor);
   4656     current = Map::cast(next);
   4657   }
   4658   set_owns_descriptors(false);
   4659 }
   4660 
   4661 Map* Map::FindRootMap(Isolate* isolate) const {
   4662   const Map* result = this;
   4663   while (true) {
   4664     Object* back = result->GetBackPointer();
   4665     if (back->IsUndefined(isolate)) {
   4666       // Initial map always owns descriptors and doesn't have unused entries
   4667       // in the descriptor array.
   4668       DCHECK(result->owns_descriptors());
   4669       DCHECK_EQ(result->NumberOfOwnDescriptors(),
   4670                 result->instance_descriptors()->number_of_descriptors());
   4671       return const_cast<Map*>(result);
   4672     }
   4673     result = Map::cast(back);
   4674   }
   4675 }
   4676 
   4677 Map* Map::FindFieldOwner(Isolate* isolate, int descriptor) const {
   4678   DisallowHeapAllocation no_allocation;
   4679   DCHECK_EQ(kField, instance_descriptors()->GetDetails(descriptor).location());
   4680   const Map* result = this;
   4681   while (true) {
   4682     Object* back = result->GetBackPointer();
   4683     if (back->IsUndefined(isolate)) break;
   4684     const Map* parent = Map::cast(back);
   4685     if (parent->NumberOfOwnDescriptors() <= descriptor) break;
   4686     result = parent;
   4687   }
   4688   return const_cast<Map*>(result);
   4689 }
   4690 
   4691 void Map::UpdateFieldType(Isolate* isolate, int descriptor, Handle<Name> name,
   4692                           PropertyConstness new_constness,
   4693                           Representation new_representation,
   4694                           MaybeObjectHandle new_wrapped_type) {
   4695   DCHECK(new_wrapped_type->IsSmi() || new_wrapped_type->IsWeakHeapObject());
   4696   // We store raw pointers in the queue, so no allocations are allowed.
   4697   DisallowHeapAllocation no_allocation;
   4698   PropertyDetails details = instance_descriptors()->GetDetails(descriptor);
   4699   if (details.location() != kField) return;
   4700   DCHECK_EQ(kData, details.kind());
   4701 
   4702   Zone zone(isolate->allocator(), ZONE_NAME);
   4703   ZoneQueue<Map*> backlog(&zone);
   4704   backlog.push(this);
   4705 
   4706   while (!backlog.empty()) {
   4707     Map* current = backlog.front();
   4708     backlog.pop();
   4709 
   4710     TransitionsAccessor transitions(isolate, current, &no_allocation);
   4711     int num_transitions = transitions.NumberOfTransitions();
   4712     for (int i = 0; i < num_transitions; ++i) {
   4713       Map* target = transitions.GetTarget(i);
   4714       backlog.push(target);
   4715     }
   4716     DescriptorArray* descriptors = current->instance_descriptors();
   4717     PropertyDetails details = descriptors->GetDetails(descriptor);
   4718 
   4719     // Currently constness change implies map change.
   4720     DCHECK_IMPLIES(new_constness != details.constness(),
   4721                    FLAG_modify_map_inplace);
   4722 
   4723     // It is allowed to change representation here only from None to something.
   4724     DCHECK(details.representation().Equals(new_representation) ||
   4725            details.representation().IsNone());
   4726 
   4727     // Skip if already updated the shared descriptor.
   4728     if ((FLAG_modify_map_inplace && new_constness != details.constness()) ||
   4729         descriptors->GetFieldType(descriptor) != *new_wrapped_type.object()) {
   4730       DCHECK_IMPLIES(!FLAG_track_constant_fields,
   4731                      new_constness == PropertyConstness::kMutable);
   4732       Descriptor d = Descriptor::DataField(
   4733           name, descriptors->GetFieldIndex(descriptor), details.attributes(),
   4734           new_constness, new_representation, new_wrapped_type);
   4735       descriptors->Replace(descriptor, &d);
   4736     }
   4737   }
   4738 }
   4739 
   4740 bool FieldTypeIsCleared(Representation rep, FieldType* type) {
   4741   return type->IsNone() && rep.IsHeapObject();
   4742 }
   4743 
   4744 
   4745 // static
   4746 Handle<FieldType> Map::GeneralizeFieldType(Representation rep1,
   4747                                            Handle<FieldType> type1,
   4748                                            Representation rep2,
   4749                                            Handle<FieldType> type2,
   4750                                            Isolate* isolate) {
   4751   // Cleared field types need special treatment. They represent lost knowledge,
   4752   // so we must be conservative, so their generalization with any other type
   4753   // is "Any".
   4754   if (FieldTypeIsCleared(rep1, *type1) || FieldTypeIsCleared(rep2, *type2)) {
   4755     return FieldType::Any(isolate);
   4756   }
   4757   if (type1->NowIs(type2)) return type2;
   4758   if (type2->NowIs(type1)) return type1;
   4759   return FieldType::Any(isolate);
   4760 }
   4761 
   4762 // static
   4763 void Map::GeneralizeField(Isolate* isolate, Handle<Map> map, int modify_index,
   4764                           PropertyConstness new_constness,
   4765                           Representation new_representation,
   4766                           Handle<FieldType> new_field_type) {
   4767   // Check if we actually need to generalize the field type at all.
   4768   Handle<DescriptorArray> old_descriptors(map->instance_descriptors(), isolate);
   4769   PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
   4770   PropertyConstness old_constness = old_details.constness();
   4771   Representation old_representation = old_details.representation();
   4772   Handle<FieldType> old_field_type(old_descriptors->GetFieldType(modify_index),
   4773                                    isolate);
   4774 
   4775   // Return if the current map is general enough to hold requested constness and
   4776   // representation/field type.
   4777   if (((FLAG_modify_map_inplace &&
   4778         IsGeneralizableTo(new_constness, old_constness)) ||
   4779        (!FLAG_modify_map_inplace && (old_constness == new_constness))) &&
   4780       old_representation.Equals(new_representation) &&
   4781       !FieldTypeIsCleared(new_representation, *new_field_type) &&
   4782       // Checking old_field_type for being cleared is not necessary because
   4783       // the NowIs check below would fail anyway in that case.
   4784       new_field_type->NowIs(old_field_type)) {
   4785     DCHECK(GeneralizeFieldType(old_representation, old_field_type,
   4786                                new_representation, new_field_type, isolate)
   4787                ->NowIs(old_field_type));
   4788     return;
   4789   }
   4790 
   4791   // Determine the field owner.
   4792   Handle<Map> field_owner(map->FindFieldOwner(isolate, modify_index), isolate);
   4793   Handle<DescriptorArray> descriptors(field_owner->instance_descriptors(),
   4794                                       isolate);
   4795   DCHECK_EQ(*old_field_type, descriptors->GetFieldType(modify_index));
   4796 
   4797   new_field_type =
   4798       Map::GeneralizeFieldType(old_representation, old_field_type,
   4799                                new_representation, new_field_type, isolate);
   4800   if (FLAG_modify_map_inplace) {
   4801     new_constness = GeneralizeConstness(old_constness, new_constness);
   4802   }
   4803 
   4804   PropertyDetails details = descriptors->GetDetails(modify_index);
   4805   Handle<Name> name(descriptors->GetKey(modify_index), isolate);
   4806 
   4807   MaybeObjectHandle wrapped_type(WrapFieldType(isolate, new_field_type));
   4808   field_owner->UpdateFieldType(isolate, modify_index, name, new_constness,
   4809                                new_representation, wrapped_type);
   4810   field_owner->dependent_code()->DeoptimizeDependentCodeGroup(
   4811       isolate, DependentCode::kFieldOwnerGroup);
   4812 
   4813   if (FLAG_trace_generalization) {
   4814     map->PrintGeneralization(
   4815         isolate, stdout, "field type generalization", modify_index,
   4816         map->NumberOfOwnDescriptors(), map->NumberOfOwnDescriptors(), false,
   4817         details.representation(), details.representation(), old_field_type,
   4818         MaybeHandle<Object>(), new_field_type, MaybeHandle<Object>());
   4819   }
   4820 }
   4821 
   4822 // TODO(ishell): remove.
   4823 // static
   4824 Handle<Map> Map::ReconfigureProperty(Isolate* isolate, Handle<Map> map,
   4825                                      int modify_index, PropertyKind new_kind,
   4826                                      PropertyAttributes new_attributes,
   4827                                      Representation new_representation,
   4828                                      Handle<FieldType> new_field_type) {
   4829   DCHECK_EQ(kData, new_kind);  // Only kData case is supported.
   4830   MapUpdater mu(isolate, map);
   4831   return mu.ReconfigureToDataField(modify_index, new_attributes,
   4832                                    PropertyConstness::kConst,
   4833                                    new_representation, new_field_type);
   4834 }
   4835 
   4836 // TODO(ishell): remove.
   4837 // static
   4838 Handle<Map> Map::ReconfigureElementsKind(Isolate* isolate, Handle<Map> map,
   4839                                          ElementsKind new_elements_kind) {
   4840   MapUpdater mu(isolate, map);
   4841   return mu.ReconfigureElementsKind(new_elements_kind);
   4842 }
   4843 
   4844 // Generalize all fields and update the transition tree.
   4845 Handle<Map> Map::GeneralizeAllFields(Isolate* isolate, Handle<Map> map) {
   4846   Handle<FieldType> any_type = FieldType::Any(isolate);
   4847 
   4848   Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate);
   4849   for (int i = 0; i < map->NumberOfOwnDescriptors(); ++i) {
   4850     PropertyDetails details = descriptors->GetDetails(i);
   4851     if (details.location() == kField) {
   4852       DCHECK_EQ(kData, details.kind());
   4853       MapUpdater mu(isolate, map);
   4854       map = mu.ReconfigureToDataField(i, details.attributes(),
   4855                                       PropertyConstness::kMutable,
   4856                                       Representation::Tagged(), any_type);
   4857     }
   4858   }
   4859   return map;
   4860 }
   4861 
   4862 
   4863 // static
   4864 MaybeHandle<Map> Map::TryUpdate(Isolate* isolate, Handle<Map> old_map) {
   4865   DisallowHeapAllocation no_allocation;
   4866   DisallowDeoptimization no_deoptimization(isolate);
   4867 
   4868   if (!old_map->is_deprecated()) return old_map;
   4869 
   4870   // Check the state of the root map.
   4871   Map* root_map = old_map->FindRootMap(isolate);
   4872   if (root_map->is_deprecated()) {
   4873     JSFunction* constructor = JSFunction::cast(root_map->GetConstructor());
   4874     DCHECK(constructor->has_initial_map());
   4875     DCHECK(constructor->initial_map()->is_dictionary_map());
   4876     if (constructor->initial_map()->elements_kind() !=
   4877         old_map->elements_kind()) {
   4878       return MaybeHandle<Map>();
   4879     }
   4880     return handle(constructor->initial_map(), constructor->GetIsolate());
   4881   }
   4882   if (!old_map->EquivalentToForTransition(root_map)) return MaybeHandle<Map>();
   4883 
   4884   ElementsKind from_kind = root_map->elements_kind();
   4885   ElementsKind to_kind = old_map->elements_kind();
   4886   if (from_kind != to_kind) {
   4887     // Try to follow existing elements kind transitions.
   4888     root_map = root_map->LookupElementsTransitionMap(isolate, to_kind);
   4889     if (root_map == nullptr) return MaybeHandle<Map>();
   4890     // From here on, use the map with correct elements kind as root map.
   4891   }
   4892   Map* new_map = root_map->TryReplayPropertyTransitions(isolate, *old_map);
   4893   if (new_map == nullptr) return MaybeHandle<Map>();
   4894   return handle(new_map, isolate);
   4895 }
   4896 
   4897 Map* Map::TryReplayPropertyTransitions(Isolate* isolate, Map* old_map) {
   4898   DisallowHeapAllocation no_allocation;
   4899   DisallowDeoptimization no_deoptimization(isolate);
   4900 
   4901   int root_nof = NumberOfOwnDescriptors();
   4902 
   4903   int old_nof = old_map->NumberOfOwnDescriptors();
   4904   DescriptorArray* old_descriptors = old_map->instance_descriptors();
   4905 
   4906   Map* new_map = this;
   4907   for (int i = root_nof; i < old_nof; ++i) {
   4908     PropertyDetails old_details = old_descriptors->GetDetails(i);
   4909     Map* transition =
   4910         TransitionsAccessor(isolate, new_map, &no_allocation)
   4911             .SearchTransition(old_descriptors->GetKey(i), old_details.kind(),
   4912                               old_details.attributes());
   4913     if (transition == nullptr) return nullptr;
   4914     new_map = transition;
   4915     DescriptorArray* new_descriptors = new_map->instance_descriptors();
   4916 
   4917     PropertyDetails new_details = new_descriptors->GetDetails(i);
   4918     DCHECK_EQ(old_details.kind(), new_details.kind());
   4919     DCHECK_EQ(old_details.attributes(), new_details.attributes());
   4920     if (!IsGeneralizableTo(old_details.constness(), new_details.constness())) {
   4921       return nullptr;
   4922     }
   4923     DCHECK(IsGeneralizableTo(old_details.location(), new_details.location()));
   4924     if (!old_details.representation().fits_into(new_details.representation())) {
   4925       return nullptr;
   4926     }
   4927     if (new_details.location() == kField) {
   4928       if (new_details.kind() == kData) {
   4929         FieldType* new_type = new_descriptors->GetFieldType(i);
   4930         // Cleared field types need special treatment. They represent lost
   4931         // knowledge, so we must first generalize the new_type to "Any".
   4932         if (FieldTypeIsCleared(new_details.representation(), new_type)) {
   4933           return nullptr;
   4934         }
   4935         DCHECK_EQ(kData, old_details.kind());
   4936         if (old_details.location() == kField) {
   4937           FieldType* old_type = old_descriptors->GetFieldType(i);
   4938           if (FieldTypeIsCleared(old_details.representation(), old_type) ||
   4939               !old_type->NowIs(new_type)) {
   4940             return nullptr;
   4941           }
   4942         } else {
   4943           DCHECK_EQ(kDescriptor, old_details.location());
   4944           DCHECK(!FLAG_track_constant_fields);
   4945           Object* old_value = old_descriptors->GetStrongValue(i);
   4946           if (!new_type->NowContains(old_value)) {
   4947             return nullptr;
   4948           }
   4949         }
   4950 
   4951       } else {
   4952         DCHECK_EQ(kAccessor, new_details.kind());
   4953 #ifdef DEBUG
   4954         FieldType* new_type = new_descriptors->GetFieldType(i);
   4955         DCHECK(new_type->IsAny());
   4956 #endif
   4957         UNREACHABLE();
   4958       }
   4959     } else {
   4960       DCHECK_EQ(kDescriptor, new_details.location());
   4961       if (old_details.location() == kField ||
   4962           old_descriptors->GetStrongValue(i) !=
   4963               new_descriptors->GetStrongValue(i)) {
   4964         return nullptr;
   4965       }
   4966     }
   4967   }
   4968   if (new_map->NumberOfOwnDescriptors() != old_nof) return nullptr;
   4969   return new_map;
   4970 }
   4971 
   4972 
   4973 // static
   4974 Handle<Map> Map::Update(Isolate* isolate, Handle<Map> map) {
   4975   if (!map->is_deprecated()) return map;
   4976   MapUpdater mu(isolate, map);
   4977   return mu.Update();
   4978 }
   4979 
   4980 Maybe<bool> JSObject::SetPropertyWithInterceptor(LookupIterator* it,
   4981                                                  ShouldThrow should_throw,
   4982                                                  Handle<Object> value) {
   4983   DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
   4984   return SetPropertyWithInterceptorInternal(it, it->GetInterceptor(),
   4985                                             should_throw, value);
   4986 }
   4987 
   4988 MaybeHandle<Object> Object::SetProperty(Isolate* isolate, Handle<Object> object,
   4989                                         Handle<Name> name, Handle<Object> value,
   4990                                         LanguageMode language_mode,
   4991                                         StoreFromKeyed store_mode) {
   4992   LookupIterator it(isolate, object, name);
   4993   MAYBE_RETURN_NULL(SetProperty(&it, value, language_mode, store_mode));
   4994   return value;
   4995 }
   4996 
   4997 
   4998 Maybe<bool> Object::SetPropertyInternal(LookupIterator* it,
   4999                                         Handle<Object> value,
   5000                                         LanguageMode language_mode,
   5001                                         StoreFromKeyed store_mode,
   5002                                         bool* found) {
   5003   it->UpdateProtector();
   5004   DCHECK(it->IsFound());
   5005   ShouldThrow should_throw =
   5006       is_sloppy(language_mode) ? kDontThrow : kThrowOnError;
   5007 
   5008   // Make sure that the top context does not change when doing callbacks or
   5009   // interceptor calls.
   5010   AssertNoContextChange ncc(it->isolate());
   5011 
   5012   do {
   5013     switch (it->state()) {
   5014       case LookupIterator::NOT_FOUND:
   5015         UNREACHABLE();
   5016 
   5017       case LookupIterator::ACCESS_CHECK:
   5018         if (it->HasAccess()) break;
   5019         // Check whether it makes sense to reuse the lookup iterator. Here it
   5020         // might still call into setters up the prototype chain.
   5021         return JSObject::SetPropertyWithFailedAccessCheck(it, value,
   5022                                                           should_throw);
   5023 
   5024       case LookupIterator::JSPROXY:
   5025         return JSProxy::SetProperty(it->GetHolder<JSProxy>(), it->GetName(),
   5026                                     value, it->GetReceiver(), language_mode);
   5027 
   5028       case LookupIterator::INTERCEPTOR: {
   5029         if (it->HolderIsReceiverOrHiddenPrototype()) {
   5030           Maybe<bool> result =
   5031               JSObject::SetPropertyWithInterceptor(it, should_throw, value);
   5032           if (result.IsNothing() || result.FromJust()) return result;
   5033         } else {
   5034           Maybe<PropertyAttributes> maybe_attributes =
   5035               JSObject::GetPropertyAttributesWithInterceptor(it);
   5036           if (maybe_attributes.IsNothing()) return Nothing<bool>();
   5037           if ((maybe_attributes.FromJust() & READ_ONLY) != 0) {
   5038             return WriteToReadOnlyProperty(it, value, should_throw);
   5039           }
   5040           if (maybe_attributes.FromJust() == ABSENT) break;
   5041           *found = false;
   5042           return Nothing<bool>();
   5043         }
   5044         break;
   5045       }
   5046 
   5047       case LookupIterator::ACCESSOR: {
   5048         if (it->IsReadOnly()) {
   5049           return WriteToReadOnlyProperty(it, value, should_throw);
   5050         }
   5051         Handle<Object> accessors = it->GetAccessors();
   5052         if (accessors->IsAccessorInfo() &&
   5053             !it->HolderIsReceiverOrHiddenPrototype() &&
   5054             AccessorInfo::cast(*accessors)->is_special_data_property()) {
   5055           *found = false;
   5056           return Nothing<bool>();
   5057         }
   5058         return SetPropertyWithAccessor(it, value, should_throw);
   5059       }
   5060       case LookupIterator::INTEGER_INDEXED_EXOTIC: {
   5061         // IntegerIndexedElementSet converts value to a Number/BigInt prior to
   5062         // the bounds check. The bounds check has already happened here, but
   5063         // perform the possibly effectful ToNumber (or ToBigInt) operation
   5064         // anyways.
   5065         auto holder = it->GetHolder<JSTypedArray>();
   5066         Handle<Object> throwaway_value;
   5067         if (holder->type() == kExternalBigInt64Array ||
   5068             holder->type() == kExternalBigUint64Array) {
   5069           ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   5070               it->isolate(), throwaway_value,
   5071               BigInt::FromObject(it->isolate(), value), Nothing<bool>());
   5072         } else {
   5073           ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   5074               it->isolate(), throwaway_value,
   5075               Object::ToNumber(it->isolate(), value), Nothing<bool>());
   5076         }
   5077 
   5078         // FIXME: Throw a TypeError if the holder is neutered here
   5079         // (IntegerIndexedElementSpec step 5).
   5080 
   5081         // TODO(verwaest): Per spec, we should return false here (steps 6-9
   5082         // in IntegerIndexedElementSpec), resulting in an exception being thrown
   5083         // on OOB accesses in strict code. Historically, v8 has not done made
   5084         // this change due to uncertainty about web compat. (v8:4901)
   5085         return Just(true);
   5086       }
   5087 
   5088       case LookupIterator::DATA:
   5089         if (it->IsReadOnly()) {
   5090           return WriteToReadOnlyProperty(it, value, should_throw);
   5091         }
   5092         if (it->HolderIsReceiverOrHiddenPrototype()) {
   5093           return SetDataProperty(it, value);
   5094         }
   5095         V8_FALLTHROUGH;
   5096       case LookupIterator::TRANSITION:
   5097         *found = false;
   5098         return Nothing<bool>();
   5099     }
   5100     it->Next();
   5101   } while (it->IsFound());
   5102 
   5103   *found = false;
   5104   return Nothing<bool>();
   5105 }
   5106 
   5107 
   5108 Maybe<bool> Object::SetProperty(LookupIterator* it, Handle<Object> value,
   5109                                 LanguageMode language_mode,
   5110                                 StoreFromKeyed store_mode) {
   5111   if (it->IsFound()) {
   5112     bool found = true;
   5113     Maybe<bool> result =
   5114         SetPropertyInternal(it, value, language_mode, store_mode, &found);
   5115     if (found) return result;
   5116   }
   5117 
   5118   // If the receiver is the JSGlobalObject, the store was contextual. In case
   5119   // the property did not exist yet on the global object itself, we have to
   5120   // throw a reference error in strict mode.  In sloppy mode, we continue.
   5121   if (is_strict(language_mode) && it->GetReceiver()->IsJSGlobalObject()) {
   5122     it->isolate()->Throw(*it->isolate()->factory()->NewReferenceError(
   5123         MessageTemplate::kNotDefined, it->name()));
   5124     return Nothing<bool>();
   5125   }
   5126 
   5127   ShouldThrow should_throw =
   5128       is_sloppy(language_mode) ? kDontThrow : kThrowOnError;
   5129   return AddDataProperty(it, value, NONE, should_throw, store_mode);
   5130 }
   5131 
   5132 
   5133 Maybe<bool> Object::SetSuperProperty(LookupIterator* it, Handle<Object> value,
   5134                                      LanguageMode language_mode,
   5135                                      StoreFromKeyed store_mode) {
   5136   Isolate* isolate = it->isolate();
   5137 
   5138   if (it->IsFound()) {
   5139     bool found = true;
   5140     Maybe<bool> result =
   5141         SetPropertyInternal(it, value, language_mode, store_mode, &found);
   5142     if (found) return result;
   5143   }
   5144 
   5145   it->UpdateProtector();
   5146 
   5147   // The property either doesn't exist on the holder or exists there as a data
   5148   // property.
   5149 
   5150   ShouldThrow should_throw =
   5151       is_sloppy(language_mode) ? kDontThrow : kThrowOnError;
   5152 
   5153   if (!it->GetReceiver()->IsJSReceiver()) {
   5154     return WriteToReadOnlyProperty(it, value, should_throw);
   5155   }
   5156   Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(it->GetReceiver());
   5157 
   5158   LookupIterator::Configuration c = LookupIterator::OWN;
   5159   LookupIterator own_lookup =
   5160       it->IsElement() ? LookupIterator(isolate, receiver, it->index(), c)
   5161                       : LookupIterator(isolate, receiver, it->name(), c);
   5162 
   5163   for (; own_lookup.IsFound(); own_lookup.Next()) {
   5164     switch (own_lookup.state()) {
   5165       case LookupIterator::ACCESS_CHECK:
   5166         if (!own_lookup.HasAccess()) {
   5167           return JSObject::SetPropertyWithFailedAccessCheck(&own_lookup, value,
   5168                                                             should_throw);
   5169         }
   5170         break;
   5171 
   5172       case LookupIterator::ACCESSOR:
   5173         if (own_lookup.GetAccessors()->IsAccessorInfo()) {
   5174           if (own_lookup.IsReadOnly()) {
   5175             return WriteToReadOnlyProperty(&own_lookup, value, should_throw);
   5176           }
   5177           return JSObject::SetPropertyWithAccessor(&own_lookup, value,
   5178                                                    should_throw);
   5179         }
   5180         V8_FALLTHROUGH;
   5181       case LookupIterator::INTEGER_INDEXED_EXOTIC:
   5182         return RedefineIncompatibleProperty(isolate, it->GetName(), value,
   5183                                             should_throw);
   5184 
   5185       case LookupIterator::DATA: {
   5186         if (own_lookup.IsReadOnly()) {
   5187           return WriteToReadOnlyProperty(&own_lookup, value, should_throw);
   5188         }
   5189         return SetDataProperty(&own_lookup, value);
   5190       }
   5191 
   5192       case LookupIterator::INTERCEPTOR:
   5193       case LookupIterator::JSPROXY: {
   5194         PropertyDescriptor desc;
   5195         Maybe<bool> owned =
   5196             JSReceiver::GetOwnPropertyDescriptor(&own_lookup, &desc);
   5197         MAYBE_RETURN(owned, Nothing<bool>());
   5198         if (!owned.FromJust()) {
   5199           return JSReceiver::CreateDataProperty(&own_lookup, value,
   5200                                                 should_throw);
   5201         }
   5202         if (PropertyDescriptor::IsAccessorDescriptor(&desc) ||
   5203             !desc.writable()) {
   5204           return RedefineIncompatibleProperty(isolate, it->GetName(), value,
   5205                                               should_throw);
   5206         }
   5207 
   5208         PropertyDescriptor value_desc;
   5209         value_desc.set_value(value);
   5210         return JSReceiver::DefineOwnProperty(isolate, receiver, it->GetName(),
   5211                                              &value_desc, should_throw);
   5212       }
   5213 
   5214       case LookupIterator::NOT_FOUND:
   5215       case LookupIterator::TRANSITION:
   5216         UNREACHABLE();
   5217     }
   5218   }
   5219 
   5220   return AddDataProperty(&own_lookup, value, NONE, should_throw, store_mode);
   5221 }
   5222 
   5223 Maybe<bool> Object::CannotCreateProperty(Isolate* isolate,
   5224                                          Handle<Object> receiver,
   5225                                          Handle<Object> name,
   5226                                          Handle<Object> value,
   5227                                          ShouldThrow should_throw) {
   5228   RETURN_FAILURE(
   5229       isolate, should_throw,
   5230       NewTypeError(MessageTemplate::kStrictCannotCreateProperty, name,
   5231                    Object::TypeOf(isolate, receiver), receiver));
   5232 }
   5233 
   5234 
   5235 Maybe<bool> Object::WriteToReadOnlyProperty(LookupIterator* it,
   5236                                             Handle<Object> value,
   5237                                             ShouldThrow should_throw) {
   5238   return WriteToReadOnlyProperty(it->isolate(), it->GetReceiver(),
   5239                                  it->GetName(), value, should_throw);
   5240 }
   5241 
   5242 
   5243 Maybe<bool> Object::WriteToReadOnlyProperty(Isolate* isolate,
   5244                                             Handle<Object> receiver,
   5245                                             Handle<Object> name,
   5246                                             Handle<Object> value,
   5247                                             ShouldThrow should_throw) {
   5248   RETURN_FAILURE(isolate, should_throw,
   5249                  NewTypeError(MessageTemplate::kStrictReadOnlyProperty, name,
   5250                               Object::TypeOf(isolate, receiver), receiver));
   5251 }
   5252 
   5253 
   5254 Maybe<bool> Object::RedefineIncompatibleProperty(Isolate* isolate,
   5255                                                  Handle<Object> name,
   5256                                                  Handle<Object> value,
   5257                                                  ShouldThrow should_throw) {
   5258   RETURN_FAILURE(isolate, should_throw,
   5259                  NewTypeError(MessageTemplate::kRedefineDisallowed, name));
   5260 }
   5261 
   5262 
   5263 Maybe<bool> Object::SetDataProperty(LookupIterator* it, Handle<Object> value) {
   5264   DCHECK_IMPLIES(it->GetReceiver()->IsJSProxy(),
   5265                  it->GetName()->IsPrivateField());
   5266   DCHECK_IMPLIES(!it->IsElement() && it->GetName()->IsPrivateField(),
   5267                  it->state() == LookupIterator::DATA);
   5268   Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(it->GetReceiver());
   5269 
   5270   // Store on the holder which may be hidden behind the receiver.
   5271   DCHECK(it->HolderIsReceiverOrHiddenPrototype());
   5272 
   5273   Handle<Object> to_assign = value;
   5274   // Convert the incoming value to a number for storing into typed arrays.
   5275   if (it->IsElement() && receiver->IsJSObject() &&
   5276       JSObject::cast(*receiver)->HasFixedTypedArrayElements()) {
   5277     ElementsKind elements_kind = JSObject::cast(*receiver)->GetElementsKind();
   5278     if (elements_kind == BIGINT64_ELEMENTS ||
   5279         elements_kind == BIGUINT64_ELEMENTS) {
   5280       ASSIGN_RETURN_ON_EXCEPTION_VALUE(it->isolate(), to_assign,
   5281                                        BigInt::FromObject(it->isolate(), value),
   5282                                        Nothing<bool>());
   5283       // We have to recheck the length. However, it can only change if the
   5284       // underlying buffer was neutered, so just check that.
   5285       if (Handle<JSArrayBufferView>::cast(receiver)->WasNeutered()) {
   5286         return Just(true);
   5287         // TODO(neis): According to the spec, this should throw a TypeError.
   5288       }
   5289     } else if (!value->IsNumber() && !value->IsUndefined(it->isolate())) {
   5290       ASSIGN_RETURN_ON_EXCEPTION_VALUE(it->isolate(), to_assign,
   5291                                        Object::ToNumber(it->isolate(), value),
   5292                                        Nothing<bool>());
   5293       // We have to recheck the length. However, it can only change if the
   5294       // underlying buffer was neutered, so just check that.
   5295       if (Handle<JSArrayBufferView>::cast(receiver)->WasNeutered()) {
   5296         return Just(true);
   5297         // TODO(neis): According to the spec, this should throw a TypeError.
   5298       }
   5299     }
   5300   }
   5301 
   5302   // Possibly migrate to the most up-to-date map that will be able to store
   5303   // |value| under it->name().
   5304   it->PrepareForDataProperty(to_assign);
   5305 
   5306   // Write the property value.
   5307   it->WriteDataValue(to_assign, false);
   5308 
   5309 #if VERIFY_HEAP
   5310   if (FLAG_verify_heap) {
   5311     receiver->HeapObjectVerify(it->isolate());
   5312   }
   5313 #endif
   5314   return Just(true);
   5315 }
   5316 
   5317 
   5318 Maybe<bool> Object::AddDataProperty(LookupIterator* it, Handle<Object> value,
   5319                                     PropertyAttributes attributes,
   5320                                     ShouldThrow should_throw,
   5321                                     StoreFromKeyed store_mode) {
   5322   if (!it->GetReceiver()->IsJSReceiver()) {
   5323     return CannotCreateProperty(it->isolate(), it->GetReceiver(), it->GetName(),
   5324                                 value, should_throw);
   5325   }
   5326 
   5327   // Private symbols should be installed on JSProxy using
   5328   // JSProxy::SetPrivateSymbol.
   5329   if (it->GetReceiver()->IsJSProxy() && it->GetName()->IsPrivate() &&
   5330       !it->GetName()->IsPrivateField()) {
   5331     RETURN_FAILURE(it->isolate(), should_throw,
   5332                    NewTypeError(MessageTemplate::kProxyPrivate));
   5333   }
   5334 
   5335   DCHECK_NE(LookupIterator::INTEGER_INDEXED_EXOTIC, it->state());
   5336 
   5337   Handle<JSReceiver> receiver = it->GetStoreTarget<JSReceiver>();
   5338   DCHECK_IMPLIES(receiver->IsJSProxy(), it->GetName()->IsPrivateField());
   5339   DCHECK_IMPLIES(receiver->IsJSProxy(),
   5340                  it->state() == LookupIterator::NOT_FOUND);
   5341 
   5342   // If the receiver is a JSGlobalProxy, store on the prototype (JSGlobalObject)
   5343   // instead. If the prototype is Null, the proxy is detached.
   5344   if (receiver->IsJSGlobalProxy()) return Just(true);
   5345 
   5346   Isolate* isolate = it->isolate();
   5347 
   5348   if (it->ExtendingNonExtensible(receiver)) {
   5349     RETURN_FAILURE(
   5350         isolate, should_throw,
   5351         NewTypeError(MessageTemplate::kObjectNotExtensible, it->GetName()));
   5352   }
   5353 
   5354   if (it->IsElement()) {
   5355     if (receiver->IsJSArray()) {
   5356       Handle<JSArray> array = Handle<JSArray>::cast(receiver);
   5357       if (JSArray::WouldChangeReadOnlyLength(array, it->index())) {
   5358         RETURN_FAILURE(isolate, should_throw,
   5359                        NewTypeError(MessageTemplate::kStrictReadOnlyProperty,
   5360                                     isolate->factory()->length_string(),
   5361                                     Object::TypeOf(isolate, array), array));
   5362       }
   5363 
   5364       if (FLAG_trace_external_array_abuse &&
   5365           array->HasFixedTypedArrayElements()) {
   5366         CheckArrayAbuse(array, "typed elements write", it->index(), true);
   5367       }
   5368 
   5369       if (FLAG_trace_js_array_abuse && !array->HasFixedTypedArrayElements()) {
   5370         CheckArrayAbuse(array, "elements write", it->index(), false);
   5371       }
   5372     }
   5373 
   5374     Handle<JSObject> receiver_obj = Handle<JSObject>::cast(receiver);
   5375     JSObject::AddDataElement(receiver_obj, it->index(), value, attributes);
   5376     JSObject::ValidateElements(*receiver_obj);
   5377     return Just(true);
   5378   } else {
   5379     it->UpdateProtector();
   5380     // Migrate to the most up-to-date map that will be able to store |value|
   5381     // under it->name() with |attributes|.
   5382     it->PrepareTransitionToDataProperty(receiver, value, attributes,
   5383                                         store_mode);
   5384     DCHECK_EQ(LookupIterator::TRANSITION, it->state());
   5385     it->ApplyTransitionToDataProperty(receiver);
   5386 
   5387     // Write the property value.
   5388     it->WriteDataValue(value, true);
   5389 
   5390 #if VERIFY_HEAP
   5391     if (FLAG_verify_heap) {
   5392       receiver->HeapObjectVerify(isolate);
   5393     }
   5394 #endif
   5395   }
   5396 
   5397   return Just(true);
   5398 }
   5399 
   5400 void Map::EnsureDescriptorSlack(Isolate* isolate, Handle<Map> map, int slack) {
   5401   // Only supports adding slack to owned descriptors.
   5402   DCHECK(map->owns_descriptors());
   5403 
   5404   Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate);
   5405   int old_size = map->NumberOfOwnDescriptors();
   5406   if (slack <= descriptors->NumberOfSlackDescriptors()) return;
   5407 
   5408   Handle<DescriptorArray> new_descriptors =
   5409       DescriptorArray::CopyUpTo(isolate, descriptors, old_size, slack);
   5410 
   5411   DisallowHeapAllocation no_allocation;
   5412   // The descriptors are still the same, so keep the layout descriptor.
   5413   LayoutDescriptor* layout_descriptor = map->GetLayoutDescriptor();
   5414 
   5415   if (old_size == 0) {
   5416     map->UpdateDescriptors(*new_descriptors, layout_descriptor);
   5417     return;
   5418   }
   5419 
   5420   // If the source descriptors had an enum cache we copy it. This ensures
   5421   // that the maps to which we push the new descriptor array back can rely
   5422   // on a cache always being available once it is set. If the map has more
   5423   // enumerated descriptors than available in the original cache, the cache
   5424   // will be lazily replaced by the extended cache when needed.
   5425   new_descriptors->CopyEnumCacheFrom(*descriptors);
   5426 
   5427   // Replace descriptors by new_descriptors in all maps that share it. The old
   5428   // descriptors will not be trimmed in the mark-compactor, we need to mark
   5429   // all its elements.
   5430   MarkingBarrierForElements(isolate->heap(), *descriptors);
   5431 
   5432   Map* current = *map;
   5433   while (current->instance_descriptors() == *descriptors) {
   5434     Object* next = current->GetBackPointer();
   5435     if (next->IsUndefined(isolate)) break;  // Stop overwriting at initial map.
   5436     current->UpdateDescriptors(*new_descriptors, layout_descriptor);
   5437     current = Map::cast(next);
   5438   }
   5439   map->UpdateDescriptors(*new_descriptors, layout_descriptor);
   5440 }
   5441 
   5442 // static
   5443 Handle<Map> Map::GetObjectCreateMap(Isolate* isolate,
   5444                                     Handle<HeapObject> prototype) {
   5445   Handle<Map> map(isolate->native_context()->object_function()->initial_map(),
   5446                   isolate);
   5447   if (map->prototype() == *prototype) return map;
   5448   if (prototype->IsNull(isolate)) {
   5449     return isolate->slow_object_with_null_prototype_map();
   5450   }
   5451   if (prototype->IsJSObject()) {
   5452     Handle<JSObject> js_prototype = Handle<JSObject>::cast(prototype);
   5453     if (!js_prototype->map()->is_prototype_map()) {
   5454       JSObject::OptimizeAsPrototype(js_prototype);
   5455     }
   5456     Handle<PrototypeInfo> info =
   5457         Map::GetOrCreatePrototypeInfo(js_prototype, isolate);
   5458     // TODO(verwaest): Use inobject slack tracking for this map.
   5459     if (info->HasObjectCreateMap()) {
   5460       map = handle(info->ObjectCreateMap(), isolate);
   5461     } else {
   5462       map = Map::CopyInitialMap(isolate, map);
   5463       Map::SetPrototype(isolate, map, prototype);
   5464       PrototypeInfo::SetObjectCreateMap(info, map);
   5465     }
   5466     return map;
   5467   }
   5468 
   5469   return Map::TransitionToPrototype(isolate, map, prototype);
   5470 }
   5471 
   5472 // static
   5473 MaybeHandle<Map> Map::TryGetObjectCreateMap(Isolate* isolate,
   5474                                             Handle<HeapObject> prototype) {
   5475   Handle<Map> map(isolate->native_context()->object_function()->initial_map(),
   5476                   isolate);
   5477   if (map->prototype() == *prototype) return map;
   5478   if (prototype->IsNull(isolate)) {
   5479     return isolate->slow_object_with_null_prototype_map();
   5480   }
   5481   if (!prototype->IsJSObject()) return MaybeHandle<Map>();
   5482   Handle<JSObject> js_prototype = Handle<JSObject>::cast(prototype);
   5483   if (!js_prototype->map()->is_prototype_map()) return MaybeHandle<Map>();
   5484   Handle<PrototypeInfo> info =
   5485       Map::GetOrCreatePrototypeInfo(js_prototype, isolate);
   5486   if (!info->HasObjectCreateMap()) return MaybeHandle<Map>();
   5487   return handle(info->ObjectCreateMap(), isolate);
   5488 }
   5489 
   5490 template <class T>
   5491 static int AppendUniqueCallbacks(Isolate* isolate,
   5492                                  Handle<TemplateList> callbacks,
   5493                                  Handle<typename T::Array> array,
   5494                                  int valid_descriptors) {
   5495   int nof_callbacks = callbacks->length();
   5496 
   5497   // Fill in new callback descriptors.  Process the callbacks from
   5498   // back to front so that the last callback with a given name takes
   5499   // precedence over previously added callbacks with that name.
   5500   for (int i = nof_callbacks - 1; i >= 0; i--) {
   5501     Handle<AccessorInfo> entry(AccessorInfo::cast(callbacks->get(i)), isolate);
   5502     Handle<Name> key(Name::cast(entry->name()), isolate);
   5503     DCHECK(key->IsUniqueName());
   5504     // Check if a descriptor with this name already exists before writing.
   5505     if (!T::Contains(key, entry, valid_descriptors, array)) {
   5506       T::Insert(key, entry, valid_descriptors, array);
   5507       valid_descriptors++;
   5508     }
   5509   }
   5510 
   5511   return valid_descriptors;
   5512 }
   5513 
   5514 struct FixedArrayAppender {
   5515   typedef FixedArray Array;
   5516   static bool Contains(Handle<Name> key,
   5517                        Handle<AccessorInfo> entry,
   5518                        int valid_descriptors,
   5519                        Handle<FixedArray> array) {
   5520     for (int i = 0; i < valid_descriptors; i++) {
   5521       if (*key == AccessorInfo::cast(array->get(i))->name()) return true;
   5522     }
   5523     return false;
   5524   }
   5525   static void Insert(Handle<Name> key,
   5526                      Handle<AccessorInfo> entry,
   5527                      int valid_descriptors,
   5528                      Handle<FixedArray> array) {
   5529     DisallowHeapAllocation no_gc;
   5530     array->set(valid_descriptors, *entry);
   5531   }
   5532 };
   5533 
   5534 int AccessorInfo::AppendUnique(Isolate* isolate, Handle<Object> descriptors,
   5535                                Handle<FixedArray> array,
   5536                                int valid_descriptors) {
   5537   Handle<TemplateList> callbacks = Handle<TemplateList>::cast(descriptors);
   5538   DCHECK_GE(array->length(), callbacks->length() + valid_descriptors);
   5539   return AppendUniqueCallbacks<FixedArrayAppender>(isolate, callbacks, array,
   5540                                                    valid_descriptors);
   5541 }
   5542 
   5543 static bool ContainsMap(MapHandles const& maps, Map* map) {
   5544   DCHECK_NOT_NULL(map);
   5545   for (Handle<Map> current : maps) {
   5546     if (!current.is_null() && *current == map) return true;
   5547   }
   5548   return false;
   5549 }
   5550 
   5551 Map* Map::FindElementsKindTransitionedMap(Isolate* isolate,
   5552                                           MapHandles const& candidates) {
   5553   DisallowHeapAllocation no_allocation;
   5554   DisallowDeoptimization no_deoptimization(isolate);
   5555 
   5556   if (is_prototype_map()) return nullptr;
   5557 
   5558   ElementsKind kind = elements_kind();
   5559   bool packed = IsFastPackedElementsKind(kind);
   5560 
   5561   Map* transition = nullptr;
   5562   if (IsTransitionableFastElementsKind(kind)) {
   5563     // Check the state of the root map.
   5564     Map* root_map = FindRootMap(isolate);
   5565     if (!EquivalentToForElementsKindTransition(root_map)) return nullptr;
   5566     root_map = root_map->LookupElementsTransitionMap(isolate, kind);
   5567     DCHECK_NOT_NULL(root_map);
   5568     // Starting from the next existing elements kind transition try to
   5569     // replay the property transitions that does not involve instance rewriting
   5570     // (ElementsTransitionAndStoreStub does not support that).
   5571     for (root_map = root_map->ElementsTransitionMap();
   5572          root_map != nullptr && root_map->has_fast_elements();
   5573          root_map = root_map->ElementsTransitionMap()) {
   5574       Map* current = root_map->TryReplayPropertyTransitions(isolate, this);
   5575       if (current == nullptr) continue;
   5576       if (InstancesNeedRewriting(current)) continue;
   5577 
   5578       if (ContainsMap(candidates, current) &&
   5579           (packed || !IsFastPackedElementsKind(current->elements_kind()))) {
   5580         transition = current;
   5581         packed = packed && IsFastPackedElementsKind(current->elements_kind());
   5582       }
   5583     }
   5584   }
   5585   return transition;
   5586 }
   5587 
   5588 static Map* FindClosestElementsTransition(Isolate* isolate, Map* map,
   5589                                           ElementsKind to_kind) {
   5590   // Ensure we are requested to search elements kind transition "near the root".
   5591   DCHECK_EQ(map->FindRootMap(isolate)->NumberOfOwnDescriptors(),
   5592             map->NumberOfOwnDescriptors());
   5593   Map* current_map = map;
   5594 
   5595   ElementsKind kind = map->elements_kind();
   5596   while (kind != to_kind) {
   5597     Map* next_map = current_map->ElementsTransitionMap();
   5598     if (next_map == nullptr) return current_map;
   5599     kind = next_map->elements_kind();
   5600     current_map = next_map;
   5601   }
   5602 
   5603   DCHECK_EQ(to_kind, current_map->elements_kind());
   5604   return current_map;
   5605 }
   5606 
   5607 Map* Map::LookupElementsTransitionMap(Isolate* isolate, ElementsKind to_kind) {
   5608   Map* to_map = FindClosestElementsTransition(isolate, this, to_kind);
   5609   if (to_map->elements_kind() == to_kind) return to_map;
   5610   return nullptr;
   5611 }
   5612 
   5613 bool Map::IsMapInArrayPrototypeChain(Isolate* isolate) const {
   5614   if (isolate->initial_array_prototype()->map() == this) {
   5615     return true;
   5616   }
   5617 
   5618   if (isolate->initial_object_prototype()->map() == this) {
   5619     return true;
   5620   }
   5621 
   5622   return false;
   5623 }
   5624 
   5625 static Handle<Map> AddMissingElementsTransitions(Isolate* isolate,
   5626                                                  Handle<Map> map,
   5627                                                  ElementsKind to_kind) {
   5628   DCHECK(IsTransitionElementsKind(map->elements_kind()));
   5629 
   5630   Handle<Map> current_map = map;
   5631 
   5632   ElementsKind kind = map->elements_kind();
   5633   TransitionFlag flag;
   5634   if (map->is_prototype_map()) {
   5635     flag = OMIT_TRANSITION;
   5636   } else {
   5637     flag = INSERT_TRANSITION;
   5638     if (IsFastElementsKind(kind)) {
   5639       while (kind != to_kind && !IsTerminalElementsKind(kind)) {
   5640         kind = GetNextTransitionElementsKind(kind);
   5641         current_map = Map::CopyAsElementsKind(isolate, current_map, kind, flag);
   5642       }
   5643     }
   5644   }
   5645 
   5646   // In case we are exiting the fast elements kind system, just add the map in
   5647   // the end.
   5648   if (kind != to_kind) {
   5649     current_map = Map::CopyAsElementsKind(isolate, current_map, to_kind, flag);
   5650   }
   5651 
   5652   DCHECK(current_map->elements_kind() == to_kind);
   5653   return current_map;
   5654 }
   5655 
   5656 Handle<Map> Map::TransitionElementsTo(Isolate* isolate, Handle<Map> map,
   5657                                       ElementsKind to_kind) {
   5658   ElementsKind from_kind = map->elements_kind();
   5659   if (from_kind == to_kind) return map;
   5660 
   5661   Context* native_context = isolate->context()->native_context();
   5662   if (from_kind == FAST_SLOPPY_ARGUMENTS_ELEMENTS) {
   5663     if (*map == native_context->fast_aliased_arguments_map()) {
   5664       DCHECK_EQ(SLOW_SLOPPY_ARGUMENTS_ELEMENTS, to_kind);
   5665       return handle(native_context->slow_aliased_arguments_map(), isolate);
   5666     }
   5667   } else if (from_kind == SLOW_SLOPPY_ARGUMENTS_ELEMENTS) {
   5668     if (*map == native_context->slow_aliased_arguments_map()) {
   5669       DCHECK_EQ(FAST_SLOPPY_ARGUMENTS_ELEMENTS, to_kind);
   5670       return handle(native_context->fast_aliased_arguments_map(), isolate);
   5671     }
   5672   } else if (IsFastElementsKind(from_kind) && IsFastElementsKind(to_kind)) {
   5673     // Reuse map transitions for JSArrays.
   5674     DisallowHeapAllocation no_gc;
   5675     if (native_context->GetInitialJSArrayMap(from_kind) == *map) {
   5676       Object* maybe_transitioned_map =
   5677           native_context->get(Context::ArrayMapIndex(to_kind));
   5678       if (maybe_transitioned_map->IsMap()) {
   5679         return handle(Map::cast(maybe_transitioned_map), isolate);
   5680       }
   5681     }
   5682   }
   5683 
   5684   DCHECK(!map->IsUndefined(isolate));
   5685   // Check if we can go back in the elements kind transition chain.
   5686   if (IsHoleyElementsKind(from_kind) &&
   5687       to_kind == GetPackedElementsKind(from_kind) &&
   5688       map->GetBackPointer()->IsMap() &&
   5689       Map::cast(map->GetBackPointer())->elements_kind() == to_kind) {
   5690     return handle(Map::cast(map->GetBackPointer()), isolate);
   5691   }
   5692 
   5693   bool allow_store_transition = IsTransitionElementsKind(from_kind);
   5694   // Only store fast element maps in ascending generality.
   5695   if (IsFastElementsKind(to_kind)) {
   5696     allow_store_transition =
   5697         allow_store_transition && IsTransitionableFastElementsKind(from_kind) &&
   5698         IsMoreGeneralElementsKindTransition(from_kind, to_kind);
   5699   }
   5700 
   5701   if (!allow_store_transition) {
   5702     return Map::CopyAsElementsKind(isolate, map, to_kind, OMIT_TRANSITION);
   5703   }
   5704 
   5705   return Map::ReconfigureElementsKind(isolate, map, to_kind);
   5706 }
   5707 
   5708 
   5709 // static
   5710 Handle<Map> Map::AsElementsKind(Isolate* isolate, Handle<Map> map,
   5711                                 ElementsKind kind) {
   5712   Handle<Map> closest_map(FindClosestElementsTransition(isolate, *map, kind),
   5713                           isolate);
   5714 
   5715   if (closest_map->elements_kind() == kind) {
   5716     return closest_map;
   5717   }
   5718 
   5719   return AddMissingElementsTransitions(isolate, closest_map, kind);
   5720 }
   5721 
   5722 
   5723 Handle<Map> JSObject::GetElementsTransitionMap(Handle<JSObject> object,
   5724                                                ElementsKind to_kind) {
   5725   Handle<Map> map(object->map(), object->GetIsolate());
   5726   return Map::TransitionElementsTo(object->GetIsolate(), map, to_kind);
   5727 }
   5728 
   5729 
   5730 void JSProxy::Revoke(Handle<JSProxy> proxy) {
   5731   Isolate* isolate = proxy->GetIsolate();
   5732   // ES#sec-proxy-revocation-functions
   5733   if (!proxy->IsRevoked()) {
   5734     // 5. Set p.[[ProxyTarget]] to null.
   5735     proxy->set_target(ReadOnlyRoots(isolate).null_value());
   5736     // 6. Set p.[[ProxyHandler]] to null.
   5737     proxy->set_handler(ReadOnlyRoots(isolate).null_value());
   5738   }
   5739   DCHECK(proxy->IsRevoked());
   5740 }
   5741 
   5742 // static
   5743 Maybe<bool> JSProxy::IsArray(Handle<JSProxy> proxy) {
   5744   Isolate* isolate = proxy->GetIsolate();
   5745   Handle<JSReceiver> object = Handle<JSReceiver>::cast(proxy);
   5746   for (int i = 0; i < JSProxy::kMaxIterationLimit; i++) {
   5747     Handle<JSProxy> proxy = Handle<JSProxy>::cast(object);
   5748     if (proxy->IsRevoked()) {
   5749       isolate->Throw(*isolate->factory()->NewTypeError(
   5750           MessageTemplate::kProxyRevoked,
   5751           isolate->factory()->NewStringFromAsciiChecked("IsArray")));
   5752       return Nothing<bool>();
   5753     }
   5754     object = handle(JSReceiver::cast(proxy->target()), isolate);
   5755     if (object->IsJSArray()) return Just(true);
   5756     if (!object->IsJSProxy()) return Just(false);
   5757   }
   5758 
   5759   // Too deep recursion, throw a RangeError.
   5760   isolate->StackOverflow();
   5761   return Nothing<bool>();
   5762 }
   5763 
   5764 Maybe<bool> JSProxy::HasProperty(Isolate* isolate, Handle<JSProxy> proxy,
   5765                                  Handle<Name> name) {
   5766   DCHECK(!name->IsPrivate());
   5767   STACK_CHECK(isolate, Nothing<bool>());
   5768   // 1. (Assert)
   5769   // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O.
   5770   Handle<Object> handler(proxy->handler(), isolate);
   5771   // 3. If handler is null, throw a TypeError exception.
   5772   // 4. Assert: Type(handler) is Object.
   5773   if (proxy->IsRevoked()) {
   5774     isolate->Throw(*isolate->factory()->NewTypeError(
   5775         MessageTemplate::kProxyRevoked, isolate->factory()->has_string()));
   5776     return Nothing<bool>();
   5777   }
   5778   // 5. Let target be the value of the [[ProxyTarget]] internal slot of O.
   5779   Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate);
   5780   // 6. Let trap be ? GetMethod(handler, "has").
   5781   Handle<Object> trap;
   5782   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   5783       isolate, trap, Object::GetMethod(Handle<JSReceiver>::cast(handler),
   5784                                        isolate->factory()->has_string()),
   5785       Nothing<bool>());
   5786   // 7. If trap is undefined, then
   5787   if (trap->IsUndefined(isolate)) {
   5788     // 7a. Return target.[[HasProperty]](P).
   5789     return JSReceiver::HasProperty(target, name);
   5790   }
   5791   // 8. Let booleanTrapResult be ToBoolean(? Call(trap, handler, target, P)).
   5792   Handle<Object> trap_result_obj;
   5793   Handle<Object> args[] = {target, name};
   5794   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   5795       isolate, trap_result_obj,
   5796       Execution::Call(isolate, trap, handler, arraysize(args), args),
   5797       Nothing<bool>());
   5798   bool boolean_trap_result = trap_result_obj->BooleanValue(isolate);
   5799   // 9. If booleanTrapResult is false, then:
   5800   if (!boolean_trap_result) {
   5801     MAYBE_RETURN(JSProxy::CheckHasTrap(isolate, name, target), Nothing<bool>());
   5802   }
   5803   // 10. Return booleanTrapResult.
   5804   return Just(boolean_trap_result);
   5805 }
   5806 
   5807 Maybe<bool> JSProxy::CheckHasTrap(Isolate* isolate, Handle<Name> name,
   5808                                   Handle<JSReceiver> target) {
   5809   // 9a. Let targetDesc be ? target.[[GetOwnProperty]](P).
   5810   PropertyDescriptor target_desc;
   5811   Maybe<bool> target_found =
   5812       JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, &target_desc);
   5813   MAYBE_RETURN(target_found, Nothing<bool>());
   5814   // 9b. If targetDesc is not undefined, then:
   5815   if (target_found.FromJust()) {
   5816     // 9b i. If targetDesc.[[Configurable]] is false, throw a TypeError
   5817     //       exception.
   5818     if (!target_desc.configurable()) {
   5819       isolate->Throw(*isolate->factory()->NewTypeError(
   5820           MessageTemplate::kProxyHasNonConfigurable, name));
   5821       return Nothing<bool>();
   5822     }
   5823     // 9b ii. Let extensibleTarget be ? IsExtensible(target).
   5824     Maybe<bool> extensible_target = JSReceiver::IsExtensible(target);
   5825     MAYBE_RETURN(extensible_target, Nothing<bool>());
   5826     // 9b iii. If extensibleTarget is false, throw a TypeError exception.
   5827     if (!extensible_target.FromJust()) {
   5828       isolate->Throw(*isolate->factory()->NewTypeError(
   5829           MessageTemplate::kProxyHasNonExtensible, name));
   5830       return Nothing<bool>();
   5831     }
   5832   }
   5833   return Just(true);
   5834 }
   5835 
   5836 Maybe<bool> JSProxy::SetProperty(Handle<JSProxy> proxy, Handle<Name> name,
   5837                                  Handle<Object> value, Handle<Object> receiver,
   5838                                  LanguageMode language_mode) {
   5839   DCHECK(!name->IsPrivate());
   5840   Isolate* isolate = proxy->GetIsolate();
   5841   STACK_CHECK(isolate, Nothing<bool>());
   5842   Factory* factory = isolate->factory();
   5843   Handle<String> trap_name = factory->set_string();
   5844   ShouldThrow should_throw =
   5845       is_sloppy(language_mode) ? kDontThrow : kThrowOnError;
   5846 
   5847   if (proxy->IsRevoked()) {
   5848     isolate->Throw(
   5849         *factory->NewTypeError(MessageTemplate::kProxyRevoked, trap_name));
   5850     return Nothing<bool>();
   5851   }
   5852   Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate);
   5853   Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate);
   5854 
   5855   Handle<Object> trap;
   5856   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   5857       isolate, trap, Object::GetMethod(handler, trap_name), Nothing<bool>());
   5858   if (trap->IsUndefined(isolate)) {
   5859     LookupIterator it =
   5860         LookupIterator::PropertyOrElement(isolate, receiver, name, target);
   5861     return Object::SetSuperProperty(&it, value, language_mode,
   5862                                     Object::MAY_BE_STORE_FROM_KEYED);
   5863   }
   5864 
   5865   Handle<Object> trap_result;
   5866   Handle<Object> args[] = {target, name, value, receiver};
   5867   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   5868       isolate, trap_result,
   5869       Execution::Call(isolate, trap, handler, arraysize(args), args),
   5870       Nothing<bool>());
   5871   if (!trap_result->BooleanValue(isolate)) {
   5872     RETURN_FAILURE(isolate, should_throw,
   5873                    NewTypeError(MessageTemplate::kProxyTrapReturnedFalsishFor,
   5874                                 trap_name, name));
   5875   }
   5876 
   5877   MaybeHandle<Object> result =
   5878       JSProxy::CheckGetSetTrapResult(isolate, name, target, value, kSet);
   5879 
   5880   if (result.is_null()) {
   5881     return Nothing<bool>();
   5882   }
   5883   return Just(true);
   5884 }
   5885 
   5886 
   5887 Maybe<bool> JSProxy::DeletePropertyOrElement(Handle<JSProxy> proxy,
   5888                                              Handle<Name> name,
   5889                                              LanguageMode language_mode) {
   5890   DCHECK(!name->IsPrivate());
   5891   ShouldThrow should_throw =
   5892       is_sloppy(language_mode) ? kDontThrow : kThrowOnError;
   5893   Isolate* isolate = proxy->GetIsolate();
   5894   STACK_CHECK(isolate, Nothing<bool>());
   5895   Factory* factory = isolate->factory();
   5896   Handle<String> trap_name = factory->deleteProperty_string();
   5897 
   5898   if (proxy->IsRevoked()) {
   5899     isolate->Throw(
   5900         *factory->NewTypeError(MessageTemplate::kProxyRevoked, trap_name));
   5901     return Nothing<bool>();
   5902   }
   5903   Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate);
   5904   Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate);
   5905 
   5906   Handle<Object> trap;
   5907   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   5908       isolate, trap, Object::GetMethod(handler, trap_name), Nothing<bool>());
   5909   if (trap->IsUndefined(isolate)) {
   5910     return JSReceiver::DeletePropertyOrElement(target, name, language_mode);
   5911   }
   5912 
   5913   Handle<Object> trap_result;
   5914   Handle<Object> args[] = {target, name};
   5915   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   5916       isolate, trap_result,
   5917       Execution::Call(isolate, trap, handler, arraysize(args), args),
   5918       Nothing<bool>());
   5919   if (!trap_result->BooleanValue(isolate)) {
   5920     RETURN_FAILURE(isolate, should_throw,
   5921                    NewTypeError(MessageTemplate::kProxyTrapReturnedFalsishFor,
   5922                                 trap_name, name));
   5923   }
   5924 
   5925   // Enforce the invariant.
   5926   PropertyDescriptor target_desc;
   5927   Maybe<bool> owned =
   5928       JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, &target_desc);
   5929   MAYBE_RETURN(owned, Nothing<bool>());
   5930   if (owned.FromJust() && !target_desc.configurable()) {
   5931     isolate->Throw(*factory->NewTypeError(
   5932         MessageTemplate::kProxyDeletePropertyNonConfigurable, name));
   5933     return Nothing<bool>();
   5934   }
   5935   return Just(true);
   5936 }
   5937 
   5938 
   5939 // static
   5940 MaybeHandle<JSProxy> JSProxy::New(Isolate* isolate, Handle<Object> target,
   5941                                   Handle<Object> handler) {
   5942   if (!target->IsJSReceiver()) {
   5943     THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kProxyNonObject),
   5944                     JSProxy);
   5945   }
   5946   if (target->IsJSProxy() && JSProxy::cast(*target)->IsRevoked()) {
   5947     THROW_NEW_ERROR(isolate,
   5948                     NewTypeError(MessageTemplate::kProxyHandlerOrTargetRevoked),
   5949                     JSProxy);
   5950   }
   5951   if (!handler->IsJSReceiver()) {
   5952     THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kProxyNonObject),
   5953                     JSProxy);
   5954   }
   5955   if (handler->IsJSProxy() && JSProxy::cast(*handler)->IsRevoked()) {
   5956     THROW_NEW_ERROR(isolate,
   5957                     NewTypeError(MessageTemplate::kProxyHandlerOrTargetRevoked),
   5958                     JSProxy);
   5959   }
   5960   return isolate->factory()->NewJSProxy(Handle<JSReceiver>::cast(target),
   5961                                         Handle<JSReceiver>::cast(handler));
   5962 }
   5963 
   5964 
   5965 // static
   5966 MaybeHandle<Context> JSProxy::GetFunctionRealm(Handle<JSProxy> proxy) {
   5967   DCHECK(proxy->map()->is_constructor());
   5968   if (proxy->IsRevoked()) {
   5969     THROW_NEW_ERROR(proxy->GetIsolate(),
   5970                     NewTypeError(MessageTemplate::kProxyRevoked), Context);
   5971   }
   5972   Handle<JSReceiver> target(JSReceiver::cast(proxy->target()),
   5973                             proxy->GetIsolate());
   5974   return JSReceiver::GetFunctionRealm(target);
   5975 }
   5976 
   5977 
   5978 // static
   5979 MaybeHandle<Context> JSBoundFunction::GetFunctionRealm(
   5980     Handle<JSBoundFunction> function) {
   5981   DCHECK(function->map()->is_constructor());
   5982   return JSReceiver::GetFunctionRealm(
   5983       handle(function->bound_target_function(), function->GetIsolate()));
   5984 }
   5985 
   5986 // static
   5987 MaybeHandle<String> JSBoundFunction::GetName(Isolate* isolate,
   5988                                              Handle<JSBoundFunction> function) {
   5989   Handle<String> prefix = isolate->factory()->bound__string();
   5990   Handle<String> target_name = prefix;
   5991   Factory* factory = isolate->factory();
   5992   // Concatenate the "bound " up to the last non-bound target.
   5993   while (function->bound_target_function()->IsJSBoundFunction()) {
   5994     ASSIGN_RETURN_ON_EXCEPTION(isolate, target_name,
   5995                                factory->NewConsString(prefix, target_name),
   5996                                String);
   5997     function = handle(JSBoundFunction::cast(function->bound_target_function()),
   5998                       isolate);
   5999   }
   6000   if (function->bound_target_function()->IsJSFunction()) {
   6001     Handle<JSFunction> target(
   6002         JSFunction::cast(function->bound_target_function()), isolate);
   6003     Handle<Object> name = JSFunction::GetName(isolate, target);
   6004     if (!name->IsString()) return target_name;
   6005     return factory->NewConsString(target_name, Handle<String>::cast(name));
   6006   }
   6007   // This will omit the proper target name for bound JSProxies.
   6008   return target_name;
   6009 }
   6010 
   6011 // static
   6012 Maybe<int> JSBoundFunction::GetLength(Isolate* isolate,
   6013                                       Handle<JSBoundFunction> function) {
   6014   int nof_bound_arguments = function->bound_arguments()->length();
   6015   while (function->bound_target_function()->IsJSBoundFunction()) {
   6016     function = handle(JSBoundFunction::cast(function->bound_target_function()),
   6017                       isolate);
   6018     // Make sure we never overflow {nof_bound_arguments}, the number of
   6019     // arguments of a function is strictly limited by the max length of an
   6020     // JSAarray, Smi::kMaxValue is thus a reasonably good overestimate.
   6021     int length = function->bound_arguments()->length();
   6022     if (V8_LIKELY(Smi::kMaxValue - nof_bound_arguments > length)) {
   6023       nof_bound_arguments += length;
   6024     } else {
   6025       nof_bound_arguments = Smi::kMaxValue;
   6026     }
   6027   }
   6028   // All non JSFunction targets get a direct property and don't use this
   6029   // accessor.
   6030   Handle<JSFunction> target(JSFunction::cast(function->bound_target_function()),
   6031                             isolate);
   6032   Maybe<int> target_length = JSFunction::GetLength(isolate, target);
   6033   if (target_length.IsNothing()) return target_length;
   6034 
   6035   int length = Max(0, target_length.FromJust() - nof_bound_arguments);
   6036   return Just(length);
   6037 }
   6038 
   6039 // static
   6040 Handle<Object> JSFunction::GetName(Isolate* isolate,
   6041                                    Handle<JSFunction> function) {
   6042   if (function->shared()->name_should_print_as_anonymous()) {
   6043     return isolate->factory()->anonymous_string();
   6044   }
   6045   return handle(function->shared()->Name(), isolate);
   6046 }
   6047 
   6048 // static
   6049 Maybe<int> JSFunction::GetLength(Isolate* isolate,
   6050                                  Handle<JSFunction> function) {
   6051   int length = 0;
   6052   if (function->shared()->is_compiled()) {
   6053     length = function->shared()->GetLength();
   6054   } else {
   6055     // If the function isn't compiled yet, the length is not computed
   6056     // correctly yet. Compile it now and return the right length.
   6057     if (Compiler::Compile(function, Compiler::KEEP_EXCEPTION)) {
   6058       length = function->shared()->GetLength();
   6059     }
   6060     if (isolate->has_pending_exception()) return Nothing<int>();
   6061   }
   6062   DCHECK_GE(length, 0);
   6063   return Just(length);
   6064 }
   6065 
   6066 // static
   6067 Handle<Context> JSFunction::GetFunctionRealm(Handle<JSFunction> function) {
   6068   DCHECK(function->map()->is_constructor());
   6069   return handle(function->context()->native_context(), function->GetIsolate());
   6070 }
   6071 
   6072 
   6073 // static
   6074 MaybeHandle<Context> JSObject::GetFunctionRealm(Handle<JSObject> object) {
   6075   DCHECK(object->map()->is_constructor());
   6076   DCHECK(!object->IsJSFunction());
   6077   return object->GetCreationContext();
   6078 }
   6079 
   6080 
   6081 // static
   6082 MaybeHandle<Context> JSReceiver::GetFunctionRealm(Handle<JSReceiver> receiver) {
   6083   if (receiver->IsJSProxy()) {
   6084     return JSProxy::GetFunctionRealm(Handle<JSProxy>::cast(receiver));
   6085   }
   6086 
   6087   if (receiver->IsJSFunction()) {
   6088     return JSFunction::GetFunctionRealm(Handle<JSFunction>::cast(receiver));
   6089   }
   6090 
   6091   if (receiver->IsJSBoundFunction()) {
   6092     return JSBoundFunction::GetFunctionRealm(
   6093         Handle<JSBoundFunction>::cast(receiver));
   6094   }
   6095 
   6096   return JSObject::GetFunctionRealm(Handle<JSObject>::cast(receiver));
   6097 }
   6098 
   6099 
   6100 Maybe<PropertyAttributes> JSProxy::GetPropertyAttributes(LookupIterator* it) {
   6101   PropertyDescriptor desc;
   6102   Maybe<bool> found = JSProxy::GetOwnPropertyDescriptor(
   6103       it->isolate(), it->GetHolder<JSProxy>(), it->GetName(), &desc);
   6104   MAYBE_RETURN(found, Nothing<PropertyAttributes>());
   6105   if (!found.FromJust()) return Just(ABSENT);
   6106   return Just(desc.ToAttributes());
   6107 }
   6108 
   6109 
   6110 void JSObject::AllocateStorageForMap(Handle<JSObject> object, Handle<Map> map) {
   6111   DCHECK(object->map()->GetInObjectProperties() ==
   6112          map->GetInObjectProperties());
   6113   ElementsKind obj_kind = object->map()->elements_kind();
   6114   ElementsKind map_kind = map->elements_kind();
   6115   if (map_kind != obj_kind) {
   6116     ElementsKind to_kind = GetMoreGeneralElementsKind(map_kind, obj_kind);
   6117     if (IsDictionaryElementsKind(obj_kind)) {
   6118       to_kind = obj_kind;
   6119     }
   6120     if (IsDictionaryElementsKind(to_kind)) {
   6121       NormalizeElements(object);
   6122     } else {
   6123       TransitionElementsKind(object, to_kind);
   6124     }
   6125     map = Map::ReconfigureElementsKind(object->GetIsolate(), map, to_kind);
   6126   }
   6127   int number_of_fields = map->NumberOfFields();
   6128   int inobject = map->GetInObjectProperties();
   6129   int unused = map->UnusedPropertyFields();
   6130   int total_size = number_of_fields + unused;
   6131   int external = total_size - inobject;
   6132   // Allocate mutable double boxes if necessary. It is always necessary if we
   6133   // have external properties, but is also necessary if we only have inobject
   6134   // properties but don't unbox double fields.
   6135   if (!FLAG_unbox_double_fields || external > 0) {
   6136     Isolate* isolate = object->GetIsolate();
   6137 
   6138     Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate);
   6139     Handle<FixedArray> storage;
   6140     if (!FLAG_unbox_double_fields) {
   6141       storage = isolate->factory()->NewFixedArray(inobject);
   6142     }
   6143 
   6144     Handle<PropertyArray> array =
   6145         isolate->factory()->NewPropertyArray(external);
   6146 
   6147     for (int i = 0; i < map->NumberOfOwnDescriptors(); i++) {
   6148       PropertyDetails details = descriptors->GetDetails(i);
   6149       Representation representation = details.representation();
   6150       if (!representation.IsDouble()) continue;
   6151       FieldIndex index = FieldIndex::ForDescriptor(*map, i);
   6152       if (map->IsUnboxedDoubleField(index)) continue;
   6153       auto box = isolate->factory()->NewMutableHeapNumberWithHoleNaN();
   6154       if (index.is_inobject()) {
   6155         storage->set(index.property_index(), *box);
   6156       } else {
   6157         array->set(index.outobject_array_index(), *box);
   6158       }
   6159     }
   6160 
   6161     object->SetProperties(*array);
   6162 
   6163     if (!FLAG_unbox_double_fields) {
   6164       for (int i = 0; i < inobject; i++) {
   6165         FieldIndex index = FieldIndex::ForPropertyIndex(*map, i);
   6166         Object* value = storage->get(i);
   6167         object->RawFastPropertyAtPut(index, value);
   6168       }
   6169     }
   6170   }
   6171   object->synchronized_set_map(*map);
   6172 }
   6173 
   6174 
   6175 void JSObject::MigrateInstance(Handle<JSObject> object) {
   6176   Handle<Map> original_map(object->map(), object->GetIsolate());
   6177   Handle<Map> map = Map::Update(object->GetIsolate(), original_map);
   6178   map->set_is_migration_target(true);
   6179   MigrateToMap(object, map);
   6180   if (FLAG_trace_migration) {
   6181     object->PrintInstanceMigration(stdout, *original_map, *map);
   6182   }
   6183 #if VERIFY_HEAP
   6184   if (FLAG_verify_heap) {
   6185     object->JSObjectVerify(object->GetIsolate());
   6186   }
   6187 #endif
   6188 }
   6189 
   6190 
   6191 // static
   6192 bool JSObject::TryMigrateInstance(Handle<JSObject> object) {
   6193   Isolate* isolate = object->GetIsolate();
   6194   DisallowDeoptimization no_deoptimization(isolate);
   6195   Handle<Map> original_map(object->map(), isolate);
   6196   Handle<Map> new_map;
   6197   if (!Map::TryUpdate(isolate, original_map).ToHandle(&new_map)) {
   6198     return false;
   6199   }
   6200   JSObject::MigrateToMap(object, new_map);
   6201   if (FLAG_trace_migration && *original_map != object->map()) {
   6202     object->PrintInstanceMigration(stdout, *original_map, object->map());
   6203   }
   6204 #if VERIFY_HEAP
   6205   if (FLAG_verify_heap) {
   6206     object->JSObjectVerify(isolate);
   6207   }
   6208 #endif
   6209   return true;
   6210 }
   6211 
   6212 void JSObject::AddProperty(Isolate* isolate, Handle<JSObject> object,
   6213                            Handle<Name> name, Handle<Object> value,
   6214                            PropertyAttributes attributes) {
   6215   LookupIterator it(isolate, object, name, object,
   6216                     LookupIterator::OWN_SKIP_INTERCEPTOR);
   6217   CHECK_NE(LookupIterator::ACCESS_CHECK, it.state());
   6218 #ifdef DEBUG
   6219   uint32_t index;
   6220   DCHECK(!object->IsJSProxy());
   6221   DCHECK(!name->AsArrayIndex(&index));
   6222   Maybe<PropertyAttributes> maybe = GetPropertyAttributes(&it);
   6223   DCHECK(maybe.IsJust());
   6224   DCHECK(!it.IsFound());
   6225   DCHECK(object->map()->is_extensible() || name->IsPrivate());
   6226 #endif
   6227   CHECK(AddDataProperty(&it, value, attributes, kThrowOnError,
   6228                         CERTAINLY_NOT_STORE_FROM_KEYED)
   6229             .IsJust());
   6230 }
   6231 
   6232 
   6233 // Reconfigures a property to a data property with attributes, even if it is not
   6234 // reconfigurable.
   6235 // Requires a LookupIterator that does not look at the prototype chain beyond
   6236 // hidden prototypes.
   6237 MaybeHandle<Object> JSObject::DefineOwnPropertyIgnoreAttributes(
   6238     LookupIterator* it, Handle<Object> value, PropertyAttributes attributes,
   6239     AccessorInfoHandling handling) {
   6240   MAYBE_RETURN_NULL(DefineOwnPropertyIgnoreAttributes(it, value, attributes,
   6241                                                       kThrowOnError, handling));
   6242   return value;
   6243 }
   6244 
   6245 
   6246 Maybe<bool> JSObject::DefineOwnPropertyIgnoreAttributes(
   6247     LookupIterator* it, Handle<Object> value, PropertyAttributes attributes,
   6248     ShouldThrow should_throw, AccessorInfoHandling handling) {
   6249   it->UpdateProtector();
   6250   Handle<JSObject> object = Handle<JSObject>::cast(it->GetReceiver());
   6251 
   6252   for (; it->IsFound(); it->Next()) {
   6253     switch (it->state()) {
   6254       case LookupIterator::JSPROXY:
   6255       case LookupIterator::NOT_FOUND:
   6256       case LookupIterator::TRANSITION:
   6257         UNREACHABLE();
   6258 
   6259       case LookupIterator::ACCESS_CHECK:
   6260         if (!it->HasAccess()) {
   6261           it->isolate()->ReportFailedAccessCheck(it->GetHolder<JSObject>());
   6262           RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(), Nothing<bool>());
   6263           return Just(true);
   6264         }
   6265         break;
   6266 
   6267       // If there's an interceptor, try to store the property with the
   6268       // interceptor.
   6269       // In case of success, the attributes will have been reset to the default
   6270       // attributes of the interceptor, rather than the incoming attributes.
   6271       //
   6272       // TODO(verwaest): JSProxy afterwards verify the attributes that the
   6273       // JSProxy claims it has, and verifies that they are compatible. If not,
   6274       // they throw. Here we should do the same.
   6275       case LookupIterator::INTERCEPTOR:
   6276         if (handling == DONT_FORCE_FIELD) {
   6277           Maybe<bool> result =
   6278               JSObject::SetPropertyWithInterceptor(it, should_throw, value);
   6279           if (result.IsNothing() || result.FromJust()) return result;
   6280         }
   6281         break;
   6282 
   6283       case LookupIterator::ACCESSOR: {
   6284         Handle<Object> accessors = it->GetAccessors();
   6285 
   6286         // Special handling for AccessorInfo, which behaves like a data
   6287         // property.
   6288         if (accessors->IsAccessorInfo() && handling == DONT_FORCE_FIELD) {
   6289           PropertyAttributes current_attributes = it->property_attributes();
   6290           // Ensure the context isn't changed after calling into accessors.
   6291           AssertNoContextChange ncc(it->isolate());
   6292 
   6293           // Update the attributes before calling the setter. The setter may
   6294           // later change the shape of the property.
   6295           if (current_attributes != attributes) {
   6296             it->TransitionToAccessorPair(accessors, attributes);
   6297           }
   6298 
   6299           return JSObject::SetPropertyWithAccessor(it, value, should_throw);
   6300         }
   6301 
   6302         it->ReconfigureDataProperty(value, attributes);
   6303         return Just(true);
   6304       }
   6305       case LookupIterator::INTEGER_INDEXED_EXOTIC:
   6306         return RedefineIncompatibleProperty(it->isolate(), it->GetName(), value,
   6307                                             should_throw);
   6308 
   6309       case LookupIterator::DATA: {
   6310         // Regular property update if the attributes match.
   6311         if (it->property_attributes() == attributes) {
   6312           return SetDataProperty(it, value);
   6313         }
   6314 
   6315         // Special case: properties of typed arrays cannot be reconfigured to
   6316         // non-writable nor to non-enumerable.
   6317         if (it->IsElement() && object->HasFixedTypedArrayElements()) {
   6318           return RedefineIncompatibleProperty(it->isolate(), it->GetName(),
   6319                                               value, should_throw);
   6320         }
   6321 
   6322         // Reconfigure the data property if the attributes mismatch.
   6323         it->ReconfigureDataProperty(value, attributes);
   6324 
   6325         return Just(true);
   6326       }
   6327     }
   6328   }
   6329 
   6330   return AddDataProperty(it, value, attributes, should_throw,
   6331                          CERTAINLY_NOT_STORE_FROM_KEYED);
   6332 }
   6333 
   6334 MaybeHandle<Object> JSObject::SetOwnPropertyIgnoreAttributes(
   6335     Handle<JSObject> object, Handle<Name> name, Handle<Object> value,
   6336     PropertyAttributes attributes) {
   6337   DCHECK(!value->IsTheHole());
   6338   LookupIterator it(object, name, object, LookupIterator::OWN);
   6339   return DefineOwnPropertyIgnoreAttributes(&it, value, attributes);
   6340 }
   6341 
   6342 MaybeHandle<Object> JSObject::SetOwnElementIgnoreAttributes(
   6343     Handle<JSObject> object, uint32_t index, Handle<Object> value,
   6344     PropertyAttributes attributes) {
   6345   Isolate* isolate = object->GetIsolate();
   6346   LookupIterator it(isolate, object, index, object, LookupIterator::OWN);
   6347   return DefineOwnPropertyIgnoreAttributes(&it, value, attributes);
   6348 }
   6349 
   6350 MaybeHandle<Object> JSObject::DefinePropertyOrElementIgnoreAttributes(
   6351     Handle<JSObject> object, Handle<Name> name, Handle<Object> value,
   6352     PropertyAttributes attributes) {
   6353   Isolate* isolate = object->GetIsolate();
   6354   LookupIterator it = LookupIterator::PropertyOrElement(
   6355       isolate, object, name, object, LookupIterator::OWN);
   6356   return DefineOwnPropertyIgnoreAttributes(&it, value, attributes);
   6357 }
   6358 
   6359 Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithInterceptor(
   6360     LookupIterator* it) {
   6361   return GetPropertyAttributesWithInterceptorInternal(it, it->GetInterceptor());
   6362 }
   6363 
   6364 Maybe<PropertyAttributes> JSReceiver::GetPropertyAttributes(
   6365     LookupIterator* it) {
   6366   for (; it->IsFound(); it->Next()) {
   6367     switch (it->state()) {
   6368       case LookupIterator::NOT_FOUND:
   6369       case LookupIterator::TRANSITION:
   6370         UNREACHABLE();
   6371       case LookupIterator::JSPROXY:
   6372         return JSProxy::GetPropertyAttributes(it);
   6373       case LookupIterator::INTERCEPTOR: {
   6374         Maybe<PropertyAttributes> result =
   6375             JSObject::GetPropertyAttributesWithInterceptor(it);
   6376         if (result.IsNothing()) return result;
   6377         if (result.FromJust() != ABSENT) return result;
   6378         break;
   6379       }
   6380       case LookupIterator::ACCESS_CHECK:
   6381         if (it->HasAccess()) break;
   6382         return JSObject::GetPropertyAttributesWithFailedAccessCheck(it);
   6383       case LookupIterator::INTEGER_INDEXED_EXOTIC:
   6384         return Just(ABSENT);
   6385       case LookupIterator::ACCESSOR:
   6386         if (it->GetHolder<Object>()->IsJSModuleNamespace()) {
   6387           return JSModuleNamespace::GetPropertyAttributes(it);
   6388         } else {
   6389           return Just(it->property_attributes());
   6390         }
   6391       case LookupIterator::DATA:
   6392         return Just(it->property_attributes());
   6393     }
   6394   }
   6395   return Just(ABSENT);
   6396 }
   6397 
   6398 
   6399 Handle<NormalizedMapCache> NormalizedMapCache::New(Isolate* isolate) {
   6400   Handle<WeakFixedArray> array(
   6401       isolate->factory()->NewWeakFixedArray(kEntries, TENURED));
   6402   return Handle<NormalizedMapCache>::cast(array);
   6403 }
   6404 
   6405 
   6406 MaybeHandle<Map> NormalizedMapCache::Get(Handle<Map> fast_map,
   6407                                          PropertyNormalizationMode mode) {
   6408   DisallowHeapAllocation no_gc;
   6409   MaybeObject* value = WeakFixedArray::Get(GetIndex(fast_map));
   6410   HeapObject* heap_object;
   6411   if (!value->ToWeakHeapObject(&heap_object)) {
   6412     return MaybeHandle<Map>();
   6413   }
   6414 
   6415   Map* normalized_map = Map::cast(heap_object);
   6416   if (!normalized_map->EquivalentToForNormalization(*fast_map, mode)) {
   6417     return MaybeHandle<Map>();
   6418   }
   6419   return handle(normalized_map, GetIsolate());
   6420 }
   6421 
   6422 void NormalizedMapCache::Set(Handle<Map> fast_map, Handle<Map> normalized_map) {
   6423   DisallowHeapAllocation no_gc;
   6424   DCHECK(normalized_map->is_dictionary_map());
   6425   WeakFixedArray::Set(GetIndex(fast_map),
   6426                       HeapObjectReference::Weak(*normalized_map));
   6427 }
   6428 
   6429 void JSObject::NormalizeProperties(Handle<JSObject> object,
   6430                                    PropertyNormalizationMode mode,
   6431                                    int expected_additional_properties,
   6432                                    const char* reason) {
   6433   if (!object->HasFastProperties()) return;
   6434 
   6435   Handle<Map> map(object->map(), object->GetIsolate());
   6436   Handle<Map> new_map = Map::Normalize(object->GetIsolate(), map, mode, reason);
   6437 
   6438   MigrateToMap(object, new_map, expected_additional_properties);
   6439 }
   6440 
   6441 
   6442 void JSObject::MigrateSlowToFast(Handle<JSObject> object,
   6443                                  int unused_property_fields,
   6444                                  const char* reason) {
   6445   if (object->HasFastProperties()) return;
   6446   DCHECK(!object->IsJSGlobalObject());
   6447   Isolate* isolate = object->GetIsolate();
   6448   Factory* factory = isolate->factory();
   6449   Handle<NameDictionary> dictionary(object->property_dictionary(), isolate);
   6450 
   6451   // Make sure we preserve dictionary representation if there are too many
   6452   // descriptors.
   6453   int number_of_elements = dictionary->NumberOfElements();
   6454   if (number_of_elements > kMaxNumberOfDescriptors) return;
   6455 
   6456   Handle<FixedArray> iteration_order =
   6457       NameDictionary::IterationIndices(isolate, dictionary);
   6458 
   6459   int instance_descriptor_length = iteration_order->length();
   6460   int number_of_fields = 0;
   6461 
   6462   // Compute the length of the instance descriptor.
   6463   ReadOnlyRoots roots(isolate);
   6464   for (int i = 0; i < instance_descriptor_length; i++) {
   6465     int index = Smi::ToInt(iteration_order->get(i));
   6466     DCHECK(dictionary->IsKey(roots, dictionary->KeyAt(index)));
   6467 
   6468     PropertyKind kind = dictionary->DetailsAt(index).kind();
   6469     if (kind == kData) {
   6470       if (FLAG_track_constant_fields) {
   6471         number_of_fields += 1;
   6472       } else {
   6473         Object* value = dictionary->ValueAt(index);
   6474         if (!value->IsJSFunction()) {
   6475           number_of_fields += 1;
   6476         }
   6477       }
   6478     }
   6479   }
   6480 
   6481   Handle<Map> old_map(object->map(), isolate);
   6482 
   6483   int inobject_props = old_map->GetInObjectProperties();
   6484 
   6485   // Allocate new map.
   6486   Handle<Map> new_map = Map::CopyDropDescriptors(isolate, old_map);
   6487   if (new_map->has_named_interceptor() || new_map->is_access_check_needed()) {
   6488     // Force certain slow paths when API interceptors are used, or if an access
   6489     // check is required.
   6490     new_map->set_may_have_interesting_symbols(true);
   6491   }
   6492   new_map->set_is_dictionary_map(false);
   6493 
   6494   NotifyMapChange(old_map, new_map, isolate);
   6495 
   6496   if (FLAG_trace_maps) {
   6497     LOG(isolate, MapEvent("SlowToFast", *old_map, *new_map, reason));
   6498   }
   6499 
   6500   if (instance_descriptor_length == 0) {
   6501     DisallowHeapAllocation no_gc;
   6502     DCHECK_LE(unused_property_fields, inobject_props);
   6503     // Transform the object.
   6504     new_map->SetInObjectUnusedPropertyFields(inobject_props);
   6505     object->synchronized_set_map(*new_map);
   6506     object->SetProperties(ReadOnlyRoots(isolate).empty_fixed_array());
   6507     // Check that it really works.
   6508     DCHECK(object->HasFastProperties());
   6509     return;
   6510   }
   6511 
   6512   // Allocate the instance descriptor.
   6513   Handle<DescriptorArray> descriptors = DescriptorArray::Allocate(
   6514       isolate, instance_descriptor_length, 0, TENURED);
   6515 
   6516   int number_of_allocated_fields =
   6517       number_of_fields + unused_property_fields - inobject_props;
   6518   if (number_of_allocated_fields < 0) {
   6519     // There is enough inobject space for all fields (including unused).
   6520     number_of_allocated_fields = 0;
   6521     unused_property_fields = inobject_props - number_of_fields;
   6522   }
   6523 
   6524   // Allocate the property array for the fields.
   6525   Handle<PropertyArray> fields =
   6526       factory->NewPropertyArray(number_of_allocated_fields);
   6527 
   6528   bool is_transitionable_elements_kind =
   6529       IsTransitionableFastElementsKind(old_map->elements_kind());
   6530 
   6531   // Fill in the instance descriptor and the fields.
   6532   int current_offset = 0;
   6533   for (int i = 0; i < instance_descriptor_length; i++) {
   6534     int index = Smi::ToInt(iteration_order->get(i));
   6535     Name* k = dictionary->NameAt(index);
   6536     // Dictionary keys are internalized upon insertion.
   6537     // TODO(jkummerow): Turn this into a DCHECK if it's not hit in the wild.
   6538     CHECK(k->IsUniqueName());
   6539     Handle<Name> key(k, isolate);
   6540 
   6541     // Properly mark the {new_map} if the {key} is an "interesting symbol".
   6542     if (key->IsInterestingSymbol()) {
   6543       new_map->set_may_have_interesting_symbols(true);
   6544     }
   6545 
   6546     Object* value = dictionary->ValueAt(index);
   6547 
   6548     PropertyDetails details = dictionary->DetailsAt(index);
   6549     DCHECK_EQ(kField, details.location());
   6550     DCHECK_EQ(PropertyConstness::kMutable, details.constness());
   6551 
   6552     Descriptor d;
   6553     if (details.kind() == kData) {
   6554       if (!FLAG_track_constant_fields && value->IsJSFunction()) {
   6555         d = Descriptor::DataConstant(key, handle(value, isolate),
   6556                                      details.attributes());
   6557       } else {
   6558         // Ensure that we make constant field only when elements kind is not
   6559         // transitionable.
   6560         PropertyConstness constness =
   6561             FLAG_track_constant_fields && !is_transitionable_elements_kind
   6562                 ? PropertyConstness::kConst
   6563                 : PropertyConstness::kMutable;
   6564         d = Descriptor::DataField(
   6565             key, current_offset, details.attributes(), constness,
   6566             // TODO(verwaest): value->OptimalRepresentation();
   6567             Representation::Tagged(),
   6568             MaybeObjectHandle(FieldType::Any(isolate)));
   6569       }
   6570     } else {
   6571       DCHECK_EQ(kAccessor, details.kind());
   6572       d = Descriptor::AccessorConstant(key, handle(value, isolate),
   6573                                        details.attributes());
   6574     }
   6575     details = d.GetDetails();
   6576     if (details.location() == kField) {
   6577       if (current_offset < inobject_props) {
   6578         object->InObjectPropertyAtPut(current_offset, value,
   6579                                       UPDATE_WRITE_BARRIER);
   6580       } else {
   6581         int offset = current_offset - inobject_props;
   6582         fields->set(offset, value);
   6583       }
   6584       current_offset += details.field_width_in_words();
   6585     }
   6586     descriptors->Set(i, &d);
   6587   }
   6588   DCHECK(current_offset == number_of_fields);
   6589 
   6590   descriptors->Sort();
   6591 
   6592   Handle<LayoutDescriptor> layout_descriptor = LayoutDescriptor::New(
   6593       isolate, new_map, descriptors, descriptors->number_of_descriptors());
   6594 
   6595   DisallowHeapAllocation no_gc;
   6596   new_map->InitializeDescriptors(*descriptors, *layout_descriptor);
   6597   if (number_of_allocated_fields == 0) {
   6598     new_map->SetInObjectUnusedPropertyFields(unused_property_fields);
   6599   } else {
   6600     new_map->SetOutOfObjectUnusedPropertyFields(unused_property_fields);
   6601   }
   6602 
   6603   // Transform the object.
   6604   object->synchronized_set_map(*new_map);
   6605 
   6606   object->SetProperties(*fields);
   6607   DCHECK(object->IsJSObject());
   6608 
   6609   // Check that it really works.
   6610   DCHECK(object->HasFastProperties());
   6611 }
   6612 
   6613 void JSObject::RequireSlowElements(NumberDictionary* dictionary) {
   6614   if (dictionary->requires_slow_elements()) return;
   6615   dictionary->set_requires_slow_elements();
   6616   if (map()->is_prototype_map()) {
   6617     // If this object is a prototype (the callee will check), invalidate any
   6618     // prototype chains involving it.
   6619     InvalidatePrototypeChains(map());
   6620   }
   6621 }
   6622 
   6623 Handle<NumberDictionary> JSObject::NormalizeElements(Handle<JSObject> object) {
   6624   DCHECK(!object->HasFixedTypedArrayElements());
   6625   Isolate* isolate = object->GetIsolate();
   6626   bool is_sloppy_arguments = object->HasSloppyArgumentsElements();
   6627   {
   6628     DisallowHeapAllocation no_gc;
   6629     FixedArrayBase* elements = object->elements();
   6630 
   6631     if (is_sloppy_arguments) {
   6632       elements = SloppyArgumentsElements::cast(elements)->arguments();
   6633     }
   6634 
   6635     if (elements->IsNumberDictionary()) {
   6636       return handle(NumberDictionary::cast(elements), isolate);
   6637     }
   6638   }
   6639 
   6640   DCHECK(object->HasSmiOrObjectElements() || object->HasDoubleElements() ||
   6641          object->HasFastArgumentsElements() ||
   6642          object->HasFastStringWrapperElements());
   6643 
   6644   Handle<NumberDictionary> dictionary =
   6645       object->GetElementsAccessor()->Normalize(object);
   6646 
   6647   // Switch to using the dictionary as the backing storage for elements.
   6648   ElementsKind target_kind = is_sloppy_arguments
   6649                                  ? SLOW_SLOPPY_ARGUMENTS_ELEMENTS
   6650                                  : object->HasFastStringWrapperElements()
   6651                                        ? SLOW_STRING_WRAPPER_ELEMENTS
   6652                                        : DICTIONARY_ELEMENTS;
   6653   Handle<Map> new_map = JSObject::GetElementsTransitionMap(object, target_kind);
   6654   // Set the new map first to satify the elements type assert in set_elements().
   6655   JSObject::MigrateToMap(object, new_map);
   6656 
   6657   if (is_sloppy_arguments) {
   6658     SloppyArgumentsElements::cast(object->elements())
   6659         ->set_arguments(*dictionary);
   6660   } else {
   6661     object->set_elements(*dictionary);
   6662   }
   6663 
   6664   isolate->counters()->elements_to_dictionary()->Increment();
   6665 
   6666 #ifdef DEBUG
   6667   if (FLAG_trace_normalization) {
   6668     StdoutStream os;
   6669     os << "Object elements have been normalized:\n";
   6670     object->Print(os);
   6671   }
   6672 #endif
   6673 
   6674   DCHECK(object->HasDictionaryElements() ||
   6675          object->HasSlowArgumentsElements() ||
   6676          object->HasSlowStringWrapperElements());
   6677   return dictionary;
   6678 }
   6679 
   6680 namespace {
   6681 
   6682 Object* SetHashAndUpdateProperties(Isolate* isolate, HeapObject* properties,
   6683                                    int hash) {
   6684   DCHECK_NE(PropertyArray::kNoHashSentinel, hash);
   6685   DCHECK(PropertyArray::HashField::is_valid(hash));
   6686 
   6687   Heap* heap = isolate->heap();
   6688   ReadOnlyRoots roots(heap);
   6689   if (properties == roots.empty_fixed_array() ||
   6690       properties == roots.empty_property_array() ||
   6691       properties == heap->empty_property_dictionary()) {
   6692     return Smi::FromInt(hash);
   6693   }
   6694 
   6695   if (properties->IsPropertyArray()) {
   6696     PropertyArray::cast(properties)->SetHash(hash);
   6697     DCHECK_LT(0, PropertyArray::cast(properties)->length());
   6698     return properties;
   6699   }
   6700 
   6701   DCHECK(properties->IsNameDictionary());
   6702   NameDictionary::cast(properties)->SetHash(hash);
   6703   return properties;
   6704 }
   6705 
   6706 int GetIdentityHashHelper(Isolate* isolate, JSReceiver* object) {
   6707   DisallowHeapAllocation no_gc;
   6708   Object* properties = object->raw_properties_or_hash();
   6709   if (properties->IsSmi()) {
   6710     return Smi::ToInt(properties);
   6711   }
   6712 
   6713   if (properties->IsPropertyArray()) {
   6714     return PropertyArray::cast(properties)->Hash();
   6715   }
   6716 
   6717   if (properties->IsNameDictionary()) {
   6718     return NameDictionary::cast(properties)->Hash();
   6719   }
   6720 
   6721   if (properties->IsGlobalDictionary()) {
   6722     return GlobalDictionary::cast(properties)->Hash();
   6723   }
   6724 
   6725 #ifdef DEBUG
   6726   FixedArray* empty_fixed_array = ReadOnlyRoots(isolate).empty_fixed_array();
   6727   FixedArray* empty_property_dictionary =
   6728       isolate->heap()->empty_property_dictionary();
   6729   DCHECK(properties == empty_fixed_array ||
   6730          properties == empty_property_dictionary);
   6731 #endif
   6732 
   6733   return PropertyArray::kNoHashSentinel;
   6734 }
   6735 }  // namespace
   6736 
   6737 void JSReceiver::SetIdentityHash(int hash) {
   6738   DisallowHeapAllocation no_gc;
   6739   DCHECK_NE(PropertyArray::kNoHashSentinel, hash);
   6740   DCHECK(PropertyArray::HashField::is_valid(hash));
   6741 
   6742   HeapObject* existing_properties = HeapObject::cast(raw_properties_or_hash());
   6743   Object* new_properties =
   6744       SetHashAndUpdateProperties(GetIsolate(), existing_properties, hash);
   6745   set_raw_properties_or_hash(new_properties);
   6746 }
   6747 
   6748 void JSReceiver::SetProperties(HeapObject* properties) {
   6749   DCHECK_IMPLIES(properties->IsPropertyArray() &&
   6750                      PropertyArray::cast(properties)->length() == 0,
   6751                  properties == GetReadOnlyRoots().empty_property_array());
   6752   DisallowHeapAllocation no_gc;
   6753   Isolate* isolate = GetIsolate();
   6754   int hash = GetIdentityHashHelper(isolate, this);
   6755   Object* new_properties = properties;
   6756 
   6757   // TODO(cbruni): Make GetIdentityHashHelper return a bool so that we
   6758   // don't have to manually compare against kNoHashSentinel.
   6759   if (hash != PropertyArray::kNoHashSentinel) {
   6760     new_properties = SetHashAndUpdateProperties(isolate, properties, hash);
   6761   }
   6762 
   6763   set_raw_properties_or_hash(new_properties);
   6764 }
   6765 
   6766 Object* JSReceiver::GetIdentityHash(Isolate* isolate) {
   6767   DisallowHeapAllocation no_gc;
   6768 
   6769   int hash = GetIdentityHashHelper(isolate, this);
   6770   if (hash == PropertyArray::kNoHashSentinel) {
   6771     return ReadOnlyRoots(isolate).undefined_value();
   6772   }
   6773 
   6774   return Smi::FromInt(hash);
   6775 }
   6776 
   6777 // static
   6778 Smi* JSReceiver::CreateIdentityHash(Isolate* isolate, JSReceiver* key) {
   6779   DisallowHeapAllocation no_gc;
   6780   int hash = isolate->GenerateIdentityHash(PropertyArray::HashField::kMax);
   6781   DCHECK_NE(PropertyArray::kNoHashSentinel, hash);
   6782 
   6783   key->SetIdentityHash(hash);
   6784   return Smi::FromInt(hash);
   6785 }
   6786 
   6787 Smi* JSReceiver::GetOrCreateIdentityHash(Isolate* isolate) {
   6788   DisallowHeapAllocation no_gc;
   6789 
   6790   Object* hash_obj = GetIdentityHash(isolate);
   6791   if (!hash_obj->IsUndefined(isolate)) {
   6792     return Smi::cast(hash_obj);
   6793   }
   6794 
   6795   return JSReceiver::CreateIdentityHash(isolate, this);
   6796 }
   6797 
   6798 Maybe<bool> JSObject::DeletePropertyWithInterceptor(LookupIterator* it,
   6799                                                     ShouldThrow should_throw) {
   6800   Isolate* isolate = it->isolate();
   6801   // Make sure that the top context does not change when doing callbacks or
   6802   // interceptor calls.
   6803   AssertNoContextChange ncc(isolate);
   6804 
   6805   DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
   6806   Handle<InterceptorInfo> interceptor(it->GetInterceptor());
   6807   if (interceptor->deleter()->IsUndefined(isolate)) return Nothing<bool>();
   6808 
   6809   Handle<JSObject> holder = it->GetHolder<JSObject>();
   6810   Handle<Object> receiver = it->GetReceiver();
   6811   if (!receiver->IsJSReceiver()) {
   6812     ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, receiver,
   6813                                      Object::ConvertReceiver(isolate, receiver),
   6814                                      Nothing<bool>());
   6815   }
   6816 
   6817   PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
   6818                                  *holder, should_throw);
   6819   Handle<Object> result;
   6820   if (it->IsElement()) {
   6821     result = args.CallIndexedDeleter(interceptor, it->index());
   6822   } else {
   6823     result = args.CallNamedDeleter(interceptor, it->name());
   6824   }
   6825 
   6826   RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
   6827   if (result.is_null()) return Nothing<bool>();
   6828 
   6829   DCHECK(result->IsBoolean());
   6830   // Rebox CustomArguments::kReturnValueOffset before returning.
   6831   return Just(result->IsTrue(isolate));
   6832 }
   6833 
   6834 void JSReceiver::DeleteNormalizedProperty(Handle<JSReceiver> object,
   6835                                           int entry) {
   6836   DCHECK(!object->HasFastProperties());
   6837   Isolate* isolate = object->GetIsolate();
   6838 
   6839   if (object->IsJSGlobalObject()) {
   6840     // If we have a global object, invalidate the cell and swap in a new one.
   6841     Handle<GlobalDictionary> dictionary(
   6842         JSGlobalObject::cast(*object)->global_dictionary(), isolate);
   6843     DCHECK_NE(GlobalDictionary::kNotFound, entry);
   6844 
   6845     auto cell = PropertyCell::InvalidateEntry(isolate, dictionary, entry);
   6846     cell->set_value(ReadOnlyRoots(isolate).the_hole_value());
   6847     cell->set_property_details(
   6848         PropertyDetails::Empty(PropertyCellType::kUninitialized));
   6849   } else {
   6850     Handle<NameDictionary> dictionary(object->property_dictionary(), isolate);
   6851     DCHECK_NE(NameDictionary::kNotFound, entry);
   6852 
   6853     dictionary = NameDictionary::DeleteEntry(isolate, dictionary, entry);
   6854     object->SetProperties(*dictionary);
   6855   }
   6856   if (object->map()->is_prototype_map()) {
   6857     // Invalidate prototype validity cell as this may invalidate transitioning
   6858     // store IC handlers.
   6859     JSObject::InvalidatePrototypeChains(object->map());
   6860   }
   6861 }
   6862 
   6863 
   6864 Maybe<bool> JSReceiver::DeleteProperty(LookupIterator* it,
   6865                                        LanguageMode language_mode) {
   6866   it->UpdateProtector();
   6867 
   6868   Isolate* isolate = it->isolate();
   6869 
   6870   if (it->state() == LookupIterator::JSPROXY) {
   6871     return JSProxy::DeletePropertyOrElement(it->GetHolder<JSProxy>(),
   6872                                             it->GetName(), language_mode);
   6873   }
   6874 
   6875   if (it->GetReceiver()->IsJSProxy()) {
   6876     if (it->state() != LookupIterator::NOT_FOUND) {
   6877       DCHECK_EQ(LookupIterator::DATA, it->state());
   6878       DCHECK(it->name()->IsPrivate());
   6879       it->Delete();
   6880     }
   6881     return Just(true);
   6882   }
   6883   Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver());
   6884 
   6885   for (; it->IsFound(); it->Next()) {
   6886     switch (it->state()) {
   6887       case LookupIterator::JSPROXY:
   6888       case LookupIterator::NOT_FOUND:
   6889       case LookupIterator::TRANSITION:
   6890         UNREACHABLE();
   6891       case LookupIterator::ACCESS_CHECK:
   6892         if (it->HasAccess()) break;
   6893         isolate->ReportFailedAccessCheck(it->GetHolder<JSObject>());
   6894         RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
   6895         return Just(false);
   6896       case LookupIterator::INTERCEPTOR: {
   6897         ShouldThrow should_throw =
   6898             is_sloppy(language_mode) ? kDontThrow : kThrowOnError;
   6899         Maybe<bool> result =
   6900             JSObject::DeletePropertyWithInterceptor(it, should_throw);
   6901         // An exception was thrown in the interceptor. Propagate.
   6902         if (isolate->has_pending_exception()) return Nothing<bool>();
   6903         // Delete with interceptor succeeded. Return result.
   6904         // TODO(neis): In strict mode, we should probably throw if the
   6905         // interceptor returns false.
   6906         if (result.IsJust()) return result;
   6907         break;
   6908       }
   6909       case LookupIterator::INTEGER_INDEXED_EXOTIC:
   6910         return Just(true);
   6911       case LookupIterator::DATA:
   6912       case LookupIterator::ACCESSOR: {
   6913         if (!it->IsConfigurable()) {
   6914           // Fail if the property is not configurable.
   6915           if (is_strict(language_mode)) {
   6916             isolate->Throw(*isolate->factory()->NewTypeError(
   6917                 MessageTemplate::kStrictDeleteProperty, it->GetName(),
   6918                 receiver));
   6919             return Nothing<bool>();
   6920           }
   6921           return Just(false);
   6922         }
   6923 
   6924         it->Delete();
   6925 
   6926         return Just(true);
   6927       }
   6928     }
   6929   }
   6930 
   6931   return Just(true);
   6932 }
   6933 
   6934 
   6935 Maybe<bool> JSReceiver::DeleteElement(Handle<JSReceiver> object, uint32_t index,
   6936                                       LanguageMode language_mode) {
   6937   LookupIterator it(object->GetIsolate(), object, index, object,
   6938                     LookupIterator::OWN);
   6939   return DeleteProperty(&it, language_mode);
   6940 }
   6941 
   6942 
   6943 Maybe<bool> JSReceiver::DeleteProperty(Handle<JSReceiver> object,
   6944                                        Handle<Name> name,
   6945                                        LanguageMode language_mode) {
   6946   LookupIterator it(object, name, object, LookupIterator::OWN);
   6947   return DeleteProperty(&it, language_mode);
   6948 }
   6949 
   6950 
   6951 Maybe<bool> JSReceiver::DeletePropertyOrElement(Handle<JSReceiver> object,
   6952                                                 Handle<Name> name,
   6953                                                 LanguageMode language_mode) {
   6954   LookupIterator it = LookupIterator::PropertyOrElement(
   6955       object->GetIsolate(), object, name, object, LookupIterator::OWN);
   6956   return DeleteProperty(&it, language_mode);
   6957 }
   6958 
   6959 // ES6 19.1.2.4
   6960 // static
   6961 Object* JSReceiver::DefineProperty(Isolate* isolate, Handle<Object> object,
   6962                                    Handle<Object> key,
   6963                                    Handle<Object> attributes) {
   6964   // 1. If Type(O) is not Object, throw a TypeError exception.
   6965   if (!object->IsJSReceiver()) {
   6966     Handle<String> fun_name =
   6967         isolate->factory()->InternalizeUtf8String("Object.defineProperty");
   6968     THROW_NEW_ERROR_RETURN_FAILURE(
   6969         isolate, NewTypeError(MessageTemplate::kCalledOnNonObject, fun_name));
   6970   }
   6971   // 2. Let key be ToPropertyKey(P).
   6972   // 3. ReturnIfAbrupt(key).
   6973   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, key, ToPropertyKey(isolate, key));
   6974   // 4. Let desc be ToPropertyDescriptor(Attributes).
   6975   // 5. ReturnIfAbrupt(desc).
   6976   PropertyDescriptor desc;
   6977   if (!PropertyDescriptor::ToPropertyDescriptor(isolate, attributes, &desc)) {
   6978     return ReadOnlyRoots(isolate).exception();
   6979   }
   6980   // 6. Let success be DefinePropertyOrThrow(O,key, desc).
   6981   Maybe<bool> success = DefineOwnProperty(
   6982       isolate, Handle<JSReceiver>::cast(object), key, &desc, kThrowOnError);
   6983   // 7. ReturnIfAbrupt(success).
   6984   MAYBE_RETURN(success, ReadOnlyRoots(isolate).exception());
   6985   CHECK(success.FromJust());
   6986   // 8. Return O.
   6987   return *object;
   6988 }
   6989 
   6990 
   6991 // ES6 19.1.2.3.1
   6992 // static
   6993 MaybeHandle<Object> JSReceiver::DefineProperties(Isolate* isolate,
   6994                                                  Handle<Object> object,
   6995                                                  Handle<Object> properties) {
   6996   // 1. If Type(O) is not Object, throw a TypeError exception.
   6997   if (!object->IsJSReceiver()) {
   6998     Handle<String> fun_name =
   6999         isolate->factory()->InternalizeUtf8String("Object.defineProperties");
   7000     THROW_NEW_ERROR(isolate,
   7001                     NewTypeError(MessageTemplate::kCalledOnNonObject, fun_name),
   7002                     Object);
   7003   }
   7004   // 2. Let props be ToObject(Properties).
   7005   // 3. ReturnIfAbrupt(props).
   7006   Handle<JSReceiver> props;
   7007   ASSIGN_RETURN_ON_EXCEPTION(isolate, props,
   7008                              Object::ToObject(isolate, properties), Object);
   7009 
   7010   // 4. Let keys be props.[[OwnPropertyKeys]]().
   7011   // 5. ReturnIfAbrupt(keys).
   7012   Handle<FixedArray> keys;
   7013   ASSIGN_RETURN_ON_EXCEPTION(
   7014       isolate, keys, KeyAccumulator::GetKeys(props, KeyCollectionMode::kOwnOnly,
   7015                                              ALL_PROPERTIES),
   7016       Object);
   7017   // 6. Let descriptors be an empty List.
   7018   int capacity = keys->length();
   7019   std::vector<PropertyDescriptor> descriptors(capacity);
   7020   size_t descriptors_index = 0;
   7021   // 7. Repeat for each element nextKey of keys in List order,
   7022   for (int i = 0; i < keys->length(); ++i) {
   7023     Handle<Object> next_key(keys->get(i), isolate);
   7024     // 7a. Let propDesc be props.[[GetOwnProperty]](nextKey).
   7025     // 7b. ReturnIfAbrupt(propDesc).
   7026     bool success = false;
   7027     LookupIterator it = LookupIterator::PropertyOrElement(
   7028         isolate, props, next_key, &success, LookupIterator::OWN);
   7029     DCHECK(success);
   7030     Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
   7031     if (maybe.IsNothing()) return MaybeHandle<Object>();
   7032     PropertyAttributes attrs = maybe.FromJust();
   7033     // 7c. If propDesc is not undefined and propDesc.[[Enumerable]] is true:
   7034     if (attrs == ABSENT) continue;
   7035     if (attrs & DONT_ENUM) continue;
   7036     // 7c i. Let descObj be Get(props, nextKey).
   7037     // 7c ii. ReturnIfAbrupt(descObj).
   7038     Handle<Object> desc_obj;
   7039     ASSIGN_RETURN_ON_EXCEPTION(isolate, desc_obj, Object::GetProperty(&it),
   7040                                Object);
   7041     // 7c iii. Let desc be ToPropertyDescriptor(descObj).
   7042     success = PropertyDescriptor::ToPropertyDescriptor(
   7043         isolate, desc_obj, &descriptors[descriptors_index]);
   7044     // 7c iv. ReturnIfAbrupt(desc).
   7045     if (!success) return MaybeHandle<Object>();
   7046     // 7c v. Append the pair (a two element List) consisting of nextKey and
   7047     //       desc to the end of descriptors.
   7048     descriptors[descriptors_index].set_name(next_key);
   7049     descriptors_index++;
   7050   }
   7051   // 8. For each pair from descriptors in list order,
   7052   for (size_t i = 0; i < descriptors_index; ++i) {
   7053     PropertyDescriptor* desc = &descriptors[i];
   7054     // 8a. Let P be the first element of pair.
   7055     // 8b. Let desc be the second element of pair.
   7056     // 8c. Let status be DefinePropertyOrThrow(O, P, desc).
   7057     Maybe<bool> status =
   7058         DefineOwnProperty(isolate, Handle<JSReceiver>::cast(object),
   7059                           desc->name(), desc, kThrowOnError);
   7060     // 8d. ReturnIfAbrupt(status).
   7061     if (status.IsNothing()) return MaybeHandle<Object>();
   7062     CHECK(status.FromJust());
   7063   }
   7064   // 9. Return o.
   7065   return object;
   7066 }
   7067 
   7068 // static
   7069 Maybe<bool> JSReceiver::DefineOwnProperty(Isolate* isolate,
   7070                                           Handle<JSReceiver> object,
   7071                                           Handle<Object> key,
   7072                                           PropertyDescriptor* desc,
   7073                                           ShouldThrow should_throw) {
   7074   if (object->IsJSArray()) {
   7075     return JSArray::DefineOwnProperty(isolate, Handle<JSArray>::cast(object),
   7076                                       key, desc, should_throw);
   7077   }
   7078   if (object->IsJSProxy()) {
   7079     return JSProxy::DefineOwnProperty(isolate, Handle<JSProxy>::cast(object),
   7080                                       key, desc, should_throw);
   7081   }
   7082   if (object->IsJSTypedArray()) {
   7083     return JSTypedArray::DefineOwnProperty(
   7084         isolate, Handle<JSTypedArray>::cast(object), key, desc, should_throw);
   7085   }
   7086 
   7087   // OrdinaryDefineOwnProperty, by virtue of calling
   7088   // DefineOwnPropertyIgnoreAttributes, can handle arguments
   7089   // (ES#sec-arguments-exotic-objects-defineownproperty-p-desc).
   7090   return OrdinaryDefineOwnProperty(isolate, Handle<JSObject>::cast(object), key,
   7091                                    desc, should_throw);
   7092 }
   7093 
   7094 
   7095 // static
   7096 Maybe<bool> JSReceiver::OrdinaryDefineOwnProperty(Isolate* isolate,
   7097                                                   Handle<JSObject> object,
   7098                                                   Handle<Object> key,
   7099                                                   PropertyDescriptor* desc,
   7100                                                   ShouldThrow should_throw) {
   7101   bool success = false;
   7102   DCHECK(key->IsName() || key->IsNumber());  // |key| is a PropertyKey...
   7103   LookupIterator it = LookupIterator::PropertyOrElement(
   7104       isolate, object, key, &success, LookupIterator::OWN);
   7105   DCHECK(success);  // ...so creating a LookupIterator can't fail.
   7106 
   7107   // Deal with access checks first.
   7108   if (it.state() == LookupIterator::ACCESS_CHECK) {
   7109     if (!it.HasAccess()) {
   7110       isolate->ReportFailedAccessCheck(it.GetHolder<JSObject>());
   7111       RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
   7112       return Just(true);
   7113     }
   7114     it.Next();
   7115   }
   7116 
   7117   return OrdinaryDefineOwnProperty(&it, desc, should_throw);
   7118 }
   7119 
   7120 
   7121 // ES6 9.1.6.1
   7122 // static
   7123 Maybe<bool> JSReceiver::OrdinaryDefineOwnProperty(LookupIterator* it,
   7124                                                   PropertyDescriptor* desc,
   7125                                                   ShouldThrow should_throw) {
   7126   Isolate* isolate = it->isolate();
   7127   // 1. Let current be O.[[GetOwnProperty]](P).
   7128   // 2. ReturnIfAbrupt(current).
   7129   PropertyDescriptor current;
   7130   MAYBE_RETURN(GetOwnPropertyDescriptor(it, &current), Nothing<bool>());
   7131 
   7132   it->Restart();
   7133   // Handle interceptor
   7134   for (; it->IsFound(); it->Next()) {
   7135     if (it->state() == LookupIterator::INTERCEPTOR) {
   7136       if (it->HolderIsReceiverOrHiddenPrototype()) {
   7137         Maybe<bool> result = DefinePropertyWithInterceptorInternal(
   7138             it, it->GetInterceptor(), should_throw, *desc);
   7139         if (result.IsNothing() || result.FromJust()) {
   7140           return result;
   7141         }
   7142       }
   7143     }
   7144   }
   7145 
   7146   // TODO(jkummerow/verwaest): It would be nice if we didn't have to reset
   7147   // the iterator every time. Currently, the reasons why we need it are:
   7148   // - handle interceptors correctly
   7149   // - handle accessors correctly (which might change the holder's map)
   7150   it->Restart();
   7151   // 3. Let extensible be the value of the [[Extensible]] internal slot of O.
   7152   Handle<JSObject> object = Handle<JSObject>::cast(it->GetReceiver());
   7153   bool extensible = JSObject::IsExtensible(object);
   7154 
   7155   return ValidateAndApplyPropertyDescriptor(
   7156       isolate, it, extensible, desc, &current, should_throw, Handle<Name>());
   7157 }
   7158 
   7159 
   7160 // ES6 9.1.6.2
   7161 // static
   7162 Maybe<bool> JSReceiver::IsCompatiblePropertyDescriptor(
   7163     Isolate* isolate, bool extensible, PropertyDescriptor* desc,
   7164     PropertyDescriptor* current, Handle<Name> property_name,
   7165     ShouldThrow should_throw) {
   7166   // 1. Return ValidateAndApplyPropertyDescriptor(undefined, undefined,
   7167   //    Extensible, Desc, Current).
   7168   return ValidateAndApplyPropertyDescriptor(
   7169       isolate, nullptr, extensible, desc, current, should_throw, property_name);
   7170 }
   7171 
   7172 
   7173 // ES6 9.1.6.3
   7174 // static
   7175 Maybe<bool> JSReceiver::ValidateAndApplyPropertyDescriptor(
   7176     Isolate* isolate, LookupIterator* it, bool extensible,
   7177     PropertyDescriptor* desc, PropertyDescriptor* current,
   7178     ShouldThrow should_throw, Handle<Name> property_name) {
   7179   // We either need a LookupIterator, or a property name.
   7180   DCHECK((it == nullptr) != property_name.is_null());
   7181   Handle<JSObject> object;
   7182   if (it != nullptr) object = Handle<JSObject>::cast(it->GetReceiver());
   7183   bool desc_is_data_descriptor = PropertyDescriptor::IsDataDescriptor(desc);
   7184   bool desc_is_accessor_descriptor =
   7185       PropertyDescriptor::IsAccessorDescriptor(desc);
   7186   bool desc_is_generic_descriptor =
   7187       PropertyDescriptor::IsGenericDescriptor(desc);
   7188   // 1. (Assert)
   7189   // 2. If current is undefined, then
   7190   if (current->is_empty()) {
   7191     // 2a. If extensible is false, return false.
   7192     if (!extensible) {
   7193       RETURN_FAILURE(
   7194           isolate, should_throw,
   7195           NewTypeError(MessageTemplate::kDefineDisallowed,
   7196                        it != nullptr ? it->GetName() : property_name));
   7197     }
   7198     // 2c. If IsGenericDescriptor(Desc) or IsDataDescriptor(Desc) is true, then:
   7199     // (This is equivalent to !IsAccessorDescriptor(desc).)
   7200     DCHECK((desc_is_generic_descriptor || desc_is_data_descriptor) ==
   7201            !desc_is_accessor_descriptor);
   7202     if (!desc_is_accessor_descriptor) {
   7203       // 2c i. If O is not undefined, create an own data property named P of
   7204       // object O whose [[Value]], [[Writable]], [[Enumerable]] and
   7205       // [[Configurable]] attribute values are described by Desc. If the value
   7206       // of an attribute field of Desc is absent, the attribute of the newly
   7207       // created property is set to its default value.
   7208       if (it != nullptr) {
   7209         if (!desc->has_writable()) desc->set_writable(false);
   7210         if (!desc->has_enumerable()) desc->set_enumerable(false);
   7211         if (!desc->has_configurable()) desc->set_configurable(false);
   7212         Handle<Object> value(
   7213             desc->has_value()
   7214                 ? desc->value()
   7215                 : Handle<Object>::cast(isolate->factory()->undefined_value()));
   7216         MaybeHandle<Object> result =
   7217             JSObject::DefineOwnPropertyIgnoreAttributes(it, value,
   7218                                                         desc->ToAttributes());
   7219         if (result.is_null()) return Nothing<bool>();
   7220       }
   7221     } else {
   7222       // 2d. Else Desc must be an accessor Property Descriptor,
   7223       DCHECK(desc_is_accessor_descriptor);
   7224       // 2d i. If O is not undefined, create an own accessor property named P
   7225       // of object O whose [[Get]], [[Set]], [[Enumerable]] and
   7226       // [[Configurable]] attribute values are described by Desc. If the value
   7227       // of an attribute field of Desc is absent, the attribute of the newly
   7228       // created property is set to its default value.
   7229       if (it != nullptr) {
   7230         if (!desc->has_enumerable()) desc->set_enumerable(false);
   7231         if (!desc->has_configurable()) desc->set_configurable(false);
   7232         Handle<Object> getter(
   7233             desc->has_get()
   7234                 ? desc->get()
   7235                 : Handle<Object>::cast(isolate->factory()->null_value()));
   7236         Handle<Object> setter(
   7237             desc->has_set()
   7238                 ? desc->set()
   7239                 : Handle<Object>::cast(isolate->factory()->null_value()));
   7240         MaybeHandle<Object> result =
   7241             JSObject::DefineAccessor(it, getter, setter, desc->ToAttributes());
   7242         if (result.is_null()) return Nothing<bool>();
   7243       }
   7244     }
   7245     // 2e. Return true.
   7246     return Just(true);
   7247   }
   7248   // 3. Return true, if every field in Desc is absent.
   7249   // 4. Return true, if every field in Desc also occurs in current and the
   7250   // value of every field in Desc is the same value as the corresponding field
   7251   // in current when compared using the SameValue algorithm.
   7252   if ((!desc->has_enumerable() ||
   7253        desc->enumerable() == current->enumerable()) &&
   7254       (!desc->has_configurable() ||
   7255        desc->configurable() == current->configurable()) &&
   7256       (!desc->has_value() ||
   7257        (current->has_value() && current->value()->SameValue(*desc->value()))) &&
   7258       (!desc->has_writable() ||
   7259        (current->has_writable() && current->writable() == desc->writable())) &&
   7260       (!desc->has_get() ||
   7261        (current->has_get() && current->get()->SameValue(*desc->get()))) &&
   7262       (!desc->has_set() ||
   7263        (current->has_set() && current->set()->SameValue(*desc->set())))) {
   7264     return Just(true);
   7265   }
   7266   // 5. If the [[Configurable]] field of current is false, then
   7267   if (!current->configurable()) {
   7268     // 5a. Return false, if the [[Configurable]] field of Desc is true.
   7269     if (desc->has_configurable() && desc->configurable()) {
   7270       RETURN_FAILURE(
   7271           isolate, should_throw,
   7272           NewTypeError(MessageTemplate::kRedefineDisallowed,
   7273                        it != nullptr ? it->GetName() : property_name));
   7274     }
   7275     // 5b. Return false, if the [[Enumerable]] field of Desc is present and the
   7276     // [[Enumerable]] fields of current and Desc are the Boolean negation of
   7277     // each other.
   7278     if (desc->has_enumerable() && desc->enumerable() != current->enumerable()) {
   7279       RETURN_FAILURE(
   7280           isolate, should_throw,
   7281           NewTypeError(MessageTemplate::kRedefineDisallowed,
   7282                        it != nullptr ? it->GetName() : property_name));
   7283     }
   7284   }
   7285 
   7286   bool current_is_data_descriptor =
   7287       PropertyDescriptor::IsDataDescriptor(current);
   7288   // 6. If IsGenericDescriptor(Desc) is true, no further validation is required.
   7289   if (desc_is_generic_descriptor) {
   7290     // Nothing to see here.
   7291 
   7292     // 7. Else if IsDataDescriptor(current) and IsDataDescriptor(Desc) have
   7293     // different results, then:
   7294   } else if (current_is_data_descriptor != desc_is_data_descriptor) {
   7295     // 7a. Return false, if the [[Configurable]] field of current is false.
   7296     if (!current->configurable()) {
   7297       RETURN_FAILURE(
   7298           isolate, should_throw,
   7299           NewTypeError(MessageTemplate::kRedefineDisallowed,
   7300                        it != nullptr ? it->GetName() : property_name));
   7301     }
   7302     // 7b. If IsDataDescriptor(current) is true, then:
   7303     if (current_is_data_descriptor) {
   7304       // 7b i. If O is not undefined, convert the property named P of object O
   7305       // from a data property to an accessor property. Preserve the existing
   7306       // values of the converted property's [[Configurable]] and [[Enumerable]]
   7307       // attributes and set the rest of the property's attributes to their
   7308       // default values.
   7309       // --> Folded into step 10.
   7310     } else {
   7311       // 7c i. If O is not undefined, convert the property named P of object O
   7312       // from an accessor property to a data property. Preserve the existing
   7313       // values of the converted propertys [[Configurable]] and [[Enumerable]]
   7314       // attributes and set the rest of the propertys attributes to their
   7315       // default values.
   7316       // --> Folded into step 10.
   7317     }
   7318 
   7319     // 8. Else if IsDataDescriptor(current) and IsDataDescriptor(Desc) are both
   7320     // true, then:
   7321   } else if (current_is_data_descriptor && desc_is_data_descriptor) {
   7322     // 8a. If the [[Configurable]] field of current is false, then:
   7323     if (!current->configurable()) {
   7324       // 8a i. Return false, if the [[Writable]] field of current is false and
   7325       // the [[Writable]] field of Desc is true.
   7326       if (!current->writable() && desc->has_writable() && desc->writable()) {
   7327         RETURN_FAILURE(
   7328             isolate, should_throw,
   7329             NewTypeError(MessageTemplate::kRedefineDisallowed,
   7330                          it != nullptr ? it->GetName() : property_name));
   7331       }
   7332       // 8a ii. If the [[Writable]] field of current is false, then:
   7333       if (!current->writable()) {
   7334         // 8a ii 1. Return false, if the [[Value]] field of Desc is present and
   7335         // SameValue(Desc.[[Value]], current.[[Value]]) is false.
   7336         if (desc->has_value() && !desc->value()->SameValue(*current->value())) {
   7337           RETURN_FAILURE(
   7338               isolate, should_throw,
   7339               NewTypeError(MessageTemplate::kRedefineDisallowed,
   7340                            it != nullptr ? it->GetName() : property_name));
   7341         }
   7342       }
   7343     }
   7344   } else {
   7345     // 9. Else IsAccessorDescriptor(current) and IsAccessorDescriptor(Desc)
   7346     // are both true,
   7347     DCHECK(PropertyDescriptor::IsAccessorDescriptor(current) &&
   7348            desc_is_accessor_descriptor);
   7349     // 9a. If the [[Configurable]] field of current is false, then:
   7350     if (!current->configurable()) {
   7351       // 9a i. Return false, if the [[Set]] field of Desc is present and
   7352       // SameValue(Desc.[[Set]], current.[[Set]]) is false.
   7353       if (desc->has_set() && !desc->set()->SameValue(*current->set())) {
   7354         RETURN_FAILURE(
   7355             isolate, should_throw,
   7356             NewTypeError(MessageTemplate::kRedefineDisallowed,
   7357                          it != nullptr ? it->GetName() : property_name));
   7358       }
   7359       // 9a ii. Return false, if the [[Get]] field of Desc is present and
   7360       // SameValue(Desc.[[Get]], current.[[Get]]) is false.
   7361       if (desc->has_get() && !desc->get()->SameValue(*current->get())) {
   7362         RETURN_FAILURE(
   7363             isolate, should_throw,
   7364             NewTypeError(MessageTemplate::kRedefineDisallowed,
   7365                          it != nullptr ? it->GetName() : property_name));
   7366       }
   7367     }
   7368   }
   7369 
   7370   // 10. If O is not undefined, then:
   7371   if (it != nullptr) {
   7372     // 10a. For each field of Desc that is present, set the corresponding
   7373     // attribute of the property named P of object O to the value of the field.
   7374     PropertyAttributes attrs = NONE;
   7375 
   7376     if (desc->has_enumerable()) {
   7377       attrs = static_cast<PropertyAttributes>(
   7378           attrs | (desc->enumerable() ? NONE : DONT_ENUM));
   7379     } else {
   7380       attrs = static_cast<PropertyAttributes>(
   7381           attrs | (current->enumerable() ? NONE : DONT_ENUM));
   7382     }
   7383     if (desc->has_configurable()) {
   7384       attrs = static_cast<PropertyAttributes>(
   7385           attrs | (desc->configurable() ? NONE : DONT_DELETE));
   7386     } else {
   7387       attrs = static_cast<PropertyAttributes>(
   7388           attrs | (current->configurable() ? NONE : DONT_DELETE));
   7389     }
   7390     if (desc_is_data_descriptor ||
   7391         (desc_is_generic_descriptor && current_is_data_descriptor)) {
   7392       if (desc->has_writable()) {
   7393         attrs = static_cast<PropertyAttributes>(
   7394             attrs | (desc->writable() ? NONE : READ_ONLY));
   7395       } else {
   7396         attrs = static_cast<PropertyAttributes>(
   7397             attrs | (current->writable() ? NONE : READ_ONLY));
   7398       }
   7399       Handle<Object> value(
   7400           desc->has_value() ? desc->value()
   7401                             : current->has_value()
   7402                                   ? current->value()
   7403                                   : Handle<Object>::cast(
   7404                                         isolate->factory()->undefined_value()));
   7405       return JSObject::DefineOwnPropertyIgnoreAttributes(it, value, attrs,
   7406                                                          should_throw);
   7407     } else {
   7408       DCHECK(desc_is_accessor_descriptor ||
   7409              (desc_is_generic_descriptor &&
   7410               PropertyDescriptor::IsAccessorDescriptor(current)));
   7411       Handle<Object> getter(
   7412           desc->has_get()
   7413               ? desc->get()
   7414               : current->has_get()
   7415                     ? current->get()
   7416                     : Handle<Object>::cast(isolate->factory()->null_value()));
   7417       Handle<Object> setter(
   7418           desc->has_set()
   7419               ? desc->set()
   7420               : current->has_set()
   7421                     ? current->set()
   7422                     : Handle<Object>::cast(isolate->factory()->null_value()));
   7423       MaybeHandle<Object> result =
   7424           JSObject::DefineAccessor(it, getter, setter, attrs);
   7425       if (result.is_null()) return Nothing<bool>();
   7426     }
   7427   }
   7428 
   7429   // 11. Return true.
   7430   return Just(true);
   7431 }
   7432 
   7433 // static
   7434 Maybe<bool> JSReceiver::CreateDataProperty(Isolate* isolate,
   7435                                            Handle<JSReceiver> object,
   7436                                            Handle<Name> key,
   7437                                            Handle<Object> value,
   7438                                            ShouldThrow should_throw) {
   7439   LookupIterator it = LookupIterator::PropertyOrElement(isolate, object, key,
   7440                                                         LookupIterator::OWN);
   7441   return CreateDataProperty(&it, value, should_throw);
   7442 }
   7443 
   7444 // static
   7445 Maybe<bool> JSReceiver::CreateDataProperty(LookupIterator* it,
   7446                                            Handle<Object> value,
   7447                                            ShouldThrow should_throw) {
   7448   DCHECK(!it->check_prototype_chain());
   7449   Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(it->GetReceiver());
   7450   Isolate* isolate = receiver->GetIsolate();
   7451 
   7452   if (receiver->IsJSObject()) {
   7453     return JSObject::CreateDataProperty(it, value, should_throw);  // Shortcut.
   7454   }
   7455 
   7456   PropertyDescriptor new_desc;
   7457   new_desc.set_value(value);
   7458   new_desc.set_writable(true);
   7459   new_desc.set_enumerable(true);
   7460   new_desc.set_configurable(true);
   7461 
   7462   return JSReceiver::DefineOwnProperty(isolate, receiver, it->GetName(),
   7463                                        &new_desc, should_throw);
   7464 }
   7465 
   7466 Maybe<bool> JSObject::CreateDataProperty(LookupIterator* it,
   7467                                          Handle<Object> value,
   7468                                          ShouldThrow should_throw) {
   7469   DCHECK(it->GetReceiver()->IsJSObject());
   7470   MAYBE_RETURN(JSReceiver::GetPropertyAttributes(it), Nothing<bool>());
   7471   Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(it->GetReceiver());
   7472   Isolate* isolate = receiver->GetIsolate();
   7473 
   7474   if (it->IsFound()) {
   7475     Maybe<PropertyAttributes> attributes = GetPropertyAttributes(it);
   7476     MAYBE_RETURN(attributes, Nothing<bool>());
   7477     if ((attributes.FromJust() & DONT_DELETE) != 0) {
   7478       RETURN_FAILURE(
   7479           isolate, should_throw,
   7480           NewTypeError(MessageTemplate::kRedefineDisallowed, it->GetName()));
   7481     }
   7482   } else {
   7483     if (!JSObject::IsExtensible(Handle<JSObject>::cast(it->GetReceiver()))) {
   7484       RETURN_FAILURE(
   7485           isolate, should_throw,
   7486           NewTypeError(MessageTemplate::kDefineDisallowed, it->GetName()));
   7487     }
   7488   }
   7489 
   7490   RETURN_ON_EXCEPTION_VALUE(it->isolate(),
   7491                             DefineOwnPropertyIgnoreAttributes(it, value, NONE),
   7492                             Nothing<bool>());
   7493 
   7494   return Just(true);
   7495 }
   7496 
   7497 // TODO(jkummerow): Consider unification with FastAsArrayLength() in
   7498 // accessors.cc.
   7499 bool PropertyKeyToArrayLength(Handle<Object> value, uint32_t* length) {
   7500   DCHECK(value->IsNumber() || value->IsName());
   7501   if (value->ToArrayLength(length)) return true;
   7502   if (value->IsString()) return String::cast(*value)->AsArrayIndex(length);
   7503   return false;
   7504 }
   7505 
   7506 bool PropertyKeyToArrayIndex(Handle<Object> index_obj, uint32_t* output) {
   7507   return PropertyKeyToArrayLength(index_obj, output) && *output != kMaxUInt32;
   7508 }
   7509 
   7510 
   7511 // ES6 9.4.2.1
   7512 // static
   7513 Maybe<bool> JSArray::DefineOwnProperty(Isolate* isolate, Handle<JSArray> o,
   7514                                        Handle<Object> name,
   7515                                        PropertyDescriptor* desc,
   7516                                        ShouldThrow should_throw) {
   7517   // 1. Assert: IsPropertyKey(P) is true. ("P" is |name|.)
   7518   // 2. If P is "length", then:
   7519   // TODO(jkummerow): Check if we need slow string comparison.
   7520   if (*name == ReadOnlyRoots(isolate).length_string()) {
   7521     // 2a. Return ArraySetLength(A, Desc).
   7522     return ArraySetLength(isolate, o, desc, should_throw);
   7523   }
   7524   // 3. Else if P is an array index, then:
   7525   uint32_t index = 0;
   7526   if (PropertyKeyToArrayIndex(name, &index)) {
   7527     // 3a. Let oldLenDesc be OrdinaryGetOwnProperty(A, "length").
   7528     PropertyDescriptor old_len_desc;
   7529     Maybe<bool> success = GetOwnPropertyDescriptor(
   7530         isolate, o, isolate->factory()->length_string(), &old_len_desc);
   7531     // 3b. (Assert)
   7532     DCHECK(success.FromJust());
   7533     USE(success);
   7534     // 3c. Let oldLen be oldLenDesc.[[Value]].
   7535     uint32_t old_len = 0;
   7536     CHECK(old_len_desc.value()->ToArrayLength(&old_len));
   7537     // 3d. Let index be ToUint32(P).
   7538     // (Already done above.)
   7539     // 3e. (Assert)
   7540     // 3f. If index >= oldLen and oldLenDesc.[[Writable]] is false,
   7541     //     return false.
   7542     if (index >= old_len && old_len_desc.has_writable() &&
   7543         !old_len_desc.writable()) {
   7544       RETURN_FAILURE(isolate, should_throw,
   7545                      NewTypeError(MessageTemplate::kDefineDisallowed, name));
   7546     }
   7547     // 3g. Let succeeded be OrdinaryDefineOwnProperty(A, P, Desc).
   7548     Maybe<bool> succeeded =
   7549         OrdinaryDefineOwnProperty(isolate, o, name, desc, should_throw);
   7550     // 3h. Assert: succeeded is not an abrupt completion.
   7551     //     In our case, if should_throw == kThrowOnError, it can be!
   7552     // 3i. If succeeded is false, return false.
   7553     if (succeeded.IsNothing() || !succeeded.FromJust()) return succeeded;
   7554     // 3j. If index >= oldLen, then:
   7555     if (index >= old_len) {
   7556       // 3j i. Set oldLenDesc.[[Value]] to index + 1.
   7557       old_len_desc.set_value(isolate->factory()->NewNumberFromUint(index + 1));
   7558       // 3j ii. Let succeeded be
   7559       //        OrdinaryDefineOwnProperty(A, "length", oldLenDesc).
   7560       succeeded = OrdinaryDefineOwnProperty(isolate, o,
   7561                                             isolate->factory()->length_string(),
   7562                                             &old_len_desc, should_throw);
   7563       // 3j iii. Assert: succeeded is true.
   7564       DCHECK(succeeded.FromJust());
   7565       USE(succeeded);
   7566     }
   7567     // 3k. Return true.
   7568     return Just(true);
   7569   }
   7570 
   7571   // 4. Return OrdinaryDefineOwnProperty(A, P, Desc).
   7572   return OrdinaryDefineOwnProperty(isolate, o, name, desc, should_throw);
   7573 }
   7574 
   7575 
   7576 // Part of ES6 9.4.2.4 ArraySetLength.
   7577 // static
   7578 bool JSArray::AnythingToArrayLength(Isolate* isolate,
   7579                                     Handle<Object> length_object,
   7580                                     uint32_t* output) {
   7581   // Fast path: check numbers and strings that can be converted directly
   7582   // and unobservably.
   7583   if (length_object->ToArrayLength(output)) return true;
   7584   if (length_object->IsString() &&
   7585       Handle<String>::cast(length_object)->AsArrayIndex(output)) {
   7586     return true;
   7587   }
   7588   // Slow path: follow steps in ES6 9.4.2.4 "ArraySetLength".
   7589   // 3. Let newLen be ToUint32(Desc.[[Value]]).
   7590   Handle<Object> uint32_v;
   7591   if (!Object::ToUint32(isolate, length_object).ToHandle(&uint32_v)) {
   7592     // 4. ReturnIfAbrupt(newLen).
   7593     return false;
   7594   }
   7595   // 5. Let numberLen be ToNumber(Desc.[[Value]]).
   7596   Handle<Object> number_v;
   7597   if (!Object::ToNumber(isolate, length_object).ToHandle(&number_v)) {
   7598     // 6. ReturnIfAbrupt(newLen).
   7599     return false;
   7600   }
   7601   // 7. If newLen != numberLen, throw a RangeError exception.
   7602   if (uint32_v->Number() != number_v->Number()) {
   7603     Handle<Object> exception =
   7604         isolate->factory()->NewRangeError(MessageTemplate::kInvalidArrayLength);
   7605     isolate->Throw(*exception);
   7606     return false;
   7607   }
   7608   CHECK(uint32_v->ToArrayLength(output));
   7609   return true;
   7610 }
   7611 
   7612 
   7613 // ES6 9.4.2.4
   7614 // static
   7615 Maybe<bool> JSArray::ArraySetLength(Isolate* isolate, Handle<JSArray> a,
   7616                                     PropertyDescriptor* desc,
   7617                                     ShouldThrow should_throw) {
   7618   // 1. If the [[Value]] field of Desc is absent, then
   7619   if (!desc->has_value()) {
   7620     // 1a. Return OrdinaryDefineOwnProperty(A, "length", Desc).
   7621     return OrdinaryDefineOwnProperty(
   7622         isolate, a, isolate->factory()->length_string(), desc, should_throw);
   7623   }
   7624   // 2. Let newLenDesc be a copy of Desc.
   7625   // (Actual copying is not necessary.)
   7626   PropertyDescriptor* new_len_desc = desc;
   7627   // 3. - 7. Convert Desc.[[Value]] to newLen.
   7628   uint32_t new_len = 0;
   7629   if (!AnythingToArrayLength(isolate, desc->value(), &new_len)) {
   7630     DCHECK(isolate->has_pending_exception());
   7631     return Nothing<bool>();
   7632   }
   7633   // 8. Set newLenDesc.[[Value]] to newLen.
   7634   // (Done below, if needed.)
   7635   // 9. Let oldLenDesc be OrdinaryGetOwnProperty(A, "length").
   7636   PropertyDescriptor old_len_desc;
   7637   Maybe<bool> success = GetOwnPropertyDescriptor(
   7638       isolate, a, isolate->factory()->length_string(), &old_len_desc);
   7639   // 10. (Assert)
   7640   DCHECK(success.FromJust());
   7641   USE(success);
   7642   // 11. Let oldLen be oldLenDesc.[[Value]].
   7643   uint32_t old_len = 0;
   7644   CHECK(old_len_desc.value()->ToArrayLength(&old_len));
   7645   // 12. If newLen >= oldLen, then
   7646   if (new_len >= old_len) {
   7647     // 8. Set newLenDesc.[[Value]] to newLen.
   7648     // 12a. Return OrdinaryDefineOwnProperty(A, "length", newLenDesc).
   7649     new_len_desc->set_value(isolate->factory()->NewNumberFromUint(new_len));
   7650     return OrdinaryDefineOwnProperty(isolate, a,
   7651                                      isolate->factory()->length_string(),
   7652                                      new_len_desc, should_throw);
   7653   }
   7654   // 13. If oldLenDesc.[[Writable]] is false, return false.
   7655   if (!old_len_desc.writable()) {
   7656     RETURN_FAILURE(isolate, should_throw,
   7657                    NewTypeError(MessageTemplate::kRedefineDisallowed,
   7658                                 isolate->factory()->length_string()));
   7659   }
   7660   // 14. If newLenDesc.[[Writable]] is absent or has the value true,
   7661   // let newWritable be true.
   7662   bool new_writable = false;
   7663   if (!new_len_desc->has_writable() || new_len_desc->writable()) {
   7664     new_writable = true;
   7665   } else {
   7666     // 15. Else,
   7667     // 15a. Need to defer setting the [[Writable]] attribute to false in case
   7668     //      any elements cannot be deleted.
   7669     // 15b. Let newWritable be false. (It's initialized as "false" anyway.)
   7670     // 15c. Set newLenDesc.[[Writable]] to true.
   7671     // (Not needed.)
   7672   }
   7673   // Most of steps 16 through 19 is implemented by JSArray::SetLength.
   7674   JSArray::SetLength(a, new_len);
   7675   // Steps 19d-ii, 20.
   7676   if (!new_writable) {
   7677     PropertyDescriptor readonly;
   7678     readonly.set_writable(false);
   7679     Maybe<bool> success = OrdinaryDefineOwnProperty(
   7680         isolate, a, isolate->factory()->length_string(), &readonly,
   7681         should_throw);
   7682     DCHECK(success.FromJust());
   7683     USE(success);
   7684   }
   7685   uint32_t actual_new_len = 0;
   7686   CHECK(a->length()->ToArrayLength(&actual_new_len));
   7687   // Steps 19d-v, 21. Return false if there were non-deletable elements.
   7688   bool result = actual_new_len == new_len;
   7689   if (!result) {
   7690     RETURN_FAILURE(
   7691         isolate, should_throw,
   7692         NewTypeError(MessageTemplate::kStrictDeleteProperty,
   7693                      isolate->factory()->NewNumberFromUint(actual_new_len - 1),
   7694                      a));
   7695   }
   7696   return Just(result);
   7697 }
   7698 
   7699 
   7700 // ES6 9.5.6
   7701 // static
   7702 Maybe<bool> JSProxy::DefineOwnProperty(Isolate* isolate, Handle<JSProxy> proxy,
   7703                                        Handle<Object> key,
   7704                                        PropertyDescriptor* desc,
   7705                                        ShouldThrow should_throw) {
   7706   STACK_CHECK(isolate, Nothing<bool>());
   7707   if (key->IsSymbol() && Handle<Symbol>::cast(key)->IsPrivate()) {
   7708     DCHECK(!Handle<Symbol>::cast(key)->IsPrivateField());
   7709     return JSProxy::SetPrivateSymbol(isolate, proxy, Handle<Symbol>::cast(key),
   7710                                      desc, should_throw);
   7711   }
   7712   Handle<String> trap_name = isolate->factory()->defineProperty_string();
   7713   // 1. Assert: IsPropertyKey(P) is true.
   7714   DCHECK(key->IsName() || key->IsNumber());
   7715   // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O.
   7716   Handle<Object> handler(proxy->handler(), isolate);
   7717   // 3. If handler is null, throw a TypeError exception.
   7718   // 4. Assert: Type(handler) is Object.
   7719   if (proxy->IsRevoked()) {
   7720     isolate->Throw(*isolate->factory()->NewTypeError(
   7721         MessageTemplate::kProxyRevoked, trap_name));
   7722     return Nothing<bool>();
   7723   }
   7724   // 5. Let target be the value of the [[ProxyTarget]] internal slot of O.
   7725   Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate);
   7726   // 6. Let trap be ? GetMethod(handler, "defineProperty").
   7727   Handle<Object> trap;
   7728   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   7729       isolate, trap,
   7730       Object::GetMethod(Handle<JSReceiver>::cast(handler), trap_name),
   7731       Nothing<bool>());
   7732   // 7. If trap is undefined, then:
   7733   if (trap->IsUndefined(isolate)) {
   7734     // 7a. Return target.[[DefineOwnProperty]](P, Desc).
   7735     return JSReceiver::DefineOwnProperty(isolate, target, key, desc,
   7736                                          should_throw);
   7737   }
   7738   // 8. Let descObj be FromPropertyDescriptor(Desc).
   7739   Handle<Object> desc_obj = desc->ToObject(isolate);
   7740   // 9. Let booleanTrapResult be
   7741   //    ToBoolean(? Call(trap, handler, target, P, descObj)).
   7742   Handle<Name> property_name =
   7743       key->IsName()
   7744           ? Handle<Name>::cast(key)
   7745           : Handle<Name>::cast(isolate->factory()->NumberToString(key));
   7746   // Do not leak private property names.
   7747   DCHECK(!property_name->IsPrivate());
   7748   Handle<Object> trap_result_obj;
   7749   Handle<Object> args[] = {target, property_name, desc_obj};
   7750   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   7751       isolate, trap_result_obj,
   7752       Execution::Call(isolate, trap, handler, arraysize(args), args),
   7753       Nothing<bool>());
   7754   // 10. If booleanTrapResult is false, return false.
   7755   if (!trap_result_obj->BooleanValue(isolate)) {
   7756     RETURN_FAILURE(isolate, should_throw,
   7757                    NewTypeError(MessageTemplate::kProxyTrapReturnedFalsishFor,
   7758                                 trap_name, property_name));
   7759   }
   7760   // 11. Let targetDesc be ? target.[[GetOwnProperty]](P).
   7761   PropertyDescriptor target_desc;
   7762   Maybe<bool> target_found =
   7763       JSReceiver::GetOwnPropertyDescriptor(isolate, target, key, &target_desc);
   7764   MAYBE_RETURN(target_found, Nothing<bool>());
   7765   // 12. Let extensibleTarget be ? IsExtensible(target).
   7766   Maybe<bool> maybe_extensible = JSReceiver::IsExtensible(target);
   7767   MAYBE_RETURN(maybe_extensible, Nothing<bool>());
   7768   bool extensible_target = maybe_extensible.FromJust();
   7769   // 13. If Desc has a [[Configurable]] field and if Desc.[[Configurable]]
   7770   //     is false, then:
   7771   // 13a. Let settingConfigFalse be true.
   7772   // 14. Else let settingConfigFalse be false.
   7773   bool setting_config_false = desc->has_configurable() && !desc->configurable();
   7774   // 15. If targetDesc is undefined, then
   7775   if (!target_found.FromJust()) {
   7776     // 15a. If extensibleTarget is false, throw a TypeError exception.
   7777     if (!extensible_target) {
   7778       isolate->Throw(*isolate->factory()->NewTypeError(
   7779           MessageTemplate::kProxyDefinePropertyNonExtensible, property_name));
   7780       return Nothing<bool>();
   7781     }
   7782     // 15b. If settingConfigFalse is true, throw a TypeError exception.
   7783     if (setting_config_false) {
   7784       isolate->Throw(*isolate->factory()->NewTypeError(
   7785           MessageTemplate::kProxyDefinePropertyNonConfigurable, property_name));
   7786       return Nothing<bool>();
   7787     }
   7788   } else {
   7789     // 16. Else targetDesc is not undefined,
   7790     // 16a. If IsCompatiblePropertyDescriptor(extensibleTarget, Desc,
   7791     //      targetDesc) is false, throw a TypeError exception.
   7792     Maybe<bool> valid =
   7793         IsCompatiblePropertyDescriptor(isolate, extensible_target, desc,
   7794                                        &target_desc, property_name, kDontThrow);
   7795     MAYBE_RETURN(valid, Nothing<bool>());
   7796     if (!valid.FromJust()) {
   7797       isolate->Throw(*isolate->factory()->NewTypeError(
   7798           MessageTemplate::kProxyDefinePropertyIncompatible, property_name));
   7799       return Nothing<bool>();
   7800     }
   7801     // 16b. If settingConfigFalse is true and targetDesc.[[Configurable]] is
   7802     //      true, throw a TypeError exception.
   7803     if (setting_config_false && target_desc.configurable()) {
   7804       isolate->Throw(*isolate->factory()->NewTypeError(
   7805           MessageTemplate::kProxyDefinePropertyNonConfigurable, property_name));
   7806       return Nothing<bool>();
   7807     }
   7808   }
   7809   // 17. Return true.
   7810   return Just(true);
   7811 }
   7812 
   7813 // static
   7814 Maybe<bool> JSProxy::SetPrivateSymbol(Isolate* isolate, Handle<JSProxy> proxy,
   7815                                       Handle<Symbol> private_name,
   7816                                       PropertyDescriptor* desc,
   7817                                       ShouldThrow should_throw) {
   7818   DCHECK(!private_name->IsPrivateField());
   7819   // Despite the generic name, this can only add private data properties.
   7820   if (!PropertyDescriptor::IsDataDescriptor(desc) ||
   7821       desc->ToAttributes() != DONT_ENUM) {
   7822     RETURN_FAILURE(isolate, should_throw,
   7823                    NewTypeError(MessageTemplate::kProxyPrivate));
   7824   }
   7825   DCHECK(proxy->map()->is_dictionary_map());
   7826   Handle<Object> value =
   7827       desc->has_value()
   7828           ? desc->value()
   7829           : Handle<Object>::cast(isolate->factory()->undefined_value());
   7830 
   7831   LookupIterator it(proxy, private_name, proxy);
   7832 
   7833   if (it.IsFound()) {
   7834     DCHECK_EQ(LookupIterator::DATA, it.state());
   7835     DCHECK_EQ(DONT_ENUM, it.property_attributes());
   7836     it.WriteDataValue(value, false);
   7837     return Just(true);
   7838   }
   7839 
   7840   Handle<NameDictionary> dict(proxy->property_dictionary(), isolate);
   7841   PropertyDetails details(kData, DONT_ENUM, PropertyCellType::kNoCell);
   7842   Handle<NameDictionary> result =
   7843       NameDictionary::Add(isolate, dict, private_name, value, details);
   7844   if (!dict.is_identical_to(result)) proxy->SetProperties(*result);
   7845   return Just(true);
   7846 }
   7847 
   7848 // static
   7849 Maybe<bool> JSReceiver::GetOwnPropertyDescriptor(Isolate* isolate,
   7850                                                  Handle<JSReceiver> object,
   7851                                                  Handle<Object> key,
   7852                                                  PropertyDescriptor* desc) {
   7853   bool success = false;
   7854   DCHECK(key->IsName() || key->IsNumber());  // |key| is a PropertyKey...
   7855   LookupIterator it = LookupIterator::PropertyOrElement(
   7856       isolate, object, key, &success, LookupIterator::OWN);
   7857   DCHECK(success);  // ...so creating a LookupIterator can't fail.
   7858   return GetOwnPropertyDescriptor(&it, desc);
   7859 }
   7860 
   7861 namespace {
   7862 
   7863 Maybe<bool> GetPropertyDescriptorWithInterceptor(LookupIterator* it,
   7864                                                  PropertyDescriptor* desc) {
   7865   if (it->state() == LookupIterator::ACCESS_CHECK) {
   7866     if (it->HasAccess()) {
   7867       it->Next();
   7868     } else if (!JSObject::AllCanRead(it) ||
   7869                it->state() != LookupIterator::INTERCEPTOR) {
   7870       it->Restart();
   7871       return Just(false);
   7872     }
   7873   }
   7874 
   7875   if (it->state() != LookupIterator::INTERCEPTOR) return Just(false);
   7876 
   7877   Isolate* isolate = it->isolate();
   7878   Handle<InterceptorInfo> interceptor = it->GetInterceptor();
   7879   if (interceptor->descriptor()->IsUndefined(isolate)) return Just(false);
   7880 
   7881   Handle<Object> result;
   7882   Handle<JSObject> holder = it->GetHolder<JSObject>();
   7883 
   7884   Handle<Object> receiver = it->GetReceiver();
   7885   if (!receiver->IsJSReceiver()) {
   7886     ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, receiver,
   7887                                      Object::ConvertReceiver(isolate, receiver),
   7888                                      Nothing<bool>());
   7889   }
   7890 
   7891   PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
   7892                                  *holder, kDontThrow);
   7893   if (it->IsElement()) {
   7894     result = args.CallIndexedDescriptor(interceptor, it->index());
   7895   } else {
   7896     result = args.CallNamedDescriptor(interceptor, it->name());
   7897   }
   7898   if (!result.is_null()) {
   7899     // Request successfully intercepted, try to set the property
   7900     // descriptor.
   7901     Utils::ApiCheck(
   7902         PropertyDescriptor::ToPropertyDescriptor(isolate, result, desc),
   7903         it->IsElement() ? "v8::IndexedPropertyDescriptorCallback"
   7904                         : "v8::NamedPropertyDescriptorCallback",
   7905         "Invalid property descriptor.");
   7906 
   7907     return Just(true);
   7908   }
   7909 
   7910   it->Next();
   7911   return Just(false);
   7912 }
   7913 }  // namespace
   7914 
   7915 // ES6 9.1.5.1
   7916 // Returns true on success, false if the property didn't exist, nothing if
   7917 // an exception was thrown.
   7918 // static
   7919 Maybe<bool> JSReceiver::GetOwnPropertyDescriptor(LookupIterator* it,
   7920                                                  PropertyDescriptor* desc) {
   7921   Isolate* isolate = it->isolate();
   7922   // "Virtual" dispatch.
   7923   if (it->IsFound() && it->GetHolder<JSReceiver>()->IsJSProxy()) {
   7924     return JSProxy::GetOwnPropertyDescriptor(isolate, it->GetHolder<JSProxy>(),
   7925                                              it->GetName(), desc);
   7926   }
   7927 
   7928   Maybe<bool> intercepted = GetPropertyDescriptorWithInterceptor(it, desc);
   7929   MAYBE_RETURN(intercepted, Nothing<bool>());
   7930   if (intercepted.FromJust()) {
   7931     return Just(true);
   7932   }
   7933 
   7934   // Request was not intercepted, continue as normal.
   7935   // 1. (Assert)
   7936   // 2. If O does not have an own property with key P, return undefined.
   7937   Maybe<PropertyAttributes> maybe = JSObject::GetPropertyAttributes(it);
   7938   MAYBE_RETURN(maybe, Nothing<bool>());
   7939   PropertyAttributes attrs = maybe.FromJust();
   7940   if (attrs == ABSENT) return Just(false);
   7941   DCHECK(!isolate->has_pending_exception());
   7942 
   7943   // 3. Let D be a newly created Property Descriptor with no fields.
   7944   DCHECK(desc->is_empty());
   7945   // 4. Let X be O's own property whose key is P.
   7946   // 5. If X is a data property, then
   7947   bool is_accessor_pair = it->state() == LookupIterator::ACCESSOR &&
   7948                           it->GetAccessors()->IsAccessorPair();
   7949   if (!is_accessor_pair) {
   7950     // 5a. Set D.[[Value]] to the value of X's [[Value]] attribute.
   7951     Handle<Object> value;
   7952     if (!Object::GetProperty(it).ToHandle(&value)) {
   7953       DCHECK(isolate->has_pending_exception());
   7954       return Nothing<bool>();
   7955     }
   7956     desc->set_value(value);
   7957     // 5b. Set D.[[Writable]] to the value of X's [[Writable]] attribute
   7958     desc->set_writable((attrs & READ_ONLY) == 0);
   7959   } else {
   7960     // 6. Else X is an accessor property, so
   7961     Handle<AccessorPair> accessors =
   7962         Handle<AccessorPair>::cast(it->GetAccessors());
   7963     // 6a. Set D.[[Get]] to the value of X's [[Get]] attribute.
   7964     desc->set_get(
   7965         AccessorPair::GetComponent(isolate, accessors, ACCESSOR_GETTER));
   7966     // 6b. Set D.[[Set]] to the value of X's [[Set]] attribute.
   7967     desc->set_set(
   7968         AccessorPair::GetComponent(isolate, accessors, ACCESSOR_SETTER));
   7969   }
   7970 
   7971   // 7. Set D.[[Enumerable]] to the value of X's [[Enumerable]] attribute.
   7972   desc->set_enumerable((attrs & DONT_ENUM) == 0);
   7973   // 8. Set D.[[Configurable]] to the value of X's [[Configurable]] attribute.
   7974   desc->set_configurable((attrs & DONT_DELETE) == 0);
   7975   // 9. Return D.
   7976   DCHECK(PropertyDescriptor::IsAccessorDescriptor(desc) !=
   7977          PropertyDescriptor::IsDataDescriptor(desc));
   7978   return Just(true);
   7979 }
   7980 
   7981 
   7982 // ES6 9.5.5
   7983 // static
   7984 Maybe<bool> JSProxy::GetOwnPropertyDescriptor(Isolate* isolate,
   7985                                               Handle<JSProxy> proxy,
   7986                                               Handle<Name> name,
   7987                                               PropertyDescriptor* desc) {
   7988   DCHECK(!name->IsPrivate());
   7989   STACK_CHECK(isolate, Nothing<bool>());
   7990 
   7991   Handle<String> trap_name =
   7992       isolate->factory()->getOwnPropertyDescriptor_string();
   7993   // 1. (Assert)
   7994   // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O.
   7995   Handle<Object> handler(proxy->handler(), isolate);
   7996   // 3. If handler is null, throw a TypeError exception.
   7997   // 4. Assert: Type(handler) is Object.
   7998   if (proxy->IsRevoked()) {
   7999     isolate->Throw(*isolate->factory()->NewTypeError(
   8000         MessageTemplate::kProxyRevoked, trap_name));
   8001     return Nothing<bool>();
   8002   }
   8003   // 5. Let target be the value of the [[ProxyTarget]] internal slot of O.
   8004   Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate);
   8005   // 6. Let trap be ? GetMethod(handler, "getOwnPropertyDescriptor").
   8006   Handle<Object> trap;
   8007   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   8008       isolate, trap,
   8009       Object::GetMethod(Handle<JSReceiver>::cast(handler), trap_name),
   8010       Nothing<bool>());
   8011   // 7. If trap is undefined, then
   8012   if (trap->IsUndefined(isolate)) {
   8013     // 7a. Return target.[[GetOwnProperty]](P).
   8014     return JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, desc);
   8015   }
   8016   // 8. Let trapResultObj be ? Call(trap, handler, target, P).
   8017   Handle<Object> trap_result_obj;
   8018   Handle<Object> args[] = {target, name};
   8019   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   8020       isolate, trap_result_obj,
   8021       Execution::Call(isolate, trap, handler, arraysize(args), args),
   8022       Nothing<bool>());
   8023   // 9. If Type(trapResultObj) is neither Object nor Undefined, throw a
   8024   //    TypeError exception.
   8025   if (!trap_result_obj->IsJSReceiver() &&
   8026       !trap_result_obj->IsUndefined(isolate)) {
   8027     isolate->Throw(*isolate->factory()->NewTypeError(
   8028         MessageTemplate::kProxyGetOwnPropertyDescriptorInvalid, name));
   8029     return Nothing<bool>();
   8030   }
   8031   // 10. Let targetDesc be ? target.[[GetOwnProperty]](P).
   8032   PropertyDescriptor target_desc;
   8033   Maybe<bool> found =
   8034       JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, &target_desc);
   8035   MAYBE_RETURN(found, Nothing<bool>());
   8036   // 11. If trapResultObj is undefined, then
   8037   if (trap_result_obj->IsUndefined(isolate)) {
   8038     // 11a. If targetDesc is undefined, return undefined.
   8039     if (!found.FromJust()) return Just(false);
   8040     // 11b. If targetDesc.[[Configurable]] is false, throw a TypeError
   8041     //      exception.
   8042     if (!target_desc.configurable()) {
   8043       isolate->Throw(*isolate->factory()->NewTypeError(
   8044           MessageTemplate::kProxyGetOwnPropertyDescriptorUndefined, name));
   8045       return Nothing<bool>();
   8046     }
   8047     // 11c. Let extensibleTarget be ? IsExtensible(target).
   8048     Maybe<bool> extensible_target = JSReceiver::IsExtensible(target);
   8049     MAYBE_RETURN(extensible_target, Nothing<bool>());
   8050     // 11d. (Assert)
   8051     // 11e. If extensibleTarget is false, throw a TypeError exception.
   8052     if (!extensible_target.FromJust()) {
   8053       isolate->Throw(*isolate->factory()->NewTypeError(
   8054           MessageTemplate::kProxyGetOwnPropertyDescriptorNonExtensible, name));
   8055       return Nothing<bool>();
   8056     }
   8057     // 11f. Return undefined.
   8058     return Just(false);
   8059   }
   8060   // 12. Let extensibleTarget be ? IsExtensible(target).
   8061   Maybe<bool> extensible_target = JSReceiver::IsExtensible(target);
   8062   MAYBE_RETURN(extensible_target, Nothing<bool>());
   8063   // 13. Let resultDesc be ? ToPropertyDescriptor(trapResultObj).
   8064   if (!PropertyDescriptor::ToPropertyDescriptor(isolate, trap_result_obj,
   8065                                                 desc)) {
   8066     DCHECK(isolate->has_pending_exception());
   8067     return Nothing<bool>();
   8068   }
   8069   // 14. Call CompletePropertyDescriptor(resultDesc).
   8070   PropertyDescriptor::CompletePropertyDescriptor(isolate, desc);
   8071   // 15. Let valid be IsCompatiblePropertyDescriptor (extensibleTarget,
   8072   //     resultDesc, targetDesc).
   8073   Maybe<bool> valid =
   8074       IsCompatiblePropertyDescriptor(isolate, extensible_target.FromJust(),
   8075                                      desc, &target_desc, name, kDontThrow);
   8076   MAYBE_RETURN(valid, Nothing<bool>());
   8077   // 16. If valid is false, throw a TypeError exception.
   8078   if (!valid.FromJust()) {
   8079     isolate->Throw(*isolate->factory()->NewTypeError(
   8080         MessageTemplate::kProxyGetOwnPropertyDescriptorIncompatible, name));
   8081     return Nothing<bool>();
   8082   }
   8083   // 17. If resultDesc.[[Configurable]] is false, then
   8084   if (!desc->configurable()) {
   8085     // 17a. If targetDesc is undefined or targetDesc.[[Configurable]] is true:
   8086     if (target_desc.is_empty() || target_desc.configurable()) {
   8087       // 17a i. Throw a TypeError exception.
   8088       isolate->Throw(*isolate->factory()->NewTypeError(
   8089           MessageTemplate::kProxyGetOwnPropertyDescriptorNonConfigurable,
   8090           name));
   8091       return Nothing<bool>();
   8092     }
   8093   }
   8094   // 18. Return resultDesc.
   8095   return Just(true);
   8096 }
   8097 
   8098 
   8099 bool JSObject::ReferencesObjectFromElements(FixedArray* elements,
   8100                                             ElementsKind kind,
   8101                                             Object* object) {
   8102   Isolate* isolate = GetIsolate();
   8103   if (IsObjectElementsKind(kind) || kind == FAST_STRING_WRAPPER_ELEMENTS) {
   8104     int length = IsJSArray() ? Smi::ToInt(JSArray::cast(this)->length())
   8105                              : elements->length();
   8106     for (int i = 0; i < length; ++i) {
   8107       Object* element = elements->get(i);
   8108       if (!element->IsTheHole(isolate) && element == object) return true;
   8109     }
   8110   } else {
   8111     DCHECK(kind == DICTIONARY_ELEMENTS || kind == SLOW_STRING_WRAPPER_ELEMENTS);
   8112     Object* key = NumberDictionary::cast(elements)->SlowReverseLookup(object);
   8113     if (!key->IsUndefined(isolate)) return true;
   8114   }
   8115   return false;
   8116 }
   8117 
   8118 
   8119 // Check whether this object references another object.
   8120 bool JSObject::ReferencesObject(Object* obj) {
   8121   Map* map_of_this = map();
   8122   Heap* heap = GetHeap();
   8123   DisallowHeapAllocation no_allocation;
   8124 
   8125   // Is the object the constructor for this object?
   8126   if (map_of_this->GetConstructor() == obj) {
   8127     return true;
   8128   }
   8129 
   8130   // Is the object the prototype for this object?
   8131   if (map_of_this->prototype() == obj) {
   8132     return true;
   8133   }
   8134 
   8135   // Check if the object is among the named properties.
   8136   Object* key = SlowReverseLookup(obj);
   8137   if (!key->IsUndefined(heap->isolate())) {
   8138     return true;
   8139   }
   8140 
   8141   // Check if the object is among the indexed properties.
   8142   ElementsKind kind = GetElementsKind();
   8143   switch (kind) {
   8144     // Raw pixels and external arrays do not reference other
   8145     // objects.
   8146 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) \
   8147   case TYPE##_ELEMENTS:                           \
   8148     break;
   8149 
   8150     TYPED_ARRAYS(TYPED_ARRAY_CASE)
   8151 #undef TYPED_ARRAY_CASE
   8152 
   8153     case PACKED_DOUBLE_ELEMENTS:
   8154     case HOLEY_DOUBLE_ELEMENTS:
   8155       break;
   8156     case PACKED_SMI_ELEMENTS:
   8157     case HOLEY_SMI_ELEMENTS:
   8158       break;
   8159     case PACKED_ELEMENTS:
   8160     case HOLEY_ELEMENTS:
   8161     case DICTIONARY_ELEMENTS:
   8162     case FAST_STRING_WRAPPER_ELEMENTS:
   8163     case SLOW_STRING_WRAPPER_ELEMENTS: {
   8164       FixedArray* elements = FixedArray::cast(this->elements());
   8165       if (ReferencesObjectFromElements(elements, kind, obj)) return true;
   8166       break;
   8167     }
   8168     case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
   8169     case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: {
   8170       SloppyArgumentsElements* elements =
   8171           SloppyArgumentsElements::cast(this->elements());
   8172       // Check the mapped parameters.
   8173       for (uint32_t i = 0; i < elements->parameter_map_length(); ++i) {
   8174         Object* value = elements->get_mapped_entry(i);
   8175         if (!value->IsTheHole(heap->isolate()) && value == obj) return true;
   8176       }
   8177       // Check the arguments.
   8178       FixedArray* arguments = elements->arguments();
   8179       kind = arguments->IsNumberDictionary() ? DICTIONARY_ELEMENTS
   8180                                              : HOLEY_ELEMENTS;
   8181       if (ReferencesObjectFromElements(arguments, kind, obj)) return true;
   8182       break;
   8183     }
   8184     case NO_ELEMENTS:
   8185       break;
   8186   }
   8187 
   8188   // For functions check the context.
   8189   if (IsJSFunction()) {
   8190     // Get the constructor function for arguments array.
   8191     Map* arguments_map =
   8192         heap->isolate()->context()->native_context()->sloppy_arguments_map();
   8193     JSFunction* arguments_function =
   8194         JSFunction::cast(arguments_map->GetConstructor());
   8195 
   8196     // Get the context and don't check if it is the native context.
   8197     JSFunction* f = JSFunction::cast(this);
   8198     Context* context = f->context();
   8199     if (context->IsNativeContext()) {
   8200       return false;
   8201     }
   8202 
   8203     // Check the non-special context slots.
   8204     for (int i = Context::MIN_CONTEXT_SLOTS; i < context->length(); i++) {
   8205       // Only check JS objects.
   8206       if (context->get(i)->IsJSObject()) {
   8207         JSObject* ctxobj = JSObject::cast(context->get(i));
   8208         // If it is an arguments array check the content.
   8209         if (ctxobj->map()->GetConstructor() == arguments_function) {
   8210           if (ctxobj->ReferencesObject(obj)) {
   8211             return true;
   8212           }
   8213         } else if (ctxobj == obj) {
   8214           return true;
   8215         }
   8216       }
   8217     }
   8218 
   8219     // Check the context extension (if any) if it can have references.
   8220     if (context->has_extension() && !context->IsCatchContext() &&
   8221         !context->IsModuleContext()) {
   8222       // With harmony scoping, a JSFunction may have a script context.
   8223       // TODO(mvstanton): walk into the ScopeInfo.
   8224       if (context->IsScriptContext()) {
   8225         return false;
   8226       }
   8227 
   8228       return context->extension_object()->ReferencesObject(obj);
   8229     }
   8230   }
   8231 
   8232   // No references to object.
   8233   return false;
   8234 }
   8235 
   8236 
   8237 Maybe<bool> JSReceiver::SetIntegrityLevel(Handle<JSReceiver> receiver,
   8238                                           IntegrityLevel level,
   8239                                           ShouldThrow should_throw) {
   8240   DCHECK(level == SEALED || level == FROZEN);
   8241 
   8242   if (receiver->IsJSObject()) {
   8243     Handle<JSObject> object = Handle<JSObject>::cast(receiver);
   8244 
   8245     if (!object->HasSloppyArgumentsElements() &&
   8246         !object->IsJSModuleNamespace()) {  // Fast path.
   8247       // Prevent memory leaks by not adding unnecessary transitions.
   8248       Maybe<bool> test = JSObject::TestIntegrityLevel(object, level);
   8249       MAYBE_RETURN(test, Nothing<bool>());
   8250       if (test.FromJust()) return test;
   8251 
   8252       if (level == SEALED) {
   8253         return JSObject::PreventExtensionsWithTransition<SEALED>(object,
   8254                                                                  should_throw);
   8255       } else {
   8256         return JSObject::PreventExtensionsWithTransition<FROZEN>(object,
   8257                                                                  should_throw);
   8258       }
   8259     }
   8260   }
   8261 
   8262   Isolate* isolate = receiver->GetIsolate();
   8263 
   8264   MAYBE_RETURN(JSReceiver::PreventExtensions(receiver, should_throw),
   8265                Nothing<bool>());
   8266 
   8267   Handle<FixedArray> keys;
   8268   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   8269       isolate, keys, JSReceiver::OwnPropertyKeys(receiver), Nothing<bool>());
   8270 
   8271   PropertyDescriptor no_conf;
   8272   no_conf.set_configurable(false);
   8273 
   8274   PropertyDescriptor no_conf_no_write;
   8275   no_conf_no_write.set_configurable(false);
   8276   no_conf_no_write.set_writable(false);
   8277 
   8278   if (level == SEALED) {
   8279     for (int i = 0; i < keys->length(); ++i) {
   8280       Handle<Object> key(keys->get(i), isolate);
   8281       MAYBE_RETURN(
   8282           DefineOwnProperty(isolate, receiver, key, &no_conf, kThrowOnError),
   8283           Nothing<bool>());
   8284     }
   8285     return Just(true);
   8286   }
   8287 
   8288   for (int i = 0; i < keys->length(); ++i) {
   8289     Handle<Object> key(keys->get(i), isolate);
   8290     PropertyDescriptor current_desc;
   8291     Maybe<bool> owned = JSReceiver::GetOwnPropertyDescriptor(
   8292         isolate, receiver, key, &current_desc);
   8293     MAYBE_RETURN(owned, Nothing<bool>());
   8294     if (owned.FromJust()) {
   8295       PropertyDescriptor desc =
   8296           PropertyDescriptor::IsAccessorDescriptor(&current_desc)
   8297               ? no_conf
   8298               : no_conf_no_write;
   8299       MAYBE_RETURN(
   8300           DefineOwnProperty(isolate, receiver, key, &desc, kThrowOnError),
   8301           Nothing<bool>());
   8302     }
   8303   }
   8304   return Just(true);
   8305 }
   8306 
   8307 namespace {
   8308 
   8309 template <typename Dictionary>
   8310 bool TestDictionaryPropertiesIntegrityLevel(Dictionary* dict,
   8311                                             ReadOnlyRoots roots,
   8312                                             PropertyAttributes level) {
   8313   DCHECK(level == SEALED || level == FROZEN);
   8314 
   8315   uint32_t capacity = dict->Capacity();
   8316   for (uint32_t i = 0; i < capacity; i++) {
   8317     Object* key;
   8318     if (!dict->ToKey(roots, i, &key)) continue;
   8319     if (key->FilterKey(ALL_PROPERTIES)) continue;
   8320     PropertyDetails details = dict->DetailsAt(i);
   8321     if (details.IsConfigurable()) return false;
   8322     if (level == FROZEN && details.kind() == kData && !details.IsReadOnly()) {
   8323       return false;
   8324     }
   8325   }
   8326   return true;
   8327 }
   8328 
   8329 bool TestFastPropertiesIntegrityLevel(Map* map, PropertyAttributes level) {
   8330   DCHECK(level == SEALED || level == FROZEN);
   8331   DCHECK(!map->IsCustomElementsReceiverMap());
   8332   DCHECK(!map->is_dictionary_map());
   8333 
   8334   DescriptorArray* descriptors = map->instance_descriptors();
   8335   int number_of_own_descriptors = map->NumberOfOwnDescriptors();
   8336   for (int i = 0; i < number_of_own_descriptors; i++) {
   8337     if (descriptors->GetKey(i)->IsPrivate()) continue;
   8338     PropertyDetails details = descriptors->GetDetails(i);
   8339     if (details.IsConfigurable()) return false;
   8340     if (level == FROZEN && details.kind() == kData && !details.IsReadOnly()) {
   8341       return false;
   8342     }
   8343   }
   8344   return true;
   8345 }
   8346 
   8347 bool TestPropertiesIntegrityLevel(JSObject* object, PropertyAttributes level) {
   8348   DCHECK(!object->map()->IsCustomElementsReceiverMap());
   8349 
   8350   if (object->HasFastProperties()) {
   8351     return TestFastPropertiesIntegrityLevel(object->map(), level);
   8352   }
   8353 
   8354   return TestDictionaryPropertiesIntegrityLevel(
   8355       object->property_dictionary(), object->GetReadOnlyRoots(), level);
   8356 }
   8357 
   8358 bool TestElementsIntegrityLevel(JSObject* object, PropertyAttributes level) {
   8359   DCHECK(!object->HasSloppyArgumentsElements());
   8360 
   8361   ElementsKind kind = object->GetElementsKind();
   8362 
   8363   if (IsDictionaryElementsKind(kind)) {
   8364     return TestDictionaryPropertiesIntegrityLevel(
   8365         NumberDictionary::cast(object->elements()), object->GetReadOnlyRoots(),
   8366         level);
   8367   }
   8368 
   8369   ElementsAccessor* accessor = ElementsAccessor::ForKind(kind);
   8370   // Only DICTIONARY_ELEMENTS and SLOW_SLOPPY_ARGUMENTS_ELEMENTS have
   8371   // PropertyAttributes so just test if empty
   8372   return accessor->NumberOfElements(object) == 0;
   8373 }
   8374 
   8375 bool FastTestIntegrityLevel(JSObject* object, PropertyAttributes level) {
   8376   DCHECK(!object->map()->IsCustomElementsReceiverMap());
   8377 
   8378   return !object->map()->is_extensible() &&
   8379          TestElementsIntegrityLevel(object, level) &&
   8380          TestPropertiesIntegrityLevel(object, level);
   8381 }
   8382 
   8383 Maybe<bool> GenericTestIntegrityLevel(Handle<JSReceiver> receiver,
   8384                                       PropertyAttributes level) {
   8385   DCHECK(level == SEALED || level == FROZEN);
   8386 
   8387   Maybe<bool> extensible = JSReceiver::IsExtensible(receiver);
   8388   MAYBE_RETURN(extensible, Nothing<bool>());
   8389   if (extensible.FromJust()) return Just(false);
   8390 
   8391   Isolate* isolate = receiver->GetIsolate();
   8392 
   8393   Handle<FixedArray> keys;
   8394   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   8395       isolate, keys, JSReceiver::OwnPropertyKeys(receiver), Nothing<bool>());
   8396 
   8397   for (int i = 0; i < keys->length(); ++i) {
   8398     Handle<Object> key(keys->get(i), isolate);
   8399     PropertyDescriptor current_desc;
   8400     Maybe<bool> owned = JSReceiver::GetOwnPropertyDescriptor(
   8401         isolate, receiver, key, &current_desc);
   8402     MAYBE_RETURN(owned, Nothing<bool>());
   8403     if (owned.FromJust()) {
   8404       if (current_desc.configurable()) return Just(false);
   8405       if (level == FROZEN &&
   8406           PropertyDescriptor::IsDataDescriptor(&current_desc) &&
   8407           current_desc.writable()) {
   8408         return Just(false);
   8409       }
   8410     }
   8411   }
   8412   return Just(true);
   8413 }
   8414 
   8415 }  // namespace
   8416 
   8417 Maybe<bool> JSReceiver::TestIntegrityLevel(Handle<JSReceiver> receiver,
   8418                                            IntegrityLevel level) {
   8419   if (!receiver->map()->IsCustomElementsReceiverMap()) {
   8420     return JSObject::TestIntegrityLevel(Handle<JSObject>::cast(receiver),
   8421                                         level);
   8422   }
   8423   return GenericTestIntegrityLevel(receiver, level);
   8424 }
   8425 
   8426 Maybe<bool> JSObject::TestIntegrityLevel(Handle<JSObject> object,
   8427                                          IntegrityLevel level) {
   8428   if (!object->map()->IsCustomElementsReceiverMap() &&
   8429       !object->HasSloppyArgumentsElements()) {
   8430     return Just(FastTestIntegrityLevel(*object, level));
   8431   }
   8432   return GenericTestIntegrityLevel(Handle<JSReceiver>::cast(object), level);
   8433 }
   8434 
   8435 Maybe<bool> JSReceiver::PreventExtensions(Handle<JSReceiver> object,
   8436                                           ShouldThrow should_throw) {
   8437   if (object->IsJSProxy()) {
   8438     return JSProxy::PreventExtensions(Handle<JSProxy>::cast(object),
   8439                                       should_throw);
   8440   }
   8441   DCHECK(object->IsJSObject());
   8442   return JSObject::PreventExtensions(Handle<JSObject>::cast(object),
   8443                                      should_throw);
   8444 }
   8445 
   8446 
   8447 Maybe<bool> JSProxy::PreventExtensions(Handle<JSProxy> proxy,
   8448                                        ShouldThrow should_throw) {
   8449   Isolate* isolate = proxy->GetIsolate();
   8450   STACK_CHECK(isolate, Nothing<bool>());
   8451   Factory* factory = isolate->factory();
   8452   Handle<String> trap_name = factory->preventExtensions_string();
   8453 
   8454   if (proxy->IsRevoked()) {
   8455     isolate->Throw(
   8456         *factory->NewTypeError(MessageTemplate::kProxyRevoked, trap_name));
   8457     return Nothing<bool>();
   8458   }
   8459   Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate);
   8460   Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate);
   8461 
   8462   Handle<Object> trap;
   8463   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   8464       isolate, trap, Object::GetMethod(handler, trap_name), Nothing<bool>());
   8465   if (trap->IsUndefined(isolate)) {
   8466     return JSReceiver::PreventExtensions(target, should_throw);
   8467   }
   8468 
   8469   Handle<Object> trap_result;
   8470   Handle<Object> args[] = {target};
   8471   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   8472       isolate, trap_result,
   8473       Execution::Call(isolate, trap, handler, arraysize(args), args),
   8474       Nothing<bool>());
   8475   if (!trap_result->BooleanValue(isolate)) {
   8476     RETURN_FAILURE(
   8477         isolate, should_throw,
   8478         NewTypeError(MessageTemplate::kProxyTrapReturnedFalsish, trap_name));
   8479   }
   8480 
   8481   // Enforce the invariant.
   8482   Maybe<bool> target_result = JSReceiver::IsExtensible(target);
   8483   MAYBE_RETURN(target_result, Nothing<bool>());
   8484   if (target_result.FromJust()) {
   8485     isolate->Throw(*factory->NewTypeError(
   8486         MessageTemplate::kProxyPreventExtensionsExtensible));
   8487     return Nothing<bool>();
   8488   }
   8489   return Just(true);
   8490 }
   8491 
   8492 
   8493 Maybe<bool> JSObject::PreventExtensions(Handle<JSObject> object,
   8494                                         ShouldThrow should_throw) {
   8495   Isolate* isolate = object->GetIsolate();
   8496 
   8497   if (!object->HasSloppyArgumentsElements()) {
   8498     return PreventExtensionsWithTransition<NONE>(object, should_throw);
   8499   }
   8500 
   8501   if (object->IsAccessCheckNeeded() &&
   8502       !isolate->MayAccess(handle(isolate->context(), isolate), object)) {
   8503     isolate->ReportFailedAccessCheck(object);
   8504     RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
   8505     RETURN_FAILURE(isolate, should_throw,
   8506                    NewTypeError(MessageTemplate::kNoAccess));
   8507   }
   8508 
   8509   if (!object->map()->is_extensible()) return Just(true);
   8510 
   8511   if (object->IsJSGlobalProxy()) {
   8512     PrototypeIterator iter(isolate, object);
   8513     if (iter.IsAtEnd()) return Just(true);
   8514     DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
   8515     return PreventExtensions(PrototypeIterator::GetCurrent<JSObject>(iter),
   8516                              should_throw);
   8517   }
   8518 
   8519   if (object->map()->has_named_interceptor() ||
   8520       object->map()->has_indexed_interceptor()) {
   8521     RETURN_FAILURE(isolate, should_throw,
   8522                    NewTypeError(MessageTemplate::kCannotPreventExt));
   8523   }
   8524 
   8525   if (!object->HasFixedTypedArrayElements()) {
   8526     // If there are fast elements we normalize.
   8527     Handle<NumberDictionary> dictionary = NormalizeElements(object);
   8528     DCHECK(object->HasDictionaryElements() ||
   8529            object->HasSlowArgumentsElements());
   8530 
   8531     // Make sure that we never go back to fast case.
   8532     object->RequireSlowElements(*dictionary);
   8533   }
   8534 
   8535   // Do a map transition, other objects with this map may still
   8536   // be extensible.
   8537   // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps.
   8538   Handle<Map> new_map =
   8539       Map::Copy(isolate, handle(object->map(), isolate), "PreventExtensions");
   8540 
   8541   new_map->set_is_extensible(false);
   8542   JSObject::MigrateToMap(object, new_map);
   8543   DCHECK(!object->map()->is_extensible());
   8544 
   8545   return Just(true);
   8546 }
   8547 
   8548 
   8549 Maybe<bool> JSReceiver::IsExtensible(Handle<JSReceiver> object) {
   8550   if (object->IsJSProxy()) {
   8551     return JSProxy::IsExtensible(Handle<JSProxy>::cast(object));
   8552   }
   8553   return Just(JSObject::IsExtensible(Handle<JSObject>::cast(object)));
   8554 }
   8555 
   8556 
   8557 Maybe<bool> JSProxy::IsExtensible(Handle<JSProxy> proxy) {
   8558   Isolate* isolate = proxy->GetIsolate();
   8559   STACK_CHECK(isolate, Nothing<bool>());
   8560   Factory* factory = isolate->factory();
   8561   Handle<String> trap_name = factory->isExtensible_string();
   8562 
   8563   if (proxy->IsRevoked()) {
   8564     isolate->Throw(
   8565         *factory->NewTypeError(MessageTemplate::kProxyRevoked, trap_name));
   8566     return Nothing<bool>();
   8567   }
   8568   Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate);
   8569   Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate);
   8570 
   8571   Handle<Object> trap;
   8572   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   8573       isolate, trap, Object::GetMethod(handler, trap_name), Nothing<bool>());
   8574   if (trap->IsUndefined(isolate)) {
   8575     return JSReceiver::IsExtensible(target);
   8576   }
   8577 
   8578   Handle<Object> trap_result;
   8579   Handle<Object> args[] = {target};
   8580   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   8581       isolate, trap_result,
   8582       Execution::Call(isolate, trap, handler, arraysize(args), args),
   8583       Nothing<bool>());
   8584 
   8585   // Enforce the invariant.
   8586   Maybe<bool> target_result = JSReceiver::IsExtensible(target);
   8587   MAYBE_RETURN(target_result, Nothing<bool>());
   8588   if (target_result.FromJust() != trap_result->BooleanValue(isolate)) {
   8589     isolate->Throw(
   8590         *factory->NewTypeError(MessageTemplate::kProxyIsExtensibleInconsistent,
   8591                                factory->ToBoolean(target_result.FromJust())));
   8592     return Nothing<bool>();
   8593   }
   8594   return target_result;
   8595 }
   8596 
   8597 
   8598 bool JSObject::IsExtensible(Handle<JSObject> object) {
   8599   Isolate* isolate = object->GetIsolate();
   8600   if (object->IsAccessCheckNeeded() &&
   8601       !isolate->MayAccess(handle(isolate->context(), isolate), object)) {
   8602     return true;
   8603   }
   8604   if (object->IsJSGlobalProxy()) {
   8605     PrototypeIterator iter(isolate, *object);
   8606     if (iter.IsAtEnd()) return false;
   8607     DCHECK(iter.GetCurrent()->IsJSGlobalObject());
   8608     return iter.GetCurrent<JSObject>()->map()->is_extensible();
   8609   }
   8610   return object->map()->is_extensible();
   8611 }
   8612 
   8613 namespace {
   8614 
   8615 template <typename Dictionary>
   8616 void ApplyAttributesToDictionary(Isolate* isolate, ReadOnlyRoots roots,
   8617                                  Handle<Dictionary> dictionary,
   8618                                  const PropertyAttributes attributes) {
   8619   int capacity = dictionary->Capacity();
   8620   for (int i = 0; i < capacity; i++) {
   8621     Object* k;
   8622     if (!dictionary->ToKey(roots, i, &k)) continue;
   8623     if (k->FilterKey(ALL_PROPERTIES)) continue;
   8624     PropertyDetails details = dictionary->DetailsAt(i);
   8625     int attrs = attributes;
   8626     // READ_ONLY is an invalid attribute for JS setters/getters.
   8627     if ((attributes & READ_ONLY) && details.kind() == kAccessor) {
   8628       Object* v = dictionary->ValueAt(i);
   8629       if (v->IsAccessorPair()) attrs &= ~READ_ONLY;
   8630     }
   8631     details = details.CopyAddAttributes(static_cast<PropertyAttributes>(attrs));
   8632     dictionary->DetailsAtPut(isolate, i, details);
   8633   }
   8634 }
   8635 
   8636 }  // namespace
   8637 
   8638 template <PropertyAttributes attrs>
   8639 Maybe<bool> JSObject::PreventExtensionsWithTransition(
   8640     Handle<JSObject> object, ShouldThrow should_throw) {
   8641   STATIC_ASSERT(attrs == NONE || attrs == SEALED || attrs == FROZEN);
   8642 
   8643   // Sealing/freezing sloppy arguments or namespace objects should be handled
   8644   // elsewhere.
   8645   DCHECK(!object->HasSloppyArgumentsElements());
   8646   DCHECK_IMPLIES(object->IsJSModuleNamespace(), attrs == NONE);
   8647 
   8648   Isolate* isolate = object->GetIsolate();
   8649   if (object->IsAccessCheckNeeded() &&
   8650       !isolate->MayAccess(handle(isolate->context(), isolate), object)) {
   8651     isolate->ReportFailedAccessCheck(object);
   8652     RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
   8653     RETURN_FAILURE(isolate, should_throw,
   8654                    NewTypeError(MessageTemplate::kNoAccess));
   8655   }
   8656 
   8657   if (attrs == NONE && !object->map()->is_extensible()) return Just(true);
   8658 
   8659   if (object->IsJSGlobalProxy()) {
   8660     PrototypeIterator iter(isolate, object);
   8661     if (iter.IsAtEnd()) return Just(true);
   8662     DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
   8663     return PreventExtensionsWithTransition<attrs>(
   8664         PrototypeIterator::GetCurrent<JSObject>(iter), should_throw);
   8665   }
   8666 
   8667   if (object->map()->has_named_interceptor() ||
   8668       object->map()->has_indexed_interceptor()) {
   8669     MessageTemplate::Template message = MessageTemplate::kNone;
   8670     switch (attrs) {
   8671       case NONE:
   8672         message = MessageTemplate::kCannotPreventExt;
   8673         break;
   8674 
   8675       case SEALED:
   8676         message = MessageTemplate::kCannotSeal;
   8677         break;
   8678 
   8679       case FROZEN:
   8680         message = MessageTemplate::kCannotFreeze;
   8681         break;
   8682     }
   8683     RETURN_FAILURE(isolate, should_throw, NewTypeError(message));
   8684   }
   8685 
   8686   Handle<NumberDictionary> new_element_dictionary;
   8687   if (!object->HasFixedTypedArrayElements() &&
   8688       !object->HasDictionaryElements() &&
   8689       !object->HasSlowStringWrapperElements()) {
   8690     int length = object->IsJSArray()
   8691                      ? Smi::ToInt(Handle<JSArray>::cast(object)->length())
   8692                      : object->elements()->length();
   8693     new_element_dictionary =
   8694         length == 0 ? isolate->factory()->empty_slow_element_dictionary()
   8695                     : object->GetElementsAccessor()->Normalize(object);
   8696   }
   8697 
   8698   Handle<Symbol> transition_marker;
   8699   if (attrs == NONE) {
   8700     transition_marker = isolate->factory()->nonextensible_symbol();
   8701   } else if (attrs == SEALED) {
   8702     transition_marker = isolate->factory()->sealed_symbol();
   8703   } else {
   8704     DCHECK(attrs == FROZEN);
   8705     transition_marker = isolate->factory()->frozen_symbol();
   8706   }
   8707 
   8708   Handle<Map> old_map(object->map(), isolate);
   8709   TransitionsAccessor transitions(isolate, old_map);
   8710   Map* transition = transitions.SearchSpecial(*transition_marker);
   8711   if (transition != nullptr) {
   8712     Handle<Map> transition_map(transition, isolate);
   8713     DCHECK(transition_map->has_dictionary_elements() ||
   8714            transition_map->has_fixed_typed_array_elements() ||
   8715            transition_map->elements_kind() == SLOW_STRING_WRAPPER_ELEMENTS);
   8716     DCHECK(!transition_map->is_extensible());
   8717     JSObject::MigrateToMap(object, transition_map);
   8718   } else if (transitions.CanHaveMoreTransitions()) {
   8719     // Create a new descriptor array with the appropriate property attributes
   8720     Handle<Map> new_map = Map::CopyForPreventExtensions(
   8721         isolate, old_map, attrs, transition_marker, "CopyForPreventExtensions");
   8722     JSObject::MigrateToMap(object, new_map);
   8723   } else {
   8724     DCHECK(old_map->is_dictionary_map() || !old_map->is_prototype_map());
   8725     // Slow path: need to normalize properties for safety
   8726     NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0,
   8727                         "SlowPreventExtensions");
   8728 
   8729     // Create a new map, since other objects with this map may be extensible.
   8730     // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps.
   8731     Handle<Map> new_map = Map::Copy(isolate, handle(object->map(), isolate),
   8732                                     "SlowCopyForPreventExtensions");
   8733     new_map->set_is_extensible(false);
   8734     if (!new_element_dictionary.is_null()) {
   8735       ElementsKind new_kind =
   8736           IsStringWrapperElementsKind(old_map->elements_kind())
   8737               ? SLOW_STRING_WRAPPER_ELEMENTS
   8738               : DICTIONARY_ELEMENTS;
   8739       new_map->set_elements_kind(new_kind);
   8740     }
   8741     JSObject::MigrateToMap(object, new_map);
   8742 
   8743     if (attrs != NONE) {
   8744       ReadOnlyRoots roots(isolate);
   8745       if (object->IsJSGlobalObject()) {
   8746         Handle<GlobalDictionary> dictionary(
   8747             JSGlobalObject::cast(*object)->global_dictionary(), isolate);
   8748         ApplyAttributesToDictionary(isolate, roots, dictionary, attrs);
   8749       } else {
   8750         Handle<NameDictionary> dictionary(object->property_dictionary(),
   8751                                           isolate);
   8752         ApplyAttributesToDictionary(isolate, roots, dictionary, attrs);
   8753       }
   8754     }
   8755   }
   8756 
   8757   // Both seal and preventExtensions always go through without modifications to
   8758   // typed array elements. Freeze works only if there are no actual elements.
   8759   if (object->HasFixedTypedArrayElements()) {
   8760     if (attrs == FROZEN &&
   8761         JSArrayBufferView::cast(*object)->byte_length()->Number() > 0) {
   8762       isolate->Throw(*isolate->factory()->NewTypeError(
   8763           MessageTemplate::kCannotFreezeArrayBufferView));
   8764       return Nothing<bool>();
   8765     }
   8766     return Just(true);
   8767   }
   8768 
   8769   DCHECK(object->map()->has_dictionary_elements() ||
   8770          object->map()->elements_kind() == SLOW_STRING_WRAPPER_ELEMENTS);
   8771   if (!new_element_dictionary.is_null()) {
   8772     object->set_elements(*new_element_dictionary);
   8773   }
   8774 
   8775   if (object->elements() !=
   8776       ReadOnlyRoots(isolate).empty_slow_element_dictionary()) {
   8777     Handle<NumberDictionary> dictionary(object->element_dictionary(), isolate);
   8778     // Make sure we never go back to the fast case
   8779     object->RequireSlowElements(*dictionary);
   8780     if (attrs != NONE) {
   8781       ApplyAttributesToDictionary(isolate, ReadOnlyRoots(isolate), dictionary,
   8782                                   attrs);
   8783     }
   8784   }
   8785 
   8786   return Just(true);
   8787 }
   8788 
   8789 
   8790 Handle<Object> JSObject::FastPropertyAt(Handle<JSObject> object,
   8791                                         Representation representation,
   8792                                         FieldIndex index) {
   8793   Isolate* isolate = object->GetIsolate();
   8794   if (object->IsUnboxedDoubleField(index)) {
   8795     double value = object->RawFastDoublePropertyAt(index);
   8796     return isolate->factory()->NewHeapNumber(value);
   8797   }
   8798   Handle<Object> raw_value(object->RawFastPropertyAt(index), isolate);
   8799   return Object::WrapForRead(isolate, raw_value, representation);
   8800 }
   8801 
   8802 // static
   8803 MaybeHandle<Object> JSReceiver::ToPrimitive(Handle<JSReceiver> receiver,
   8804                                             ToPrimitiveHint hint) {
   8805   Isolate* const isolate = receiver->GetIsolate();
   8806   Handle<Object> exotic_to_prim;
   8807   ASSIGN_RETURN_ON_EXCEPTION(
   8808       isolate, exotic_to_prim,
   8809       GetMethod(receiver, isolate->factory()->to_primitive_symbol()), Object);
   8810   if (!exotic_to_prim->IsUndefined(isolate)) {
   8811     Handle<Object> hint_string =
   8812         isolate->factory()->ToPrimitiveHintString(hint);
   8813     Handle<Object> result;
   8814     ASSIGN_RETURN_ON_EXCEPTION(
   8815         isolate, result,
   8816         Execution::Call(isolate, exotic_to_prim, receiver, 1, &hint_string),
   8817         Object);
   8818     if (result->IsPrimitive()) return result;
   8819     THROW_NEW_ERROR(isolate,
   8820                     NewTypeError(MessageTemplate::kCannotConvertToPrimitive),
   8821                     Object);
   8822   }
   8823   return OrdinaryToPrimitive(receiver, (hint == ToPrimitiveHint::kString)
   8824                                            ? OrdinaryToPrimitiveHint::kString
   8825                                            : OrdinaryToPrimitiveHint::kNumber);
   8826 }
   8827 
   8828 
   8829 // static
   8830 MaybeHandle<Object> JSReceiver::OrdinaryToPrimitive(
   8831     Handle<JSReceiver> receiver, OrdinaryToPrimitiveHint hint) {
   8832   Isolate* const isolate = receiver->GetIsolate();
   8833   Handle<String> method_names[2];
   8834   switch (hint) {
   8835     case OrdinaryToPrimitiveHint::kNumber:
   8836       method_names[0] = isolate->factory()->valueOf_string();
   8837       method_names[1] = isolate->factory()->toString_string();
   8838       break;
   8839     case OrdinaryToPrimitiveHint::kString:
   8840       method_names[0] = isolate->factory()->toString_string();
   8841       method_names[1] = isolate->factory()->valueOf_string();
   8842       break;
   8843   }
   8844   for (Handle<String> name : method_names) {
   8845     Handle<Object> method;
   8846     ASSIGN_RETURN_ON_EXCEPTION(isolate, method,
   8847                                JSReceiver::GetProperty(isolate, receiver, name),
   8848                                Object);
   8849     if (method->IsCallable()) {
   8850       Handle<Object> result;
   8851       ASSIGN_RETURN_ON_EXCEPTION(
   8852           isolate, result,
   8853           Execution::Call(isolate, method, receiver, 0, nullptr), Object);
   8854       if (result->IsPrimitive()) return result;
   8855     }
   8856   }
   8857   THROW_NEW_ERROR(isolate,
   8858                   NewTypeError(MessageTemplate::kCannotConvertToPrimitive),
   8859                   Object);
   8860 }
   8861 
   8862 
   8863 // TODO(cbruni/jkummerow): Consider moving this into elements.cc.
   8864 bool JSObject::HasEnumerableElements() {
   8865   // TODO(cbruni): cleanup
   8866   JSObject* object = this;
   8867   switch (object->GetElementsKind()) {
   8868     case PACKED_SMI_ELEMENTS:
   8869     case PACKED_ELEMENTS:
   8870     case PACKED_DOUBLE_ELEMENTS: {
   8871       int length = object->IsJSArray()
   8872                        ? Smi::ToInt(JSArray::cast(object)->length())
   8873                        : object->elements()->length();
   8874       return length > 0;
   8875     }
   8876     case HOLEY_SMI_ELEMENTS:
   8877     case HOLEY_ELEMENTS: {
   8878       FixedArray* elements = FixedArray::cast(object->elements());
   8879       int length = object->IsJSArray()
   8880                        ? Smi::ToInt(JSArray::cast(object)->length())
   8881                        : elements->length();
   8882       Isolate* isolate = GetIsolate();
   8883       for (int i = 0; i < length; i++) {
   8884         if (!elements->is_the_hole(isolate, i)) return true;
   8885       }
   8886       return false;
   8887     }
   8888     case HOLEY_DOUBLE_ELEMENTS: {
   8889       int length = object->IsJSArray()
   8890                        ? Smi::ToInt(JSArray::cast(object)->length())
   8891                        : object->elements()->length();
   8892       // Zero-length arrays would use the empty FixedArray...
   8893       if (length == 0) return false;
   8894       // ...so only cast to FixedDoubleArray otherwise.
   8895       FixedDoubleArray* elements = FixedDoubleArray::cast(object->elements());
   8896       for (int i = 0; i < length; i++) {
   8897         if (!elements->is_the_hole(i)) return true;
   8898       }
   8899       return false;
   8900     }
   8901 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) case TYPE##_ELEMENTS:
   8902 
   8903       TYPED_ARRAYS(TYPED_ARRAY_CASE)
   8904 #undef TYPED_ARRAY_CASE
   8905       {
   8906         int length = object->elements()->length();
   8907         return length > 0;
   8908       }
   8909     case DICTIONARY_ELEMENTS: {
   8910       NumberDictionary* elements = NumberDictionary::cast(object->elements());
   8911       return elements->NumberOfEnumerableProperties() > 0;
   8912     }
   8913     case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
   8914     case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
   8915       // We're approximating non-empty arguments objects here.
   8916       return true;
   8917     case FAST_STRING_WRAPPER_ELEMENTS:
   8918     case SLOW_STRING_WRAPPER_ELEMENTS:
   8919       if (String::cast(JSValue::cast(object)->value())->length() > 0) {
   8920         return true;
   8921       }
   8922       return object->elements()->length() > 0;
   8923     case NO_ELEMENTS:
   8924       return false;
   8925   }
   8926   UNREACHABLE();
   8927 }
   8928 
   8929 int Map::NumberOfEnumerableProperties() const {
   8930   int result = 0;
   8931   DescriptorArray* descs = instance_descriptors();
   8932   int limit = NumberOfOwnDescriptors();
   8933   for (int i = 0; i < limit; i++) {
   8934     if ((descs->GetDetails(i).attributes() & ONLY_ENUMERABLE) == 0 &&
   8935         !descs->GetKey(i)->FilterKey(ENUMERABLE_STRINGS)) {
   8936       result++;
   8937     }
   8938   }
   8939   return result;
   8940 }
   8941 
   8942 int Map::NextFreePropertyIndex() const {
   8943   int free_index = 0;
   8944   int number_of_own_descriptors = NumberOfOwnDescriptors();
   8945   DescriptorArray* descs = instance_descriptors();
   8946   for (int i = 0; i < number_of_own_descriptors; i++) {
   8947     PropertyDetails details = descs->GetDetails(i);
   8948     if (details.location() == kField) {
   8949       int candidate = details.field_index() + details.field_width_in_words();
   8950       if (candidate > free_index) free_index = candidate;
   8951     }
   8952   }
   8953   return free_index;
   8954 }
   8955 
   8956 bool Map::OnlyHasSimpleProperties() const {
   8957   // Wrapped string elements aren't explicitly stored in the elements backing
   8958   // store, but are loaded indirectly from the underlying string.
   8959   return !IsStringWrapperElementsKind(elements_kind()) &&
   8960          !IsSpecialReceiverMap() && !has_hidden_prototype() &&
   8961          !is_dictionary_map();
   8962 }
   8963 
   8964 V8_WARN_UNUSED_RESULT Maybe<bool> FastGetOwnValuesOrEntries(
   8965     Isolate* isolate, Handle<JSReceiver> receiver, bool get_entries,
   8966     Handle<FixedArray>* result) {
   8967   Handle<Map> map(JSReceiver::cast(*receiver)->map(), isolate);
   8968 
   8969   if (!map->IsJSObjectMap()) return Just(false);
   8970   if (!map->OnlyHasSimpleProperties()) return Just(false);
   8971 
   8972   Handle<JSObject> object(JSObject::cast(*receiver), isolate);
   8973 
   8974   Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate);
   8975   int number_of_own_descriptors = map->NumberOfOwnDescriptors();
   8976   int number_of_own_elements =
   8977       object->GetElementsAccessor()->GetCapacity(*object, object->elements());
   8978   Handle<FixedArray> values_or_entries = isolate->factory()->NewFixedArray(
   8979       number_of_own_descriptors + number_of_own_elements);
   8980   int count = 0;
   8981 
   8982   if (object->elements() != ReadOnlyRoots(isolate).empty_fixed_array()) {
   8983     MAYBE_RETURN(object->GetElementsAccessor()->CollectValuesOrEntries(
   8984                      isolate, object, values_or_entries, get_entries, &count,
   8985                      ENUMERABLE_STRINGS),
   8986                  Nothing<bool>());
   8987   }
   8988 
   8989   bool stable = object->map() == *map;
   8990 
   8991   for (int index = 0; index < number_of_own_descriptors; index++) {
   8992     Handle<Name> next_key(descriptors->GetKey(index), isolate);
   8993     if (!next_key->IsString()) continue;
   8994     Handle<Object> prop_value;
   8995 
   8996     // Directly decode from the descriptor array if |from| did not change shape.
   8997     if (stable) {
   8998       PropertyDetails details = descriptors->GetDetails(index);
   8999       if (!details.IsEnumerable()) continue;
   9000       if (details.kind() == kData) {
   9001         if (details.location() == kDescriptor) {
   9002           prop_value = handle(descriptors->GetStrongValue(index), isolate);
   9003         } else {
   9004           Representation representation = details.representation();
   9005           FieldIndex field_index = FieldIndex::ForDescriptor(*map, index);
   9006           prop_value =
   9007               JSObject::FastPropertyAt(object, representation, field_index);
   9008         }
   9009       } else {
   9010         ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   9011             isolate, prop_value,
   9012             JSReceiver::GetProperty(isolate, object, next_key),
   9013             Nothing<bool>());
   9014         stable = object->map() == *map;
   9015       }
   9016     } else {
   9017       // If the map did change, do a slower lookup. We are still guaranteed that
   9018       // the object has a simple shape, and that the key is a name.
   9019       LookupIterator it(isolate, object, next_key,
   9020                         LookupIterator::OWN_SKIP_INTERCEPTOR);
   9021       if (!it.IsFound()) continue;
   9022       DCHECK(it.state() == LookupIterator::DATA ||
   9023              it.state() == LookupIterator::ACCESSOR);
   9024       if (!it.IsEnumerable()) continue;
   9025       ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   9026           isolate, prop_value, Object::GetProperty(&it), Nothing<bool>());
   9027     }
   9028 
   9029     if (get_entries) {
   9030       prop_value = MakeEntryPair(isolate, next_key, prop_value);
   9031     }
   9032 
   9033     values_or_entries->set(count, *prop_value);
   9034     count++;
   9035   }
   9036 
   9037   DCHECK_LE(count, values_or_entries->length());
   9038   *result = FixedArray::ShrinkOrEmpty(isolate, values_or_entries, count);
   9039   return Just(true);
   9040 }
   9041 
   9042 MaybeHandle<FixedArray> GetOwnValuesOrEntries(Isolate* isolate,
   9043                                               Handle<JSReceiver> object,
   9044                                               PropertyFilter filter,
   9045                                               bool try_fast_path,
   9046                                               bool get_entries) {
   9047   Handle<FixedArray> values_or_entries;
   9048   if (try_fast_path && filter == ENUMERABLE_STRINGS) {
   9049     Maybe<bool> fast_values_or_entries = FastGetOwnValuesOrEntries(
   9050         isolate, object, get_entries, &values_or_entries);
   9051     if (fast_values_or_entries.IsNothing()) return MaybeHandle<FixedArray>();
   9052     if (fast_values_or_entries.FromJust()) return values_or_entries;
   9053   }
   9054 
   9055   PropertyFilter key_filter =
   9056       static_cast<PropertyFilter>(filter & ~ONLY_ENUMERABLE);
   9057 
   9058   Handle<FixedArray> keys;
   9059   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   9060       isolate, keys,
   9061       KeyAccumulator::GetKeys(object, KeyCollectionMode::kOwnOnly, key_filter,
   9062                               GetKeysConversion::kConvertToString),
   9063       MaybeHandle<FixedArray>());
   9064 
   9065   values_or_entries = isolate->factory()->NewFixedArray(keys->length());
   9066   int length = 0;
   9067 
   9068   for (int i = 0; i < keys->length(); ++i) {
   9069     Handle<Name> key = Handle<Name>::cast(handle(keys->get(i), isolate));
   9070 
   9071     if (filter & ONLY_ENUMERABLE) {
   9072       PropertyDescriptor descriptor;
   9073       Maybe<bool> did_get_descriptor = JSReceiver::GetOwnPropertyDescriptor(
   9074           isolate, object, key, &descriptor);
   9075       MAYBE_RETURN(did_get_descriptor, MaybeHandle<FixedArray>());
   9076       if (!did_get_descriptor.FromJust() || !descriptor.enumerable()) continue;
   9077     }
   9078 
   9079     Handle<Object> value;
   9080     ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   9081         isolate, value, JSReceiver::GetPropertyOrElement(isolate, object, key),
   9082         MaybeHandle<FixedArray>());
   9083 
   9084     if (get_entries) {
   9085       Handle<FixedArray> entry_storage =
   9086           isolate->factory()->NewUninitializedFixedArray(2);
   9087       entry_storage->set(0, *key);
   9088       entry_storage->set(1, *value);
   9089       value = isolate->factory()->NewJSArrayWithElements(entry_storage,
   9090                                                          PACKED_ELEMENTS, 2);
   9091     }
   9092 
   9093     values_or_entries->set(length, *value);
   9094     length++;
   9095   }
   9096   DCHECK_LE(length, values_or_entries->length());
   9097   return FixedArray::ShrinkOrEmpty(isolate, values_or_entries, length);
   9098 }
   9099 
   9100 MaybeHandle<FixedArray> JSReceiver::GetOwnValues(Handle<JSReceiver> object,
   9101                                                  PropertyFilter filter,
   9102                                                  bool try_fast_path) {
   9103   return GetOwnValuesOrEntries(object->GetIsolate(), object, filter,
   9104                                try_fast_path, false);
   9105 }
   9106 
   9107 MaybeHandle<FixedArray> JSReceiver::GetOwnEntries(Handle<JSReceiver> object,
   9108                                                   PropertyFilter filter,
   9109                                                   bool try_fast_path) {
   9110   return GetOwnValuesOrEntries(object->GetIsolate(), object, filter,
   9111                                try_fast_path, true);
   9112 }
   9113 
   9114 Handle<FixedArray> JSReceiver::GetOwnElementIndices(Isolate* isolate,
   9115                                                     Handle<JSReceiver> receiver,
   9116                                                     Handle<JSObject> object) {
   9117   KeyAccumulator accumulator(isolate, KeyCollectionMode::kOwnOnly,
   9118                              ALL_PROPERTIES);
   9119   accumulator.CollectOwnElementIndices(receiver, object);
   9120   Handle<FixedArray> keys =
   9121       accumulator.GetKeys(GetKeysConversion::kKeepNumbers);
   9122   DCHECK(keys->ContainsSortedNumbers());
   9123   return keys;
   9124 }
   9125 
   9126 bool Map::DictionaryElementsInPrototypeChainOnly(Isolate* isolate) {
   9127   if (IsDictionaryElementsKind(elements_kind())) {
   9128     return false;
   9129   }
   9130 
   9131   for (PrototypeIterator iter(isolate, this); !iter.IsAtEnd(); iter.Advance()) {
   9132     // Be conservative, don't walk into proxies.
   9133     if (iter.GetCurrent()->IsJSProxy()) return true;
   9134     // String wrappers have non-configurable, non-writable elements.
   9135     if (iter.GetCurrent()->IsStringWrapper()) return true;
   9136     JSObject* current = iter.GetCurrent<JSObject>();
   9137 
   9138     if (current->HasDictionaryElements() &&
   9139         current->element_dictionary()->requires_slow_elements()) {
   9140       return true;
   9141     }
   9142 
   9143     if (current->HasSlowArgumentsElements()) {
   9144       FixedArray* parameter_map = FixedArray::cast(current->elements());
   9145       Object* arguments = parameter_map->get(1);
   9146       if (NumberDictionary::cast(arguments)->requires_slow_elements()) {
   9147         return true;
   9148       }
   9149     }
   9150   }
   9151 
   9152   return false;
   9153 }
   9154 
   9155 
   9156 MaybeHandle<Object> JSObject::DefineAccessor(Handle<JSObject> object,
   9157                                              Handle<Name> name,
   9158                                              Handle<Object> getter,
   9159                                              Handle<Object> setter,
   9160                                              PropertyAttributes attributes) {
   9161   Isolate* isolate = object->GetIsolate();
   9162 
   9163   LookupIterator it = LookupIterator::PropertyOrElement(
   9164       isolate, object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
   9165   return DefineAccessor(&it, getter, setter, attributes);
   9166 }
   9167 
   9168 
   9169 MaybeHandle<Object> JSObject::DefineAccessor(LookupIterator* it,
   9170                                              Handle<Object> getter,
   9171                                              Handle<Object> setter,
   9172                                              PropertyAttributes attributes) {
   9173   Isolate* isolate = it->isolate();
   9174 
   9175   it->UpdateProtector();
   9176 
   9177   if (it->state() == LookupIterator::ACCESS_CHECK) {
   9178     if (!it->HasAccess()) {
   9179       isolate->ReportFailedAccessCheck(it->GetHolder<JSObject>());
   9180       RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
   9181       return isolate->factory()->undefined_value();
   9182     }
   9183     it->Next();
   9184   }
   9185 
   9186   Handle<JSObject> object = Handle<JSObject>::cast(it->GetReceiver());
   9187   // Ignore accessors on typed arrays.
   9188   if (it->IsElement() && object->HasFixedTypedArrayElements()) {
   9189     return it->factory()->undefined_value();
   9190   }
   9191 
   9192   DCHECK(getter->IsCallable() || getter->IsUndefined(isolate) ||
   9193          getter->IsNull(isolate) || getter->IsFunctionTemplateInfo());
   9194   DCHECK(setter->IsCallable() || setter->IsUndefined(isolate) ||
   9195          setter->IsNull(isolate) || setter->IsFunctionTemplateInfo());
   9196   it->TransitionToAccessorProperty(getter, setter, attributes);
   9197 
   9198   return isolate->factory()->undefined_value();
   9199 }
   9200 
   9201 MaybeHandle<Object> JSObject::SetAccessor(Handle<JSObject> object,
   9202                                           Handle<Name> name,
   9203                                           Handle<AccessorInfo> info,
   9204                                           PropertyAttributes attributes) {
   9205   Isolate* isolate = object->GetIsolate();
   9206 
   9207   LookupIterator it = LookupIterator::PropertyOrElement(
   9208       isolate, object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
   9209 
   9210   // Duplicate ACCESS_CHECK outside of GetPropertyAttributes for the case that
   9211   // the FailedAccessCheckCallbackFunction doesn't throw an exception.
   9212   //
   9213   // TODO(verwaest): Force throw an exception if the callback doesn't, so we can
   9214   // remove reliance on default return values.
   9215   if (it.state() == LookupIterator::ACCESS_CHECK) {
   9216     if (!it.HasAccess()) {
   9217       isolate->ReportFailedAccessCheck(object);
   9218       RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
   9219       return it.factory()->undefined_value();
   9220     }
   9221     it.Next();
   9222   }
   9223 
   9224   // Ignore accessors on typed arrays.
   9225   if (it.IsElement() && object->HasFixedTypedArrayElements()) {
   9226     return it.factory()->undefined_value();
   9227   }
   9228 
   9229   CHECK(GetPropertyAttributes(&it).IsJust());
   9230 
   9231   // ES5 forbids turning a property into an accessor if it's not
   9232   // configurable. See 8.6.1 (Table 5).
   9233   if (it.IsFound() && !it.IsConfigurable()) {
   9234     return it.factory()->undefined_value();
   9235   }
   9236 
   9237   it.TransitionToAccessorPair(info, attributes);
   9238 
   9239   return object;
   9240 }
   9241 
   9242 Object* JSObject::SlowReverseLookup(Object* value) {
   9243   if (HasFastProperties()) {
   9244     int number_of_own_descriptors = map()->NumberOfOwnDescriptors();
   9245     DescriptorArray* descs = map()->instance_descriptors();
   9246     bool value_is_number = value->IsNumber();
   9247     for (int i = 0; i < number_of_own_descriptors; i++) {
   9248       PropertyDetails details = descs->GetDetails(i);
   9249       if (details.location() == kField) {
   9250         DCHECK_EQ(kData, details.kind());
   9251         FieldIndex field_index = FieldIndex::ForDescriptor(map(), i);
   9252         if (IsUnboxedDoubleField(field_index)) {
   9253           if (value_is_number) {
   9254             double property = RawFastDoublePropertyAt(field_index);
   9255             if (property == value->Number()) {
   9256               return descs->GetKey(i);
   9257             }
   9258           }
   9259         } else {
   9260           Object* property = RawFastPropertyAt(field_index);
   9261           if (field_index.is_double()) {
   9262             DCHECK(property->IsMutableHeapNumber());
   9263             if (value_is_number && property->Number() == value->Number()) {
   9264               return descs->GetKey(i);
   9265             }
   9266           } else if (property == value) {
   9267             return descs->GetKey(i);
   9268           }
   9269         }
   9270       } else {
   9271         DCHECK_EQ(kDescriptor, details.location());
   9272         if (details.kind() == kData) {
   9273           if (descs->GetStrongValue(i) == value) {
   9274             return descs->GetKey(i);
   9275           }
   9276         }
   9277       }
   9278     }
   9279     return GetReadOnlyRoots().undefined_value();
   9280   } else if (IsJSGlobalObject()) {
   9281     return JSGlobalObject::cast(this)->global_dictionary()->SlowReverseLookup(
   9282         value);
   9283   } else {
   9284     return property_dictionary()->SlowReverseLookup(value);
   9285   }
   9286 }
   9287 
   9288 Handle<Map> Map::RawCopy(Isolate* isolate, Handle<Map> map, int instance_size,
   9289                          int inobject_properties) {
   9290   Handle<Map> result = isolate->factory()->NewMap(
   9291       map->instance_type(), instance_size, TERMINAL_FAST_ELEMENTS_KIND,
   9292       inobject_properties);
   9293   Handle<Object> prototype(map->prototype(), isolate);
   9294   Map::SetPrototype(isolate, result, prototype);
   9295   result->set_constructor_or_backpointer(map->GetConstructor());
   9296   result->set_bit_field(map->bit_field());
   9297   result->set_bit_field2(map->bit_field2());
   9298   int new_bit_field3 = map->bit_field3();
   9299   new_bit_field3 = OwnsDescriptorsBit::update(new_bit_field3, true);
   9300   new_bit_field3 = NumberOfOwnDescriptorsBits::update(new_bit_field3, 0);
   9301   new_bit_field3 = EnumLengthBits::update(new_bit_field3,
   9302                                           kInvalidEnumCacheSentinel);
   9303   new_bit_field3 = IsDeprecatedBit::update(new_bit_field3, false);
   9304   if (!map->is_dictionary_map()) {
   9305     new_bit_field3 = IsUnstableBit::update(new_bit_field3, false);
   9306   }
   9307   result->set_bit_field3(new_bit_field3);
   9308   return result;
   9309 }
   9310 
   9311 Handle<Map> Map::Normalize(Isolate* isolate, Handle<Map> fast_map,
   9312                            PropertyNormalizationMode mode, const char* reason) {
   9313   DCHECK(!fast_map->is_dictionary_map());
   9314 
   9315   Handle<Object> maybe_cache(isolate->native_context()->normalized_map_cache(),
   9316                              isolate);
   9317   bool use_cache =
   9318       !fast_map->is_prototype_map() && !maybe_cache->IsUndefined(isolate);
   9319   Handle<NormalizedMapCache> cache;
   9320   if (use_cache) cache = Handle<NormalizedMapCache>::cast(maybe_cache);
   9321 
   9322   Handle<Map> new_map;
   9323   if (use_cache && cache->Get(fast_map, mode).ToHandle(&new_map)) {
   9324 #ifdef VERIFY_HEAP
   9325     if (FLAG_verify_heap) new_map->DictionaryMapVerify(isolate);
   9326 #endif
   9327 #ifdef ENABLE_SLOW_DCHECKS
   9328     if (FLAG_enable_slow_asserts) {
   9329       // The cached map should match newly created normalized map bit-by-bit,
   9330       // except for the code cache, which can contain some ICs which can be
   9331       // applied to the shared map, dependent code and weak cell cache.
   9332       Handle<Map> fresh = Map::CopyNormalized(isolate, fast_map, mode);
   9333 
   9334       if (new_map->is_prototype_map()) {
   9335         // For prototype maps, the PrototypeInfo is not copied.
   9336         DCHECK_EQ(0, memcmp(reinterpret_cast<void*>(fresh->address()),
   9337                             reinterpret_cast<void*>(new_map->address()),
   9338                             kTransitionsOrPrototypeInfoOffset));
   9339         DCHECK_EQ(fresh->raw_transitions(),
   9340                   MaybeObject::FromObject(Smi::kZero));
   9341         STATIC_ASSERT(kDescriptorsOffset ==
   9342                       kTransitionsOrPrototypeInfoOffset + kPointerSize);
   9343         DCHECK_EQ(0, memcmp(HeapObject::RawField(*fresh, kDescriptorsOffset),
   9344                             HeapObject::RawField(*new_map, kDescriptorsOffset),
   9345                             kDependentCodeOffset - kDescriptorsOffset));
   9346       } else {
   9347         DCHECK_EQ(0, memcmp(reinterpret_cast<void*>(fresh->address()),
   9348                             reinterpret_cast<void*>(new_map->address()),
   9349                             Map::kDependentCodeOffset));
   9350       }
   9351       STATIC_ASSERT(Map::kPrototypeValidityCellOffset ==
   9352                     Map::kDependentCodeOffset + kPointerSize);
   9353       int offset = Map::kPrototypeValidityCellOffset + kPointerSize;
   9354       DCHECK_EQ(0, memcmp(reinterpret_cast<void*>(fresh->address() + offset),
   9355                           reinterpret_cast<void*>(new_map->address() + offset),
   9356                           Map::kSize - offset));
   9357     }
   9358 #endif
   9359   } else {
   9360     new_map = Map::CopyNormalized(isolate, fast_map, mode);
   9361     if (use_cache) {
   9362       cache->Set(fast_map, new_map);
   9363       isolate->counters()->maps_normalized()->Increment();
   9364     }
   9365     if (FLAG_trace_maps) {
   9366       LOG(isolate, MapEvent("Normalize", *fast_map, *new_map, reason));
   9367     }
   9368   }
   9369   fast_map->NotifyLeafMapLayoutChange(isolate);
   9370   return new_map;
   9371 }
   9372 
   9373 Handle<Map> Map::CopyNormalized(Isolate* isolate, Handle<Map> map,
   9374                                 PropertyNormalizationMode mode) {
   9375   int new_instance_size = map->instance_size();
   9376   if (mode == CLEAR_INOBJECT_PROPERTIES) {
   9377     new_instance_size -= map->GetInObjectProperties() * kPointerSize;
   9378   }
   9379 
   9380   Handle<Map> result = RawCopy(
   9381       isolate, map, new_instance_size,
   9382       mode == CLEAR_INOBJECT_PROPERTIES ? 0 : map->GetInObjectProperties());
   9383   // Clear the unused_property_fields explicitly as this field should not
   9384   // be accessed for normalized maps.
   9385   result->SetInObjectUnusedPropertyFields(0);
   9386   result->set_is_dictionary_map(true);
   9387   result->set_is_migration_target(false);
   9388   result->set_may_have_interesting_symbols(true);
   9389   result->set_construction_counter(kNoSlackTracking);
   9390 
   9391 #ifdef VERIFY_HEAP
   9392   if (FLAG_verify_heap) result->DictionaryMapVerify(isolate);
   9393 #endif
   9394 
   9395   return result;
   9396 }
   9397 
   9398 // Return an immutable prototype exotic object version of the input map.
   9399 // Never even try to cache it in the transition tree, as it is intended
   9400 // for the global object and its prototype chain, and excluding it saves
   9401 // memory on the map transition tree.
   9402 
   9403 // static
   9404 Handle<Map> Map::TransitionToImmutableProto(Isolate* isolate, Handle<Map> map) {
   9405   Handle<Map> new_map = Map::Copy(isolate, map, "ImmutablePrototype");
   9406   new_map->set_is_immutable_proto(true);
   9407   return new_map;
   9408 }
   9409 
   9410 namespace {
   9411 void EnsureInitialMap(Isolate* isolate, Handle<Map> map) {
   9412 #ifdef DEBUG
   9413   // Strict function maps have Function as a constructor but the
   9414   // Function's initial map is a sloppy function map. Same holds for
   9415   // GeneratorFunction / AsyncFunction and its initial map.
   9416   Object* constructor = map->GetConstructor();
   9417   DCHECK(constructor->IsJSFunction());
   9418   DCHECK(*map == JSFunction::cast(constructor)->initial_map() ||
   9419          *map == *isolate->strict_function_map() ||
   9420          *map == *isolate->strict_function_with_name_map() ||
   9421          *map == *isolate->generator_function_map() ||
   9422          *map == *isolate->generator_function_with_name_map() ||
   9423          *map == *isolate->generator_function_with_home_object_map() ||
   9424          *map == *isolate->generator_function_with_name_and_home_object_map() ||
   9425          *map == *isolate->async_function_map() ||
   9426          *map == *isolate->async_function_with_name_map() ||
   9427          *map == *isolate->async_function_with_home_object_map() ||
   9428          *map == *isolate->async_function_with_name_and_home_object_map());
   9429 #endif
   9430   // Initial maps must always own their descriptors and it's descriptor array
   9431   // does not contain descriptors that do not belong to the map.
   9432   DCHECK(map->owns_descriptors());
   9433   DCHECK_EQ(map->NumberOfOwnDescriptors(),
   9434             map->instance_descriptors()->number_of_descriptors());
   9435 }
   9436 }  // namespace
   9437 
   9438 // static
   9439 Handle<Map> Map::CopyInitialMapNormalized(Isolate* isolate, Handle<Map> map,
   9440                                           PropertyNormalizationMode mode) {
   9441   EnsureInitialMap(isolate, map);
   9442   return CopyNormalized(isolate, map, mode);
   9443 }
   9444 
   9445 // static
   9446 Handle<Map> Map::CopyInitialMap(Isolate* isolate, Handle<Map> map,
   9447                                 int instance_size, int inobject_properties,
   9448                                 int unused_property_fields) {
   9449   EnsureInitialMap(isolate, map);
   9450   Handle<Map> result =
   9451       RawCopy(isolate, map, instance_size, inobject_properties);
   9452 
   9453   // Please note instance_type and instance_size are set when allocated.
   9454   result->SetInObjectUnusedPropertyFields(unused_property_fields);
   9455 
   9456   int number_of_own_descriptors = map->NumberOfOwnDescriptors();
   9457   if (number_of_own_descriptors > 0) {
   9458     // The copy will use the same descriptors array.
   9459     result->UpdateDescriptors(map->instance_descriptors(),
   9460                               map->GetLayoutDescriptor());
   9461     result->SetNumberOfOwnDescriptors(number_of_own_descriptors);
   9462 
   9463     DCHECK_EQ(result->NumberOfFields(),
   9464               result->GetInObjectProperties() - result->UnusedPropertyFields());
   9465   }
   9466 
   9467   return result;
   9468 }
   9469 
   9470 Handle<Map> Map::CopyDropDescriptors(Isolate* isolate, Handle<Map> map) {
   9471   Handle<Map> result =
   9472       RawCopy(isolate, map, map->instance_size(),
   9473               map->IsJSObjectMap() ? map->GetInObjectProperties() : 0);
   9474 
   9475   // Please note instance_type and instance_size are set when allocated.
   9476   if (map->IsJSObjectMap()) {
   9477     result->CopyUnusedPropertyFields(*map);
   9478   }
   9479   map->NotifyLeafMapLayoutChange(isolate);
   9480   return result;
   9481 }
   9482 
   9483 Handle<Map> Map::ShareDescriptor(Isolate* isolate, Handle<Map> map,
   9484                                  Handle<DescriptorArray> descriptors,
   9485                                  Descriptor* descriptor) {
   9486   // Sanity check. This path is only to be taken if the map owns its descriptor
   9487   // array, implying that its NumberOfOwnDescriptors equals the number of
   9488   // descriptors in the descriptor array.
   9489   DCHECK_EQ(map->NumberOfOwnDescriptors(),
   9490             map->instance_descriptors()->number_of_descriptors());
   9491 
   9492   Handle<Map> result = CopyDropDescriptors(isolate, map);
   9493   Handle<Name> name = descriptor->GetKey();
   9494 
   9495   // Properly mark the {result} if the {name} is an "interesting symbol".
   9496   if (name->IsInterestingSymbol()) {
   9497     result->set_may_have_interesting_symbols(true);
   9498   }
   9499 
   9500   // Ensure there's space for the new descriptor in the shared descriptor array.
   9501   if (descriptors->NumberOfSlackDescriptors() == 0) {
   9502     int old_size = descriptors->number_of_descriptors();
   9503     if (old_size == 0) {
   9504       descriptors = DescriptorArray::Allocate(isolate, 0, 1);
   9505     } else {
   9506       int slack = SlackForArraySize(old_size, kMaxNumberOfDescriptors);
   9507       EnsureDescriptorSlack(isolate, map, slack);
   9508       descriptors = handle(map->instance_descriptors(), isolate);
   9509     }
   9510   }
   9511 
   9512   Handle<LayoutDescriptor> layout_descriptor =
   9513       FLAG_unbox_double_fields
   9514           ? LayoutDescriptor::ShareAppend(isolate, map,
   9515                                           descriptor->GetDetails())
   9516           : handle(LayoutDescriptor::FastPointerLayout(), isolate);
   9517 
   9518   {
   9519     DisallowHeapAllocation no_gc;
   9520     descriptors->Append(descriptor);
   9521     result->InitializeDescriptors(*descriptors, *layout_descriptor);
   9522   }
   9523 
   9524   DCHECK(result->NumberOfOwnDescriptors() == map->NumberOfOwnDescriptors() + 1);
   9525   ConnectTransition(isolate, map, result, name, SIMPLE_PROPERTY_TRANSITION);
   9526 
   9527   return result;
   9528 }
   9529 
   9530 void Map::ConnectTransition(Isolate* isolate, Handle<Map> parent,
   9531                             Handle<Map> child, Handle<Name> name,
   9532                             SimpleTransitionFlag flag) {
   9533   DCHECK_IMPLIES(name->IsInterestingSymbol(),
   9534                  child->may_have_interesting_symbols());
   9535   DCHECK_IMPLIES(parent->may_have_interesting_symbols(),
   9536                  child->may_have_interesting_symbols());
   9537   // Do not track transitions during bootstrap except for element transitions.
   9538   if (isolate->bootstrapper()->IsActive() &&
   9539       !name.is_identical_to(isolate->factory()->elements_transition_symbol())) {
   9540     if (FLAG_trace_maps) {
   9541       LOG(isolate,
   9542           MapEvent("Transition", *parent, *child,
   9543                    child->is_prototype_map() ? "prototype" : "", *name));
   9544     }
   9545     return;
   9546   }
   9547   if (!parent->GetBackPointer()->IsUndefined(isolate)) {
   9548     parent->set_owns_descriptors(false);
   9549   } else {
   9550     // |parent| is initial map and it must keep the ownership, there must be no
   9551     // descriptors in the descriptors array that do not belong to the map.
   9552     DCHECK(parent->owns_descriptors());
   9553     DCHECK_EQ(parent->NumberOfOwnDescriptors(),
   9554               parent->instance_descriptors()->number_of_descriptors());
   9555   }
   9556   if (parent->is_prototype_map()) {
   9557     DCHECK(child->is_prototype_map());
   9558     if (FLAG_trace_maps) {
   9559       LOG(isolate, MapEvent("Transition", *parent, *child, "prototype", *name));
   9560     }
   9561   } else {
   9562     TransitionsAccessor(isolate, parent).Insert(name, child, flag);
   9563     if (FLAG_trace_maps) {
   9564       LOG(isolate, MapEvent("Transition", *parent, *child, "", *name));
   9565     }
   9566   }
   9567 }
   9568 
   9569 Handle<Map> Map::CopyReplaceDescriptors(
   9570     Isolate* isolate, Handle<Map> map, Handle<DescriptorArray> descriptors,
   9571     Handle<LayoutDescriptor> layout_descriptor, TransitionFlag flag,
   9572     MaybeHandle<Name> maybe_name, const char* reason,
   9573     SimpleTransitionFlag simple_flag) {
   9574   DCHECK(descriptors->IsSortedNoDuplicates());
   9575 
   9576   Handle<Map> result = CopyDropDescriptors(isolate, map);
   9577 
   9578   // Properly mark the {result} if the {name} is an "interesting symbol".
   9579   Handle<Name> name;
   9580   if (maybe_name.ToHandle(&name) && name->IsInterestingSymbol()) {
   9581     result->set_may_have_interesting_symbols(true);
   9582   }
   9583 
   9584   if (!map->is_prototype_map()) {
   9585     if (flag == INSERT_TRANSITION &&
   9586         TransitionsAccessor(isolate, map).CanHaveMoreTransitions()) {
   9587       result->InitializeDescriptors(*descriptors, *layout_descriptor);
   9588 
   9589       DCHECK(!maybe_name.is_null());
   9590       ConnectTransition(isolate, map, result, name, simple_flag);
   9591     } else {
   9592       descriptors->GeneralizeAllFields();
   9593       result->InitializeDescriptors(*descriptors,
   9594                                     LayoutDescriptor::FastPointerLayout());
   9595     }
   9596   } else {
   9597     result->InitializeDescriptors(*descriptors, *layout_descriptor);
   9598   }
   9599   if (FLAG_trace_maps &&
   9600       // Mirror conditions above that did not call ConnectTransition().
   9601       (map->is_prototype_map() ||
   9602        !(flag == INSERT_TRANSITION &&
   9603          TransitionsAccessor(isolate, map).CanHaveMoreTransitions()))) {
   9604     LOG(isolate, MapEvent("ReplaceDescriptors", *map, *result, reason,
   9605                           maybe_name.is_null() ? nullptr : *name));
   9606   }
   9607   return result;
   9608 }
   9609 
   9610 
   9611 // Creates transition tree starting from |split_map| and adding all descriptors
   9612 // starting from descriptor with index |split_map|.NumberOfOwnDescriptors().
   9613 // The way how it is done is tricky because of GC and special descriptors
   9614 // marking logic.
   9615 Handle<Map> Map::AddMissingTransitions(
   9616     Isolate* isolate, Handle<Map> split_map,
   9617     Handle<DescriptorArray> descriptors,
   9618     Handle<LayoutDescriptor> full_layout_descriptor) {
   9619   DCHECK(descriptors->IsSortedNoDuplicates());
   9620   int split_nof = split_map->NumberOfOwnDescriptors();
   9621   int nof_descriptors = descriptors->number_of_descriptors();
   9622   DCHECK_LT(split_nof, nof_descriptors);
   9623 
   9624   // Start with creating last map which will own full descriptors array.
   9625   // This is necessary to guarantee that GC will mark the whole descriptor
   9626   // array if any of the allocations happening below fail.
   9627   // Number of unused properties is temporarily incorrect and the layout
   9628   // descriptor could unnecessarily be in slow mode but we will fix after
   9629   // all the other intermediate maps are created.
   9630   // Also the last map might have interesting symbols, we temporarily set
   9631   // the flag and clear it right before the descriptors are installed. This
   9632   // makes heap verification happy and ensures the flag ends up accurate.
   9633   Handle<Map> last_map = CopyDropDescriptors(isolate, split_map);
   9634   last_map->InitializeDescriptors(*descriptors, *full_layout_descriptor);
   9635   last_map->SetInObjectUnusedPropertyFields(0);
   9636   last_map->set_may_have_interesting_symbols(true);
   9637 
   9638   // During creation of intermediate maps we violate descriptors sharing
   9639   // invariant since the last map is not yet connected to the transition tree
   9640   // we create here. But it is safe because GC never trims map's descriptors
   9641   // if there are no dead transitions from that map and this is exactly the
   9642   // case for all the intermediate maps we create here.
   9643   Handle<Map> map = split_map;
   9644   for (int i = split_nof; i < nof_descriptors - 1; ++i) {
   9645     Handle<Map> new_map = CopyDropDescriptors(isolate, map);
   9646     InstallDescriptors(isolate, map, new_map, i, descriptors,
   9647                        full_layout_descriptor);
   9648     map = new_map;
   9649   }
   9650   map->NotifyLeafMapLayoutChange(isolate);
   9651   last_map->set_may_have_interesting_symbols(false);
   9652   InstallDescriptors(isolate, map, last_map, nof_descriptors - 1, descriptors,
   9653                      full_layout_descriptor);
   9654   return last_map;
   9655 }
   9656 
   9657 
   9658 // Since this method is used to rewrite an existing transition tree, it can
   9659 // always insert transitions without checking.
   9660 void Map::InstallDescriptors(Isolate* isolate, Handle<Map> parent,
   9661                              Handle<Map> child, int new_descriptor,
   9662                              Handle<DescriptorArray> descriptors,
   9663                              Handle<LayoutDescriptor> full_layout_descriptor) {
   9664   DCHECK(descriptors->IsSortedNoDuplicates());
   9665 
   9666   child->set_instance_descriptors(*descriptors);
   9667   child->SetNumberOfOwnDescriptors(new_descriptor + 1);
   9668   child->CopyUnusedPropertyFields(*parent);
   9669   PropertyDetails details = descriptors->GetDetails(new_descriptor);
   9670   if (details.location() == kField) {
   9671     child->AccountAddedPropertyField();
   9672   }
   9673 
   9674   if (FLAG_unbox_double_fields) {
   9675     Handle<LayoutDescriptor> layout_descriptor =
   9676         LayoutDescriptor::AppendIfFastOrUseFull(isolate, parent, details,
   9677                                                 full_layout_descriptor);
   9678     child->set_layout_descriptor(*layout_descriptor);
   9679 #ifdef VERIFY_HEAP
   9680     // TODO(ishell): remove these checks from VERIFY_HEAP mode.
   9681     if (FLAG_verify_heap) {
   9682       CHECK(child->layout_descriptor()->IsConsistentWithMap(*child));
   9683     }
   9684 #else
   9685     SLOW_DCHECK(child->layout_descriptor()->IsConsistentWithMap(*child));
   9686 #endif
   9687     child->set_visitor_id(Map::GetVisitorId(*child));
   9688   }
   9689 
   9690   Handle<Name> name = handle(descriptors->GetKey(new_descriptor), isolate);
   9691   if (parent->may_have_interesting_symbols() || name->IsInterestingSymbol()) {
   9692     child->set_may_have_interesting_symbols(true);
   9693   }
   9694   ConnectTransition(isolate, parent, child, name, SIMPLE_PROPERTY_TRANSITION);
   9695 }
   9696 
   9697 Handle<Map> Map::CopyAsElementsKind(Isolate* isolate, Handle<Map> map,
   9698                                     ElementsKind kind, TransitionFlag flag) {
   9699   // Only certain objects are allowed to have non-terminal fast transitional
   9700   // elements kinds.
   9701   DCHECK(map->IsJSObjectMap());
   9702   DCHECK_IMPLIES(
   9703       !map->CanHaveFastTransitionableElementsKind(),
   9704       IsDictionaryElementsKind(kind) || IsTerminalElementsKind(kind));
   9705 
   9706   Map* maybe_elements_transition_map = nullptr;
   9707   if (flag == INSERT_TRANSITION) {
   9708     // Ensure we are requested to add elements kind transition "near the root".
   9709     DCHECK_EQ(map->FindRootMap(isolate)->NumberOfOwnDescriptors(),
   9710               map->NumberOfOwnDescriptors());
   9711 
   9712     maybe_elements_transition_map = map->ElementsTransitionMap();
   9713     DCHECK(maybe_elements_transition_map == nullptr ||
   9714            (maybe_elements_transition_map->elements_kind() ==
   9715                 DICTIONARY_ELEMENTS &&
   9716             kind == DICTIONARY_ELEMENTS));
   9717     DCHECK(!IsFastElementsKind(kind) ||
   9718            IsMoreGeneralElementsKindTransition(map->elements_kind(), kind));
   9719     DCHECK(kind != map->elements_kind());
   9720   }
   9721 
   9722   bool insert_transition =
   9723       flag == INSERT_TRANSITION &&
   9724       TransitionsAccessor(isolate, map).CanHaveMoreTransitions() &&
   9725       maybe_elements_transition_map == nullptr;
   9726 
   9727   if (insert_transition) {
   9728     Handle<Map> new_map = CopyForTransition(isolate, map, "CopyAsElementsKind");
   9729     new_map->set_elements_kind(kind);
   9730 
   9731     Handle<Name> name = isolate->factory()->elements_transition_symbol();
   9732     ConnectTransition(isolate, map, new_map, name, SPECIAL_TRANSITION);
   9733     return new_map;
   9734   }
   9735 
   9736   // Create a new free-floating map only if we are not allowed to store it.
   9737   Handle<Map> new_map = Copy(isolate, map, "CopyAsElementsKind");
   9738   new_map->set_elements_kind(kind);
   9739   return new_map;
   9740 }
   9741 
   9742 Handle<Map> Map::AsLanguageMode(Isolate* isolate, Handle<Map> initial_map,
   9743                                 Handle<SharedFunctionInfo> shared_info) {
   9744   DCHECK_EQ(JS_FUNCTION_TYPE, initial_map->instance_type());
   9745   // Initial map for sloppy mode function is stored in the function
   9746   // constructor. Initial maps for strict mode are cached as special transitions
   9747   // using |strict_function_transition_symbol| as a key.
   9748   if (is_sloppy(shared_info->language_mode())) return initial_map;
   9749 
   9750   Handle<Map> function_map(Map::cast(isolate->native_context()->get(
   9751                                shared_info->function_map_index())),
   9752                            isolate);
   9753 
   9754   STATIC_ASSERT(LanguageModeSize == 2);
   9755   DCHECK_EQ(LanguageMode::kStrict, shared_info->language_mode());
   9756   Handle<Symbol> transition_symbol =
   9757       isolate->factory()->strict_function_transition_symbol();
   9758   Map* maybe_transition = TransitionsAccessor(isolate, initial_map)
   9759                               .SearchSpecial(*transition_symbol);
   9760   if (maybe_transition != nullptr) {
   9761     return handle(maybe_transition, isolate);
   9762   }
   9763   initial_map->NotifyLeafMapLayoutChange(isolate);
   9764 
   9765   // Create new map taking descriptors from the |function_map| and all
   9766   // the other details from the |initial_map|.
   9767   Handle<Map> map =
   9768       Map::CopyInitialMap(isolate, function_map, initial_map->instance_size(),
   9769                           initial_map->GetInObjectProperties(),
   9770                           initial_map->UnusedPropertyFields());
   9771   map->SetConstructor(initial_map->GetConstructor());
   9772   map->set_prototype(initial_map->prototype());
   9773   map->set_construction_counter(initial_map->construction_counter());
   9774 
   9775   if (TransitionsAccessor(isolate, initial_map).CanHaveMoreTransitions()) {
   9776     Map::ConnectTransition(isolate, initial_map, map, transition_symbol,
   9777                            SPECIAL_TRANSITION);
   9778   }
   9779   return map;
   9780 }
   9781 
   9782 Handle<Map> Map::CopyForTransition(Isolate* isolate, Handle<Map> map,
   9783                                    const char* reason) {
   9784   DCHECK(!map->is_prototype_map());
   9785   Handle<Map> new_map = CopyDropDescriptors(isolate, map);
   9786 
   9787   if (map->owns_descriptors()) {
   9788     // In case the map owned its own descriptors, share the descriptors and
   9789     // transfer ownership to the new map.
   9790     // The properties did not change, so reuse descriptors.
   9791     new_map->InitializeDescriptors(map->instance_descriptors(),
   9792                                    map->GetLayoutDescriptor());
   9793   } else {
   9794     // In case the map did not own its own descriptors, a split is forced by
   9795     // copying the map; creating a new descriptor array cell.
   9796     Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate);
   9797     int number_of_own_descriptors = map->NumberOfOwnDescriptors();
   9798     Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo(
   9799         isolate, descriptors, number_of_own_descriptors);
   9800     Handle<LayoutDescriptor> new_layout_descriptor(map->GetLayoutDescriptor(),
   9801                                                    isolate);
   9802     new_map->InitializeDescriptors(*new_descriptors, *new_layout_descriptor);
   9803   }
   9804 
   9805   if (FLAG_trace_maps) {
   9806     LOG(isolate, MapEvent("CopyForTransition", *map, *new_map, reason));
   9807   }
   9808   return new_map;
   9809 }
   9810 
   9811 Handle<Map> Map::Copy(Isolate* isolate, Handle<Map> map, const char* reason) {
   9812   Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate);
   9813   int number_of_own_descriptors = map->NumberOfOwnDescriptors();
   9814   Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo(
   9815       isolate, descriptors, number_of_own_descriptors);
   9816   Handle<LayoutDescriptor> new_layout_descriptor(map->GetLayoutDescriptor(),
   9817                                                  isolate);
   9818   return CopyReplaceDescriptors(
   9819       isolate, map, new_descriptors, new_layout_descriptor, OMIT_TRANSITION,
   9820       MaybeHandle<Name>(), reason, SPECIAL_TRANSITION);
   9821 }
   9822 
   9823 
   9824 Handle<Map> Map::Create(Isolate* isolate, int inobject_properties) {
   9825   Handle<Map> copy =
   9826       Copy(isolate, handle(isolate->object_function()->initial_map(), isolate),
   9827            "MapCreate");
   9828 
   9829   // Check that we do not overflow the instance size when adding the extra
   9830   // inobject properties. If the instance size overflows, we allocate as many
   9831   // properties as we can as inobject properties.
   9832   if (inobject_properties > JSObject::kMaxInObjectProperties) {
   9833     inobject_properties = JSObject::kMaxInObjectProperties;
   9834   }
   9835 
   9836   int new_instance_size =
   9837       JSObject::kHeaderSize + kPointerSize * inobject_properties;
   9838 
   9839   // Adjust the map with the extra inobject properties.
   9840   copy->set_instance_size(new_instance_size);
   9841   copy->SetInObjectPropertiesStartInWords(JSObject::kHeaderSize / kPointerSize);
   9842   DCHECK_EQ(copy->GetInObjectProperties(), inobject_properties);
   9843   copy->SetInObjectUnusedPropertyFields(inobject_properties);
   9844   copy->set_visitor_id(Map::GetVisitorId(*copy));
   9845   return copy;
   9846 }
   9847 
   9848 Handle<Map> Map::CopyForPreventExtensions(Isolate* isolate, Handle<Map> map,
   9849                                           PropertyAttributes attrs_to_add,
   9850                                           Handle<Symbol> transition_marker,
   9851                                           const char* reason) {
   9852   int num_descriptors = map->NumberOfOwnDescriptors();
   9853   Handle<DescriptorArray> new_desc = DescriptorArray::CopyUpToAddAttributes(
   9854       isolate, handle(map->instance_descriptors(), isolate), num_descriptors,
   9855       attrs_to_add);
   9856   Handle<LayoutDescriptor> new_layout_descriptor(map->GetLayoutDescriptor(),
   9857                                                  isolate);
   9858   Handle<Map> new_map = CopyReplaceDescriptors(
   9859       isolate, map, new_desc, new_layout_descriptor, INSERT_TRANSITION,
   9860       transition_marker, reason, SPECIAL_TRANSITION);
   9861   new_map->set_is_extensible(false);
   9862   if (!IsFixedTypedArrayElementsKind(map->elements_kind())) {
   9863     ElementsKind new_kind = IsStringWrapperElementsKind(map->elements_kind())
   9864                                 ? SLOW_STRING_WRAPPER_ELEMENTS
   9865                                 : DICTIONARY_ELEMENTS;
   9866     new_map->set_elements_kind(new_kind);
   9867   }
   9868   return new_map;
   9869 }
   9870 
   9871 namespace {
   9872 
   9873 bool CanHoldValue(DescriptorArray* descriptors, int descriptor,
   9874                   PropertyConstness constness, Object* value) {
   9875   PropertyDetails details = descriptors->GetDetails(descriptor);
   9876   if (details.location() == kField) {
   9877     if (details.kind() == kData) {
   9878       return IsGeneralizableTo(constness, details.constness()) &&
   9879              value->FitsRepresentation(details.representation()) &&
   9880              descriptors->GetFieldType(descriptor)->NowContains(value);
   9881     } else {
   9882       DCHECK_EQ(kAccessor, details.kind());
   9883       return false;
   9884     }
   9885 
   9886   } else {
   9887     DCHECK_EQ(kDescriptor, details.location());
   9888     DCHECK_EQ(PropertyConstness::kConst, details.constness());
   9889     if (details.kind() == kData) {
   9890       DCHECK(!FLAG_track_constant_fields);
   9891       DCHECK(descriptors->GetStrongValue(descriptor) != value ||
   9892              value->FitsRepresentation(details.representation()));
   9893       return descriptors->GetStrongValue(descriptor) == value;
   9894     } else {
   9895       DCHECK_EQ(kAccessor, details.kind());
   9896       return false;
   9897     }
   9898   }
   9899   UNREACHABLE();
   9900 }
   9901 
   9902 Handle<Map> UpdateDescriptorForValue(Isolate* isolate, Handle<Map> map,
   9903                                      int descriptor,
   9904                                      PropertyConstness constness,
   9905                                      Handle<Object> value) {
   9906   if (CanHoldValue(map->instance_descriptors(), descriptor, constness,
   9907                    *value)) {
   9908     return map;
   9909   }
   9910 
   9911   PropertyAttributes attributes =
   9912       map->instance_descriptors()->GetDetails(descriptor).attributes();
   9913   Representation representation = value->OptimalRepresentation();
   9914   Handle<FieldType> type = value->OptimalType(isolate, representation);
   9915 
   9916   MapUpdater mu(isolate, map);
   9917   return mu.ReconfigureToDataField(descriptor, attributes, constness,
   9918                                    representation, type);
   9919 }
   9920 
   9921 }  // namespace
   9922 
   9923 // static
   9924 Handle<Map> Map::PrepareForDataProperty(Isolate* isolate, Handle<Map> map,
   9925                                         int descriptor,
   9926                                         PropertyConstness constness,
   9927                                         Handle<Object> value) {
   9928   // Dictionaries can store any property value.
   9929   DCHECK(!map->is_dictionary_map());
   9930   // Update to the newest map before storing the property.
   9931   return UpdateDescriptorForValue(isolate, Update(isolate, map), descriptor,
   9932                                   constness, value);
   9933 }
   9934 
   9935 Handle<Map> Map::TransitionToDataProperty(Isolate* isolate, Handle<Map> map,
   9936                                           Handle<Name> name,
   9937                                           Handle<Object> value,
   9938                                           PropertyAttributes attributes,
   9939                                           PropertyConstness constness,
   9940                                           StoreFromKeyed store_mode) {
   9941   RuntimeCallTimerScope stats_scope(
   9942       isolate, *map,
   9943       map->is_prototype_map()
   9944           ? RuntimeCallCounterId::kPrototypeMap_TransitionToDataProperty
   9945           : RuntimeCallCounterId::kMap_TransitionToDataProperty);
   9946 
   9947   DCHECK(name->IsUniqueName());
   9948   DCHECK(!map->is_dictionary_map());
   9949 
   9950   // Migrate to the newest map before storing the property.
   9951   map = Update(isolate, map);
   9952 
   9953   Map* maybe_transition = TransitionsAccessor(isolate, map)
   9954                               .SearchTransition(*name, kData, attributes);
   9955   if (maybe_transition != nullptr) {
   9956     Handle<Map> transition(maybe_transition, isolate);
   9957     int descriptor = transition->LastAdded();
   9958 
   9959     DCHECK_EQ(attributes, transition->instance_descriptors()
   9960                               ->GetDetails(descriptor)
   9961                               .attributes());
   9962 
   9963     return UpdateDescriptorForValue(isolate, transition, descriptor, constness,
   9964                                     value);
   9965   }
   9966 
   9967   TransitionFlag flag = INSERT_TRANSITION;
   9968   MaybeHandle<Map> maybe_map;
   9969   if (!map->TooManyFastProperties(store_mode)) {
   9970     if (!FLAG_track_constant_fields && value->IsJSFunction()) {
   9971       maybe_map =
   9972           Map::CopyWithConstant(isolate, map, name, value, attributes, flag);
   9973     } else {
   9974       Representation representation = value->OptimalRepresentation();
   9975       Handle<FieldType> type = value->OptimalType(isolate, representation);
   9976       maybe_map = Map::CopyWithField(isolate, map, name, type, attributes,
   9977                                      constness, representation, flag);
   9978     }
   9979   }
   9980 
   9981   Handle<Map> result;
   9982   if (!maybe_map.ToHandle(&result)) {
   9983     const char* reason = "TooManyFastProperties";
   9984 #if V8_TRACE_MAPS
   9985     std::unique_ptr<ScopedVector<char>> buffer;
   9986     if (FLAG_trace_maps) {
   9987       ScopedVector<char> name_buffer(100);
   9988       name->NameShortPrint(name_buffer);
   9989       buffer.reset(new ScopedVector<char>(128));
   9990       SNPrintF(*buffer, "TooManyFastProperties %s", name_buffer.start());
   9991       reason = buffer->start();
   9992     }
   9993 #endif
   9994     Handle<Object> maybe_constructor(map->GetConstructor(), isolate);
   9995     if (FLAG_feedback_normalization && map->new_target_is_base() &&
   9996         maybe_constructor->IsJSFunction() &&
   9997         !JSFunction::cast(*maybe_constructor)->shared()->native()) {
   9998       Handle<JSFunction> constructor =
   9999           Handle<JSFunction>::cast(maybe_constructor);
   10000       DCHECK_NE(*constructor,
   10001                 constructor->context()->native_context()->object_function());
   10002       Handle<Map> initial_map(constructor->initial_map(), isolate);
   10003       result = Map::Normalize(isolate, initial_map, CLEAR_INOBJECT_PROPERTIES,
   10004                               reason);
   10005       initial_map->DeprecateTransitionTree(isolate);
   10006       Handle<Object> prototype(result->prototype(), isolate);
   10007       JSFunction::SetInitialMap(constructor, result, prototype);
   10008 
   10009       // Deoptimize all code that embeds the previous initial map.
   10010       initial_map->dependent_code()->DeoptimizeDependentCodeGroup(
   10011           isolate, DependentCode::kInitialMapChangedGroup);
   10012       if (!result->EquivalentToForNormalization(*map,
   10013                                                 CLEAR_INOBJECT_PROPERTIES)) {
   10014         result =
   10015             Map::Normalize(isolate, map, CLEAR_INOBJECT_PROPERTIES, reason);
   10016       }
   10017     } else {
   10018       result = Map::Normalize(isolate, map, CLEAR_INOBJECT_PROPERTIES, reason);
   10019     }
   10020   }
   10021 
   10022   return result;
   10023 }
   10024 
   10025 Handle<Map> Map::ReconfigureExistingProperty(Isolate* isolate, Handle<Map> map,
   10026                                              int descriptor, PropertyKind kind,
   10027                                              PropertyAttributes attributes) {
   10028   // Dictionaries have to be reconfigured in-place.
   10029   DCHECK(!map->is_dictionary_map());
   10030 
   10031   if (!map->GetBackPointer()->IsMap()) {
   10032     // There is no benefit from reconstructing transition tree for maps without
   10033     // back pointers.
   10034     return CopyGeneralizeAllFields(isolate, map, map->elements_kind(),
   10035                                    descriptor, kind, attributes,
   10036                                    "GenAll_AttributesMismatchProtoMap");
   10037   }
   10038 
   10039   if (FLAG_trace_generalization) {
   10040     map->PrintReconfiguration(isolate, stdout, descriptor, kind, attributes);
   10041   }
   10042 
   10043   MapUpdater mu(isolate, map);
   10044   DCHECK_EQ(kData, kind);  // Only kData case is supported so far.
   10045   Handle<Map> new_map = mu.ReconfigureToDataField(
   10046       descriptor, attributes, kDefaultFieldConstness, Representation::None(),
   10047       FieldType::None(isolate));
   10048   return new_map;
   10049 }
   10050 
   10051 Handle<Map> Map::TransitionToAccessorProperty(Isolate* isolate, Handle<Map> map,
   10052                                               Handle<Name> name, int descriptor,
   10053                                               Handle<Object> getter,
   10054                                               Handle<Object> setter,
   10055                                               PropertyAttributes attributes) {
   10056   RuntimeCallTimerScope stats_scope(
   10057       isolate,
   10058       map->is_prototype_map()
   10059           ? RuntimeCallCounterId::kPrototypeMap_TransitionToAccessorProperty
   10060           : RuntimeCallCounterId::kMap_TransitionToAccessorProperty);
   10061 
   10062   // At least one of the accessors needs to be a new value.
   10063   DCHECK(!getter->IsNull(isolate) || !setter->IsNull(isolate));
   10064   DCHECK(name->IsUniqueName());
   10065 
   10066   // Dictionary maps can always have additional data properties.
   10067   if (map->is_dictionary_map()) return map;
   10068 
   10069   // Migrate to the newest map before transitioning to the new property.
   10070   map = Update(isolate, map);
   10071 
   10072   PropertyNormalizationMode mode = map->is_prototype_map()
   10073                                        ? KEEP_INOBJECT_PROPERTIES
   10074                                        : CLEAR_INOBJECT_PROPERTIES;
   10075 
   10076   Map* maybe_transition = TransitionsAccessor(isolate, map)
   10077                               .SearchTransition(*name, kAccessor, attributes);
   10078   if (maybe_transition != nullptr) {
   10079     Handle<Map> transition(maybe_transition, isolate);
   10080     DescriptorArray* descriptors = transition->instance_descriptors();
   10081     int descriptor = transition->LastAdded();
   10082     DCHECK(descriptors->GetKey(descriptor)->Equals(*name));
   10083 
   10084     DCHECK_EQ(kAccessor, descriptors->GetDetails(descriptor).kind());
   10085     DCHECK_EQ(attributes, descriptors->GetDetails(descriptor).attributes());
   10086 
   10087     Handle<Object> maybe_pair(descriptors->GetStrongValue(descriptor), isolate);
   10088     if (!maybe_pair->IsAccessorPair()) {
   10089       return Map::Normalize(isolate, map, mode,
   10090                             "TransitionToAccessorFromNonPair");
   10091     }
   10092 
   10093     Handle<AccessorPair> pair = Handle<AccessorPair>::cast(maybe_pair);
   10094     if (!pair->Equals(*getter, *setter)) {
   10095       return Map::Normalize(isolate, map, mode,
   10096                             "TransitionToDifferentAccessor");
   10097     }
   10098 
   10099     return transition;
   10100   }
   10101 
   10102   Handle<AccessorPair> pair;
   10103   DescriptorArray* old_descriptors = map->instance_descriptors();
   10104   if (descriptor != DescriptorArray::kNotFound) {
   10105     if (descriptor != map->LastAdded()) {
   10106       return Map::Normalize(isolate, map, mode, "AccessorsOverwritingNonLast");
   10107     }
   10108     PropertyDetails old_details = old_descriptors->GetDetails(descriptor);
   10109     if (old_details.kind() != kAccessor) {
   10110       return Map::Normalize(isolate, map, mode,
   10111                             "AccessorsOverwritingNonAccessors");
   10112     }
   10113 
   10114     if (old_details.attributes() != attributes) {
   10115       return Map::Normalize(isolate, map, mode, "AccessorsWithAttributes");
   10116     }
   10117 
   10118     Handle<Object> maybe_pair(old_descriptors->GetStrongValue(descriptor),
   10119                               isolate);
   10120     if (!maybe_pair->IsAccessorPair()) {
   10121       return Map::Normalize(isolate, map, mode, "AccessorsOverwritingNonPair");
   10122     }
   10123 
   10124     Handle<AccessorPair> current_pair = Handle<AccessorPair>::cast(maybe_pair);
   10125     if (current_pair->Equals(*getter, *setter)) return map;
   10126 
   10127     bool overwriting_accessor = false;
   10128     if (!getter->IsNull(isolate) &&
   10129         !current_pair->get(ACCESSOR_GETTER)->IsNull(isolate) &&
   10130         current_pair->get(ACCESSOR_GETTER) != *getter) {
   10131       overwriting_accessor = true;
   10132     }
   10133     if (!setter->IsNull(isolate) &&
   10134         !current_pair->get(ACCESSOR_SETTER)->IsNull(isolate) &&
   10135         current_pair->get(ACCESSOR_SETTER) != *setter) {
   10136       overwriting_accessor = true;
   10137     }
   10138     if (overwriting_accessor) {
   10139       return Map::Normalize(isolate, map, mode,
   10140                             "AccessorsOverwritingAccessors");
   10141     }
   10142 
   10143     pair = AccessorPair::Copy(isolate, Handle<AccessorPair>::cast(maybe_pair));
   10144   } else if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors ||
   10145              map->TooManyFastProperties(CERTAINLY_NOT_STORE_FROM_KEYED)) {
   10146     return Map::Normalize(isolate, map, CLEAR_INOBJECT_PROPERTIES,
   10147                           "TooManyAccessors");
   10148   } else {
   10149     pair = isolate->factory()->NewAccessorPair();
   10150   }
   10151 
   10152   pair->SetComponents(*getter, *setter);
   10153 
   10154   TransitionFlag flag = INSERT_TRANSITION;
   10155   Descriptor d = Descriptor::AccessorConstant(name, pair, attributes);
   10156   return Map::CopyInsertDescriptor(isolate, map, &d, flag);
   10157 }
   10158 
   10159 Handle<Map> Map::CopyAddDescriptor(Isolate* isolate, Handle<Map> map,
   10160                                    Descriptor* descriptor,
   10161                                    TransitionFlag flag) {
   10162   Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate);
   10163 
   10164   // Share descriptors only if map owns descriptors and it not an initial map.
   10165   if (flag == INSERT_TRANSITION && map->owns_descriptors() &&
   10166       !map->GetBackPointer()->IsUndefined(isolate) &&
   10167       TransitionsAccessor(isolate, map).CanHaveMoreTransitions()) {
   10168     return ShareDescriptor(isolate, map, descriptors, descriptor);
   10169   }
   10170 
   10171   int nof = map->NumberOfOwnDescriptors();
   10172   Handle<DescriptorArray> new_descriptors =
   10173       DescriptorArray::CopyUpTo(isolate, descriptors, nof, 1);
   10174   new_descriptors->Append(descriptor);
   10175 
   10176   Handle<LayoutDescriptor> new_layout_descriptor =
   10177       FLAG_unbox_double_fields
   10178           ? LayoutDescriptor::New(isolate, map, new_descriptors, nof + 1)
   10179           : handle(LayoutDescriptor::FastPointerLayout(), isolate);
   10180 
   10181   return CopyReplaceDescriptors(
   10182       isolate, map, new_descriptors, new_layout_descriptor, flag,
   10183       descriptor->GetKey(), "CopyAddDescriptor", SIMPLE_PROPERTY_TRANSITION);
   10184 }
   10185 
   10186 Handle<Map> Map::CopyInsertDescriptor(Isolate* isolate, Handle<Map> map,
   10187                                       Descriptor* descriptor,
   10188                                       TransitionFlag flag) {
   10189   Handle<DescriptorArray> old_descriptors(map->instance_descriptors(), isolate);
   10190 
   10191   // We replace the key if it is already present.
   10192   int index =
   10193       old_descriptors->SearchWithCache(isolate, *descriptor->GetKey(), *map);
   10194   if (index != DescriptorArray::kNotFound) {
   10195     return CopyReplaceDescriptor(isolate, map, old_descriptors, descriptor,
   10196                                  index, flag);
   10197   }
   10198   return CopyAddDescriptor(isolate, map, descriptor, flag);
   10199 }
   10200 
   10201 Handle<DescriptorArray> DescriptorArray::CopyUpTo(Isolate* isolate,
   10202                                                   Handle<DescriptorArray> desc,
   10203                                                   int enumeration_index,
   10204                                                   int slack) {
   10205   return DescriptorArray::CopyUpToAddAttributes(isolate, desc,
   10206                                                 enumeration_index, NONE, slack);
   10207 }
   10208 
   10209 Handle<DescriptorArray> DescriptorArray::CopyUpToAddAttributes(
   10210     Isolate* isolate, Handle<DescriptorArray> desc, int enumeration_index,
   10211     PropertyAttributes attributes, int slack) {
   10212   if (enumeration_index + slack == 0) {
   10213     return isolate->factory()->empty_descriptor_array();
   10214   }
   10215 
   10216   int size = enumeration_index;
   10217 
   10218   Handle<DescriptorArray> descriptors =
   10219       DescriptorArray::Allocate(isolate, size, slack);
   10220 
   10221   if (attributes != NONE) {
   10222     for (int i = 0; i < size; ++i) {
   10223       MaybeObject* value_or_field_type = desc->GetValue(i);
   10224       Name* key = desc->GetKey(i);
   10225       PropertyDetails details = desc->GetDetails(i);
   10226       // Bulk attribute changes never affect private properties.
   10227       if (!key->IsPrivate()) {
   10228         int mask = DONT_DELETE | DONT_ENUM;
   10229         // READ_ONLY is an invalid attribute for JS setters/getters.
   10230         HeapObject* heap_object;
   10231         if (details.kind() != kAccessor ||
   10232             !(value_or_field_type->ToStrongHeapObject(&heap_object) &&
   10233               heap_object->IsAccessorPair())) {
   10234           mask |= READ_ONLY;
   10235         }
   10236         details = details.CopyAddAttributes(
   10237             static_cast<PropertyAttributes>(attributes & mask));
   10238       }
   10239       descriptors->Set(i, key, value_or_field_type, details);
   10240     }
   10241   } else {
   10242     for (int i = 0; i < size; ++i) {
   10243       descriptors->CopyFrom(i, *desc);
   10244     }
   10245   }
   10246 
   10247   if (desc->number_of_descriptors() != enumeration_index) descriptors->Sort();
   10248 
   10249   return descriptors;
   10250 }
   10251 
   10252 // Create a new descriptor array with only enumerable, configurable, writeable
   10253 // data properties, but identical field locations.
   10254 Handle<DescriptorArray> DescriptorArray::CopyForFastObjectClone(
   10255     Isolate* isolate, Handle<DescriptorArray> src, int enumeration_index,
   10256     int slack) {
   10257   if (enumeration_index + slack == 0) {
   10258     return isolate->factory()->empty_descriptor_array();
   10259   }
   10260 
   10261   int size = enumeration_index;
   10262   Handle<DescriptorArray> descriptors =
   10263       DescriptorArray::Allocate(isolate, size, slack);
   10264 
   10265   for (int i = 0; i < size; ++i) {
   10266     Name* key = src->GetKey(i);
   10267     PropertyDetails details = src->GetDetails(i);
   10268 
   10269     DCHECK(!key->IsPrivateField());
   10270     DCHECK(details.IsEnumerable());
   10271     DCHECK_EQ(details.kind(), kData);
   10272 
   10273     // Ensure the ObjectClone property details are NONE, and that all source
   10274     // details did not contain DONT_ENUM.
   10275     PropertyDetails new_details(kData, NONE, details.location(),
   10276                                 details.constness(), details.representation(),
   10277                                 details.field_index());
   10278     // Do not propagate the field type of normal object fields from the
   10279     // original descriptors since FieldType changes don't create new maps.
   10280     MaybeObject* type = src->GetValue(i);
   10281     if (details.location() == PropertyLocation::kField) {
   10282       type = MaybeObject::FromObject(FieldType::Any());
   10283     }
   10284     descriptors->Set(i, key, type, new_details);
   10285   }
   10286 
   10287   descriptors->Sort();
   10288 
   10289   return descriptors;
   10290 }
   10291 
   10292 bool DescriptorArray::IsEqualUpTo(DescriptorArray* desc, int nof_descriptors) {
   10293   for (int i = 0; i < nof_descriptors; i++) {
   10294     if (GetKey(i) != desc->GetKey(i) || GetValue(i) != desc->GetValue(i)) {
   10295       return false;
   10296     }
   10297     PropertyDetails details = GetDetails(i);
   10298     PropertyDetails other_details = desc->GetDetails(i);
   10299     if (details.kind() != other_details.kind() ||
   10300         details.location() != other_details.location() ||
   10301         !details.representation().Equals(other_details.representation())) {
   10302       return false;
   10303     }
   10304   }
   10305   return true;
   10306 }
   10307 
   10308 Handle<Map> Map::CopyReplaceDescriptor(Isolate* isolate, Handle<Map> map,
   10309                                        Handle<DescriptorArray> descriptors,
   10310                                        Descriptor* descriptor,
   10311                                        int insertion_index,
   10312                                        TransitionFlag flag) {
   10313   Handle<Name> key = descriptor->GetKey();
   10314   DCHECK_EQ(*key, descriptors->GetKey(insertion_index));
   10315   // This function does not support replacing property fields as
   10316   // that would break property field counters.
   10317   DCHECK_NE(kField, descriptor->GetDetails().location());
   10318   DCHECK_NE(kField, descriptors->GetDetails(insertion_index).location());
   10319 
   10320   Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo(
   10321       isolate, descriptors, map->NumberOfOwnDescriptors());
   10322 
   10323   new_descriptors->Replace(insertion_index, descriptor);
   10324   Handle<LayoutDescriptor> new_layout_descriptor = LayoutDescriptor::New(
   10325       isolate, map, new_descriptors, new_descriptors->number_of_descriptors());
   10326 
   10327   SimpleTransitionFlag simple_flag =
   10328       (insertion_index == descriptors->number_of_descriptors() - 1)
   10329           ? SIMPLE_PROPERTY_TRANSITION
   10330           : PROPERTY_TRANSITION;
   10331   return CopyReplaceDescriptors(isolate, map, new_descriptors,
   10332                                 new_layout_descriptor, flag, key,
   10333                                 "CopyReplaceDescriptor", simple_flag);
   10334 }
   10335 
   10336 Handle<FixedArray> FixedArray::SetAndGrow(Isolate* isolate,
   10337                                           Handle<FixedArray> array, int index,
   10338                                           Handle<Object> value,
   10339                                           PretenureFlag pretenure) {
   10340   if (index < array->length()) {
   10341     array->set(index, *value);
   10342     return array;
   10343   }
   10344   int capacity = array->length();
   10345   do {
   10346     capacity = JSObject::NewElementsCapacity(capacity);
   10347   } while (capacity <= index);
   10348   Handle<FixedArray> new_array =
   10349       isolate->factory()->NewUninitializedFixedArray(capacity, pretenure);
   10350   array->CopyTo(0, *new_array, 0, array->length());
   10351   new_array->FillWithHoles(array->length(), new_array->length());
   10352   new_array->set(index, *value);
   10353   return new_array;
   10354 }
   10355 
   10356 bool FixedArray::ContainsSortedNumbers() {
   10357   for (int i = 1; i < length(); ++i) {
   10358     Object* a_obj = get(i - 1);
   10359     Object* b_obj = get(i);
   10360     if (!a_obj->IsNumber() || !b_obj->IsNumber()) return false;
   10361 
   10362     uint32_t a = NumberToUint32(a_obj);
   10363     uint32_t b = NumberToUint32(b_obj);
   10364 
   10365     if (a > b) return false;
   10366   }
   10367   return true;
   10368 }
   10369 
   10370 Handle<FixedArray> FixedArray::ShrinkOrEmpty(Isolate* isolate,
   10371                                              Handle<FixedArray> array,
   10372                                              int new_length) {
   10373   if (new_length == 0) {
   10374     return array->GetReadOnlyRoots().empty_fixed_array_handle();
   10375   } else {
   10376     array->Shrink(isolate, new_length);
   10377     return array;
   10378   }
   10379 }
   10380 
   10381 void FixedArray::Shrink(Isolate* isolate, int new_length) {
   10382   DCHECK(0 < new_length && new_length <= length());
   10383   if (new_length < length()) {
   10384     isolate->heap()->RightTrimFixedArray(this, length() - new_length);
   10385   }
   10386 }
   10387 
   10388 void FixedArray::CopyTo(int pos, FixedArray* dest, int dest_pos,
   10389                         int len) const {
   10390   DisallowHeapAllocation no_gc;
   10391   // Return early if len == 0 so that we don't try to read the write barrier off
   10392   // a canonical read-only empty fixed array.
   10393   if (len == 0) return;
   10394   WriteBarrierMode mode = dest->GetWriteBarrierMode(no_gc);
   10395   for (int index = 0; index < len; index++) {
   10396     dest->set(dest_pos+index, get(pos+index), mode);
   10397   }
   10398 }
   10399 
   10400 #ifdef DEBUG
   10401 bool FixedArray::IsEqualTo(FixedArray* other) {
   10402   if (length() != other->length()) return false;
   10403   for (int i = 0 ; i < length(); ++i) {
   10404     if (get(i) != other->get(i)) return false;
   10405   }
   10406   return true;
   10407 }
   10408 #endif
   10409 
   10410 void JSObject::PrototypeRegistryCompactionCallback(HeapObject* value,
   10411                                                    int old_index,
   10412                                                    int new_index) {
   10413   DCHECK(value->IsMap() && Map::cast(value)->is_prototype_map());
   10414   Map* map = Map::cast(value);
   10415   DCHECK(map->prototype_info()->IsPrototypeInfo());
   10416   PrototypeInfo* proto_info = PrototypeInfo::cast(map->prototype_info());
   10417   DCHECK_EQ(old_index, proto_info->registry_slot());
   10418   proto_info->set_registry_slot(new_index);
   10419 }
   10420 
   10421 // static
   10422 Handle<ArrayList> ArrayList::Add(Isolate* isolate, Handle<ArrayList> array,
   10423                                  Handle<Object> obj) {
   10424   int length = array->Length();
   10425   array = EnsureSpace(isolate, array, length + 1);
   10426   // Check that GC didn't remove elements from the array.
   10427   DCHECK_EQ(array->Length(), length);
   10428   array->Set(length, *obj);
   10429   array->SetLength(length + 1);
   10430   return array;
   10431 }
   10432 
   10433 // static
   10434 Handle<ArrayList> ArrayList::Add(Isolate* isolate, Handle<ArrayList> array,
   10435                                  Handle<Object> obj1, Handle<Object> obj2) {
   10436   int length = array->Length();
   10437   array = EnsureSpace(isolate, array, length + 2);
   10438   // Check that GC didn't remove elements from the array.
   10439   DCHECK_EQ(array->Length(), length);
   10440   array->Set(length, *obj1);
   10441   array->Set(length + 1, *obj2);
   10442   array->SetLength(length + 2);
   10443   return array;
   10444 }
   10445 
   10446 // static
   10447 Handle<ArrayList> ArrayList::New(Isolate* isolate, int size) {
   10448   Handle<FixedArray> fixed_array =
   10449       isolate->factory()->NewFixedArray(size + kFirstIndex);
   10450   fixed_array->set_map_no_write_barrier(
   10451       ReadOnlyRoots(isolate).array_list_map());
   10452   Handle<ArrayList> result = Handle<ArrayList>::cast(fixed_array);
   10453   result->SetLength(0);
   10454   return result;
   10455 }
   10456 
   10457 Handle<FixedArray> ArrayList::Elements(Isolate* isolate,
   10458                                        Handle<ArrayList> array) {
   10459   int length = array->Length();
   10460   Handle<FixedArray> result = isolate->factory()->NewFixedArray(length);
   10461   // Do not copy the first entry, i.e., the length.
   10462   array->CopyTo(kFirstIndex, *result, 0, length);
   10463   return result;
   10464 }
   10465 
   10466 bool ArrayList::IsFull() {
   10467   int capacity = length();
   10468   return kFirstIndex + Length() == capacity;
   10469 }
   10470 
   10471 namespace {
   10472 
   10473 Handle<FixedArray> EnsureSpaceInFixedArray(Isolate* isolate,
   10474                                            Handle<FixedArray> array,
   10475                                            int length) {
   10476   int capacity = array->length();
   10477   if (capacity < length) {
   10478     int new_capacity = length;
   10479     new_capacity = new_capacity + Max(new_capacity / 2, 2);
   10480     int grow_by = new_capacity - capacity;
   10481     array = isolate->factory()->CopyFixedArrayAndGrow(array, grow_by);
   10482   }
   10483   return array;
   10484 }
   10485 
   10486 }  // namespace
   10487 
   10488 // static
   10489 Handle<ArrayList> ArrayList::EnsureSpace(Isolate* isolate,
   10490                                          Handle<ArrayList> array, int length) {
   10491   const bool empty = (array->length() == 0);
   10492   auto ret = EnsureSpaceInFixedArray(isolate, array, kFirstIndex + length);
   10493   if (empty) {
   10494     ret->set_map_no_write_barrier(array->GetReadOnlyRoots().array_list_map());
   10495 
   10496     Handle<ArrayList>::cast(ret)->SetLength(0);
   10497   }
   10498   return Handle<ArrayList>::cast(ret);
   10499 }
   10500 
   10501 // static
   10502 Handle<WeakArrayList> WeakArrayList::AddToEnd(Isolate* isolate,
   10503                                               Handle<WeakArrayList> array,
   10504                                               MaybeObjectHandle value) {
   10505   int length = array->length();
   10506   array = EnsureSpace(isolate, array, length + 1);
   10507   // Reload length; GC might have removed elements from the array.
   10508   length = array->length();
   10509   array->Set(length, *value);
   10510   array->set_length(length + 1);
   10511   return array;
   10512 }
   10513 
   10514 bool WeakArrayList::IsFull() { return length() == capacity(); }
   10515 
   10516 // static
   10517 Handle<WeakArrayList> WeakArrayList::EnsureSpace(Isolate* isolate,
   10518                                                  Handle<WeakArrayList> array,
   10519                                                  int length,
   10520                                                  PretenureFlag pretenure) {
   10521   int capacity = array->capacity();
   10522   if (capacity < length) {
   10523     int new_capacity = length;
   10524     new_capacity = new_capacity + Max(new_capacity / 2, 2);
   10525     int grow_by = new_capacity - capacity;
   10526     array =
   10527         isolate->factory()->CopyWeakArrayListAndGrow(array, grow_by, pretenure);
   10528   }
   10529   return array;
   10530 }
   10531 
   10532 int WeakArrayList::CountLiveWeakReferences() const {
   10533   int live_weak_references = 0;
   10534   for (int i = 0; i < length(); i++) {
   10535     if (Get(i)->IsWeakHeapObject()) {
   10536       ++live_weak_references;
   10537     }
   10538   }
   10539   return live_weak_references;
   10540 }
   10541 
   10542 bool WeakArrayList::RemoveOne(MaybeObjectHandle value) {
   10543   if (length() == 0) return false;
   10544   // Optimize for the most recently added element to be removed again.
   10545   int last_index = length() - 1;
   10546   for (int i = last_index; i >= 0; --i) {
   10547     if (Get(i) == *value) {
   10548       // Move the last element into the this slot (or no-op, if this is the
   10549       // last slot).
   10550       Set(i, Get(last_index));
   10551       Set(last_index, HeapObjectReference::ClearedValue());
   10552       set_length(last_index);
   10553       return true;
   10554     }
   10555   }
   10556   return false;
   10557 }
   10558 
   10559 // static
   10560 Handle<WeakArrayList> PrototypeUsers::Add(Isolate* isolate,
   10561                                           Handle<WeakArrayList> array,
   10562                                           Handle<Map> value,
   10563                                           int* assigned_index) {
   10564   int length = array->length();
   10565   if (length == 0) {
   10566     // Uninitialized WeakArrayList; need to initialize empty_slot_index.
   10567     array = WeakArrayList::EnsureSpace(isolate, array, kFirstIndex + 1);
   10568     set_empty_slot_index(*array, kNoEmptySlotsMarker);
   10569     array->Set(kFirstIndex, HeapObjectReference::Weak(*value));
   10570     array->set_length(kFirstIndex + 1);
   10571     if (assigned_index != nullptr) *assigned_index = kFirstIndex;
   10572     return array;
   10573   }
   10574 
   10575   // If the array has unfilled space at the end, use it.
   10576   if (!array->IsFull()) {
   10577     array->Set(length, HeapObjectReference::Weak(*value));
   10578     array->set_length(length + 1);
   10579     if (assigned_index != nullptr) *assigned_index = length;
   10580     return array;
   10581   }
   10582 
   10583   // If there are empty slots, use one of them.
   10584   int empty_slot = Smi::ToInt(empty_slot_index(*array));
   10585   if (empty_slot != kNoEmptySlotsMarker) {
   10586     DCHECK_GE(empty_slot, kFirstIndex);
   10587     CHECK_LT(empty_slot, array->length());
   10588     int next_empty_slot = Smi::ToInt(array->Get(empty_slot)->ToSmi());
   10589 
   10590     array->Set(empty_slot, HeapObjectReference::Weak(*value));
   10591     if (assigned_index != nullptr) *assigned_index = empty_slot;
   10592 
   10593     set_empty_slot_index(*array, next_empty_slot);
   10594     return array;
   10595   } else {
   10596     DCHECK_EQ(empty_slot, kNoEmptySlotsMarker);
   10597   }
   10598 
   10599   // Array full and no empty slots. Grow the array.
   10600   array = WeakArrayList::EnsureSpace(isolate, array, length + 1);
   10601   array->Set(length, HeapObjectReference::Weak(*value));
   10602   array->set_length(length + 1);
   10603   if (assigned_index != nullptr) *assigned_index = length;
   10604   return array;
   10605 }
   10606 
   10607 WeakArrayList* PrototypeUsers::Compact(Handle<WeakArrayList> array, Heap* heap,
   10608                                        CompactionCallback callback,
   10609                                        PretenureFlag pretenure) {
   10610   if (array->length() == 0) {
   10611     return *array;
   10612   }
   10613   int new_length = kFirstIndex + array->CountLiveWeakReferences();
   10614   if (new_length == array->length()) {
   10615     return *array;
   10616   }
   10617 
   10618   Handle<WeakArrayList> new_array = WeakArrayList::EnsureSpace(
   10619       heap->isolate(),
   10620       handle(ReadOnlyRoots(heap).empty_weak_array_list(), heap->isolate()),
   10621       new_length, pretenure);
   10622   // Allocation might have caused GC and turned some of the elements into
   10623   // cleared weak heap objects. Count the number of live objects again.
   10624   int copy_to = kFirstIndex;
   10625   for (int i = kFirstIndex; i < array->length(); i++) {
   10626     MaybeObject* element = array->Get(i);
   10627     if (element->IsSmi()) continue;
   10628     if (element->IsClearedWeakHeapObject()) continue;
   10629     HeapObject* value = element->ToWeakHeapObject();
   10630     callback(value, i, copy_to);
   10631     new_array->Set(copy_to++, element);
   10632   }
   10633   new_array->set_length(copy_to);
   10634   set_empty_slot_index(*new_array, kNoEmptySlotsMarker);
   10635   return *new_array;
   10636 }
   10637 
   10638 Handle<RegExpMatchInfo> RegExpMatchInfo::ReserveCaptures(
   10639     Isolate* isolate, Handle<RegExpMatchInfo> match_info, int capture_count) {
   10640   DCHECK_GE(match_info->length(), kLastMatchOverhead);
   10641   const int required_length = kFirstCaptureIndex + capture_count;
   10642   Handle<FixedArray> result =
   10643       EnsureSpaceInFixedArray(isolate, match_info, required_length);
   10644   return Handle<RegExpMatchInfo>::cast(result);
   10645 }
   10646 
   10647 // static
   10648 Handle<FrameArray> FrameArray::AppendJSFrame(Handle<FrameArray> in,
   10649                                              Handle<Object> receiver,
   10650                                              Handle<JSFunction> function,
   10651                                              Handle<AbstractCode> code,
   10652                                              int offset, int flags) {
   10653   const int frame_count = in->FrameCount();
   10654   const int new_length = LengthFor(frame_count + 1);
   10655   Handle<FrameArray> array =
   10656       EnsureSpace(function->GetIsolate(), in, new_length);
   10657   array->SetReceiver(frame_count, *receiver);
   10658   array->SetFunction(frame_count, *function);
   10659   array->SetCode(frame_count, *code);
   10660   array->SetOffset(frame_count, Smi::FromInt(offset));
   10661   array->SetFlags(frame_count, Smi::FromInt(flags));
   10662   array->set(kFrameCountIndex, Smi::FromInt(frame_count + 1));
   10663   return array;
   10664 }
   10665 
   10666 // static
   10667 Handle<FrameArray> FrameArray::AppendWasmFrame(
   10668     Handle<FrameArray> in, Handle<WasmInstanceObject> wasm_instance,
   10669     int wasm_function_index, wasm::WasmCode* code, int offset, int flags) {
   10670   Isolate* isolate = wasm_instance->GetIsolate();
   10671   const int frame_count = in->FrameCount();
   10672   const int new_length = LengthFor(frame_count + 1);
   10673   Handle<FrameArray> array = EnsureSpace(isolate, in, new_length);
   10674   // The {code} will be {nullptr} for interpreted wasm frames.
   10675   Handle<Foreign> code_foreign =
   10676       isolate->factory()->NewForeign(reinterpret_cast<Address>(code));
   10677   array->SetWasmInstance(frame_count, *wasm_instance);
   10678   array->SetWasmFunctionIndex(frame_count, Smi::FromInt(wasm_function_index));
   10679   array->SetWasmCodeObject(frame_count, *code_foreign);
   10680   array->SetOffset(frame_count, Smi::FromInt(offset));
   10681   array->SetFlags(frame_count, Smi::FromInt(flags));
   10682   array->set(kFrameCountIndex, Smi::FromInt(frame_count + 1));
   10683   return array;
   10684 }
   10685 
   10686 void FrameArray::ShrinkToFit(Isolate* isolate) {
   10687   Shrink(isolate, LengthFor(FrameCount()));
   10688 }
   10689 
   10690 // static
   10691 Handle<FrameArray> FrameArray::EnsureSpace(Isolate* isolate,
   10692                                            Handle<FrameArray> array,
   10693                                            int length) {
   10694   return Handle<FrameArray>::cast(
   10695       EnsureSpaceInFixedArray(isolate, array, length));
   10696 }
   10697 
   10698 Handle<DescriptorArray> DescriptorArray::Allocate(Isolate* isolate,
   10699                                                   int number_of_descriptors,
   10700                                                   int slack,
   10701                                                   PretenureFlag pretenure) {
   10702   DCHECK_LE(0, number_of_descriptors);
   10703   Factory* factory = isolate->factory();
   10704   // Do not use DescriptorArray::cast on incomplete object.
   10705   int size = number_of_descriptors + slack;
   10706   if (size == 0) return factory->empty_descriptor_array();
   10707   // Allocate the array of keys.
   10708   Handle<WeakFixedArray> result =
   10709       factory->NewWeakFixedArrayWithMap<DescriptorArray>(
   10710           Heap::kDescriptorArrayMapRootIndex, LengthFor(size), pretenure);
   10711   result->Set(kDescriptorLengthIndex,
   10712               MaybeObject::FromObject(Smi::FromInt(number_of_descriptors)));
   10713   result->Set(kEnumCacheIndex, MaybeObject::FromObject(
   10714                                    ReadOnlyRoots(isolate).empty_enum_cache()));
   10715   return Handle<DescriptorArray>::cast(result);
   10716 }
   10717 
   10718 void DescriptorArray::ClearEnumCache() {
   10719   set(kEnumCacheIndex,
   10720       MaybeObject::FromObject(GetReadOnlyRoots().empty_enum_cache()));
   10721 }
   10722 
   10723 void DescriptorArray::Replace(int index, Descriptor* descriptor) {
   10724   descriptor->SetSortedKeyIndex(GetSortedKeyIndex(index));
   10725   Set(index, descriptor);
   10726 }
   10727 
   10728 // static
   10729 void DescriptorArray::SetEnumCache(Handle<DescriptorArray> descriptors,
   10730                                    Isolate* isolate, Handle<FixedArray> keys,
   10731                                    Handle<FixedArray> indices) {
   10732   EnumCache* enum_cache = descriptors->GetEnumCache();
   10733   if (enum_cache == ReadOnlyRoots(isolate).empty_enum_cache()) {
   10734     enum_cache = *isolate->factory()->NewEnumCache(keys, indices);
   10735     descriptors->set(kEnumCacheIndex, MaybeObject::FromObject(enum_cache));
   10736   } else {
   10737     enum_cache->set_keys(*keys);
   10738     enum_cache->set_indices(*indices);
   10739   }
   10740 }
   10741 
   10742 void DescriptorArray::CopyFrom(int index, DescriptorArray* src) {
   10743   PropertyDetails details = src->GetDetails(index);
   10744   Set(index, src->GetKey(index), src->GetValue(index), details);
   10745 }
   10746 
   10747 void DescriptorArray::Sort() {
   10748   // In-place heap sort.
   10749   int len = number_of_descriptors();
   10750   // Reset sorting since the descriptor array might contain invalid pointers.
   10751   for (int i = 0; i < len; ++i) SetSortedKey(i, i);
   10752   // Bottom-up max-heap construction.
   10753   // Index of the last node with children
   10754   const int max_parent_index = (len / 2) - 1;
   10755   for (int i = max_parent_index; i >= 0; --i) {
   10756     int parent_index = i;
   10757     const uint32_t parent_hash = GetSortedKey(i)->Hash();
   10758     while (parent_index <= max_parent_index) {
   10759       int child_index = 2 * parent_index + 1;
   10760       uint32_t child_hash = GetSortedKey(child_index)->Hash();
   10761       if (child_index + 1 < len) {
   10762         uint32_t right_child_hash = GetSortedKey(child_index + 1)->Hash();
   10763         if (right_child_hash > child_hash) {
   10764           child_index++;
   10765           child_hash = right_child_hash;
   10766         }
   10767       }
   10768       if (child_hash <= parent_hash) break;
   10769       SwapSortedKeys(parent_index, child_index);
   10770       // Now element at child_index could be < its children.
   10771       parent_index = child_index;  // parent_hash remains correct.
   10772     }
   10773   }
   10774 
   10775   // Extract elements and create sorted array.
   10776   for (int i = len - 1; i > 0; --i) {
   10777     // Put max element at the back of the array.
   10778     SwapSortedKeys(0, i);
   10779     // Shift down the new top element.
   10780     int parent_index = 0;
   10781     const uint32_t parent_hash = GetSortedKey(parent_index)->Hash();
   10782     const int max_parent_index = (i / 2) - 1;
   10783     while (parent_index <= max_parent_index) {
   10784       int child_index = parent_index * 2 + 1;
   10785       uint32_t child_hash = GetSortedKey(child_index)->Hash();
   10786       if (child_index + 1 < i) {
   10787         uint32_t right_child_hash = GetSortedKey(child_index + 1)->Hash();
   10788         if (right_child_hash > child_hash) {
   10789           child_index++;
   10790           child_hash = right_child_hash;
   10791         }
   10792       }
   10793       if (child_hash <= parent_hash) break;
   10794       SwapSortedKeys(parent_index, child_index);
   10795       parent_index = child_index;
   10796     }
   10797   }
   10798   DCHECK(IsSortedNoDuplicates());
   10799 }
   10800 
   10801 Handle<AccessorPair> AccessorPair::Copy(Isolate* isolate,
   10802                                         Handle<AccessorPair> pair) {
   10803   Handle<AccessorPair> copy = isolate->factory()->NewAccessorPair();
   10804   copy->set_getter(pair->getter());
   10805   copy->set_setter(pair->setter());
   10806   return copy;
   10807 }
   10808 
   10809 Handle<Object> AccessorPair::GetComponent(Isolate* isolate,
   10810                                           Handle<AccessorPair> accessor_pair,
   10811                                           AccessorComponent component) {
   10812   Object* accessor = accessor_pair->get(component);
   10813   if (accessor->IsFunctionTemplateInfo()) {
   10814     return ApiNatives::InstantiateFunction(
   10815                handle(FunctionTemplateInfo::cast(accessor), isolate))
   10816         .ToHandleChecked();
   10817   }
   10818   if (accessor->IsNull(isolate)) {
   10819     return isolate->factory()->undefined_value();
   10820   }
   10821   return handle(accessor, isolate);
   10822 }
   10823 
   10824 Handle<DeoptimizationData> DeoptimizationData::New(Isolate* isolate,
   10825                                                    int deopt_entry_count,
   10826                                                    PretenureFlag pretenure) {
   10827   return Handle<DeoptimizationData>::cast(isolate->factory()->NewFixedArray(
   10828       LengthFor(deopt_entry_count), pretenure));
   10829 }
   10830 
   10831 Handle<DeoptimizationData> DeoptimizationData::Empty(Isolate* isolate) {
   10832   return Handle<DeoptimizationData>::cast(
   10833       isolate->factory()->empty_fixed_array());
   10834 }
   10835 
   10836 SharedFunctionInfo* DeoptimizationData::GetInlinedFunction(int index) {
   10837   if (index == -1) {
   10838     return SharedFunctionInfo::cast(SharedFunctionInfo());
   10839   } else {
   10840     return SharedFunctionInfo::cast(LiteralArray()->get(index));
   10841   }
   10842 }
   10843 
   10844 #ifdef DEBUG
   10845 bool DescriptorArray::IsEqualTo(DescriptorArray* other) {
   10846   if (length() != other->length()) return false;
   10847   for (int i = 0; i < length(); ++i) {
   10848     if (get(i) != other->get(i)) return false;
   10849   }
   10850   return true;
   10851 }
   10852 #endif
   10853 
   10854 // static
   10855 Handle<String> String::Trim(Isolate* isolate, Handle<String> string,
   10856                             TrimMode mode) {
   10857   string = String::Flatten(isolate, string);
   10858   int const length = string->length();
   10859 
   10860   // Perform left trimming if requested.
   10861   int left = 0;
   10862   UnicodeCache* unicode_cache = isolate->unicode_cache();
   10863   if (mode == kTrim || mode == kTrimStart) {
   10864     while (left < length &&
   10865            unicode_cache->IsWhiteSpaceOrLineTerminator(string->Get(left))) {
   10866       left++;
   10867     }
   10868   }
   10869 
   10870   // Perform right trimming if requested.
   10871   int right = length;
   10872   if (mode == kTrim || mode == kTrimEnd) {
   10873     while (
   10874         right > left &&
   10875         unicode_cache->IsWhiteSpaceOrLineTerminator(string->Get(right - 1))) {
   10876       right--;
   10877     }
   10878   }
   10879 
   10880   return isolate->factory()->NewSubString(string, left, right);
   10881 }
   10882 
   10883 bool String::LooksValid() {
   10884   // TODO(leszeks): Maybe remove this check entirely, Heap::Contains uses
   10885   // basically the same logic as the way we access the heap in the first place.
   10886   MemoryChunk* chunk = MemoryChunk::FromHeapObject(this);
   10887   // RO_SPACE objects should always be valid.
   10888   if (chunk->owner()->identity() == RO_SPACE) return true;
   10889   if (chunk->heap() == nullptr) return false;
   10890   return chunk->heap()->Contains(this);
   10891 }
   10892 
   10893 // static
   10894 MaybeHandle<String> Name::ToFunctionName(Isolate* isolate, Handle<Name> name) {
   10895   if (name->IsString()) return Handle<String>::cast(name);
   10896   // ES6 section 9.2.11 SetFunctionName, step 4.
   10897   Handle<Object> description(Handle<Symbol>::cast(name)->name(), isolate);
   10898   if (description->IsUndefined(isolate)) {
   10899     return isolate->factory()->empty_string();
   10900   }
   10901   IncrementalStringBuilder builder(isolate);
   10902   builder.AppendCharacter('[');
   10903   builder.AppendString(Handle<String>::cast(description));
   10904   builder.AppendCharacter(']');
   10905   return builder.Finish();
   10906 }
   10907 
   10908 // static
   10909 MaybeHandle<String> Name::ToFunctionName(Isolate* isolate, Handle<Name> name,
   10910                                          Handle<String> prefix) {
   10911   Handle<String> name_string;
   10912   ASSIGN_RETURN_ON_EXCEPTION(isolate, name_string,
   10913                              ToFunctionName(isolate, name), String);
   10914   IncrementalStringBuilder builder(isolate);
   10915   builder.AppendString(prefix);
   10916   builder.AppendCharacter(' ');
   10917   builder.AppendString(name_string);
   10918   return builder.Finish();
   10919 }
   10920 
   10921 namespace {
   10922 
   10923 bool AreDigits(const uint8_t* s, int from, int to) {
   10924   for (int i = from; i < to; i++) {
   10925     if (s[i] < '0' || s[i] > '9') return false;
   10926   }
   10927 
   10928   return true;
   10929 }
   10930 
   10931 
   10932 int ParseDecimalInteger(const uint8_t* s, int from, int to) {
   10933   DCHECK_LT(to - from, 10);  // Overflow is not possible.
   10934   DCHECK(from < to);
   10935   int d = s[from] - '0';
   10936 
   10937   for (int i = from + 1; i < to; i++) {
   10938     d = 10 * d + (s[i] - '0');
   10939   }
   10940 
   10941   return d;
   10942 }
   10943 
   10944 }  // namespace
   10945 
   10946 // static
   10947 Handle<Object> String::ToNumber(Isolate* isolate, Handle<String> subject) {
   10948   // Flatten {subject} string first.
   10949   subject = String::Flatten(isolate, subject);
   10950 
   10951   // Fast array index case.
   10952   uint32_t index;
   10953   if (subject->AsArrayIndex(&index)) {
   10954     return isolate->factory()->NewNumberFromUint(index);
   10955   }
   10956 
   10957   // Fast case: short integer or some sorts of junk values.
   10958   if (subject->IsSeqOneByteString()) {
   10959     int len = subject->length();
   10960     if (len == 0) return handle(Smi::kZero, isolate);
   10961 
   10962     DisallowHeapAllocation no_gc;
   10963     uint8_t const* data = Handle<SeqOneByteString>::cast(subject)->GetChars();
   10964     bool minus = (data[0] == '-');
   10965     int start_pos = (minus ? 1 : 0);
   10966 
   10967     if (start_pos == len) {
   10968       return isolate->factory()->nan_value();
   10969     } else if (data[start_pos] > '9') {
   10970       // Fast check for a junk value. A valid string may start from a
   10971       // whitespace, a sign ('+' or '-'), the decimal point, a decimal digit
   10972       // or the 'I' character ('Infinity'). All of that have codes not greater
   10973       // than '9' except 'I' and &nbsp;.
   10974       if (data[start_pos] != 'I' && data[start_pos] != 0xA0) {
   10975         return isolate->factory()->nan_value();
   10976       }
   10977     } else if (len - start_pos < 10 && AreDigits(data, start_pos, len)) {
   10978       // The maximal/minimal smi has 10 digits. If the string has less digits
   10979       // we know it will fit into the smi-data type.
   10980       int d = ParseDecimalInteger(data, start_pos, len);
   10981       if (minus) {
   10982         if (d == 0) return isolate->factory()->minus_zero_value();
   10983         d = -d;
   10984       } else if (!subject->HasHashCode() && len <= String::kMaxArrayIndexSize &&
   10985                  (len == 1 || data[0] != '0')) {
   10986         // String hash is not calculated yet but all the data are present.
   10987         // Update the hash field to speed up sequential convertions.
   10988         uint32_t hash = StringHasher::MakeArrayIndexHash(d, len);
   10989 #ifdef DEBUG
   10990         subject->Hash();  // Force hash calculation.
   10991         DCHECK_EQ(static_cast<int>(subject->hash_field()),
   10992                   static_cast<int>(hash));
   10993 #endif
   10994         subject->set_hash_field(hash);
   10995       }
   10996       return handle(Smi::FromInt(d), isolate);
   10997     }
   10998   }
   10999 
   11000   // Slower case.
   11001   int flags = ALLOW_HEX | ALLOW_OCTAL | ALLOW_BINARY;
   11002   return isolate->factory()->NewNumber(
   11003       StringToDouble(isolate, isolate->unicode_cache(), subject, flags));
   11004 }
   11005 
   11006 
   11007 String::FlatContent String::GetFlatContent() {
   11008   DCHECK(!AllowHeapAllocation::IsAllowed());
   11009   int length = this->length();
   11010   StringShape shape(this);
   11011   String* string = this;
   11012   int offset = 0;
   11013   if (shape.representation_tag() == kConsStringTag) {
   11014     ConsString* cons = ConsString::cast(string);
   11015     if (cons->second()->length() != 0) {
   11016       return FlatContent();
   11017     }
   11018     string = cons->first();
   11019     shape = StringShape(string);
   11020   } else if (shape.representation_tag() == kSlicedStringTag) {
   11021     SlicedString* slice = SlicedString::cast(string);
   11022     offset = slice->offset();
   11023     string = slice->parent();
   11024     shape = StringShape(string);
   11025     DCHECK(shape.representation_tag() != kConsStringTag &&
   11026            shape.representation_tag() != kSlicedStringTag);
   11027   }
   11028   if (shape.representation_tag() == kThinStringTag) {
   11029     ThinString* thin = ThinString::cast(string);
   11030     string = thin->actual();
   11031     shape = StringShape(string);
   11032     DCHECK(!shape.IsCons());
   11033     DCHECK(!shape.IsSliced());
   11034   }
   11035   if (shape.encoding_tag() == kOneByteStringTag) {
   11036     const uint8_t* start;
   11037     if (shape.representation_tag() == kSeqStringTag) {
   11038       start = SeqOneByteString::cast(string)->GetChars();
   11039     } else {
   11040       start = ExternalOneByteString::cast(string)->GetChars();
   11041     }
   11042     return FlatContent(start + offset, length);
   11043   } else {
   11044     DCHECK_EQ(shape.encoding_tag(), kTwoByteStringTag);
   11045     const uc16* start;
   11046     if (shape.representation_tag() == kSeqStringTag) {
   11047       start = SeqTwoByteString::cast(string)->GetChars();
   11048     } else {
   11049       start = ExternalTwoByteString::cast(string)->GetChars();
   11050     }
   11051     return FlatContent(start + offset, length);
   11052   }
   11053 }
   11054 
   11055 std::unique_ptr<char[]> String::ToCString(AllowNullsFlag allow_nulls,
   11056                                           RobustnessFlag robust_flag,
   11057                                           int offset, int length,
   11058                                           int* length_return) {
   11059   if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) {
   11060     return std::unique_ptr<char[]>();
   11061   }
   11062   // Negative length means the to the end of the string.
   11063   if (length < 0) length = kMaxInt - offset;
   11064 
   11065   // Compute the size of the UTF-8 string. Start at the specified offset.
   11066   StringCharacterStream stream(this, offset);
   11067   int character_position = offset;
   11068   int utf8_bytes = 0;
   11069   int last = unibrow::Utf16::kNoPreviousCharacter;
   11070   while (stream.HasMore() && character_position++ < offset + length) {
   11071     uint16_t character = stream.GetNext();
   11072     utf8_bytes += unibrow::Utf8::Length(character, last);
   11073     last = character;
   11074   }
   11075 
   11076   if (length_return) {
   11077     *length_return = utf8_bytes;
   11078   }
   11079 
   11080   char* result = NewArray<char>(utf8_bytes + 1);
   11081 
   11082   // Convert the UTF-16 string to a UTF-8 buffer. Start at the specified offset.
   11083   stream.Reset(this, offset);
   11084   character_position = offset;
   11085   int utf8_byte_position = 0;
   11086   last = unibrow::Utf16::kNoPreviousCharacter;
   11087   while (stream.HasMore() && character_position++ < offset + length) {
   11088     uint16_t character = stream.GetNext();
   11089     if (allow_nulls == DISALLOW_NULLS && character == 0) {
   11090       character = ' ';
   11091     }
   11092     utf8_byte_position +=
   11093         unibrow::Utf8::Encode(result + utf8_byte_position, character, last);
   11094     last = character;
   11095   }
   11096   result[utf8_byte_position] = 0;
   11097   return std::unique_ptr<char[]>(result);
   11098 }
   11099 
   11100 std::unique_ptr<char[]> String::ToCString(AllowNullsFlag allow_nulls,
   11101                                           RobustnessFlag robust_flag,
   11102                                           int* length_return) {
   11103   return ToCString(allow_nulls, robust_flag, 0, -1, length_return);
   11104 }
   11105 
   11106 
   11107 const uc16* String::GetTwoByteData(unsigned start) {
   11108   DCHECK(!IsOneByteRepresentationUnderneath());
   11109   switch (StringShape(this).representation_tag()) {
   11110     case kSeqStringTag:
   11111       return SeqTwoByteString::cast(this)->SeqTwoByteStringGetData(start);
   11112     case kExternalStringTag:
   11113       return ExternalTwoByteString::cast(this)->
   11114         ExternalTwoByteStringGetData(start);
   11115     case kSlicedStringTag: {
   11116       SlicedString* slice = SlicedString::cast(this);
   11117       return slice->parent()->GetTwoByteData(start + slice->offset());
   11118     }
   11119     case kConsStringTag:
   11120     case kThinStringTag:
   11121       UNREACHABLE();
   11122   }
   11123   UNREACHABLE();
   11124 }
   11125 
   11126 
   11127 const uc16* SeqTwoByteString::SeqTwoByteStringGetData(unsigned start) {
   11128   return reinterpret_cast<uc16*>(
   11129       reinterpret_cast<char*>(this) - kHeapObjectTag + kHeaderSize) + start;
   11130 }
   11131 
   11132 
   11133 void Relocatable::PostGarbageCollectionProcessing(Isolate* isolate) {
   11134   Relocatable* current = isolate->relocatable_top();
   11135   while (current != nullptr) {
   11136     current->PostGarbageCollection();
   11137     current = current->prev_;
   11138   }
   11139 }
   11140 
   11141 
   11142 // Reserve space for statics needing saving and restoring.
   11143 int Relocatable::ArchiveSpacePerThread() {
   11144   return sizeof(Relocatable*);  // NOLINT
   11145 }
   11146 
   11147 
   11148 // Archive statics that are thread-local.
   11149 char* Relocatable::ArchiveState(Isolate* isolate, char* to) {
   11150   *reinterpret_cast<Relocatable**>(to) = isolate->relocatable_top();
   11151   isolate->set_relocatable_top(nullptr);
   11152   return to + ArchiveSpacePerThread();
   11153 }
   11154 
   11155 
   11156 // Restore statics that are thread-local.
   11157 char* Relocatable::RestoreState(Isolate* isolate, char* from) {
   11158   isolate->set_relocatable_top(*reinterpret_cast<Relocatable**>(from));
   11159   return from + ArchiveSpacePerThread();
   11160 }
   11161 
   11162 char* Relocatable::Iterate(RootVisitor* v, char* thread_storage) {
   11163   Relocatable* top = *reinterpret_cast<Relocatable**>(thread_storage);
   11164   Iterate(v, top);
   11165   return thread_storage + ArchiveSpacePerThread();
   11166 }
   11167 
   11168 void Relocatable::Iterate(Isolate* isolate, RootVisitor* v) {
   11169   Iterate(v, isolate->relocatable_top());
   11170 }
   11171 
   11172 void Relocatable::Iterate(RootVisitor* v, Relocatable* top) {
   11173   Relocatable* current = top;
   11174   while (current != nullptr) {
   11175     current->IterateInstance(v);
   11176     current = current->prev_;
   11177   }
   11178 }
   11179 
   11180 
   11181 FlatStringReader::FlatStringReader(Isolate* isolate, Handle<String> str)
   11182     : Relocatable(isolate),
   11183       str_(str.location()),
   11184       length_(str->length()) {
   11185   PostGarbageCollection();
   11186 }
   11187 
   11188 
   11189 FlatStringReader::FlatStringReader(Isolate* isolate, Vector<const char> input)
   11190     : Relocatable(isolate),
   11191       str_(0),
   11192       is_one_byte_(true),
   11193       length_(input.length()),
   11194       start_(input.start()) {}
   11195 
   11196 
   11197 void FlatStringReader::PostGarbageCollection() {
   11198   if (str_ == nullptr) return;
   11199   Handle<String> str(str_);
   11200   DCHECK(str->IsFlat());
   11201   DisallowHeapAllocation no_gc;
   11202   // This does not actually prevent the vector from being relocated later.
   11203   String::FlatContent content = str->GetFlatContent();
   11204   DCHECK(content.IsFlat());
   11205   is_one_byte_ = content.IsOneByte();
   11206   if (is_one_byte_) {
   11207     start_ = content.ToOneByteVector().start();
   11208   } else {
   11209     start_ = content.ToUC16Vector().start();
   11210   }
   11211 }
   11212 
   11213 
   11214 void ConsStringIterator::Initialize(ConsString* cons_string, int offset) {
   11215   DCHECK_NOT_NULL(cons_string);
   11216   root_ = cons_string;
   11217   consumed_ = offset;
   11218   // Force stack blown condition to trigger restart.
   11219   depth_ = 1;
   11220   maximum_depth_ = kStackSize + depth_;
   11221   DCHECK(StackBlown());
   11222 }
   11223 
   11224 
   11225 String* ConsStringIterator::Continue(int* offset_out) {
   11226   DCHECK_NE(depth_, 0);
   11227   DCHECK_EQ(0, *offset_out);
   11228   bool blew_stack = StackBlown();
   11229   String* string = nullptr;
   11230   // Get the next leaf if there is one.
   11231   if (!blew_stack) string = NextLeaf(&blew_stack);
   11232   // Restart search from root.
   11233   if (blew_stack) {
   11234     DCHECK_NULL(string);
   11235     string = Search(offset_out);
   11236   }
   11237   // Ensure future calls return null immediately.
   11238   if (string == nullptr) Reset(nullptr);
   11239   return string;
   11240 }
   11241 
   11242 
   11243 String* ConsStringIterator::Search(int* offset_out) {
   11244   ConsString* cons_string = root_;
   11245   // Reset the stack, pushing the root string.
   11246   depth_ = 1;
   11247   maximum_depth_ = 1;
   11248   frames_[0] = cons_string;
   11249   const int consumed = consumed_;
   11250   int offset = 0;
   11251   while (true) {
   11252     // Loop until the string is found which contains the target offset.
   11253     String* string = cons_string->first();
   11254     int length = string->length();
   11255     int32_t type;
   11256     if (consumed < offset + length) {
   11257       // Target offset is in the left branch.
   11258       // Keep going if we're still in a ConString.
   11259       type = string->map()->instance_type();
   11260       if ((type & kStringRepresentationMask) == kConsStringTag) {
   11261         cons_string = ConsString::cast(string);
   11262         PushLeft(cons_string);
   11263         continue;
   11264       }
   11265       // Tell the stack we're done descending.
   11266       AdjustMaximumDepth();
   11267     } else {
   11268       // Descend right.
   11269       // Update progress through the string.
   11270       offset += length;
   11271       // Keep going if we're still in a ConString.
   11272       string = cons_string->second();
   11273       type = string->map()->instance_type();
   11274       if ((type & kStringRepresentationMask) == kConsStringTag) {
   11275         cons_string = ConsString::cast(string);
   11276         PushRight(cons_string);
   11277         continue;
   11278       }
   11279       // Need this to be updated for the current string.
   11280       length = string->length();
   11281       // Account for the possibility of an empty right leaf.
   11282       // This happens only if we have asked for an offset outside the string.
   11283       if (length == 0) {
   11284         // Reset so future operations will return null immediately.
   11285         Reset(nullptr);
   11286         return nullptr;
   11287       }
   11288       // Tell the stack we're done descending.
   11289       AdjustMaximumDepth();
   11290       // Pop stack so next iteration is in correct place.
   11291       Pop();
   11292     }
   11293     DCHECK_NE(length, 0);
   11294     // Adjust return values and exit.
   11295     consumed_ = offset + length;
   11296     *offset_out = consumed - offset;
   11297     return string;
   11298   }
   11299   UNREACHABLE();
   11300 }
   11301 
   11302 
   11303 String* ConsStringIterator::NextLeaf(bool* blew_stack) {
   11304   while (true) {
   11305     // Tree traversal complete.
   11306     if (depth_ == 0) {
   11307       *blew_stack = false;
   11308       return nullptr;
   11309     }
   11310     // We've lost track of higher nodes.
   11311     if (StackBlown()) {
   11312       *blew_stack = true;
   11313       return nullptr;
   11314     }
   11315     // Go right.
   11316     ConsString* cons_string = frames_[OffsetForDepth(depth_ - 1)];
   11317     String* string = cons_string->second();
   11318     int32_t type = string->map()->instance_type();
   11319     if ((type & kStringRepresentationMask) != kConsStringTag) {
   11320       // Pop stack so next iteration is in correct place.
   11321       Pop();
   11322       int length = string->length();
   11323       // Could be a flattened ConsString.
   11324       if (length == 0) continue;
   11325       consumed_ += length;
   11326       return string;
   11327     }
   11328     cons_string = ConsString::cast(string);
   11329     PushRight(cons_string);
   11330     // Need to traverse all the way left.
   11331     while (true) {
   11332       // Continue left.
   11333       string = cons_string->first();
   11334       type = string->map()->instance_type();
   11335       if ((type & kStringRepresentationMask) != kConsStringTag) {
   11336         AdjustMaximumDepth();
   11337         int length = string->length();
   11338         if (length == 0) break;  // Skip empty left-hand sides of ConsStrings.
   11339         consumed_ += length;
   11340         return string;
   11341       }
   11342       cons_string = ConsString::cast(string);
   11343       PushLeft(cons_string);
   11344     }
   11345   }
   11346   UNREACHABLE();
   11347 }
   11348 
   11349 
   11350 uint16_t ConsString::ConsStringGet(int index) {
   11351   DCHECK(index >= 0 && index < this->length());
   11352 
   11353   // Check for a flattened cons string
   11354   if (second()->length() == 0) {
   11355     String* left = first();
   11356     return left->Get(index);
   11357   }
   11358 
   11359   String* string = String::cast(this);
   11360 
   11361   while (true) {
   11362     if (StringShape(string).IsCons()) {
   11363       ConsString* cons_string = ConsString::cast(string);
   11364       String* left = cons_string->first();
   11365       if (left->length() > index) {
   11366         string = left;
   11367       } else {
   11368         index -= left->length();
   11369         string = cons_string->second();
   11370       }
   11371     } else {
   11372       return string->Get(index);
   11373     }
   11374   }
   11375 
   11376   UNREACHABLE();
   11377 }
   11378 
   11379 uint16_t ThinString::ThinStringGet(int index) { return actual()->Get(index); }
   11380 
   11381 uint16_t SlicedString::SlicedStringGet(int index) {
   11382   return parent()->Get(offset() + index);
   11383 }
   11384 
   11385 
   11386 template <typename sinkchar>
   11387 void String::WriteToFlat(String* src,
   11388                          sinkchar* sink,
   11389                          int f,
   11390                          int t) {
   11391   String* source = src;
   11392   int from = f;
   11393   int to = t;
   11394   while (true) {
   11395     DCHECK(0 <= from && from <= to && to <= source->length());
   11396     switch (StringShape(source).full_representation_tag()) {
   11397       case kOneByteStringTag | kExternalStringTag: {
   11398         CopyChars(sink, ExternalOneByteString::cast(source)->GetChars() + from,
   11399                   to - from);
   11400         return;
   11401       }
   11402       case kTwoByteStringTag | kExternalStringTag: {
   11403         const uc16* data =
   11404             ExternalTwoByteString::cast(source)->GetChars();
   11405         CopyChars(sink,
   11406                   data + from,
   11407                   to - from);
   11408         return;
   11409       }
   11410       case kOneByteStringTag | kSeqStringTag: {
   11411         CopyChars(sink,
   11412                   SeqOneByteString::cast(source)->GetChars() + from,
   11413                   to - from);
   11414         return;
   11415       }
   11416       case kTwoByteStringTag | kSeqStringTag: {
   11417         CopyChars(sink,
   11418                   SeqTwoByteString::cast(source)->GetChars() + from,
   11419                   to - from);
   11420         return;
   11421       }
   11422       case kOneByteStringTag | kConsStringTag:
   11423       case kTwoByteStringTag | kConsStringTag: {
   11424         ConsString* cons_string = ConsString::cast(source);
   11425         String* first = cons_string->first();
   11426         int boundary = first->length();
   11427         if (to - boundary >= boundary - from) {
   11428           // Right hand side is longer.  Recurse over left.
   11429           if (from < boundary) {
   11430             WriteToFlat(first, sink, from, boundary);
   11431             if (from == 0 && cons_string->second() == first) {
   11432               CopyChars(sink + boundary, sink, boundary);
   11433               return;
   11434             }
   11435             sink += boundary - from;
   11436             from = 0;
   11437           } else {
   11438             from -= boundary;
   11439           }
   11440           to -= boundary;
   11441           source = cons_string->second();
   11442         } else {
   11443           // Left hand side is longer.  Recurse over right.
   11444           if (to > boundary) {
   11445             String* second = cons_string->second();
   11446             // When repeatedly appending to a string, we get a cons string that
   11447             // is unbalanced to the left, a list, essentially.  We inline the
   11448             // common case of sequential one-byte right child.
   11449             if (to - boundary == 1) {
   11450               sink[boundary - from] = static_cast<sinkchar>(second->Get(0));
   11451             } else if (second->IsSeqOneByteString()) {
   11452               CopyChars(sink + boundary - from,
   11453                         SeqOneByteString::cast(second)->GetChars(),
   11454                         to - boundary);
   11455             } else {
   11456               WriteToFlat(second,
   11457                           sink + boundary - from,
   11458                           0,
   11459                           to - boundary);
   11460             }
   11461             to = boundary;
   11462           }
   11463           source = first;
   11464         }
   11465         break;
   11466       }
   11467       case kOneByteStringTag | kSlicedStringTag:
   11468       case kTwoByteStringTag | kSlicedStringTag: {
   11469         SlicedString* slice = SlicedString::cast(source);
   11470         unsigned offset = slice->offset();
   11471         WriteToFlat(slice->parent(), sink, from + offset, to + offset);
   11472         return;
   11473       }
   11474       case kOneByteStringTag | kThinStringTag:
   11475       case kTwoByteStringTag | kThinStringTag:
   11476         source = ThinString::cast(source)->actual();
   11477         break;
   11478     }
   11479   }
   11480 }
   11481 
   11482 template <typename SourceChar>
   11483 static void CalculateLineEndsImpl(Isolate* isolate, std::vector<int>* line_ends,
   11484                                   Vector<const SourceChar> src,
   11485                                   bool include_ending_line) {
   11486   const int src_len = src.length();
   11487   UnicodeCache* cache = isolate->unicode_cache();
   11488   for (int i = 0; i < src_len - 1; i++) {
   11489     SourceChar current = src[i];
   11490     SourceChar next = src[i + 1];
   11491     if (cache->IsLineTerminatorSequence(current, next)) line_ends->push_back(i);
   11492   }
   11493 
   11494   if (src_len > 0 && cache->IsLineTerminatorSequence(src[src_len - 1], 0)) {
   11495     line_ends->push_back(src_len - 1);
   11496   }
   11497   if (include_ending_line) {
   11498     // Include one character beyond the end of script. The rewriter uses that
   11499     // position for the implicit return statement.
   11500     line_ends->push_back(src_len);
   11501   }
   11502 }
   11503 
   11504 Handle<FixedArray> String::CalculateLineEnds(Isolate* isolate,
   11505                                              Handle<String> src,
   11506                                              bool include_ending_line) {
   11507   src = Flatten(isolate, src);
   11508   // Rough estimate of line count based on a roughly estimated average
   11509   // length of (unpacked) code.
   11510   int line_count_estimate = src->length() >> 4;
   11511   std::vector<int> line_ends;
   11512   line_ends.reserve(line_count_estimate);
   11513   { DisallowHeapAllocation no_allocation;  // ensure vectors stay valid.
   11514     // Dispatch on type of strings.
   11515     String::FlatContent content = src->GetFlatContent();
   11516     DCHECK(content.IsFlat());
   11517     if (content.IsOneByte()) {
   11518       CalculateLineEndsImpl(isolate,
   11519                             &line_ends,
   11520                             content.ToOneByteVector(),
   11521                             include_ending_line);
   11522     } else {
   11523       CalculateLineEndsImpl(isolate,
   11524                             &line_ends,
   11525                             content.ToUC16Vector(),
   11526                             include_ending_line);
   11527     }
   11528   }
   11529   int line_count = static_cast<int>(line_ends.size());
   11530   Handle<FixedArray> array = isolate->factory()->NewFixedArray(line_count);
   11531   for (int i = 0; i < line_count; i++) {
   11532     array->set(i, Smi::FromInt(line_ends[i]));
   11533   }
   11534   return array;
   11535 }
   11536 
   11537 
   11538 // Compares the contents of two strings by reading and comparing
   11539 // int-sized blocks of characters.
   11540 template <typename Char>
   11541 static inline bool CompareRawStringContents(const Char* const a,
   11542                                             const Char* const b,
   11543                                             int length) {
   11544   return CompareChars(a, b, length) == 0;
   11545 }
   11546 
   11547 
   11548 template<typename Chars1, typename Chars2>
   11549 class RawStringComparator : public AllStatic {
   11550  public:
   11551   static inline bool compare(const Chars1* a, const Chars2* b, int len) {
   11552     DCHECK(sizeof(Chars1) != sizeof(Chars2));
   11553     for (int i = 0; i < len; i++) {
   11554       if (a[i] != b[i]) {
   11555         return false;
   11556       }
   11557     }
   11558     return true;
   11559   }
   11560 };
   11561 
   11562 
   11563 template<>
   11564 class RawStringComparator<uint16_t, uint16_t> {
   11565  public:
   11566   static inline bool compare(const uint16_t* a, const uint16_t* b, int len) {
   11567     return CompareRawStringContents(a, b, len);
   11568   }
   11569 };
   11570 
   11571 
   11572 template<>
   11573 class RawStringComparator<uint8_t, uint8_t> {
   11574  public:
   11575   static inline bool compare(const uint8_t* a, const uint8_t* b, int len) {
   11576     return CompareRawStringContents(a, b, len);
   11577   }
   11578 };
   11579 
   11580 
   11581 class StringComparator {
   11582   class State {
   11583    public:
   11584     State() : is_one_byte_(true), length_(0), buffer8_(nullptr) {}
   11585 
   11586     void Init(String* string) {
   11587       ConsString* cons_string = String::VisitFlat(this, string);
   11588       iter_.Reset(cons_string);
   11589       if (cons_string != nullptr) {
   11590         int offset;
   11591         string = iter_.Next(&offset);
   11592         String::VisitFlat(this, string, offset);
   11593       }
   11594     }
   11595 
   11596     inline void VisitOneByteString(const uint8_t* chars, int length) {
   11597       is_one_byte_ = true;
   11598       buffer8_ = chars;
   11599       length_ = length;
   11600     }
   11601 
   11602     inline void VisitTwoByteString(const uint16_t* chars, int length) {
   11603       is_one_byte_ = false;
   11604       buffer16_ = chars;
   11605       length_ = length;
   11606     }
   11607 
   11608     void Advance(int consumed) {
   11609       DCHECK(consumed <= length_);
   11610       // Still in buffer.
   11611       if (length_ != consumed) {
   11612         if (is_one_byte_) {
   11613           buffer8_ += consumed;
   11614         } else {
   11615           buffer16_ += consumed;
   11616         }
   11617         length_ -= consumed;
   11618         return;
   11619       }
   11620       // Advance state.
   11621       int offset;
   11622       String* next = iter_.Next(&offset);
   11623       DCHECK_EQ(0, offset);
   11624       DCHECK_NOT_NULL(next);
   11625       String::VisitFlat(this, next);
   11626     }
   11627 
   11628     ConsStringIterator iter_;
   11629     bool is_one_byte_;
   11630     int length_;
   11631     union {
   11632       const uint8_t* buffer8_;
   11633       const uint16_t* buffer16_;
   11634     };
   11635 
   11636    private:
   11637     DISALLOW_COPY_AND_ASSIGN(State);
   11638   };
   11639 
   11640  public:
   11641   inline StringComparator() {}
   11642 
   11643   template<typename Chars1, typename Chars2>
   11644   static inline bool Equals(State* state_1, State* state_2, int to_check) {
   11645     const Chars1* a = reinterpret_cast<const Chars1*>(state_1->buffer8_);
   11646     const Chars2* b = reinterpret_cast<const Chars2*>(state_2->buffer8_);
   11647     return RawStringComparator<Chars1, Chars2>::compare(a, b, to_check);
   11648   }
   11649 
   11650   bool Equals(String* string_1, String* string_2) {
   11651     int length = string_1->length();
   11652     state_1_.Init(string_1);
   11653     state_2_.Init(string_2);
   11654     while (true) {
   11655       int to_check = Min(state_1_.length_, state_2_.length_);
   11656       DCHECK(to_check > 0 && to_check <= length);
   11657       bool is_equal;
   11658       if (state_1_.is_one_byte_) {
   11659         if (state_2_.is_one_byte_) {
   11660           is_equal = Equals<uint8_t, uint8_t>(&state_1_, &state_2_, to_check);
   11661         } else {
   11662           is_equal = Equals<uint8_t, uint16_t>(&state_1_, &state_2_, to_check);
   11663         }
   11664       } else {
   11665         if (state_2_.is_one_byte_) {
   11666           is_equal = Equals<uint16_t, uint8_t>(&state_1_, &state_2_, to_check);
   11667         } else {
   11668           is_equal = Equals<uint16_t, uint16_t>(&state_1_, &state_2_, to_check);
   11669         }
   11670       }
   11671       // Looping done.
   11672       if (!is_equal) return false;
   11673       length -= to_check;
   11674       // Exit condition. Strings are equal.
   11675       if (length == 0) return true;
   11676       state_1_.Advance(to_check);
   11677       state_2_.Advance(to_check);
   11678     }
   11679   }
   11680 
   11681  private:
   11682   State state_1_;
   11683   State state_2_;
   11684 
   11685   DISALLOW_COPY_AND_ASSIGN(StringComparator);
   11686 };
   11687 
   11688 
   11689 bool String::SlowEquals(String* other) {
   11690   DisallowHeapAllocation no_gc;
   11691   // Fast check: negative check with lengths.
   11692   int len = length();
   11693   if (len != other->length()) return false;
   11694   if (len == 0) return true;
   11695 
   11696   // Fast check: if at least one ThinString is involved, dereference it/them
   11697   // and restart.
   11698   if (this->IsThinString() || other->IsThinString()) {
   11699     if (other->IsThinString()) other = ThinString::cast(other)->actual();
   11700     if (this->IsThinString()) {
   11701       return ThinString::cast(this)->actual()->Equals(other);
   11702     } else {
   11703       return this->Equals(other);
   11704     }
   11705   }
   11706 
   11707   // Fast check: if hash code is computed for both strings
   11708   // a fast negative check can be performed.
   11709   if (HasHashCode() && other->HasHashCode()) {
   11710 #ifdef ENABLE_SLOW_DCHECKS
   11711     if (FLAG_enable_slow_asserts) {
   11712       if (Hash() != other->Hash()) {
   11713         bool found_difference = false;
   11714         for (int i = 0; i < len; i++) {
   11715           if (Get(i) != other->Get(i)) {
   11716             found_difference = true;
   11717             break;
   11718           }
   11719         }
   11720         DCHECK(found_difference);
   11721       }
   11722     }
   11723 #endif
   11724     if (Hash() != other->Hash()) return false;
   11725   }
   11726 
   11727   // We know the strings are both non-empty. Compare the first chars
   11728   // before we try to flatten the strings.
   11729   if (this->Get(0) != other->Get(0)) return false;
   11730 
   11731   if (IsSeqOneByteString() && other->IsSeqOneByteString()) {
   11732     const uint8_t* str1 = SeqOneByteString::cast(this)->GetChars();
   11733     const uint8_t* str2 = SeqOneByteString::cast(other)->GetChars();
   11734     return CompareRawStringContents(str1, str2, len);
   11735   }
   11736 
   11737   StringComparator comparator;
   11738   return comparator.Equals(this, other);
   11739 }
   11740 
   11741 bool String::SlowEquals(Isolate* isolate, Handle<String> one,
   11742                         Handle<String> two) {
   11743   // Fast check: negative check with lengths.
   11744   int one_length = one->length();
   11745   if (one_length != two->length()) return false;
   11746   if (one_length == 0) return true;
   11747 
   11748   // Fast check: if at least one ThinString is involved, dereference it/them
   11749   // and restart.
   11750   if (one->IsThinString() || two->IsThinString()) {
   11751     if (one->IsThinString())
   11752       one = handle(ThinString::cast(*one)->actual(), isolate);
   11753     if (two->IsThinString())
   11754       two = handle(ThinString::cast(*two)->actual(), isolate);
   11755     return String::Equals(isolate, one, two);
   11756   }
   11757 
   11758   // Fast check: if hash code is computed for both strings
   11759   // a fast negative check can be performed.
   11760   if (one->HasHashCode() && two->HasHashCode()) {
   11761 #ifdef ENABLE_SLOW_DCHECKS
   11762     if (FLAG_enable_slow_asserts) {
   11763       if (one->Hash() != two->Hash()) {
   11764         bool found_difference = false;
   11765         for (int i = 0; i < one_length; i++) {
   11766           if (one->Get(i) != two->Get(i)) {
   11767             found_difference = true;
   11768             break;
   11769           }
   11770         }
   11771         DCHECK(found_difference);
   11772       }
   11773     }
   11774 #endif
   11775     if (one->Hash() != two->Hash()) return false;
   11776   }
   11777 
   11778   // We know the strings are both non-empty. Compare the first chars
   11779   // before we try to flatten the strings.
   11780   if (one->Get(0) != two->Get(0)) return false;
   11781 
   11782   one = String::Flatten(isolate, one);
   11783   two = String::Flatten(isolate, two);
   11784 
   11785   DisallowHeapAllocation no_gc;
   11786   String::FlatContent flat1 = one->GetFlatContent();
   11787   String::FlatContent flat2 = two->GetFlatContent();
   11788 
   11789   if (flat1.IsOneByte() && flat2.IsOneByte()) {
   11790       return CompareRawStringContents(flat1.ToOneByteVector().start(),
   11791                                       flat2.ToOneByteVector().start(),
   11792                                       one_length);
   11793   } else {
   11794     for (int i = 0; i < one_length; i++) {
   11795       if (flat1.Get(i) != flat2.Get(i)) return false;
   11796     }
   11797     return true;
   11798   }
   11799 }
   11800 
   11801 
   11802 // static
   11803 ComparisonResult String::Compare(Isolate* isolate, Handle<String> x,
   11804                                  Handle<String> y) {
   11805   // A few fast case tests before we flatten.
   11806   if (x.is_identical_to(y)) {
   11807     return ComparisonResult::kEqual;
   11808   } else if (y->length() == 0) {
   11809     return x->length() == 0 ? ComparisonResult::kEqual
   11810                             : ComparisonResult::kGreaterThan;
   11811   } else if (x->length() == 0) {
   11812     return ComparisonResult::kLessThan;
   11813   }
   11814 
   11815   int const d = x->Get(0) - y->Get(0);
   11816   if (d < 0) {
   11817     return ComparisonResult::kLessThan;
   11818   } else if (d > 0) {
   11819     return ComparisonResult::kGreaterThan;
   11820   }
   11821 
   11822   // Slow case.
   11823   x = String::Flatten(isolate, x);
   11824   y = String::Flatten(isolate, y);
   11825 
   11826   DisallowHeapAllocation no_gc;
   11827   ComparisonResult result = ComparisonResult::kEqual;
   11828   int prefix_length = x->length();
   11829   if (y->length() < prefix_length) {
   11830     prefix_length = y->length();
   11831     result = ComparisonResult::kGreaterThan;
   11832   } else if (y->length() > prefix_length) {
   11833     result = ComparisonResult::kLessThan;
   11834   }
   11835   int r;
   11836   String::FlatContent x_content = x->GetFlatContent();
   11837   String::FlatContent y_content = y->GetFlatContent();
   11838   if (x_content.IsOneByte()) {
   11839     Vector<const uint8_t> x_chars = x_content.ToOneByteVector();
   11840     if (y_content.IsOneByte()) {
   11841       Vector<const uint8_t> y_chars = y_content.ToOneByteVector();
   11842       r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
   11843     } else {
   11844       Vector<const uc16> y_chars = y_content.ToUC16Vector();
   11845       r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
   11846     }
   11847   } else {
   11848     Vector<const uc16> x_chars = x_content.ToUC16Vector();
   11849     if (y_content.IsOneByte()) {
   11850       Vector<const uint8_t> y_chars = y_content.ToOneByteVector();
   11851       r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
   11852     } else {
   11853       Vector<const uc16> y_chars = y_content.ToUC16Vector();
   11854       r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
   11855     }
   11856   }
   11857   if (r < 0) {
   11858     result = ComparisonResult::kLessThan;
   11859   } else if (r > 0) {
   11860     result = ComparisonResult::kGreaterThan;
   11861   }
   11862   return result;
   11863 }
   11864 
   11865 Object* String::IndexOf(Isolate* isolate, Handle<Object> receiver,
   11866                         Handle<Object> search, Handle<Object> position) {
   11867   if (receiver->IsNullOrUndefined(isolate)) {
   11868     THROW_NEW_ERROR_RETURN_FAILURE(
   11869         isolate, NewTypeError(MessageTemplate::kCalledOnNullOrUndefined,
   11870                               isolate->factory()->NewStringFromAsciiChecked(
   11871                                   "String.prototype.indexOf")));
   11872   }
   11873   Handle<String> receiver_string;
   11874   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver_string,
   11875                                      Object::ToString(isolate, receiver));
   11876 
   11877   Handle<String> search_string;
   11878   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, search_string,
   11879                                      Object::ToString(isolate, search));
   11880 
   11881   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, position,
   11882                                      Object::ToInteger(isolate, position));
   11883 
   11884   uint32_t index = receiver_string->ToValidIndex(*position);
   11885   return Smi::FromInt(
   11886       String::IndexOf(isolate, receiver_string, search_string, index));
   11887 }
   11888 
   11889 namespace {
   11890 
   11891 template <typename T>
   11892 int SearchString(Isolate* isolate, String::FlatContent receiver_content,
   11893                  Vector<T> pat_vector, int start_index) {
   11894   if (receiver_content.IsOneByte()) {
   11895     return SearchString(isolate, receiver_content.ToOneByteVector(), pat_vector,
   11896                         start_index);
   11897   }
   11898   return SearchString(isolate, receiver_content.ToUC16Vector(), pat_vector,
   11899                       start_index);
   11900 }
   11901 
   11902 }  // namespace
   11903 
   11904 int String::IndexOf(Isolate* isolate, Handle<String> receiver,
   11905                     Handle<String> search, int start_index) {
   11906   DCHECK_LE(0, start_index);
   11907   DCHECK(start_index <= receiver->length());
   11908 
   11909   uint32_t search_length = search->length();
   11910   if (search_length == 0) return start_index;
   11911 
   11912   uint32_t receiver_length = receiver->length();
   11913   if (start_index + search_length > receiver_length) return -1;
   11914 
   11915   receiver = String::Flatten(isolate, receiver);
   11916   search = String::Flatten(isolate, search);
   11917 
   11918   DisallowHeapAllocation no_gc;  // ensure vectors stay valid
   11919   // Extract flattened substrings of cons strings before getting encoding.
   11920   String::FlatContent receiver_content = receiver->GetFlatContent();
   11921   String::FlatContent search_content = search->GetFlatContent();
   11922 
   11923   // dispatch on type of strings
   11924   if (search_content.IsOneByte()) {
   11925     Vector<const uint8_t> pat_vector = search_content.ToOneByteVector();
   11926     return SearchString<const uint8_t>(isolate, receiver_content, pat_vector,
   11927                                        start_index);
   11928   }
   11929   Vector<const uc16> pat_vector = search_content.ToUC16Vector();
   11930   return SearchString<const uc16>(isolate, receiver_content, pat_vector,
   11931                                   start_index);
   11932 }
   11933 
   11934 MaybeHandle<String> String::GetSubstitution(Isolate* isolate, Match* match,
   11935                                             Handle<String> replacement,
   11936                                             int start_index) {
   11937   DCHECK_GE(start_index, 0);
   11938 
   11939   Factory* factory = isolate->factory();
   11940 
   11941   const int replacement_length = replacement->length();
   11942   const int captures_length = match->CaptureCount();
   11943 
   11944   replacement = String::Flatten(isolate, replacement);
   11945 
   11946   Handle<String> dollar_string =
   11947       factory->LookupSingleCharacterStringFromCode('$');
   11948   int next_dollar_ix =
   11949       String::IndexOf(isolate, replacement, dollar_string, start_index);
   11950   if (next_dollar_ix < 0) {
   11951     return replacement;
   11952   }
   11953 
   11954   IncrementalStringBuilder builder(isolate);
   11955 
   11956   if (next_dollar_ix > 0) {
   11957     builder.AppendString(factory->NewSubString(replacement, 0, next_dollar_ix));
   11958   }
   11959 
   11960   while (true) {
   11961     const int peek_ix = next_dollar_ix + 1;
   11962     if (peek_ix >= replacement_length) {
   11963       builder.AppendCharacter('$');
   11964       return builder.Finish();
   11965     }
   11966 
   11967     int continue_from_ix = -1;
   11968     const uint16_t peek = replacement->Get(peek_ix);
   11969     switch (peek) {
   11970       case '$':  // $$
   11971         builder.AppendCharacter('$');
   11972         continue_from_ix = peek_ix + 1;
   11973         break;
   11974       case '&':  // $& - match
   11975         builder.AppendString(match->GetMatch());
   11976         continue_from_ix = peek_ix + 1;
   11977         break;
   11978       case '`':  // $` - prefix
   11979         builder.AppendString(match->GetPrefix());
   11980         continue_from_ix = peek_ix + 1;
   11981         break;
   11982       case '\'':  // $' - suffix
   11983         builder.AppendString(match->GetSuffix());
   11984         continue_from_ix = peek_ix + 1;
   11985         break;
   11986       case '0':
   11987       case '1':
   11988       case '2':
   11989       case '3':
   11990       case '4':
   11991       case '5':
   11992       case '6':
   11993       case '7':
   11994       case '8':
   11995       case '9': {
   11996         // Valid indices are $1 .. $9, $01 .. $09 and $10 .. $99
   11997         int scaled_index = (peek - '0');
   11998         int advance = 1;
   11999 
   12000         if (peek_ix + 1 < replacement_length) {
   12001           const uint16_t next_peek = replacement->Get(peek_ix + 1);
   12002           if (next_peek >= '0' && next_peek <= '9') {
   12003             const int new_scaled_index = scaled_index * 10 + (next_peek - '0');
   12004             if (new_scaled_index < captures_length) {
   12005               scaled_index = new_scaled_index;
   12006               advance = 2;
   12007             }
   12008           }
   12009         }
   12010 
   12011         if (scaled_index == 0 || scaled_index >= captures_length) {
   12012           builder.AppendCharacter('$');
   12013           continue_from_ix = peek_ix;
   12014           break;
   12015         }
   12016 
   12017         bool capture_exists;
   12018         Handle<String> capture;
   12019         ASSIGN_RETURN_ON_EXCEPTION(
   12020             isolate, capture, match->GetCapture(scaled_index, &capture_exists),
   12021             String);
   12022         if (capture_exists) builder.AppendString(capture);
   12023         continue_from_ix = peek_ix + advance;
   12024         break;
   12025       }
   12026       case '<': {  // $<name> - named capture
   12027         typedef String::Match::CaptureState CaptureState;
   12028 
   12029         if (!match->HasNamedCaptures()) {
   12030           builder.AppendCharacter('$');
   12031           continue_from_ix = peek_ix;
   12032           break;
   12033         }
   12034 
   12035         Handle<String> bracket_string =
   12036             factory->LookupSingleCharacterStringFromCode('>');
   12037         const int closing_bracket_ix =
   12038             String::IndexOf(isolate, replacement, bracket_string, peek_ix + 1);
   12039 
   12040         if (closing_bracket_ix == -1) {
   12041           // No closing bracket was found, treat '$<' as a string literal.
   12042           builder.AppendCharacter('$');
   12043           continue_from_ix = peek_ix;
   12044           break;
   12045         }
   12046 
   12047         Handle<String> capture_name =
   12048             factory->NewSubString(replacement, peek_ix + 1, closing_bracket_ix);
   12049         Handle<String> capture;
   12050         CaptureState capture_state;
   12051         ASSIGN_RETURN_ON_EXCEPTION(
   12052             isolate, capture,
   12053             match->GetNamedCapture(capture_name, &capture_state), String);
   12054 
   12055         switch (capture_state) {
   12056           case CaptureState::INVALID:
   12057           case CaptureState::UNMATCHED:
   12058             break;
   12059           case CaptureState::MATCHED:
   12060             builder.AppendString(capture);
   12061             break;
   12062         }
   12063 
   12064         continue_from_ix = closing_bracket_ix + 1;
   12065         break;
   12066       }
   12067       default:
   12068         builder.AppendCharacter('$');
   12069         continue_from_ix = peek_ix;
   12070         break;
   12071     }
   12072 
   12073     // Go the the next $ in the replacement.
   12074     // TODO(jgruber): Single-char lookups could be much more efficient.
   12075     DCHECK_NE(continue_from_ix, -1);
   12076     next_dollar_ix =
   12077         String::IndexOf(isolate, replacement, dollar_string, continue_from_ix);
   12078 
   12079     // Return if there are no more $ characters in the replacement. If we
   12080     // haven't reached the end, we need to append the suffix.
   12081     if (next_dollar_ix < 0) {
   12082       if (continue_from_ix < replacement_length) {
   12083         builder.AppendString(factory->NewSubString(
   12084             replacement, continue_from_ix, replacement_length));
   12085       }
   12086       return builder.Finish();
   12087     }
   12088 
   12089     // Append substring between the previous and the next $ character.
   12090     if (next_dollar_ix > continue_from_ix) {
   12091       builder.AppendString(
   12092           factory->NewSubString(replacement, continue_from_ix, next_dollar_ix));
   12093     }
   12094   }
   12095 
   12096   UNREACHABLE();
   12097 }
   12098 
   12099 namespace {  // for String.Prototype.lastIndexOf
   12100 
   12101 template <typename schar, typename pchar>
   12102 int StringMatchBackwards(Vector<const schar> subject,
   12103                          Vector<const pchar> pattern, int idx) {
   12104   int pattern_length = pattern.length();
   12105   DCHECK_GE(pattern_length, 1);
   12106   DCHECK(idx + pattern_length <= subject.length());
   12107 
   12108   if (sizeof(schar) == 1 && sizeof(pchar) > 1) {
   12109     for (int i = 0; i < pattern_length; i++) {
   12110       uc16 c = pattern[i];
   12111       if (c > String::kMaxOneByteCharCode) {
   12112         return -1;
   12113       }
   12114     }
   12115   }
   12116 
   12117   pchar pattern_first_char = pattern[0];
   12118   for (int i = idx; i >= 0; i--) {
   12119     if (subject[i] != pattern_first_char) continue;
   12120     int j = 1;
   12121     while (j < pattern_length) {
   12122       if (pattern[j] != subject[i + j]) {
   12123         break;
   12124       }
   12125       j++;
   12126     }
   12127     if (j == pattern_length) {
   12128       return i;
   12129     }
   12130   }
   12131   return -1;
   12132 }
   12133 
   12134 }  // namespace
   12135 
   12136 Object* String::LastIndexOf(Isolate* isolate, Handle<Object> receiver,
   12137                             Handle<Object> search, Handle<Object> position) {
   12138   if (receiver->IsNullOrUndefined(isolate)) {
   12139     THROW_NEW_ERROR_RETURN_FAILURE(
   12140         isolate, NewTypeError(MessageTemplate::kCalledOnNullOrUndefined,
   12141                               isolate->factory()->NewStringFromAsciiChecked(
   12142                                   "String.prototype.lastIndexOf")));
   12143   }
   12144   Handle<String> receiver_string;
   12145   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver_string,
   12146                                      Object::ToString(isolate, receiver));
   12147 
   12148   Handle<String> search_string;
   12149   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, search_string,
   12150                                      Object::ToString(isolate, search));
   12151 
   12152   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, position,
   12153                                      Object::ToNumber(isolate, position));
   12154 
   12155   uint32_t start_index;
   12156 
   12157   if (position->IsNaN()) {
   12158     start_index = receiver_string->length();
   12159   } else {
   12160     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, position,
   12161                                        Object::ToInteger(isolate, position));
   12162     start_index = receiver_string->ToValidIndex(*position);
   12163   }
   12164 
   12165   uint32_t pattern_length = search_string->length();
   12166   uint32_t receiver_length = receiver_string->length();
   12167 
   12168   if (start_index + pattern_length > receiver_length) {
   12169     start_index = receiver_length - pattern_length;
   12170   }
   12171 
   12172   if (pattern_length == 0) {
   12173     return Smi::FromInt(start_index);
   12174   }
   12175 
   12176   receiver_string = String::Flatten(isolate, receiver_string);
   12177   search_string = String::Flatten(isolate, search_string);
   12178 
   12179   int last_index = -1;
   12180   DisallowHeapAllocation no_gc;  // ensure vectors stay valid
   12181 
   12182   String::FlatContent receiver_content = receiver_string->GetFlatContent();
   12183   String::FlatContent search_content = search_string->GetFlatContent();
   12184 
   12185   if (search_content.IsOneByte()) {
   12186     Vector<const uint8_t> pat_vector = search_content.ToOneByteVector();
   12187     if (receiver_content.IsOneByte()) {
   12188       last_index = StringMatchBackwards(receiver_content.ToOneByteVector(),
   12189                                         pat_vector, start_index);
   12190     } else {
   12191       last_index = StringMatchBackwards(receiver_content.ToUC16Vector(),
   12192                                         pat_vector, start_index);
   12193     }
   12194   } else {
   12195     Vector<const uc16> pat_vector = search_content.ToUC16Vector();
   12196     if (receiver_content.IsOneByte()) {
   12197       last_index = StringMatchBackwards(receiver_content.ToOneByteVector(),
   12198                                         pat_vector, start_index);
   12199     } else {
   12200       last_index = StringMatchBackwards(receiver_content.ToUC16Vector(),
   12201                                         pat_vector, start_index);
   12202     }
   12203   }
   12204   return Smi::FromInt(last_index);
   12205 }
   12206 
   12207 bool String::IsUtf8EqualTo(Vector<const char> str, bool allow_prefix_match) {
   12208   int slen = length();
   12209   // Can't check exact length equality, but we can check bounds.
   12210   int str_len = str.length();
   12211   if (!allow_prefix_match &&
   12212       (str_len < slen ||
   12213           str_len > slen*static_cast<int>(unibrow::Utf8::kMaxEncodedSize))) {
   12214     return false;
   12215   }
   12216 
   12217   int i = 0;
   12218   unibrow::Utf8Iterator it = unibrow::Utf8Iterator(str);
   12219   while (i < slen && !it.Done()) {
   12220     if (Get(i++) != *it) return false;
   12221     ++it;
   12222   }
   12223 
   12224   return (allow_prefix_match || i == slen) && it.Done();
   12225 }
   12226 
   12227 template <>
   12228 bool String::IsEqualTo(Vector<const uint8_t> str) {
   12229   return IsOneByteEqualTo(str);
   12230 }
   12231 
   12232 template <>
   12233 bool String::IsEqualTo(Vector<const uc16> str) {
   12234   return IsTwoByteEqualTo(str);
   12235 }
   12236 
   12237 bool String::IsOneByteEqualTo(Vector<const uint8_t> str) {
   12238   int slen = length();
   12239   if (str.length() != slen) return false;
   12240   DisallowHeapAllocation no_gc;
   12241   FlatContent content = GetFlatContent();
   12242   if (content.IsOneByte()) {
   12243     return CompareChars(content.ToOneByteVector().start(),
   12244                         str.start(), slen) == 0;
   12245   }
   12246   for (int i = 0; i < slen; i++) {
   12247     if (Get(i) != static_cast<uint16_t>(str[i])) return false;
   12248   }
   12249   return true;
   12250 }
   12251 
   12252 
   12253 bool String::IsTwoByteEqualTo(Vector<const uc16> str) {
   12254   int slen = length();
   12255   if (str.length() != slen) return false;
   12256   DisallowHeapAllocation no_gc;
   12257   FlatContent content = GetFlatContent();
   12258   if (content.IsTwoByte()) {
   12259     return CompareChars(content.ToUC16Vector().start(), str.start(), slen) == 0;
   12260   }
   12261   for (int i = 0; i < slen; i++) {
   12262     if (Get(i) != str[i]) return false;
   12263   }
   12264   return true;
   12265 }
   12266 
   12267 uint32_t String::ComputeAndSetHash(Isolate* isolate) {
   12268   // Should only be called if hash code has not yet been computed.
   12269   DCHECK(!HasHashCode());
   12270 
   12271   // Store the hash code in the object.
   12272   uint32_t field =
   12273       IteratingStringHasher::Hash(this, isolate->heap()->HashSeed());
   12274   set_hash_field(field);
   12275 
   12276   // Check the hash code is there.
   12277   DCHECK(HasHashCode());
   12278   uint32_t result = field >> kHashShift;
   12279   DCHECK_NE(result, 0);  // Ensure that the hash value of 0 is never computed.
   12280   return result;
   12281 }
   12282 
   12283 
   12284 bool String::ComputeArrayIndex(uint32_t* index) {
   12285   int length = this->length();
   12286   if (length == 0 || length > kMaxArrayIndexSize) return false;
   12287   StringCharacterStream stream(this);
   12288   return StringToArrayIndex(&stream, index);
   12289 }
   12290 
   12291 
   12292 bool String::SlowAsArrayIndex(uint32_t* index) {
   12293   if (length() <= kMaxCachedArrayIndexLength) {
   12294     Hash();  // force computation of hash code
   12295     uint32_t field = hash_field();
   12296     if ((field & kIsNotArrayIndexMask) != 0) return false;
   12297     // Isolate the array index form the full hash field.
   12298     *index = ArrayIndexValueBits::decode(field);
   12299     return true;
   12300   } else {
   12301     return ComputeArrayIndex(index);
   12302   }
   12303 }
   12304 
   12305 
   12306 Handle<String> SeqString::Truncate(Handle<SeqString> string, int new_length) {
   12307   if (new_length == 0) return string->GetReadOnlyRoots().empty_string_handle();
   12308 
   12309   int new_size, old_size;
   12310   int old_length = string->length();
   12311   if (old_length <= new_length) return string;
   12312 
   12313   if (string->IsSeqOneByteString()) {
   12314     old_size = SeqOneByteString::SizeFor(old_length);
   12315     new_size = SeqOneByteString::SizeFor(new_length);
   12316   } else {
   12317     DCHECK(string->IsSeqTwoByteString());
   12318     old_size = SeqTwoByteString::SizeFor(old_length);
   12319     new_size = SeqTwoByteString::SizeFor(new_length);
   12320   }
   12321 
   12322   int delta = old_size - new_size;
   12323 
   12324   Address start_of_string = string->address();
   12325   DCHECK_OBJECT_ALIGNED(start_of_string);
   12326   DCHECK_OBJECT_ALIGNED(start_of_string + new_size);
   12327 
   12328   Heap* heap = Heap::FromWritableHeapObject(*string);
   12329   // Sizes are pointer size aligned, so that we can use filler objects
   12330   // that are a multiple of pointer size.
   12331   heap->CreateFillerObjectAt(start_of_string + new_size, delta,
   12332                              ClearRecordedSlots::kNo);
   12333   // We are storing the new length using release store after creating a filler
   12334   // for the left-over space to avoid races with the sweeper thread.
   12335   string->synchronized_set_length(new_length);
   12336 
   12337   return string;
   12338 }
   12339 
   12340 void SeqOneByteString::clear_padding() {
   12341   int data_size = SeqString::kHeaderSize + length() * kOneByteSize;
   12342   memset(reinterpret_cast<void*>(address() + data_size), 0,
   12343          SizeFor(length()) - data_size);
   12344 }
   12345 
   12346 void SeqTwoByteString::clear_padding() {
   12347   int data_size = SeqString::kHeaderSize + length() * kUC16Size;
   12348   memset(reinterpret_cast<void*>(address() + data_size), 0,
   12349          SizeFor(length()) - data_size);
   12350 }
   12351 
   12352 int ExternalString::ExternalPayloadSize() const {
   12353   int length_multiplier = IsTwoByteRepresentation() ? i::kShortSize : kCharSize;
   12354   return length() * length_multiplier;
   12355 }
   12356 
   12357 uint32_t StringHasher::MakeArrayIndexHash(uint32_t value, int length) {
   12358   // For array indexes mix the length into the hash as an array index could
   12359   // be zero.
   12360   DCHECK_GT(length, 0);
   12361   DCHECK_LE(length, String::kMaxArrayIndexSize);
   12362   DCHECK(TenToThe(String::kMaxCachedArrayIndexLength) <
   12363          (1 << String::kArrayIndexValueBits));
   12364 
   12365   value <<= String::ArrayIndexValueBits::kShift;
   12366   value |= length << String::ArrayIndexLengthBits::kShift;
   12367 
   12368   DCHECK_EQ(value & String::kIsNotArrayIndexMask, 0);
   12369   DCHECK_EQ(length <= String::kMaxCachedArrayIndexLength,
   12370             Name::ContainsCachedArrayIndex(value));
   12371   return value;
   12372 }
   12373 
   12374 
   12375 uint32_t StringHasher::GetHashField() {
   12376   if (length_ <= String::kMaxHashCalcLength) {
   12377     if (is_array_index_) {
   12378       return MakeArrayIndexHash(array_index_, length_);
   12379     }
   12380     return (GetHashCore(raw_running_hash_) << String::kHashShift) |
   12381            String::kIsNotArrayIndexMask;
   12382   } else {
   12383     return (length_ << String::kHashShift) | String::kIsNotArrayIndexMask;
   12384   }
   12385 }
   12386 
   12387 uint32_t StringHasher::ComputeUtf8Hash(Vector<const char> chars, uint64_t seed,
   12388                                        int* utf16_length_out) {
   12389   int vector_length = chars.length();
   12390   // Handle some edge cases
   12391   if (vector_length <= 1) {
   12392     DCHECK(vector_length == 0 ||
   12393            static_cast<uint8_t>(chars.start()[0]) <=
   12394                unibrow::Utf8::kMaxOneByteChar);
   12395     *utf16_length_out = vector_length;
   12396     return HashSequentialString(chars.start(), vector_length, seed);
   12397   }
   12398 
   12399   // Start with a fake length which won't affect computation.
   12400   // It will be updated later.
   12401   StringHasher hasher(String::kMaxArrayIndexSize, seed);
   12402   DCHECK(hasher.is_array_index_);
   12403 
   12404   unibrow::Utf8Iterator it = unibrow::Utf8Iterator(chars);
   12405   int utf16_length = 0;
   12406   bool is_index = true;
   12407 
   12408   while (utf16_length < String::kMaxHashCalcLength && !it.Done()) {
   12409     utf16_length++;
   12410     uint16_t c = *it;
   12411     ++it;
   12412     hasher.AddCharacter(c);
   12413     if (is_index) is_index = hasher.UpdateIndex(c);
   12414   }
   12415 
   12416   // Now that hashing is done, we just need to calculate utf16_length
   12417   while (!it.Done()) {
   12418     ++it;
   12419     utf16_length++;
   12420   }
   12421 
   12422   *utf16_length_out = utf16_length;
   12423   // Must set length here so that hash computation is correct.
   12424   hasher.length_ = utf16_length;
   12425   return hasher.GetHashField();
   12426 }
   12427 
   12428 
   12429 void IteratingStringHasher::VisitConsString(ConsString* cons_string) {
   12430   // Run small ConsStrings through ConsStringIterator.
   12431   if (cons_string->length() < 64) {
   12432     ConsStringIterator iter(cons_string);
   12433     int offset;
   12434     String* string;
   12435     while (nullptr != (string = iter.Next(&offset))) {
   12436       DCHECK_EQ(0, offset);
   12437       String::VisitFlat(this, string, 0);
   12438     }
   12439     return;
   12440   }
   12441   // Slow case.
   12442   const int max_length = String::kMaxHashCalcLength;
   12443   int length = std::min(cons_string->length(), max_length);
   12444   if (cons_string->HasOnlyOneByteChars()) {
   12445     uint8_t* buffer = new uint8_t[length];
   12446     String::WriteToFlat(cons_string, buffer, 0, length);
   12447     AddCharacters(buffer, length);
   12448     delete[] buffer;
   12449   } else {
   12450     uint16_t* buffer = new uint16_t[length];
   12451     String::WriteToFlat(cons_string, buffer, 0, length);
   12452     AddCharacters(buffer, length);
   12453     delete[] buffer;
   12454   }
   12455 }
   12456 
   12457 
   12458 void String::PrintOn(FILE* file) {
   12459   int length = this->length();
   12460   for (int i = 0; i < length; i++) {
   12461     PrintF(file, "%c", Get(i));
   12462   }
   12463 }
   12464 
   12465 
   12466 int Map::Hash() {
   12467   // For performance reasons we only hash the 3 most variable fields of a map:
   12468   // constructor, prototype and bit_field2. For predictability reasons we
   12469   // use objects' offsets in respective pages for hashing instead of raw
   12470   // addresses.
   12471 
   12472   // Shift away the tag.
   12473   int hash = ObjectAddressForHashing(GetConstructor()) >> 2;
   12474 
   12475   // XOR-ing the prototype and constructor directly yields too many zero bits
   12476   // when the two pointers are close (which is fairly common).
   12477   // To avoid this we shift the prototype bits relatively to the constructor.
   12478   hash ^= ObjectAddressForHashing(prototype()) << (32 - kPageSizeBits);
   12479 
   12480   return hash ^ (hash >> 16) ^ bit_field2();
   12481 }
   12482 
   12483 
   12484 namespace {
   12485 
   12486 bool CheckEquivalent(const Map* first, const Map* second) {
   12487   return first->GetConstructor() == second->GetConstructor() &&
   12488          first->prototype() == second->prototype() &&
   12489          first->instance_type() == second->instance_type() &&
   12490          first->bit_field() == second->bit_field() &&
   12491          first->is_extensible() == second->is_extensible() &&
   12492          first->new_target_is_base() == second->new_target_is_base() &&
   12493          first->has_hidden_prototype() == second->has_hidden_prototype();
   12494 }
   12495 
   12496 }  // namespace
   12497 
   12498 bool Map::EquivalentToForTransition(const Map* other) const {
   12499   if (!CheckEquivalent(this, other)) return false;
   12500   if (instance_type() == JS_FUNCTION_TYPE) {
   12501     // JSFunctions require more checks to ensure that sloppy function is
   12502     // not equivalent to strict function.
   12503     int nof = Min(NumberOfOwnDescriptors(), other->NumberOfOwnDescriptors());
   12504     return instance_descriptors()->IsEqualUpTo(other->instance_descriptors(),
   12505                                                nof);
   12506   }
   12507   return true;
   12508 }
   12509 
   12510 bool Map::EquivalentToForElementsKindTransition(const Map* other) const {
   12511   if (!EquivalentToForTransition(other)) return false;
   12512 #ifdef DEBUG
   12513   // Ensure that we don't try to generate elements kind transitions from maps
   12514   // with fields that may be generalized in-place. This must already be handled
   12515   // during addition of a new field.
   12516   DescriptorArray* descriptors = instance_descriptors();
   12517   int nof = NumberOfOwnDescriptors();
   12518   for (int i = 0; i < nof; i++) {
   12519     PropertyDetails details = descriptors->GetDetails(i);
   12520     if (details.location() == kField) {
   12521       DCHECK(!IsInplaceGeneralizableField(details.constness(),
   12522                                           details.representation(),
   12523                                           descriptors->GetFieldType(i)));
   12524     }
   12525   }
   12526 #endif
   12527   return true;
   12528 }
   12529 
   12530 bool Map::EquivalentToForNormalization(const Map* other,
   12531                                        PropertyNormalizationMode mode) const {
   12532   int properties =
   12533       mode == CLEAR_INOBJECT_PROPERTIES ? 0 : other->GetInObjectProperties();
   12534   return CheckEquivalent(this, other) && bit_field2() == other->bit_field2() &&
   12535          GetInObjectProperties() == properties &&
   12536          JSObject::GetEmbedderFieldCount(this) ==
   12537              JSObject::GetEmbedderFieldCount(other);
   12538 }
   12539 
   12540 
   12541 void JSFunction::MarkForOptimization(ConcurrencyMode mode) {
   12542   Isolate* isolate = GetIsolate();
   12543   if (!isolate->concurrent_recompilation_enabled() ||
   12544       isolate->bootstrapper()->IsActive()) {
   12545     mode = ConcurrencyMode::kNotConcurrent;
   12546   }
   12547 
   12548   DCHECK(!is_compiled() || IsInterpreted());
   12549   DCHECK(shared()->IsInterpreted());
   12550   DCHECK(!IsOptimized());
   12551   DCHECK(!HasOptimizedCode());
   12552   DCHECK(shared()->allows_lazy_compilation() ||
   12553          !shared()->optimization_disabled());
   12554 
   12555   if (mode == ConcurrencyMode::kConcurrent) {
   12556     if (IsInOptimizationQueue()) {
   12557       if (FLAG_trace_concurrent_recompilation) {
   12558         PrintF("  ** Not marking ");
   12559         ShortPrint();
   12560         PrintF(" -- already in optimization queue.\n");
   12561       }
   12562       return;
   12563     }
   12564     if (FLAG_trace_concurrent_recompilation) {
   12565       PrintF("  ** Marking ");
   12566       ShortPrint();
   12567       PrintF(" for concurrent recompilation.\n");
   12568     }
   12569   }
   12570 
   12571   SetOptimizationMarker(mode == ConcurrencyMode::kConcurrent
   12572                             ? OptimizationMarker::kCompileOptimizedConcurrent
   12573                             : OptimizationMarker::kCompileOptimized);
   12574 }
   12575 
   12576 // static
   12577 void JSFunction::EnsureFeedbackVector(Handle<JSFunction> function) {
   12578   Isolate* const isolate = function->GetIsolate();
   12579   if (function->feedback_cell()->value()->IsUndefined(isolate)) {
   12580     Handle<SharedFunctionInfo> shared(function->shared(), isolate);
   12581     if (!shared->HasAsmWasmData()) {
   12582       Handle<FeedbackVector> feedback_vector =
   12583           FeedbackVector::New(isolate, shared);
   12584       if (function->feedback_cell() == isolate->heap()->many_closures_cell()) {
   12585         Handle<FeedbackCell> feedback_cell =
   12586             isolate->factory()->NewOneClosureCell(feedback_vector);
   12587         function->set_feedback_cell(*feedback_cell);
   12588       } else {
   12589         function->feedback_cell()->set_value(*feedback_vector);
   12590       }
   12591     }
   12592   }
   12593 }
   12594 
   12595 static void GetMinInobjectSlack(Map* map, void* data) {
   12596   int slack = map->UnusedPropertyFields();
   12597   if (*reinterpret_cast<int*>(data) > slack) {
   12598     *reinterpret_cast<int*>(data) = slack;
   12599   }
   12600 }
   12601 
   12602 int Map::InstanceSizeFromSlack(int slack) const {
   12603   return instance_size() - slack * kPointerSize;
   12604 }
   12605 
   12606 static void ShrinkInstanceSize(Map* map, void* data) {
   12607   int slack = *reinterpret_cast<int*>(data);
   12608   DCHECK_GE(slack, 0);
   12609 #ifdef DEBUG
   12610   int old_visitor_id = Map::GetVisitorId(map);
   12611   int new_unused = map->UnusedPropertyFields() - slack;
   12612 #endif
   12613   map->set_instance_size(map->InstanceSizeFromSlack(slack));
   12614   map->set_construction_counter(Map::kNoSlackTracking);
   12615   DCHECK_EQ(old_visitor_id, Map::GetVisitorId(map));
   12616   DCHECK_EQ(new_unused, map->UnusedPropertyFields());
   12617 }
   12618 
   12619 static void StopSlackTracking(Map* map, void* data) {
   12620   map->set_construction_counter(Map::kNoSlackTracking);
   12621 }
   12622 
   12623 int Map::ComputeMinObjectSlack(Isolate* isolate) {
   12624   DisallowHeapAllocation no_gc;
   12625   // Has to be an initial map.
   12626   DCHECK(GetBackPointer()->IsUndefined(isolate));
   12627 
   12628   int slack = UnusedPropertyFields();
   12629   TransitionsAccessor transitions(isolate, this, &no_gc);
   12630   transitions.TraverseTransitionTree(&GetMinInobjectSlack, &slack);
   12631   return slack;
   12632 }
   12633 
   12634 void Map::CompleteInobjectSlackTracking(Isolate* isolate) {
   12635   DisallowHeapAllocation no_gc;
   12636   // Has to be an initial map.
   12637   DCHECK(GetBackPointer()->IsUndefined(isolate));
   12638 
   12639   int slack = ComputeMinObjectSlack(isolate);
   12640   TransitionsAccessor transitions(isolate, this, &no_gc);
   12641   if (slack != 0) {
   12642     // Resize the initial map and all maps in its transition tree.
   12643     transitions.TraverseTransitionTree(&ShrinkInstanceSize, &slack);
   12644   } else {
   12645     transitions.TraverseTransitionTree(&StopSlackTracking, nullptr);
   12646   }
   12647 }
   12648 
   12649 
   12650 static bool PrototypeBenefitsFromNormalization(Handle<JSObject> object) {
   12651   DisallowHeapAllocation no_gc;
   12652   if (!object->HasFastProperties()) return false;
   12653   if (object->IsJSGlobalProxy()) return false;
   12654   if (object->GetIsolate()->bootstrapper()->IsActive()) return false;
   12655   return !object->map()->is_prototype_map() ||
   12656          !object->map()->should_be_fast_prototype_map();
   12657 }
   12658 
   12659 // static
   12660 void JSObject::MakePrototypesFast(Handle<Object> receiver,
   12661                                   WhereToStart where_to_start,
   12662                                   Isolate* isolate) {
   12663   if (!receiver->IsJSReceiver()) return;
   12664   for (PrototypeIterator iter(isolate, Handle<JSReceiver>::cast(receiver),
   12665                               where_to_start);
   12666        !iter.IsAtEnd(); iter.Advance()) {
   12667     Handle<Object> current = PrototypeIterator::GetCurrent(iter);
   12668     if (!current->IsJSObject()) return;
   12669     Handle<JSObject> current_obj = Handle<JSObject>::cast(current);
   12670     Map* current_map = current_obj->map();
   12671     if (current_map->is_prototype_map()) {
   12672       // If the map is already marked as should be fast, we're done. Its
   12673       // prototypes will have been marked already as well.
   12674       if (current_map->should_be_fast_prototype_map()) return;
   12675       Handle<Map> map(current_map, isolate);
   12676       Map::SetShouldBeFastPrototypeMap(map, true, isolate);
   12677       JSObject::OptimizeAsPrototype(current_obj);
   12678     }
   12679   }
   12680 }
   12681 
   12682 // static
   12683 void JSObject::OptimizeAsPrototype(Handle<JSObject> object,
   12684                                    bool enable_setup_mode) {
   12685   if (object->IsJSGlobalObject()) return;
   12686   if (enable_setup_mode && PrototypeBenefitsFromNormalization(object)) {
   12687     // First normalize to ensure all JSFunctions are DATA_CONSTANT.
   12688     JSObject::NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, 0,
   12689                                   "NormalizeAsPrototype");
   12690   }
   12691   if (object->map()->is_prototype_map()) {
   12692     if (object->map()->should_be_fast_prototype_map() &&
   12693         !object->HasFastProperties()) {
   12694       JSObject::MigrateSlowToFast(object, 0, "OptimizeAsPrototype");
   12695     }
   12696   } else {
   12697     Handle<Map> new_map = Map::Copy(object->GetIsolate(),
   12698                                     handle(object->map(), object->GetIsolate()),
   12699                                     "CopyAsPrototype");
   12700     JSObject::MigrateToMap(object, new_map);
   12701     object->map()->set_is_prototype_map(true);
   12702 
   12703     // Replace the pointer to the exact constructor with the Object function
   12704     // from the same context if undetectable from JS. This is to avoid keeping
   12705     // memory alive unnecessarily.
   12706     Object* maybe_constructor = object->map()->GetConstructor();
   12707     if (maybe_constructor->IsJSFunction()) {
   12708       JSFunction* constructor = JSFunction::cast(maybe_constructor);
   12709       if (!constructor->shared()->IsApiFunction()) {
   12710         Context* context = constructor->context()->native_context();
   12711         JSFunction* object_function = context->object_function();
   12712         object->map()->SetConstructor(object_function);
   12713       }
   12714     }
   12715   }
   12716 }
   12717 
   12718 
   12719 // static
   12720 void JSObject::ReoptimizeIfPrototype(Handle<JSObject> object) {
   12721   if (!object->map()->is_prototype_map()) return;
   12722   if (!object->map()->should_be_fast_prototype_map()) return;
   12723   OptimizeAsPrototype(object);
   12724 }
   12725 
   12726 
   12727 // static
   12728 void JSObject::LazyRegisterPrototypeUser(Handle<Map> user, Isolate* isolate) {
   12729   // Contract: In line with InvalidatePrototypeChains()'s requirements,
   12730   // leaf maps don't need to register as users, only prototypes do.
   12731   DCHECK(user->is_prototype_map());
   12732 
   12733   Handle<Map> current_user = user;
   12734   Handle<PrototypeInfo> current_user_info =
   12735       Map::GetOrCreatePrototypeInfo(user, isolate);
   12736   for (PrototypeIterator iter(isolate, user); !iter.IsAtEnd(); iter.Advance()) {
   12737     // Walk up the prototype chain as far as links haven't been registered yet.
   12738     if (current_user_info->registry_slot() != PrototypeInfo::UNREGISTERED) {
   12739       break;
   12740     }
   12741     Handle<Object> maybe_proto = PrototypeIterator::GetCurrent(iter);
   12742     // Proxies on the prototype chain are not supported. They make it
   12743     // impossible to make any assumptions about the prototype chain anyway.
   12744     if (maybe_proto->IsJSProxy()) return;
   12745     Handle<JSObject> proto = Handle<JSObject>::cast(maybe_proto);
   12746     Handle<PrototypeInfo> proto_info =
   12747         Map::GetOrCreatePrototypeInfo(proto, isolate);
   12748     Handle<Object> maybe_registry(proto_info->prototype_users(), isolate);
   12749     Handle<WeakArrayList> registry =
   12750         maybe_registry->IsSmi()
   12751             ? handle(ReadOnlyRoots(isolate->heap()).empty_weak_array_list(),
   12752                      isolate)
   12753             : Handle<WeakArrayList>::cast(maybe_registry);
   12754     int slot = 0;
   12755     Handle<WeakArrayList> new_array =
   12756         PrototypeUsers::Add(isolate, registry, current_user, &slot);
   12757     current_user_info->set_registry_slot(slot);
   12758     if (!maybe_registry.is_identical_to(new_array)) {
   12759       proto_info->set_prototype_users(*new_array);
   12760     }
   12761     if (FLAG_trace_prototype_users) {
   12762       PrintF("Registering %p as a user of prototype %p (map=%p).\n",
   12763              reinterpret_cast<void*>(*current_user),
   12764              reinterpret_cast<void*>(*proto),
   12765              reinterpret_cast<void*>(proto->map()));
   12766     }
   12767 
   12768     current_user = handle(proto->map(), isolate);
   12769     current_user_info = proto_info;
   12770   }
   12771 }
   12772 
   12773 
   12774 // Can be called regardless of whether |user| was actually registered with
   12775 // |prototype|. Returns true when there was a registration.
   12776 // static
   12777 bool JSObject::UnregisterPrototypeUser(Handle<Map> user, Isolate* isolate) {
   12778   DCHECK(user->is_prototype_map());
   12779   // If it doesn't have a PrototypeInfo, it was never registered.
   12780   if (!user->prototype_info()->IsPrototypeInfo()) return false;
   12781   // If it had no prototype before, see if it had users that might expect
   12782   // registration.
   12783   if (!user->prototype()->IsJSObject()) {
   12784     Object* users =
   12785         PrototypeInfo::cast(user->prototype_info())->prototype_users();
   12786     return users->IsWeakArrayList();
   12787   }
   12788   Handle<JSObject> prototype(JSObject::cast(user->prototype()), isolate);
   12789   Handle<PrototypeInfo> user_info =
   12790       Map::GetOrCreatePrototypeInfo(user, isolate);
   12791   int slot = user_info->registry_slot();
   12792   if (slot == PrototypeInfo::UNREGISTERED) return false;
   12793   DCHECK(prototype->map()->is_prototype_map());
   12794   Object* maybe_proto_info = prototype->map()->prototype_info();
   12795   // User knows its registry slot, prototype info and user registry must exist.
   12796   DCHECK(maybe_proto_info->IsPrototypeInfo());
   12797   Handle<PrototypeInfo> proto_info(PrototypeInfo::cast(maybe_proto_info),
   12798                                    isolate);
   12799   Handle<WeakArrayList> prototype_users(
   12800       WeakArrayList::cast(proto_info->prototype_users()), isolate);
   12801   DCHECK_EQ(prototype_users->Get(slot), HeapObjectReference::Weak(*user));
   12802   PrototypeUsers::MarkSlotEmpty(*prototype_users, slot);
   12803   if (FLAG_trace_prototype_users) {
   12804     PrintF("Unregistering %p as a user of prototype %p.\n",
   12805            reinterpret_cast<void*>(*user), reinterpret_cast<void*>(*prototype));
   12806   }
   12807   return true;
   12808 }
   12809 
   12810 namespace {
   12811 
   12812 // This function must be kept in sync with
   12813 // AccessorAssembler::InvalidateValidityCellIfPrototype() which does pre-checks
   12814 // before jumping here.
   12815 void InvalidateOnePrototypeValidityCellInternal(Map* map) {
   12816   DCHECK(map->is_prototype_map());
   12817   if (FLAG_trace_prototype_users) {
   12818     PrintF("Invalidating prototype map %p 's cell\n",
   12819            reinterpret_cast<void*>(map));
   12820   }
   12821   Object* maybe_cell = map->prototype_validity_cell();
   12822   if (maybe_cell->IsCell()) {
   12823     // Just set the value; the cell will be replaced lazily.
   12824     Cell* cell = Cell::cast(maybe_cell);
   12825     cell->set_value(Smi::FromInt(Map::kPrototypeChainInvalid));
   12826   }
   12827 }
   12828 
   12829 void InvalidatePrototypeChainsInternal(Map* map) {
   12830   InvalidateOnePrototypeValidityCellInternal(map);
   12831 
   12832   Object* maybe_proto_info = map->prototype_info();
   12833   if (!maybe_proto_info->IsPrototypeInfo()) return;
   12834   PrototypeInfo* proto_info = PrototypeInfo::cast(maybe_proto_info);
   12835   WeakArrayList* prototype_users =
   12836       WeakArrayList::cast(proto_info->prototype_users());
   12837   // For now, only maps register themselves as users.
   12838   for (int i = PrototypeUsers::kFirstIndex; i < prototype_users->length();
   12839        ++i) {
   12840     HeapObject* heap_object;
   12841     if (prototype_users->Get(i)->ToWeakHeapObject(&heap_object) &&
   12842         heap_object->IsMap()) {
   12843       // Walk the prototype chain (backwards, towards leaf objects) if
   12844       // necessary.
   12845       InvalidatePrototypeChainsInternal(Map::cast(heap_object));
   12846     }
   12847   }
   12848 }
   12849 
   12850 }  // namespace
   12851 
   12852 // static
   12853 Map* JSObject::InvalidatePrototypeChains(Map* map) {
   12854   DisallowHeapAllocation no_gc;
   12855   InvalidatePrototypeChainsInternal(map);
   12856   return map;
   12857 }
   12858 
   12859 // We also invalidate global objects validity cell when a new lexical
   12860 // environment variable is added. This is necessary to ensure that
   12861 // Load/StoreGlobalIC handlers that load/store from global object's prototype
   12862 // get properly invalidated.
   12863 // Note, that the normal Load/StoreICs that load/store through the global object
   12864 // in the prototype chain are not affected by appearance of a new lexical
   12865 // variable and therefore we don't propagate invalidation down.
   12866 // static
   12867 void JSObject::InvalidatePrototypeValidityCell(JSGlobalObject* global) {
   12868   DisallowHeapAllocation no_gc;
   12869   InvalidateOnePrototypeValidityCellInternal(global->map());
   12870 }
   12871 
   12872 // static
   12873 Handle<PrototypeInfo> Map::GetOrCreatePrototypeInfo(Handle<JSObject> prototype,
   12874                                                     Isolate* isolate) {
   12875   Object* maybe_proto_info = prototype->map()->prototype_info();
   12876   if (maybe_proto_info->IsPrototypeInfo()) {
   12877     return handle(PrototypeInfo::cast(maybe_proto_info), isolate);
   12878   }
   12879   Handle<PrototypeInfo> proto_info = isolate->factory()->NewPrototypeInfo();
   12880   prototype->map()->set_prototype_info(*proto_info);
   12881   return proto_info;
   12882 }
   12883 
   12884 
   12885 // static
   12886 Handle<PrototypeInfo> Map::GetOrCreatePrototypeInfo(Handle<Map> prototype_map,
   12887                                                     Isolate* isolate) {
   12888   Object* maybe_proto_info = prototype_map->prototype_info();
   12889   if (maybe_proto_info->IsPrototypeInfo()) {
   12890     return handle(PrototypeInfo::cast(maybe_proto_info), isolate);
   12891   }
   12892   Handle<PrototypeInfo> proto_info = isolate->factory()->NewPrototypeInfo();
   12893   prototype_map->set_prototype_info(*proto_info);
   12894   return proto_info;
   12895 }
   12896 
   12897 // static
   12898 void Map::SetShouldBeFastPrototypeMap(Handle<Map> map, bool value,
   12899                                       Isolate* isolate) {
   12900   if (value == false && !map->prototype_info()->IsPrototypeInfo()) {
   12901     // "False" is the implicit default value, so there's nothing to do.
   12902     return;
   12903   }
   12904   GetOrCreatePrototypeInfo(map, isolate)->set_should_be_fast_map(value);
   12905 }
   12906 
   12907 // static
   12908 Handle<Object> Map::GetOrCreatePrototypeChainValidityCell(Handle<Map> map,
   12909                                                           Isolate* isolate) {
   12910   Handle<Object> maybe_prototype;
   12911   if (map->IsJSGlobalObjectMap()) {
   12912     DCHECK(map->is_prototype_map());
   12913     // Global object is prototype of a global proxy and therefore we can
   12914     // use its validity cell for guarding global object's prototype change.
   12915     maybe_prototype = isolate->global_object();
   12916   } else {
   12917     maybe_prototype =
   12918         handle(map->GetPrototypeChainRootMap(isolate)->prototype(), isolate);
   12919   }
   12920   if (!maybe_prototype->IsJSObject()) {
   12921     return handle(Smi::FromInt(Map::kPrototypeChainValid), isolate);
   12922   }
   12923   Handle<JSObject> prototype = Handle<JSObject>::cast(maybe_prototype);
   12924   // Ensure the prototype is registered with its own prototypes so its cell
   12925   // will be invalidated when necessary.
   12926   JSObject::LazyRegisterPrototypeUser(handle(prototype->map(), isolate),
   12927                                       isolate);
   12928 
   12929   Object* maybe_cell = prototype->map()->prototype_validity_cell();
   12930   // Return existing cell if it's still valid.
   12931   if (maybe_cell->IsCell()) {
   12932     Handle<Cell> cell(Cell::cast(maybe_cell), isolate);
   12933     if (cell->value() == Smi::FromInt(Map::kPrototypeChainValid)) {
   12934       return cell;
   12935     }
   12936   }
   12937   // Otherwise create a new cell.
   12938   Handle<Cell> cell = isolate->factory()->NewCell(
   12939       handle(Smi::FromInt(Map::kPrototypeChainValid), isolate));
   12940   prototype->map()->set_prototype_validity_cell(*cell);
   12941   return cell;
   12942 }
   12943 
   12944 // static
   12945 bool Map::IsPrototypeChainInvalidated(Map* map) {
   12946   DCHECK(map->is_prototype_map());
   12947   Object* maybe_cell = map->prototype_validity_cell();
   12948   if (maybe_cell->IsCell()) {
   12949     Cell* cell = Cell::cast(maybe_cell);
   12950     return cell->value() != Smi::FromInt(Map::kPrototypeChainValid);
   12951   }
   12952   return true;
   12953 }
   12954 
   12955 // static
   12956 void Map::SetPrototype(Isolate* isolate, Handle<Map> map,
   12957                        Handle<Object> prototype,
   12958                        bool enable_prototype_setup_mode) {
   12959   RuntimeCallTimerScope stats_scope(isolate, *map,
   12960                                     RuntimeCallCounterId::kMap_SetPrototype);
   12961 
   12962   bool is_hidden = false;
   12963   if (prototype->IsJSObject()) {
   12964     Handle<JSObject> prototype_jsobj = Handle<JSObject>::cast(prototype);
   12965     JSObject::OptimizeAsPrototype(prototype_jsobj, enable_prototype_setup_mode);
   12966 
   12967     Object* maybe_constructor = prototype_jsobj->map()->GetConstructor();
   12968     if (maybe_constructor->IsJSFunction()) {
   12969       JSFunction* constructor = JSFunction::cast(maybe_constructor);
   12970       Object* data = constructor->shared()->function_data();
   12971       is_hidden = (data->IsFunctionTemplateInfo() &&
   12972                    FunctionTemplateInfo::cast(data)->hidden_prototype()) ||
   12973                   prototype->IsJSGlobalObject();
   12974     } else if (maybe_constructor->IsFunctionTemplateInfo()) {
   12975       is_hidden =
   12976           FunctionTemplateInfo::cast(maybe_constructor)->hidden_prototype() ||
   12977           prototype->IsJSGlobalObject();
   12978     }
   12979   }
   12980   map->set_has_hidden_prototype(is_hidden);
   12981 
   12982   WriteBarrierMode wb_mode =
   12983       prototype->IsNull(isolate) ? SKIP_WRITE_BARRIER : UPDATE_WRITE_BARRIER;
   12984   map->set_prototype(*prototype, wb_mode);
   12985 }
   12986 
   12987 Handle<Object> CacheInitialJSArrayMaps(Handle<Context> native_context,
   12988                                        Handle<Map> initial_map) {
   12989   // Replace all of the cached initial array maps in the native context with
   12990   // the appropriate transitioned elements kind maps.
   12991   Handle<Map> current_map = initial_map;
   12992   ElementsKind kind = current_map->elements_kind();
   12993   DCHECK_EQ(GetInitialFastElementsKind(), kind);
   12994   native_context->set(Context::ArrayMapIndex(kind), *current_map);
   12995   for (int i = GetSequenceIndexFromFastElementsKind(kind) + 1;
   12996        i < kFastElementsKindCount; ++i) {
   12997     Handle<Map> new_map;
   12998     ElementsKind next_kind = GetFastElementsKindFromSequenceIndex(i);
   12999     if (Map* maybe_elements_transition = current_map->ElementsTransitionMap()) {
   13000       new_map = handle(maybe_elements_transition, native_context->GetIsolate());
   13001     } else {
   13002       new_map =
   13003           Map::CopyAsElementsKind(native_context->GetIsolate(), current_map,
   13004                                   next_kind, INSERT_TRANSITION);
   13005     }
   13006     DCHECK_EQ(next_kind, new_map->elements_kind());
   13007     native_context->set(Context::ArrayMapIndex(next_kind), *new_map);
   13008     current_map = new_map;
   13009   }
   13010   return initial_map;
   13011 }
   13012 
   13013 namespace {
   13014 
   13015 void SetInstancePrototype(Isolate* isolate, Handle<JSFunction> function,
   13016                           Handle<JSReceiver> value) {
   13017   // Now some logic for the maps of the objects that are created by using this
   13018   // function as a constructor.
   13019   if (function->has_initial_map()) {
   13020     // If the function has allocated the initial map replace it with a
   13021     // copy containing the new prototype.  Also complete any in-object
   13022     // slack tracking that is in progress at this point because it is
   13023     // still tracking the old copy.
   13024     function->CompleteInobjectSlackTrackingIfActive();
   13025 
   13026     Handle<Map> initial_map(function->initial_map(), isolate);
   13027 
   13028     if (!isolate->bootstrapper()->IsActive() &&
   13029         initial_map->instance_type() == JS_OBJECT_TYPE) {
   13030       // Put the value in the initial map field until an initial map is needed.
   13031       // At that point, a new initial map is created and the prototype is put
   13032       // into the initial map where it belongs.
   13033       function->set_prototype_or_initial_map(*value);
   13034     } else {
   13035       Handle<Map> new_map =
   13036           Map::Copy(isolate, initial_map, "SetInstancePrototype");
   13037       JSFunction::SetInitialMap(function, new_map, value);
   13038 
   13039       // If the function is used as the global Array function, cache the
   13040       // updated initial maps (and transitioned versions) in the native context.
   13041       Handle<Context> native_context(function->context()->native_context(),
   13042                                      isolate);
   13043       Handle<Object> array_function(
   13044           native_context->get(Context::ARRAY_FUNCTION_INDEX), isolate);
   13045       if (array_function->IsJSFunction() &&
   13046           *function == JSFunction::cast(*array_function)) {
   13047         CacheInitialJSArrayMaps(native_context, new_map);
   13048       }
   13049     }
   13050 
   13051     // Deoptimize all code that embeds the previous initial map.
   13052     initial_map->dependent_code()->DeoptimizeDependentCodeGroup(
   13053         isolate, DependentCode::kInitialMapChangedGroup);
   13054   } else {
   13055     // Put the value in the initial map field until an initial map is
   13056     // needed.  At that point, a new initial map is created and the
   13057     // prototype is put into the initial map where it belongs.
   13058     function->set_prototype_or_initial_map(*value);
   13059     if (value->IsJSObject()) {
   13060       // Optimize as prototype to detach it from its transition tree.
   13061       JSObject::OptimizeAsPrototype(Handle<JSObject>::cast(value));
   13062     }
   13063   }
   13064 }
   13065 
   13066 }  // anonymous namespace
   13067 
   13068 void JSFunction::SetPrototype(Handle<JSFunction> function,
   13069                               Handle<Object> value) {
   13070   DCHECK(function->IsConstructor() ||
   13071          IsGeneratorFunction(function->shared()->kind()));
   13072   Isolate* isolate = function->GetIsolate();
   13073   Handle<JSReceiver> construct_prototype;
   13074 
   13075   // If the value is not a JSReceiver, store the value in the map's
   13076   // constructor field so it can be accessed.  Also, set the prototype
   13077   // used for constructing objects to the original object prototype.
   13078   // See ECMA-262 13.2.2.
   13079   if (!value->IsJSReceiver()) {
   13080     // Copy the map so this does not affect unrelated functions.
   13081     // Remove map transitions because they point to maps with a
   13082     // different prototype.
   13083     Handle<Map> new_map =
   13084         Map::Copy(isolate, handle(function->map(), isolate), "SetPrototype");
   13085 
   13086     JSObject::MigrateToMap(function, new_map);
   13087     new_map->SetConstructor(*value);
   13088     new_map->set_has_non_instance_prototype(true);
   13089 
   13090     FunctionKind kind = function->shared()->kind();
   13091     Handle<Context> native_context(function->context()->native_context(),
   13092                                    isolate);
   13093 
   13094     construct_prototype = Handle<JSReceiver>(
   13095         IsGeneratorFunction(kind)
   13096             ? IsAsyncFunction(kind)
   13097                   ? native_context->initial_async_generator_prototype()
   13098                   : native_context->initial_generator_prototype()
   13099             : native_context->initial_object_prototype(),
   13100         isolate);
   13101   } else {
   13102     construct_prototype = Handle<JSReceiver>::cast(value);
   13103     function->map()->set_has_non_instance_prototype(false);
   13104   }
   13105 
   13106   SetInstancePrototype(isolate, function, construct_prototype);
   13107 }
   13108 
   13109 void JSFunction::SetInitialMap(Handle<JSFunction> function, Handle<Map> map,
   13110                                Handle<Object> prototype) {
   13111   if (map->prototype() != *prototype)
   13112     Map::SetPrototype(function->GetIsolate(), map, prototype);
   13113   function->set_prototype_or_initial_map(*map);
   13114   map->SetConstructor(*function);
   13115   if (FLAG_trace_maps) {
   13116     LOG(function->GetIsolate(), MapEvent("InitialMap", nullptr, *map, "",
   13117                                          function->shared()->DebugName()));
   13118   }
   13119 }
   13120 
   13121 
   13122 #ifdef DEBUG
   13123 namespace {
   13124 
   13125 bool CanSubclassHaveInobjectProperties(InstanceType instance_type) {
   13126   switch (instance_type) {
   13127     case JS_API_OBJECT_TYPE:
   13128     case JS_ARRAY_BUFFER_TYPE:
   13129     case JS_ARRAY_TYPE:
   13130     case JS_ASYNC_FROM_SYNC_ITERATOR_TYPE:
   13131     case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
   13132     case JS_DATA_VIEW_TYPE:
   13133     case JS_DATE_TYPE:
   13134     case JS_FUNCTION_TYPE:
   13135     case JS_GENERATOR_OBJECT_TYPE:
   13136 #ifdef V8_INTL_SUPPORT
   13137     case JS_INTL_COLLATOR_TYPE:
   13138     case JS_INTL_LIST_FORMAT_TYPE:
   13139     case JS_INTL_PLURAL_RULES_TYPE:
   13140     case JS_INTL_RELATIVE_TIME_FORMAT_TYPE:
   13141 #endif
   13142     case JS_ASYNC_GENERATOR_OBJECT_TYPE:
   13143     case JS_MAP_TYPE:
   13144     case JS_MESSAGE_OBJECT_TYPE:
   13145     case JS_OBJECT_TYPE:
   13146     case JS_ERROR_TYPE:
   13147     case JS_ARGUMENTS_TYPE:
   13148     case JS_PROMISE_TYPE:
   13149     case JS_REGEXP_TYPE:
   13150     case JS_SET_TYPE:
   13151     case JS_SPECIAL_API_OBJECT_TYPE:
   13152     case JS_TYPED_ARRAY_TYPE:
   13153     case JS_VALUE_TYPE:
   13154     case JS_WEAK_MAP_TYPE:
   13155     case JS_WEAK_SET_TYPE:
   13156     case WASM_GLOBAL_TYPE:
   13157     case WASM_INSTANCE_TYPE:
   13158     case WASM_MEMORY_TYPE:
   13159     case WASM_MODULE_TYPE:
   13160     case WASM_TABLE_TYPE:
   13161       return true;
   13162 
   13163     case BIGINT_TYPE:
   13164     case OBJECT_BOILERPLATE_DESCRIPTION_TYPE:
   13165     case BYTECODE_ARRAY_TYPE:
   13166     case BYTE_ARRAY_TYPE:
   13167     case CELL_TYPE:
   13168     case CODE_TYPE:
   13169     case FILLER_TYPE:
   13170     case FIXED_ARRAY_TYPE:
   13171     case SCRIPT_CONTEXT_TABLE_TYPE:
   13172     case FIXED_DOUBLE_ARRAY_TYPE:
   13173     case FEEDBACK_METADATA_TYPE:
   13174     case FOREIGN_TYPE:
   13175     case FREE_SPACE_TYPE:
   13176     case HASH_TABLE_TYPE:
   13177     case ORDERED_HASH_MAP_TYPE:
   13178     case ORDERED_HASH_SET_TYPE:
   13179     case NAME_DICTIONARY_TYPE:
   13180     case GLOBAL_DICTIONARY_TYPE:
   13181     case NUMBER_DICTIONARY_TYPE:
   13182     case SIMPLE_NUMBER_DICTIONARY_TYPE:
   13183     case STRING_TABLE_TYPE:
   13184     case HEAP_NUMBER_TYPE:
   13185     case JS_BOUND_FUNCTION_TYPE:
   13186     case JS_GLOBAL_OBJECT_TYPE:
   13187     case JS_GLOBAL_PROXY_TYPE:
   13188     case JS_PROXY_TYPE:
   13189     case MAP_TYPE:
   13190     case MUTABLE_HEAP_NUMBER_TYPE:
   13191     case ODDBALL_TYPE:
   13192     case PROPERTY_CELL_TYPE:
   13193     case SHARED_FUNCTION_INFO_TYPE:
   13194     case SYMBOL_TYPE:
   13195     case ALLOCATION_SITE_TYPE:
   13196 
   13197 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
   13198   case FIXED_##TYPE##_ARRAY_TYPE:
   13199 #undef TYPED_ARRAY_CASE
   13200 
   13201 #define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE:
   13202       STRUCT_LIST(MAKE_STRUCT_CASE)
   13203 #undef MAKE_STRUCT_CASE
   13204       // We must not end up here for these instance types at all.
   13205       UNREACHABLE();
   13206     // Fall through.
   13207     default:
   13208       return false;
   13209   }
   13210 }
   13211 
   13212 }  // namespace
   13213 #endif
   13214 
   13215 
   13216 void JSFunction::EnsureHasInitialMap(Handle<JSFunction> function) {
   13217   DCHECK(function->has_prototype_slot());
   13218   DCHECK(function->IsConstructor() ||
   13219          IsResumableFunction(function->shared()->kind()));
   13220   if (function->has_initial_map()) return;
   13221   Isolate* isolate = function->GetIsolate();
   13222 
   13223   // First create a new map with the size and number of in-object properties
   13224   // suggested by the function.
   13225   InstanceType instance_type;
   13226   if (IsResumableFunction(function->shared()->kind())) {
   13227     instance_type = IsAsyncGeneratorFunction(function->shared()->kind())
   13228                         ? JS_ASYNC_GENERATOR_OBJECT_TYPE
   13229                         : JS_GENERATOR_OBJECT_TYPE;
   13230   } else {
   13231     instance_type = JS_OBJECT_TYPE;
   13232   }
   13233 
   13234   // The constructor should be compiled for the optimization hints to be
   13235   // available.
   13236   int expected_nof_properties = 0;
   13237   if (function->shared()->is_compiled() ||
   13238       Compiler::Compile(function, Compiler::CLEAR_EXCEPTION)) {
   13239     DCHECK(function->shared()->is_compiled());
   13240     expected_nof_properties = function->shared()->expected_nof_properties();
   13241   }
   13242 
   13243   int instance_size;
   13244   int inobject_properties;
   13245   CalculateInstanceSizeHelper(instance_type, false, 0, expected_nof_properties,
   13246                               &instance_size, &inobject_properties);
   13247 
   13248   Handle<Map> map = isolate->factory()->NewMap(instance_type, instance_size,
   13249                                                TERMINAL_FAST_ELEMENTS_KIND,
   13250                                                inobject_properties);
   13251 
   13252   // Fetch or allocate prototype.
   13253   Handle<Object> prototype;
   13254   if (function->has_instance_prototype()) {
   13255     prototype = handle(function->instance_prototype(), isolate);
   13256   } else {
   13257     prototype = isolate->factory()->NewFunctionPrototype(function);
   13258   }
   13259   DCHECK(map->has_fast_object_elements());
   13260 
   13261   // Finally link initial map and constructor function.
   13262   DCHECK(prototype->IsJSReceiver());
   13263   JSFunction::SetInitialMap(function, map, prototype);
   13264   map->StartInobjectSlackTracking();
   13265 }
   13266 
   13267 namespace {
   13268 bool FastInitializeDerivedMap(Isolate* isolate, Handle<JSFunction> new_target,
   13269                               Handle<JSFunction> constructor,
   13270                               Handle<Map> constructor_initial_map) {
   13271   // Check that |function|'s initial map still in sync with the |constructor|,
   13272   // otherwise we must create a new initial map for |function|.
   13273   if (new_target->has_initial_map() &&
   13274       new_target->initial_map()->GetConstructor() == *constructor) {
   13275     DCHECK(new_target->instance_prototype()->IsJSReceiver());
   13276     return true;
   13277   }
   13278   InstanceType instance_type = constructor_initial_map->instance_type();
   13279   DCHECK(CanSubclassHaveInobjectProperties(instance_type));
   13280   // Create a new map with the size and number of in-object properties
   13281   // suggested by |function|.
   13282 
   13283   // Link initial map and constructor function if the new.target is actually a
   13284   // subclass constructor.
   13285   if (!IsDerivedConstructor(new_target->shared()->kind())) return false;
   13286 
   13287   int instance_size;
   13288   int in_object_properties;
   13289   int embedder_fields =
   13290       JSObject::GetEmbedderFieldCount(*constructor_initial_map);
   13291   bool success = JSFunction::CalculateInstanceSizeForDerivedClass(
   13292       new_target, instance_type, embedder_fields, &instance_size,
   13293       &in_object_properties);
   13294 
   13295   Handle<Map> map;
   13296   if (success) {
   13297     int pre_allocated = constructor_initial_map->GetInObjectProperties() -
   13298                         constructor_initial_map->UnusedPropertyFields();
   13299     CHECK_LE(constructor_initial_map->UsedInstanceSize(), instance_size);
   13300     int unused_property_fields = in_object_properties - pre_allocated;
   13301     map = Map::CopyInitialMap(isolate, constructor_initial_map, instance_size,
   13302                               in_object_properties, unused_property_fields);
   13303   } else {
   13304     map = Map::CopyInitialMap(isolate, constructor_initial_map);
   13305   }
   13306   map->set_new_target_is_base(false);
   13307   Handle<Object> prototype(new_target->instance_prototype(), isolate);
   13308   JSFunction::SetInitialMap(new_target, map, prototype);
   13309   DCHECK(new_target->instance_prototype()->IsJSReceiver());
   13310   map->SetConstructor(*constructor);
   13311   map->set_construction_counter(Map::kNoSlackTracking);
   13312   map->StartInobjectSlackTracking();
   13313   return true;
   13314 }
   13315 
   13316 }  // namespace
   13317 
   13318 // static
   13319 MaybeHandle<Map> JSFunction::GetDerivedMap(Isolate* isolate,
   13320                                            Handle<JSFunction> constructor,
   13321                                            Handle<JSReceiver> new_target) {
   13322   EnsureHasInitialMap(constructor);
   13323 
   13324   Handle<Map> constructor_initial_map(constructor->initial_map(), isolate);
   13325   if (*new_target == *constructor) return constructor_initial_map;
   13326 
   13327   Handle<Map> result_map;
   13328   // Fast case, new.target is a subclass of constructor. The map is cacheable
   13329   // (and may already have been cached). new.target.prototype is guaranteed to
   13330   // be a JSReceiver.
   13331   if (new_target->IsJSFunction()) {
   13332     Handle<JSFunction> function = Handle<JSFunction>::cast(new_target);
   13333     if (FastInitializeDerivedMap(isolate, function, constructor,
   13334                                  constructor_initial_map)) {
   13335       return handle(function->initial_map(), isolate);
   13336     }
   13337   }
   13338 
   13339   // Slow path, new.target is either a proxy or can't cache the map.
   13340   // new.target.prototype is not guaranteed to be a JSReceiver, and may need to
   13341   // fall back to the intrinsicDefaultProto.
   13342   Handle<Object> prototype;
   13343   if (new_target->IsJSFunction()) {
   13344     Handle<JSFunction> function = Handle<JSFunction>::cast(new_target);
   13345     // Make sure the new.target.prototype is cached.
   13346     EnsureHasInitialMap(function);
   13347     prototype = handle(function->prototype(), isolate);
   13348   } else {
   13349     Handle<String> prototype_string = isolate->factory()->prototype_string();
   13350     ASSIGN_RETURN_ON_EXCEPTION(
   13351         isolate, prototype,
   13352         JSReceiver::GetProperty(isolate, new_target, prototype_string), Map);
   13353     // The above prototype lookup might change the constructor and its
   13354     // prototype, hence we have to reload the initial map.
   13355     EnsureHasInitialMap(constructor);
   13356     constructor_initial_map = handle(constructor->initial_map(), isolate);
   13357   }
   13358 
   13359   // If prototype is not a JSReceiver, fetch the intrinsicDefaultProto from the
   13360   // correct realm. Rather than directly fetching the .prototype, we fetch the
   13361   // constructor that points to the .prototype. This relies on
   13362   // constructor.prototype being FROZEN for those constructors.
   13363   if (!prototype->IsJSReceiver()) {
   13364     Handle<Context> context;
   13365     ASSIGN_RETURN_ON_EXCEPTION(isolate, context,
   13366                                JSReceiver::GetFunctionRealm(new_target), Map);
   13367     DCHECK(context->IsNativeContext());
   13368     Handle<Object> maybe_index = JSReceiver::GetDataProperty(
   13369         constructor, isolate->factory()->native_context_index_symbol());
   13370     int index = maybe_index->IsSmi() ? Smi::ToInt(*maybe_index)
   13371                                      : Context::OBJECT_FUNCTION_INDEX;
   13372     Handle<JSFunction> realm_constructor(JSFunction::cast(context->get(index)),
   13373                                          isolate);
   13374     prototype = handle(realm_constructor->prototype(), isolate);
   13375   }
   13376 
   13377   Handle<Map> map = Map::CopyInitialMap(isolate, constructor_initial_map);
   13378   map->set_new_target_is_base(false);
   13379   CHECK(prototype->IsJSReceiver());
   13380   if (map->prototype() != *prototype)
   13381     Map::SetPrototype(isolate, map, prototype);
   13382   map->SetConstructor(*constructor);
   13383   return map;
   13384 }
   13385 
   13386 int JSFunction::ComputeInstanceSizeWithMinSlack(Isolate* isolate) {
   13387   if (has_prototype_slot() && has_initial_map() &&
   13388       initial_map()->IsInobjectSlackTrackingInProgress()) {
   13389     int slack = initial_map()->ComputeMinObjectSlack(isolate);
   13390     return initial_map()->InstanceSizeFromSlack(slack);
   13391   }
   13392   return initial_map()->instance_size();
   13393 }
   13394 
   13395 void JSFunction::PrintName(FILE* out) {
   13396   std::unique_ptr<char[]> name = shared()->DebugName()->ToCString();
   13397   PrintF(out, "%s", name.get());
   13398 }
   13399 
   13400 
   13401 Handle<String> JSFunction::GetName(Handle<JSFunction> function) {
   13402   Isolate* isolate = function->GetIsolate();
   13403   Handle<Object> name =
   13404       JSReceiver::GetDataProperty(function, isolate->factory()->name_string());
   13405   if (name->IsString()) return Handle<String>::cast(name);
   13406   return handle(function->shared()->DebugName(), isolate);
   13407 }
   13408 
   13409 
   13410 Handle<String> JSFunction::GetDebugName(Handle<JSFunction> function) {
   13411   Isolate* isolate = function->GetIsolate();
   13412   Handle<Object> name = JSReceiver::GetDataProperty(
   13413       function, isolate->factory()->display_name_string());
   13414   if (name->IsString()) return Handle<String>::cast(name);
   13415   return JSFunction::GetName(function);
   13416 }
   13417 
   13418 bool JSFunction::SetName(Handle<JSFunction> function, Handle<Name> name,
   13419                          Handle<String> prefix) {
   13420   Isolate* isolate = function->GetIsolate();
   13421   Handle<String> function_name;
   13422   ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, function_name,
   13423                                    Name::ToFunctionName(isolate, name), false);
   13424   if (prefix->length() > 0) {
   13425     IncrementalStringBuilder builder(isolate);
   13426     builder.AppendString(prefix);
   13427     builder.AppendCharacter(' ');
   13428     builder.AppendString(function_name);
   13429     ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, function_name, builder.Finish(),
   13430                                      false);
   13431   }
   13432   RETURN_ON_EXCEPTION_VALUE(
   13433       isolate,
   13434       JSObject::DefinePropertyOrElementIgnoreAttributes(
   13435           function, isolate->factory()->name_string(), function_name,
   13436           static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY)),
   13437       false);
   13438   return true;
   13439 }
   13440 
   13441 namespace {
   13442 
   13443 Handle<String> NativeCodeFunctionSourceString(
   13444     Handle<SharedFunctionInfo> shared_info) {
   13445   Isolate* const isolate = shared_info->GetIsolate();
   13446   IncrementalStringBuilder builder(isolate);
   13447   builder.AppendCString("function ");
   13448   builder.AppendString(handle(shared_info->Name(), isolate));
   13449   builder.AppendCString("() { [native code] }");
   13450   return builder.Finish().ToHandleChecked();
   13451 }
   13452 
   13453 }  // namespace
   13454 
   13455 
   13456 // static
   13457 Handle<String> JSBoundFunction::ToString(Handle<JSBoundFunction> function) {
   13458   Isolate* const isolate = function->GetIsolate();
   13459   return isolate->factory()->function_native_code_string();
   13460 }
   13461 
   13462 
   13463 // static
   13464 Handle<String> JSFunction::ToString(Handle<JSFunction> function) {
   13465   Isolate* const isolate = function->GetIsolate();
   13466   Handle<SharedFunctionInfo> shared_info(function->shared(), isolate);
   13467 
   13468   // Check if {function} should hide its source code.
   13469   if (!shared_info->IsUserJavaScript()) {
   13470     return NativeCodeFunctionSourceString(shared_info);
   13471   }
   13472 
   13473   // Check if we should print {function} as a class.
   13474   Handle<Object> maybe_class_positions = JSReceiver::GetDataProperty(
   13475       function, isolate->factory()->class_positions_symbol());
   13476   if (maybe_class_positions->IsTuple2()) {
   13477     Tuple2* class_positions = Tuple2::cast(*maybe_class_positions);
   13478     int start_position = Smi::ToInt(class_positions->value1());
   13479     int end_position = Smi::ToInt(class_positions->value2());
   13480     Handle<String> script_source(
   13481         String::cast(Script::cast(shared_info->script())->source()), isolate);
   13482     return isolate->factory()->NewSubString(script_source, start_position,
   13483                                             end_position);
   13484   }
   13485 
   13486   // Check if we have source code for the {function}.
   13487   if (!shared_info->HasSourceCode()) {
   13488     return NativeCodeFunctionSourceString(shared_info);
   13489   }
   13490 
   13491   if (FLAG_harmony_function_tostring) {
   13492     if (shared_info->function_token_position() == kNoSourcePosition) {
   13493       // If the function token position isn't valid, return [native code] to
   13494       // ensure calling eval on the returned source code throws rather than
   13495       // giving inconsistent call behaviour.
   13496       isolate->CountUsage(v8::Isolate::UseCounterFeature::
   13497                               kFunctionTokenOffsetTooLongForToString);
   13498       return NativeCodeFunctionSourceString(shared_info);
   13499     }
   13500     return Handle<String>::cast(
   13501         SharedFunctionInfo::GetSourceCodeHarmony(shared_info));
   13502   }
   13503 
   13504   IncrementalStringBuilder builder(isolate);
   13505   FunctionKind kind = shared_info->kind();
   13506   if (!IsArrowFunction(kind)) {
   13507     if (IsConciseMethod(kind)) {
   13508       if (IsAsyncGeneratorFunction(kind)) {
   13509         builder.AppendCString("async *");
   13510       } else if (IsGeneratorFunction(kind)) {
   13511         builder.AppendCharacter('*');
   13512       } else if (IsAsyncFunction(kind)) {
   13513         builder.AppendCString("async ");
   13514       }
   13515     } else {
   13516       if (IsAsyncGeneratorFunction(kind)) {
   13517         builder.AppendCString("async function* ");
   13518       } else if (IsGeneratorFunction(kind)) {
   13519         builder.AppendCString("function* ");
   13520       } else if (IsAsyncFunction(kind)) {
   13521         builder.AppendCString("async function ");
   13522       } else {
   13523         builder.AppendCString("function ");
   13524       }
   13525     }
   13526     if (shared_info->name_should_print_as_anonymous()) {
   13527       builder.AppendCString("anonymous");
   13528     } else if (!shared_info->is_anonymous_expression()) {
   13529       builder.AppendString(handle(shared_info->Name(), isolate));
   13530     }
   13531   }
   13532   if (shared_info->is_wrapped()) {
   13533     builder.AppendCharacter('(');
   13534     Handle<FixedArray> args(
   13535         Script::cast(shared_info->script())->wrapped_arguments(), isolate);
   13536     int argc = args->length();
   13537     for (int i = 0; i < argc; i++) {
   13538       if (i > 0) builder.AppendCString(", ");
   13539       builder.AppendString(Handle<String>(String::cast(args->get(i)), isolate));
   13540     }
   13541     builder.AppendCString(") {\n");
   13542   }
   13543   builder.AppendString(
   13544       Handle<String>::cast(SharedFunctionInfo::GetSourceCode(shared_info)));
   13545   if (shared_info->is_wrapped()) {
   13546     builder.AppendCString("\n}");
   13547   }
   13548   return builder.Finish().ToHandleChecked();
   13549 }
   13550 
   13551 void Oddball::Initialize(Isolate* isolate, Handle<Oddball> oddball,
   13552                          const char* to_string, Handle<Object> to_number,
   13553                          const char* type_of, byte kind) {
   13554   Handle<String> internalized_to_string =
   13555       isolate->factory()->InternalizeUtf8String(to_string);
   13556   Handle<String> internalized_type_of =
   13557       isolate->factory()->InternalizeUtf8String(type_of);
   13558   if (to_number->IsHeapNumber()) {
   13559     oddball->set_to_number_raw_as_bits(
   13560         Handle<HeapNumber>::cast(to_number)->value_as_bits());
   13561   } else {
   13562     oddball->set_to_number_raw(to_number->Number());
   13563   }
   13564   oddball->set_to_number(*to_number);
   13565   oddball->set_to_string(*internalized_to_string);
   13566   oddball->set_type_of(*internalized_type_of);
   13567   oddball->set_kind(kind);
   13568 }
   13569 
   13570 int Script::GetEvalPosition() {
   13571   DisallowHeapAllocation no_gc;
   13572   DCHECK(compilation_type() == Script::COMPILATION_TYPE_EVAL);
   13573   int position = eval_from_position();
   13574   if (position < 0) {
   13575     // Due to laziness, the position may not have been translated from code
   13576     // offset yet, which would be encoded as negative integer. In that case,
   13577     // translate and set the position.
   13578     if (!has_eval_from_shared()) {
   13579       position = 0;
   13580     } else {
   13581       SharedFunctionInfo* shared = eval_from_shared();
   13582       position = shared->abstract_code()->SourcePosition(-position);
   13583     }
   13584     DCHECK_GE(position, 0);
   13585     set_eval_from_position(position);
   13586   }
   13587   return position;
   13588 }
   13589 
   13590 void Script::InitLineEnds(Handle<Script> script) {
   13591   Isolate* isolate = script->GetIsolate();
   13592   if (!script->line_ends()->IsUndefined(isolate)) return;
   13593   DCHECK_NE(Script::TYPE_WASM, script->type());
   13594 
   13595   Object* src_obj = script->source();
   13596   if (!src_obj->IsString()) {
   13597     DCHECK(src_obj->IsUndefined(isolate));
   13598     script->set_line_ends(ReadOnlyRoots(isolate).empty_fixed_array());
   13599   } else {
   13600     DCHECK(src_obj->IsString());
   13601     Handle<String> src(String::cast(src_obj), isolate);
   13602     Handle<FixedArray> array = String::CalculateLineEnds(isolate, src, true);
   13603     script->set_line_ends(*array);
   13604   }
   13605 
   13606   DCHECK(script->line_ends()->IsFixedArray());
   13607 }
   13608 
   13609 bool Script::GetPositionInfo(Handle<Script> script, int position,
   13610                              PositionInfo* info, OffsetFlag offset_flag) {
   13611   // For wasm, we do not create an artificial line_ends array, but do the
   13612   // translation directly.
   13613   if (script->type() != Script::TYPE_WASM) InitLineEnds(script);
   13614   return script->GetPositionInfo(position, info, offset_flag);
   13615 }
   13616 
   13617 bool Script::IsUserJavaScript() { return type() == Script::TYPE_NORMAL; }
   13618 
   13619 bool Script::ContainsAsmModule() {
   13620   DisallowHeapAllocation no_gc;
   13621   SharedFunctionInfo::ScriptIterator iter(this->GetIsolate(), this);
   13622   while (SharedFunctionInfo* info = iter.Next()) {
   13623     if (info->HasAsmWasmData()) return true;
   13624   }
   13625   return false;
   13626 }
   13627 
   13628 namespace {
   13629 bool GetPositionInfoSlow(const Script* script, int position,
   13630                          Script::PositionInfo* info) {
   13631   if (!script->source()->IsString()) return false;
   13632   if (position < 0) position = 0;
   13633 
   13634   String* source_string = String::cast(script->source());
   13635   int line = 0;
   13636   int line_start = 0;
   13637   int len = source_string->length();
   13638   for (int pos = 0; pos <= len; ++pos) {
   13639     if (pos == len || source_string->Get(pos) == '\n') {
   13640       if (position <= pos) {
   13641         info->line = line;
   13642         info->column = position - line_start;
   13643         info->line_start = line_start;
   13644         info->line_end = pos;
   13645         return true;
   13646       }
   13647       line++;
   13648       line_start = pos + 1;
   13649     }
   13650   }
   13651   return false;
   13652 }
   13653 }  // namespace
   13654 
   13655 #define SMI_VALUE(x) (Smi::ToInt(x))
   13656 bool Script::GetPositionInfo(int position, PositionInfo* info,
   13657                              OffsetFlag offset_flag) const {
   13658   DisallowHeapAllocation no_allocation;
   13659 
   13660   // For wasm, we do not rely on the line_ends array, but do the translation
   13661   // directly.
   13662   if (type() == Script::TYPE_WASM) {
   13663     DCHECK_LE(0, position);
   13664     return WasmModuleObject::cast(wasm_module_object())
   13665         ->GetPositionInfo(static_cast<uint32_t>(position), info);
   13666   }
   13667 
   13668   if (line_ends()->IsUndefined()) {
   13669     // Slow mode: we do not have line_ends. We have to iterate through source.
   13670     if (!GetPositionInfoSlow(this, position, info)) return false;
   13671   } else {
   13672     DCHECK(line_ends()->IsFixedArray());
   13673     FixedArray* ends = FixedArray::cast(line_ends());
   13674 
   13675     const int ends_len = ends->length();
   13676     if (ends_len == 0) return false;
   13677 
   13678     // Return early on invalid positions. Negative positions behave as if 0 was
   13679     // passed, and positions beyond the end of the script return as failure.
   13680     if (position < 0) {
   13681       position = 0;
   13682     } else if (position > SMI_VALUE(ends->get(ends_len - 1))) {
   13683       return false;
   13684     }
   13685 
   13686     // Determine line number by doing a binary search on the line ends array.
   13687     if (SMI_VALUE(ends->get(0)) >= position) {
   13688       info->line = 0;
   13689       info->line_start = 0;
   13690       info->column = position;
   13691     } else {
   13692       int left = 0;
   13693       int right = ends_len - 1;
   13694 
   13695       while (right > 0) {
   13696         DCHECK_LE(left, right);
   13697         const int mid = (left + right) / 2;
   13698         if (position > SMI_VALUE(ends->get(mid))) {
   13699           left = mid + 1;
   13700         } else if (position <= SMI_VALUE(ends->get(mid - 1))) {
   13701           right = mid - 1;
   13702         } else {
   13703           info->line = mid;
   13704           break;
   13705         }
   13706       }
   13707       DCHECK(SMI_VALUE(ends->get(info->line)) >= position &&
   13708              SMI_VALUE(ends->get(info->line - 1)) < position);
   13709       info->line_start = SMI_VALUE(ends->get(info->line - 1)) + 1;
   13710       info->column = position - info->line_start;
   13711     }
   13712 
   13713     // Line end is position of the linebreak character.
   13714     info->line_end = SMI_VALUE(ends->get(info->line));
   13715     if (info->line_end > 0) {
   13716       DCHECK(source()->IsString());
   13717       String* src = String::cast(source());
   13718       if (src->length() >= info->line_end &&
   13719           src->Get(info->line_end - 1) == '\r') {
   13720         info->line_end--;
   13721       }
   13722     }
   13723   }
   13724 
   13725   // Add offsets if requested.
   13726   if (offset_flag == WITH_OFFSET) {
   13727     if (info->line == 0) {
   13728       info->column += column_offset();
   13729     }
   13730     info->line += line_offset();
   13731   }
   13732 
   13733   return true;
   13734 }
   13735 #undef SMI_VALUE
   13736 
   13737 int Script::GetColumnNumber(Handle<Script> script, int code_pos) {
   13738   PositionInfo info;
   13739   GetPositionInfo(script, code_pos, &info, WITH_OFFSET);
   13740   return info.column;
   13741 }
   13742 
   13743 int Script::GetColumnNumber(int code_pos) const {
   13744   PositionInfo info;
   13745   GetPositionInfo(code_pos, &info, WITH_OFFSET);
   13746   return info.column;
   13747 }
   13748 
   13749 int Script::GetLineNumber(Handle<Script> script, int code_pos) {
   13750   PositionInfo info;
   13751   GetPositionInfo(script, code_pos, &info, WITH_OFFSET);
   13752   return info.line;
   13753 }
   13754 
   13755 int Script::GetLineNumber(int code_pos) const {
   13756   PositionInfo info;
   13757   GetPositionInfo(code_pos, &info, WITH_OFFSET);
   13758   return info.line;
   13759 }
   13760 
   13761 Object* Script::GetNameOrSourceURL() {
   13762   // Keep in sync with ScriptNameOrSourceURL in messages.js.
   13763   if (!source_url()->IsUndefined()) return source_url();
   13764   return name();
   13765 }
   13766 
   13767 MaybeHandle<SharedFunctionInfo> Script::FindSharedFunctionInfo(
   13768     Isolate* isolate, const FunctionLiteral* fun) {
   13769   CHECK_NE(fun->function_literal_id(), FunctionLiteral::kIdTypeInvalid);
   13770   // If this check fails, the problem is most probably the function id
   13771   // renumbering done by AstFunctionLiteralIdReindexer; in particular, that
   13772   // AstTraversalVisitor doesn't recurse properly in the construct which
   13773   // triggers the mismatch.
   13774   CHECK_LT(fun->function_literal_id(), shared_function_infos()->length());
   13775   MaybeObject* shared =
   13776       shared_function_infos()->Get(fun->function_literal_id());
   13777   HeapObject* heap_object;
   13778   if (!shared->ToStrongOrWeakHeapObject(&heap_object) ||
   13779       heap_object->IsUndefined(isolate)) {
   13780     return MaybeHandle<SharedFunctionInfo>();
   13781   }
   13782   return handle(SharedFunctionInfo::cast(heap_object), isolate);
   13783 }
   13784 
   13785 Script::Iterator::Iterator(Isolate* isolate)
   13786     : iterator_(isolate->heap()->script_list()) {}
   13787 
   13788 Script* Script::Iterator::Next() {
   13789   Object* o = iterator_.Next();
   13790   if (o != nullptr) {
   13791     return Script::cast(o);
   13792   }
   13793   return nullptr;
   13794 }
   13795 
   13796 Code* SharedFunctionInfo::GetCode() const {
   13797   // ======
   13798   // NOTE: This chain of checks MUST be kept in sync with the equivalent CSA
   13799   // GetSharedFunctionInfoCode method in code-stub-assembler.cc.
   13800   // ======
   13801 
   13802   Isolate* isolate = GetIsolate();
   13803   Object* data = function_data();
   13804   if (data->IsSmi()) {
   13805     // Holding a Smi means we are a builtin.
   13806     DCHECK(HasBuiltinId());
   13807     return isolate->builtins()->builtin(builtin_id());
   13808   } else if (data->IsBytecodeArray()) {
   13809     // Having a bytecode array means we are a compiled, interpreted function.
   13810     DCHECK(HasBytecodeArray());
   13811     return isolate->builtins()->builtin(Builtins::kInterpreterEntryTrampoline);
   13812   } else if (data->IsFixedArray()) {
   13813     // Having a fixed array means we are an asm.js/wasm function.
   13814     DCHECK(HasAsmWasmData());
   13815     return isolate->builtins()->builtin(Builtins::kInstantiateAsmJs);
   13816   } else if (data->IsUncompiledData()) {
   13817     // Having uncompiled data (with or without scope) means we need to compile.
   13818     DCHECK(HasUncompiledData());
   13819     return isolate->builtins()->builtin(Builtins::kCompileLazy);
   13820   } else if (data->IsFunctionTemplateInfo()) {
   13821     // Having a function template info means we are an API function.
   13822     DCHECK(IsApiFunction());
   13823     return isolate->builtins()->builtin(Builtins::kHandleApiCall);
   13824   } else if (data->IsWasmExportedFunctionData()) {
   13825     // Having a WasmExportedFunctionData means the code is in there.
   13826     DCHECK(HasWasmExportedFunctionData());
   13827     return wasm_exported_function_data()->wrapper_code();
   13828   } else if (data->IsInterpreterData()) {
   13829     Code* code = InterpreterTrampoline();
   13830     DCHECK(code->IsCode());
   13831     DCHECK(code->is_interpreter_trampoline_builtin());
   13832     return code;
   13833   }
   13834   UNREACHABLE();
   13835 }
   13836 
   13837 WasmExportedFunctionData* SharedFunctionInfo::wasm_exported_function_data()
   13838     const {
   13839   DCHECK(HasWasmExportedFunctionData());
   13840   return WasmExportedFunctionData::cast(function_data());
   13841 }
   13842 
   13843 SharedFunctionInfo::ScriptIterator::ScriptIterator(Isolate* isolate,
   13844                                                    Script* script)
   13845     : ScriptIterator(isolate,
   13846                      handle(script->shared_function_infos(), isolate)) {}
   13847 
   13848 SharedFunctionInfo::ScriptIterator::ScriptIterator(
   13849     Isolate* isolate, Handle<WeakFixedArray> shared_function_infos)
   13850     : isolate_(isolate),
   13851       shared_function_infos_(shared_function_infos),
   13852       index_(0) {}
   13853 
   13854 SharedFunctionInfo* SharedFunctionInfo::ScriptIterator::Next() {
   13855   while (index_ < shared_function_infos_->length()) {
   13856     MaybeObject* raw = shared_function_infos_->Get(index_++);
   13857     HeapObject* heap_object;
   13858     if (!raw->ToStrongOrWeakHeapObject(&heap_object) ||
   13859         heap_object->IsUndefined(isolate_)) {
   13860       continue;
   13861     }
   13862     return SharedFunctionInfo::cast(heap_object);
   13863   }
   13864   return nullptr;
   13865 }
   13866 
   13867 void SharedFunctionInfo::ScriptIterator::Reset(Script* script) {
   13868   shared_function_infos_ = handle(script->shared_function_infos(), isolate_);
   13869   index_ = 0;
   13870 }
   13871 
   13872 SharedFunctionInfo::GlobalIterator::GlobalIterator(Isolate* isolate)
   13873     : script_iterator_(isolate),
   13874       noscript_sfi_iterator_(isolate->heap()->noscript_shared_function_infos()),
   13875       sfi_iterator_(isolate, script_iterator_.Next()) {}
   13876 
   13877 SharedFunctionInfo* SharedFunctionInfo::GlobalIterator::Next() {
   13878   HeapObject* next = noscript_sfi_iterator_.Next();
   13879   if (next != nullptr) return SharedFunctionInfo::cast(next);
   13880   for (;;) {
   13881     next = sfi_iterator_.Next();
   13882     if (next != nullptr) return SharedFunctionInfo::cast(next);
   13883     Script* next_script = script_iterator_.Next();
   13884     if (next_script == nullptr) return nullptr;
   13885     sfi_iterator_.Reset(next_script);
   13886   }
   13887 }
   13888 
   13889 void SharedFunctionInfo::SetScript(Handle<SharedFunctionInfo> shared,
   13890                                    Handle<Object> script_object,
   13891                                    int function_literal_id,
   13892                                    bool reset_preparsed_scope_data) {
   13893   if (shared->script() == *script_object) return;
   13894   Isolate* isolate = shared->GetIsolate();
   13895 
   13896   if (reset_preparsed_scope_data &&
   13897       shared->HasUncompiledDataWithPreParsedScope()) {
   13898     shared->ClearPreParsedScopeData();
   13899   }
   13900 
   13901   // Add shared function info to new script's list. If a collection occurs,
   13902   // the shared function info may be temporarily in two lists.
   13903   // This is okay because the gc-time processing of these lists can tolerate
   13904   // duplicates.
   13905   if (script_object->IsScript()) {
   13906     DCHECK(!shared->script()->IsScript());
   13907     Handle<Script> script = Handle<Script>::cast(script_object);
   13908     Handle<WeakFixedArray> list =
   13909         handle(script->shared_function_infos(), isolate);
   13910 #ifdef DEBUG
   13911     DCHECK_LT(function_literal_id, list->length());
   13912     MaybeObject* maybe_object = list->Get(function_literal_id);
   13913     HeapObject* heap_object;
   13914     if (maybe_object->ToWeakHeapObject(&heap_object)) {
   13915       DCHECK_EQ(heap_object, *shared);
   13916     }
   13917 #endif
   13918     list->Set(function_literal_id, HeapObjectReference::Weak(*shared));
   13919 
   13920     // Remove shared function info from root array.
   13921     WeakArrayList* noscript_list =
   13922         isolate->heap()->noscript_shared_function_infos();
   13923     CHECK(noscript_list->RemoveOne(MaybeObjectHandle::Weak(shared)));
   13924   } else {
   13925     DCHECK(shared->script()->IsScript());
   13926     Handle<WeakArrayList> list =
   13927         isolate->factory()->noscript_shared_function_infos();
   13928 
   13929 #ifdef DEBUG
   13930     if (FLAG_enable_slow_asserts) {
   13931       WeakArrayList::Iterator iterator(*list);
   13932       HeapObject* next;
   13933       while ((next = iterator.Next()) != nullptr) {
   13934         DCHECK_NE(next, *shared);
   13935       }
   13936     }
   13937 #endif  // DEBUG
   13938 
   13939     list =
   13940         WeakArrayList::AddToEnd(isolate, list, MaybeObjectHandle::Weak(shared));
   13941 
   13942     isolate->heap()->SetRootNoScriptSharedFunctionInfos(*list);
   13943 
   13944     // Remove shared function info from old script's list.
   13945     Script* old_script = Script::cast(shared->script());
   13946 
   13947     // Due to liveedit, it might happen that the old_script doesn't know
   13948     // about the SharedFunctionInfo, so we have to guard against that.
   13949     Handle<WeakFixedArray> infos(old_script->shared_function_infos(), isolate);
   13950     if (function_literal_id < infos->length()) {
   13951       MaybeObject* raw =
   13952           old_script->shared_function_infos()->Get(function_literal_id);
   13953       HeapObject* heap_object;
   13954       if (raw->ToWeakHeapObject(&heap_object) && heap_object == *shared) {
   13955         old_script->shared_function_infos()->Set(
   13956             function_literal_id, HeapObjectReference::Strong(
   13957                                      ReadOnlyRoots(isolate).undefined_value()));
   13958       }
   13959     }
   13960   }
   13961 
   13962   // Finally set new script.
   13963   shared->set_script(*script_object);
   13964 }
   13965 
   13966 bool SharedFunctionInfo::HasBreakInfo() const {
   13967   if (!HasDebugInfo()) return false;
   13968   DebugInfo* info = DebugInfo::cast(GetDebugInfo());
   13969   bool has_break_info = info->HasBreakInfo();
   13970   return has_break_info;
   13971 }
   13972 
   13973 bool SharedFunctionInfo::BreakAtEntry() const {
   13974   if (!HasDebugInfo()) return false;
   13975   DebugInfo* info = DebugInfo::cast(GetDebugInfo());
   13976   bool break_at_entry = info->BreakAtEntry();
   13977   return break_at_entry;
   13978 }
   13979 
   13980 bool SharedFunctionInfo::HasCoverageInfo() const {
   13981   if (!HasDebugInfo()) return false;
   13982   DebugInfo* info = DebugInfo::cast(GetDebugInfo());
   13983   bool has_coverage_info = info->HasCoverageInfo();
   13984   return has_coverage_info;
   13985 }
   13986 
   13987 CoverageInfo* SharedFunctionInfo::GetCoverageInfo() const {
   13988   DCHECK(HasCoverageInfo());
   13989   return CoverageInfo::cast(GetDebugInfo()->coverage_info());
   13990 }
   13991 
   13992 String* SharedFunctionInfo::DebugName() {
   13993   DisallowHeapAllocation no_gc;
   13994   String* function_name = Name();
   13995   if (function_name->length() > 0) return function_name;
   13996   return inferred_name();
   13997 }
   13998 
   13999 bool SharedFunctionInfo::PassesFilter(const char* raw_filter) {
   14000   Vector<const char> filter = CStrVector(raw_filter);
   14001   std::unique_ptr<char[]> cstrname(DebugName()->ToCString());
   14002   return v8::internal::PassesFilter(CStrVector(cstrname.get()), filter);
   14003 }
   14004 
   14005 bool SharedFunctionInfo::HasSourceCode() const {
   14006   Isolate* isolate = GetIsolate();
   14007   return !script()->IsUndefined(isolate) &&
   14008          !reinterpret_cast<Script*>(script())->source()->IsUndefined(isolate);
   14009 }
   14010 
   14011 // static
   14012 Handle<Object> SharedFunctionInfo::GetSourceCode(
   14013     Handle<SharedFunctionInfo> shared) {
   14014   Isolate* isolate = shared->GetIsolate();
   14015   if (!shared->HasSourceCode()) return isolate->factory()->undefined_value();
   14016   Handle<String> source(String::cast(Script::cast(shared->script())->source()),
   14017                         isolate);
   14018   return isolate->factory()->NewSubString(source, shared->StartPosition(),
   14019                                           shared->EndPosition());
   14020 }
   14021 
   14022 // static
   14023 Handle<Object> SharedFunctionInfo::GetSourceCodeHarmony(
   14024     Handle<SharedFunctionInfo> shared) {
   14025   Isolate* isolate = shared->GetIsolate();
   14026   if (!shared->HasSourceCode()) return isolate->factory()->undefined_value();
   14027   Handle<String> script_source(
   14028       String::cast(Script::cast(shared->script())->source()), isolate);
   14029   int start_pos = shared->function_token_position();
   14030   DCHECK_NE(start_pos, kNoSourcePosition);
   14031   Handle<String> source = isolate->factory()->NewSubString(
   14032       script_source, start_pos, shared->EndPosition());
   14033   if (!shared->is_wrapped()) return source;
   14034 
   14035   DCHECK(!shared->name_should_print_as_anonymous());
   14036   IncrementalStringBuilder builder(isolate);
   14037   builder.AppendCString("function ");
   14038   builder.AppendString(Handle<String>(shared->Name(), isolate));
   14039   builder.AppendCString("(");
   14040   Handle<FixedArray> args(Script::cast(shared->script())->wrapped_arguments(),
   14041                           isolate);
   14042   int argc = args->length();
   14043   for (int i = 0; i < argc; i++) {
   14044     if (i > 0) builder.AppendCString(", ");
   14045     builder.AppendString(Handle<String>(String::cast(args->get(i)), isolate));
   14046   }
   14047   builder.AppendCString(") {\n");
   14048   builder.AppendString(source);
   14049   builder.AppendCString("\n}");
   14050   return builder.Finish().ToHandleChecked();
   14051 }
   14052 
   14053 bool SharedFunctionInfo::IsInlineable() {
   14054   // Check that the function has a script associated with it.
   14055   if (!script()->IsScript()) return false;
   14056   if (GetIsolate()->is_precise_binary_code_coverage() &&
   14057       !has_reported_binary_coverage()) {
   14058     // We may miss invocations if this function is inlined.
   14059     return false;
   14060   }
   14061   return !optimization_disabled();
   14062 }
   14063 
   14064 int SharedFunctionInfo::SourceSize() { return EndPosition() - StartPosition(); }
   14065 
   14066 int SharedFunctionInfo::FindIndexInScript(Isolate* isolate) const {
   14067   DisallowHeapAllocation no_gc;
   14068 
   14069   Object* script_obj = script();
   14070   if (!script_obj->IsScript()) return FunctionLiteral::kIdTypeInvalid;
   14071 
   14072   WeakFixedArray* shared_info_list =
   14073       Script::cast(script_obj)->shared_function_infos();
   14074   SharedFunctionInfo::ScriptIterator iterator(
   14075       isolate, Handle<WeakFixedArray>(&shared_info_list));
   14076 
   14077   for (SharedFunctionInfo* shared = iterator.Next(); shared != nullptr;
   14078        shared = iterator.Next()) {
   14079     if (shared == this) {
   14080       return iterator.CurrentIndex();
   14081     }
   14082   }
   14083 
   14084   return FunctionLiteral::kIdTypeInvalid;
   14085 }
   14086 
   14087 void JSFunction::CalculateInstanceSizeHelper(InstanceType instance_type,
   14088                                              bool has_prototype_slot,
   14089                                              int requested_embedder_fields,
   14090                                              int requested_in_object_properties,
   14091                                              int* instance_size,
   14092                                              int* in_object_properties) {
   14093   DCHECK_LE(static_cast<unsigned>(requested_embedder_fields),
   14094             JSObject::kMaxEmbedderFields);
   14095   int header_size = JSObject::GetHeaderSize(instance_type, has_prototype_slot);
   14096   int max_nof_fields =
   14097       (JSObject::kMaxInstanceSize - header_size) >> kPointerSizeLog2;
   14098   CHECK_LE(max_nof_fields, JSObject::kMaxInObjectProperties);
   14099   CHECK_LE(static_cast<unsigned>(requested_embedder_fields),
   14100            static_cast<unsigned>(max_nof_fields));
   14101   *in_object_properties = Min(requested_in_object_properties,
   14102                               max_nof_fields - requested_embedder_fields);
   14103   *instance_size =
   14104       header_size +
   14105       ((requested_embedder_fields + *in_object_properties) << kPointerSizeLog2);
   14106   CHECK_EQ(*in_object_properties,
   14107            ((*instance_size - header_size) >> kPointerSizeLog2) -
   14108                requested_embedder_fields);
   14109   CHECK_LE(static_cast<unsigned>(*instance_size),
   14110            static_cast<unsigned>(JSObject::kMaxInstanceSize));
   14111 }
   14112 
   14113 // static
   14114 bool JSFunction::CalculateInstanceSizeForDerivedClass(
   14115     Handle<JSFunction> function, InstanceType instance_type,
   14116     int requested_embedder_fields, int* instance_size,
   14117     int* in_object_properties) {
   14118   Isolate* isolate = function->GetIsolate();
   14119   int expected_nof_properties = 0;
   14120   for (PrototypeIterator iter(isolate, function, kStartAtReceiver);
   14121        !iter.IsAtEnd(); iter.Advance()) {
   14122     Handle<JSReceiver> current =
   14123         PrototypeIterator::GetCurrent<JSReceiver>(iter);
   14124     if (!current->IsJSFunction()) break;
   14125     Handle<JSFunction> func(Handle<JSFunction>::cast(current));
   14126     // The super constructor should be compiled for the number of expected
   14127     // properties to be available.
   14128     Handle<SharedFunctionInfo> shared(func->shared(), isolate);
   14129     if (shared->is_compiled() ||
   14130         Compiler::Compile(func, Compiler::CLEAR_EXCEPTION)) {
   14131       DCHECK(shared->is_compiled());
   14132       int count = shared->expected_nof_properties();
   14133       // Check that the estimate is sane.
   14134       if (expected_nof_properties <= JSObject::kMaxInObjectProperties - count) {
   14135         expected_nof_properties += count;
   14136       } else {
   14137         expected_nof_properties = JSObject::kMaxInObjectProperties;
   14138       }
   14139     } else if (!shared->is_compiled()) {
   14140       // In case there was a compilation error for the constructor we will
   14141       // throw an error during instantiation. Hence we directly return 0;
   14142       return false;
   14143     }
   14144     if (!IsDerivedConstructor(shared->kind())) break;
   14145   }
   14146   CalculateInstanceSizeHelper(instance_type, true, requested_embedder_fields,
   14147                               expected_nof_properties, instance_size,
   14148                               in_object_properties);
   14149   return true;
   14150 }
   14151 
   14152 
   14153 // Output the source code without any allocation in the heap.
   14154 std::ostream& operator<<(std::ostream& os, const SourceCodeOf& v) {
   14155   const SharedFunctionInfo* s = v.value;
   14156   // For some native functions there is no source.
   14157   if (!s->HasSourceCode()) return os << "<No Source>";
   14158 
   14159   // Get the source for the script which this function came from.
   14160   // Don't use String::cast because we don't want more assertion errors while
   14161   // we are already creating a stack dump.
   14162   String* script_source =
   14163       reinterpret_cast<String*>(Script::cast(s->script())->source());
   14164 
   14165   if (!script_source->LooksValid()) return os << "<Invalid Source>";
   14166 
   14167   if (!s->is_toplevel()) {
   14168     os << "function ";
   14169     String* name = s->Name();
   14170     if (name->length() > 0) {
   14171       name->PrintUC16(os);
   14172     }
   14173   }
   14174 
   14175   int len = s->EndPosition() - s->StartPosition();
   14176   if (len <= v.max_length || v.max_length < 0) {
   14177     script_source->PrintUC16(os, s->StartPosition(), s->EndPosition());
   14178     return os;
   14179   } else {
   14180     script_source->PrintUC16(os, s->StartPosition(),
   14181                              s->StartPosition() + v.max_length);
   14182     return os << "...\n";
   14183   }
   14184 }
   14185 
   14186 
   14187 void SharedFunctionInfo::DisableOptimization(BailoutReason reason) {
   14188   DCHECK_NE(reason, BailoutReason::kNoReason);
   14189 
   14190   set_flags(DisabledOptimizationReasonBits::update(flags(), reason));
   14191   // Code should be the lazy compilation stub or else interpreted.
   14192   DCHECK(abstract_code()->kind() == AbstractCode::INTERPRETED_FUNCTION ||
   14193          abstract_code()->kind() == AbstractCode::BUILTIN);
   14194   PROFILE(GetIsolate(), CodeDisableOptEvent(abstract_code(), this));
   14195   if (FLAG_trace_opt) {
   14196     PrintF("[disabled optimization for ");
   14197     ShortPrint();
   14198     PrintF(", reason: %s]\n", GetBailoutReason(reason));
   14199   }
   14200 }
   14201 
   14202 void SharedFunctionInfo::InitFromFunctionLiteral(
   14203     Handle<SharedFunctionInfo> shared_info, FunctionLiteral* lit,
   14204     bool is_toplevel) {
   14205   Isolate* isolate = shared_info->GetIsolate();
   14206   bool needs_position_info = true;
   14207 
   14208   // When adding fields here, make sure DeclarationScope::AnalyzePartially is
   14209   // updated accordingly.
   14210   shared_info->set_internal_formal_parameter_count(lit->parameter_count());
   14211   shared_info->SetFunctionTokenPosition(lit->function_token_position(),
   14212                                         lit->start_position());
   14213   if (shared_info->scope_info()->HasPositionInfo()) {
   14214     shared_info->scope_info()->SetPositionInfo(lit->start_position(),
   14215                                                lit->end_position());
   14216     needs_position_info = false;
   14217   }
   14218   shared_info->set_is_declaration(lit->is_declaration());
   14219   shared_info->set_is_named_expression(lit->is_named_expression());
   14220   shared_info->set_is_anonymous_expression(lit->is_anonymous_expression());
   14221   shared_info->set_allows_lazy_compilation(lit->AllowsLazyCompilation());
   14222   shared_info->set_language_mode(lit->language_mode());
   14223   shared_info->set_is_wrapped(lit->is_wrapped());
   14224   //  shared_info->set_kind(lit->kind());
   14225   // FunctionKind must have already been set.
   14226   DCHECK(lit->kind() == shared_info->kind());
   14227   shared_info->set_needs_home_object(lit->scope()->NeedsHomeObject());
   14228   DCHECK_IMPLIES(lit->requires_instance_fields_initializer(),
   14229                  IsClassConstructor(lit->kind()));
   14230   shared_info->set_requires_instance_fields_initializer(
   14231       lit->requires_instance_fields_initializer());
   14232 
   14233   shared_info->set_is_toplevel(is_toplevel);
   14234   DCHECK(shared_info->outer_scope_info()->IsTheHole());
   14235   if (!is_toplevel) {
   14236     Scope* outer_scope = lit->scope()->GetOuterScopeWithContext();
   14237     if (outer_scope) {
   14238       shared_info->set_outer_scope_info(*outer_scope->scope_info());
   14239     }
   14240   }
   14241 
   14242   // For lazy parsed functions, the following flags will be inaccurate since we
   14243   // don't have the information yet. They're set later in
   14244   // SetSharedFunctionFlagsFromLiteral (compiler.cc), when the function is
   14245   // really parsed and compiled.
   14246   if (lit->body() != nullptr) {
   14247     shared_info->set_length(lit->function_length());
   14248     shared_info->set_has_duplicate_parameters(lit->has_duplicate_parameters());
   14249     shared_info->SetExpectedNofPropertiesFromEstimate(lit);
   14250     DCHECK_NULL(lit->produced_preparsed_scope_data());
   14251     if (lit->ShouldEagerCompile()) {
   14252       // If we're about to eager compile, we'll have the function literal
   14253       // available, so there's no need to wastefully allocate an uncompiled
   14254       // data.
   14255       // TODO(leszeks): This should be explicitly passed as a parameter, rather
   14256       // than relying on a property of the literal.
   14257       needs_position_info = false;
   14258     }
   14259   } else {
   14260     // Set an invalid length for lazy functions. This way we can set the correct
   14261     // value after compiling, but avoid overwriting values set manually by the
   14262     // bootstrapper.
   14263     shared_info->set_length(SharedFunctionInfo::kInvalidLength);
   14264     if (FLAG_preparser_scope_analysis) {
   14265       ProducedPreParsedScopeData* scope_data =
   14266           lit->produced_preparsed_scope_data();
   14267       if (scope_data != nullptr) {
   14268         Handle<PreParsedScopeData> pre_parsed_scope_data;
   14269         if (scope_data->Serialize(shared_info->GetIsolate())
   14270                 .ToHandle(&pre_parsed_scope_data)) {
   14271           Handle<UncompiledData> data =
   14272               isolate->factory()->NewUncompiledDataWithPreParsedScope(
   14273                   lit->inferred_name(), lit->start_position(),
   14274                   lit->end_position(), lit->function_literal_id(),
   14275                   pre_parsed_scope_data);
   14276           shared_info->set_uncompiled_data(*data);
   14277           needs_position_info = false;
   14278         }
   14279       }
   14280     }
   14281   }
   14282   if (needs_position_info) {
   14283     Handle<UncompiledData> data =
   14284         isolate->factory()->NewUncompiledDataWithoutPreParsedScope(
   14285             lit->inferred_name(), lit->start_position(), lit->end_position(),
   14286             lit->function_literal_id());
   14287     shared_info->set_uncompiled_data(*data);
   14288   }
   14289 }
   14290 
   14291 void SharedFunctionInfo::SetExpectedNofPropertiesFromEstimate(
   14292     FunctionLiteral* literal) {
   14293   int estimate = literal->expected_property_count();
   14294 
   14295   // If no properties are added in the constructor, they are more likely
   14296   // to be added later.
   14297   if (estimate == 0) estimate = 2;
   14298 
   14299   // Inobject slack tracking will reclaim redundant inobject space later,
   14300   // so we can afford to adjust the estimate generously.
   14301   estimate += 8;
   14302 
   14303   // Limit actual estimate to fit in a 8 bit field, we will never allocate
   14304   // more than this in any case.
   14305   STATIC_ASSERT(JSObject::kMaxInObjectProperties <= kMaxUInt8);
   14306   estimate = std::min(estimate, kMaxUInt8);
   14307 
   14308   set_expected_nof_properties(estimate);
   14309 }
   14310 
   14311 void SharedFunctionInfo::SetFunctionTokenPosition(int function_token_position,
   14312                                                   int start_position) {
   14313   int offset;
   14314   if (function_token_position == kNoSourcePosition) {
   14315     offset = 0;
   14316   } else {
   14317     offset = start_position - function_token_position;
   14318   }
   14319 
   14320   if (offset > kMaximumFunctionTokenOffset) {
   14321     offset = kFunctionTokenOutOfRange;
   14322   }
   14323   set_raw_function_token_offset(offset);
   14324 }
   14325 
   14326 void Map::StartInobjectSlackTracking() {
   14327   DCHECK(!IsInobjectSlackTrackingInProgress());
   14328   if (UnusedPropertyFields() == 0) return;
   14329   set_construction_counter(Map::kSlackTrackingCounterStart);
   14330 }
   14331 
   14332 void ObjectVisitor::VisitCodeTarget(Code* host, RelocInfo* rinfo) {
   14333   DCHECK(RelocInfo::IsCodeTargetMode(rinfo->rmode()));
   14334   Object* old_pointer = Code::GetCodeFromTargetAddress(rinfo->target_address());
   14335   Object* new_pointer = old_pointer;
   14336   VisitPointer(host, &new_pointer);
   14337   DCHECK_EQ(old_pointer, new_pointer);
   14338 }
   14339 
   14340 void ObjectVisitor::VisitEmbeddedPointer(Code* host, RelocInfo* rinfo) {
   14341   DCHECK(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT);
   14342   Object* old_pointer = rinfo->target_object();
   14343   Object* new_pointer = old_pointer;
   14344   VisitPointer(host, &new_pointer);
   14345   DCHECK_EQ(old_pointer, new_pointer);
   14346 }
   14347 
   14348 void ObjectVisitor::VisitRelocInfo(RelocIterator* it) {
   14349   for (; !it->done(); it->next()) {
   14350     it->rinfo()->Visit(this);
   14351   }
   14352 }
   14353 
   14354 void Code::InvalidateEmbeddedObjects(Heap* heap) {
   14355   HeapObject* undefined = ReadOnlyRoots(heap).undefined_value();
   14356   int mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
   14357   for (RelocIterator it(this, mode_mask); !it.done(); it.next()) {
   14358     RelocInfo::Mode mode = it.rinfo()->rmode();
   14359     if (mode == RelocInfo::EMBEDDED_OBJECT) {
   14360       it.rinfo()->set_target_object(heap, undefined, SKIP_WRITE_BARRIER);
   14361     }
   14362   }
   14363 }
   14364 
   14365 
   14366 void Code::Relocate(intptr_t delta) {
   14367   for (RelocIterator it(this, RelocInfo::kApplyMask); !it.done(); it.next()) {
   14368     it.rinfo()->apply(delta);
   14369   }
   14370   Assembler::FlushICache(raw_instruction_start(), raw_instruction_size());
   14371 }
   14372 
   14373 void Code::FlushICache() const {
   14374   Assembler::FlushICache(raw_instruction_start(), raw_instruction_size());
   14375 }
   14376 
   14377 void Code::CopyFrom(Heap* heap, const CodeDesc& desc) {
   14378   CopyFromNoFlush(heap, desc);
   14379   FlushICache();
   14380 }
   14381 
   14382 void Code::CopyFromNoFlush(Heap* heap, const CodeDesc& desc) {
   14383   // Copy code.
   14384   CopyBytes(reinterpret_cast<byte*>(raw_instruction_start()), desc.buffer,
   14385             static_cast<size_t>(desc.instr_size));
   14386 
   14387   // Copy unwinding info, if any.
   14388   if (desc.unwinding_info) {
   14389     DCHECK_GT(desc.unwinding_info_size, 0);
   14390     set_unwinding_info_size(desc.unwinding_info_size);
   14391     CopyBytes(reinterpret_cast<byte*>(unwinding_info_start()),
   14392               desc.unwinding_info,
   14393               static_cast<size_t>(desc.unwinding_info_size));
   14394   }
   14395 
   14396   // Copy reloc info.
   14397   CopyBytes(relocation_start(),
   14398             desc.buffer + desc.buffer_size - desc.reloc_size,
   14399             static_cast<size_t>(desc.reloc_size));
   14400 
   14401   // Unbox handles and relocate.
   14402   Assembler* origin = desc.origin;
   14403   AllowDeferredHandleDereference embedding_raw_address;
   14404   const int mode_mask = RelocInfo::PostCodegenRelocationMask();
   14405   for (RelocIterator it(this, mode_mask); !it.done(); it.next()) {
   14406     RelocInfo::Mode mode = it.rinfo()->rmode();
   14407     if (mode == RelocInfo::EMBEDDED_OBJECT) {
   14408       Handle<HeapObject> p = it.rinfo()->target_object_handle(origin);
   14409       it.rinfo()->set_target_object(heap, *p, UPDATE_WRITE_BARRIER,
   14410                                     SKIP_ICACHE_FLUSH);
   14411     } else if (RelocInfo::IsCodeTargetMode(mode)) {
   14412       // Rewrite code handles to direct pointers to the first instruction in the
   14413       // code object.
   14414       Handle<Object> p = it.rinfo()->target_object_handle(origin);
   14415       Code* code = Code::cast(*p);
   14416       it.rinfo()->set_target_address(code->raw_instruction_start(),
   14417                                      UPDATE_WRITE_BARRIER, SKIP_ICACHE_FLUSH);
   14418     } else if (RelocInfo::IsRuntimeEntry(mode)) {
   14419       Address p = it.rinfo()->target_runtime_entry(origin);
   14420       it.rinfo()->set_target_runtime_entry(p, UPDATE_WRITE_BARRIER,
   14421                                            SKIP_ICACHE_FLUSH);
   14422     } else {
   14423       intptr_t delta =
   14424           raw_instruction_start() - reinterpret_cast<Address>(desc.buffer);
   14425       it.rinfo()->apply(delta);
   14426     }
   14427   }
   14428 }
   14429 
   14430 
   14431 SafepointEntry Code::GetSafepointEntry(Address pc) {
   14432   SafepointTable table(this);
   14433   return table.FindEntry(pc);
   14434 }
   14435 
   14436 int Code::OffHeapInstructionSize() const {
   14437   DCHECK(is_off_heap_trampoline());
   14438   if (Isolate::CurrentEmbeddedBlob() == nullptr) return raw_instruction_size();
   14439   EmbeddedData d = EmbeddedData::FromBlob();
   14440   return d.InstructionSizeOfBuiltin(builtin_index());
   14441 }
   14442 
   14443 Address Code::OffHeapInstructionStart() const {
   14444   DCHECK(is_off_heap_trampoline());
   14445   if (Isolate::CurrentEmbeddedBlob() == nullptr) return raw_instruction_start();
   14446   EmbeddedData d = EmbeddedData::FromBlob();
   14447   return d.InstructionStartOfBuiltin(builtin_index());
   14448 }
   14449 
   14450 Address Code::OffHeapInstructionEnd() const {
   14451   DCHECK(is_off_heap_trampoline());
   14452   if (Isolate::CurrentEmbeddedBlob() == nullptr) return raw_instruction_end();
   14453   EmbeddedData d = EmbeddedData::FromBlob();
   14454   return d.InstructionStartOfBuiltin(builtin_index()) +
   14455          d.InstructionSizeOfBuiltin(builtin_index());
   14456 }
   14457 
   14458 namespace {
   14459 template <typename Code>
   14460 void SetStackFrameCacheCommon(Isolate* isolate, Handle<Code> code,
   14461                               Handle<SimpleNumberDictionary> cache) {
   14462   Handle<Object> maybe_table(code->source_position_table(), isolate);
   14463   if (maybe_table->IsSourcePositionTableWithFrameCache()) {
   14464     Handle<SourcePositionTableWithFrameCache>::cast(maybe_table)
   14465         ->set_stack_frame_cache(*cache);
   14466     return;
   14467   }
   14468   DCHECK(maybe_table->IsByteArray());
   14469   Handle<ByteArray> table(Handle<ByteArray>::cast(maybe_table));
   14470   Handle<SourcePositionTableWithFrameCache> table_with_cache =
   14471       isolate->factory()->NewSourcePositionTableWithFrameCache(table, cache);
   14472   code->set_source_position_table(*table_with_cache);
   14473 }
   14474 }  // namespace
   14475 
   14476 // static
   14477 void AbstractCode::SetStackFrameCache(Handle<AbstractCode> abstract_code,
   14478                                       Handle<SimpleNumberDictionary> cache) {
   14479   if (abstract_code->IsCode()) {
   14480     SetStackFrameCacheCommon(
   14481         abstract_code->GetIsolate(),
   14482         handle(abstract_code->GetCode(), abstract_code->GetIsolate()), cache);
   14483   } else {
   14484     SetStackFrameCacheCommon(
   14485         abstract_code->GetIsolate(),
   14486         handle(abstract_code->GetBytecodeArray(), abstract_code->GetIsolate()),
   14487         cache);
   14488   }
   14489 }
   14490 
   14491 namespace {
   14492 template <typename Code>
   14493 void DropStackFrameCacheCommon(Code* code) {
   14494   i::Object* maybe_table = code->source_position_table();
   14495   if (maybe_table->IsByteArray()) return;
   14496   DCHECK(maybe_table->IsSourcePositionTableWithFrameCache());
   14497   code->set_source_position_table(
   14498       i::SourcePositionTableWithFrameCache::cast(maybe_table)
   14499           ->source_position_table());
   14500 }
   14501 }  // namespace
   14502 
   14503 void AbstractCode::DropStackFrameCache() {
   14504   if (IsCode()) {
   14505     DropStackFrameCacheCommon(GetCode());
   14506   } else {
   14507     DropStackFrameCacheCommon(GetBytecodeArray());
   14508   }
   14509 }
   14510 
   14511 int AbstractCode::SourcePosition(int offset) {
   14512   int position = 0;
   14513   // Subtract one because the current PC is one instruction after the call site.
   14514   if (IsCode()) offset--;
   14515   for (SourcePositionTableIterator iterator(source_position_table());
   14516        !iterator.done() && iterator.code_offset() <= offset;
   14517        iterator.Advance()) {
   14518     position = iterator.source_position().ScriptOffset();
   14519   }
   14520   return position;
   14521 }
   14522 
   14523 int AbstractCode::SourceStatementPosition(int offset) {
   14524   // First find the closest position.
   14525   int position = SourcePosition(offset);
   14526   // Now find the closest statement position before the position.
   14527   int statement_position = 0;
   14528   for (SourcePositionTableIterator it(source_position_table()); !it.done();
   14529        it.Advance()) {
   14530     if (it.is_statement()) {
   14531       int p = it.source_position().ScriptOffset();
   14532       if (statement_position < p && p <= position) {
   14533         statement_position = p;
   14534       }
   14535     }
   14536   }
   14537   return statement_position;
   14538 }
   14539 
   14540 void JSFunction::ClearTypeFeedbackInfo() {
   14541   if (feedback_cell()->value()->IsFeedbackVector()) {
   14542     FeedbackVector* vector = feedback_vector();
   14543     Isolate* isolate = GetIsolate();
   14544     if (vector->ClearSlots(isolate)) {
   14545       IC::OnFeedbackChanged(isolate, vector, FeedbackSlot::Invalid(), this,
   14546                             "ClearTypeFeedbackInfo");
   14547     }
   14548   }
   14549 }
   14550 
   14551 void Code::PrintDeoptLocation(FILE* out, const char* str, Address pc) {
   14552   Deoptimizer::DeoptInfo info = Deoptimizer::GetDeoptInfo(this, pc);
   14553   class SourcePosition pos = info.position;
   14554   if (info.deopt_reason != DeoptimizeReason::kUnknown || pos.IsKnown()) {
   14555     PrintF(out, "%s", str);
   14556     OFStream outstr(out);
   14557     pos.Print(outstr, this);
   14558     PrintF(out, ", %s\n", DeoptimizeReasonToString(info.deopt_reason));
   14559   }
   14560 }
   14561 
   14562 
   14563 bool Code::CanDeoptAt(Address pc) {
   14564   DeoptimizationData* deopt_data =
   14565       DeoptimizationData::cast(deoptimization_data());
   14566   Address code_start_address = InstructionStart();
   14567   for (int i = 0; i < deopt_data->DeoptCount(); i++) {
   14568     if (deopt_data->Pc(i)->value() == -1) continue;
   14569     Address address = code_start_address + deopt_data->Pc(i)->value();
   14570     if (address == pc && deopt_data->BytecodeOffset(i) != BailoutId::None()) {
   14571       return true;
   14572     }
   14573   }
   14574   return false;
   14575 }
   14576 
   14577 
   14578 // Identify kind of code.
   14579 const char* Code::Kind2String(Kind kind) {
   14580   switch (kind) {
   14581 #define CASE(name) case name: return #name;
   14582     CODE_KIND_LIST(CASE)
   14583 #undef CASE
   14584     case NUMBER_OF_KINDS: break;
   14585   }
   14586   UNREACHABLE();
   14587 }
   14588 
   14589 // Identify kind of code.
   14590 const char* AbstractCode::Kind2String(Kind kind) {
   14591   if (kind < AbstractCode::INTERPRETED_FUNCTION)
   14592     return Code::Kind2String((Code::Kind)kind);
   14593   if (kind == AbstractCode::INTERPRETED_FUNCTION) return "INTERPRETED_FUNCTION";
   14594   UNREACHABLE();
   14595 }
   14596 
   14597 bool Code::IsIsolateIndependent(Isolate* isolate) {
   14598   constexpr int all_real_modes_mask =
   14599       (1 << (RelocInfo::LAST_REAL_RELOC_MODE + 1)) - 1;
   14600   constexpr int mode_mask = all_real_modes_mask &
   14601                             ~RelocInfo::ModeMask(RelocInfo::COMMENT) &
   14602                             ~RelocInfo::ModeMask(RelocInfo::CONST_POOL) &
   14603                             ~RelocInfo::ModeMask(RelocInfo::OFF_HEAP_TARGET) &
   14604                             ~RelocInfo::ModeMask(RelocInfo::VENEER_POOL);
   14605   STATIC_ASSERT(RelocInfo::LAST_REAL_RELOC_MODE == RelocInfo::VENEER_POOL);
   14606   STATIC_ASSERT(RelocInfo::ModeMask(RelocInfo::COMMENT) ==
   14607                 (1 << RelocInfo::COMMENT));
   14608   STATIC_ASSERT(mode_mask ==
   14609                 (RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
   14610                  RelocInfo::ModeMask(RelocInfo::RELATIVE_CODE_TARGET) |
   14611                  RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
   14612                  RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) |
   14613                  RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) |
   14614                  RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED) |
   14615                  RelocInfo::ModeMask(RelocInfo::JS_TO_WASM_CALL) |
   14616                  RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY) |
   14617                  RelocInfo::ModeMask(RelocInfo::WASM_CALL) |
   14618                  RelocInfo::ModeMask(RelocInfo::WASM_STUB_CALL)));
   14619 
   14620   bool is_process_independent = true;
   14621   for (RelocIterator it(this, mode_mask); !it.done(); it.next()) {
   14622 #if defined(V8_TARGET_ARCH_X64) || defined(V8_TARGET_ARCH_ARM64) || \
   14623     defined(V8_TARGET_ARCH_ARM)
   14624     // On X64, ARM, ARM64 we emit relative builtin-to-builtin jumps for isolate
   14625     // independent builtins in the snapshot. They are later rewritten as
   14626     // pc-relative jumps to the off-heap instruction stream and are thus
   14627     // process-independent.
   14628     // See also: FinalizeEmbeddedCodeTargets.
   14629     if (RelocInfo::IsCodeTargetMode(it.rinfo()->rmode())) {
   14630       Address target_address = it.rinfo()->target_address();
   14631       if (InstructionStream::PcIsOffHeap(isolate, target_address)) continue;
   14632 
   14633       Code* target = Code::GetCodeFromTargetAddress(target_address);
   14634       CHECK(target->IsCode());
   14635       if (Builtins::IsIsolateIndependentBuiltin(target)) continue;
   14636     }
   14637 #endif
   14638     is_process_independent = false;
   14639   }
   14640 
   14641   return is_process_independent;
   14642 }
   14643 
   14644 bool Code::Inlines(SharedFunctionInfo* sfi) {
   14645   // We can only check for inlining for optimized code.
   14646   DCHECK(is_optimized_code());
   14647   DisallowHeapAllocation no_gc;
   14648   DeoptimizationData* const data =
   14649       DeoptimizationData::cast(deoptimization_data());
   14650   if (data->length() == 0) return false;
   14651   if (data->SharedFunctionInfo() == sfi) return true;
   14652   FixedArray* const literals = data->LiteralArray();
   14653   int const inlined_count = data->InlinedFunctionCount()->value();
   14654   for (int i = 0; i < inlined_count; ++i) {
   14655     if (SharedFunctionInfo::cast(literals->get(i)) == sfi) return true;
   14656   }
   14657   return false;
   14658 }
   14659 
   14660 Code::OptimizedCodeIterator::OptimizedCodeIterator(Isolate* isolate) {
   14661   isolate_ = isolate;
   14662   Object* list = isolate->heap()->native_contexts_list();
   14663   next_context_ = list->IsUndefined(isolate_) ? nullptr : Context::cast(list);
   14664   current_code_ = nullptr;
   14665 }
   14666 
   14667 Code* Code::OptimizedCodeIterator::Next() {
   14668   do {
   14669     Object* next;
   14670     if (current_code_ != nullptr) {
   14671       // Get next code in the linked list.
   14672       next = Code::cast(current_code_)->next_code_link();
   14673     } else if (next_context_ != nullptr) {
   14674       // Linked list of code exhausted. Get list of next context.
   14675       next = next_context_->OptimizedCodeListHead();
   14676       Object* next_context = next_context_->next_context_link();
   14677       next_context_ = next_context->IsUndefined(isolate_)
   14678                           ? nullptr
   14679                           : Context::cast(next_context);
   14680     } else {
   14681       // Exhausted contexts.
   14682       return nullptr;
   14683     }
   14684     current_code_ = next->IsUndefined(isolate_) ? nullptr : Code::cast(next);
   14685   } while (current_code_ == nullptr);
   14686   Code* code = Code::cast(current_code_);
   14687   DCHECK_EQ(Code::OPTIMIZED_FUNCTION, code->kind());
   14688   return code;
   14689 }
   14690 
   14691 #ifdef ENABLE_DISASSEMBLER
   14692 
   14693 namespace {
   14694 void print_pc(std::ostream& os, int pc) {
   14695   if (pc == -1) {
   14696     os << "NA";
   14697   } else {
   14698     os << std::hex << pc << std::dec;
   14699   }
   14700 }
   14701 }  // anonymous namespace
   14702 
   14703 void DeoptimizationData::DeoptimizationDataPrint(std::ostream& os) {  // NOLINT
   14704   if (length() == 0) {
   14705     os << "Deoptimization Input Data invalidated by lazy deoptimization\n";
   14706     return;
   14707   }
   14708 
   14709   disasm::NameConverter converter;
   14710   int const inlined_function_count = InlinedFunctionCount()->value();
   14711   os << "Inlined functions (count = " << inlined_function_count << ")\n";
   14712   for (int id = 0; id < inlined_function_count; ++id) {
   14713     Object* info = LiteralArray()->get(id);
   14714     os << " " << Brief(SharedFunctionInfo::cast(info)) << "\n";
   14715   }
   14716   os << "\n";
   14717   int deopt_count = DeoptCount();
   14718   os << "Deoptimization Input Data (deopt points = " << deopt_count << ")\n";
   14719   if (0 != deopt_count) {
   14720     os << " index  bytecode-offset    pc";
   14721     if (FLAG_print_code_verbose) os << "  commands";
   14722     os << "\n";
   14723   }
   14724   for (int i = 0; i < deopt_count; i++) {
   14725     os << std::setw(6) << i << "  " << std::setw(15)
   14726        << BytecodeOffset(i).ToInt() << "  " << std::setw(4);
   14727     print_pc(os, Pc(i)->value());
   14728     os << std::setw(2);
   14729 
   14730     if (!FLAG_print_code_verbose) {
   14731       os << "\n";
   14732       continue;
   14733     }
   14734 
   14735     // Print details of the frame translation.
   14736     int translation_index = TranslationIndex(i)->value();
   14737     TranslationIterator iterator(TranslationByteArray(), translation_index);
   14738     Translation::Opcode opcode =
   14739         static_cast<Translation::Opcode>(iterator.Next());
   14740     DCHECK(Translation::BEGIN == opcode);
   14741     int frame_count = iterator.Next();
   14742     int jsframe_count = iterator.Next();
   14743     int update_feedback_count = iterator.Next();
   14744     os << "  " << Translation::StringFor(opcode)
   14745        << " {frame count=" << frame_count
   14746        << ", js frame count=" << jsframe_count
   14747        << ", update_feedback_count=" << update_feedback_count << "}\n";
   14748 
   14749     while (iterator.HasNext() &&
   14750            Translation::BEGIN !=
   14751            (opcode = static_cast<Translation::Opcode>(iterator.Next()))) {
   14752       os << std::setw(31) << "    " << Translation::StringFor(opcode) << " ";
   14753 
   14754       switch (opcode) {
   14755         case Translation::BEGIN:
   14756           UNREACHABLE();
   14757           break;
   14758 
   14759         case Translation::INTERPRETED_FRAME: {
   14760           int bytecode_offset = iterator.Next();
   14761           int shared_info_id = iterator.Next();
   14762           unsigned height = iterator.Next();
   14763           Object* shared_info = LiteralArray()->get(shared_info_id);
   14764           os << "{bytecode_offset=" << bytecode_offset << ", function="
   14765              << Brief(SharedFunctionInfo::cast(shared_info)->DebugName())
   14766              << ", height=" << height << "}";
   14767           break;
   14768         }
   14769 
   14770         case Translation::CONSTRUCT_STUB_FRAME: {
   14771           int bailout_id = iterator.Next();
   14772           int shared_info_id = iterator.Next();
   14773           Object* shared_info = LiteralArray()->get(shared_info_id);
   14774           unsigned height = iterator.Next();
   14775           os << "{bailout_id=" << bailout_id << ", function="
   14776              << Brief(SharedFunctionInfo::cast(shared_info)->DebugName())
   14777              << ", height=" << height << "}";
   14778           break;
   14779         }
   14780 
   14781         case Translation::BUILTIN_CONTINUATION_FRAME:
   14782         case Translation::JAVA_SCRIPT_BUILTIN_CONTINUATION_FRAME:
   14783         case Translation::JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH_FRAME: {
   14784           int bailout_id = iterator.Next();
   14785           int shared_info_id = iterator.Next();
   14786           Object* shared_info = LiteralArray()->get(shared_info_id);
   14787           unsigned height = iterator.Next();
   14788           os << "{bailout_id=" << bailout_id << ", function="
   14789              << Brief(SharedFunctionInfo::cast(shared_info)->DebugName())
   14790              << ", height=" << height << "}";
   14791           break;
   14792         }
   14793 
   14794         case Translation::ARGUMENTS_ADAPTOR_FRAME: {
   14795           int shared_info_id = iterator.Next();
   14796           Object* shared_info = LiteralArray()->get(shared_info_id);
   14797           unsigned height = iterator.Next();
   14798           os << "{function="
   14799              << Brief(SharedFunctionInfo::cast(shared_info)->DebugName())
   14800              << ", height=" << height << "}";
   14801           break;
   14802         }
   14803 
   14804         case Translation::REGISTER: {
   14805           int reg_code = iterator.Next();
   14806           os << "{input=" << converter.NameOfCPURegister(reg_code) << "}";
   14807           break;
   14808         }
   14809 
   14810         case Translation::INT32_REGISTER: {
   14811           int reg_code = iterator.Next();
   14812           os << "{input=" << converter.NameOfCPURegister(reg_code) << "}";
   14813           break;
   14814         }
   14815 
   14816         case Translation::UINT32_REGISTER: {
   14817           int reg_code = iterator.Next();
   14818           os << "{input=" << converter.NameOfCPURegister(reg_code)
   14819              << " (unsigned)}";
   14820           break;
   14821         }
   14822 
   14823         case Translation::BOOL_REGISTER: {
   14824           int reg_code = iterator.Next();
   14825           os << "{input=" << converter.NameOfCPURegister(reg_code)
   14826              << " (bool)}";
   14827           break;
   14828         }
   14829 
   14830         case Translation::FLOAT_REGISTER: {
   14831           int reg_code = iterator.Next();
   14832           os << "{input="
   14833              << RegisterConfiguration::Default()->GetFloatRegisterName(reg_code)
   14834              << "}";
   14835           break;
   14836         }
   14837 
   14838         case Translation::DOUBLE_REGISTER: {
   14839           int reg_code = iterator.Next();
   14840           os << "{input="
   14841              << RegisterConfiguration::Default()->GetDoubleRegisterName(
   14842                     reg_code)
   14843              << "}";
   14844           break;
   14845         }
   14846 
   14847         case Translation::STACK_SLOT: {
   14848           int input_slot_index = iterator.Next();
   14849           os << "{input=" << input_slot_index << "}";
   14850           break;
   14851         }
   14852 
   14853         case Translation::INT32_STACK_SLOT: {
   14854           int input_slot_index = iterator.Next();
   14855           os << "{input=" << input_slot_index << "}";
   14856           break;
   14857         }
   14858 
   14859         case Translation::UINT32_STACK_SLOT: {
   14860           int input_slot_index = iterator.Next();
   14861           os << "{input=" << input_slot_index << " (unsigned)}";
   14862           break;
   14863         }
   14864 
   14865         case Translation::BOOL_STACK_SLOT: {
   14866           int input_slot_index = iterator.Next();
   14867           os << "{input=" << input_slot_index << " (bool)}";
   14868           break;
   14869         }
   14870 
   14871         case Translation::FLOAT_STACK_SLOT:
   14872         case Translation::DOUBLE_STACK_SLOT: {
   14873           int input_slot_index = iterator.Next();
   14874           os << "{input=" << input_slot_index << "}";
   14875           break;
   14876         }
   14877 
   14878         case Translation::LITERAL: {
   14879           int literal_index = iterator.Next();
   14880           Object* literal_value = LiteralArray()->get(literal_index);
   14881           os << "{literal_id=" << literal_index << " (" << Brief(literal_value)
   14882              << ")}";
   14883           break;
   14884         }
   14885 
   14886         case Translation::DUPLICATED_OBJECT: {
   14887           int object_index = iterator.Next();
   14888           os << "{object_index=" << object_index << "}";
   14889           break;
   14890         }
   14891 
   14892         case Translation::ARGUMENTS_ELEMENTS:
   14893         case Translation::ARGUMENTS_LENGTH: {
   14894           CreateArgumentsType arguments_type =
   14895               static_cast<CreateArgumentsType>(iterator.Next());
   14896           os << "{arguments_type=" << arguments_type << "}";
   14897           break;
   14898         }
   14899 
   14900         case Translation::CAPTURED_OBJECT: {
   14901           int args_length = iterator.Next();
   14902           os << "{length=" << args_length << "}";
   14903           break;
   14904         }
   14905 
   14906         case Translation::UPDATE_FEEDBACK: {
   14907           int literal_index = iterator.Next();
   14908           FeedbackSlot slot(iterator.Next());
   14909           os << "{feedback={vector_index=" << literal_index << ", slot=" << slot
   14910              << "}}";
   14911           break;
   14912         }
   14913       }
   14914       os << "\n";
   14915     }
   14916   }
   14917 }
   14918 
   14919 const char* Code::GetName(Isolate* isolate) const {
   14920   if (is_stub()) {
   14921     return CodeStub::MajorName(CodeStub::GetMajorKey(this));
   14922   } else if (kind() == BYTECODE_HANDLER) {
   14923     return isolate->interpreter()->LookupNameOfBytecodeHandler(this);
   14924   } else {
   14925     // There are some handlers and ICs that we can also find names for with
   14926     // Builtins::Lookup.
   14927     return isolate->builtins()->Lookup(raw_instruction_start());
   14928   }
   14929 }
   14930 
   14931 void Code::PrintBuiltinCode(Isolate* isolate, const char* name) {
   14932   DCHECK(FLAG_print_builtin_code);
   14933   if (name == nullptr) {
   14934     name = GetName(isolate);
   14935   }
   14936   if (name != nullptr &&
   14937       PassesFilter(CStrVector(name),
   14938                    CStrVector(FLAG_print_builtin_code_filter))) {
   14939     CodeTracer::Scope trace_scope(isolate->GetCodeTracer());
   14940     OFStream os(trace_scope.file());
   14941     Disassemble(name, os);
   14942     os << "\n";
   14943   }
   14944 }
   14945 
   14946 namespace {
   14947 
   14948 inline void DisassembleCodeRange(Isolate* isolate, std::ostream& os, Code* code,
   14949                                  Address begin, size_t size,
   14950                                  Address current_pc) {
   14951   Address end = begin + size;
   14952   // TODO(mstarzinger): Refactor CodeReference to avoid the
   14953   // unhandlified->handlified transition.
   14954   AllowHandleAllocation allow_handles;
   14955   DisallowHeapAllocation no_gc;
   14956   HandleScope handle_scope(isolate);
   14957   Disassembler::Decode(isolate, &os, reinterpret_cast<byte*>(begin),
   14958                        reinterpret_cast<byte*>(end),
   14959                        CodeReference(handle(code, isolate)), current_pc);
   14960 }
   14961 
   14962 }  // namespace
   14963 
   14964 void Code::Disassemble(const char* name, std::ostream& os, Address current_pc) {
   14965   Isolate* isolate = GetIsolate();
   14966   os << "kind = " << Kind2String(kind()) << "\n";
   14967   if (is_stub()) {
   14968     const char* n = CodeStub::MajorName(CodeStub::GetMajorKey(this));
   14969     os << "major_key = " << (n == nullptr ? "null" : n) << "\n";
   14970     os << "minor_key = " << CodeStub::MinorKeyFromKey(this->stub_key()) << "\n";
   14971   }
   14972   if (name == nullptr) {
   14973     name = GetName(isolate);
   14974   }
   14975   if ((name != nullptr) && (name[0] != '\0')) {
   14976     os << "name = " << name << "\n";
   14977   }
   14978   if (kind() == OPTIMIZED_FUNCTION) {
   14979     os << "stack_slots = " << stack_slots() << "\n";
   14980   }
   14981   os << "compiler = " << (is_turbofanned() ? "turbofan" : "unknown") << "\n";
   14982   os << "address = " << static_cast<const void*>(this) << "\n\n";
   14983 
   14984   if (is_off_heap_trampoline()) {
   14985     int trampoline_size = raw_instruction_size();
   14986     os << "Trampoline (size = " << trampoline_size << ")\n";
   14987     DisassembleCodeRange(isolate, os, this, raw_instruction_start(),
   14988                          trampoline_size, current_pc);
   14989     os << "\n";
   14990   }
   14991 
   14992   {
   14993     int size = InstructionSize();
   14994     int safepoint_offset =
   14995         has_safepoint_info() ? safepoint_table_offset() : size;
   14996     int constant_pool_offset = this->constant_pool_offset();
   14997     int handler_offset = handler_table_offset() ? handler_table_offset() : size;
   14998 
   14999     // Stop before reaching any embedded tables
   15000     int code_size =
   15001         Min(handler_offset, Min(safepoint_offset, constant_pool_offset));
   15002     os << "Instructions (size = " << code_size << ")\n";
   15003     DisassembleCodeRange(isolate, os, this, InstructionStart(), code_size,
   15004                          current_pc);
   15005 
   15006     if (constant_pool_offset < size) {
   15007       int constant_pool_size = safepoint_offset - constant_pool_offset;
   15008       DCHECK_EQ(constant_pool_size & kPointerAlignmentMask, 0);
   15009       os << "\nConstant Pool (size = " << constant_pool_size << ")\n";
   15010       Vector<char> buf = Vector<char>::New(50);
   15011       intptr_t* ptr = reinterpret_cast<intptr_t*>(InstructionStart() +
   15012                                                   constant_pool_offset);
   15013       for (int i = 0; i < constant_pool_size; i += kPointerSize, ptr++) {
   15014         SNPrintF(buf, "%4d %08" V8PRIxPTR, i, *ptr);
   15015         os << static_cast<const void*>(ptr) << "  " << buf.start() << "\n";
   15016       }
   15017     }
   15018   }
   15019   os << "\n";
   15020 
   15021   SourcePositionTableIterator it(SourcePositionTable());
   15022   if (!it.done()) {
   15023     os << "Source positions:\n pc offset  position\n";
   15024     for (; !it.done(); it.Advance()) {
   15025       os << std::setw(10) << std::hex << it.code_offset() << std::dec
   15026          << std::setw(10) << it.source_position().ScriptOffset()
   15027          << (it.is_statement() ? "  statement" : "") << "\n";
   15028     }
   15029     os << "\n";
   15030   }
   15031 
   15032   if (kind() == OPTIMIZED_FUNCTION) {
   15033     DeoptimizationData* data =
   15034         DeoptimizationData::cast(this->deoptimization_data());
   15035     data->DeoptimizationDataPrint(os);
   15036   }
   15037   os << "\n";
   15038 
   15039   if (has_safepoint_info()) {
   15040     SafepointTable table(this);
   15041     os << "Safepoints (size = " << table.size() << ")\n";
   15042     for (unsigned i = 0; i < table.length(); i++) {
   15043       unsigned pc_offset = table.GetPcOffset(i);
   15044       os << reinterpret_cast<const void*>(InstructionStart() + pc_offset)
   15045          << "  ";
   15046       os << std::setw(6) << std::hex << pc_offset << "  " << std::setw(4);
   15047       int trampoline_pc = table.GetTrampolinePcOffset(i);
   15048       print_pc(os, trampoline_pc);
   15049       os << std::dec << "  ";
   15050       table.PrintEntry(i, os);
   15051       os << " (sp -> fp)  ";
   15052       SafepointEntry entry = table.GetEntry(i);
   15053       if (entry.deoptimization_index() != Safepoint::kNoDeoptimizationIndex) {
   15054         os << std::setw(6) << entry.deoptimization_index();
   15055       } else {
   15056         os << "<none>";
   15057       }
   15058       if (entry.argument_count() > 0) {
   15059         os << " argc: " << entry.argument_count();
   15060       }
   15061       os << "\n";
   15062     }
   15063     os << "\n";
   15064   }
   15065 
   15066   if (handler_table_offset() > 0) {
   15067     HandlerTable table(this);
   15068     os << "Handler Table (size = " << table.NumberOfReturnEntries() << ")\n";
   15069     if (kind() == OPTIMIZED_FUNCTION) {
   15070       table.HandlerTableReturnPrint(os);
   15071     }
   15072     os << "\n";
   15073   }
   15074 
   15075   os << "RelocInfo (size = " << relocation_size() << ")\n";
   15076   for (RelocIterator it(this); !it.done(); it.next()) {
   15077     it.rinfo()->Print(isolate, os);
   15078   }
   15079   os << "\n";
   15080 
   15081   if (has_unwinding_info()) {
   15082     os << "UnwindingInfo (size = " << unwinding_info_size() << ")\n";
   15083     EhFrameDisassembler eh_frame_disassembler(
   15084         reinterpret_cast<byte*>(unwinding_info_start()),
   15085         reinterpret_cast<byte*>(unwinding_info_end()));
   15086     eh_frame_disassembler.DisassembleToStream(os);
   15087     os << "\n";
   15088   }
   15089 }
   15090 #endif  // ENABLE_DISASSEMBLER
   15091 
   15092 void BytecodeArray::Disassemble(std::ostream& os) {
   15093   DisallowHeapAllocation no_gc;
   15094 
   15095   os << "Parameter count " << parameter_count() << "\n";
   15096   os << "Frame size " << frame_size() << "\n";
   15097 
   15098   Address base_address = GetFirstBytecodeAddress();
   15099   SourcePositionTableIterator source_positions(SourcePositionTable());
   15100 
   15101   // Storage for backing the handle passed to the iterator. This handle won't be
   15102   // updated by the gc, but that's ok because we've disallowed GCs anyway.
   15103   BytecodeArray* handle_storage = this;
   15104   Handle<BytecodeArray> handle(&handle_storage);
   15105   interpreter::BytecodeArrayIterator iterator(handle);
   15106   while (!iterator.done()) {
   15107     if (!source_positions.done() &&
   15108         iterator.current_offset() == source_positions.code_offset()) {
   15109       os << std::setw(5) << source_positions.source_position().ScriptOffset();
   15110       os << (source_positions.is_statement() ? " S> " : " E> ");
   15111       source_positions.Advance();
   15112     } else {
   15113       os << "         ";
   15114     }
   15115     Address current_address = base_address + iterator.current_offset();
   15116     os << reinterpret_cast<const void*>(current_address) << " @ "
   15117        << std::setw(4) << iterator.current_offset() << " : ";
   15118     interpreter::BytecodeDecoder::Decode(
   15119         os, reinterpret_cast<byte*>(current_address), parameter_count());
   15120     if (interpreter::Bytecodes::IsJump(iterator.current_bytecode())) {
   15121       Address jump_target = base_address + iterator.GetJumpTargetOffset();
   15122       os << " (" << reinterpret_cast<void*>(jump_target) << " @ "
   15123          << iterator.GetJumpTargetOffset() << ")";
   15124     }
   15125     if (interpreter::Bytecodes::IsSwitch(iterator.current_bytecode())) {
   15126       os << " {";
   15127       bool first_entry = true;
   15128       for (const auto& entry : iterator.GetJumpTableTargetOffsets()) {
   15129         if (first_entry) {
   15130           first_entry = false;
   15131         } else {
   15132           os << ",";
   15133         }
   15134         os << " " << entry.case_value << ": @" << entry.target_offset;
   15135       }
   15136       os << " }";
   15137     }
   15138     os << std::endl;
   15139     iterator.Advance();
   15140   }
   15141 
   15142   os << "Constant pool (size = " << constant_pool()->length() << ")\n";
   15143 #ifdef OBJECT_PRINT
   15144   if (constant_pool()->length() > 0) {
   15145     constant_pool()->Print();
   15146   }
   15147 #endif
   15148 
   15149   os << "Handler Table (size = " << handler_table()->length() << ")\n";
   15150 #ifdef ENABLE_DISASSEMBLER
   15151   if (handler_table()->length() > 0) {
   15152     HandlerTable table(this);
   15153     table.HandlerTableRangePrint(os);
   15154   }
   15155 #endif
   15156 }
   15157 
   15158 void BytecodeArray::CopyBytecodesTo(BytecodeArray* to) {
   15159   BytecodeArray* from = this;
   15160   DCHECK_EQ(from->length(), to->length());
   15161   CopyBytes(reinterpret_cast<byte*>(to->GetFirstBytecodeAddress()),
   15162             reinterpret_cast<byte*>(from->GetFirstBytecodeAddress()),
   15163             from->length());
   15164 }
   15165 
   15166 void BytecodeArray::MakeOlder() {
   15167   // BytecodeArray is aged in concurrent marker.
   15168   // The word must be completely within the byte code array.
   15169   Address age_addr = address() + kBytecodeAgeOffset;
   15170   DCHECK_LE((age_addr & ~kPointerAlignmentMask) + kPointerSize,
   15171             address() + Size());
   15172   Age age = bytecode_age();
   15173   if (age < kLastBytecodeAge) {
   15174     base::AsAtomic8::Release_CompareAndSwap(reinterpret_cast<byte*>(age_addr),
   15175                                             age, age + 1);
   15176   }
   15177 
   15178   DCHECK_GE(bytecode_age(), kFirstBytecodeAge);
   15179   DCHECK_LE(bytecode_age(), kLastBytecodeAge);
   15180 }
   15181 
   15182 bool BytecodeArray::IsOld() const {
   15183   return bytecode_age() >= kIsOldBytecodeAge;
   15184 }
   15185 
   15186 // static
   15187 void JSArray::Initialize(Handle<JSArray> array, int capacity, int length) {
   15188   DCHECK_GE(capacity, 0);
   15189   array->GetIsolate()->factory()->NewJSArrayStorage(
   15190       array, length, capacity, INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE);
   15191 }
   15192 
   15193 void JSArray::SetLength(Handle<JSArray> array, uint32_t new_length) {
   15194   // We should never end in here with a pixel or external array.
   15195   DCHECK(array->AllowsSetLength());
   15196   if (array->SetLengthWouldNormalize(new_length)) {
   15197     JSObject::NormalizeElements(array);
   15198   }
   15199   array->GetElementsAccessor()->SetLength(array, new_length);
   15200 }
   15201 
   15202 DependentCode* DependentCode::GetDependentCode(Handle<HeapObject> object) {
   15203   if (object->IsMap()) {
   15204     return Handle<Map>::cast(object)->dependent_code();
   15205   } else if (object->IsPropertyCell()) {
   15206     return Handle<PropertyCell>::cast(object)->dependent_code();
   15207   } else if (object->IsAllocationSite()) {
   15208     return Handle<AllocationSite>::cast(object)->dependent_code();
   15209   }
   15210   UNREACHABLE();
   15211 }
   15212 
   15213 void DependentCode::SetDependentCode(Handle<HeapObject> object,
   15214                                      Handle<DependentCode> dep) {
   15215   if (object->IsMap()) {
   15216     Handle<Map>::cast(object)->set_dependent_code(*dep);
   15217   } else if (object->IsPropertyCell()) {
   15218     Handle<PropertyCell>::cast(object)->set_dependent_code(*dep);
   15219   } else if (object->IsAllocationSite()) {
   15220     Handle<AllocationSite>::cast(object)->set_dependent_code(*dep);
   15221   } else {
   15222     UNREACHABLE();
   15223   }
   15224 }
   15225 
   15226 void DependentCode::InstallDependency(Isolate* isolate, MaybeObjectHandle code,
   15227                                       Handle<HeapObject> object,
   15228                                       DependencyGroup group) {
   15229   Handle<DependentCode> old_deps(DependentCode::GetDependentCode(object),
   15230                                  isolate);
   15231   Handle<DependentCode> new_deps =
   15232       InsertWeakCode(isolate, old_deps, group, code);
   15233   // Update the list head if necessary.
   15234   if (!new_deps.is_identical_to(old_deps))
   15235     DependentCode::SetDependentCode(object, new_deps);
   15236 }
   15237 
   15238 Handle<DependentCode> DependentCode::InsertWeakCode(
   15239     Isolate* isolate, Handle<DependentCode> entries, DependencyGroup group,
   15240     MaybeObjectHandle code) {
   15241   if (entries->length() == 0 || entries->group() > group) {
   15242     // There is no such group.
   15243     return DependentCode::New(isolate, group, code, entries);
   15244   }
   15245   if (entries->group() < group) {
   15246     // The group comes later in the list.
   15247     Handle<DependentCode> old_next(entries->next_link(), isolate);
   15248     Handle<DependentCode> new_next =
   15249         InsertWeakCode(isolate, old_next, group, code);
   15250     if (!old_next.is_identical_to(new_next)) {
   15251       entries->set_next_link(*new_next);
   15252     }
   15253     return entries;
   15254   }
   15255   DCHECK_EQ(group, entries->group());
   15256   int count = entries->count();
   15257   // Check for existing entry to avoid duplicates.
   15258   for (int i = 0; i < count; i++) {
   15259     if (entries->object_at(i) == *code) return entries;
   15260   }
   15261   if (entries->length() < kCodesStartIndex + count + 1) {
   15262     entries = EnsureSpace(isolate, entries);
   15263     // Count could have changed, reload it.
   15264     count = entries->count();
   15265   }
   15266   entries->set_object_at(count, *code);
   15267   entries->set_count(count + 1);
   15268   return entries;
   15269 }
   15270 
   15271 Handle<DependentCode> DependentCode::New(Isolate* isolate,
   15272                                          DependencyGroup group,
   15273                                          MaybeObjectHandle object,
   15274                                          Handle<DependentCode> next) {
   15275   Handle<DependentCode> result = Handle<DependentCode>::cast(
   15276       isolate->factory()->NewWeakFixedArray(kCodesStartIndex + 1, TENURED));
   15277   result->set_next_link(*next);
   15278   result->set_flags(GroupField::encode(group) | CountField::encode(1));
   15279   result->set_object_at(0, *object);
   15280   return result;
   15281 }
   15282 
   15283 Handle<DependentCode> DependentCode::EnsureSpace(
   15284     Isolate* isolate, Handle<DependentCode> entries) {
   15285   if (entries->Compact()) return entries;
   15286   int capacity = kCodesStartIndex + DependentCode::Grow(entries->count());
   15287   int grow_by = capacity - entries->length();
   15288   return Handle<DependentCode>::cast(
   15289       isolate->factory()->CopyWeakFixedArrayAndGrow(entries, grow_by, TENURED));
   15290 }
   15291 
   15292 
   15293 bool DependentCode::Compact() {
   15294   int old_count = count();
   15295   int new_count = 0;
   15296   for (int i = 0; i < old_count; i++) {
   15297     MaybeObject* obj = object_at(i);
   15298     if (!obj->IsClearedWeakHeapObject()) {
   15299       if (i != new_count) {
   15300         copy(i, new_count);
   15301       }
   15302       new_count++;
   15303     }
   15304   }
   15305   set_count(new_count);
   15306   for (int i = new_count; i < old_count; i++) {
   15307     clear_at(i);
   15308   }
   15309   return new_count < old_count;
   15310 }
   15311 
   15312 bool DependentCode::Contains(DependencyGroup group, MaybeObject* code) {
   15313   if (this->length() == 0 || this->group() > group) {
   15314     // There is no such group.
   15315     return false;
   15316   }
   15317   if (this->group() < group) {
   15318     // The group comes later in the list.
   15319     return next_link()->Contains(group, code);
   15320   }
   15321   DCHECK_EQ(group, this->group());
   15322   int count = this->count();
   15323   for (int i = 0; i < count; i++) {
   15324     if (object_at(i) == code) return true;
   15325   }
   15326   return false;
   15327 }
   15328 
   15329 
   15330 bool DependentCode::IsEmpty(DependencyGroup group) {
   15331   if (this->length() == 0 || this->group() > group) {
   15332     // There is no such group.
   15333     return true;
   15334   }
   15335   if (this->group() < group) {
   15336     // The group comes later in the list.
   15337     return next_link()->IsEmpty(group);
   15338   }
   15339   DCHECK_EQ(group, this->group());
   15340   return count() == 0;
   15341 }
   15342 
   15343 
   15344 bool DependentCode::MarkCodeForDeoptimization(
   15345     Isolate* isolate,
   15346     DependentCode::DependencyGroup group) {
   15347   if (this->length() == 0 || this->group() > group) {
   15348     // There is no such group.
   15349     return false;
   15350   }
   15351   if (this->group() < group) {
   15352     // The group comes later in the list.
   15353     return next_link()->MarkCodeForDeoptimization(isolate, group);
   15354   }
   15355   DCHECK_EQ(group, this->group());
   15356   DisallowHeapAllocation no_allocation_scope;
   15357   // Mark all the code that needs to be deoptimized.
   15358   bool marked = false;
   15359   int count = this->count();
   15360   for (int i = 0; i < count; i++) {
   15361     MaybeObject* obj = object_at(i);
   15362     if (obj->IsClearedWeakHeapObject()) continue;
   15363     Code* code = Code::cast(obj->ToWeakHeapObject());
   15364     if (!code->marked_for_deoptimization()) {
   15365       code->SetMarkedForDeoptimization(DependencyGroupName(group));
   15366       marked = true;
   15367     }
   15368   }
   15369   for (int i = 0; i < count; i++) {
   15370     clear_at(i);
   15371   }
   15372   set_count(0);
   15373   return marked;
   15374 }
   15375 
   15376 
   15377 void DependentCode::DeoptimizeDependentCodeGroup(
   15378     Isolate* isolate,
   15379     DependentCode::DependencyGroup group) {
   15380   DisallowHeapAllocation no_allocation_scope;
   15381   bool marked = MarkCodeForDeoptimization(isolate, group);
   15382   if (marked) {
   15383     DCHECK(AllowCodeDependencyChange::IsAllowed());
   15384     Deoptimizer::DeoptimizeMarkedCode(isolate);
   15385   }
   15386 }
   15387 
   15388 void Code::SetMarkedForDeoptimization(const char* reason) {
   15389   set_marked_for_deoptimization(true);
   15390   if (FLAG_trace_deopt &&
   15391       (deoptimization_data() != GetReadOnlyRoots().empty_fixed_array())) {
   15392     DeoptimizationData* deopt_data =
   15393         DeoptimizationData::cast(deoptimization_data());
   15394     CodeTracer::Scope scope(GetHeap()->isolate()->GetCodeTracer());
   15395     PrintF(scope.file(),
   15396            "[marking dependent code " V8PRIxPTR_FMT
   15397            " (opt #%d) for deoptimization, reason: %s]\n",
   15398            reinterpret_cast<intptr_t>(this),
   15399            deopt_data->OptimizationId()->value(), reason);
   15400   }
   15401 }
   15402 
   15403 
   15404 const char* DependentCode::DependencyGroupName(DependencyGroup group) {
   15405   switch (group) {
   15406     case kTransitionGroup:
   15407       return "transition";
   15408     case kPrototypeCheckGroup:
   15409       return "prototype-check";
   15410     case kPropertyCellChangedGroup:
   15411       return "property-cell-changed";
   15412     case kFieldOwnerGroup:
   15413       return "field-owner";
   15414     case kInitialMapChangedGroup:
   15415       return "initial-map-changed";
   15416     case kAllocationSiteTenuringChangedGroup:
   15417       return "allocation-site-tenuring-changed";
   15418     case kAllocationSiteTransitionChangedGroup:
   15419       return "allocation-site-transition-changed";
   15420   }
   15421   UNREACHABLE();
   15422 }
   15423 
   15424 Handle<Map> Map::TransitionToPrototype(Isolate* isolate, Handle<Map> map,
   15425                                        Handle<Object> prototype) {
   15426   Handle<Map> new_map =
   15427       TransitionsAccessor(isolate, map).GetPrototypeTransition(prototype);
   15428   if (new_map.is_null()) {
   15429     new_map = Copy(isolate, map, "TransitionToPrototype");
   15430     TransitionsAccessor(isolate, map)
   15431         .PutPrototypeTransition(prototype, new_map);
   15432     Map::SetPrototype(isolate, new_map, prototype);
   15433   }
   15434   return new_map;
   15435 }
   15436 
   15437 
   15438 Maybe<bool> JSReceiver::SetPrototype(Handle<JSReceiver> object,
   15439                                      Handle<Object> value, bool from_javascript,
   15440                                      ShouldThrow should_throw) {
   15441   if (object->IsJSProxy()) {
   15442     return JSProxy::SetPrototype(Handle<JSProxy>::cast(object), value,
   15443                                  from_javascript, should_throw);
   15444   }
   15445   return JSObject::SetPrototype(Handle<JSObject>::cast(object), value,
   15446                                 from_javascript, should_throw);
   15447 }
   15448 
   15449 
   15450 // ES6: 9.5.2 [[SetPrototypeOf]] (V)
   15451 // static
   15452 Maybe<bool> JSProxy::SetPrototype(Handle<JSProxy> proxy, Handle<Object> value,
   15453                                   bool from_javascript,
   15454                                   ShouldThrow should_throw) {
   15455   Isolate* isolate = proxy->GetIsolate();
   15456   STACK_CHECK(isolate, Nothing<bool>());
   15457   Handle<Name> trap_name = isolate->factory()->setPrototypeOf_string();
   15458   // 1. Assert: Either Type(V) is Object or Type(V) is Null.
   15459   DCHECK(value->IsJSReceiver() || value->IsNull(isolate));
   15460   // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O.
   15461   Handle<Object> handler(proxy->handler(), isolate);
   15462   // 3. If handler is null, throw a TypeError exception.
   15463   // 4. Assert: Type(handler) is Object.
   15464   if (proxy->IsRevoked()) {
   15465     isolate->Throw(*isolate->factory()->NewTypeError(
   15466         MessageTemplate::kProxyRevoked, trap_name));
   15467     return Nothing<bool>();
   15468   }
   15469   // 5. Let target be the value of the [[ProxyTarget]] internal slot.
   15470   Handle<JSReceiver> target(JSReceiver::cast(proxy->target()), isolate);
   15471   // 6. Let trap be ? GetMethod(handler, "getPrototypeOf").
   15472   Handle<Object> trap;
   15473   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   15474       isolate, trap,
   15475       Object::GetMethod(Handle<JSReceiver>::cast(handler), trap_name),
   15476       Nothing<bool>());
   15477   // 7. If trap is undefined, then return target.[[SetPrototypeOf]]().
   15478   if (trap->IsUndefined(isolate)) {
   15479     return JSReceiver::SetPrototype(target, value, from_javascript,
   15480                                     should_throw);
   15481   }
   15482   // 8. Let booleanTrapResult be ToBoolean(? Call(trap, handler, target, V)).
   15483   Handle<Object> argv[] = {target, value};
   15484   Handle<Object> trap_result;
   15485   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   15486       isolate, trap_result,
   15487       Execution::Call(isolate, trap, handler, arraysize(argv), argv),
   15488       Nothing<bool>());
   15489   bool bool_trap_result = trap_result->BooleanValue(isolate);
   15490   // 9. If booleanTrapResult is false, return false.
   15491   if (!bool_trap_result) {
   15492     RETURN_FAILURE(
   15493         isolate, should_throw,
   15494         NewTypeError(MessageTemplate::kProxyTrapReturnedFalsish, trap_name));
   15495   }
   15496   // 10. Let extensibleTarget be ? IsExtensible(target).
   15497   Maybe<bool> is_extensible = JSReceiver::IsExtensible(target);
   15498   if (is_extensible.IsNothing()) return Nothing<bool>();
   15499   // 11. If extensibleTarget is true, return true.
   15500   if (is_extensible.FromJust()) {
   15501     if (bool_trap_result) return Just(true);
   15502     RETURN_FAILURE(
   15503         isolate, should_throw,
   15504         NewTypeError(MessageTemplate::kProxyTrapReturnedFalsish, trap_name));
   15505   }
   15506   // 12. Let targetProto be ? target.[[GetPrototypeOf]]().
   15507   Handle<Object> target_proto;
   15508   ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, target_proto,
   15509                                    JSReceiver::GetPrototype(isolate, target),
   15510                                    Nothing<bool>());
   15511   // 13. If SameValue(V, targetProto) is false, throw a TypeError exception.
   15512   if (bool_trap_result && !value->SameValue(*target_proto)) {
   15513     isolate->Throw(*isolate->factory()->NewTypeError(
   15514         MessageTemplate::kProxySetPrototypeOfNonExtensible));
   15515     return Nothing<bool>();
   15516   }
   15517   // 14. Return true.
   15518   return Just(true);
   15519 }
   15520 
   15521 
   15522 Maybe<bool> JSObject::SetPrototype(Handle<JSObject> object,
   15523                                    Handle<Object> value, bool from_javascript,
   15524                                    ShouldThrow should_throw) {
   15525   Isolate* isolate = object->GetIsolate();
   15526 
   15527 #ifdef DEBUG
   15528   int size = object->Size();
   15529 #endif
   15530 
   15531   if (from_javascript) {
   15532     if (object->IsAccessCheckNeeded() &&
   15533         !isolate->MayAccess(handle(isolate->context(), isolate), object)) {
   15534       isolate->ReportFailedAccessCheck(object);
   15535       RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
   15536       RETURN_FAILURE(isolate, should_throw,
   15537                      NewTypeError(MessageTemplate::kNoAccess));
   15538     }
   15539   } else {
   15540     DCHECK(!object->IsAccessCheckNeeded());
   15541   }
   15542 
   15543   // Silently ignore the change if value is not a JSObject or null.
   15544   // SpiderMonkey behaves this way.
   15545   if (!value->IsJSReceiver() && !value->IsNull(isolate)) return Just(true);
   15546 
   15547   bool all_extensible = object->map()->is_extensible();
   15548   Handle<JSObject> real_receiver = object;
   15549   if (from_javascript) {
   15550     // Find the first object in the chain whose prototype object is not
   15551     // hidden.
   15552     PrototypeIterator iter(isolate, real_receiver, kStartAtPrototype,
   15553                            PrototypeIterator::END_AT_NON_HIDDEN);
   15554     while (!iter.IsAtEnd()) {
   15555       // Casting to JSObject is fine because hidden prototypes are never
   15556       // JSProxies.
   15557       real_receiver = PrototypeIterator::GetCurrent<JSObject>(iter);
   15558       iter.Advance();
   15559       all_extensible = all_extensible && real_receiver->map()->is_extensible();
   15560     }
   15561   }
   15562   Handle<Map> map(real_receiver->map(), isolate);
   15563 
   15564   // Nothing to do if prototype is already set.
   15565   if (map->prototype() == *value) return Just(true);
   15566 
   15567   bool immutable_proto = map->is_immutable_proto();
   15568   if (immutable_proto) {
   15569     RETURN_FAILURE(
   15570         isolate, should_throw,
   15571         NewTypeError(MessageTemplate::kImmutablePrototypeSet, object));
   15572   }
   15573 
   15574   // From 8.6.2 Object Internal Methods
   15575   // ...
   15576   // In addition, if [[Extensible]] is false the value of the [[Class]] and
   15577   // [[Prototype]] internal properties of the object may not be modified.
   15578   // ...
   15579   // Implementation specific extensions that modify [[Class]], [[Prototype]]
   15580   // or [[Extensible]] must not violate the invariants defined in the preceding
   15581   // paragraph.
   15582   if (!all_extensible) {
   15583     RETURN_FAILURE(isolate, should_throw,
   15584                    NewTypeError(MessageTemplate::kNonExtensibleProto, object));
   15585   }
   15586 
   15587   // Before we can set the prototype we need to be sure prototype cycles are
   15588   // prevented.  It is sufficient to validate that the receiver is not in the
   15589   // new prototype chain.
   15590   if (value->IsJSReceiver()) {
   15591     for (PrototypeIterator iter(isolate, JSReceiver::cast(*value),
   15592                                 kStartAtReceiver);
   15593          !iter.IsAtEnd(); iter.Advance()) {
   15594       if (iter.GetCurrent<JSReceiver>() == *object) {
   15595         // Cycle detected.
   15596         RETURN_FAILURE(isolate, should_throw,
   15597                        NewTypeError(MessageTemplate::kCyclicProto));
   15598       }
   15599     }
   15600   }
   15601 
   15602   // Set the new prototype of the object.
   15603 
   15604   isolate->UpdateNoElementsProtectorOnSetPrototype(real_receiver);
   15605 
   15606   Handle<Map> new_map = Map::TransitionToPrototype(isolate, map, value);
   15607   DCHECK(new_map->prototype() == *value);
   15608   JSObject::MigrateToMap(real_receiver, new_map);
   15609 
   15610   DCHECK(size == object->Size());
   15611   return Just(true);
   15612 }
   15613 
   15614 // static
   15615 void JSObject::SetImmutableProto(Handle<JSObject> object) {
   15616   DCHECK(!object->IsAccessCheckNeeded());  // Never called from JS
   15617   Handle<Map> map(object->map(), object->GetIsolate());
   15618 
   15619   // Nothing to do if prototype is already set.
   15620   if (map->is_immutable_proto()) return;
   15621 
   15622   Handle<Map> new_map =
   15623       Map::TransitionToImmutableProto(object->GetIsolate(), map);
   15624   object->synchronized_set_map(*new_map);
   15625 }
   15626 
   15627 void JSObject::EnsureCanContainElements(Handle<JSObject> object,
   15628                                         Arguments* args,
   15629                                         uint32_t first_arg,
   15630                                         uint32_t arg_count,
   15631                                         EnsureElementsMode mode) {
   15632   // Elements in |Arguments| are ordered backwards (because they're on the
   15633   // stack), but the method that's called here iterates over them in forward
   15634   // direction.
   15635   return EnsureCanContainElements(
   15636       object, args->arguments() - first_arg - (arg_count - 1), arg_count, mode);
   15637 }
   15638 
   15639 
   15640 ElementsAccessor* JSObject::GetElementsAccessor() {
   15641   return ElementsAccessor::ForKind(GetElementsKind());
   15642 }
   15643 
   15644 void JSObject::ValidateElements(JSObject* object) {
   15645 #ifdef ENABLE_SLOW_DCHECKS
   15646   if (FLAG_enable_slow_asserts) {
   15647     object->GetElementsAccessor()->Validate(object);
   15648   }
   15649 #endif
   15650 }
   15651 
   15652 
   15653 static bool ShouldConvertToSlowElements(JSObject* object, uint32_t capacity,
   15654                                         uint32_t index,
   15655                                         uint32_t* new_capacity) {
   15656   STATIC_ASSERT(JSObject::kMaxUncheckedOldFastElementsLength <=
   15657                 JSObject::kMaxUncheckedFastElementsLength);
   15658   if (index < capacity) {
   15659     *new_capacity = capacity;
   15660     return false;
   15661   }
   15662   if (index - capacity >= JSObject::kMaxGap) return true;
   15663   *new_capacity = JSObject::NewElementsCapacity(index + 1);
   15664   DCHECK_LT(index, *new_capacity);
   15665   if (*new_capacity <= JSObject::kMaxUncheckedOldFastElementsLength ||
   15666       (*new_capacity <= JSObject::kMaxUncheckedFastElementsLength &&
   15667        Heap::InNewSpace(object))) {
   15668     return false;
   15669   }
   15670   // If the fast-case backing storage takes up much more memory than a
   15671   // dictionary backing storage would, the object should have slow elements.
   15672   int used_elements = object->GetFastElementsUsage();
   15673   uint32_t size_threshold = NumberDictionary::kPreferFastElementsSizeFactor *
   15674                             NumberDictionary::ComputeCapacity(used_elements) *
   15675                             NumberDictionary::kEntrySize;
   15676   return size_threshold <= *new_capacity;
   15677 }
   15678 
   15679 
   15680 bool JSObject::WouldConvertToSlowElements(uint32_t index) {
   15681   if (!HasFastElements()) return false;
   15682   uint32_t capacity = static_cast<uint32_t>(elements()->length());
   15683   uint32_t new_capacity;
   15684   return ShouldConvertToSlowElements(this, capacity, index, &new_capacity);
   15685 }
   15686 
   15687 
   15688 static ElementsKind BestFittingFastElementsKind(JSObject* object) {
   15689   if (!object->map()->CanHaveFastTransitionableElementsKind()) {
   15690     return HOLEY_ELEMENTS;
   15691   }
   15692   if (object->HasSloppyArgumentsElements()) {
   15693     return FAST_SLOPPY_ARGUMENTS_ELEMENTS;
   15694   }
   15695   if (object->HasStringWrapperElements()) {
   15696     return FAST_STRING_WRAPPER_ELEMENTS;
   15697   }
   15698   DCHECK(object->HasDictionaryElements());
   15699   NumberDictionary* dictionary = object->element_dictionary();
   15700   ElementsKind kind = HOLEY_SMI_ELEMENTS;
   15701   for (int i = 0; i < dictionary->Capacity(); i++) {
   15702     Object* key = dictionary->KeyAt(i);
   15703     if (key->IsNumber()) {
   15704       Object* value = dictionary->ValueAt(i);
   15705       if (!value->IsNumber()) return HOLEY_ELEMENTS;
   15706       if (!value->IsSmi()) {
   15707         if (!FLAG_unbox_double_arrays) return HOLEY_ELEMENTS;
   15708         kind = HOLEY_DOUBLE_ELEMENTS;
   15709       }
   15710     }
   15711   }
   15712   return kind;
   15713 }
   15714 
   15715 static bool ShouldConvertToFastElements(JSObject* object,
   15716                                         NumberDictionary* dictionary,
   15717                                         uint32_t index,
   15718                                         uint32_t* new_capacity) {
   15719   // If properties with non-standard attributes or accessors were added, we
   15720   // cannot go back to fast elements.
   15721   if (dictionary->requires_slow_elements()) return false;
   15722 
   15723   // Adding a property with this index will require slow elements.
   15724   if (index >= static_cast<uint32_t>(Smi::kMaxValue)) return false;
   15725 
   15726   if (object->IsJSArray()) {
   15727     Object* length = JSArray::cast(object)->length();
   15728     if (!length->IsSmi()) return false;
   15729     *new_capacity = static_cast<uint32_t>(Smi::ToInt(length));
   15730   } else if (object->IsJSSloppyArgumentsObject()) {
   15731     return false;
   15732   } else {
   15733     *new_capacity = dictionary->max_number_key() + 1;
   15734   }
   15735   *new_capacity = Max(index + 1, *new_capacity);
   15736 
   15737   uint32_t dictionary_size = static_cast<uint32_t>(dictionary->Capacity()) *
   15738                              NumberDictionary::kEntrySize;
   15739 
   15740   // Turn fast if the dictionary only saves 50% space.
   15741   return 2 * dictionary_size >= *new_capacity;
   15742 }
   15743 
   15744 // static
   15745 void JSObject::AddDataElement(Handle<JSObject> object, uint32_t index,
   15746                               Handle<Object> value,
   15747                               PropertyAttributes attributes) {
   15748   DCHECK(object->map()->is_extensible());
   15749 
   15750   Isolate* isolate = object->GetIsolate();
   15751 
   15752   uint32_t old_length = 0;
   15753   uint32_t new_capacity = 0;
   15754 
   15755   if (object->IsJSArray()) {
   15756     CHECK(JSArray::cast(*object)->length()->ToArrayLength(&old_length));
   15757   }
   15758 
   15759   ElementsKind kind = object->GetElementsKind();
   15760   FixedArrayBase* elements = object->elements();
   15761   ElementsKind dictionary_kind = DICTIONARY_ELEMENTS;
   15762   if (IsSloppyArgumentsElementsKind(kind)) {
   15763     elements = SloppyArgumentsElements::cast(elements)->arguments();
   15764     dictionary_kind = SLOW_SLOPPY_ARGUMENTS_ELEMENTS;
   15765   } else if (IsStringWrapperElementsKind(kind)) {
   15766     dictionary_kind = SLOW_STRING_WRAPPER_ELEMENTS;
   15767   }
   15768 
   15769   if (attributes != NONE) {
   15770     kind = dictionary_kind;
   15771   } else if (elements->IsNumberDictionary()) {
   15772     kind = ShouldConvertToFastElements(
   15773                *object, NumberDictionary::cast(elements), index, &new_capacity)
   15774                ? BestFittingFastElementsKind(*object)
   15775                : dictionary_kind;
   15776   } else if (ShouldConvertToSlowElements(
   15777                  *object, static_cast<uint32_t>(elements->length()), index,
   15778                  &new_capacity)) {
   15779     kind = dictionary_kind;
   15780   }
   15781 
   15782   ElementsKind to = value->OptimalElementsKind();
   15783   if (IsHoleyElementsKind(kind) || !object->IsJSArray() || index > old_length) {
   15784     to = GetHoleyElementsKind(to);
   15785     kind = GetHoleyElementsKind(kind);
   15786   }
   15787   to = GetMoreGeneralElementsKind(kind, to);
   15788   ElementsAccessor* accessor = ElementsAccessor::ForKind(to);
   15789   accessor->Add(object, index, value, attributes, new_capacity);
   15790 
   15791   if (object->IsJSArray() && index >= old_length) {
   15792     Handle<Object> new_length =
   15793         isolate->factory()->NewNumberFromUint(index + 1);
   15794     JSArray::cast(*object)->set_length(*new_length);
   15795   }
   15796 }
   15797 
   15798 
   15799 bool JSArray::SetLengthWouldNormalize(uint32_t new_length) {
   15800   if (!HasFastElements()) return false;
   15801   uint32_t capacity = static_cast<uint32_t>(elements()->length());
   15802   uint32_t new_capacity;
   15803   return JSArray::SetLengthWouldNormalize(GetHeap(), new_length) &&
   15804          ShouldConvertToSlowElements(this, capacity, new_length - 1,
   15805                                      &new_capacity);
   15806 }
   15807 
   15808 
   15809 const double AllocationSite::kPretenureRatio = 0.85;
   15810 
   15811 
   15812 void AllocationSite::ResetPretenureDecision() {
   15813   set_pretenure_decision(kUndecided);
   15814   set_memento_found_count(0);
   15815   set_memento_create_count(0);
   15816 }
   15817 
   15818 PretenureFlag AllocationSite::GetPretenureMode() const {
   15819   PretenureDecision mode = pretenure_decision();
   15820   // Zombie objects "decide" to be untenured.
   15821   return mode == kTenure ? TENURED : NOT_TENURED;
   15822 }
   15823 
   15824 bool AllocationSite::IsNested() {
   15825   DCHECK(FLAG_trace_track_allocation_sites);
   15826   Object* current = boilerplate()->GetHeap()->allocation_sites_list();
   15827   while (current->IsAllocationSite()) {
   15828     AllocationSite* current_site = AllocationSite::cast(current);
   15829     if (current_site->nested_site() == this) {
   15830       return true;
   15831     }
   15832     current = current_site->weak_next();
   15833   }
   15834   return false;
   15835 }
   15836 
   15837 template <AllocationSiteUpdateMode update_or_check>
   15838 bool AllocationSite::DigestTransitionFeedback(Handle<AllocationSite> site,
   15839                                               ElementsKind to_kind) {
   15840   Isolate* isolate = site->GetIsolate();
   15841   bool result = false;
   15842 
   15843   if (site->PointsToLiteral() && site->boilerplate()->IsJSArray()) {
   15844     Handle<JSArray> boilerplate(JSArray::cast(site->boilerplate()), isolate);
   15845     ElementsKind kind = boilerplate->GetElementsKind();
   15846     // if kind is holey ensure that to_kind is as well.
   15847     if (IsHoleyElementsKind(kind)) {
   15848       to_kind = GetHoleyElementsKind(to_kind);
   15849     }
   15850     if (IsMoreGeneralElementsKindTransition(kind, to_kind)) {
   15851       // If the array is huge, it's not likely to be defined in a local
   15852       // function, so we shouldn't make new instances of it very often.
   15853       uint32_t length = 0;
   15854       CHECK(boilerplate->length()->ToArrayLength(&length));
   15855       if (length <= kMaximumArrayBytesToPretransition) {
   15856         if (update_or_check == AllocationSiteUpdateMode::kCheckOnly) {
   15857           return true;
   15858         }
   15859         if (FLAG_trace_track_allocation_sites) {
   15860           bool is_nested = site->IsNested();
   15861           PrintF("AllocationSite: JSArray %p boilerplate %supdated %s->%s\n",
   15862                  reinterpret_cast<void*>(*site), is_nested ? "(nested)" : " ",
   15863                  ElementsKindToString(kind), ElementsKindToString(to_kind));
   15864         }
   15865         JSObject::TransitionElementsKind(boilerplate, to_kind);
   15866         site->dependent_code()->DeoptimizeDependentCodeGroup(
   15867             isolate, DependentCode::kAllocationSiteTransitionChangedGroup);
   15868         result = true;
   15869       }
   15870     }
   15871   } else {
   15872     // The AllocationSite is for a constructed Array.
   15873     ElementsKind kind = site->GetElementsKind();
   15874     // if kind is holey ensure that to_kind is as well.
   15875     if (IsHoleyElementsKind(kind)) {
   15876       to_kind = GetHoleyElementsKind(to_kind);
   15877     }
   15878     if (IsMoreGeneralElementsKindTransition(kind, to_kind)) {
   15879       if (update_or_check == AllocationSiteUpdateMode::kCheckOnly) return true;
   15880       if (FLAG_trace_track_allocation_sites) {
   15881         PrintF("AllocationSite: JSArray %p site updated %s->%s\n",
   15882                reinterpret_cast<void*>(*site),
   15883                ElementsKindToString(kind),
   15884                ElementsKindToString(to_kind));
   15885       }
   15886       site->SetElementsKind(to_kind);
   15887       site->dependent_code()->DeoptimizeDependentCodeGroup(
   15888           isolate, DependentCode::kAllocationSiteTransitionChangedGroup);
   15889       result = true;
   15890     }
   15891   }
   15892   return result;
   15893 }
   15894 
   15895 bool AllocationSite::ShouldTrack(ElementsKind from, ElementsKind to) {
   15896   return IsSmiElementsKind(from) &&
   15897          IsMoreGeneralElementsKindTransition(from, to);
   15898 }
   15899 
   15900 const char* AllocationSite::PretenureDecisionName(PretenureDecision decision) {
   15901   switch (decision) {
   15902     case kUndecided: return "undecided";
   15903     case kDontTenure: return "don't tenure";
   15904     case kMaybeTenure: return "maybe tenure";
   15905     case kTenure: return "tenure";
   15906     case kZombie: return "zombie";
   15907     default: UNREACHABLE();
   15908   }
   15909   return nullptr;
   15910 }
   15911 
   15912 template <AllocationSiteUpdateMode update_or_check>
   15913 bool JSObject::UpdateAllocationSite(Handle<JSObject> object,
   15914                                     ElementsKind to_kind) {
   15915   if (!object->IsJSArray()) return false;
   15916 
   15917   if (!Heap::InNewSpace(*object)) return false;
   15918 
   15919   Handle<AllocationSite> site;
   15920   {
   15921     DisallowHeapAllocation no_allocation;
   15922 
   15923     Heap* heap = object->GetHeap();
   15924     AllocationMemento* memento =
   15925         heap->FindAllocationMemento<Heap::kForRuntime>(object->map(), *object);
   15926     if (memento == nullptr) return false;
   15927 
   15928     // Walk through to the Allocation Site
   15929     site = handle(memento->GetAllocationSite(), heap->isolate());
   15930   }
   15931   return AllocationSite::DigestTransitionFeedback<update_or_check>(site,
   15932                                                                    to_kind);
   15933 }
   15934 
   15935 template bool
   15936 JSObject::UpdateAllocationSite<AllocationSiteUpdateMode::kCheckOnly>(
   15937     Handle<JSObject> object, ElementsKind to_kind);
   15938 
   15939 template bool JSObject::UpdateAllocationSite<AllocationSiteUpdateMode::kUpdate>(
   15940     Handle<JSObject> object, ElementsKind to_kind);
   15941 
   15942 void JSObject::TransitionElementsKind(Handle<JSObject> object,
   15943                                       ElementsKind to_kind) {
   15944   ElementsKind from_kind = object->GetElementsKind();
   15945 
   15946   if (IsHoleyElementsKind(from_kind)) {
   15947     to_kind = GetHoleyElementsKind(to_kind);
   15948   }
   15949 
   15950   if (from_kind == to_kind) return;
   15951 
   15952   // This method should never be called for any other case.
   15953   DCHECK(IsFastElementsKind(from_kind));
   15954   DCHECK(IsFastElementsKind(to_kind));
   15955   DCHECK_NE(TERMINAL_FAST_ELEMENTS_KIND, from_kind);
   15956 
   15957   UpdateAllocationSite(object, to_kind);
   15958   if (object->elements() == object->GetReadOnlyRoots().empty_fixed_array() ||
   15959       IsDoubleElementsKind(from_kind) == IsDoubleElementsKind(to_kind)) {
   15960     // No change is needed to the elements() buffer, the transition
   15961     // only requires a map change.
   15962     Handle<Map> new_map = GetElementsTransitionMap(object, to_kind);
   15963     MigrateToMap(object, new_map);
   15964     if (FLAG_trace_elements_transitions) {
   15965       Handle<FixedArrayBase> elms(object->elements(), object->GetIsolate());
   15966       PrintElementsTransition(stdout, object, from_kind, elms, to_kind, elms);
   15967     }
   15968   } else {
   15969     DCHECK((IsSmiElementsKind(from_kind) && IsDoubleElementsKind(to_kind)) ||
   15970            (IsDoubleElementsKind(from_kind) && IsObjectElementsKind(to_kind)));
   15971     uint32_t c = static_cast<uint32_t>(object->elements()->length());
   15972     ElementsAccessor::ForKind(to_kind)->GrowCapacityAndConvert(object, c);
   15973   }
   15974 }
   15975 
   15976 
   15977 // static
   15978 bool Map::IsValidElementsTransition(ElementsKind from_kind,
   15979                                     ElementsKind to_kind) {
   15980   // Transitions can't go backwards.
   15981   if (!IsMoreGeneralElementsKindTransition(from_kind, to_kind)) {
   15982     return false;
   15983   }
   15984 
   15985   // Transitions from HOLEY -> PACKED are not allowed.
   15986   return !IsHoleyElementsKind(from_kind) || IsHoleyElementsKind(to_kind);
   15987 }
   15988 
   15989 
   15990 bool JSArray::HasReadOnlyLength(Handle<JSArray> array) {
   15991   Map* map = array->map();
   15992   // Fast path: "length" is the first fast property of arrays. Since it's not
   15993   // configurable, it's guaranteed to be the first in the descriptor array.
   15994   if (!map->is_dictionary_map()) {
   15995     DCHECK(map->instance_descriptors()->GetKey(0) ==
   15996            array->GetReadOnlyRoots().length_string());
   15997     return map->instance_descriptors()->GetDetails(0).IsReadOnly();
   15998   }
   15999 
   16000   Isolate* isolate = array->GetIsolate();
   16001   LookupIterator it(array, isolate->factory()->length_string(), array,
   16002                     LookupIterator::OWN_SKIP_INTERCEPTOR);
   16003   CHECK_EQ(LookupIterator::ACCESSOR, it.state());
   16004   return it.IsReadOnly();
   16005 }
   16006 
   16007 
   16008 bool JSArray::WouldChangeReadOnlyLength(Handle<JSArray> array,
   16009                                         uint32_t index) {
   16010   uint32_t length = 0;
   16011   CHECK(array->length()->ToArrayLength(&length));
   16012   if (length <= index) return HasReadOnlyLength(array);
   16013   return false;
   16014 }
   16015 
   16016 template <typename BackingStore>
   16017 static int HoleyElementsUsage(JSObject* object, BackingStore* store) {
   16018   Isolate* isolate = object->GetIsolate();
   16019   int limit = object->IsJSArray() ? Smi::ToInt(JSArray::cast(object)->length())
   16020                                   : store->length();
   16021   int used = 0;
   16022   for (int i = 0; i < limit; ++i) {
   16023     if (!store->is_the_hole(isolate, i)) ++used;
   16024   }
   16025   return used;
   16026 }
   16027 
   16028 int JSObject::GetFastElementsUsage() {
   16029   FixedArrayBase* store = elements();
   16030   switch (GetElementsKind()) {
   16031     case PACKED_SMI_ELEMENTS:
   16032     case PACKED_DOUBLE_ELEMENTS:
   16033     case PACKED_ELEMENTS:
   16034       return IsJSArray() ? Smi::ToInt(JSArray::cast(this)->length())
   16035                          : store->length();
   16036     case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
   16037       store = SloppyArgumentsElements::cast(store)->arguments();
   16038       V8_FALLTHROUGH;
   16039     case HOLEY_SMI_ELEMENTS:
   16040     case HOLEY_ELEMENTS:
   16041     case FAST_STRING_WRAPPER_ELEMENTS:
   16042       return HoleyElementsUsage(this, FixedArray::cast(store));
   16043     case HOLEY_DOUBLE_ELEMENTS:
   16044       if (elements()->length() == 0) return 0;
   16045       return HoleyElementsUsage(this, FixedDoubleArray::cast(store));
   16046 
   16047     case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
   16048     case SLOW_STRING_WRAPPER_ELEMENTS:
   16049     case DICTIONARY_ELEMENTS:
   16050     case NO_ELEMENTS:
   16051 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) case TYPE##_ELEMENTS:
   16052 
   16053       TYPED_ARRAYS(TYPED_ARRAY_CASE)
   16054 #undef TYPED_ARRAY_CASE
   16055     UNREACHABLE();
   16056   }
   16057   return 0;
   16058 }
   16059 
   16060 
   16061 // Certain compilers request function template instantiation when they
   16062 // see the definition of the other template functions in the
   16063 // class. This requires us to have the template functions put
   16064 // together, so even though this function belongs in objects-debug.cc,
   16065 // we keep it here instead to satisfy certain compilers.
   16066 #ifdef OBJECT_PRINT
   16067 template <typename Derived, typename Shape>
   16068 void Dictionary<Derived, Shape>::Print(std::ostream& os) {
   16069   DisallowHeapAllocation no_gc;
   16070   ReadOnlyRoots roots = this->GetReadOnlyRoots();
   16071   Derived* dictionary = Derived::cast(this);
   16072   int capacity = dictionary->Capacity();
   16073   for (int i = 0; i < capacity; i++) {
   16074     Object* k = dictionary->KeyAt(i);
   16075     if (!dictionary->ToKey(roots, i, &k)) continue;
   16076     os << "\n   ";
   16077     if (k->IsString()) {
   16078       String::cast(k)->StringPrint(os);
   16079     } else {
   16080       os << Brief(k);
   16081     }
   16082     os << ": " << Brief(dictionary->ValueAt(i)) << " ";
   16083     dictionary->DetailsAt(i).PrintAsSlowTo(os);
   16084   }
   16085 }
   16086 template <typename Derived, typename Shape>
   16087 void Dictionary<Derived, Shape>::Print() {
   16088   StdoutStream os;
   16089   Print(os);
   16090   os << std::endl;
   16091 }
   16092 #endif
   16093 
   16094 
   16095 MaybeHandle<Object> JSObject::GetPropertyWithInterceptor(LookupIterator* it,
   16096                                                          bool* done) {
   16097   DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
   16098   return GetPropertyWithInterceptorInternal(it, it->GetInterceptor(), done);
   16099 }
   16100 
   16101 Maybe<bool> JSObject::HasRealNamedProperty(Handle<JSObject> object,
   16102                                            Handle<Name> name) {
   16103   LookupIterator it = LookupIterator::PropertyOrElement(
   16104       object->GetIsolate(), object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
   16105   return HasProperty(&it);
   16106 }
   16107 
   16108 
   16109 Maybe<bool> JSObject::HasRealElementProperty(Handle<JSObject> object,
   16110                                              uint32_t index) {
   16111   Isolate* isolate = object->GetIsolate();
   16112   LookupIterator it(isolate, object, index, object,
   16113                     LookupIterator::OWN_SKIP_INTERCEPTOR);
   16114   return HasProperty(&it);
   16115 }
   16116 
   16117 
   16118 Maybe<bool> JSObject::HasRealNamedCallbackProperty(Handle<JSObject> object,
   16119                                                    Handle<Name> name) {
   16120   LookupIterator it = LookupIterator::PropertyOrElement(
   16121       object->GetIsolate(), object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
   16122   Maybe<PropertyAttributes> maybe_result = GetPropertyAttributes(&it);
   16123   return maybe_result.IsJust() ? Just(it.state() == LookupIterator::ACCESSOR)
   16124                                : Nothing<bool>();
   16125 }
   16126 
   16127 int FixedArrayBase::GetMaxLengthForNewSpaceAllocation(ElementsKind kind) {
   16128   return ((kMaxRegularHeapObjectSize - FixedArrayBase::kHeaderSize) >>
   16129           ElementsKindToShiftSize(kind));
   16130 }
   16131 
   16132 bool FixedArrayBase::IsCowArray() const {
   16133   return map() == GetReadOnlyRoots().fixed_cow_array_map();
   16134 }
   16135 
   16136 bool JSObject::IsApiWrapper() {
   16137   auto instance_type = map()->instance_type();
   16138   return instance_type == JS_API_OBJECT_TYPE ||
   16139          instance_type == JS_SPECIAL_API_OBJECT_TYPE;
   16140 }
   16141 
   16142 const char* Symbol::PrivateSymbolToName() const {
   16143   ReadOnlyRoots roots = GetReadOnlyRoots();
   16144 #define SYMBOL_CHECK_AND_PRINT(name) \
   16145   if (this == roots.name()) return #name;
   16146   PRIVATE_SYMBOL_LIST(SYMBOL_CHECK_AND_PRINT)
   16147 #undef SYMBOL_CHECK_AND_PRINT
   16148   return "UNKNOWN";
   16149 }
   16150 
   16151 
   16152 void Symbol::SymbolShortPrint(std::ostream& os) {
   16153   os << "<Symbol:";
   16154   if (!name()->IsUndefined()) {
   16155     os << " ";
   16156     HeapStringAllocator allocator;
   16157     StringStream accumulator(&allocator);
   16158     String::cast(name())->StringShortPrint(&accumulator, false);
   16159     os << accumulator.ToCString().get();
   16160   } else {
   16161     os << " (" << PrivateSymbolToName() << ")";
   16162   }
   16163   os << ">";
   16164 }
   16165 
   16166 
   16167 // StringSharedKeys are used as keys in the eval cache.
   16168 class StringSharedKey : public HashTableKey {
   16169  public:
   16170   // This tuple unambiguously identifies calls to eval() or
   16171   // CreateDynamicFunction() (such as through the Function() constructor).
   16172   // * source is the string passed into eval(). For dynamic functions, this is
   16173   //   the effective source for the function, some of which is implicitly
   16174   //   generated.
   16175   // * shared is the shared function info for the function containing the call
   16176   //   to eval(). for dynamic functions, shared is the native context closure.
   16177   // * When positive, position is the position in the source where eval is
   16178   //   called. When negative, position is the negation of the position in the
   16179   //   dynamic function's effective source where the ')' ends the parameters.
   16180   StringSharedKey(Handle<String> source, Handle<SharedFunctionInfo> shared,
   16181                   LanguageMode language_mode, int position)
   16182       : HashTableKey(CompilationCacheShape::StringSharedHash(
   16183             *source, *shared, language_mode, position)),
   16184         source_(source),
   16185         shared_(shared),
   16186         language_mode_(language_mode),
   16187         position_(position) {}
   16188 
   16189   bool IsMatch(Object* other) override {
   16190     DisallowHeapAllocation no_allocation;
   16191     if (!other->IsFixedArray()) {
   16192       DCHECK(other->IsNumber());
   16193       uint32_t other_hash = static_cast<uint32_t>(other->Number());
   16194       return Hash() == other_hash;
   16195     }
   16196     FixedArray* other_array = FixedArray::cast(other);
   16197     SharedFunctionInfo* shared = SharedFunctionInfo::cast(other_array->get(0));
   16198     if (shared != *shared_) return false;
   16199     int language_unchecked = Smi::ToInt(other_array->get(2));
   16200     DCHECK(is_valid_language_mode(language_unchecked));
   16201     LanguageMode language_mode = static_cast<LanguageMode>(language_unchecked);
   16202     if (language_mode != language_mode_) return false;
   16203     int position = Smi::ToInt(other_array->get(3));
   16204     if (position != position_) return false;
   16205     String* source = String::cast(other_array->get(1));
   16206     return source->Equals(*source_);
   16207   }
   16208 
   16209   Handle<Object> AsHandle(Isolate* isolate) {
   16210     Handle<FixedArray> array = isolate->factory()->NewFixedArray(4);
   16211     array->set(0, *shared_);
   16212     array->set(1, *source_);
   16213     array->set(2, Smi::FromEnum(language_mode_));
   16214     array->set(3, Smi::FromInt(position_));
   16215     array->set_map(ReadOnlyRoots(isolate).fixed_cow_array_map());
   16216     return array;
   16217   }
   16218 
   16219  private:
   16220   Handle<String> source_;
   16221   Handle<SharedFunctionInfo> shared_;
   16222   LanguageMode language_mode_;
   16223   int position_;
   16224 };
   16225 
   16226 v8::Promise::PromiseState JSPromise::status() const {
   16227   int value = flags() & kStatusMask;
   16228   DCHECK(value == 0 || value == 1 || value == 2);
   16229   return static_cast<v8::Promise::PromiseState>(value);
   16230 }
   16231 
   16232 void JSPromise::set_status(Promise::PromiseState status) {
   16233   int value = flags() & ~kStatusMask;
   16234   set_flags(value | status);
   16235 }
   16236 
   16237 // static
   16238 const char* JSPromise::Status(v8::Promise::PromiseState status) {
   16239   switch (status) {
   16240     case v8::Promise::kFulfilled:
   16241       return "resolved";
   16242     case v8::Promise::kPending:
   16243       return "pending";
   16244     case v8::Promise::kRejected:
   16245       return "rejected";
   16246   }
   16247   UNREACHABLE();
   16248 }
   16249 
   16250 int JSPromise::async_task_id() const {
   16251   return AsyncTaskIdField::decode(flags());
   16252 }
   16253 
   16254 void JSPromise::set_async_task_id(int id) {
   16255   set_flags(AsyncTaskIdField::update(flags(), id));
   16256 }
   16257 
   16258 // static
   16259 Handle<Object> JSPromise::Fulfill(Handle<JSPromise> promise,
   16260                                   Handle<Object> value) {
   16261   Isolate* const isolate = promise->GetIsolate();
   16262 
   16263   // 1. Assert: The value of promise.[[PromiseState]] is "pending".
   16264   DCHECK_EQ(Promise::kPending, promise->status());
   16265 
   16266   // 2. Let reactions be promise.[[PromiseFulfillReactions]].
   16267   Handle<Object> reactions(promise->reactions(), isolate);
   16268 
   16269   // 3. Set promise.[[PromiseResult]] to value.
   16270   // 4. Set promise.[[PromiseFulfillReactions]] to undefined.
   16271   // 5. Set promise.[[PromiseRejectReactions]] to undefined.
   16272   promise->set_reactions_or_result(*value);
   16273 
   16274   // 6. Set promise.[[PromiseState]] to "fulfilled".
   16275   promise->set_status(Promise::kFulfilled);
   16276 
   16277   // 7. Return TriggerPromiseReactions(reactions, value).
   16278   return TriggerPromiseReactions(isolate, reactions, value,
   16279                                  PromiseReaction::kFulfill);
   16280 }
   16281 
   16282 // static
   16283 Handle<Object> JSPromise::Reject(Handle<JSPromise> promise,
   16284                                  Handle<Object> reason, bool debug_event) {
   16285   Isolate* const isolate = promise->GetIsolate();
   16286 
   16287   if (debug_event) isolate->debug()->OnPromiseReject(promise, reason);
   16288   isolate->RunPromiseHook(PromiseHookType::kResolve, promise,
   16289                           isolate->factory()->undefined_value());
   16290 
   16291   // 1. Assert: The value of promise.[[PromiseState]] is "pending".
   16292   DCHECK_EQ(Promise::kPending, promise->status());
   16293 
   16294   // 2. Let reactions be promise.[[PromiseRejectReactions]].
   16295   Handle<Object> reactions(promise->reactions(), isolate);
   16296 
   16297   // 3. Set promise.[[PromiseResult]] to reason.
   16298   // 4. Set promise.[[PromiseFulfillReactions]] to undefined.
   16299   // 5. Set promise.[[PromiseRejectReactions]] to undefined.
   16300   promise->set_reactions_or_result(*reason);
   16301 
   16302   // 6. Set promise.[[PromiseState]] to "rejected".
   16303   promise->set_status(Promise::kRejected);
   16304 
   16305   // 7. If promise.[[PromiseIsHandled]] is false, perform
   16306   //    HostPromiseRejectionTracker(promise, "reject").
   16307   if (!promise->has_handler()) {
   16308     isolate->ReportPromiseReject(promise, reason, kPromiseRejectWithNoHandler);
   16309   }
   16310 
   16311   // 8. Return TriggerPromiseReactions(reactions, reason).
   16312   return TriggerPromiseReactions(isolate, reactions, reason,
   16313                                  PromiseReaction::kReject);
   16314 }
   16315 
   16316 // static
   16317 MaybeHandle<Object> JSPromise::Resolve(Handle<JSPromise> promise,
   16318                                        Handle<Object> resolution) {
   16319   Isolate* const isolate = promise->GetIsolate();
   16320 
   16321   isolate->RunPromiseHook(PromiseHookType::kResolve, promise,
   16322                           isolate->factory()->undefined_value());
   16323 
   16324   // 6. If SameValue(resolution, promise) is true, then
   16325   if (promise.is_identical_to(resolution)) {
   16326     // a. Let selfResolutionError be a newly created TypeError object.
   16327     Handle<Object> self_resolution_error = isolate->factory()->NewTypeError(
   16328         MessageTemplate::kPromiseCyclic, resolution);
   16329     // b. Return RejectPromise(promise, selfResolutionError).
   16330     return Reject(promise, self_resolution_error);
   16331   }
   16332 
   16333   // 7. If Type(resolution) is not Object, then
   16334   if (!resolution->IsJSReceiver()) {
   16335     // a. Return FulfillPromise(promise, resolution).
   16336     return Fulfill(promise, resolution);
   16337   }
   16338 
   16339   // 8. Let then be Get(resolution, "then").
   16340   MaybeHandle<Object> then;
   16341   if (isolate->IsPromiseThenLookupChainIntact(
   16342           Handle<JSReceiver>::cast(resolution))) {
   16343     // We can skip the "then" lookup on {resolution} if its [[Prototype]]
   16344     // is the (initial) Promise.prototype and the Promise#then protector
   16345     // is intact, as that guards the lookup path for the "then" property
   16346     // on JSPromise instances which have the (initial) %PromisePrototype%.
   16347     then = isolate->promise_then();
   16348   } else {
   16349     then =
   16350         JSReceiver::GetProperty(isolate, Handle<JSReceiver>::cast(resolution),
   16351                                 isolate->factory()->then_string());
   16352   }
   16353 
   16354   // 9. If then is an abrupt completion, then
   16355   Handle<Object> then_action;
   16356   if (!then.ToHandle(&then_action)) {
   16357     // a. Return RejectPromise(promise, then.[[Value]]).
   16358     Handle<Object> reason(isolate->pending_exception(), isolate);
   16359     isolate->clear_pending_exception();
   16360     return Reject(promise, reason, false);
   16361   }
   16362 
   16363   // 10. Let thenAction be then.[[Value]].
   16364   // 11. If IsCallable(thenAction) is false, then
   16365   if (!then_action->IsCallable()) {
   16366     // a. Return FulfillPromise(promise, resolution).
   16367     return Fulfill(promise, resolution);
   16368   }
   16369 
   16370   // 12. Perform EnqueueJob("PromiseJobs", PromiseResolveThenableJob,
   16371   //                        promise, resolution, thenAction).
   16372   Handle<PromiseResolveThenableJobTask> task =
   16373       isolate->factory()->NewPromiseResolveThenableJobTask(
   16374           promise, Handle<JSReceiver>::cast(then_action),
   16375           Handle<JSReceiver>::cast(resolution), isolate->native_context());
   16376   if (isolate->debug()->is_active() && resolution->IsJSPromise()) {
   16377     // Mark the dependency of the new {promise} on the {resolution}.
   16378     Object::SetProperty(isolate, resolution,
   16379                         isolate->factory()->promise_handled_by_symbol(),
   16380                         promise, LanguageMode::kStrict)
   16381         .Check();
   16382   }
   16383   isolate->EnqueueMicrotask(task);
   16384 
   16385   // 13. Return undefined.
   16386   return isolate->factory()->undefined_value();
   16387 }
   16388 
   16389 // static
   16390 Handle<Object> JSPromise::TriggerPromiseReactions(Isolate* isolate,
   16391                                                   Handle<Object> reactions,
   16392                                                   Handle<Object> argument,
   16393                                                   PromiseReaction::Type type) {
   16394   DCHECK(reactions->IsSmi() || reactions->IsPromiseReaction());
   16395 
   16396   // We need to reverse the {reactions} here, since we record them
   16397   // on the JSPromise in the reverse order.
   16398   {
   16399     DisallowHeapAllocation no_gc;
   16400     Object* current = *reactions;
   16401     Object* reversed = Smi::kZero;
   16402     while (!current->IsSmi()) {
   16403       Object* next = PromiseReaction::cast(current)->next();
   16404       PromiseReaction::cast(current)->set_next(reversed);
   16405       reversed = current;
   16406       current = next;
   16407     }
   16408     reactions = handle(reversed, isolate);
   16409   }
   16410 
   16411   // Morph the {reactions} into PromiseReactionJobTasks
   16412   // and push them onto the microtask queue.
   16413   while (!reactions->IsSmi()) {
   16414     Handle<HeapObject> task = Handle<HeapObject>::cast(reactions);
   16415     Handle<PromiseReaction> reaction = Handle<PromiseReaction>::cast(task);
   16416     reactions = handle(reaction->next(), isolate);
   16417 
   16418     STATIC_ASSERT(PromiseReaction::kSize == PromiseReactionJobTask::kSize);
   16419     if (type == PromiseReaction::kFulfill) {
   16420       task->synchronized_set_map(
   16421           ReadOnlyRoots(isolate).promise_fulfill_reaction_job_task_map());
   16422       Handle<PromiseFulfillReactionJobTask>::cast(task)->set_argument(
   16423           *argument);
   16424       Handle<PromiseFulfillReactionJobTask>::cast(task)->set_context(
   16425           *isolate->native_context());
   16426       STATIC_ASSERT(PromiseReaction::kFulfillHandlerOffset ==
   16427                     PromiseFulfillReactionJobTask::kHandlerOffset);
   16428       STATIC_ASSERT(PromiseReaction::kPromiseOrCapabilityOffset ==
   16429                     PromiseFulfillReactionJobTask::kPromiseOrCapabilityOffset);
   16430     } else {
   16431       DisallowHeapAllocation no_gc;
   16432       HeapObject* handler = reaction->reject_handler();
   16433       task->synchronized_set_map(
   16434           ReadOnlyRoots(isolate).promise_reject_reaction_job_task_map());
   16435       Handle<PromiseRejectReactionJobTask>::cast(task)->set_argument(*argument);
   16436       Handle<PromiseRejectReactionJobTask>::cast(task)->set_context(
   16437           *isolate->native_context());
   16438       Handle<PromiseRejectReactionJobTask>::cast(task)->set_handler(handler);
   16439       STATIC_ASSERT(PromiseReaction::kPromiseOrCapabilityOffset ==
   16440                     PromiseRejectReactionJobTask::kPromiseOrCapabilityOffset);
   16441     }
   16442 
   16443     isolate->EnqueueMicrotask(Handle<PromiseReactionJobTask>::cast(task));
   16444   }
   16445 
   16446   return isolate->factory()->undefined_value();
   16447 }
   16448 
   16449 namespace {
   16450 
   16451 JSRegExp::Flags RegExpFlagsFromString(Handle<String> flags, bool* success) {
   16452   JSRegExp::Flags value = JSRegExp::kNone;
   16453   int length = flags->length();
   16454   // A longer flags string cannot be valid.
   16455   if (length > JSRegExp::FlagCount()) return JSRegExp::Flags(0);
   16456   for (int i = 0; i < length; i++) {
   16457     JSRegExp::Flag flag = JSRegExp::kNone;
   16458     switch (flags->Get(i)) {
   16459       case 'g':
   16460         flag = JSRegExp::kGlobal;
   16461         break;
   16462       case 'i':
   16463         flag = JSRegExp::kIgnoreCase;
   16464         break;
   16465       case 'm':
   16466         flag = JSRegExp::kMultiline;
   16467         break;
   16468       case 's':
   16469         flag = JSRegExp::kDotAll;
   16470         break;
   16471       case 'u':
   16472         flag = JSRegExp::kUnicode;
   16473         break;
   16474       case 'y':
   16475         flag = JSRegExp::kSticky;
   16476         break;
   16477       default:
   16478         return JSRegExp::Flags(0);
   16479     }
   16480     // Duplicate flag.
   16481     if (value & flag) return JSRegExp::Flags(0);
   16482     value |= flag;
   16483   }
   16484   *success = true;
   16485   return value;
   16486 }
   16487 
   16488 }  // namespace
   16489 
   16490 
   16491 // static
   16492 MaybeHandle<JSRegExp> JSRegExp::New(Isolate* isolate, Handle<String> pattern,
   16493                                     Flags flags) {
   16494   Handle<JSFunction> constructor = isolate->regexp_function();
   16495   Handle<JSRegExp> regexp =
   16496       Handle<JSRegExp>::cast(isolate->factory()->NewJSObject(constructor));
   16497 
   16498   return JSRegExp::Initialize(regexp, pattern, flags);
   16499 }
   16500 
   16501 
   16502 // static
   16503 Handle<JSRegExp> JSRegExp::Copy(Handle<JSRegExp> regexp) {
   16504   Isolate* const isolate = regexp->GetIsolate();
   16505   return Handle<JSRegExp>::cast(isolate->factory()->CopyJSObject(regexp));
   16506 }
   16507 
   16508 
   16509 template <typename Char>
   16510 inline int CountRequiredEscapes(Handle<String> source) {
   16511   DisallowHeapAllocation no_gc;
   16512   int escapes = 0;
   16513   Vector<const Char> src = source->GetCharVector<Char>();
   16514   for (int i = 0; i < src.length(); i++) {
   16515     if (src[i] == '\\') {
   16516       // Escape. Skip next character;
   16517       i++;
   16518     } else if (src[i] == '/') {
   16519       // Not escaped forward-slash needs escape.
   16520       escapes++;
   16521     }
   16522   }
   16523   return escapes;
   16524 }
   16525 
   16526 
   16527 template <typename Char, typename StringType>
   16528 inline Handle<StringType> WriteEscapedRegExpSource(Handle<String> source,
   16529                                                    Handle<StringType> result) {
   16530   DisallowHeapAllocation no_gc;
   16531   Vector<const Char> src = source->GetCharVector<Char>();
   16532   Vector<Char> dst(result->GetChars(), result->length());
   16533   int s = 0;
   16534   int d = 0;
   16535   while (s < src.length()) {
   16536     if (src[s] == '\\') {
   16537       // Escape. Copy this and next character.
   16538       dst[d++] = src[s++];
   16539       if (s == src.length()) break;
   16540     } else if (src[s] == '/') {
   16541       // Not escaped forward-slash needs escape.
   16542       dst[d++] = '\\';
   16543     }
   16544     dst[d++] = src[s++];
   16545   }
   16546   DCHECK_EQ(result->length(), d);
   16547   return result;
   16548 }
   16549 
   16550 
   16551 MaybeHandle<String> EscapeRegExpSource(Isolate* isolate,
   16552                                        Handle<String> source) {
   16553   DCHECK(source->IsFlat());
   16554   if (source->length() == 0) return isolate->factory()->query_colon_string();
   16555   bool one_byte = source->IsOneByteRepresentationUnderneath();
   16556   int escapes = one_byte ? CountRequiredEscapes<uint8_t>(source)
   16557                          : CountRequiredEscapes<uc16>(source);
   16558   if (escapes == 0) return source;
   16559   int length = source->length() + escapes;
   16560   if (one_byte) {
   16561     Handle<SeqOneByteString> result;
   16562     ASSIGN_RETURN_ON_EXCEPTION(isolate, result,
   16563                                isolate->factory()->NewRawOneByteString(length),
   16564                                String);
   16565     return WriteEscapedRegExpSource<uint8_t>(source, result);
   16566   } else {
   16567     Handle<SeqTwoByteString> result;
   16568     ASSIGN_RETURN_ON_EXCEPTION(isolate, result,
   16569                                isolate->factory()->NewRawTwoByteString(length),
   16570                                String);
   16571     return WriteEscapedRegExpSource<uc16>(source, result);
   16572   }
   16573 }
   16574 
   16575 
   16576 // static
   16577 MaybeHandle<JSRegExp> JSRegExp::Initialize(Handle<JSRegExp> regexp,
   16578                                            Handle<String> source,
   16579                                            Handle<String> flags_string) {
   16580   Isolate* isolate = regexp->GetIsolate();
   16581   bool success = false;
   16582   Flags flags = RegExpFlagsFromString(flags_string, &success);
   16583   if (!success) {
   16584     THROW_NEW_ERROR(
   16585         isolate,
   16586         NewSyntaxError(MessageTemplate::kInvalidRegExpFlags, flags_string),
   16587         JSRegExp);
   16588   }
   16589   return Initialize(regexp, source, flags);
   16590 }
   16591 
   16592 
   16593 // static
   16594 MaybeHandle<JSRegExp> JSRegExp::Initialize(Handle<JSRegExp> regexp,
   16595                                            Handle<String> source, Flags flags) {
   16596   Isolate* isolate = regexp->GetIsolate();
   16597   Factory* factory = isolate->factory();
   16598   // If source is the empty string we set it to "(?:)" instead as
   16599   // suggested by ECMA-262, 5th, section 15.10.4.1.
   16600   if (source->length() == 0) source = factory->query_colon_string();
   16601 
   16602   source = String::Flatten(isolate, source);
   16603 
   16604   Handle<String> escaped_source;
   16605   ASSIGN_RETURN_ON_EXCEPTION(isolate, escaped_source,
   16606                              EscapeRegExpSource(isolate, source), JSRegExp);
   16607 
   16608   RETURN_ON_EXCEPTION(
   16609       isolate, RegExpImpl::Compile(isolate, regexp, source, flags), JSRegExp);
   16610 
   16611   regexp->set_source(*escaped_source);
   16612   regexp->set_flags(Smi::FromInt(flags));
   16613 
   16614   Map* map = regexp->map();
   16615   Object* constructor = map->GetConstructor();
   16616   if (constructor->IsJSFunction() &&
   16617       JSFunction::cast(constructor)->initial_map() == map) {
   16618     // If we still have the original map, set in-object properties directly.
   16619     regexp->InObjectPropertyAtPut(JSRegExp::kLastIndexFieldIndex, Smi::kZero,
   16620                                   SKIP_WRITE_BARRIER);
   16621   } else {
   16622     // Map has changed, so use generic, but slower, method.
   16623     RETURN_ON_EXCEPTION(
   16624         isolate,
   16625         JSReceiver::SetProperty(isolate, regexp, factory->lastIndex_string(),
   16626                                 Handle<Smi>(Smi::kZero, isolate),
   16627                                 LanguageMode::kStrict),
   16628         JSRegExp);
   16629   }
   16630 
   16631   return regexp;
   16632 }
   16633 
   16634 
   16635 // RegExpKey carries the source and flags of a regular expression as key.
   16636 class RegExpKey : public HashTableKey {
   16637  public:
   16638   RegExpKey(Handle<String> string, JSRegExp::Flags flags)
   16639       : HashTableKey(
   16640             CompilationCacheShape::RegExpHash(*string, Smi::FromInt(flags))),
   16641         string_(string),
   16642         flags_(Smi::FromInt(flags)) {}
   16643 
   16644   // Rather than storing the key in the hash table, a pointer to the
   16645   // stored value is stored where the key should be.  IsMatch then
   16646   // compares the search key to the found object, rather than comparing
   16647   // a key to a key.
   16648   bool IsMatch(Object* obj) override {
   16649     FixedArray* val = FixedArray::cast(obj);
   16650     return string_->Equals(String::cast(val->get(JSRegExp::kSourceIndex)))
   16651         && (flags_ == val->get(JSRegExp::kFlagsIndex));
   16652   }
   16653 
   16654   Handle<String> string_;
   16655   Smi* flags_;
   16656 };
   16657 
   16658 Handle<String> OneByteStringKey::AsHandle(Isolate* isolate) {
   16659   return isolate->factory()->NewOneByteInternalizedString(string_, HashField());
   16660 }
   16661 
   16662 Handle<String> TwoByteStringKey::AsHandle(Isolate* isolate) {
   16663   return isolate->factory()->NewTwoByteInternalizedString(string_, HashField());
   16664 }
   16665 
   16666 Handle<String> SeqOneByteSubStringKey::AsHandle(Isolate* isolate) {
   16667   return isolate->factory()->NewOneByteInternalizedSubString(
   16668       string_, from_, length_, HashField());
   16669 }
   16670 
   16671 
   16672 bool SeqOneByteSubStringKey::IsMatch(Object* string) {
   16673   Vector<const uint8_t> chars(string_->GetChars() + from_, length_);
   16674   return String::cast(string)->IsOneByteEqualTo(chars);
   16675 }
   16676 
   16677 
   16678 // InternalizedStringKey carries a string/internalized-string object as key.
   16679 class InternalizedStringKey : public StringTableKey {
   16680  public:
   16681   explicit InternalizedStringKey(Handle<String> string)
   16682       : StringTableKey(0), string_(string) {
   16683     DCHECK(!string->IsInternalizedString());
   16684     DCHECK(string->IsFlat());
   16685     // Make sure hash_field is computed.
   16686     string->Hash();
   16687     set_hash_field(string->hash_field());
   16688   }
   16689 
   16690   bool IsMatch(Object* string) override {
   16691     return string_->SlowEquals(String::cast(string));
   16692   }
   16693 
   16694   Handle<String> AsHandle(Isolate* isolate) override {
   16695     // Internalize the string if possible.
   16696     MaybeHandle<Map> maybe_map =
   16697         isolate->factory()->InternalizedStringMapForString(string_);
   16698     Handle<Map> map;
   16699     if (maybe_map.ToHandle(&map)) {
   16700       string_->set_map_no_write_barrier(*map);
   16701       DCHECK(string_->IsInternalizedString());
   16702       return string_;
   16703     }
   16704     if (FLAG_thin_strings) {
   16705       // External strings get special treatment, to avoid copying their
   16706       // contents.
   16707       if (string_->IsExternalOneByteString()) {
   16708         return isolate->factory()
   16709             ->InternalizeExternalString<ExternalOneByteString>(string_);
   16710       } else if (string_->IsExternalTwoByteString()) {
   16711         return isolate->factory()
   16712             ->InternalizeExternalString<ExternalTwoByteString>(string_);
   16713       }
   16714     }
   16715     // Otherwise allocate a new internalized string.
   16716     return isolate->factory()->NewInternalizedStringImpl(
   16717         string_, string_->length(), string_->hash_field());
   16718   }
   16719 
   16720  private:
   16721   Handle<String> string_;
   16722 };
   16723 
   16724 template <typename Derived, typename Shape>
   16725 void HashTable<Derived, Shape>::IteratePrefix(ObjectVisitor* v) {
   16726   BodyDescriptorBase::IteratePointers(this, 0, kElementsStartOffset, v);
   16727 }
   16728 
   16729 template <typename Derived, typename Shape>
   16730 void HashTable<Derived, Shape>::IterateElements(ObjectVisitor* v) {
   16731   BodyDescriptorBase::IteratePointers(this, kElementsStartOffset,
   16732                                       kHeaderSize + length() * kPointerSize, v);
   16733 }
   16734 
   16735 template <typename Derived, typename Shape>
   16736 Handle<Derived> HashTable<Derived, Shape>::New(
   16737     Isolate* isolate, int at_least_space_for, PretenureFlag pretenure,
   16738     MinimumCapacity capacity_option) {
   16739   DCHECK_LE(0, at_least_space_for);
   16740   DCHECK_IMPLIES(capacity_option == USE_CUSTOM_MINIMUM_CAPACITY,
   16741                  base::bits::IsPowerOfTwo(at_least_space_for));
   16742 
   16743   int capacity = (capacity_option == USE_CUSTOM_MINIMUM_CAPACITY)
   16744                      ? at_least_space_for
   16745                      : ComputeCapacity(at_least_space_for);
   16746   if (capacity > HashTable::kMaxCapacity) {
   16747     isolate->heap()->FatalProcessOutOfMemory("invalid table size");
   16748   }
   16749   return NewInternal(isolate, capacity, pretenure);
   16750 }
   16751 
   16752 template <typename Derived, typename Shape>
   16753 Handle<Derived> HashTable<Derived, Shape>::NewInternal(
   16754     Isolate* isolate, int capacity, PretenureFlag pretenure) {
   16755   Factory* factory = isolate->factory();
   16756   int length = EntryToIndex(capacity);
   16757   Heap::RootListIndex map_root_index =
   16758       static_cast<Heap::RootListIndex>(Shape::GetMapRootIndex());
   16759   Handle<FixedArray> array =
   16760       factory->NewFixedArrayWithMap(map_root_index, length, pretenure);
   16761   Handle<Derived> table = Handle<Derived>::cast(array);
   16762 
   16763   table->SetNumberOfElements(0);
   16764   table->SetNumberOfDeletedElements(0);
   16765   table->SetCapacity(capacity);
   16766   return table;
   16767 }
   16768 
   16769 template <typename Derived, typename Shape>
   16770 void HashTable<Derived, Shape>::Rehash(Isolate* isolate, Derived* new_table) {
   16771   DisallowHeapAllocation no_gc;
   16772   WriteBarrierMode mode = new_table->GetWriteBarrierMode(no_gc);
   16773 
   16774   DCHECK_LT(NumberOfElements(), new_table->Capacity());
   16775 
   16776   // Copy prefix to new array.
   16777   for (int i = kPrefixStartIndex; i < kElementsStartIndex; i++) {
   16778     new_table->set(i, get(i), mode);
   16779   }
   16780 
   16781   // Rehash the elements.
   16782   int capacity = this->Capacity();
   16783   ReadOnlyRoots roots(isolate);
   16784   for (int i = 0; i < capacity; i++) {
   16785     uint32_t from_index = EntryToIndex(i);
   16786     Object* k = this->get(from_index);
   16787     if (!Shape::IsLive(roots, k)) continue;
   16788     uint32_t hash = Shape::HashForObject(isolate, k);
   16789     uint32_t insertion_index =
   16790         EntryToIndex(new_table->FindInsertionEntry(hash));
   16791     for (int j = 0; j < Shape::kEntrySize; j++) {
   16792       new_table->set(insertion_index + j, get(from_index + j), mode);
   16793     }
   16794   }
   16795   new_table->SetNumberOfElements(NumberOfElements());
   16796   new_table->SetNumberOfDeletedElements(0);
   16797 }
   16798 
   16799 template <typename Derived, typename Shape>
   16800 uint32_t HashTable<Derived, Shape>::EntryForProbe(Isolate* isolate, Object* k,
   16801                                                   int probe,
   16802                                                   uint32_t expected) {
   16803   uint32_t hash = Shape::HashForObject(isolate, k);
   16804   uint32_t capacity = this->Capacity();
   16805   uint32_t entry = FirstProbe(hash, capacity);
   16806   for (int i = 1; i < probe; i++) {
   16807     if (entry == expected) return expected;
   16808     entry = NextProbe(entry, i, capacity);
   16809   }
   16810   return entry;
   16811 }
   16812 
   16813 template <typename Derived, typename Shape>
   16814 void HashTable<Derived, Shape>::Swap(uint32_t entry1, uint32_t entry2,
   16815                                      WriteBarrierMode mode) {
   16816   int index1 = EntryToIndex(entry1);
   16817   int index2 = EntryToIndex(entry2);
   16818   Object* temp[Shape::kEntrySize];
   16819   for (int j = 0; j < Shape::kEntrySize; j++) {
   16820     temp[j] = get(index1 + j);
   16821   }
   16822   for (int j = 0; j < Shape::kEntrySize; j++) {
   16823     set(index1 + j, get(index2 + j), mode);
   16824   }
   16825   for (int j = 0; j < Shape::kEntrySize; j++) {
   16826     set(index2 + j, temp[j], mode);
   16827   }
   16828 }
   16829 
   16830 template <typename Derived, typename Shape>
   16831 void HashTable<Derived, Shape>::Rehash(Isolate* isolate) {
   16832   DisallowHeapAllocation no_gc;
   16833   WriteBarrierMode mode = GetWriteBarrierMode(no_gc);
   16834   ReadOnlyRoots roots(isolate);
   16835   uint32_t capacity = Capacity();
   16836   bool done = false;
   16837   for (int probe = 1; !done; probe++) {
   16838     // All elements at entries given by one of the first _probe_ probes
   16839     // are placed correctly. Other elements might need to be moved.
   16840     done = true;
   16841     for (uint32_t current = 0; current < capacity; current++) {
   16842       Object* current_key = KeyAt(current);
   16843       if (!Shape::IsLive(roots, current_key)) continue;
   16844       uint32_t target = EntryForProbe(isolate, current_key, probe, current);
   16845       if (current == target) continue;
   16846       Object* target_key = KeyAt(target);
   16847       if (!Shape::IsLive(roots, target_key) ||
   16848           EntryForProbe(isolate, target_key, probe, target) != target) {
   16849         // Put the current element into the correct position.
   16850         Swap(current, target, mode);
   16851         // The other element will be processed on the next iteration.
   16852         current--;
   16853       } else {
   16854         // The place for the current element is occupied. Leave the element
   16855         // for the next probe.
   16856         done = false;
   16857       }
   16858     }
   16859   }
   16860   // Wipe deleted entries.
   16861   Object* the_hole = roots.the_hole_value();
   16862   Object* undefined = roots.undefined_value();
   16863   for (uint32_t current = 0; current < capacity; current++) {
   16864     if (KeyAt(current) == the_hole) {
   16865       set(EntryToIndex(current) + kEntryKeyIndex, undefined);
   16866     }
   16867   }
   16868   SetNumberOfDeletedElements(0);
   16869 }
   16870 
   16871 template <typename Derived, typename Shape>
   16872 Handle<Derived> HashTable<Derived, Shape>::EnsureCapacity(
   16873     Isolate* isolate, Handle<Derived> table, int n, PretenureFlag pretenure) {
   16874   if (table->HasSufficientCapacityToAdd(n)) return table;
   16875 
   16876   int capacity = table->Capacity();
   16877   int new_nof = table->NumberOfElements() + n;
   16878 
   16879   const int kMinCapacityForPretenure = 256;
   16880   bool should_pretenure =
   16881       pretenure == TENURED ||
   16882       ((capacity > kMinCapacityForPretenure) && !Heap::InNewSpace(*table));
   16883   Handle<Derived> new_table = HashTable::New(
   16884       isolate, new_nof, should_pretenure ? TENURED : NOT_TENURED);
   16885 
   16886   table->Rehash(isolate, *new_table);
   16887   return new_table;
   16888 }
   16889 
   16890 template bool
   16891 HashTable<NameDictionary, NameDictionaryShape>::HasSufficientCapacityToAdd(int);
   16892 
   16893 template <typename Derived, typename Shape>
   16894 bool HashTable<Derived, Shape>::HasSufficientCapacityToAdd(
   16895     int number_of_additional_elements) {
   16896   int capacity = Capacity();
   16897   int nof = NumberOfElements() + number_of_additional_elements;
   16898   int nod = NumberOfDeletedElements();
   16899   // Return true if:
   16900   //   50% is still free after adding number_of_additional_elements elements and
   16901   //   at most 50% of the free elements are deleted elements.
   16902   if ((nof < capacity) && ((nod <= (capacity - nof) >> 1))) {
   16903     int needed_free = nof >> 1;
   16904     if (nof + needed_free <= capacity) return true;
   16905   }
   16906   return false;
   16907 }
   16908 
   16909 template <typename Derived, typename Shape>
   16910 Handle<Derived> HashTable<Derived, Shape>::Shrink(Isolate* isolate,
   16911                                                   Handle<Derived> table,
   16912                                                   int additionalCapacity) {
   16913   int capacity = table->Capacity();
   16914   int nof = table->NumberOfElements();
   16915 
   16916   // Shrink to fit the number of elements if only a quarter of the
   16917   // capacity is filled with elements.
   16918   if (nof > (capacity >> 2)) return table;
   16919   // Allocate a new dictionary with room for at least the current number of
   16920   // elements + {additionalCapacity}. The allocation method will make sure that
   16921   // there is extra room in the dictionary for additions. Don't go lower than
   16922   // room for {kMinShrinkCapacity} elements.
   16923   int at_least_room_for = nof + additionalCapacity;
   16924   int new_capacity = ComputeCapacity(at_least_room_for);
   16925   if (new_capacity < Derived::kMinShrinkCapacity) return table;
   16926   if (new_capacity == capacity) return table;
   16927 
   16928   const int kMinCapacityForPretenure = 256;
   16929   bool pretenure = (at_least_room_for > kMinCapacityForPretenure) &&
   16930                    !Heap::InNewSpace(*table);
   16931   Handle<Derived> new_table =
   16932       HashTable::New(isolate, new_capacity, pretenure ? TENURED : NOT_TENURED,
   16933                      USE_CUSTOM_MINIMUM_CAPACITY);
   16934 
   16935   table->Rehash(isolate, *new_table);
   16936   return new_table;
   16937 }
   16938 
   16939 template <typename Derived, typename Shape>
   16940 uint32_t HashTable<Derived, Shape>::FindInsertionEntry(uint32_t hash) {
   16941   uint32_t capacity = Capacity();
   16942   uint32_t entry = FirstProbe(hash, capacity);
   16943   uint32_t count = 1;
   16944   // EnsureCapacity will guarantee the hash table is never full.
   16945   ReadOnlyRoots roots = GetReadOnlyRoots();
   16946   while (true) {
   16947     if (!Shape::IsLive(roots, KeyAt(entry))) break;
   16948     entry = NextProbe(entry, count++, capacity);
   16949   }
   16950   return entry;
   16951 }
   16952 
   16953 void JSGlobalObject::InvalidatePropertyCell(Handle<JSGlobalObject> global,
   16954                                             Handle<Name> name) {
   16955   // Regardless of whether the property is there or not invalidate
   16956   // Load/StoreGlobalICs that load/store through global object's prototype.
   16957   JSObject::InvalidatePrototypeValidityCell(*global);
   16958 
   16959   DCHECK(!global->HasFastProperties());
   16960   auto dictionary = handle(global->global_dictionary(), global->GetIsolate());
   16961   int entry = dictionary->FindEntry(global->GetIsolate(), name);
   16962   if (entry == GlobalDictionary::kNotFound) return;
   16963   PropertyCell::InvalidateEntry(global->GetIsolate(), dictionary, entry);
   16964 }
   16965 
   16966 Handle<PropertyCell> JSGlobalObject::EnsureEmptyPropertyCell(
   16967     Handle<JSGlobalObject> global, Handle<Name> name,
   16968     PropertyCellType cell_type, int* entry_out) {
   16969   Isolate* isolate = global->GetIsolate();
   16970   DCHECK(!global->HasFastProperties());
   16971   Handle<GlobalDictionary> dictionary(global->global_dictionary(), isolate);
   16972   int entry = dictionary->FindEntry(isolate, name);
   16973   Handle<PropertyCell> cell;
   16974   if (entry != GlobalDictionary::kNotFound) {
   16975     if (entry_out) *entry_out = entry;
   16976     cell = handle(dictionary->CellAt(entry), isolate);
   16977     PropertyCellType original_cell_type = cell->property_details().cell_type();
   16978     DCHECK(original_cell_type == PropertyCellType::kInvalidated ||
   16979            original_cell_type == PropertyCellType::kUninitialized);
   16980     DCHECK(cell->value()->IsTheHole(isolate));
   16981     if (original_cell_type == PropertyCellType::kInvalidated) {
   16982       cell = PropertyCell::InvalidateEntry(isolate, dictionary, entry);
   16983     }
   16984     PropertyDetails details(kData, NONE, cell_type);
   16985     cell->set_property_details(details);
   16986     return cell;
   16987   }
   16988   cell = isolate->factory()->NewPropertyCell(name);
   16989   PropertyDetails details(kData, NONE, cell_type);
   16990   dictionary = GlobalDictionary::Add(isolate, dictionary, name, cell, details,
   16991                                      entry_out);
   16992   // {*entry_out} is initialized inside GlobalDictionary::Add().
   16993   global->SetProperties(*dictionary);
   16994   return cell;
   16995 }
   16996 
   16997 
   16998 // This class is used for looking up two character strings in the string table.
   16999 // If we don't have a hit we don't want to waste much time so we unroll the
   17000 // string hash calculation loop here for speed.  Doesn't work if the two
   17001 // characters form a decimal integer, since such strings have a different hash
   17002 // algorithm.
   17003 class TwoCharHashTableKey : public StringTableKey {
   17004  public:
   17005   TwoCharHashTableKey(uint16_t c1, uint16_t c2, uint64_t seed)
   17006       : StringTableKey(ComputeHashField(c1, c2, seed)), c1_(c1), c2_(c2) {}
   17007 
   17008   bool IsMatch(Object* o) override {
   17009     String* other = String::cast(o);
   17010     if (other->length() != 2) return false;
   17011     if (other->Get(0) != c1_) return false;
   17012     return other->Get(1) == c2_;
   17013   }
   17014 
   17015   Handle<String> AsHandle(Isolate* isolate) override {
   17016     // The TwoCharHashTableKey is only used for looking in the string
   17017     // table, not for adding to it.
   17018     UNREACHABLE();
   17019   }
   17020 
   17021  private:
   17022   uint32_t ComputeHashField(uint16_t c1, uint16_t c2, uint64_t seed) {
   17023     // Char 1.
   17024     uint32_t hash = static_cast<uint32_t>(seed);
   17025     hash += c1;
   17026     hash += hash << 10;
   17027     hash ^= hash >> 6;
   17028     // Char 2.
   17029     hash += c2;
   17030     hash += hash << 10;
   17031     hash ^= hash >> 6;
   17032     // GetHash.
   17033     hash += hash << 3;
   17034     hash ^= hash >> 11;
   17035     hash += hash << 15;
   17036     if ((hash & String::kHashBitMask) == 0) hash = StringHasher::kZeroHash;
   17037     hash = (hash << String::kHashShift) | String::kIsNotArrayIndexMask;
   17038 #ifdef DEBUG
   17039     // If this assert fails then we failed to reproduce the two-character
   17040     // version of the string hashing algorithm above.  One reason could be
   17041     // that we were passed two digits as characters, since the hash
   17042     // algorithm is different in that case.
   17043     uint16_t chars[2] = {c1, c2};
   17044     uint32_t check_hash = StringHasher::HashSequentialString(chars, 2, seed);
   17045     DCHECK_EQ(hash, check_hash);
   17046 #endif
   17047     return hash;
   17048   }
   17049 
   17050   uint16_t c1_;
   17051   uint16_t c2_;
   17052 };
   17053 
   17054 MaybeHandle<String> StringTable::LookupTwoCharsStringIfExists(
   17055     Isolate* isolate,
   17056     uint16_t c1,
   17057     uint16_t c2) {
   17058   TwoCharHashTableKey key(c1, c2, isolate->heap()->HashSeed());
   17059   Handle<StringTable> string_table = isolate->factory()->string_table();
   17060   int entry = string_table->FindEntry(isolate, &key);
   17061   if (entry == kNotFound) return MaybeHandle<String>();
   17062 
   17063   Handle<String> result(String::cast(string_table->KeyAt(entry)), isolate);
   17064   DCHECK(StringShape(*result).IsInternalized());
   17065   DCHECK_EQ(result->Hash(), key.Hash());
   17066   return result;
   17067 }
   17068 
   17069 void StringTable::EnsureCapacityForDeserialization(Isolate* isolate,
   17070                                                    int expected) {
   17071   Handle<StringTable> table = isolate->factory()->string_table();
   17072   // We need a key instance for the virtual hash function.
   17073   table = StringTable::EnsureCapacity(isolate, table, expected);
   17074   isolate->heap()->SetRootStringTable(*table);
   17075 }
   17076 
   17077 namespace {
   17078 
   17079 template <class StringClass>
   17080 void MigrateExternalStringResource(Isolate* isolate, String* from, String* to) {
   17081   StringClass* cast_from = StringClass::cast(from);
   17082   StringClass* cast_to = StringClass::cast(to);
   17083   const typename StringClass::Resource* to_resource = cast_to->resource();
   17084   if (to_resource == nullptr) {
   17085     // |to| is a just-created internalized copy of |from|. Migrate the resource.
   17086     cast_to->SetResource(isolate, cast_from->resource());
   17087     // Zap |from|'s resource pointer to reflect the fact that |from| has
   17088     // relinquished ownership of its resource.
   17089     isolate->heap()->UpdateExternalString(
   17090         from, ExternalString::cast(from)->ExternalPayloadSize(), 0);
   17091     cast_from->SetResource(isolate, nullptr);
   17092   } else if (to_resource != cast_from->resource()) {
   17093     // |to| already existed and has its own resource. Finalize |from|.
   17094     isolate->heap()->FinalizeExternalString(from);
   17095   }
   17096 }
   17097 
   17098 void MakeStringThin(String* string, String* internalized, Isolate* isolate) {
   17099   DCHECK_NE(string, internalized);
   17100   DCHECK(internalized->IsInternalizedString());
   17101 
   17102   if (string->IsExternalString()) {
   17103     if (internalized->IsExternalOneByteString()) {
   17104       MigrateExternalStringResource<ExternalOneByteString>(isolate, string,
   17105                                                            internalized);
   17106     } else if (internalized->IsExternalTwoByteString()) {
   17107       MigrateExternalStringResource<ExternalTwoByteString>(isolate, string,
   17108                                                            internalized);
   17109     } else {
   17110       // If the external string is duped into an existing non-external
   17111       // internalized string, free its resource (it's about to be rewritten
   17112       // into a ThinString below).
   17113       isolate->heap()->FinalizeExternalString(string);
   17114     }
   17115   }
   17116 
   17117   DisallowHeapAllocation no_gc;
   17118   int old_size = string->Size();
   17119   isolate->heap()->NotifyObjectLayoutChange(string, old_size, no_gc);
   17120   bool one_byte = internalized->IsOneByteRepresentation();
   17121   Handle<Map> map = one_byte ? isolate->factory()->thin_one_byte_string_map()
   17122                              : isolate->factory()->thin_string_map();
   17123   DCHECK_GE(old_size, ThinString::kSize);
   17124   string->synchronized_set_map(*map);
   17125   ThinString* thin = ThinString::cast(string);
   17126   thin->set_actual(internalized);
   17127   Address thin_end = thin->address() + ThinString::kSize;
   17128   int size_delta = old_size - ThinString::kSize;
   17129   if (size_delta != 0) {
   17130     Heap* heap = isolate->heap();
   17131     heap->CreateFillerObjectAt(thin_end, size_delta, ClearRecordedSlots::kNo);
   17132   }
   17133 }
   17134 
   17135 }  // namespace
   17136 
   17137 // static
   17138 Handle<String> StringTable::LookupString(Isolate* isolate,
   17139                                          Handle<String> string) {
   17140   string = String::Flatten(isolate, string);
   17141   if (string->IsInternalizedString()) return string;
   17142 
   17143   InternalizedStringKey key(string);
   17144   Handle<String> result = LookupKey(isolate, &key);
   17145 
   17146   if (FLAG_thin_strings) {
   17147     if (!string->IsInternalizedString()) {
   17148       MakeStringThin(*string, *result, isolate);
   17149     }
   17150   } else {  // !FLAG_thin_strings
   17151     if (string->IsConsString()) {
   17152       Handle<ConsString> cons = Handle<ConsString>::cast(string);
   17153       cons->set_first(isolate, *result);
   17154       cons->set_second(isolate, ReadOnlyRoots(isolate).empty_string());
   17155     } else if (string->IsSlicedString()) {
   17156       STATIC_ASSERT(ConsString::kSize == SlicedString::kSize);
   17157       DisallowHeapAllocation no_gc;
   17158       bool one_byte = result->IsOneByteRepresentation();
   17159       Handle<Map> map = one_byte
   17160                             ? isolate->factory()->cons_one_byte_string_map()
   17161                             : isolate->factory()->cons_string_map();
   17162       string->set_map(*map);
   17163       Handle<ConsString> cons = Handle<ConsString>::cast(string);
   17164       cons->set_first(isolate, *result);
   17165       cons->set_second(isolate, ReadOnlyRoots(isolate).empty_string());
   17166     }
   17167   }
   17168   return result;
   17169 }
   17170 
   17171 // static
   17172 Handle<String> StringTable::LookupKey(Isolate* isolate, StringTableKey* key) {
   17173   Handle<StringTable> table = isolate->factory()->string_table();
   17174   int entry = table->FindEntry(isolate, key);
   17175 
   17176   // String already in table.
   17177   if (entry != kNotFound) {
   17178     return handle(String::cast(table->KeyAt(entry)), isolate);
   17179   }
   17180 
   17181   table = StringTable::CautiousShrink(isolate, table);
   17182   // Adding new string. Grow table if needed.
   17183   table = StringTable::EnsureCapacity(isolate, table, 1);
   17184   isolate->heap()->SetRootStringTable(*table);
   17185 
   17186   return AddKeyNoResize(isolate, key);
   17187 }
   17188 
   17189 Handle<String> StringTable::AddKeyNoResize(Isolate* isolate,
   17190                                            StringTableKey* key) {
   17191   Handle<StringTable> table = isolate->factory()->string_table();
   17192   DCHECK(table->HasSufficientCapacityToAdd(1));
   17193   // Create string object.
   17194   Handle<String> string = key->AsHandle(isolate);
   17195   // There must be no attempts to internalize strings that could throw
   17196   // InvalidStringLength error.
   17197   CHECK(!string.is_null());
   17198   DCHECK(string->HasHashCode());
   17199   DCHECK_EQ(table->FindEntry(isolate, key), kNotFound);
   17200 
   17201   // Add the new string and return it along with the string table.
   17202   int entry = table->FindInsertionEntry(key->Hash());
   17203   table->set(EntryToIndex(entry), *string);
   17204   table->ElementAdded();
   17205 
   17206   return Handle<String>::cast(string);
   17207 }
   17208 
   17209 Handle<StringTable> StringTable::CautiousShrink(Isolate* isolate,
   17210                                                 Handle<StringTable> table) {
   17211   // Only shrink if the table is very empty to avoid performance penalty.
   17212   int capacity = table->Capacity();
   17213   int nof = table->NumberOfElements();
   17214   if (capacity <= StringTable::kMinCapacity) return table;
   17215   if (nof > (capacity / kMaxEmptyFactor)) return table;
   17216   // Keep capacity for at least half of the current nof elements.
   17217   int slack_capacity = nof >> 2;
   17218   return Shrink(isolate, table, slack_capacity);
   17219 }
   17220 
   17221 namespace {
   17222 
   17223 class StringTableNoAllocateKey : public StringTableKey {
   17224  public:
   17225   StringTableNoAllocateKey(String* string, uint64_t seed)
   17226       : StringTableKey(0), string_(string) {
   17227     StringShape shape(string);
   17228     one_byte_ = shape.HasOnlyOneByteChars();
   17229     DCHECK(!shape.IsInternalized());
   17230     DCHECK(!shape.IsThin());
   17231     int length = string->length();
   17232     if (shape.IsCons() && length <= String::kMaxHashCalcLength) {
   17233       special_flattening_ = true;
   17234       uint32_t hash_field = 0;
   17235       if (one_byte_) {
   17236         if (V8_LIKELY(length <=
   17237                       static_cast<int>(arraysize(one_byte_buffer_)))) {
   17238           one_byte_content_ = one_byte_buffer_;
   17239         } else {
   17240           one_byte_content_ = new uint8_t[length];
   17241         }
   17242         String::WriteToFlat(string, one_byte_content_, 0, length);
   17243         hash_field =
   17244             StringHasher::HashSequentialString(one_byte_content_, length, seed);
   17245       } else {
   17246         if (V8_LIKELY(length <=
   17247                       static_cast<int>(arraysize(two_byte_buffer_)))) {
   17248           two_byte_content_ = two_byte_buffer_;
   17249         } else {
   17250           two_byte_content_ = new uint16_t[length];
   17251         }
   17252         String::WriteToFlat(string, two_byte_content_, 0, length);
   17253         hash_field =
   17254             StringHasher::HashSequentialString(two_byte_content_, length, seed);
   17255       }
   17256       string->set_hash_field(hash_field);
   17257     } else {
   17258       special_flattening_ = false;
   17259       one_byte_content_ = nullptr;
   17260       string->Hash();
   17261     }
   17262 
   17263     DCHECK(string->HasHashCode());
   17264     set_hash_field(string->hash_field());
   17265   }
   17266 
   17267   ~StringTableNoAllocateKey() {
   17268     if (one_byte_) {
   17269       if (one_byte_content_ != one_byte_buffer_) delete[] one_byte_content_;
   17270     } else {
   17271       if (two_byte_content_ != two_byte_buffer_) delete[] two_byte_content_;
   17272     }
   17273   }
   17274 
   17275   bool IsMatch(Object* otherstring) override {
   17276     String* other = String::cast(otherstring);
   17277     DCHECK(other->IsInternalizedString());
   17278     DCHECK(other->IsFlat());
   17279     if (Hash() != other->Hash()) return false;
   17280     int len = string_->length();
   17281     if (len != other->length()) return false;
   17282 
   17283     if (!special_flattening_) {
   17284       if (string_->Get(0) != other->Get(0)) return false;
   17285       if (string_->IsFlat()) {
   17286         StringShape shape1(string_);
   17287         StringShape shape2(other);
   17288         if (shape1.encoding_tag() == kOneByteStringTag &&
   17289             shape2.encoding_tag() == kOneByteStringTag) {
   17290           String::FlatContent flat1 = string_->GetFlatContent();
   17291           String::FlatContent flat2 = other->GetFlatContent();
   17292           return CompareRawStringContents(flat1.ToOneByteVector().start(),
   17293                                           flat2.ToOneByteVector().start(), len);
   17294         }
   17295         if (shape1.encoding_tag() == kTwoByteStringTag &&
   17296             shape2.encoding_tag() == kTwoByteStringTag) {
   17297           String::FlatContent flat1 = string_->GetFlatContent();
   17298           String::FlatContent flat2 = other->GetFlatContent();
   17299           return CompareRawStringContents(flat1.ToUC16Vector().start(),
   17300                                           flat2.ToUC16Vector().start(), len);
   17301         }
   17302       }
   17303       StringComparator comparator;
   17304       return comparator.Equals(string_, other);
   17305     }
   17306 
   17307     String::FlatContent flat_content = other->GetFlatContent();
   17308     if (one_byte_) {
   17309       if (flat_content.IsOneByte()) {
   17310         return CompareRawStringContents(
   17311             one_byte_content_, flat_content.ToOneByteVector().start(), len);
   17312       } else {
   17313         DCHECK(flat_content.IsTwoByte());
   17314         for (int i = 0; i < len; i++) {
   17315           if (flat_content.Get(i) != one_byte_content_[i]) return false;
   17316         }
   17317         return true;
   17318       }
   17319     } else {
   17320       if (flat_content.IsTwoByte()) {
   17321         return CompareRawStringContents(
   17322             two_byte_content_, flat_content.ToUC16Vector().start(), len);
   17323       } else {
   17324         DCHECK(flat_content.IsOneByte());
   17325         for (int i = 0; i < len; i++) {
   17326           if (flat_content.Get(i) != two_byte_content_[i]) return false;
   17327         }
   17328         return true;
   17329       }
   17330     }
   17331   }
   17332 
   17333   V8_WARN_UNUSED_RESULT Handle<String> AsHandle(Isolate* isolate) override {
   17334     UNREACHABLE();
   17335   }
   17336 
   17337  private:
   17338   String* string_;
   17339   bool one_byte_;
   17340   bool special_flattening_;
   17341   union {
   17342     uint8_t* one_byte_content_;
   17343     uint16_t* two_byte_content_;
   17344   };
   17345   union {
   17346     uint8_t one_byte_buffer_[256];
   17347     uint16_t two_byte_buffer_[128];
   17348   };
   17349 };
   17350 
   17351 }  // namespace
   17352 
   17353 // static
   17354 Object* StringTable::LookupStringIfExists_NoAllocate(Isolate* isolate,
   17355                                                      String* string) {
   17356   DisallowHeapAllocation no_gc;
   17357   Heap* heap = isolate->heap();
   17358   StringTable* table = heap->string_table();
   17359 
   17360   StringTableNoAllocateKey key(string, heap->HashSeed());
   17361 
   17362   // String could be an array index.
   17363   uint32_t hash = string->hash_field();
   17364 
   17365   // Valid array indices are >= 0, so they cannot be mixed up with any of
   17366   // the result sentinels, which are negative.
   17367   STATIC_ASSERT(
   17368       !String::ArrayIndexValueBits::is_valid(ResultSentinel::kUnsupported));
   17369   STATIC_ASSERT(
   17370       !String::ArrayIndexValueBits::is_valid(ResultSentinel::kNotFound));
   17371 
   17372   if (Name::ContainsCachedArrayIndex(hash)) {
   17373     return Smi::FromInt(String::ArrayIndexValueBits::decode(hash));
   17374   }
   17375   if ((hash & Name::kIsNotArrayIndexMask) == 0) {
   17376     // It is an indexed, but it's not cached.
   17377     return Smi::FromInt(ResultSentinel::kUnsupported);
   17378   }
   17379 
   17380   DCHECK(!string->IsInternalizedString());
   17381   int entry = table->FindEntry(ReadOnlyRoots(isolate), &key, key.Hash());
   17382   if (entry != kNotFound) {
   17383     String* internalized = String::cast(table->KeyAt(entry));
   17384     if (FLAG_thin_strings) {
   17385       MakeStringThin(string, internalized, isolate);
   17386     }
   17387     return internalized;
   17388   }
   17389   // A string that's not an array index, and not in the string table,
   17390   // cannot have been used as a property name before.
   17391   return Smi::FromInt(ResultSentinel::kNotFound);
   17392 }
   17393 
   17394 String* StringTable::ForwardStringIfExists(Isolate* isolate,
   17395                                            StringTableKey* key,
   17396                                            String* string) {
   17397   Handle<StringTable> table = isolate->factory()->string_table();
   17398   int entry = table->FindEntry(isolate, key);
   17399   if (entry == kNotFound) return nullptr;
   17400 
   17401   String* canonical = String::cast(table->KeyAt(entry));
   17402   if (canonical != string) MakeStringThin(string, canonical, isolate);
   17403   return canonical;
   17404 }
   17405 
   17406 Handle<StringSet> StringSet::New(Isolate* isolate) {
   17407   return HashTable::New(isolate, 0);
   17408 }
   17409 
   17410 Handle<StringSet> StringSet::Add(Isolate* isolate, Handle<StringSet> stringset,
   17411                                  Handle<String> name) {
   17412   if (!stringset->Has(isolate, name)) {
   17413     stringset = EnsureCapacity(isolate, stringset, 1);
   17414     uint32_t hash = ShapeT::Hash(isolate, *name);
   17415     int entry = stringset->FindInsertionEntry(hash);
   17416     stringset->set(EntryToIndex(entry), *name);
   17417     stringset->ElementAdded();
   17418   }
   17419   return stringset;
   17420 }
   17421 
   17422 bool StringSet::Has(Isolate* isolate, Handle<String> name) {
   17423   return FindEntry(isolate, *name) != kNotFound;
   17424 }
   17425 
   17426 Handle<ObjectHashSet> ObjectHashSet::Add(Isolate* isolate,
   17427                                          Handle<ObjectHashSet> set,
   17428                                          Handle<Object> key) {
   17429   int32_t hash = key->GetOrCreateHash(isolate)->value();
   17430   if (!set->Has(isolate, key, hash)) {
   17431     set = EnsureCapacity(isolate, set, 1);
   17432     int entry = set->FindInsertionEntry(hash);
   17433     set->set(EntryToIndex(entry), *key);
   17434     set->ElementAdded();
   17435   }
   17436   return set;
   17437 }
   17438 
   17439 Handle<Object> CompilationCacheTable::Lookup(Handle<String> src,
   17440                                              Handle<SharedFunctionInfo> shared,
   17441                                              LanguageMode language_mode) {
   17442   Isolate* isolate = GetIsolate();
   17443   StringSharedKey key(src, shared, language_mode, kNoSourcePosition);
   17444   int entry = FindEntry(isolate, &key);
   17445   if (entry == kNotFound) return isolate->factory()->undefined_value();
   17446   int index = EntryToIndex(entry);
   17447   if (!get(index)->IsFixedArray()) return isolate->factory()->undefined_value();
   17448   return Handle<Object>(get(index + 1), isolate);
   17449 }
   17450 
   17451 namespace {
   17452 
   17453 const int kLiteralEntryLength = 2;
   17454 const int kLiteralInitialLength = 2;
   17455 const int kLiteralContextOffset = 0;
   17456 const int kLiteralLiteralsOffset = 1;
   17457 
   17458 int SearchLiteralsMapEntry(CompilationCacheTable* cache, int cache_entry,
   17459                            Context* native_context) {
   17460   DisallowHeapAllocation no_gc;
   17461   DCHECK(native_context->IsNativeContext());
   17462   Object* obj = cache->get(cache_entry);
   17463 
   17464   // Check that there's no confusion between FixedArray and WeakFixedArray (the
   17465   // object used to be a FixedArray here).
   17466   DCHECK(!obj->IsFixedArray());
   17467   if (obj->IsWeakFixedArray()) {
   17468     WeakFixedArray* literals_map = WeakFixedArray::cast(obj);
   17469     int length = literals_map->length();
   17470     for (int i = 0; i < length; i += kLiteralEntryLength) {
   17471       DCHECK(literals_map->Get(i + kLiteralContextOffset)
   17472                  ->IsWeakOrClearedHeapObject());
   17473       if (literals_map->Get(i + kLiteralContextOffset) ==
   17474           HeapObjectReference::Weak(native_context)) {
   17475         return i;
   17476       }
   17477     }
   17478   }
   17479   return -1;
   17480 }
   17481 
   17482 void AddToFeedbackCellsMap(Handle<CompilationCacheTable> cache, int cache_entry,
   17483                            Handle<Context> native_context,
   17484                            Handle<FeedbackCell> feedback_cell) {
   17485   Isolate* isolate = native_context->GetIsolate();
   17486   DCHECK(native_context->IsNativeContext());
   17487   STATIC_ASSERT(kLiteralEntryLength == 2);
   17488   Handle<WeakFixedArray> new_literals_map;
   17489   int entry;
   17490 
   17491   Object* obj = cache->get(cache_entry);
   17492 
   17493   // Check that there's no confusion between FixedArray and WeakFixedArray (the
   17494   // object used to be a FixedArray here).
   17495   DCHECK(!obj->IsFixedArray());
   17496   if (!obj->IsWeakFixedArray() || WeakFixedArray::cast(obj)->length() == 0) {
   17497     new_literals_map =
   17498         isolate->factory()->NewWeakFixedArray(kLiteralInitialLength, TENURED);
   17499     entry = 0;
   17500   } else {
   17501     Handle<WeakFixedArray> old_literals_map(WeakFixedArray::cast(obj), isolate);
   17502     entry = SearchLiteralsMapEntry(*cache, cache_entry, *native_context);
   17503     if (entry >= 0) {
   17504       // Just set the code of the entry.
   17505       old_literals_map->Set(entry + kLiteralLiteralsOffset,
   17506                             HeapObjectReference::Weak(*feedback_cell));
   17507       return;
   17508     }
   17509 
   17510     // Can we reuse an entry?
   17511     DCHECK_LT(entry, 0);
   17512     int length = old_literals_map->length();
   17513     for (int i = 0; i < length; i += kLiteralEntryLength) {
   17514       if (old_literals_map->Get(i + kLiteralContextOffset)
   17515               ->IsClearedWeakHeapObject()) {
   17516         new_literals_map = old_literals_map;
   17517         entry = i;
   17518         break;
   17519       }
   17520     }
   17521 
   17522     if (entry < 0) {
   17523       // Copy old optimized code map and append one new entry.
   17524       new_literals_map = isolate->factory()->CopyWeakFixedArrayAndGrow(
   17525           old_literals_map, kLiteralEntryLength, TENURED);
   17526       entry = old_literals_map->length();
   17527     }
   17528   }
   17529 
   17530   new_literals_map->Set(entry + kLiteralContextOffset,
   17531                         HeapObjectReference::Weak(*native_context));
   17532   new_literals_map->Set(entry + kLiteralLiteralsOffset,
   17533                         HeapObjectReference::Weak(*feedback_cell));
   17534 
   17535 #ifdef DEBUG
   17536   for (int i = 0; i < new_literals_map->length(); i += kLiteralEntryLength) {
   17537     MaybeObject* object = new_literals_map->Get(i + kLiteralContextOffset);
   17538     DCHECK(object->IsClearedWeakHeapObject() ||
   17539            object->ToWeakHeapObject()->IsNativeContext());
   17540     object = new_literals_map->Get(i + kLiteralLiteralsOffset);
   17541     DCHECK(object->IsClearedWeakHeapObject() ||
   17542            object->ToWeakHeapObject()->IsFeedbackCell());
   17543   }
   17544 #endif
   17545 
   17546   Object* old_literals_map = cache->get(cache_entry);
   17547   if (old_literals_map != *new_literals_map) {
   17548     cache->set(cache_entry, *new_literals_map);
   17549   }
   17550 }
   17551 
   17552 FeedbackCell* SearchLiteralsMap(CompilationCacheTable* cache, int cache_entry,
   17553                                 Context* native_context) {
   17554   FeedbackCell* result = nullptr;
   17555   int entry = SearchLiteralsMapEntry(cache, cache_entry, native_context);
   17556   if (entry >= 0) {
   17557     WeakFixedArray* literals_map =
   17558         WeakFixedArray::cast(cache->get(cache_entry));
   17559     DCHECK_LE(entry + kLiteralEntryLength, literals_map->length());
   17560     MaybeObject* object = literals_map->Get(entry + kLiteralLiteralsOffset);
   17561 
   17562     result = object->IsClearedWeakHeapObject()
   17563                  ? nullptr
   17564                  : FeedbackCell::cast(object->ToWeakHeapObject());
   17565   }
   17566   DCHECK(result == nullptr || result->IsFeedbackCell());
   17567   return result;
   17568 }
   17569 
   17570 }  // namespace
   17571 
   17572 MaybeHandle<SharedFunctionInfo> CompilationCacheTable::LookupScript(
   17573     Handle<String> src, Handle<Context> native_context,
   17574     LanguageMode language_mode) {
   17575   // We use the empty function SFI as part of the key. Although the
   17576   // empty_function is native context dependent, the SFI is de-duped on
   17577   // snapshot builds by the PartialSnapshotCache, and so this does not prevent
   17578   // reuse of scripts in the compilation cache across native contexts.
   17579   Handle<SharedFunctionInfo> shared(native_context->empty_function()->shared(),
   17580                                     native_context->GetIsolate());
   17581   StringSharedKey key(src, shared, language_mode, kNoSourcePosition);
   17582   int entry = FindEntry(GetIsolate(), &key);
   17583   if (entry == kNotFound) return MaybeHandle<SharedFunctionInfo>();
   17584   int index = EntryToIndex(entry);
   17585   if (!get(index)->IsFixedArray()) return MaybeHandle<SharedFunctionInfo>();
   17586   Object* obj = get(index + 1);
   17587   if (obj->IsSharedFunctionInfo()) {
   17588     return handle(SharedFunctionInfo::cast(obj), native_context->GetIsolate());
   17589   }
   17590   return MaybeHandle<SharedFunctionInfo>();
   17591 }
   17592 
   17593 InfoCellPair CompilationCacheTable::LookupEval(
   17594     Handle<String> src, Handle<SharedFunctionInfo> outer_info,
   17595     Handle<Context> native_context, LanguageMode language_mode, int position) {
   17596   InfoCellPair empty_result;
   17597   StringSharedKey key(src, outer_info, language_mode, position);
   17598   int entry = FindEntry(GetIsolate(), &key);
   17599   if (entry == kNotFound) return empty_result;
   17600   int index = EntryToIndex(entry);
   17601   if (!get(index)->IsFixedArray()) return empty_result;
   17602   Object* obj = get(EntryToIndex(entry) + 1);
   17603   if (obj->IsSharedFunctionInfo()) {
   17604     FeedbackCell* feedback_cell =
   17605         SearchLiteralsMap(this, EntryToIndex(entry) + 2, *native_context);
   17606     return InfoCellPair(SharedFunctionInfo::cast(obj), feedback_cell);
   17607   }
   17608   return empty_result;
   17609 }
   17610 
   17611 Handle<Object> CompilationCacheTable::LookupRegExp(Handle<String> src,
   17612                                                    JSRegExp::Flags flags) {
   17613   Isolate* isolate = GetIsolate();
   17614   DisallowHeapAllocation no_allocation;
   17615   RegExpKey key(src, flags);
   17616   int entry = FindEntry(isolate, &key);
   17617   if (entry == kNotFound) return isolate->factory()->undefined_value();
   17618   return Handle<Object>(get(EntryToIndex(entry) + 1), isolate);
   17619 }
   17620 
   17621 Handle<CompilationCacheTable> CompilationCacheTable::Put(
   17622     Handle<CompilationCacheTable> cache, Handle<String> src,
   17623     Handle<SharedFunctionInfo> shared, LanguageMode language_mode,
   17624     Handle<Object> value) {
   17625   Isolate* isolate = cache->GetIsolate();
   17626   StringSharedKey key(src, shared, language_mode, kNoSourcePosition);
   17627   Handle<Object> k = key.AsHandle(isolate);
   17628   cache = EnsureCapacity(isolate, cache, 1);
   17629   int entry = cache->FindInsertionEntry(key.Hash());
   17630   cache->set(EntryToIndex(entry), *k);
   17631   cache->set(EntryToIndex(entry) + 1, *value);
   17632   cache->ElementAdded();
   17633   return cache;
   17634 }
   17635 
   17636 Handle<CompilationCacheTable> CompilationCacheTable::PutScript(
   17637     Handle<CompilationCacheTable> cache, Handle<String> src,
   17638     Handle<Context> native_context, LanguageMode language_mode,
   17639     Handle<SharedFunctionInfo> value) {
   17640   Isolate* isolate = native_context->GetIsolate();
   17641   // We use the empty function SFI as part of the key. Although the
   17642   // empty_function is native context dependent, the SFI is de-duped on
   17643   // snapshot builds by the PartialSnapshotCache, and so this does not prevent
   17644   // reuse of scripts in the compilation cache across native contexts.
   17645   Handle<SharedFunctionInfo> shared(native_context->empty_function()->shared(),
   17646                                     isolate);
   17647   StringSharedKey key(src, shared, language_mode, kNoSourcePosition);
   17648   Handle<Object> k = key.AsHandle(isolate);
   17649   cache = EnsureCapacity(isolate, cache, 1);
   17650   int entry = cache->FindInsertionEntry(key.Hash());
   17651   cache->set(EntryToIndex(entry), *k);
   17652   cache->set(EntryToIndex(entry) + 1, *value);
   17653   cache->ElementAdded();
   17654   return cache;
   17655 }
   17656 
   17657 Handle<CompilationCacheTable> CompilationCacheTable::PutEval(
   17658     Handle<CompilationCacheTable> cache, Handle<String> src,
   17659     Handle<SharedFunctionInfo> outer_info, Handle<SharedFunctionInfo> value,
   17660     Handle<Context> native_context, Handle<FeedbackCell> feedback_cell,
   17661     int position) {
   17662   Isolate* isolate = native_context->GetIsolate();
   17663   StringSharedKey key(src, outer_info, value->language_mode(), position);
   17664   {
   17665     Handle<Object> k = key.AsHandle(isolate);
   17666     int entry = cache->FindEntry(isolate, &key);
   17667     if (entry != kNotFound) {
   17668       cache->set(EntryToIndex(entry), *k);
   17669       cache->set(EntryToIndex(entry) + 1, *value);
   17670       // AddToFeedbackCellsMap may allocate a new sub-array to live in the
   17671       // entry, but it won't change the cache array. Therefore EntryToIndex
   17672       // and entry remains correct.
   17673       AddToFeedbackCellsMap(cache, EntryToIndex(entry) + 2, native_context,
   17674                             feedback_cell);
   17675       return cache;
   17676     }
   17677   }
   17678 
   17679   cache = EnsureCapacity(isolate, cache, 1);
   17680   int entry = cache->FindInsertionEntry(key.Hash());
   17681   Handle<Object> k =
   17682       isolate->factory()->NewNumber(static_cast<double>(key.Hash()));
   17683   cache->set(EntryToIndex(entry), *k);
   17684   cache->set(EntryToIndex(entry) + 1, Smi::FromInt(kHashGenerations));
   17685   cache->ElementAdded();
   17686   return cache;
   17687 }
   17688 
   17689 Handle<CompilationCacheTable> CompilationCacheTable::PutRegExp(
   17690     Isolate* isolate, Handle<CompilationCacheTable> cache, Handle<String> src,
   17691     JSRegExp::Flags flags, Handle<FixedArray> value) {
   17692   RegExpKey key(src, flags);
   17693   cache = EnsureCapacity(isolate, cache, 1);
   17694   int entry = cache->FindInsertionEntry(key.Hash());
   17695   // We store the value in the key slot, and compare the search key
   17696   // to the stored value with a custon IsMatch function during lookups.
   17697   cache->set(EntryToIndex(entry), *value);
   17698   cache->set(EntryToIndex(entry) + 1, *value);
   17699   cache->ElementAdded();
   17700   return cache;
   17701 }
   17702 
   17703 
   17704 void CompilationCacheTable::Age() {
   17705   DisallowHeapAllocation no_allocation;
   17706   Object* the_hole_value = GetReadOnlyRoots().the_hole_value();
   17707   for (int entry = 0, size = Capacity(); entry < size; entry++) {
   17708     int entry_index = EntryToIndex(entry);
   17709     int value_index = entry_index + 1;
   17710 
   17711     if (get(entry_index)->IsNumber()) {
   17712       Smi* count = Smi::cast(get(value_index));
   17713       count = Smi::FromInt(count->value() - 1);
   17714       if (count->value() == 0) {
   17715         NoWriteBarrierSet(this, entry_index, the_hole_value);
   17716         NoWriteBarrierSet(this, value_index, the_hole_value);
   17717         ElementRemoved();
   17718       } else {
   17719         NoWriteBarrierSet(this, value_index, count);
   17720       }
   17721     } else if (get(entry_index)->IsFixedArray()) {
   17722       SharedFunctionInfo* info = SharedFunctionInfo::cast(get(value_index));
   17723       if (info->IsInterpreted() && info->GetBytecodeArray()->IsOld()) {
   17724         for (int i = 0; i < kEntrySize; i++) {
   17725           NoWriteBarrierSet(this, entry_index + i, the_hole_value);
   17726         }
   17727         ElementRemoved();
   17728       }
   17729     }
   17730   }
   17731 }
   17732 
   17733 
   17734 void CompilationCacheTable::Remove(Object* value) {
   17735   DisallowHeapAllocation no_allocation;
   17736   Object* the_hole_value = GetReadOnlyRoots().the_hole_value();
   17737   for (int entry = 0, size = Capacity(); entry < size; entry++) {
   17738     int entry_index = EntryToIndex(entry);
   17739     int value_index = entry_index + 1;
   17740     if (get(value_index) == value) {
   17741       for (int i = 0; i < kEntrySize; i++) {
   17742         NoWriteBarrierSet(this, entry_index + i, the_hole_value);
   17743       }
   17744       ElementRemoved();
   17745     }
   17746   }
   17747   return;
   17748 }
   17749 
   17750 template <typename Derived, typename Shape>
   17751 Handle<Derived> BaseNameDictionary<Derived, Shape>::New(
   17752     Isolate* isolate, int at_least_space_for, PretenureFlag pretenure,
   17753     MinimumCapacity capacity_option) {
   17754   DCHECK_LE(0, at_least_space_for);
   17755   Handle<Derived> dict = Dictionary<Derived, Shape>::New(
   17756       isolate, at_least_space_for, pretenure, capacity_option);
   17757   dict->SetHash(PropertyArray::kNoHashSentinel);
   17758   dict->SetNextEnumerationIndex(PropertyDetails::kInitialIndex);
   17759   return dict;
   17760 }
   17761 
   17762 template <typename Derived, typename Shape>
   17763 Handle<Derived> BaseNameDictionary<Derived, Shape>::EnsureCapacity(
   17764     Isolate* isolate, Handle<Derived> dictionary, int n) {
   17765   // Check whether there are enough enumeration indices to add n elements.
   17766   if (!PropertyDetails::IsValidIndex(dictionary->NextEnumerationIndex() + n)) {
   17767     // If not, we generate new indices for the properties.
   17768     int length = dictionary->NumberOfElements();
   17769 
   17770     Handle<FixedArray> iteration_order = IterationIndices(isolate, dictionary);
   17771     DCHECK_EQ(length, iteration_order->length());
   17772 
   17773     // Iterate over the dictionary using the enumeration order and update
   17774     // the dictionary with new enumeration indices.
   17775     for (int i = 0; i < length; i++) {
   17776       int index = Smi::ToInt(iteration_order->get(i));
   17777       DCHECK(dictionary->IsKey(dictionary->GetReadOnlyRoots(),
   17778                                dictionary->KeyAt(index)));
   17779 
   17780       int enum_index = PropertyDetails::kInitialIndex + i;
   17781 
   17782       PropertyDetails details = dictionary->DetailsAt(index);
   17783       PropertyDetails new_details = details.set_index(enum_index);
   17784       dictionary->DetailsAtPut(isolate, index, new_details);
   17785     }
   17786 
   17787     // Set the next enumeration index.
   17788     dictionary->SetNextEnumerationIndex(PropertyDetails::kInitialIndex +
   17789                                         length);
   17790   }
   17791   return HashTable<Derived, Shape>::EnsureCapacity(isolate, dictionary, n);
   17792 }
   17793 
   17794 template <typename Derived, typename Shape>
   17795 Handle<Derived> Dictionary<Derived, Shape>::DeleteEntry(
   17796     Isolate* isolate, Handle<Derived> dictionary, int entry) {
   17797   DCHECK(Shape::kEntrySize != 3 ||
   17798          dictionary->DetailsAt(entry).IsConfigurable());
   17799   dictionary->ClearEntry(isolate, entry);
   17800   dictionary->ElementRemoved();
   17801   return Shrink(isolate, dictionary);
   17802 }
   17803 
   17804 template <typename Derived, typename Shape>
   17805 Handle<Derived> Dictionary<Derived, Shape>::AtPut(Isolate* isolate,
   17806                                                   Handle<Derived> dictionary,
   17807                                                   Key key, Handle<Object> value,
   17808                                                   PropertyDetails details) {
   17809   int entry = dictionary->FindEntry(isolate, key);
   17810 
   17811   // If the entry is present set the value;
   17812   if (entry == Dictionary::kNotFound) {
   17813     return Derived::Add(isolate, dictionary, key, value, details);
   17814   }
   17815 
   17816   // We don't need to copy over the enumeration index.
   17817   dictionary->ValueAtPut(entry, *value);
   17818   if (Shape::kEntrySize == 3) dictionary->DetailsAtPut(isolate, entry, details);
   17819   return dictionary;
   17820 }
   17821 
   17822 template <typename Derived, typename Shape>
   17823 Handle<Derived>
   17824 BaseNameDictionary<Derived, Shape>::AddNoUpdateNextEnumerationIndex(
   17825     Isolate* isolate, Handle<Derived> dictionary, Key key, Handle<Object> value,
   17826     PropertyDetails details, int* entry_out) {
   17827   // Insert element at empty or deleted entry
   17828   return Dictionary<Derived, Shape>::Add(isolate, dictionary, key, value,
   17829                                          details, entry_out);
   17830 }
   17831 
   17832 // GCC workaround: Explicitly instantiate template method for NameDictionary
   17833 // to avoid "undefined reference" issues during linking.
   17834 template Handle<NameDictionary>
   17835 BaseNameDictionary<NameDictionary, NameDictionaryShape>::
   17836     AddNoUpdateNextEnumerationIndex(Isolate* isolate, Handle<NameDictionary>,
   17837                                     Handle<Name>, Handle<Object>,
   17838                                     PropertyDetails, int*);
   17839 
   17840 template <typename Derived, typename Shape>
   17841 Handle<Derived> BaseNameDictionary<Derived, Shape>::Add(
   17842     Isolate* isolate, Handle<Derived> dictionary, Key key, Handle<Object> value,
   17843     PropertyDetails details, int* entry_out) {
   17844   // Insert element at empty or deleted entry
   17845   DCHECK_EQ(0, details.dictionary_index());
   17846   // Assign an enumeration index to the property and update
   17847   // SetNextEnumerationIndex.
   17848   int index = dictionary->NextEnumerationIndex();
   17849   details = details.set_index(index);
   17850   dictionary->SetNextEnumerationIndex(index + 1);
   17851   return AddNoUpdateNextEnumerationIndex(isolate, dictionary, key, value,
   17852                                          details, entry_out);
   17853 }
   17854 
   17855 template <typename Derived, typename Shape>
   17856 Handle<Derived> Dictionary<Derived, Shape>::Add(Isolate* isolate,
   17857                                                 Handle<Derived> dictionary,
   17858                                                 Key key, Handle<Object> value,
   17859                                                 PropertyDetails details,
   17860                                                 int* entry_out) {
   17861   uint32_t hash = Shape::Hash(isolate, key);
   17862   // Valdate key is absent.
   17863   SLOW_DCHECK((dictionary->FindEntry(isolate, key) == Dictionary::kNotFound));
   17864   // Check whether the dictionary should be extended.
   17865   dictionary = Derived::EnsureCapacity(isolate, dictionary, 1);
   17866 
   17867   // Compute the key object.
   17868   Handle<Object> k = Shape::AsHandle(isolate, key);
   17869 
   17870   uint32_t entry = dictionary->FindInsertionEntry(hash);
   17871   dictionary->SetEntry(isolate, entry, *k, *value, details);
   17872   DCHECK(dictionary->KeyAt(entry)->IsNumber() ||
   17873          Shape::Unwrap(dictionary->KeyAt(entry))->IsUniqueName());
   17874   dictionary->ElementAdded();
   17875   if (entry_out) *entry_out = entry;
   17876   return dictionary;
   17877 }
   17878 
   17879 // static
   17880 Handle<SimpleNumberDictionary> SimpleNumberDictionary::Set(
   17881     Isolate* isolate, Handle<SimpleNumberDictionary> dictionary, uint32_t key,
   17882     Handle<Object> value) {
   17883   return AtPut(isolate, dictionary, key, value, PropertyDetails::Empty());
   17884 }
   17885 
   17886 bool NumberDictionary::HasComplexElements() {
   17887   if (!requires_slow_elements()) return false;
   17888   ReadOnlyRoots roots = GetReadOnlyRoots();
   17889   int capacity = this->Capacity();
   17890   for (int i = 0; i < capacity; i++) {
   17891     Object* k;
   17892     if (!this->ToKey(roots, i, &k)) continue;
   17893     PropertyDetails details = this->DetailsAt(i);
   17894     if (details.kind() == kAccessor) return true;
   17895     PropertyAttributes attr = details.attributes();
   17896     if (attr & ALL_ATTRIBUTES_MASK) return true;
   17897   }
   17898   return false;
   17899 }
   17900 
   17901 void NumberDictionary::UpdateMaxNumberKey(uint32_t key,
   17902                                           Handle<JSObject> dictionary_holder) {
   17903   DisallowHeapAllocation no_allocation;
   17904   // If the dictionary requires slow elements an element has already
   17905   // been added at a high index.
   17906   if (requires_slow_elements()) return;
   17907   // Check if this index is high enough that we should require slow
   17908   // elements.
   17909   if (key > kRequiresSlowElementsLimit) {
   17910     if (!dictionary_holder.is_null()) {
   17911       dictionary_holder->RequireSlowElements(this);
   17912     }
   17913     set_requires_slow_elements();
   17914     return;
   17915   }
   17916   // Update max key value.
   17917   Object* max_index_object = get(kMaxNumberKeyIndex);
   17918   if (!max_index_object->IsSmi() || max_number_key() < key) {
   17919     FixedArray::set(kMaxNumberKeyIndex,
   17920                     Smi::FromInt(key << kRequiresSlowElementsTagSize));
   17921   }
   17922 }
   17923 
   17924 Handle<NumberDictionary> NumberDictionary::Set(
   17925     Isolate* isolate, Handle<NumberDictionary> dictionary, uint32_t key,
   17926     Handle<Object> value, Handle<JSObject> dictionary_holder,
   17927     PropertyDetails details) {
   17928   dictionary->UpdateMaxNumberKey(key, dictionary_holder);
   17929   return AtPut(isolate, dictionary, key, value, details);
   17930 }
   17931 
   17932 void NumberDictionary::CopyValuesTo(FixedArray* elements) {
   17933   ReadOnlyRoots roots = GetReadOnlyRoots();
   17934   int pos = 0;
   17935   int capacity = this->Capacity();
   17936   DisallowHeapAllocation no_gc;
   17937   WriteBarrierMode mode = elements->GetWriteBarrierMode(no_gc);
   17938   for (int i = 0; i < capacity; i++) {
   17939     Object* k;
   17940     if (this->ToKey(roots, i, &k)) {
   17941       elements->set(pos++, this->ValueAt(i), mode);
   17942     }
   17943   }
   17944   DCHECK_EQ(pos, elements->length());
   17945 }
   17946 
   17947 template <typename Derived, typename Shape>
   17948 int Dictionary<Derived, Shape>::NumberOfEnumerableProperties() {
   17949   ReadOnlyRoots roots = this->GetReadOnlyRoots();
   17950   int capacity = this->Capacity();
   17951   int result = 0;
   17952   for (int i = 0; i < capacity; i++) {
   17953     Object* k;
   17954     if (!this->ToKey(roots, i, &k)) continue;
   17955     if (k->FilterKey(ENUMERABLE_STRINGS)) continue;
   17956     PropertyDetails details = this->DetailsAt(i);
   17957     PropertyAttributes attr = details.attributes();
   17958     if ((attr & ONLY_ENUMERABLE) == 0) result++;
   17959   }
   17960   return result;
   17961 }
   17962 
   17963 
   17964 template <typename Dictionary>
   17965 struct EnumIndexComparator {
   17966   explicit EnumIndexComparator(Dictionary* dict) : dict(dict) {}
   17967   bool operator()(const base::AtomicElement<Smi*>& a,
   17968                   const base::AtomicElement<Smi*>& b) {
   17969     PropertyDetails da(dict->DetailsAt(a.value()->value()));
   17970     PropertyDetails db(dict->DetailsAt(b.value()->value()));
   17971     return da.dictionary_index() < db.dictionary_index();
   17972   }
   17973   Dictionary* dict;
   17974 };
   17975 
   17976 template <typename Derived, typename Shape>
   17977 void BaseNameDictionary<Derived, Shape>::CopyEnumKeysTo(
   17978     Isolate* isolate, Handle<Derived> dictionary, Handle<FixedArray> storage,
   17979     KeyCollectionMode mode, KeyAccumulator* accumulator) {
   17980   DCHECK_IMPLIES(mode != KeyCollectionMode::kOwnOnly, accumulator != nullptr);
   17981   int length = storage->length();
   17982   int capacity = dictionary->Capacity();
   17983   int properties = 0;
   17984   ReadOnlyRoots roots(isolate);
   17985   for (int i = 0; i < capacity; i++) {
   17986     Object* key;
   17987     if (!dictionary->ToKey(roots, i, &key)) continue;
   17988     bool is_shadowing_key = false;
   17989     if (key->IsSymbol()) continue;
   17990     PropertyDetails details = dictionary->DetailsAt(i);
   17991     if (details.IsDontEnum()) {
   17992       if (mode == KeyCollectionMode::kIncludePrototypes) {
   17993         is_shadowing_key = true;
   17994       } else {
   17995         continue;
   17996       }
   17997     }
   17998     if (is_shadowing_key) {
   17999       accumulator->AddShadowingKey(key);
   18000       continue;
   18001     } else {
   18002       storage->set(properties, Smi::FromInt(i));
   18003     }
   18004     properties++;
   18005     if (mode == KeyCollectionMode::kOwnOnly && properties == length) break;
   18006   }
   18007 
   18008   CHECK_EQ(length, properties);
   18009   DisallowHeapAllocation no_gc;
   18010   Derived* raw_dictionary = *dictionary;
   18011   FixedArray* raw_storage = *storage;
   18012   EnumIndexComparator<Derived> cmp(raw_dictionary);
   18013   // Use AtomicElement wrapper to ensure that std::sort uses atomic load and
   18014   // store operations that are safe for concurrent marking.
   18015   base::AtomicElement<Smi*>* start =
   18016       reinterpret_cast<base::AtomicElement<Smi*>*>(
   18017           storage->GetFirstElementAddress());
   18018   std::sort(start, start + length, cmp);
   18019   for (int i = 0; i < length; i++) {
   18020     int index = Smi::ToInt(raw_storage->get(i));
   18021     raw_storage->set(i, raw_dictionary->NameAt(index));
   18022   }
   18023 }
   18024 
   18025 template <typename Derived, typename Shape>
   18026 Handle<FixedArray> BaseNameDictionary<Derived, Shape>::IterationIndices(
   18027     Isolate* isolate, Handle<Derived> dictionary) {
   18028   int capacity = dictionary->Capacity();
   18029   int length = dictionary->NumberOfElements();
   18030   Handle<FixedArray> array = isolate->factory()->NewFixedArray(length);
   18031   ReadOnlyRoots roots(isolate);
   18032   int array_size = 0;
   18033   {
   18034     DisallowHeapAllocation no_gc;
   18035     Derived* raw_dictionary = *dictionary;
   18036     for (int i = 0; i < capacity; i++) {
   18037       Object* k;
   18038       if (!raw_dictionary->ToKey(roots, i, &k)) continue;
   18039       array->set(array_size++, Smi::FromInt(i));
   18040     }
   18041 
   18042     DCHECK_EQ(array_size, length);
   18043 
   18044     EnumIndexComparator<Derived> cmp(raw_dictionary);
   18045     // Use AtomicElement wrapper to ensure that std::sort uses atomic load and
   18046     // store operations that are safe for concurrent marking.
   18047     base::AtomicElement<Smi*>* start =
   18048         reinterpret_cast<base::AtomicElement<Smi*>*>(
   18049             array->GetFirstElementAddress());
   18050     std::sort(start, start + array_size, cmp);
   18051   }
   18052   return FixedArray::ShrinkOrEmpty(isolate, array, array_size);
   18053 }
   18054 
   18055 template <typename Derived, typename Shape>
   18056 void BaseNameDictionary<Derived, Shape>::CollectKeysTo(
   18057     Handle<Derived> dictionary, KeyAccumulator* keys) {
   18058   Isolate* isolate = keys->isolate();
   18059   ReadOnlyRoots roots(isolate);
   18060   int capacity = dictionary->Capacity();
   18061   Handle<FixedArray> array =
   18062       isolate->factory()->NewFixedArray(dictionary->NumberOfElements());
   18063   int array_size = 0;
   18064   PropertyFilter filter = keys->filter();
   18065   {
   18066     DisallowHeapAllocation no_gc;
   18067     Derived* raw_dictionary = *dictionary;
   18068     for (int i = 0; i < capacity; i++) {
   18069       Object* k;
   18070       if (!raw_dictionary->ToKey(roots, i, &k)) continue;
   18071       if (k->FilterKey(filter)) continue;
   18072       PropertyDetails details = raw_dictionary->DetailsAt(i);
   18073       if ((details.attributes() & filter) != 0) {
   18074         keys->AddShadowingKey(k);
   18075         continue;
   18076       }
   18077       if (filter & ONLY_ALL_CAN_READ) {
   18078         if (details.kind() != kAccessor) continue;
   18079         Object* accessors = raw_dictionary->ValueAt(i);
   18080         if (!accessors->IsAccessorInfo()) continue;
   18081         if (!AccessorInfo::cast(accessors)->all_can_read()) continue;
   18082       }
   18083       array->set(array_size++, Smi::FromInt(i));
   18084     }
   18085 
   18086     EnumIndexComparator<Derived> cmp(raw_dictionary);
   18087     // Use AtomicElement wrapper to ensure that std::sort uses atomic load and
   18088     // store operations that are safe for concurrent marking.
   18089     base::AtomicElement<Smi*>* start =
   18090         reinterpret_cast<base::AtomicElement<Smi*>*>(
   18091             array->GetFirstElementAddress());
   18092     std::sort(start, start + array_size, cmp);
   18093   }
   18094 
   18095   bool has_seen_symbol = false;
   18096   for (int i = 0; i < array_size; i++) {
   18097     int index = Smi::ToInt(array->get(i));
   18098     Object* key = dictionary->NameAt(index);
   18099     if (key->IsSymbol()) {
   18100       has_seen_symbol = true;
   18101       continue;
   18102     }
   18103     keys->AddKey(key, DO_NOT_CONVERT);
   18104   }
   18105   if (has_seen_symbol) {
   18106     for (int i = 0; i < array_size; i++) {
   18107       int index = Smi::ToInt(array->get(i));
   18108       Object* key = dictionary->NameAt(index);
   18109       if (!key->IsSymbol()) continue;
   18110       keys->AddKey(key, DO_NOT_CONVERT);
   18111     }
   18112   }
   18113 }
   18114 
   18115 // Backwards lookup (slow).
   18116 template <typename Derived, typename Shape>
   18117 Object* Dictionary<Derived, Shape>::SlowReverseLookup(Object* value) {
   18118   Derived* dictionary = Derived::cast(this);
   18119   ReadOnlyRoots roots = dictionary->GetReadOnlyRoots();
   18120   int capacity = dictionary->Capacity();
   18121   for (int i = 0; i < capacity; i++) {
   18122     Object* k;
   18123     if (!dictionary->ToKey(roots, i, &k)) continue;
   18124     Object* e = dictionary->ValueAt(i);
   18125     if (e == value) return k;
   18126   }
   18127   return roots.undefined_value();
   18128 }
   18129 
   18130 template <typename Derived, typename Shape>
   18131 void ObjectHashTableBase<Derived, Shape>::FillEntriesWithHoles(
   18132     Handle<Derived> table) {
   18133   int length = table->length();
   18134   for (int i = Derived::EntryToIndex(0); i < length; i++) {
   18135     table->set_the_hole(i);
   18136   }
   18137 }
   18138 
   18139 template <typename Derived, typename Shape>
   18140 Object* ObjectHashTableBase<Derived, Shape>::Lookup(ReadOnlyRoots roots,
   18141                                                     Handle<Object> key,
   18142                                                     int32_t hash) {
   18143   DisallowHeapAllocation no_gc;
   18144   DCHECK(this->IsKey(roots, *key));
   18145 
   18146   int entry = this->FindEntry(roots, key, hash);
   18147   if (entry == kNotFound) return roots.the_hole_value();
   18148   return this->get(Derived::EntryToIndex(entry) + 1);
   18149 }
   18150 
   18151 template <typename Derived, typename Shape>
   18152 Object* ObjectHashTableBase<Derived, Shape>::Lookup(Handle<Object> key) {
   18153   DisallowHeapAllocation no_gc;
   18154 
   18155   ReadOnlyRoots roots = this->GetReadOnlyRoots();
   18156   DCHECK(this->IsKey(roots, *key));
   18157 
   18158   // If the object does not have an identity hash, it was never used as a key.
   18159   Object* hash = key->GetHash();
   18160   if (hash->IsUndefined(roots)) {
   18161     return roots.the_hole_value();
   18162   }
   18163   return Lookup(roots, key, Smi::ToInt(hash));
   18164 }
   18165 
   18166 template <typename Derived, typename Shape>
   18167 Object* ObjectHashTableBase<Derived, Shape>::Lookup(Handle<Object> key,
   18168                                                     int32_t hash) {
   18169   return Lookup(this->GetReadOnlyRoots(), key, hash);
   18170 }
   18171 
   18172 template <typename Derived, typename Shape>
   18173 Object* ObjectHashTableBase<Derived, Shape>::ValueAt(int entry) {
   18174   return this->get(EntryToValueIndex(entry));
   18175 }
   18176 
   18177 template <typename Derived, typename Shape>
   18178 Handle<Derived> ObjectHashTableBase<Derived, Shape>::Put(Handle<Derived> table,
   18179                                                          Handle<Object> key,
   18180                                                          Handle<Object> value) {
   18181   Isolate* isolate = Heap::FromWritableHeapObject(*table)->isolate();
   18182   DCHECK(table->IsKey(ReadOnlyRoots(isolate), *key));
   18183   DCHECK(!value->IsTheHole(ReadOnlyRoots(isolate)));
   18184 
   18185   // Make sure the key object has an identity hash code.
   18186   int32_t hash = key->GetOrCreateHash(isolate)->value();
   18187 
   18188   return ObjectHashTableBase<Derived, Shape>::Put(isolate, table, key, value,
   18189                                                   hash);
   18190 }
   18191 
   18192 template <typename Derived, typename Shape>
   18193 Handle<Derived> ObjectHashTableBase<Derived, Shape>::Put(Isolate* isolate,
   18194                                                          Handle<Derived> table,
   18195                                                          Handle<Object> key,
   18196                                                          Handle<Object> value,
   18197                                                          int32_t hash) {
   18198   ReadOnlyRoots roots(isolate);
   18199   DCHECK(table->IsKey(roots, *key));
   18200   DCHECK(!value->IsTheHole(roots));
   18201 
   18202   int entry = table->FindEntry(roots, key, hash);
   18203 
   18204   // Key is already in table, just overwrite value.
   18205   if (entry != kNotFound) {
   18206     table->set(Derived::EntryToIndex(entry) + 1, *value);
   18207     return table;
   18208   }
   18209 
   18210   // Rehash if more than 33% of the entries are deleted entries.
   18211   // TODO(jochen): Consider to shrink the fixed array in place.
   18212   if ((table->NumberOfDeletedElements() << 1) > table->NumberOfElements()) {
   18213     table->Rehash(isolate);
   18214   }
   18215   // If we're out of luck, we didn't get a GC recently, and so rehashing
   18216   // isn't enough to avoid a crash.
   18217   if (!table->HasSufficientCapacityToAdd(1)) {
   18218     int nof = table->NumberOfElements() + 1;
   18219     int capacity = ObjectHashTable::ComputeCapacity(nof * 2);
   18220     if (capacity > ObjectHashTable::kMaxCapacity) {
   18221       for (size_t i = 0; i < 2; ++i) {
   18222         isolate->heap()->CollectAllGarbage(
   18223             Heap::kFinalizeIncrementalMarkingMask,
   18224             GarbageCollectionReason::kFullHashtable);
   18225       }
   18226       table->Rehash(isolate);
   18227     }
   18228   }
   18229 
   18230   // Check whether the hash table should be extended.
   18231   table = Derived::EnsureCapacity(isolate, table, 1);
   18232   table->AddEntry(table->FindInsertionEntry(hash), *key, *value);
   18233   return table;
   18234 }
   18235 
   18236 template <typename Derived, typename Shape>
   18237 Handle<Derived> ObjectHashTableBase<Derived, Shape>::Remove(
   18238     Isolate* isolate, Handle<Derived> table, Handle<Object> key,
   18239     bool* was_present) {
   18240   DCHECK(table->IsKey(table->GetReadOnlyRoots(), *key));
   18241 
   18242   Object* hash = key->GetHash();
   18243   if (hash->IsUndefined()) {
   18244     *was_present = false;
   18245     return table;
   18246   }
   18247 
   18248   return Remove(isolate, table, key, was_present, Smi::ToInt(hash));
   18249 }
   18250 
   18251 template <typename Derived, typename Shape>
   18252 Handle<Derived> ObjectHashTableBase<Derived, Shape>::Remove(
   18253     Isolate* isolate, Handle<Derived> table, Handle<Object> key,
   18254     bool* was_present, int32_t hash) {
   18255   ReadOnlyRoots roots = table->GetReadOnlyRoots();
   18256   DCHECK(table->IsKey(roots, *key));
   18257 
   18258   int entry = table->FindEntry(roots, key, hash);
   18259   if (entry == kNotFound) {
   18260     *was_present = false;
   18261     return table;
   18262   }
   18263 
   18264   *was_present = true;
   18265   table->RemoveEntry(entry);
   18266   return Derived::Shrink(isolate, table);
   18267 }
   18268 
   18269 template <typename Derived, typename Shape>
   18270 void ObjectHashTableBase<Derived, Shape>::AddEntry(int entry, Object* key,
   18271                                                    Object* value) {
   18272   this->set(Derived::EntryToIndex(entry), key);
   18273   this->set(Derived::EntryToIndex(entry) + 1, value);
   18274   this->ElementAdded();
   18275 }
   18276 
   18277 template <typename Derived, typename Shape>
   18278 void ObjectHashTableBase<Derived, Shape>::RemoveEntry(int entry) {
   18279   this->set_the_hole(Derived::EntryToIndex(entry));
   18280   this->set_the_hole(Derived::EntryToIndex(entry) + 1);
   18281   this->ElementRemoved();
   18282 }
   18283 
   18284 
   18285 void JSSet::Initialize(Handle<JSSet> set, Isolate* isolate) {
   18286   Handle<OrderedHashSet> table = isolate->factory()->NewOrderedHashSet();
   18287   set->set_table(*table);
   18288 }
   18289 
   18290 void JSSet::Clear(Isolate* isolate, Handle<JSSet> set) {
   18291   Handle<OrderedHashSet> table(OrderedHashSet::cast(set->table()), isolate);
   18292   table = OrderedHashSet::Clear(isolate, table);
   18293   set->set_table(*table);
   18294 }
   18295 
   18296 
   18297 void JSMap::Initialize(Handle<JSMap> map, Isolate* isolate) {
   18298   Handle<OrderedHashMap> table = isolate->factory()->NewOrderedHashMap();
   18299   map->set_table(*table);
   18300 }
   18301 
   18302 void JSMap::Clear(Isolate* isolate, Handle<JSMap> map) {
   18303   Handle<OrderedHashMap> table(OrderedHashMap::cast(map->table()), isolate);
   18304   table = OrderedHashMap::Clear(isolate, table);
   18305   map->set_table(*table);
   18306 }
   18307 
   18308 
   18309 void JSWeakCollection::Initialize(Handle<JSWeakCollection> weak_collection,
   18310                                   Isolate* isolate) {
   18311   Handle<EphemeronHashTable> table = EphemeronHashTable::New(isolate, 0);
   18312   weak_collection->set_table(*table);
   18313 }
   18314 
   18315 
   18316 void JSWeakCollection::Set(Handle<JSWeakCollection> weak_collection,
   18317                            Handle<Object> key, Handle<Object> value,
   18318                            int32_t hash) {
   18319   DCHECK(key->IsJSReceiver() || key->IsSymbol());
   18320   Handle<EphemeronHashTable> table(
   18321       EphemeronHashTable::cast(weak_collection->table()),
   18322       weak_collection->GetIsolate());
   18323   DCHECK(table->IsKey(weak_collection->GetReadOnlyRoots(), *key));
   18324   Handle<EphemeronHashTable> new_table = EphemeronHashTable::Put(
   18325       weak_collection->GetIsolate(), table, key, value, hash);
   18326   weak_collection->set_table(*new_table);
   18327   if (*table != *new_table) {
   18328     // Zap the old table since we didn't record slots for its elements.
   18329     EphemeronHashTable::FillEntriesWithHoles(table);
   18330   }
   18331 }
   18332 
   18333 
   18334 bool JSWeakCollection::Delete(Handle<JSWeakCollection> weak_collection,
   18335                               Handle<Object> key, int32_t hash) {
   18336   DCHECK(key->IsJSReceiver() || key->IsSymbol());
   18337   Handle<EphemeronHashTable> table(
   18338       EphemeronHashTable::cast(weak_collection->table()),
   18339       weak_collection->GetIsolate());
   18340   DCHECK(table->IsKey(weak_collection->GetReadOnlyRoots(), *key));
   18341   bool was_present = false;
   18342   Handle<EphemeronHashTable> new_table = EphemeronHashTable::Remove(
   18343       weak_collection->GetIsolate(), table, key, &was_present, hash);
   18344   weak_collection->set_table(*new_table);
   18345   if (*table != *new_table) {
   18346     // Zap the old table since we didn't record slots for its elements.
   18347     EphemeronHashTable::FillEntriesWithHoles(table);
   18348   }
   18349   return was_present;
   18350 }
   18351 
   18352 Handle<JSArray> JSWeakCollection::GetEntries(Handle<JSWeakCollection> holder,
   18353                                              int max_entries) {
   18354   Isolate* isolate = holder->GetIsolate();
   18355   Handle<EphemeronHashTable> table(EphemeronHashTable::cast(holder->table()),
   18356                                    isolate);
   18357   if (max_entries == 0 || max_entries > table->NumberOfElements()) {
   18358     max_entries = table->NumberOfElements();
   18359   }
   18360   int values_per_entry = holder->IsJSWeakMap() ? 2 : 1;
   18361   Handle<FixedArray> entries =
   18362       isolate->factory()->NewFixedArray(max_entries * values_per_entry);
   18363   // Recompute max_values because GC could have removed elements from the table.
   18364   if (max_entries > table->NumberOfElements()) {
   18365     max_entries = table->NumberOfElements();
   18366   }
   18367 
   18368   {
   18369     DisallowHeapAllocation no_gc;
   18370     ReadOnlyRoots roots = ReadOnlyRoots(isolate);
   18371     int count = 0;
   18372     for (int i = 0;
   18373          count / values_per_entry < max_entries && i < table->Capacity(); i++) {
   18374       Object* key;
   18375       if (table->ToKey(roots, i, &key)) {
   18376         entries->set(count++, key);
   18377         if (values_per_entry > 1) {
   18378           Object* value = table->Lookup(handle(key, isolate));
   18379           entries->set(count++, value);
   18380         }
   18381       }
   18382     }
   18383     DCHECK_EQ(max_entries * values_per_entry, count);
   18384   }
   18385   return isolate->factory()->NewJSArrayWithElements(entries);
   18386 }
   18387 
   18388 // static
   18389 MaybeHandle<JSDate> JSDate::New(Handle<JSFunction> constructor,
   18390                                 Handle<JSReceiver> new_target, double tv) {
   18391   Isolate* const isolate = constructor->GetIsolate();
   18392   Handle<JSObject> result;
   18393   ASSIGN_RETURN_ON_EXCEPTION(isolate, result,
   18394                              JSObject::New(constructor, new_target), JSDate);
   18395   if (-DateCache::kMaxTimeInMs <= tv && tv <= DateCache::kMaxTimeInMs) {
   18396     tv = DoubleToInteger(tv) + 0.0;
   18397   } else {
   18398     tv = std::numeric_limits<double>::quiet_NaN();
   18399   }
   18400   Handle<Object> value = isolate->factory()->NewNumber(tv);
   18401   Handle<JSDate>::cast(result)->SetValue(*value, std::isnan(tv));
   18402   return Handle<JSDate>::cast(result);
   18403 }
   18404 
   18405 
   18406 // static
   18407 double JSDate::CurrentTimeValue(Isolate* isolate) {
   18408   if (FLAG_log_internal_timer_events) LOG(isolate, CurrentTimeEvent());
   18409 
   18410   // According to ECMA-262, section 15.9.1, page 117, the precision of
   18411   // the number in a Date object representing a particular instant in
   18412   // time is milliseconds. Therefore, we floor the result of getting
   18413   // the OS time.
   18414   return Floor(V8::GetCurrentPlatform()->CurrentClockTimeMillis());
   18415 }
   18416 
   18417 
   18418 // static
   18419 Object* JSDate::GetField(Object* object, Smi* index) {
   18420   return JSDate::cast(object)->DoGetField(
   18421       static_cast<FieldIndex>(index->value()));
   18422 }
   18423 
   18424 
   18425 Object* JSDate::DoGetField(FieldIndex index) {
   18426   DCHECK_NE(index, kDateValue);
   18427 
   18428   DateCache* date_cache = GetIsolate()->date_cache();
   18429 
   18430   if (index < kFirstUncachedField) {
   18431     Object* stamp = cache_stamp();
   18432     if (stamp != date_cache->stamp() && stamp->IsSmi()) {
   18433       // Since the stamp is not NaN, the value is also not NaN.
   18434       int64_t local_time_ms =
   18435           date_cache->ToLocal(static_cast<int64_t>(value()->Number()));
   18436       SetCachedFields(local_time_ms, date_cache);
   18437     }
   18438     switch (index) {
   18439       case kYear: return year();
   18440       case kMonth: return month();
   18441       case kDay: return day();
   18442       case kWeekday: return weekday();
   18443       case kHour: return hour();
   18444       case kMinute: return min();
   18445       case kSecond: return sec();
   18446       default: UNREACHABLE();
   18447     }
   18448   }
   18449 
   18450   if (index >= kFirstUTCField) {
   18451     return GetUTCField(index, value()->Number(), date_cache);
   18452   }
   18453 
   18454   double time = value()->Number();
   18455   if (std::isnan(time)) return GetReadOnlyRoots().nan_value();
   18456 
   18457   int64_t local_time_ms = date_cache->ToLocal(static_cast<int64_t>(time));
   18458   int days = DateCache::DaysFromTime(local_time_ms);
   18459 
   18460   if (index == kDays) return Smi::FromInt(days);
   18461 
   18462   int time_in_day_ms = DateCache::TimeInDay(local_time_ms, days);
   18463   if (index == kMillisecond) return Smi::FromInt(time_in_day_ms % 1000);
   18464   DCHECK_EQ(index, kTimeInDay);
   18465   return Smi::FromInt(time_in_day_ms);
   18466 }
   18467 
   18468 
   18469 Object* JSDate::GetUTCField(FieldIndex index,
   18470                             double value,
   18471                             DateCache* date_cache) {
   18472   DCHECK_GE(index, kFirstUTCField);
   18473 
   18474   if (std::isnan(value)) return GetReadOnlyRoots().nan_value();
   18475 
   18476   int64_t time_ms = static_cast<int64_t>(value);
   18477 
   18478   if (index == kTimezoneOffset) {
   18479     return Smi::FromInt(date_cache->TimezoneOffset(time_ms));
   18480   }
   18481 
   18482   int days = DateCache::DaysFromTime(time_ms);
   18483 
   18484   if (index == kWeekdayUTC) return Smi::FromInt(date_cache->Weekday(days));
   18485 
   18486   if (index <= kDayUTC) {
   18487     int year, month, day;
   18488     date_cache->YearMonthDayFromDays(days, &year, &month, &day);
   18489     if (index == kYearUTC) return Smi::FromInt(year);
   18490     if (index == kMonthUTC) return Smi::FromInt(month);
   18491     DCHECK_EQ(index, kDayUTC);
   18492     return Smi::FromInt(day);
   18493   }
   18494 
   18495   int time_in_day_ms = DateCache::TimeInDay(time_ms, days);
   18496   switch (index) {
   18497     case kHourUTC: return Smi::FromInt(time_in_day_ms / (60 * 60 * 1000));
   18498     case kMinuteUTC: return Smi::FromInt((time_in_day_ms / (60 * 1000)) % 60);
   18499     case kSecondUTC: return Smi::FromInt((time_in_day_ms / 1000) % 60);
   18500     case kMillisecondUTC: return Smi::FromInt(time_in_day_ms % 1000);
   18501     case kDaysUTC: return Smi::FromInt(days);
   18502     case kTimeInDayUTC: return Smi::FromInt(time_in_day_ms);
   18503     default: UNREACHABLE();
   18504   }
   18505 
   18506   UNREACHABLE();
   18507 }
   18508 
   18509 
   18510 // static
   18511 Handle<Object> JSDate::SetValue(Handle<JSDate> date, double v) {
   18512   Isolate* const isolate = date->GetIsolate();
   18513   Handle<Object> value = isolate->factory()->NewNumber(v);
   18514   bool value_is_nan = std::isnan(v);
   18515   date->SetValue(*value, value_is_nan);
   18516   return value;
   18517 }
   18518 
   18519 
   18520 void JSDate::SetValue(Object* value, bool is_value_nan) {
   18521   set_value(value);
   18522   if (is_value_nan) {
   18523     HeapNumber* nan = GetReadOnlyRoots().nan_value();
   18524     set_cache_stamp(nan, SKIP_WRITE_BARRIER);
   18525     set_year(nan, SKIP_WRITE_BARRIER);
   18526     set_month(nan, SKIP_WRITE_BARRIER);
   18527     set_day(nan, SKIP_WRITE_BARRIER);
   18528     set_hour(nan, SKIP_WRITE_BARRIER);
   18529     set_min(nan, SKIP_WRITE_BARRIER);
   18530     set_sec(nan, SKIP_WRITE_BARRIER);
   18531     set_weekday(nan, SKIP_WRITE_BARRIER);
   18532   } else {
   18533     set_cache_stamp(Smi::FromInt(DateCache::kInvalidStamp), SKIP_WRITE_BARRIER);
   18534   }
   18535 }
   18536 
   18537 
   18538 void JSDate::SetCachedFields(int64_t local_time_ms, DateCache* date_cache) {
   18539   int days = DateCache::DaysFromTime(local_time_ms);
   18540   int time_in_day_ms = DateCache::TimeInDay(local_time_ms, days);
   18541   int year, month, day;
   18542   date_cache->YearMonthDayFromDays(days, &year, &month, &day);
   18543   int weekday = date_cache->Weekday(days);
   18544   int hour = time_in_day_ms / (60 * 60 * 1000);
   18545   int min = (time_in_day_ms / (60 * 1000)) % 60;
   18546   int sec = (time_in_day_ms / 1000) % 60;
   18547   set_cache_stamp(date_cache->stamp());
   18548   set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER);
   18549   set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER);
   18550   set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER);
   18551   set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER);
   18552   set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER);
   18553   set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER);
   18554   set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER);
   18555 }
   18556 
   18557 int JSMessageObject::GetLineNumber() const {
   18558   if (start_position() == -1) return Message::kNoLineNumberInfo;
   18559 
   18560   Handle<Script> the_script(script(), GetIsolate());
   18561 
   18562   Script::PositionInfo info;
   18563   const Script::OffsetFlag offset_flag = Script::WITH_OFFSET;
   18564   if (!Script::GetPositionInfo(the_script, start_position(), &info,
   18565                                offset_flag)) {
   18566     return Message::kNoLineNumberInfo;
   18567   }
   18568 
   18569   return info.line + 1;
   18570 }
   18571 
   18572 int JSMessageObject::GetColumnNumber() const {
   18573   if (start_position() == -1) return -1;
   18574 
   18575   Handle<Script> the_script(script(), GetIsolate());
   18576 
   18577   Script::PositionInfo info;
   18578   const Script::OffsetFlag offset_flag = Script::WITH_OFFSET;
   18579   if (!Script::GetPositionInfo(the_script, start_position(), &info,
   18580                                offset_flag)) {
   18581     return -1;
   18582   }
   18583 
   18584   return info.column;  // Note: No '+1' in contrast to GetLineNumber.
   18585 }
   18586 
   18587 Handle<String> JSMessageObject::GetSourceLine() const {
   18588   Isolate* isolate = GetIsolate();
   18589   Handle<Script> the_script(script(), isolate);
   18590 
   18591   if (the_script->type() == Script::TYPE_WASM) {
   18592     return isolate->factory()->empty_string();
   18593   }
   18594 
   18595   Script::PositionInfo info;
   18596   const Script::OffsetFlag offset_flag = Script::WITH_OFFSET;
   18597   if (!Script::GetPositionInfo(the_script, start_position(), &info,
   18598                                offset_flag)) {
   18599     return isolate->factory()->empty_string();
   18600   }
   18601 
   18602   Handle<String> src = handle(String::cast(the_script->source()), isolate);
   18603   return isolate->factory()->NewSubString(src, info.line_start, info.line_end);
   18604 }
   18605 
   18606 Handle<PropertyCell> PropertyCell::InvalidateEntry(
   18607     Isolate* isolate, Handle<GlobalDictionary> dictionary, int entry) {
   18608   // Swap with a copy.
   18609   Handle<PropertyCell> cell(dictionary->CellAt(entry), isolate);
   18610   Handle<Name> name(cell->name(), isolate);
   18611   Handle<PropertyCell> new_cell = isolate->factory()->NewPropertyCell(name);
   18612   new_cell->set_value(cell->value());
   18613   dictionary->ValueAtPut(entry, *new_cell);
   18614   bool is_the_hole = cell->value()->IsTheHole(isolate);
   18615   // Cell is officially mutable henceforth.
   18616   PropertyDetails details = cell->property_details();
   18617   details = details.set_cell_type(is_the_hole ? PropertyCellType::kUninitialized
   18618                                               : PropertyCellType::kMutable);
   18619   new_cell->set_property_details(details);
   18620   // Old cell is ready for invalidation.
   18621   if (is_the_hole) {
   18622     cell->set_value(ReadOnlyRoots(isolate).undefined_value());
   18623   } else {
   18624     cell->set_value(ReadOnlyRoots(isolate).the_hole_value());
   18625   }
   18626   details = details.set_cell_type(PropertyCellType::kInvalidated);
   18627   cell->set_property_details(details);
   18628   cell->dependent_code()->DeoptimizeDependentCodeGroup(
   18629       isolate, DependentCode::kPropertyCellChangedGroup);
   18630   return new_cell;
   18631 }
   18632 
   18633 
   18634 PropertyCellConstantType PropertyCell::GetConstantType() {
   18635   if (value()->IsSmi()) return PropertyCellConstantType::kSmi;
   18636   return PropertyCellConstantType::kStableMap;
   18637 }
   18638 
   18639 
   18640 static bool RemainsConstantType(Handle<PropertyCell> cell,
   18641                                 Handle<Object> value) {
   18642   // TODO(dcarney): double->smi and smi->double transition from kConstant
   18643   if (cell->value()->IsSmi() && value->IsSmi()) {
   18644     return true;
   18645   } else if (cell->value()->IsHeapObject() && value->IsHeapObject()) {
   18646     return HeapObject::cast(cell->value())->map() ==
   18647                HeapObject::cast(*value)->map() &&
   18648            HeapObject::cast(*value)->map()->is_stable();
   18649   }
   18650   return false;
   18651 }
   18652 
   18653 PropertyCellType PropertyCell::UpdatedType(Isolate* isolate,
   18654                                            Handle<PropertyCell> cell,
   18655                                            Handle<Object> value,
   18656                                            PropertyDetails details) {
   18657   PropertyCellType type = details.cell_type();
   18658   DCHECK(!value->IsTheHole(isolate));
   18659   if (cell->value()->IsTheHole(isolate)) {
   18660     switch (type) {
   18661       // Only allow a cell to transition once into constant state.
   18662       case PropertyCellType::kUninitialized:
   18663         if (value->IsUndefined(isolate)) return PropertyCellType::kUndefined;
   18664         return PropertyCellType::kConstant;
   18665       case PropertyCellType::kInvalidated:
   18666         return PropertyCellType::kMutable;
   18667       default:
   18668         UNREACHABLE();
   18669     }
   18670   }
   18671   switch (type) {
   18672     case PropertyCellType::kUndefined:
   18673       return PropertyCellType::kConstant;
   18674     case PropertyCellType::kConstant:
   18675       if (*value == cell->value()) return PropertyCellType::kConstant;
   18676       V8_FALLTHROUGH;
   18677     case PropertyCellType::kConstantType:
   18678       if (RemainsConstantType(cell, value)) {
   18679         return PropertyCellType::kConstantType;
   18680       }
   18681       V8_FALLTHROUGH;
   18682     case PropertyCellType::kMutable:
   18683       return PropertyCellType::kMutable;
   18684   }
   18685   UNREACHABLE();
   18686 }
   18687 
   18688 Handle<PropertyCell> PropertyCell::PrepareForValue(
   18689     Isolate* isolate, Handle<GlobalDictionary> dictionary, int entry,
   18690     Handle<Object> value, PropertyDetails details) {
   18691   DCHECK(!value->IsTheHole(isolate));
   18692   Handle<PropertyCell> cell(dictionary->CellAt(entry), isolate);
   18693   const PropertyDetails original_details = cell->property_details();
   18694   // Data accesses could be cached in ics or optimized code.
   18695   bool invalidate =
   18696       (original_details.kind() == kData && details.kind() == kAccessor) ||
   18697       (!original_details.IsReadOnly() && details.IsReadOnly());
   18698   int index;
   18699   PropertyCellType old_type = original_details.cell_type();
   18700   // Preserve the enumeration index unless the property was deleted or never
   18701   // initialized.
   18702   if (cell->value()->IsTheHole(isolate)) {
   18703     index = dictionary->NextEnumerationIndex();
   18704     dictionary->SetNextEnumerationIndex(index + 1);
   18705   } else {
   18706     index = original_details.dictionary_index();
   18707   }
   18708   DCHECK_LT(0, index);
   18709   details = details.set_index(index);
   18710 
   18711   PropertyCellType new_type =
   18712       UpdatedType(isolate, cell, value, original_details);
   18713   if (invalidate) {
   18714     cell = PropertyCell::InvalidateEntry(isolate, dictionary, entry);
   18715   }
   18716 
   18717   // Install new property details.
   18718   details = details.set_cell_type(new_type);
   18719   cell->set_property_details(details);
   18720 
   18721   if (new_type == PropertyCellType::kConstant ||
   18722       new_type == PropertyCellType::kConstantType) {
   18723     // Store the value now to ensure that the cell contains the constant or
   18724     // type information. Otherwise subsequent store operation will turn
   18725     // the cell to mutable.
   18726     cell->set_value(*value);
   18727   }
   18728 
   18729   // Deopt when transitioning from a constant type.
   18730   if (!invalidate && (old_type != new_type ||
   18731                       original_details.IsReadOnly() != details.IsReadOnly())) {
   18732     cell->dependent_code()->DeoptimizeDependentCodeGroup(
   18733         isolate, DependentCode::kPropertyCellChangedGroup);
   18734   }
   18735   return cell;
   18736 }
   18737 
   18738 
   18739 // static
   18740 void PropertyCell::SetValueWithInvalidation(Isolate* isolate,
   18741                                             Handle<PropertyCell> cell,
   18742                                             Handle<Object> new_value) {
   18743   if (cell->value() != *new_value) {
   18744     cell->set_value(*new_value);
   18745     cell->dependent_code()->DeoptimizeDependentCodeGroup(
   18746         isolate, DependentCode::kPropertyCellChangedGroup);
   18747   }
   18748 }
   18749 
   18750 int JSGeneratorObject::source_position() const {
   18751   CHECK(is_suspended());
   18752   DCHECK(function()->shared()->HasBytecodeArray());
   18753 
   18754   int code_offset = Smi::ToInt(input_or_debug_pos());
   18755 
   18756   // The stored bytecode offset is relative to a different base than what
   18757   // is used in the source position table, hence the subtraction.
   18758   code_offset -= BytecodeArray::kHeaderSize - kHeapObjectTag;
   18759   AbstractCode* code =
   18760       AbstractCode::cast(function()->shared()->GetBytecodeArray());
   18761   return code->SourcePosition(code_offset);
   18762 }
   18763 
   18764 // static
   18765 AccessCheckInfo* AccessCheckInfo::Get(Isolate* isolate,
   18766                                       Handle<JSObject> receiver) {
   18767   DisallowHeapAllocation no_gc;
   18768   DCHECK(receiver->map()->is_access_check_needed());
   18769   Object* maybe_constructor = receiver->map()->GetConstructor();
   18770   if (maybe_constructor->IsFunctionTemplateInfo()) {
   18771     Object* data_obj =
   18772         FunctionTemplateInfo::cast(maybe_constructor)->access_check_info();
   18773     if (data_obj->IsUndefined(isolate)) return nullptr;
   18774     return AccessCheckInfo::cast(data_obj);
   18775   }
   18776   // Might happen for a detached context.
   18777   if (!maybe_constructor->IsJSFunction()) return nullptr;
   18778   JSFunction* constructor = JSFunction::cast(maybe_constructor);
   18779   // Might happen for the debug context.
   18780   if (!constructor->shared()->IsApiFunction()) return nullptr;
   18781 
   18782   Object* data_obj =
   18783       constructor->shared()->get_api_func_data()->access_check_info();
   18784   if (data_obj->IsUndefined(isolate)) return nullptr;
   18785 
   18786   return AccessCheckInfo::cast(data_obj);
   18787 }
   18788 
   18789 bool JSReceiver::HasProxyInPrototype(Isolate* isolate) {
   18790   for (PrototypeIterator iter(isolate, this, kStartAtReceiver,
   18791                               PrototypeIterator::END_AT_NULL);
   18792        !iter.IsAtEnd(); iter.AdvanceIgnoringProxies()) {
   18793     if (iter.GetCurrent<Object>()->IsJSProxy()) return true;
   18794   }
   18795   return false;
   18796 }
   18797 
   18798 bool JSReceiver::HasComplexElements() {
   18799   if (IsJSProxy()) return true;
   18800   JSObject* this_object = JSObject::cast(this);
   18801   if (this_object->HasIndexedInterceptor()) {
   18802     return true;
   18803   }
   18804   if (!this_object->HasDictionaryElements()) return false;
   18805   return this_object->element_dictionary()->HasComplexElements();
   18806 }
   18807 
   18808 MaybeHandle<Name> FunctionTemplateInfo::TryGetCachedPropertyName(
   18809     Isolate* isolate, Handle<Object> getter) {
   18810   if (getter->IsFunctionTemplateInfo()) {
   18811     Handle<FunctionTemplateInfo> fti =
   18812         Handle<FunctionTemplateInfo>::cast(getter);
   18813     // Check if the accessor uses a cached property.
   18814     if (!fti->cached_property_name()->IsTheHole(isolate)) {
   18815       return handle(Name::cast(fti->cached_property_name()), isolate);
   18816     }
   18817   }
   18818   return MaybeHandle<Name>();
   18819 }
   18820 
   18821 // Force instantiation of template instances class.
   18822 // Please note this list is compiler dependent.
   18823 // Keep this at the end of this file
   18824 
   18825 template class HashTable<StringTable, StringTableShape>;
   18826 
   18827 template class HashTable<CompilationCacheTable, CompilationCacheShape>;
   18828 
   18829 template class HashTable<ObjectHashTable, ObjectHashTableShape>;
   18830 
   18831 template class HashTable<EphemeronHashTable, EphemeronHashTableShape>;
   18832 
   18833 template class ObjectHashTableBase<ObjectHashTable, ObjectHashTableShape>;
   18834 
   18835 template class ObjectHashTableBase<EphemeronHashTable, EphemeronHashTableShape>;
   18836 
   18837 template class Dictionary<NameDictionary, NameDictionaryShape>;
   18838 
   18839 template class Dictionary<GlobalDictionary, GlobalDictionaryShape>;
   18840 
   18841 template class EXPORT_TEMPLATE_DEFINE(
   18842     V8_EXPORT_PRIVATE) HashTable<NumberDictionary, NumberDictionaryShape>;
   18843 
   18844 template class EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
   18845     Dictionary<NumberDictionary, NumberDictionaryShape>;
   18846 
   18847 template class EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
   18848     HashTable<SimpleNumberDictionary, SimpleNumberDictionaryShape>;
   18849 
   18850 template class EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
   18851     Dictionary<SimpleNumberDictionary, SimpleNumberDictionaryShape>;
   18852 
   18853 template Handle<NameDictionary>
   18854 BaseNameDictionary<NameDictionary, NameDictionaryShape>::New(
   18855     Isolate*, int n, PretenureFlag pretenure, MinimumCapacity capacity_option);
   18856 
   18857 template Handle<GlobalDictionary>
   18858 BaseNameDictionary<GlobalDictionary, GlobalDictionaryShape>::New(
   18859     Isolate*, int n, PretenureFlag pretenure, MinimumCapacity capacity_option);
   18860 
   18861 template Handle<NameDictionary>
   18862 HashTable<NameDictionary, NameDictionaryShape>::New(Isolate*, int,
   18863                                                     PretenureFlag,
   18864                                                     MinimumCapacity);
   18865 
   18866 template Handle<ObjectHashSet>
   18867 HashTable<ObjectHashSet, ObjectHashSetShape>::New(Isolate*, int n,
   18868                                                   PretenureFlag,
   18869                                                   MinimumCapacity);
   18870 
   18871 template Handle<NameDictionary>
   18872 HashTable<NameDictionary, NameDictionaryShape>::Shrink(Isolate* isolate,
   18873                                                        Handle<NameDictionary>,
   18874                                                        int additionalCapacity);
   18875 
   18876 template Handle<NameDictionary>
   18877 BaseNameDictionary<NameDictionary, NameDictionaryShape>::Add(
   18878     Isolate* isolate, Handle<NameDictionary>, Handle<Name>, Handle<Object>,
   18879     PropertyDetails, int*);
   18880 
   18881 template Handle<GlobalDictionary>
   18882 BaseNameDictionary<GlobalDictionary, GlobalDictionaryShape>::Add(
   18883     Isolate* isolate, Handle<GlobalDictionary>, Handle<Name>, Handle<Object>,
   18884     PropertyDetails, int*);
   18885 
   18886 template void HashTable<GlobalDictionary, GlobalDictionaryShape>::Rehash(
   18887     Isolate* isolate);
   18888 
   18889 template Handle<NameDictionary>
   18890 BaseNameDictionary<NameDictionary, NameDictionaryShape>::EnsureCapacity(
   18891     Isolate* isolate, Handle<NameDictionary>, int);
   18892 
   18893 template void
   18894 BaseNameDictionary<GlobalDictionary, GlobalDictionaryShape>::CopyEnumKeysTo(
   18895     Isolate* isolate, Handle<GlobalDictionary> dictionary,
   18896     Handle<FixedArray> storage, KeyCollectionMode mode,
   18897     KeyAccumulator* accumulator);
   18898 
   18899 template void
   18900 BaseNameDictionary<NameDictionary, NameDictionaryShape>::CopyEnumKeysTo(
   18901     Isolate* isolate, Handle<NameDictionary> dictionary,
   18902     Handle<FixedArray> storage, KeyCollectionMode mode,
   18903     KeyAccumulator* accumulator);
   18904 
   18905 template Handle<FixedArray>
   18906 BaseNameDictionary<GlobalDictionary, GlobalDictionaryShape>::IterationIndices(
   18907     Isolate* isolate, Handle<GlobalDictionary> dictionary);
   18908 template void
   18909 BaseNameDictionary<GlobalDictionary, GlobalDictionaryShape>::CollectKeysTo(
   18910     Handle<GlobalDictionary> dictionary, KeyAccumulator* keys);
   18911 
   18912 template Handle<FixedArray>
   18913 BaseNameDictionary<NameDictionary, NameDictionaryShape>::IterationIndices(
   18914     Isolate* isolate, Handle<NameDictionary> dictionary);
   18915 template void
   18916 BaseNameDictionary<NameDictionary, NameDictionaryShape>::CollectKeysTo(
   18917     Handle<NameDictionary> dictionary, KeyAccumulator* keys);
   18918 
   18919 }  // namespace internal
   18920 }  // namespace v8
   18921