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 <sstream>
     10 
     11 #include "src/objects-inl.h"
     12 
     13 #include "src/accessors.h"
     14 #include "src/allocation-site-scopes.h"
     15 #include "src/api-arguments-inl.h"
     16 #include "src/api-natives.h"
     17 #include "src/api.h"
     18 #include "src/base/bits.h"
     19 #include "src/base/utils/random-number-generator.h"
     20 #include "src/bootstrapper.h"
     21 #include "src/code-stubs.h"
     22 #include "src/codegen.h"
     23 #include "src/compilation-dependencies.h"
     24 #include "src/compiler.h"
     25 #include "src/counters-inl.h"
     26 #include "src/counters.h"
     27 #include "src/date.h"
     28 #include "src/debug/debug.h"
     29 #include "src/deoptimizer.h"
     30 #include "src/elements.h"
     31 #include "src/execution.h"
     32 #include "src/field-index-inl.h"
     33 #include "src/field-index.h"
     34 #include "src/field-type.h"
     35 #include "src/frames-inl.h"
     36 #include "src/full-codegen/full-codegen.h"
     37 #include "src/ic/ic.h"
     38 #include "src/identity-map.h"
     39 #include "src/interpreter/bytecode-array-iterator.h"
     40 #include "src/interpreter/interpreter.h"
     41 #include "src/interpreter/source-position-table.h"
     42 #include "src/isolate-inl.h"
     43 #include "src/keys.h"
     44 #include "src/list.h"
     45 #include "src/log.h"
     46 #include "src/lookup.h"
     47 #include "src/macro-assembler.h"
     48 #include "src/messages.h"
     49 #include "src/objects-body-descriptors-inl.h"
     50 #include "src/property-descriptor.h"
     51 #include "src/prototype.h"
     52 #include "src/regexp/jsregexp.h"
     53 #include "src/safepoint-table.h"
     54 #include "src/string-builder.h"
     55 #include "src/string-search.h"
     56 #include "src/string-stream.h"
     57 #include "src/utils.h"
     58 #include "src/zone.h"
     59 
     60 #ifdef ENABLE_DISASSEMBLER
     61 #include "src/disasm.h"
     62 #include "src/disassembler.h"
     63 #endif
     64 
     65 namespace v8 {
     66 namespace internal {
     67 
     68 std::ostream& operator<<(std::ostream& os, InstanceType instance_type) {
     69   switch (instance_type) {
     70 #define WRITE_TYPE(TYPE) \
     71   case TYPE:             \
     72     return os << #TYPE;
     73     INSTANCE_TYPE_LIST(WRITE_TYPE)
     74 #undef WRITE_TYPE
     75   }
     76   UNREACHABLE();
     77   return os << "UNKNOWN";  // Keep the compiler happy.
     78 }
     79 
     80 Handle<FieldType> Object::OptimalType(Isolate* isolate,
     81                                       Representation representation) {
     82   if (representation.IsNone()) return FieldType::None(isolate);
     83   if (FLAG_track_field_types) {
     84     if (representation.IsHeapObject() && IsHeapObject()) {
     85       // We can track only JavaScript objects with stable maps.
     86       Handle<Map> map(HeapObject::cast(this)->map(), isolate);
     87       if (map->is_stable() && map->IsJSReceiverMap()) {
     88         return FieldType::Class(map, isolate);
     89       }
     90     }
     91   }
     92   return FieldType::Any(isolate);
     93 }
     94 
     95 
     96 MaybeHandle<JSReceiver> Object::ToObject(Isolate* isolate,
     97                                          Handle<Object> object,
     98                                          Handle<Context> native_context) {
     99   if (object->IsJSReceiver()) return Handle<JSReceiver>::cast(object);
    100   Handle<JSFunction> constructor;
    101   if (object->IsSmi()) {
    102     constructor = handle(native_context->number_function(), isolate);
    103   } else {
    104     int constructor_function_index =
    105         Handle<HeapObject>::cast(object)->map()->GetConstructorFunctionIndex();
    106     if (constructor_function_index == Map::kNoConstructorFunctionIndex) {
    107       THROW_NEW_ERROR(isolate,
    108                       NewTypeError(MessageTemplate::kUndefinedOrNullToObject),
    109                       JSReceiver);
    110     }
    111     constructor = handle(
    112         JSFunction::cast(native_context->get(constructor_function_index)),
    113         isolate);
    114   }
    115   Handle<JSObject> result = isolate->factory()->NewJSObject(constructor);
    116   Handle<JSValue>::cast(result)->set_value(*object);
    117   return result;
    118 }
    119 
    120 // ES6 section 9.2.1.2, OrdinaryCallBindThis for sloppy callee.
    121 // static
    122 MaybeHandle<JSReceiver> Object::ConvertReceiver(Isolate* isolate,
    123                                                 Handle<Object> object) {
    124   if (object->IsJSReceiver()) return Handle<JSReceiver>::cast(object);
    125   if (*object == isolate->heap()->null_value() ||
    126       object->IsUndefined(isolate)) {
    127     return isolate->global_proxy();
    128   }
    129   return Object::ToObject(isolate, object);
    130 }
    131 
    132 // static
    133 MaybeHandle<Object> Object::ToNumber(Handle<Object> input) {
    134   while (true) {
    135     if (input->IsNumber()) {
    136       return input;
    137     }
    138     if (input->IsString()) {
    139       return String::ToNumber(Handle<String>::cast(input));
    140     }
    141     if (input->IsOddball()) {
    142       return Oddball::ToNumber(Handle<Oddball>::cast(input));
    143     }
    144     Isolate* const isolate = Handle<HeapObject>::cast(input)->GetIsolate();
    145     if (input->IsSymbol()) {
    146       THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kSymbolToNumber),
    147                       Object);
    148     }
    149     if (input->IsSimd128Value()) {
    150       THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kSimdToNumber),
    151                       Object);
    152     }
    153     ASSIGN_RETURN_ON_EXCEPTION(
    154         isolate, input, JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(input),
    155                                                 ToPrimitiveHint::kNumber),
    156         Object);
    157   }
    158 }
    159 
    160 
    161 // static
    162 MaybeHandle<Object> Object::ToInteger(Isolate* isolate, Handle<Object> input) {
    163   ASSIGN_RETURN_ON_EXCEPTION(isolate, input, ToNumber(input), Object);
    164   return isolate->factory()->NewNumber(DoubleToInteger(input->Number()));
    165 }
    166 
    167 
    168 // static
    169 MaybeHandle<Object> Object::ToInt32(Isolate* isolate, Handle<Object> input) {
    170   ASSIGN_RETURN_ON_EXCEPTION(isolate, input, ToNumber(input), Object);
    171   return isolate->factory()->NewNumberFromInt(DoubleToInt32(input->Number()));
    172 }
    173 
    174 
    175 // static
    176 MaybeHandle<Object> Object::ToUint32(Isolate* isolate, Handle<Object> input) {
    177   ASSIGN_RETURN_ON_EXCEPTION(isolate, input, ToNumber(input), Object);
    178   return isolate->factory()->NewNumberFromUint(DoubleToUint32(input->Number()));
    179 }
    180 
    181 
    182 // static
    183 MaybeHandle<Name> Object::ConvertToName(Isolate* isolate,
    184                                         Handle<Object> input) {
    185   ASSIGN_RETURN_ON_EXCEPTION(
    186       isolate, input, Object::ToPrimitive(input, ToPrimitiveHint::kString),
    187       Name);
    188   if (input->IsName()) return Handle<Name>::cast(input);
    189   return ToString(isolate, input);
    190 }
    191 
    192 // static
    193 MaybeHandle<String> Object::ToString(Isolate* isolate, Handle<Object> input) {
    194   while (true) {
    195     if (input->IsString()) {
    196       return Handle<String>::cast(input);
    197     }
    198     if (input->IsOddball()) {
    199       return handle(Handle<Oddball>::cast(input)->to_string(), isolate);
    200     }
    201     if (input->IsNumber()) {
    202       return isolate->factory()->NumberToString(input);
    203     }
    204     if (input->IsSymbol()) {
    205       THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kSymbolToString),
    206                       String);
    207     }
    208     if (input->IsSimd128Value()) {
    209       return Simd128Value::ToString(Handle<Simd128Value>::cast(input));
    210     }
    211     ASSIGN_RETURN_ON_EXCEPTION(
    212         isolate, input, JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(input),
    213                                                 ToPrimitiveHint::kString),
    214         String);
    215   }
    216 }
    217 
    218 
    219 // static
    220 MaybeHandle<Object> Object::ToLength(Isolate* isolate, Handle<Object> input) {
    221   ASSIGN_RETURN_ON_EXCEPTION(isolate, input, ToNumber(input), Object);
    222   double len = DoubleToInteger(input->Number());
    223   if (len <= 0.0) {
    224     len = 0.0;
    225   } else if (len >= kMaxSafeInteger) {
    226     len = kMaxSafeInteger;
    227   }
    228   return isolate->factory()->NewNumber(len);
    229 }
    230 
    231 
    232 bool Object::BooleanValue() {
    233   if (IsSmi()) return Smi::cast(this)->value() != 0;
    234   DCHECK(IsHeapObject());
    235   Isolate* isolate = HeapObject::cast(this)->GetIsolate();
    236   if (IsBoolean()) return IsTrue(isolate);
    237   if (IsUndefined(isolate) || IsNull(isolate)) return false;
    238   if (IsUndetectable()) return false;  // Undetectable object is false.
    239   if (IsString()) return String::cast(this)->length() != 0;
    240   if (IsHeapNumber()) return HeapNumber::cast(this)->HeapNumberBooleanValue();
    241   return true;
    242 }
    243 
    244 
    245 namespace {
    246 
    247 // TODO(bmeurer): Maybe we should introduce a marker interface Number,
    248 // where we put all these methods at some point?
    249 ComparisonResult NumberCompare(double x, double y) {
    250   if (std::isnan(x) || std::isnan(y)) {
    251     return ComparisonResult::kUndefined;
    252   } else if (x < y) {
    253     return ComparisonResult::kLessThan;
    254   } else if (x > y) {
    255     return ComparisonResult::kGreaterThan;
    256   } else {
    257     return ComparisonResult::kEqual;
    258   }
    259 }
    260 
    261 
    262 bool NumberEquals(double x, double y) {
    263   // Must check explicitly for NaN's on Windows, but -0 works fine.
    264   if (std::isnan(x)) return false;
    265   if (std::isnan(y)) return false;
    266   return x == y;
    267 }
    268 
    269 
    270 bool NumberEquals(const Object* x, const Object* y) {
    271   return NumberEquals(x->Number(), y->Number());
    272 }
    273 
    274 
    275 bool NumberEquals(Handle<Object> x, Handle<Object> y) {
    276   return NumberEquals(*x, *y);
    277 }
    278 
    279 }  // namespace
    280 
    281 
    282 // static
    283 Maybe<ComparisonResult> Object::Compare(Handle<Object> x, Handle<Object> y) {
    284   // ES6 section 7.2.11 Abstract Relational Comparison step 3 and 4.
    285   if (!Object::ToPrimitive(x, ToPrimitiveHint::kNumber).ToHandle(&x) ||
    286       !Object::ToPrimitive(y, ToPrimitiveHint::kNumber).ToHandle(&y)) {
    287     return Nothing<ComparisonResult>();
    288   }
    289   if (x->IsString() && y->IsString()) {
    290     // ES6 section 7.2.11 Abstract Relational Comparison step 5.
    291     return Just(
    292         String::Compare(Handle<String>::cast(x), Handle<String>::cast(y)));
    293   }
    294   // ES6 section 7.2.11 Abstract Relational Comparison step 6.
    295   if (!Object::ToNumber(x).ToHandle(&x) || !Object::ToNumber(y).ToHandle(&y)) {
    296     return Nothing<ComparisonResult>();
    297   }
    298   return Just(NumberCompare(x->Number(), y->Number()));
    299 }
    300 
    301 
    302 // static
    303 Maybe<bool> Object::Equals(Handle<Object> x, Handle<Object> y) {
    304   // This is the generic version of Abstract Equality Comparison; a version in
    305   // JavaScript land is available in the EqualStub and NotEqualStub. Whenever
    306   // you change something functionality wise in here, remember to update the
    307   // TurboFan code stubs as well.
    308   while (true) {
    309     if (x->IsNumber()) {
    310       if (y->IsNumber()) {
    311         return Just(NumberEquals(x, y));
    312       } else if (y->IsBoolean()) {
    313         return Just(NumberEquals(*x, Handle<Oddball>::cast(y)->to_number()));
    314       } else if (y->IsString()) {
    315         return Just(NumberEquals(x, String::ToNumber(Handle<String>::cast(y))));
    316       } else if (y->IsJSReceiver()) {
    317         if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(y))
    318                  .ToHandle(&y)) {
    319           return Nothing<bool>();
    320         }
    321       } else {
    322         return Just(false);
    323       }
    324     } else if (x->IsString()) {
    325       if (y->IsString()) {
    326         return Just(
    327             String::Equals(Handle<String>::cast(x), Handle<String>::cast(y)));
    328       } else if (y->IsNumber()) {
    329         x = String::ToNumber(Handle<String>::cast(x));
    330         return Just(NumberEquals(x, y));
    331       } else if (y->IsBoolean()) {
    332         x = String::ToNumber(Handle<String>::cast(x));
    333         return Just(NumberEquals(*x, Handle<Oddball>::cast(y)->to_number()));
    334       } else if (y->IsJSReceiver()) {
    335         if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(y))
    336                  .ToHandle(&y)) {
    337           return Nothing<bool>();
    338         }
    339       } else {
    340         return Just(false);
    341       }
    342     } else if (x->IsBoolean()) {
    343       if (y->IsOddball()) {
    344         return Just(x.is_identical_to(y));
    345       } else if (y->IsNumber()) {
    346         return Just(NumberEquals(Handle<Oddball>::cast(x)->to_number(), *y));
    347       } else if (y->IsString()) {
    348         y = String::ToNumber(Handle<String>::cast(y));
    349         return Just(NumberEquals(Handle<Oddball>::cast(x)->to_number(), *y));
    350       } else if (y->IsJSReceiver()) {
    351         if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(y))
    352                  .ToHandle(&y)) {
    353           return Nothing<bool>();
    354         }
    355         x = Oddball::ToNumber(Handle<Oddball>::cast(x));
    356       } else {
    357         return Just(false);
    358       }
    359     } else if (x->IsSymbol()) {
    360       if (y->IsSymbol()) {
    361         return Just(x.is_identical_to(y));
    362       } else if (y->IsJSReceiver()) {
    363         if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(y))
    364                  .ToHandle(&y)) {
    365           return Nothing<bool>();
    366         }
    367       } else {
    368         return Just(false);
    369       }
    370     } else if (x->IsSimd128Value()) {
    371       if (y->IsSimd128Value()) {
    372         return Just(Simd128Value::Equals(Handle<Simd128Value>::cast(x),
    373                                          Handle<Simd128Value>::cast(y)));
    374       } else if (y->IsJSReceiver()) {
    375         if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(y))
    376                  .ToHandle(&y)) {
    377           return Nothing<bool>();
    378         }
    379       } else {
    380         return Just(false);
    381       }
    382     } else if (x->IsJSReceiver()) {
    383       if (y->IsJSReceiver()) {
    384         return Just(x.is_identical_to(y));
    385       } else if (y->IsUndetectable()) {
    386         return Just(x->IsUndetectable());
    387       } else if (y->IsBoolean()) {
    388         y = Oddball::ToNumber(Handle<Oddball>::cast(y));
    389       } else if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(x))
    390                       .ToHandle(&x)) {
    391         return Nothing<bool>();
    392       }
    393     } else {
    394       return Just(x->IsUndetectable() && y->IsUndetectable());
    395     }
    396   }
    397 }
    398 
    399 
    400 bool Object::StrictEquals(Object* that) {
    401   if (this->IsNumber()) {
    402     if (!that->IsNumber()) return false;
    403     return NumberEquals(this, that);
    404   } else if (this->IsString()) {
    405     if (!that->IsString()) return false;
    406     return String::cast(this)->Equals(String::cast(that));
    407   } else if (this->IsSimd128Value()) {
    408     if (!that->IsSimd128Value()) return false;
    409     return Simd128Value::cast(this)->Equals(Simd128Value::cast(that));
    410   }
    411   return this == that;
    412 }
    413 
    414 
    415 // static
    416 Handle<String> Object::TypeOf(Isolate* isolate, Handle<Object> object) {
    417   if (object->IsNumber()) return isolate->factory()->number_string();
    418   if (object->IsOddball()) return handle(Oddball::cast(*object)->type_of());
    419   if (object->IsUndetectable()) {
    420     return isolate->factory()->undefined_string();
    421   }
    422   if (object->IsString()) return isolate->factory()->string_string();
    423   if (object->IsSymbol()) return isolate->factory()->symbol_string();
    424   if (object->IsString()) return isolate->factory()->string_string();
    425 #define SIMD128_TYPE(TYPE, Type, type, lane_count, lane_type) \
    426   if (object->Is##Type()) return isolate->factory()->type##_string();
    427   SIMD128_TYPES(SIMD128_TYPE)
    428 #undef SIMD128_TYPE
    429   if (object->IsCallable()) return isolate->factory()->function_string();
    430   return isolate->factory()->object_string();
    431 }
    432 
    433 
    434 // static
    435 MaybeHandle<Object> Object::Multiply(Isolate* isolate, Handle<Object> lhs,
    436                                      Handle<Object> rhs) {
    437   if (!lhs->IsNumber() || !rhs->IsNumber()) {
    438     ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(lhs), Object);
    439     ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(rhs), Object);
    440   }
    441   return isolate->factory()->NewNumber(lhs->Number() * rhs->Number());
    442 }
    443 
    444 
    445 // static
    446 MaybeHandle<Object> Object::Divide(Isolate* isolate, Handle<Object> lhs,
    447                                    Handle<Object> rhs) {
    448   if (!lhs->IsNumber() || !rhs->IsNumber()) {
    449     ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(lhs), Object);
    450     ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(rhs), Object);
    451   }
    452   return isolate->factory()->NewNumber(lhs->Number() / rhs->Number());
    453 }
    454 
    455 
    456 // static
    457 MaybeHandle<Object> Object::Modulus(Isolate* isolate, Handle<Object> lhs,
    458                                     Handle<Object> rhs) {
    459   if (!lhs->IsNumber() || !rhs->IsNumber()) {
    460     ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(lhs), Object);
    461     ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(rhs), Object);
    462   }
    463   return isolate->factory()->NewNumber(modulo(lhs->Number(), rhs->Number()));
    464 }
    465 
    466 
    467 // static
    468 MaybeHandle<Object> Object::Add(Isolate* isolate, Handle<Object> lhs,
    469                                 Handle<Object> rhs) {
    470   if (lhs->IsNumber() && rhs->IsNumber()) {
    471     return isolate->factory()->NewNumber(lhs->Number() + rhs->Number());
    472   } else if (lhs->IsString() && rhs->IsString()) {
    473     return isolate->factory()->NewConsString(Handle<String>::cast(lhs),
    474                                              Handle<String>::cast(rhs));
    475   }
    476   ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToPrimitive(lhs), Object);
    477   ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToPrimitive(rhs), Object);
    478   if (lhs->IsString() || rhs->IsString()) {
    479     ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToString(isolate, rhs),
    480                                Object);
    481     ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToString(isolate, lhs),
    482                                Object);
    483     return isolate->factory()->NewConsString(Handle<String>::cast(lhs),
    484                                              Handle<String>::cast(rhs));
    485   }
    486   ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(rhs), Object);
    487   ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(lhs), Object);
    488   return isolate->factory()->NewNumber(lhs->Number() + rhs->Number());
    489 }
    490 
    491 
    492 // static
    493 MaybeHandle<Object> Object::Subtract(Isolate* isolate, Handle<Object> lhs,
    494                                      Handle<Object> rhs) {
    495   if (!lhs->IsNumber() || !rhs->IsNumber()) {
    496     ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(lhs), Object);
    497     ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(rhs), Object);
    498   }
    499   return isolate->factory()->NewNumber(lhs->Number() - rhs->Number());
    500 }
    501 
    502 
    503 // static
    504 MaybeHandle<Object> Object::ShiftLeft(Isolate* isolate, Handle<Object> lhs,
    505                                       Handle<Object> rhs) {
    506   if (!lhs->IsNumber() || !rhs->IsNumber()) {
    507     ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(lhs), Object);
    508     ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(rhs), Object);
    509   }
    510   return isolate->factory()->NewNumberFromInt(NumberToInt32(*lhs)
    511                                               << (NumberToUint32(*rhs) & 0x1F));
    512 }
    513 
    514 
    515 // static
    516 MaybeHandle<Object> Object::ShiftRight(Isolate* isolate, Handle<Object> lhs,
    517                                        Handle<Object> rhs) {
    518   if (!lhs->IsNumber() || !rhs->IsNumber()) {
    519     ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(lhs), Object);
    520     ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(rhs), Object);
    521   }
    522   return isolate->factory()->NewNumberFromInt(NumberToInt32(*lhs) >>
    523                                               (NumberToUint32(*rhs) & 0x1F));
    524 }
    525 
    526 
    527 // static
    528 MaybeHandle<Object> Object::ShiftRightLogical(Isolate* isolate,
    529                                               Handle<Object> lhs,
    530                                               Handle<Object> rhs) {
    531   if (!lhs->IsNumber() || !rhs->IsNumber()) {
    532     ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(lhs), Object);
    533     ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(rhs), Object);
    534   }
    535   return isolate->factory()->NewNumberFromUint(NumberToUint32(*lhs) >>
    536                                                (NumberToUint32(*rhs) & 0x1F));
    537 }
    538 
    539 
    540 // static
    541 MaybeHandle<Object> Object::BitwiseAnd(Isolate* isolate, Handle<Object> lhs,
    542                                        Handle<Object> rhs) {
    543   if (!lhs->IsNumber() || !rhs->IsNumber()) {
    544     ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(lhs), Object);
    545     ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(rhs), Object);
    546   }
    547   return isolate->factory()->NewNumberFromInt(NumberToInt32(*lhs) &
    548                                               NumberToInt32(*rhs));
    549 }
    550 
    551 
    552 // static
    553 MaybeHandle<Object> Object::BitwiseOr(Isolate* isolate, Handle<Object> lhs,
    554                                       Handle<Object> rhs) {
    555   if (!lhs->IsNumber() || !rhs->IsNumber()) {
    556     ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(lhs), Object);
    557     ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(rhs), Object);
    558   }
    559   return isolate->factory()->NewNumberFromInt(NumberToInt32(*lhs) |
    560                                               NumberToInt32(*rhs));
    561 }
    562 
    563 
    564 // static
    565 MaybeHandle<Object> Object::BitwiseXor(Isolate* isolate, Handle<Object> lhs,
    566                                        Handle<Object> rhs) {
    567   if (!lhs->IsNumber() || !rhs->IsNumber()) {
    568     ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(lhs), Object);
    569     ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(rhs), Object);
    570   }
    571   return isolate->factory()->NewNumberFromInt(NumberToInt32(*lhs) ^
    572                                               NumberToInt32(*rhs));
    573 }
    574 
    575 // static
    576 MaybeHandle<Object> Object::OrdinaryHasInstance(Isolate* isolate,
    577                                                 Handle<Object> callable,
    578                                                 Handle<Object> object) {
    579   // The {callable} must have a [[Call]] internal method.
    580   if (!callable->IsCallable()) return isolate->factory()->false_value();
    581 
    582   // Check if {callable} is a bound function, and if so retrieve its
    583   // [[BoundTargetFunction]] and use that instead of {callable}.
    584   if (callable->IsJSBoundFunction()) {
    585     Handle<Object> bound_callable(
    586         Handle<JSBoundFunction>::cast(callable)->bound_target_function(),
    587         isolate);
    588     return Object::InstanceOf(isolate, object, bound_callable);
    589   }
    590 
    591   // If {object} is not a receiver, return false.
    592   if (!object->IsJSReceiver()) return isolate->factory()->false_value();
    593 
    594   // Get the "prototype" of {callable}; raise an error if it's not a receiver.
    595   Handle<Object> prototype;
    596   ASSIGN_RETURN_ON_EXCEPTION(
    597       isolate, prototype,
    598       Object::GetProperty(callable, isolate->factory()->prototype_string()),
    599       Object);
    600   if (!prototype->IsJSReceiver()) {
    601     THROW_NEW_ERROR(
    602         isolate,
    603         NewTypeError(MessageTemplate::kInstanceofNonobjectProto, prototype),
    604         Object);
    605   }
    606 
    607   // Return whether or not {prototype} is in the prototype chain of {object}.
    608   Maybe<bool> result = JSReceiver::HasInPrototypeChain(
    609       isolate, Handle<JSReceiver>::cast(object), prototype);
    610   if (result.IsNothing()) return MaybeHandle<Object>();
    611   return isolate->factory()->ToBoolean(result.FromJust());
    612 }
    613 
    614 // static
    615 MaybeHandle<Object> Object::InstanceOf(Isolate* isolate, Handle<Object> object,
    616                                        Handle<Object> callable) {
    617   // The {callable} must be a receiver.
    618   if (!callable->IsJSReceiver()) {
    619     THROW_NEW_ERROR(isolate,
    620                     NewTypeError(MessageTemplate::kNonObjectInInstanceOfCheck),
    621                     Object);
    622   }
    623 
    624   // Lookup the @@hasInstance method on {callable}.
    625   Handle<Object> inst_of_handler;
    626   ASSIGN_RETURN_ON_EXCEPTION(
    627       isolate, inst_of_handler,
    628       JSReceiver::GetMethod(Handle<JSReceiver>::cast(callable),
    629                             isolate->factory()->has_instance_symbol()),
    630       Object);
    631   if (!inst_of_handler->IsUndefined(isolate)) {
    632     // Call the {inst_of_handler} on the {callable}.
    633     Handle<Object> result;
    634     ASSIGN_RETURN_ON_EXCEPTION(
    635         isolate, result,
    636         Execution::Call(isolate, inst_of_handler, callable, 1, &object),
    637         Object);
    638     return isolate->factory()->ToBoolean(result->BooleanValue());
    639   }
    640 
    641   // The {callable} must have a [[Call]] internal method.
    642   if (!callable->IsCallable()) {
    643     THROW_NEW_ERROR(
    644         isolate, NewTypeError(MessageTemplate::kNonCallableInInstanceOfCheck),
    645         Object);
    646   }
    647 
    648   // Fall back to OrdinaryHasInstance with {callable} and {object}.
    649   Handle<Object> result;
    650   ASSIGN_RETURN_ON_EXCEPTION(
    651       isolate, result,
    652       JSReceiver::OrdinaryHasInstance(isolate, callable, object), Object);
    653   return result;
    654 }
    655 
    656 Maybe<bool> Object::IsArray(Handle<Object> object) {
    657   if (object->IsJSArray()) return Just(true);
    658   if (object->IsJSProxy()) {
    659     Handle<JSProxy> proxy = Handle<JSProxy>::cast(object);
    660     Isolate* isolate = proxy->GetIsolate();
    661     if (proxy->IsRevoked()) {
    662       isolate->Throw(*isolate->factory()->NewTypeError(
    663           MessageTemplate::kProxyRevoked,
    664           isolate->factory()->NewStringFromAsciiChecked("IsArray")));
    665       return Nothing<bool>();
    666     }
    667     return Object::IsArray(handle(proxy->target(), isolate));
    668   }
    669   return Just(false);
    670 }
    671 
    672 
    673 // static
    674 MaybeHandle<Object> Object::GetMethod(Handle<JSReceiver> receiver,
    675                                       Handle<Name> name) {
    676   Handle<Object> func;
    677   Isolate* isolate = receiver->GetIsolate();
    678   ASSIGN_RETURN_ON_EXCEPTION(isolate, func,
    679                              JSReceiver::GetProperty(receiver, name), Object);
    680   if (func->IsNull(isolate) || func->IsUndefined(isolate)) {
    681     return isolate->factory()->undefined_value();
    682   }
    683   if (!func->IsCallable()) {
    684     THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kPropertyNotFunction,
    685                                           func, name, receiver),
    686                     Object);
    687   }
    688   return func;
    689 }
    690 
    691 
    692 // static
    693 MaybeHandle<FixedArray> Object::CreateListFromArrayLike(
    694     Isolate* isolate, Handle<Object> object, ElementTypes element_types) {
    695   // 1. ReturnIfAbrupt(object).
    696   // 2. (default elementTypes -- not applicable.)
    697   // 3. If Type(obj) is not Object, throw a TypeError exception.
    698   if (!object->IsJSReceiver()) {
    699     THROW_NEW_ERROR(isolate,
    700                     NewTypeError(MessageTemplate::kCalledOnNonObject,
    701                                  isolate->factory()->NewStringFromAsciiChecked(
    702                                      "CreateListFromArrayLike")),
    703                     FixedArray);
    704   }
    705   // 4. Let len be ? ToLength(? Get(obj, "length")).
    706   Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(object);
    707   Handle<Object> raw_length_number;
    708   ASSIGN_RETURN_ON_EXCEPTION(isolate, raw_length_number,
    709                              Object::GetLengthFromArrayLike(isolate, receiver),
    710                              FixedArray);
    711   uint32_t len;
    712   if (!raw_length_number->ToUint32(&len) ||
    713       len > static_cast<uint32_t>(FixedArray::kMaxLength)) {
    714     THROW_NEW_ERROR(isolate,
    715                     NewRangeError(MessageTemplate::kInvalidArrayLength),
    716                     FixedArray);
    717   }
    718   // 5. Let list be an empty List.
    719   Handle<FixedArray> list = isolate->factory()->NewFixedArray(len);
    720   // 6. Let index be 0.
    721   // 7. Repeat while index < len:
    722   for (uint32_t index = 0; index < len; ++index) {
    723     // 7a. Let indexName be ToString(index).
    724     // 7b. Let next be ? Get(obj, indexName).
    725     Handle<Object> next;
    726     ASSIGN_RETURN_ON_EXCEPTION(isolate, next,
    727                                JSReceiver::GetElement(isolate, receiver, index),
    728                                FixedArray);
    729     switch (element_types) {
    730       case ElementTypes::kAll:
    731         // Nothing to do.
    732         break;
    733       case ElementTypes::kStringAndSymbol: {
    734         // 7c. If Type(next) is not an element of elementTypes, throw a
    735         //     TypeError exception.
    736         if (!next->IsName()) {
    737           THROW_NEW_ERROR(isolate,
    738                           NewTypeError(MessageTemplate::kNotPropertyName, next),
    739                           FixedArray);
    740         }
    741         // 7d. Append next as the last element of list.
    742         // Internalize on the fly so we can use pointer identity later.
    743         next = isolate->factory()->InternalizeName(Handle<Name>::cast(next));
    744         break;
    745       }
    746     }
    747     list->set(index, *next);
    748     // 7e. Set index to index + 1. (See loop header.)
    749   }
    750   // 8. Return list.
    751   return list;
    752 }
    753 
    754 
    755 // static
    756 MaybeHandle<Object> Object::GetLengthFromArrayLike(Isolate* isolate,
    757                                                    Handle<Object> object) {
    758   Handle<Object> val;
    759   Handle<Object> key = isolate->factory()->length_string();
    760   ASSIGN_RETURN_ON_EXCEPTION(
    761       isolate, val, Runtime::GetObjectProperty(isolate, object, key), Object);
    762   return Object::ToLength(isolate, val);
    763 }
    764 
    765 // static
    766 Maybe<bool> JSReceiver::HasProperty(LookupIterator* it) {
    767   for (; it->IsFound(); it->Next()) {
    768     switch (it->state()) {
    769       case LookupIterator::NOT_FOUND:
    770       case LookupIterator::TRANSITION:
    771         UNREACHABLE();
    772       case LookupIterator::JSPROXY:
    773         return JSProxy::HasProperty(it->isolate(), it->GetHolder<JSProxy>(),
    774                                     it->GetName());
    775       case LookupIterator::INTERCEPTOR: {
    776         Maybe<PropertyAttributes> result =
    777             JSObject::GetPropertyAttributesWithInterceptor(it);
    778         if (result.IsNothing()) return Nothing<bool>();
    779         if (result.FromJust() != ABSENT) return Just(true);
    780         break;
    781       }
    782       case LookupIterator::ACCESS_CHECK: {
    783         if (it->HasAccess()) break;
    784         Maybe<PropertyAttributes> result =
    785             JSObject::GetPropertyAttributesWithFailedAccessCheck(it);
    786         if (result.IsNothing()) return Nothing<bool>();
    787         return Just(result.FromJust() != ABSENT);
    788       }
    789       case LookupIterator::INTEGER_INDEXED_EXOTIC:
    790         // TypedArray out-of-bounds access.
    791         return Just(false);
    792       case LookupIterator::ACCESSOR:
    793       case LookupIterator::DATA:
    794         return Just(true);
    795     }
    796   }
    797   return Just(false);
    798 }
    799 
    800 
    801 // static
    802 MaybeHandle<Object> Object::GetProperty(LookupIterator* it) {
    803   for (; it->IsFound(); it->Next()) {
    804     switch (it->state()) {
    805       case LookupIterator::NOT_FOUND:
    806       case LookupIterator::TRANSITION:
    807         UNREACHABLE();
    808       case LookupIterator::JSPROXY: {
    809         bool was_found;
    810         MaybeHandle<Object> result =
    811             JSProxy::GetProperty(it->isolate(), it->GetHolder<JSProxy>(),
    812                                  it->GetName(), it->GetReceiver(), &was_found);
    813         if (!was_found) it->NotFound();
    814         return result;
    815       }
    816       case LookupIterator::INTERCEPTOR: {
    817         bool done;
    818         Handle<Object> result;
    819         ASSIGN_RETURN_ON_EXCEPTION(
    820             it->isolate(), result,
    821             JSObject::GetPropertyWithInterceptor(it, &done), Object);
    822         if (done) return result;
    823         break;
    824       }
    825       case LookupIterator::ACCESS_CHECK:
    826         if (it->HasAccess()) break;
    827         return JSObject::GetPropertyWithFailedAccessCheck(it);
    828       case LookupIterator::ACCESSOR:
    829         return GetPropertyWithAccessor(it);
    830       case LookupIterator::INTEGER_INDEXED_EXOTIC:
    831         return ReadAbsentProperty(it);
    832       case LookupIterator::DATA:
    833         return it->GetDataValue();
    834     }
    835   }
    836   return ReadAbsentProperty(it);
    837 }
    838 
    839 
    840 // static
    841 MaybeHandle<Object> JSProxy::GetProperty(Isolate* isolate,
    842                                          Handle<JSProxy> proxy,
    843                                          Handle<Name> name,
    844                                          Handle<Object> receiver,
    845                                          bool* was_found) {
    846   *was_found = true;
    847   if (receiver->IsJSGlobalObject()) {
    848     THROW_NEW_ERROR(
    849         isolate,
    850         NewTypeError(MessageTemplate::kReadGlobalReferenceThroughProxy, name),
    851         Object);
    852   }
    853 
    854   DCHECK(!name->IsPrivate());
    855   STACK_CHECK(isolate, MaybeHandle<Object>());
    856   Handle<Name> trap_name = isolate->factory()->get_string();
    857   // 1. Assert: IsPropertyKey(P) is true.
    858   // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O.
    859   Handle<Object> handler(proxy->handler(), isolate);
    860   // 3. If handler is null, throw a TypeError exception.
    861   // 4. Assert: Type(handler) is Object.
    862   if (proxy->IsRevoked()) {
    863     THROW_NEW_ERROR(isolate,
    864                     NewTypeError(MessageTemplate::kProxyRevoked, trap_name),
    865                     Object);
    866   }
    867   // 5. Let target be the value of the [[ProxyTarget]] internal slot of O.
    868   Handle<JSReceiver> target(proxy->target(), isolate);
    869   // 6. Let trap be ? GetMethod(handler, "get").
    870   Handle<Object> trap;
    871   ASSIGN_RETURN_ON_EXCEPTION(
    872       isolate, trap,
    873       Object::GetMethod(Handle<JSReceiver>::cast(handler), trap_name), Object);
    874   // 7. If trap is undefined, then
    875   if (trap->IsUndefined(isolate)) {
    876     // 7.a Return target.[[Get]](P, Receiver).
    877     LookupIterator it =
    878         LookupIterator::PropertyOrElement(isolate, receiver, name, target);
    879     MaybeHandle<Object> result = Object::GetProperty(&it);
    880     *was_found = it.IsFound();
    881     return result;
    882   }
    883   // 8. Let trapResult be ? Call(trap, handler, target, P, Receiver).
    884   Handle<Object> trap_result;
    885   Handle<Object> args[] = {target, name, receiver};
    886   ASSIGN_RETURN_ON_EXCEPTION(
    887       isolate, trap_result,
    888       Execution::Call(isolate, trap, handler, arraysize(args), args), Object);
    889   // 9. Let targetDesc be ? target.[[GetOwnProperty]](P).
    890   PropertyDescriptor target_desc;
    891   Maybe<bool> target_found =
    892       JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, &target_desc);
    893   MAYBE_RETURN_NULL(target_found);
    894   // 10. If targetDesc is not undefined, then
    895   if (target_found.FromJust()) {
    896     // 10.a. If IsDataDescriptor(targetDesc) and targetDesc.[[Configurable]] is
    897     //       false and targetDesc.[[Writable]] is false, then
    898     // 10.a.i. If SameValue(trapResult, targetDesc.[[Value]]) is false,
    899     //        throw a TypeError exception.
    900     bool inconsistent = PropertyDescriptor::IsDataDescriptor(&target_desc) &&
    901                         !target_desc.configurable() &&
    902                         !target_desc.writable() &&
    903                         !trap_result->SameValue(*target_desc.value());
    904     if (inconsistent) {
    905       THROW_NEW_ERROR(
    906           isolate, NewTypeError(MessageTemplate::kProxyGetNonConfigurableData,
    907                                 name, target_desc.value(), trap_result),
    908           Object);
    909     }
    910     // 10.b. If IsAccessorDescriptor(targetDesc) and targetDesc.[[Configurable]]
    911     //       is false and targetDesc.[[Get]] is undefined, then
    912     // 10.b.i. If trapResult is not undefined, throw a TypeError exception.
    913     inconsistent = PropertyDescriptor::IsAccessorDescriptor(&target_desc) &&
    914                    !target_desc.configurable() &&
    915                    target_desc.get()->IsUndefined(isolate) &&
    916                    !trap_result->IsUndefined(isolate);
    917     if (inconsistent) {
    918       THROW_NEW_ERROR(
    919           isolate,
    920           NewTypeError(MessageTemplate::kProxyGetNonConfigurableAccessor, name,
    921                        trap_result),
    922           Object);
    923     }
    924   }
    925   // 11. Return trap_result
    926   return trap_result;
    927 }
    928 
    929 
    930 Handle<Object> JSReceiver::GetDataProperty(LookupIterator* it) {
    931   for (; it->IsFound(); it->Next()) {
    932     switch (it->state()) {
    933       case LookupIterator::INTERCEPTOR:
    934       case LookupIterator::NOT_FOUND:
    935       case LookupIterator::TRANSITION:
    936         UNREACHABLE();
    937       case LookupIterator::ACCESS_CHECK:
    938         // Support calling this method without an active context, but refuse
    939         // access to access-checked objects in that case.
    940         if (it->isolate()->context() != nullptr && it->HasAccess()) continue;
    941       // Fall through.
    942       case LookupIterator::JSPROXY:
    943         it->NotFound();
    944         return it->isolate()->factory()->undefined_value();
    945       case LookupIterator::ACCESSOR:
    946         // TODO(verwaest): For now this doesn't call into AccessorInfo, since
    947         // clients don't need it. Update once relevant.
    948         it->NotFound();
    949         return it->isolate()->factory()->undefined_value();
    950       case LookupIterator::INTEGER_INDEXED_EXOTIC:
    951         return it->isolate()->factory()->undefined_value();
    952       case LookupIterator::DATA:
    953         return it->GetDataValue();
    954     }
    955   }
    956   return it->isolate()->factory()->undefined_value();
    957 }
    958 
    959 
    960 bool Object::ToInt32(int32_t* value) {
    961   if (IsSmi()) {
    962     *value = Smi::cast(this)->value();
    963     return true;
    964   }
    965   if (IsHeapNumber()) {
    966     double num = HeapNumber::cast(this)->value();
    967     if (FastI2D(FastD2I(num)) == num) {
    968       *value = FastD2I(num);
    969       return true;
    970     }
    971   }
    972   return false;
    973 }
    974 
    975 Handle<SharedFunctionInfo> FunctionTemplateInfo::GetOrCreateSharedFunctionInfo(
    976     Isolate* isolate, Handle<FunctionTemplateInfo> info) {
    977   Object* current_info = info->shared_function_info();
    978   if (current_info->IsSharedFunctionInfo()) {
    979     return handle(SharedFunctionInfo::cast(current_info), isolate);
    980   }
    981 
    982   Handle<Object> class_name(info->class_name(), isolate);
    983   Handle<String> name = class_name->IsString()
    984                             ? Handle<String>::cast(class_name)
    985                             : isolate->factory()->empty_string();
    986   Handle<Code> code;
    987   if (info->call_code()->IsCallHandlerInfo() &&
    988       CallHandlerInfo::cast(info->call_code())->fast_handler()->IsCode()) {
    989     code = isolate->builtins()->HandleFastApiCall();
    990   } else {
    991     code = isolate->builtins()->HandleApiCall();
    992   }
    993   bool is_constructor = !info->remove_prototype();
    994   Handle<SharedFunctionInfo> result =
    995       isolate->factory()->NewSharedFunctionInfo(name, code, is_constructor);
    996   if (is_constructor) {
    997     result->set_construct_stub(*isolate->builtins()->JSConstructStubApi());
    998   }
    999 
   1000   result->set_length(info->length());
   1001   if (class_name->IsString()) result->set_instance_class_name(*class_name);
   1002   result->set_api_func_data(*info);
   1003   result->DontAdaptArguments();
   1004   DCHECK(result->IsApiFunction());
   1005 
   1006   info->set_shared_function_info(*result);
   1007   return result;
   1008 }
   1009 
   1010 bool FunctionTemplateInfo::IsTemplateFor(Map* map) {
   1011   // There is a constraint on the object; check.
   1012   if (!map->IsJSObjectMap()) return false;
   1013   // Fetch the constructor function of the object.
   1014   Object* cons_obj = map->GetConstructor();
   1015   if (!cons_obj->IsJSFunction()) return false;
   1016   JSFunction* fun = JSFunction::cast(cons_obj);
   1017   // Iterate through the chain of inheriting function templates to
   1018   // see if the required one occurs.
   1019   for (Object* type = fun->shared()->function_data();
   1020        type->IsFunctionTemplateInfo();
   1021        type = FunctionTemplateInfo::cast(type)->parent_template()) {
   1022     if (type == this) return true;
   1023   }
   1024   // Didn't find the required type in the inheritance chain.
   1025   return false;
   1026 }
   1027 
   1028 
   1029 // static
   1030 MaybeHandle<JSObject> JSObject::New(Handle<JSFunction> constructor,
   1031                                     Handle<JSReceiver> new_target,
   1032                                     Handle<AllocationSite> site) {
   1033   // If called through new, new.target can be:
   1034   // - a subclass of constructor,
   1035   // - a proxy wrapper around constructor, or
   1036   // - the constructor itself.
   1037   // If called through Reflect.construct, it's guaranteed to be a constructor.
   1038   Isolate* const isolate = constructor->GetIsolate();
   1039   DCHECK(constructor->IsConstructor());
   1040   DCHECK(new_target->IsConstructor());
   1041   DCHECK(!constructor->has_initial_map() ||
   1042          constructor->initial_map()->instance_type() != JS_FUNCTION_TYPE);
   1043 
   1044   Handle<Map> initial_map;
   1045   ASSIGN_RETURN_ON_EXCEPTION(
   1046       isolate, initial_map,
   1047       JSFunction::GetDerivedMap(isolate, constructor, new_target), JSObject);
   1048   Handle<JSObject> result =
   1049       isolate->factory()->NewJSObjectFromMap(initial_map, NOT_TENURED, site);
   1050   isolate->counters()->constructed_objects()->Increment();
   1051   isolate->counters()->constructed_objects_runtime()->Increment();
   1052   return result;
   1053 }
   1054 
   1055 void JSObject::EnsureWritableFastElements(Handle<JSObject> object) {
   1056   DCHECK(object->HasFastSmiOrObjectElements() ||
   1057          object->HasFastStringWrapperElements());
   1058   FixedArray* raw_elems = FixedArray::cast(object->elements());
   1059   Heap* heap = object->GetHeap();
   1060   if (raw_elems->map() != heap->fixed_cow_array_map()) return;
   1061   Isolate* isolate = heap->isolate();
   1062   Handle<FixedArray> elems(raw_elems, isolate);
   1063   Handle<FixedArray> writable_elems = isolate->factory()->CopyFixedArrayWithMap(
   1064       elems, isolate->factory()->fixed_array_map());
   1065   object->set_elements(*writable_elems);
   1066   isolate->counters()->cow_arrays_converted()->Increment();
   1067 }
   1068 
   1069 
   1070 // ES6 9.5.1
   1071 // static
   1072 MaybeHandle<Object> JSProxy::GetPrototype(Handle<JSProxy> proxy) {
   1073   Isolate* isolate = proxy->GetIsolate();
   1074   Handle<String> trap_name = isolate->factory()->getPrototypeOf_string();
   1075 
   1076   STACK_CHECK(isolate, MaybeHandle<Object>());
   1077 
   1078   // 1. Let handler be the value of the [[ProxyHandler]] internal slot.
   1079   // 2. If handler is null, throw a TypeError exception.
   1080   // 3. Assert: Type(handler) is Object.
   1081   // 4. Let target be the value of the [[ProxyTarget]] internal slot.
   1082   if (proxy->IsRevoked()) {
   1083     THROW_NEW_ERROR(isolate,
   1084                     NewTypeError(MessageTemplate::kProxyRevoked, trap_name),
   1085                     Object);
   1086   }
   1087   Handle<JSReceiver> target(proxy->target(), isolate);
   1088   Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate);
   1089 
   1090   // 5. Let trap be ? GetMethod(handler, "getPrototypeOf").
   1091   Handle<Object> trap;
   1092   ASSIGN_RETURN_ON_EXCEPTION(isolate, trap, GetMethod(handler, trap_name),
   1093                              Object);
   1094   // 6. If trap is undefined, then return target.[[GetPrototypeOf]]().
   1095   if (trap->IsUndefined(isolate)) {
   1096     return JSReceiver::GetPrototype(isolate, target);
   1097   }
   1098   // 7. Let handlerProto be ? Call(trap, handler, target).
   1099   Handle<Object> argv[] = {target};
   1100   Handle<Object> handler_proto;
   1101   ASSIGN_RETURN_ON_EXCEPTION(
   1102       isolate, handler_proto,
   1103       Execution::Call(isolate, trap, handler, arraysize(argv), argv), Object);
   1104   // 8. If Type(handlerProto) is neither Object nor Null, throw a TypeError.
   1105   if (!(handler_proto->IsJSReceiver() || handler_proto->IsNull(isolate))) {
   1106     THROW_NEW_ERROR(isolate,
   1107                     NewTypeError(MessageTemplate::kProxyGetPrototypeOfInvalid),
   1108                     Object);
   1109   }
   1110   // 9. Let extensibleTarget be ? IsExtensible(target).
   1111   Maybe<bool> is_extensible = JSReceiver::IsExtensible(target);
   1112   MAYBE_RETURN_NULL(is_extensible);
   1113   // 10. If extensibleTarget is true, return handlerProto.
   1114   if (is_extensible.FromJust()) return handler_proto;
   1115   // 11. Let targetProto be ? target.[[GetPrototypeOf]]().
   1116   Handle<Object> target_proto;
   1117   ASSIGN_RETURN_ON_EXCEPTION(isolate, target_proto,
   1118                              JSReceiver::GetPrototype(isolate, target), Object);
   1119   // 12. If SameValue(handlerProto, targetProto) is false, throw a TypeError.
   1120   if (!handler_proto->SameValue(*target_proto)) {
   1121     THROW_NEW_ERROR(
   1122         isolate,
   1123         NewTypeError(MessageTemplate::kProxyGetPrototypeOfNonExtensible),
   1124         Object);
   1125   }
   1126   // 13. Return handlerProto.
   1127   return handler_proto;
   1128 }
   1129 
   1130 MaybeHandle<Object> Object::GetPropertyWithAccessor(LookupIterator* it) {
   1131   Isolate* isolate = it->isolate();
   1132   Handle<Object> structure = it->GetAccessors();
   1133   Handle<Object> receiver = it->GetReceiver();
   1134 
   1135   // We should never get here to initialize a const with the hole value since a
   1136   // const declaration would conflict with the getter.
   1137   DCHECK(!structure->IsForeign());
   1138 
   1139   // API style callbacks.
   1140   if (structure->IsAccessorInfo()) {
   1141     Handle<JSObject> holder = it->GetHolder<JSObject>();
   1142     Handle<Name> name = it->GetName();
   1143     Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(structure);
   1144     if (!info->IsCompatibleReceiver(*receiver)) {
   1145       THROW_NEW_ERROR(isolate,
   1146                       NewTypeError(MessageTemplate::kIncompatibleMethodReceiver,
   1147                                    name, receiver),
   1148                       Object);
   1149     }
   1150 
   1151     v8::AccessorNameGetterCallback call_fun =
   1152         v8::ToCData<v8::AccessorNameGetterCallback>(info->getter());
   1153     if (call_fun == nullptr) return isolate->factory()->undefined_value();
   1154 
   1155     if (info->is_sloppy() && !receiver->IsJSReceiver()) {
   1156       ASSIGN_RETURN_ON_EXCEPTION(isolate, receiver,
   1157                                  Object::ConvertReceiver(isolate, receiver),
   1158                                  Object);
   1159     }
   1160 
   1161     PropertyCallbackArguments args(isolate, info->data(), *receiver, *holder,
   1162                                    Object::DONT_THROW);
   1163     Handle<Object> result = args.Call(call_fun, name);
   1164     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
   1165     if (result.is_null()) return ReadAbsentProperty(isolate, receiver, name);
   1166     // Rebox handle before return.
   1167     return handle(*result, isolate);
   1168   }
   1169 
   1170   // Regular accessor.
   1171   Handle<Object> getter(AccessorPair::cast(*structure)->getter(), isolate);
   1172   if (getter->IsFunctionTemplateInfo()) {
   1173     return Builtins::InvokeApiFunction(
   1174         isolate, Handle<FunctionTemplateInfo>::cast(getter), receiver, 0,
   1175         nullptr);
   1176   } else if (getter->IsCallable()) {
   1177     // TODO(rossberg): nicer would be to cast to some JSCallable here...
   1178     return Object::GetPropertyWithDefinedGetter(
   1179         receiver, Handle<JSReceiver>::cast(getter));
   1180   }
   1181   // Getter is not a function.
   1182   return ReadAbsentProperty(isolate, receiver, it->GetName());
   1183 }
   1184 
   1185 // static
   1186 Address AccessorInfo::redirect(Isolate* isolate, Address address,
   1187                                AccessorComponent component) {
   1188   ApiFunction fun(address);
   1189   DCHECK_EQ(ACCESSOR_GETTER, component);
   1190   ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL;
   1191   return ExternalReference(&fun, type, isolate).address();
   1192 }
   1193 
   1194 Address AccessorInfo::redirected_getter() const {
   1195   Address accessor = v8::ToCData<Address>(getter());
   1196   if (accessor == nullptr) return nullptr;
   1197   return redirect(GetIsolate(), accessor, ACCESSOR_GETTER);
   1198 }
   1199 
   1200 bool AccessorInfo::IsCompatibleReceiverMap(Isolate* isolate,
   1201                                            Handle<AccessorInfo> info,
   1202                                            Handle<Map> map) {
   1203   if (!info->HasExpectedReceiverType()) return true;
   1204   if (!map->IsJSObjectMap()) return false;
   1205   return FunctionTemplateInfo::cast(info->expected_receiver_type())
   1206       ->IsTemplateFor(*map);
   1207 }
   1208 
   1209 Maybe<bool> Object::SetPropertyWithAccessor(LookupIterator* it,
   1210                                             Handle<Object> value,
   1211                                             ShouldThrow should_throw) {
   1212   Isolate* isolate = it->isolate();
   1213   Handle<Object> structure = it->GetAccessors();
   1214   Handle<Object> receiver = it->GetReceiver();
   1215 
   1216   // We should never get here to initialize a const with the hole value since a
   1217   // const declaration would conflict with the setter.
   1218   DCHECK(!structure->IsForeign());
   1219 
   1220   // API style callbacks.
   1221   if (structure->IsAccessorInfo()) {
   1222     Handle<JSObject> holder = it->GetHolder<JSObject>();
   1223     Handle<Name> name = it->GetName();
   1224     Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(structure);
   1225     if (!info->IsCompatibleReceiver(*receiver)) {
   1226       isolate->Throw(*isolate->factory()->NewTypeError(
   1227           MessageTemplate::kIncompatibleMethodReceiver, name, receiver));
   1228       return Nothing<bool>();
   1229     }
   1230 
   1231     v8::AccessorNameSetterCallback call_fun =
   1232         v8::ToCData<v8::AccessorNameSetterCallback>(info->setter());
   1233     // TODO(verwaest): We should not get here anymore once all AccessorInfos are
   1234     // marked as special_data_property. They cannot both be writable and not
   1235     // have a setter.
   1236     if (call_fun == nullptr) return Just(true);
   1237 
   1238     if (info->is_sloppy() && !receiver->IsJSReceiver()) {
   1239       ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   1240           isolate, receiver, Object::ConvertReceiver(isolate, receiver),
   1241           Nothing<bool>());
   1242     }
   1243 
   1244     PropertyCallbackArguments args(isolate, info->data(), *receiver, *holder,
   1245                                    should_throw);
   1246     args.Call(call_fun, name, value);
   1247     RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
   1248     return Just(true);
   1249   }
   1250 
   1251   // Regular accessor.
   1252   Handle<Object> setter(AccessorPair::cast(*structure)->setter(), isolate);
   1253   if (setter->IsFunctionTemplateInfo()) {
   1254     Handle<Object> argv[] = {value};
   1255     RETURN_ON_EXCEPTION_VALUE(
   1256         isolate, Builtins::InvokeApiFunction(
   1257                      isolate, Handle<FunctionTemplateInfo>::cast(setter),
   1258                      receiver, arraysize(argv), argv),
   1259         Nothing<bool>());
   1260     return Just(true);
   1261   } else if (setter->IsCallable()) {
   1262     // TODO(rossberg): nicer would be to cast to some JSCallable here...
   1263     return SetPropertyWithDefinedSetter(
   1264         receiver, Handle<JSReceiver>::cast(setter), value, should_throw);
   1265   }
   1266 
   1267   RETURN_FAILURE(isolate, should_throw,
   1268                  NewTypeError(MessageTemplate::kNoSetterInCallback,
   1269                               it->GetName(), it->GetHolder<JSObject>()));
   1270 }
   1271 
   1272 
   1273 MaybeHandle<Object> Object::GetPropertyWithDefinedGetter(
   1274     Handle<Object> receiver,
   1275     Handle<JSReceiver> getter) {
   1276   Isolate* isolate = getter->GetIsolate();
   1277 
   1278   // Platforms with simulators like arm/arm64 expose a funny issue. If the
   1279   // simulator has a separate JS stack pointer from the C++ stack pointer, it
   1280   // can miss C++ stack overflows in the stack guard at the start of JavaScript
   1281   // functions. It would be very expensive to check the C++ stack pointer at
   1282   // that location. The best solution seems to be to break the impasse by
   1283   // adding checks at possible recursion points. What's more, we don't put
   1284   // this stack check behind the USE_SIMULATOR define in order to keep
   1285   // behavior the same between hardware and simulators.
   1286   StackLimitCheck check(isolate);
   1287   if (check.JsHasOverflowed()) {
   1288     isolate->StackOverflow();
   1289     return MaybeHandle<Object>();
   1290   }
   1291 
   1292   return Execution::Call(isolate, getter, receiver, 0, NULL);
   1293 }
   1294 
   1295 
   1296 Maybe<bool> Object::SetPropertyWithDefinedSetter(Handle<Object> receiver,
   1297                                                  Handle<JSReceiver> setter,
   1298                                                  Handle<Object> value,
   1299                                                  ShouldThrow should_throw) {
   1300   Isolate* isolate = setter->GetIsolate();
   1301 
   1302   Handle<Object> argv[] = { value };
   1303   RETURN_ON_EXCEPTION_VALUE(isolate, Execution::Call(isolate, setter, receiver,
   1304                                                      arraysize(argv), argv),
   1305                             Nothing<bool>());
   1306   return Just(true);
   1307 }
   1308 
   1309 
   1310 // static
   1311 bool JSObject::AllCanRead(LookupIterator* it) {
   1312   // Skip current iteration, it's in state ACCESS_CHECK or INTERCEPTOR, both of
   1313   // which have already been checked.
   1314   DCHECK(it->state() == LookupIterator::ACCESS_CHECK ||
   1315          it->state() == LookupIterator::INTERCEPTOR);
   1316   for (it->Next(); it->IsFound(); it->Next()) {
   1317     if (it->state() == LookupIterator::ACCESSOR) {
   1318       auto accessors = it->GetAccessors();
   1319       if (accessors->IsAccessorInfo()) {
   1320         if (AccessorInfo::cast(*accessors)->all_can_read()) return true;
   1321       }
   1322     } else if (it->state() == LookupIterator::INTERCEPTOR) {
   1323       if (it->GetInterceptor()->all_can_read()) return true;
   1324     } else if (it->state() == LookupIterator::JSPROXY) {
   1325       // Stop lookupiterating. And no, AllCanNotRead.
   1326       return false;
   1327     }
   1328   }
   1329   return false;
   1330 }
   1331 
   1332 namespace {
   1333 
   1334 MaybeHandle<Object> GetPropertyWithInterceptorInternal(
   1335     LookupIterator* it, Handle<InterceptorInfo> interceptor, bool* done) {
   1336   *done = false;
   1337   Isolate* isolate = it->isolate();
   1338   // Make sure that the top context does not change when doing callbacks or
   1339   // interceptor calls.
   1340   AssertNoContextChange ncc(isolate);
   1341 
   1342   if (interceptor->getter()->IsUndefined(isolate)) {
   1343     return isolate->factory()->undefined_value();
   1344   }
   1345 
   1346   Handle<JSObject> holder = it->GetHolder<JSObject>();
   1347   Handle<Object> result;
   1348   Handle<Object> receiver = it->GetReceiver();
   1349   if (!receiver->IsJSReceiver()) {
   1350     ASSIGN_RETURN_ON_EXCEPTION(
   1351         isolate, receiver, Object::ConvertReceiver(isolate, receiver), Object);
   1352   }
   1353   PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
   1354                                  *holder, Object::DONT_THROW);
   1355 
   1356   if (it->IsElement()) {
   1357     uint32_t index = it->index();
   1358     v8::IndexedPropertyGetterCallback getter =
   1359         v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter());
   1360     result = args.Call(getter, index);
   1361   } else {
   1362     Handle<Name> name = it->name();
   1363     DCHECK(!name->IsPrivate());
   1364 
   1365     if (name->IsSymbol() && !interceptor->can_intercept_symbols()) {
   1366       return isolate->factory()->undefined_value();
   1367     }
   1368 
   1369     v8::GenericNamedPropertyGetterCallback getter =
   1370         v8::ToCData<v8::GenericNamedPropertyGetterCallback>(
   1371             interceptor->getter());
   1372     result = args.Call(getter, name);
   1373   }
   1374 
   1375   RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
   1376   if (result.is_null()) return isolate->factory()->undefined_value();
   1377   *done = true;
   1378   // Rebox handle before return
   1379   return handle(*result, isolate);
   1380 }
   1381 
   1382 Maybe<PropertyAttributes> GetPropertyAttributesWithInterceptorInternal(
   1383     LookupIterator* it, Handle<InterceptorInfo> interceptor) {
   1384   Isolate* isolate = it->isolate();
   1385   // Make sure that the top context does not change when doing
   1386   // callbacks or interceptor calls.
   1387   AssertNoContextChange ncc(isolate);
   1388   HandleScope scope(isolate);
   1389 
   1390   Handle<JSObject> holder = it->GetHolder<JSObject>();
   1391   if (!it->IsElement() && it->name()->IsSymbol() &&
   1392       !interceptor->can_intercept_symbols()) {
   1393     return Just(ABSENT);
   1394   }
   1395   Handle<Object> receiver = it->GetReceiver();
   1396   if (!receiver->IsJSReceiver()) {
   1397     ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, receiver,
   1398                                      Object::ConvertReceiver(isolate, receiver),
   1399                                      Nothing<PropertyAttributes>());
   1400   }
   1401   PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
   1402                                  *holder, Object::DONT_THROW);
   1403   if (!interceptor->query()->IsUndefined(isolate)) {
   1404     Handle<Object> result;
   1405     if (it->IsElement()) {
   1406       uint32_t index = it->index();
   1407       v8::IndexedPropertyQueryCallback query =
   1408           v8::ToCData<v8::IndexedPropertyQueryCallback>(interceptor->query());
   1409       result = args.Call(query, index);
   1410     } else {
   1411       Handle<Name> name = it->name();
   1412       DCHECK(!name->IsPrivate());
   1413       v8::GenericNamedPropertyQueryCallback query =
   1414           v8::ToCData<v8::GenericNamedPropertyQueryCallback>(
   1415               interceptor->query());
   1416       result = args.Call(query, name);
   1417     }
   1418     if (!result.is_null()) {
   1419       int32_t value;
   1420       CHECK(result->ToInt32(&value));
   1421       return Just(static_cast<PropertyAttributes>(value));
   1422     }
   1423   } else if (!interceptor->getter()->IsUndefined(isolate)) {
   1424     // TODO(verwaest): Use GetPropertyWithInterceptor?
   1425     Handle<Object> result;
   1426     if (it->IsElement()) {
   1427       uint32_t index = it->index();
   1428       v8::IndexedPropertyGetterCallback getter =
   1429           v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter());
   1430       result = args.Call(getter, index);
   1431     } else {
   1432       Handle<Name> name = it->name();
   1433       DCHECK(!name->IsPrivate());
   1434       v8::GenericNamedPropertyGetterCallback getter =
   1435           v8::ToCData<v8::GenericNamedPropertyGetterCallback>(
   1436               interceptor->getter());
   1437       result = args.Call(getter, name);
   1438     }
   1439     if (!result.is_null()) return Just(DONT_ENUM);
   1440   }
   1441 
   1442   RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<PropertyAttributes>());
   1443   return Just(ABSENT);
   1444 }
   1445 
   1446 Maybe<bool> SetPropertyWithInterceptorInternal(
   1447     LookupIterator* it, Handle<InterceptorInfo> interceptor,
   1448     Object::ShouldThrow should_throw, Handle<Object> value) {
   1449   Isolate* isolate = it->isolate();
   1450   // Make sure that the top context does not change when doing callbacks or
   1451   // interceptor calls.
   1452   AssertNoContextChange ncc(isolate);
   1453 
   1454   if (interceptor->setter()->IsUndefined(isolate)) return Just(false);
   1455 
   1456   Handle<JSObject> holder = it->GetHolder<JSObject>();
   1457   bool result;
   1458   Handle<Object> receiver = it->GetReceiver();
   1459   if (!receiver->IsJSReceiver()) {
   1460     ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, receiver,
   1461                                      Object::ConvertReceiver(isolate, receiver),
   1462                                      Nothing<bool>());
   1463   }
   1464   PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
   1465                                  *holder, should_throw);
   1466 
   1467   if (it->IsElement()) {
   1468     uint32_t index = it->index();
   1469     v8::IndexedPropertySetterCallback setter =
   1470         v8::ToCData<v8::IndexedPropertySetterCallback>(interceptor->setter());
   1471     // TODO(neis): In the future, we may want to actually return the
   1472     // interceptor's result, which then should be a boolean.
   1473     result = !args.Call(setter, index, value).is_null();
   1474   } else {
   1475     Handle<Name> name = it->name();
   1476     DCHECK(!name->IsPrivate());
   1477 
   1478     if (name->IsSymbol() && !interceptor->can_intercept_symbols()) {
   1479       return Just(false);
   1480     }
   1481 
   1482     v8::GenericNamedPropertySetterCallback setter =
   1483         v8::ToCData<v8::GenericNamedPropertySetterCallback>(
   1484             interceptor->setter());
   1485     result = !args.Call(setter, name, value).is_null();
   1486   }
   1487 
   1488   RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(), Nothing<bool>());
   1489   return Just(result);
   1490 }
   1491 
   1492 }  // namespace
   1493 
   1494 MaybeHandle<Object> JSObject::GetPropertyWithFailedAccessCheck(
   1495     LookupIterator* it) {
   1496   Isolate* isolate = it->isolate();
   1497   Handle<JSObject> checked = it->GetHolder<JSObject>();
   1498   Handle<InterceptorInfo> interceptor =
   1499       it->GetInterceptorForFailedAccessCheck();
   1500   if (interceptor.is_null()) {
   1501     while (AllCanRead(it)) {
   1502       if (it->state() == LookupIterator::ACCESSOR) {
   1503         return GetPropertyWithAccessor(it);
   1504       }
   1505       DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
   1506       bool done;
   1507       Handle<Object> result;
   1508       ASSIGN_RETURN_ON_EXCEPTION(isolate, result,
   1509                                  GetPropertyWithInterceptor(it, &done), Object);
   1510       if (done) return result;
   1511     }
   1512   } else {
   1513     MaybeHandle<Object> result;
   1514     bool done;
   1515     result = GetPropertyWithInterceptorInternal(it, interceptor, &done);
   1516     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
   1517     if (done) return result;
   1518   }
   1519 
   1520   // Cross-Origin [[Get]] of Well-Known Symbols does not throw, and returns
   1521   // undefined.
   1522   Handle<Name> name = it->GetName();
   1523   if (name->IsSymbol() && Symbol::cast(*name)->is_well_known_symbol()) {
   1524     return it->factory()->undefined_value();
   1525   }
   1526 
   1527   isolate->ReportFailedAccessCheck(checked);
   1528   RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
   1529   return it->factory()->undefined_value();
   1530 }
   1531 
   1532 
   1533 Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithFailedAccessCheck(
   1534     LookupIterator* it) {
   1535   Isolate* isolate = it->isolate();
   1536   Handle<JSObject> checked = it->GetHolder<JSObject>();
   1537   Handle<InterceptorInfo> interceptor =
   1538       it->GetInterceptorForFailedAccessCheck();
   1539   if (interceptor.is_null()) {
   1540     while (AllCanRead(it)) {
   1541       if (it->state() == LookupIterator::ACCESSOR) {
   1542         return Just(it->property_attributes());
   1543       }
   1544       DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
   1545       auto result = GetPropertyAttributesWithInterceptor(it);
   1546       if (isolate->has_scheduled_exception()) break;
   1547       if (result.IsJust() && result.FromJust() != ABSENT) return result;
   1548     }
   1549   } else {
   1550     Maybe<PropertyAttributes> result =
   1551         GetPropertyAttributesWithInterceptorInternal(it, interceptor);
   1552     RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<PropertyAttributes>());
   1553     if (result.FromMaybe(ABSENT) != ABSENT) return result;
   1554   }
   1555   isolate->ReportFailedAccessCheck(checked);
   1556   RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<PropertyAttributes>());
   1557   return Just(ABSENT);
   1558 }
   1559 
   1560 
   1561 // static
   1562 bool JSObject::AllCanWrite(LookupIterator* it) {
   1563   for (; it->IsFound() && it->state() != LookupIterator::JSPROXY; it->Next()) {
   1564     if (it->state() == LookupIterator::ACCESSOR) {
   1565       Handle<Object> accessors = it->GetAccessors();
   1566       if (accessors->IsAccessorInfo()) {
   1567         if (AccessorInfo::cast(*accessors)->all_can_write()) return true;
   1568       }
   1569     }
   1570   }
   1571   return false;
   1572 }
   1573 
   1574 
   1575 Maybe<bool> JSObject::SetPropertyWithFailedAccessCheck(
   1576     LookupIterator* it, Handle<Object> value, ShouldThrow should_throw) {
   1577   Isolate* isolate = it->isolate();
   1578   Handle<JSObject> checked = it->GetHolder<JSObject>();
   1579   Handle<InterceptorInfo> interceptor =
   1580       it->GetInterceptorForFailedAccessCheck();
   1581   if (interceptor.is_null()) {
   1582     if (AllCanWrite(it)) {
   1583       return SetPropertyWithAccessor(it, value, should_throw);
   1584     }
   1585   } else {
   1586     Maybe<bool> result = SetPropertyWithInterceptorInternal(
   1587         it, interceptor, should_throw, value);
   1588     RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
   1589     if (result.IsJust()) return result;
   1590   }
   1591 
   1592   isolate->ReportFailedAccessCheck(checked);
   1593   RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
   1594   return Just(true);
   1595 }
   1596 
   1597 
   1598 void JSObject::SetNormalizedProperty(Handle<JSObject> object,
   1599                                      Handle<Name> name,
   1600                                      Handle<Object> value,
   1601                                      PropertyDetails details) {
   1602   DCHECK(!object->HasFastProperties());
   1603   if (!name->IsUniqueName()) {
   1604     name = object->GetIsolate()->factory()->InternalizeString(
   1605         Handle<String>::cast(name));
   1606   }
   1607 
   1608   if (object->IsJSGlobalObject()) {
   1609     Handle<GlobalDictionary> property_dictionary(object->global_dictionary());
   1610 
   1611     int entry = property_dictionary->FindEntry(name);
   1612     if (entry == GlobalDictionary::kNotFound) {
   1613       Isolate* isolate = object->GetIsolate();
   1614       auto cell = isolate->factory()->NewPropertyCell();
   1615       cell->set_value(*value);
   1616       auto cell_type = value->IsUndefined(isolate)
   1617                            ? PropertyCellType::kUndefined
   1618                            : PropertyCellType::kConstant;
   1619       details = details.set_cell_type(cell_type);
   1620       value = cell;
   1621       property_dictionary =
   1622           GlobalDictionary::Add(property_dictionary, name, value, details);
   1623       object->set_properties(*property_dictionary);
   1624     } else {
   1625       PropertyCell::UpdateCell(property_dictionary, entry, value, details);
   1626     }
   1627   } else {
   1628     Handle<NameDictionary> property_dictionary(object->property_dictionary());
   1629 
   1630     int entry = property_dictionary->FindEntry(name);
   1631     if (entry == NameDictionary::kNotFound) {
   1632       property_dictionary =
   1633           NameDictionary::Add(property_dictionary, name, value, details);
   1634       object->set_properties(*property_dictionary);
   1635     } else {
   1636       PropertyDetails original_details = property_dictionary->DetailsAt(entry);
   1637       int enumeration_index = original_details.dictionary_index();
   1638       DCHECK(enumeration_index > 0);
   1639       details = details.set_index(enumeration_index);
   1640       property_dictionary->SetEntry(entry, name, value, details);
   1641     }
   1642   }
   1643 }
   1644 
   1645 // static
   1646 Maybe<bool> JSReceiver::HasInPrototypeChain(Isolate* isolate,
   1647                                             Handle<JSReceiver> object,
   1648                                             Handle<Object> proto) {
   1649   PrototypeIterator iter(isolate, object, kStartAtReceiver);
   1650   while (true) {
   1651     if (!iter.AdvanceFollowingProxies()) return Nothing<bool>();
   1652     if (iter.IsAtEnd()) return Just(false);
   1653     if (PrototypeIterator::GetCurrent(iter).is_identical_to(proto)) {
   1654       return Just(true);
   1655     }
   1656   }
   1657 }
   1658 
   1659 Map* Object::GetRootMap(Isolate* isolate) {
   1660   DisallowHeapAllocation no_alloc;
   1661   if (IsSmi()) {
   1662     Context* native_context = isolate->context()->native_context();
   1663     return native_context->number_function()->initial_map();
   1664   }
   1665 
   1666   // The object is either a number, a string, a symbol, a boolean, a SIMD value,
   1667   // a real JS object, or a Harmony proxy.
   1668   HeapObject* heap_object = HeapObject::cast(this);
   1669   if (heap_object->IsJSReceiver()) {
   1670     return heap_object->map();
   1671   }
   1672   int constructor_function_index =
   1673       heap_object->map()->GetConstructorFunctionIndex();
   1674   if (constructor_function_index != Map::kNoConstructorFunctionIndex) {
   1675     Context* native_context = isolate->context()->native_context();
   1676     JSFunction* constructor_function =
   1677         JSFunction::cast(native_context->get(constructor_function_index));
   1678     return constructor_function->initial_map();
   1679   }
   1680   return isolate->heap()->null_value()->map();
   1681 }
   1682 
   1683 namespace {
   1684 
   1685 // Returns a non-SMI for JSObjects, but returns the hash code for simple
   1686 // objects.  This avoids a double lookup in the cases where we know we will
   1687 // add the hash to the JSObject if it does not already exist.
   1688 Object* GetSimpleHash(Object* object) {
   1689   // The object is either a Smi, a HeapNumber, a name, an odd-ball,
   1690   // a SIMD value type, a real JS object, or a Harmony proxy.
   1691   if (object->IsSmi()) {
   1692     uint32_t hash =
   1693         ComputeIntegerHash(Smi::cast(object)->value(), kZeroHashSeed);
   1694     return Smi::FromInt(hash & Smi::kMaxValue);
   1695   }
   1696   if (object->IsHeapNumber()) {
   1697     double num = HeapNumber::cast(object)->value();
   1698     if (std::isnan(num)) return Smi::FromInt(Smi::kMaxValue);
   1699     if (i::IsMinusZero(num)) num = 0;
   1700     if (IsSmiDouble(num)) {
   1701       return Smi::FromInt(FastD2I(num))->GetHash();
   1702     }
   1703     uint32_t hash = ComputeLongHash(double_to_uint64(num));
   1704     return Smi::FromInt(hash & Smi::kMaxValue);
   1705   }
   1706   if (object->IsName()) {
   1707     uint32_t hash = Name::cast(object)->Hash();
   1708     return Smi::FromInt(hash);
   1709   }
   1710   if (object->IsOddball()) {
   1711     uint32_t hash = Oddball::cast(object)->to_string()->Hash();
   1712     return Smi::FromInt(hash);
   1713   }
   1714   if (object->IsSimd128Value()) {
   1715     uint32_t hash = Simd128Value::cast(object)->Hash();
   1716     return Smi::FromInt(hash & Smi::kMaxValue);
   1717   }
   1718   DCHECK(object->IsJSReceiver());
   1719   // Simply return the receiver as it is guaranteed to not be a SMI.
   1720   return object;
   1721 }
   1722 
   1723 }  // namespace
   1724 
   1725 Object* Object::GetHash() {
   1726   Object* hash = GetSimpleHash(this);
   1727   if (hash->IsSmi()) return hash;
   1728 
   1729   DisallowHeapAllocation no_gc;
   1730   DCHECK(IsJSReceiver());
   1731   JSReceiver* receiver = JSReceiver::cast(this);
   1732   Isolate* isolate = receiver->GetIsolate();
   1733   return JSReceiver::GetIdentityHash(isolate, handle(receiver, isolate));
   1734 }
   1735 
   1736 Smi* Object::GetOrCreateHash(Isolate* isolate, Handle<Object> object) {
   1737   Object* hash = GetSimpleHash(*object);
   1738   if (hash->IsSmi()) return Smi::cast(hash);
   1739 
   1740   DCHECK(object->IsJSReceiver());
   1741   return JSReceiver::GetOrCreateIdentityHash(isolate,
   1742                                              Handle<JSReceiver>::cast(object));
   1743 }
   1744 
   1745 
   1746 bool Object::SameValue(Object* other) {
   1747   if (other == this) return true;
   1748 
   1749   // The object is either a number, a name, an odd-ball,
   1750   // a real JS object, or a Harmony proxy.
   1751   if (IsNumber() && other->IsNumber()) {
   1752     double this_value = Number();
   1753     double other_value = other->Number();
   1754     // SameValue(NaN, NaN) is true.
   1755     if (this_value != other_value) {
   1756       return std::isnan(this_value) && std::isnan(other_value);
   1757     }
   1758     // SameValue(0.0, -0.0) is false.
   1759     return (std::signbit(this_value) == std::signbit(other_value));
   1760   }
   1761   if (IsString() && other->IsString()) {
   1762     return String::cast(this)->Equals(String::cast(other));
   1763   }
   1764   if (IsFloat32x4() && other->IsFloat32x4()) {
   1765     Float32x4* a = Float32x4::cast(this);
   1766     Float32x4* b = Float32x4::cast(other);
   1767     for (int i = 0; i < 4; i++) {
   1768       float x = a->get_lane(i);
   1769       float y = b->get_lane(i);
   1770       // Implements the ES5 SameValue operation for floating point types.
   1771       // http://www.ecma-international.org/ecma-262/6.0/#sec-samevalue
   1772       if (x != y && !(std::isnan(x) && std::isnan(y))) return false;
   1773       if (std::signbit(x) != std::signbit(y)) return false;
   1774     }
   1775     return true;
   1776   } else if (IsSimd128Value() && other->IsSimd128Value()) {
   1777     Simd128Value* a = Simd128Value::cast(this);
   1778     Simd128Value* b = Simd128Value::cast(other);
   1779     return a->map() == b->map() && a->BitwiseEquals(b);
   1780   }
   1781   return false;
   1782 }
   1783 
   1784 
   1785 bool Object::SameValueZero(Object* other) {
   1786   if (other == this) return true;
   1787 
   1788   // The object is either a number, a name, an odd-ball,
   1789   // a real JS object, or a Harmony proxy.
   1790   if (IsNumber() && other->IsNumber()) {
   1791     double this_value = Number();
   1792     double other_value = other->Number();
   1793     // +0 == -0 is true
   1794     return this_value == other_value ||
   1795            (std::isnan(this_value) && std::isnan(other_value));
   1796   }
   1797   if (IsString() && other->IsString()) {
   1798     return String::cast(this)->Equals(String::cast(other));
   1799   }
   1800   if (IsFloat32x4() && other->IsFloat32x4()) {
   1801     Float32x4* a = Float32x4::cast(this);
   1802     Float32x4* b = Float32x4::cast(other);
   1803     for (int i = 0; i < 4; i++) {
   1804       float x = a->get_lane(i);
   1805       float y = b->get_lane(i);
   1806       // Implements the ES6 SameValueZero operation for floating point types.
   1807       // http://www.ecma-international.org/ecma-262/6.0/#sec-samevaluezero
   1808       if (x != y && !(std::isnan(x) && std::isnan(y))) return false;
   1809       // SameValueZero doesn't distinguish between 0 and -0.
   1810     }
   1811     return true;
   1812   } else if (IsSimd128Value() && other->IsSimd128Value()) {
   1813     Simd128Value* a = Simd128Value::cast(this);
   1814     Simd128Value* b = Simd128Value::cast(other);
   1815     return a->map() == b->map() && a->BitwiseEquals(b);
   1816   }
   1817   return false;
   1818 }
   1819 
   1820 
   1821 MaybeHandle<Object> Object::ArraySpeciesConstructor(
   1822     Isolate* isolate, Handle<Object> original_array) {
   1823   Handle<Object> default_species = isolate->array_function();
   1824   if (original_array->IsJSArray() &&
   1825       Handle<JSArray>::cast(original_array)->HasArrayPrototype(isolate) &&
   1826       isolate->IsArraySpeciesLookupChainIntact()) {
   1827     return default_species;
   1828   }
   1829   Handle<Object> constructor = isolate->factory()->undefined_value();
   1830   Maybe<bool> is_array = Object::IsArray(original_array);
   1831   MAYBE_RETURN_NULL(is_array);
   1832   if (is_array.FromJust()) {
   1833     ASSIGN_RETURN_ON_EXCEPTION(
   1834         isolate, constructor,
   1835         Object::GetProperty(original_array,
   1836                             isolate->factory()->constructor_string()),
   1837         Object);
   1838     if (constructor->IsConstructor()) {
   1839       Handle<Context> constructor_context;
   1840       ASSIGN_RETURN_ON_EXCEPTION(
   1841           isolate, constructor_context,
   1842           JSReceiver::GetFunctionRealm(Handle<JSReceiver>::cast(constructor)),
   1843           Object);
   1844       if (*constructor_context != *isolate->native_context() &&
   1845           *constructor == constructor_context->array_function()) {
   1846         constructor = isolate->factory()->undefined_value();
   1847       }
   1848     }
   1849     if (constructor->IsJSReceiver()) {
   1850       ASSIGN_RETURN_ON_EXCEPTION(
   1851           isolate, constructor,
   1852           JSReceiver::GetProperty(Handle<JSReceiver>::cast(constructor),
   1853                                   isolate->factory()->species_symbol()),
   1854           Object);
   1855       if (constructor->IsNull(isolate)) {
   1856         constructor = isolate->factory()->undefined_value();
   1857       }
   1858     }
   1859   }
   1860   if (constructor->IsUndefined(isolate)) {
   1861     return default_species;
   1862   } else {
   1863     if (!constructor->IsConstructor()) {
   1864       THROW_NEW_ERROR(isolate,
   1865           NewTypeError(MessageTemplate::kSpeciesNotConstructor),
   1866           Object);
   1867     }
   1868     return constructor;
   1869   }
   1870 }
   1871 
   1872 
   1873 void Object::ShortPrint(FILE* out) {
   1874   OFStream os(out);
   1875   os << Brief(this);
   1876 }
   1877 
   1878 
   1879 void Object::ShortPrint(StringStream* accumulator) {
   1880   std::ostringstream os;
   1881   os << Brief(this);
   1882   accumulator->Add(os.str().c_str());
   1883 }
   1884 
   1885 
   1886 void Object::ShortPrint(std::ostream& os) { os << Brief(this); }
   1887 
   1888 
   1889 std::ostream& operator<<(std::ostream& os, const Brief& v) {
   1890   if (v.value->IsSmi()) {
   1891     Smi::cast(v.value)->SmiPrint(os);
   1892   } else {
   1893     // TODO(svenpanne) Const-correct HeapObjectShortPrint!
   1894     HeapObject* obj = const_cast<HeapObject*>(HeapObject::cast(v.value));
   1895     obj->HeapObjectShortPrint(os);
   1896   }
   1897   return os;
   1898 }
   1899 
   1900 
   1901 void Smi::SmiPrint(std::ostream& os) const {  // NOLINT
   1902   os << value();
   1903 }
   1904 
   1905 
   1906 // Should a word be prefixed by 'a' or 'an' in order to read naturally in
   1907 // English?  Returns false for non-ASCII or words that don't start with
   1908 // a capital letter.  The a/an rule follows pronunciation in English.
   1909 // We don't use the BBC's overcorrect "an historic occasion" though if
   1910 // you speak a dialect you may well say "an 'istoric occasion".
   1911 static bool AnWord(String* str) {
   1912   if (str->length() == 0) return false;  // A nothing.
   1913   int c0 = str->Get(0);
   1914   int c1 = str->length() > 1 ? str->Get(1) : 0;
   1915   if (c0 == 'U') {
   1916     if (c1 > 'Z') {
   1917       return true;  // An Umpire, but a UTF8String, a U.
   1918     }
   1919   } else if (c0 == 'A' || c0 == 'E' || c0 == 'I' || c0 == 'O') {
   1920     return true;    // An Ape, an ABCBook.
   1921   } else if ((c1 == 0 || (c1 >= 'A' && c1 <= 'Z')) &&
   1922            (c0 == 'F' || c0 == 'H' || c0 == 'M' || c0 == 'N' || c0 == 'R' ||
   1923             c0 == 'S' || c0 == 'X')) {
   1924     return true;    // An MP3File, an M.
   1925   }
   1926   return false;
   1927 }
   1928 
   1929 
   1930 Handle<String> String::SlowFlatten(Handle<ConsString> cons,
   1931                                    PretenureFlag pretenure) {
   1932   DCHECK(AllowHeapAllocation::IsAllowed());
   1933   DCHECK(cons->second()->length() != 0);
   1934   Isolate* isolate = cons->GetIsolate();
   1935   int length = cons->length();
   1936   PretenureFlag tenure = isolate->heap()->InNewSpace(*cons) ? pretenure
   1937                                                             : TENURED;
   1938   Handle<SeqString> result;
   1939   if (cons->IsOneByteRepresentation()) {
   1940     Handle<SeqOneByteString> flat = isolate->factory()->NewRawOneByteString(
   1941         length, tenure).ToHandleChecked();
   1942     DisallowHeapAllocation no_gc;
   1943     WriteToFlat(*cons, flat->GetChars(), 0, length);
   1944     result = flat;
   1945   } else {
   1946     Handle<SeqTwoByteString> flat = isolate->factory()->NewRawTwoByteString(
   1947         length, tenure).ToHandleChecked();
   1948     DisallowHeapAllocation no_gc;
   1949     WriteToFlat(*cons, flat->GetChars(), 0, length);
   1950     result = flat;
   1951   }
   1952   cons->set_first(*result);
   1953   cons->set_second(isolate->heap()->empty_string());
   1954   DCHECK(result->IsFlat());
   1955   return result;
   1956 }
   1957 
   1958 
   1959 
   1960 bool String::MakeExternal(v8::String::ExternalStringResource* resource) {
   1961   // Externalizing twice leaks the external resource, so it's
   1962   // prohibited by the API.
   1963   DCHECK(!this->IsExternalString());
   1964   DCHECK(!resource->IsCompressible());
   1965 #ifdef ENABLE_SLOW_DCHECKS
   1966   if (FLAG_enable_slow_asserts) {
   1967     // Assert that the resource and the string are equivalent.
   1968     DCHECK(static_cast<size_t>(this->length()) == resource->length());
   1969     ScopedVector<uc16> smart_chars(this->length());
   1970     String::WriteToFlat(this, smart_chars.start(), 0, this->length());
   1971     DCHECK(memcmp(smart_chars.start(),
   1972                   resource->data(),
   1973                   resource->length() * sizeof(smart_chars[0])) == 0);
   1974   }
   1975 #endif  // DEBUG
   1976   int size = this->Size();  // Byte size of the original string.
   1977   // Abort if size does not allow in-place conversion.
   1978   if (size < ExternalString::kShortSize) return false;
   1979   Heap* heap = GetHeap();
   1980   bool is_one_byte = this->IsOneByteRepresentation();
   1981   bool is_internalized = this->IsInternalizedString();
   1982 
   1983   // Morph the string to an external string by replacing the map and
   1984   // reinitializing the fields.  This won't work if the space the existing
   1985   // string occupies is too small for a regular  external string.
   1986   // Instead, we resort to a short external string instead, omitting
   1987   // the field caching the address of the backing store.  When we encounter
   1988   // short external strings in generated code, we need to bailout to runtime.
   1989   Map* new_map;
   1990   if (size < ExternalString::kSize) {
   1991     new_map = is_internalized
   1992         ? (is_one_byte
   1993            ? heap->short_external_internalized_string_with_one_byte_data_map()
   1994            : heap->short_external_internalized_string_map())
   1995         : (is_one_byte ? heap->short_external_string_with_one_byte_data_map()
   1996                        : heap->short_external_string_map());
   1997   } else {
   1998     new_map = is_internalized
   1999         ? (is_one_byte
   2000            ? heap->external_internalized_string_with_one_byte_data_map()
   2001            : heap->external_internalized_string_map())
   2002         : (is_one_byte ? heap->external_string_with_one_byte_data_map()
   2003                        : heap->external_string_map());
   2004   }
   2005 
   2006   // Byte size of the external String object.
   2007   int new_size = this->SizeFromMap(new_map);
   2008   heap->CreateFillerObjectAt(this->address() + new_size, size - new_size,
   2009                              ClearRecordedSlots::kNo);
   2010 
   2011   // We are storing the new map using release store after creating a filler for
   2012   // the left-over space to avoid races with the sweeper thread.
   2013   this->synchronized_set_map(new_map);
   2014 
   2015   ExternalTwoByteString* self = ExternalTwoByteString::cast(this);
   2016   self->set_resource(resource);
   2017   if (is_internalized) self->Hash();  // Force regeneration of the hash value.
   2018 
   2019   heap->AdjustLiveBytes(this, new_size - size, Heap::CONCURRENT_TO_SWEEPER);
   2020   return true;
   2021 }
   2022 
   2023 
   2024 bool String::MakeExternal(v8::String::ExternalOneByteStringResource* resource) {
   2025   // Externalizing twice leaks the external resource, so it's
   2026   // prohibited by the API.
   2027   DCHECK(!this->IsExternalString());
   2028   DCHECK(!resource->IsCompressible());
   2029 #ifdef ENABLE_SLOW_DCHECKS
   2030   if (FLAG_enable_slow_asserts) {
   2031     // Assert that the resource and the string are equivalent.
   2032     DCHECK(static_cast<size_t>(this->length()) == resource->length());
   2033     if (this->IsTwoByteRepresentation()) {
   2034       ScopedVector<uint16_t> smart_chars(this->length());
   2035       String::WriteToFlat(this, smart_chars.start(), 0, this->length());
   2036       DCHECK(String::IsOneByte(smart_chars.start(), this->length()));
   2037     }
   2038     ScopedVector<char> smart_chars(this->length());
   2039     String::WriteToFlat(this, smart_chars.start(), 0, this->length());
   2040     DCHECK(memcmp(smart_chars.start(),
   2041                   resource->data(),
   2042                   resource->length() * sizeof(smart_chars[0])) == 0);
   2043   }
   2044 #endif  // DEBUG
   2045   int size = this->Size();  // Byte size of the original string.
   2046   // Abort if size does not allow in-place conversion.
   2047   if (size < ExternalString::kShortSize) return false;
   2048   Heap* heap = GetHeap();
   2049   bool is_internalized = this->IsInternalizedString();
   2050 
   2051   // Morph the string to an external string by replacing the map and
   2052   // reinitializing the fields.  This won't work if the space the existing
   2053   // string occupies is too small for a regular  external string.
   2054   // Instead, we resort to a short external string instead, omitting
   2055   // the field caching the address of the backing store.  When we encounter
   2056   // short external strings in generated code, we need to bailout to runtime.
   2057   Map* new_map;
   2058   if (size < ExternalString::kSize) {
   2059     new_map = is_internalized
   2060                   ? heap->short_external_one_byte_internalized_string_map()
   2061                   : heap->short_external_one_byte_string_map();
   2062   } else {
   2063     new_map = is_internalized
   2064                   ? heap->external_one_byte_internalized_string_map()
   2065                   : heap->external_one_byte_string_map();
   2066   }
   2067 
   2068   // Byte size of the external String object.
   2069   int new_size = this->SizeFromMap(new_map);
   2070   heap->CreateFillerObjectAt(this->address() + new_size, size - new_size,
   2071                              ClearRecordedSlots::kNo);
   2072 
   2073   // We are storing the new map using release store after creating a filler for
   2074   // the left-over space to avoid races with the sweeper thread.
   2075   this->synchronized_set_map(new_map);
   2076 
   2077   ExternalOneByteString* self = ExternalOneByteString::cast(this);
   2078   self->set_resource(resource);
   2079   if (is_internalized) self->Hash();  // Force regeneration of the hash value.
   2080 
   2081   heap->AdjustLiveBytes(this, new_size - size, Heap::CONCURRENT_TO_SWEEPER);
   2082   return true;
   2083 }
   2084 
   2085 void String::StringShortPrint(StringStream* accumulator, bool show_details) {
   2086   int len = length();
   2087   if (len > kMaxShortPrintLength) {
   2088     accumulator->Add("<Very long string[%u]>", len);
   2089     return;
   2090   }
   2091 
   2092   if (!LooksValid()) {
   2093     accumulator->Add("<Invalid String>");
   2094     return;
   2095   }
   2096 
   2097   StringCharacterStream stream(this);
   2098 
   2099   bool truncated = false;
   2100   if (len > kMaxShortPrintLength) {
   2101     len = kMaxShortPrintLength;
   2102     truncated = true;
   2103   }
   2104   bool one_byte = true;
   2105   for (int i = 0; i < len; i++) {
   2106     uint16_t c = stream.GetNext();
   2107 
   2108     if (c < 32 || c >= 127) {
   2109       one_byte = false;
   2110     }
   2111   }
   2112   stream.Reset(this);
   2113   if (one_byte) {
   2114     if (show_details) accumulator->Add("<String[%u]: ", length());
   2115     for (int i = 0; i < len; i++) {
   2116       accumulator->Put(static_cast<char>(stream.GetNext()));
   2117     }
   2118     if (show_details) accumulator->Put('>');
   2119   } else {
   2120     // Backslash indicates that the string contains control
   2121     // characters and that backslashes are therefore escaped.
   2122     if (show_details) accumulator->Add("<String[%u]\\: ", length());
   2123     for (int i = 0; i < len; i++) {
   2124       uint16_t c = stream.GetNext();
   2125       if (c == '\n') {
   2126         accumulator->Add("\\n");
   2127       } else if (c == '\r') {
   2128         accumulator->Add("\\r");
   2129       } else if (c == '\\') {
   2130         accumulator->Add("\\\\");
   2131       } else if (c < 32 || c > 126) {
   2132         accumulator->Add("\\x%02x", c);
   2133       } else {
   2134         accumulator->Put(static_cast<char>(c));
   2135       }
   2136     }
   2137     if (truncated) {
   2138       accumulator->Put('.');
   2139       accumulator->Put('.');
   2140       accumulator->Put('.');
   2141     }
   2142     if (show_details) accumulator->Put('>');
   2143   }
   2144   return;
   2145 }
   2146 
   2147 
   2148 void String::PrintUC16(std::ostream& os, int start, int end) {  // NOLINT
   2149   if (end < 0) end = length();
   2150   StringCharacterStream stream(this, start);
   2151   for (int i = start; i < end && stream.HasMore(); i++) {
   2152     os << AsUC16(stream.GetNext());
   2153   }
   2154 }
   2155 
   2156 
   2157 void JSObject::JSObjectShortPrint(StringStream* accumulator) {
   2158   switch (map()->instance_type()) {
   2159     case JS_ARRAY_TYPE: {
   2160       double length = JSArray::cast(this)->length()->IsUndefined(GetIsolate())
   2161                           ? 0
   2162                           : JSArray::cast(this)->length()->Number();
   2163       accumulator->Add("<JS Array[%u]>", static_cast<uint32_t>(length));
   2164       break;
   2165     }
   2166     case JS_BOUND_FUNCTION_TYPE: {
   2167       JSBoundFunction* bound_function = JSBoundFunction::cast(this);
   2168       accumulator->Add("<JS BoundFunction");
   2169       accumulator->Add(
   2170           " (BoundTargetFunction %p)>",
   2171           reinterpret_cast<void*>(bound_function->bound_target_function()));
   2172       break;
   2173     }
   2174     case JS_WEAK_MAP_TYPE: {
   2175       accumulator->Add("<JS WeakMap>");
   2176       break;
   2177     }
   2178     case JS_WEAK_SET_TYPE: {
   2179       accumulator->Add("<JS WeakSet>");
   2180       break;
   2181     }
   2182     case JS_REGEXP_TYPE: {
   2183       accumulator->Add("<JS RegExp>");
   2184       break;
   2185     }
   2186     case JS_FUNCTION_TYPE: {
   2187       JSFunction* function = JSFunction::cast(this);
   2188       Object* fun_name = function->shared()->DebugName();
   2189       bool printed = false;
   2190       if (fun_name->IsString()) {
   2191         String* str = String::cast(fun_name);
   2192         if (str->length() > 0) {
   2193           accumulator->Add("<JS Function ");
   2194           accumulator->Put(str);
   2195           printed = true;
   2196         }
   2197       }
   2198       if (!printed) {
   2199         accumulator->Add("<JS Function");
   2200       }
   2201       if (FLAG_trace_file_names) {
   2202         Object* source_name =
   2203             Script::cast(function->shared()->script())->name();
   2204         if (source_name->IsString()) {
   2205           String* str = String::cast(source_name);
   2206           if (str->length() > 0) {
   2207             accumulator->Add(" <");
   2208             accumulator->Put(str);
   2209             accumulator->Add(">");
   2210           }
   2211         }
   2212       }
   2213       accumulator->Add(" (SharedFunctionInfo %p)",
   2214                        reinterpret_cast<void*>(function->shared()));
   2215       accumulator->Put('>');
   2216       break;
   2217     }
   2218     case JS_GENERATOR_OBJECT_TYPE: {
   2219       accumulator->Add("<JS Generator>");
   2220       break;
   2221     }
   2222     case JS_MODULE_TYPE: {
   2223       accumulator->Add("<JS Module>");
   2224       break;
   2225     }
   2226     // All other JSObjects are rather similar to each other (JSObject,
   2227     // JSGlobalProxy, JSGlobalObject, JSUndetectable, JSValue).
   2228     default: {
   2229       Map* map_of_this = map();
   2230       Heap* heap = GetHeap();
   2231       Object* constructor = map_of_this->GetConstructor();
   2232       bool printed = false;
   2233       if (constructor->IsHeapObject() &&
   2234           !heap->Contains(HeapObject::cast(constructor))) {
   2235         accumulator->Add("!!!INVALID CONSTRUCTOR!!!");
   2236       } else {
   2237         bool global_object = IsJSGlobalProxy();
   2238         if (constructor->IsJSFunction()) {
   2239           if (!heap->Contains(JSFunction::cast(constructor)->shared())) {
   2240             accumulator->Add("!!!INVALID SHARED ON CONSTRUCTOR!!!");
   2241           } else {
   2242             Object* constructor_name =
   2243                 JSFunction::cast(constructor)->shared()->name();
   2244             if (constructor_name->IsString()) {
   2245               String* str = String::cast(constructor_name);
   2246               if (str->length() > 0) {
   2247                 bool vowel = AnWord(str);
   2248                 accumulator->Add("<%sa%s ",
   2249                        global_object ? "Global Object: " : "",
   2250                        vowel ? "n" : "");
   2251                 accumulator->Put(str);
   2252                 accumulator->Add(" with %smap %p",
   2253                     map_of_this->is_deprecated() ? "deprecated " : "",
   2254                     map_of_this);
   2255                 printed = true;
   2256               }
   2257             }
   2258           }
   2259         }
   2260         if (!printed) {
   2261           accumulator->Add("<JS %sObject", global_object ? "Global " : "");
   2262         }
   2263       }
   2264       if (IsJSValue()) {
   2265         accumulator->Add(" value = ");
   2266         JSValue::cast(this)->value()->ShortPrint(accumulator);
   2267       }
   2268       accumulator->Put('>');
   2269       break;
   2270     }
   2271   }
   2272 }
   2273 
   2274 
   2275 void JSObject::PrintElementsTransition(
   2276     FILE* file, Handle<JSObject> object,
   2277     ElementsKind from_kind, Handle<FixedArrayBase> from_elements,
   2278     ElementsKind to_kind, Handle<FixedArrayBase> to_elements) {
   2279   if (from_kind != to_kind) {
   2280     OFStream os(file);
   2281     os << "elements transition [" << ElementsKindToString(from_kind) << " -> "
   2282        << ElementsKindToString(to_kind) << "] in ";
   2283     JavaScriptFrame::PrintTop(object->GetIsolate(), file, false, true);
   2284     PrintF(file, " for ");
   2285     object->ShortPrint(file);
   2286     PrintF(file, " from ");
   2287     from_elements->ShortPrint(file);
   2288     PrintF(file, " to ");
   2289     to_elements->ShortPrint(file);
   2290     PrintF(file, "\n");
   2291   }
   2292 }
   2293 
   2294 
   2295 // static
   2296 MaybeHandle<JSFunction> Map::GetConstructorFunction(
   2297     Handle<Map> map, Handle<Context> native_context) {
   2298   if (map->IsPrimitiveMap()) {
   2299     int const constructor_function_index = map->GetConstructorFunctionIndex();
   2300     if (constructor_function_index != kNoConstructorFunctionIndex) {
   2301       return handle(
   2302           JSFunction::cast(native_context->get(constructor_function_index)));
   2303     }
   2304   }
   2305   return MaybeHandle<JSFunction>();
   2306 }
   2307 
   2308 
   2309 void Map::PrintReconfiguration(FILE* file, int modify_index, PropertyKind kind,
   2310                                PropertyAttributes attributes) {
   2311   OFStream os(file);
   2312   os << "[reconfiguring]";
   2313   Name* name = instance_descriptors()->GetKey(modify_index);
   2314   if (name->IsString()) {
   2315     String::cast(name)->PrintOn(file);
   2316   } else {
   2317     os << "{symbol " << static_cast<void*>(name) << "}";
   2318   }
   2319   os << ": " << (kind == kData ? "kData" : "ACCESSORS") << ", attrs: ";
   2320   os << attributes << " [";
   2321   JavaScriptFrame::PrintTop(GetIsolate(), file, false, true);
   2322   os << "]\n";
   2323 }
   2324 
   2325 void Map::PrintGeneralization(
   2326     FILE* file, const char* reason, int modify_index, int split,
   2327     int descriptors, bool constant_to_field, Representation old_representation,
   2328     Representation new_representation, MaybeHandle<FieldType> old_field_type,
   2329     MaybeHandle<Object> old_value, MaybeHandle<FieldType> new_field_type,
   2330     MaybeHandle<Object> new_value) {
   2331   OFStream os(file);
   2332   os << "[generalizing]";
   2333   Name* name = instance_descriptors()->GetKey(modify_index);
   2334   if (name->IsString()) {
   2335     String::cast(name)->PrintOn(file);
   2336   } else {
   2337     os << "{symbol " << static_cast<void*>(name) << "}";
   2338   }
   2339   os << ":";
   2340   if (constant_to_field) {
   2341     os << "c";
   2342   } else {
   2343     os << old_representation.Mnemonic() << "{";
   2344     if (old_field_type.is_null()) {
   2345       os << Brief(*(old_value.ToHandleChecked()));
   2346     } else {
   2347       old_field_type.ToHandleChecked()->PrintTo(os);
   2348     }
   2349     os << "}";
   2350   }
   2351   os << "->" << new_representation.Mnemonic() << "{";
   2352   if (new_field_type.is_null()) {
   2353     os << Brief(*(new_value.ToHandleChecked()));
   2354   } else {
   2355     new_field_type.ToHandleChecked()->PrintTo(os);
   2356   }
   2357   os << "} (";
   2358   if (strlen(reason) > 0) {
   2359     os << reason;
   2360   } else {
   2361     os << "+" << (descriptors - split) << " maps";
   2362   }
   2363   os << ") [";
   2364   JavaScriptFrame::PrintTop(GetIsolate(), file, false, true);
   2365   os << "]\n";
   2366 }
   2367 
   2368 
   2369 void JSObject::PrintInstanceMigration(FILE* file,
   2370                                       Map* original_map,
   2371                                       Map* new_map) {
   2372   PrintF(file, "[migrating]");
   2373   DescriptorArray* o = original_map->instance_descriptors();
   2374   DescriptorArray* n = new_map->instance_descriptors();
   2375   for (int i = 0; i < original_map->NumberOfOwnDescriptors(); i++) {
   2376     Representation o_r = o->GetDetails(i).representation();
   2377     Representation n_r = n->GetDetails(i).representation();
   2378     if (!o_r.Equals(n_r)) {
   2379       String::cast(o->GetKey(i))->PrintOn(file);
   2380       PrintF(file, ":%s->%s ", o_r.Mnemonic(), n_r.Mnemonic());
   2381     } else if (o->GetDetails(i).type() == DATA_CONSTANT &&
   2382                n->GetDetails(i).type() == DATA) {
   2383       Name* name = o->GetKey(i);
   2384       if (name->IsString()) {
   2385         String::cast(name)->PrintOn(file);
   2386       } else {
   2387         PrintF(file, "{symbol %p}", static_cast<void*>(name));
   2388       }
   2389       PrintF(file, " ");
   2390     }
   2391   }
   2392   PrintF(file, "\n");
   2393 }
   2394 
   2395 
   2396 void HeapObject::HeapObjectShortPrint(std::ostream& os) {  // NOLINT
   2397   Heap* heap = GetHeap();
   2398   Isolate* isolate = heap->isolate();
   2399   if (!heap->Contains(this)) {
   2400     os << "!!!INVALID POINTER!!!";
   2401     return;
   2402   }
   2403   if (!heap->Contains(map())) {
   2404     os << "!!!INVALID MAP!!!";
   2405     return;
   2406   }
   2407 
   2408   os << this << " ";
   2409 
   2410   if (IsString()) {
   2411     HeapStringAllocator allocator;
   2412     StringStream accumulator(&allocator);
   2413     String::cast(this)->StringShortPrint(&accumulator);
   2414     os << accumulator.ToCString().get();
   2415     return;
   2416   }
   2417   if (IsJSObject()) {
   2418     HeapStringAllocator allocator;
   2419     StringStream accumulator(&allocator);
   2420     JSObject::cast(this)->JSObjectShortPrint(&accumulator);
   2421     os << accumulator.ToCString().get();
   2422     return;
   2423   }
   2424   switch (map()->instance_type()) {
   2425     case MAP_TYPE:
   2426       os << "<Map(" << ElementsKindToString(Map::cast(this)->elements_kind())
   2427          << ")>";
   2428       break;
   2429     case FIXED_ARRAY_TYPE:
   2430       os << "<FixedArray[" << FixedArray::cast(this)->length() << "]>";
   2431       break;
   2432     case FIXED_DOUBLE_ARRAY_TYPE:
   2433       os << "<FixedDoubleArray[" << FixedDoubleArray::cast(this)->length()
   2434          << "]>";
   2435       break;
   2436     case BYTE_ARRAY_TYPE:
   2437       os << "<ByteArray[" << ByteArray::cast(this)->length() << "]>";
   2438       break;
   2439     case BYTECODE_ARRAY_TYPE:
   2440       os << "<BytecodeArray[" << BytecodeArray::cast(this)->length() << "]>";
   2441       break;
   2442     case TRANSITION_ARRAY_TYPE:
   2443       os << "<TransitionArray[" << TransitionArray::cast(this)->length()
   2444          << "]>";
   2445       break;
   2446     case FREE_SPACE_TYPE:
   2447       os << "<FreeSpace[" << FreeSpace::cast(this)->size() << "]>";
   2448       break;
   2449 #define TYPED_ARRAY_SHORT_PRINT(Type, type, TYPE, ctype, size)                \
   2450   case FIXED_##TYPE##_ARRAY_TYPE:                                             \
   2451     os << "<Fixed" #Type "Array[" << Fixed##Type##Array::cast(this)->length() \
   2452        << "]>";                                                               \
   2453     break;
   2454 
   2455     TYPED_ARRAYS(TYPED_ARRAY_SHORT_PRINT)
   2456 #undef TYPED_ARRAY_SHORT_PRINT
   2457 
   2458     case SHARED_FUNCTION_INFO_TYPE: {
   2459       SharedFunctionInfo* shared = SharedFunctionInfo::cast(this);
   2460       base::SmartArrayPointer<char> debug_name =
   2461           shared->DebugName()->ToCString();
   2462       if (debug_name[0] != 0) {
   2463         os << "<SharedFunctionInfo " << debug_name.get() << ">";
   2464       } else {
   2465         os << "<SharedFunctionInfo>";
   2466       }
   2467       break;
   2468     }
   2469     case JS_MESSAGE_OBJECT_TYPE:
   2470       os << "<JSMessageObject>";
   2471       break;
   2472 #define MAKE_STRUCT_CASE(NAME, Name, name) \
   2473   case NAME##_TYPE:                        \
   2474     os << "<" #Name ">";                   \
   2475     break;
   2476   STRUCT_LIST(MAKE_STRUCT_CASE)
   2477 #undef MAKE_STRUCT_CASE
   2478     case CODE_TYPE: {
   2479       Code* code = Code::cast(this);
   2480       os << "<Code: " << Code::Kind2String(code->kind()) << ">";
   2481       break;
   2482     }
   2483     case ODDBALL_TYPE: {
   2484       if (IsUndefined(isolate)) {
   2485         os << "<undefined>";
   2486       } else if (IsTheHole(isolate)) {
   2487         os << "<the hole>";
   2488       } else if (IsNull(isolate)) {
   2489         os << "<null>";
   2490       } else if (IsTrue(isolate)) {
   2491         os << "<true>";
   2492       } else if (IsFalse(isolate)) {
   2493         os << "<false>";
   2494       } else {
   2495         os << "<Odd Oddball: ";
   2496         os << Oddball::cast(this)->to_string()->ToCString().get();
   2497         os << ">";
   2498       }
   2499       break;
   2500     }
   2501     case SYMBOL_TYPE: {
   2502       Symbol* symbol = Symbol::cast(this);
   2503       symbol->SymbolShortPrint(os);
   2504       break;
   2505     }
   2506     case HEAP_NUMBER_TYPE: {
   2507       os << "<Number: ";
   2508       HeapNumber::cast(this)->HeapNumberPrint(os);
   2509       os << ">";
   2510       break;
   2511     }
   2512     case MUTABLE_HEAP_NUMBER_TYPE: {
   2513       os << "<MutableNumber: ";
   2514       HeapNumber::cast(this)->HeapNumberPrint(os);
   2515       os << '>';
   2516       break;
   2517     }
   2518     case SIMD128_VALUE_TYPE: {
   2519 #define SIMD128_TYPE(TYPE, Type, type, lane_count, lane_type) \
   2520   if (Is##Type()) {                                           \
   2521     os << "<" #Type ">";                                      \
   2522     break;                                                    \
   2523   }
   2524       SIMD128_TYPES(SIMD128_TYPE)
   2525 #undef SIMD128_TYPE
   2526       UNREACHABLE();
   2527       break;
   2528     }
   2529     case JS_PROXY_TYPE:
   2530       os << "<JSProxy>";
   2531       break;
   2532     case FOREIGN_TYPE:
   2533       os << "<Foreign>";
   2534       break;
   2535     case CELL_TYPE: {
   2536       os << "Cell for ";
   2537       HeapStringAllocator allocator;
   2538       StringStream accumulator(&allocator);
   2539       Cell::cast(this)->value()->ShortPrint(&accumulator);
   2540       os << accumulator.ToCString().get();
   2541       break;
   2542     }
   2543     case PROPERTY_CELL_TYPE: {
   2544       os << "PropertyCell for ";
   2545       HeapStringAllocator allocator;
   2546       StringStream accumulator(&allocator);
   2547       PropertyCell* cell = PropertyCell::cast(this);
   2548       cell->value()->ShortPrint(&accumulator);
   2549       os << accumulator.ToCString().get();
   2550       break;
   2551     }
   2552     case WEAK_CELL_TYPE: {
   2553       os << "WeakCell for ";
   2554       HeapStringAllocator allocator;
   2555       StringStream accumulator(&allocator);
   2556       WeakCell::cast(this)->value()->ShortPrint(&accumulator);
   2557       os << accumulator.ToCString().get();
   2558       break;
   2559     }
   2560     default:
   2561       os << "<Other heap object (" << map()->instance_type() << ")>";
   2562       break;
   2563   }
   2564 }
   2565 
   2566 
   2567 void HeapObject::Iterate(ObjectVisitor* v) { IterateFast<ObjectVisitor>(v); }
   2568 
   2569 
   2570 void HeapObject::IterateBody(ObjectVisitor* v) {
   2571   Map* m = map();
   2572   IterateBodyFast<ObjectVisitor>(m->instance_type(), SizeFromMap(m), v);
   2573 }
   2574 
   2575 
   2576 void HeapObject::IterateBody(InstanceType type, int object_size,
   2577                              ObjectVisitor* v) {
   2578   IterateBodyFast<ObjectVisitor>(type, object_size, v);
   2579 }
   2580 
   2581 
   2582 struct CallIsValidSlot {
   2583   template <typename BodyDescriptor>
   2584   static bool apply(HeapObject* obj, int offset, int) {
   2585     return BodyDescriptor::IsValidSlot(obj, offset);
   2586   }
   2587 };
   2588 
   2589 
   2590 bool HeapObject::IsValidSlot(int offset) {
   2591   DCHECK_NE(0, offset);
   2592   return BodyDescriptorApply<CallIsValidSlot, bool>(map()->instance_type(),
   2593                                                     this, offset, 0);
   2594 }
   2595 
   2596 
   2597 bool HeapNumber::HeapNumberBooleanValue() {
   2598   return DoubleToBoolean(value());
   2599 }
   2600 
   2601 
   2602 void HeapNumber::HeapNumberPrint(std::ostream& os) {  // NOLINT
   2603   os << value();
   2604 }
   2605 
   2606 
   2607 #define FIELD_ADDR_CONST(p, offset) \
   2608   (reinterpret_cast<const byte*>(p) + offset - kHeapObjectTag)
   2609 
   2610 #define READ_INT32_FIELD(p, offset) \
   2611   (*reinterpret_cast<const int32_t*>(FIELD_ADDR_CONST(p, offset)))
   2612 
   2613 #define READ_INT64_FIELD(p, offset) \
   2614   (*reinterpret_cast<const int64_t*>(FIELD_ADDR_CONST(p, offset)))
   2615 
   2616 #define READ_BYTE_FIELD(p, offset) \
   2617   (*reinterpret_cast<const byte*>(FIELD_ADDR_CONST(p, offset)))
   2618 
   2619 
   2620 // static
   2621 Handle<String> Simd128Value::ToString(Handle<Simd128Value> input) {
   2622 #define SIMD128_TYPE(TYPE, Type, type, lane_count, lane_type) \
   2623   if (input->Is##Type()) return Type::ToString(Handle<Type>::cast(input));
   2624   SIMD128_TYPES(SIMD128_TYPE)
   2625 #undef SIMD128_TYPE
   2626   UNREACHABLE();
   2627   return Handle<String>::null();
   2628 }
   2629 
   2630 
   2631 // static
   2632 Handle<String> Float32x4::ToString(Handle<Float32x4> input) {
   2633   Isolate* const isolate = input->GetIsolate();
   2634   char arr[100];
   2635   Vector<char> buffer(arr, arraysize(arr));
   2636   std::ostringstream os;
   2637   os << "SIMD.Float32x4("
   2638      << std::string(DoubleToCString(input->get_lane(0), buffer)) << ", "
   2639      << std::string(DoubleToCString(input->get_lane(1), buffer)) << ", "
   2640      << std::string(DoubleToCString(input->get_lane(2), buffer)) << ", "
   2641      << std::string(DoubleToCString(input->get_lane(3), buffer)) << ")";
   2642   return isolate->factory()->NewStringFromAsciiChecked(os.str().c_str());
   2643 }
   2644 
   2645 
   2646 #define SIMD128_BOOL_TO_STRING(Type, lane_count)                            \
   2647   Handle<String> Type::ToString(Handle<Type> input) {                       \
   2648     Isolate* const isolate = input->GetIsolate();                           \
   2649     std::ostringstream os;                                                  \
   2650     os << "SIMD." #Type "(";                                                \
   2651     os << (input->get_lane(0) ? "true" : "false");                          \
   2652     for (int i = 1; i < lane_count; i++) {                                  \
   2653       os << ", " << (input->get_lane(i) ? "true" : "false");                \
   2654     }                                                                       \
   2655     os << ")";                                                              \
   2656     return isolate->factory()->NewStringFromAsciiChecked(os.str().c_str()); \
   2657   }
   2658 SIMD128_BOOL_TO_STRING(Bool32x4, 4)
   2659 SIMD128_BOOL_TO_STRING(Bool16x8, 8)
   2660 SIMD128_BOOL_TO_STRING(Bool8x16, 16)
   2661 #undef SIMD128_BOOL_TO_STRING
   2662 
   2663 
   2664 #define SIMD128_INT_TO_STRING(Type, lane_count)                             \
   2665   Handle<String> Type::ToString(Handle<Type> input) {                       \
   2666     Isolate* const isolate = input->GetIsolate();                           \
   2667     char arr[100];                                                          \
   2668     Vector<char> buffer(arr, arraysize(arr));                               \
   2669     std::ostringstream os;                                                  \
   2670     os << "SIMD." #Type "(";                                                \
   2671     os << IntToCString(input->get_lane(0), buffer);                         \
   2672     for (int i = 1; i < lane_count; i++) {                                  \
   2673       os << ", " << IntToCString(input->get_lane(i), buffer);               \
   2674     }                                                                       \
   2675     os << ")";                                                              \
   2676     return isolate->factory()->NewStringFromAsciiChecked(os.str().c_str()); \
   2677   }
   2678 SIMD128_INT_TO_STRING(Int32x4, 4)
   2679 SIMD128_INT_TO_STRING(Uint32x4, 4)
   2680 SIMD128_INT_TO_STRING(Int16x8, 8)
   2681 SIMD128_INT_TO_STRING(Uint16x8, 8)
   2682 SIMD128_INT_TO_STRING(Int8x16, 16)
   2683 SIMD128_INT_TO_STRING(Uint8x16, 16)
   2684 #undef SIMD128_INT_TO_STRING
   2685 
   2686 
   2687 bool Simd128Value::BitwiseEquals(const Simd128Value* other) const {
   2688   return READ_INT64_FIELD(this, kValueOffset) ==
   2689              READ_INT64_FIELD(other, kValueOffset) &&
   2690          READ_INT64_FIELD(this, kValueOffset + kInt64Size) ==
   2691              READ_INT64_FIELD(other, kValueOffset + kInt64Size);
   2692 }
   2693 
   2694 
   2695 uint32_t Simd128Value::Hash() const {
   2696   uint32_t seed = v8::internal::kZeroHashSeed;
   2697   uint32_t hash;
   2698   hash = ComputeIntegerHash(READ_INT32_FIELD(this, kValueOffset), seed);
   2699   hash = ComputeIntegerHash(
   2700       READ_INT32_FIELD(this, kValueOffset + 1 * kInt32Size), hash * 31);
   2701   hash = ComputeIntegerHash(
   2702       READ_INT32_FIELD(this, kValueOffset + 2 * kInt32Size), hash * 31);
   2703   hash = ComputeIntegerHash(
   2704       READ_INT32_FIELD(this, kValueOffset + 3 * kInt32Size), hash * 31);
   2705   return hash;
   2706 }
   2707 
   2708 
   2709 void Simd128Value::CopyBits(void* destination) const {
   2710   memcpy(destination, &READ_BYTE_FIELD(this, kValueOffset), kSimd128Size);
   2711 }
   2712 
   2713 
   2714 String* JSReceiver::class_name() {
   2715   if (IsFunction()) {
   2716     return GetHeap()->Function_string();
   2717   }
   2718   Object* maybe_constructor = map()->GetConstructor();
   2719   if (maybe_constructor->IsJSFunction()) {
   2720     JSFunction* constructor = JSFunction::cast(maybe_constructor);
   2721     return String::cast(constructor->shared()->instance_class_name());
   2722   }
   2723   // If the constructor is not present, return "Object".
   2724   return GetHeap()->Object_string();
   2725 }
   2726 
   2727 
   2728 // static
   2729 Handle<String> JSReceiver::GetConstructorName(Handle<JSReceiver> receiver) {
   2730   Isolate* isolate = receiver->GetIsolate();
   2731 
   2732   // If the object was instantiated simply with base == new.target, the
   2733   // constructor on the map provides the most accurate name.
   2734   // Don't provide the info for prototypes, since their constructors are
   2735   // reclaimed and replaced by Object in OptimizeAsPrototype.
   2736   if (!receiver->IsJSProxy() && receiver->map()->new_target_is_base() &&
   2737       !receiver->map()->is_prototype_map()) {
   2738     Object* maybe_constructor = receiver->map()->GetConstructor();
   2739     if (maybe_constructor->IsJSFunction()) {
   2740       JSFunction* constructor = JSFunction::cast(maybe_constructor);
   2741       String* name = String::cast(constructor->shared()->name());
   2742       if (name->length() == 0) name = constructor->shared()->inferred_name();
   2743       if (name->length() != 0 &&
   2744           !name->Equals(isolate->heap()->Object_string())) {
   2745         return handle(name, isolate);
   2746       }
   2747     }
   2748   }
   2749 
   2750   Handle<Object> maybe_tag = JSReceiver::GetDataProperty(
   2751       receiver, isolate->factory()->to_string_tag_symbol());
   2752   if (maybe_tag->IsString()) return Handle<String>::cast(maybe_tag);
   2753 
   2754   PrototypeIterator iter(isolate, receiver);
   2755   if (iter.IsAtEnd()) return handle(receiver->class_name());
   2756   Handle<JSReceiver> start = PrototypeIterator::GetCurrent<JSReceiver>(iter);
   2757   LookupIterator it(receiver, isolate->factory()->constructor_string(), start,
   2758                     LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
   2759   Handle<Object> maybe_constructor = JSReceiver::GetDataProperty(&it);
   2760   Handle<String> result = isolate->factory()->Object_string();
   2761   if (maybe_constructor->IsJSFunction()) {
   2762     JSFunction* constructor = JSFunction::cast(*maybe_constructor);
   2763     String* name = String::cast(constructor->shared()->name());
   2764     if (name->length() == 0) name = constructor->shared()->inferred_name();
   2765     if (name->length() > 0) result = handle(name, isolate);
   2766   }
   2767 
   2768   return result.is_identical_to(isolate->factory()->Object_string())
   2769              ? handle(receiver->class_name())
   2770              : result;
   2771 }
   2772 
   2773 
   2774 Context* JSReceiver::GetCreationContext() {
   2775   JSReceiver* receiver = this;
   2776   while (receiver->IsJSBoundFunction()) {
   2777     receiver = JSBoundFunction::cast(receiver)->bound_target_function();
   2778   }
   2779   Object* constructor = receiver->map()->GetConstructor();
   2780   JSFunction* function;
   2781   if (constructor->IsJSFunction()) {
   2782     function = JSFunction::cast(constructor);
   2783   } else {
   2784     // Functions have null as a constructor,
   2785     // but any JSFunction knows its context immediately.
   2786     CHECK(receiver->IsJSFunction());
   2787     function = JSFunction::cast(receiver);
   2788   }
   2789 
   2790   return function->context()->native_context();
   2791 }
   2792 
   2793 static Handle<Object> WrapType(Handle<FieldType> type) {
   2794   if (type->IsClass()) return Map::WeakCellForMap(type->AsClass());
   2795   return type;
   2796 }
   2797 
   2798 MaybeHandle<Map> Map::CopyWithField(Handle<Map> map, Handle<Name> name,
   2799                                     Handle<FieldType> type,
   2800                                     PropertyAttributes attributes,
   2801                                     Representation representation,
   2802                                     TransitionFlag flag) {
   2803   DCHECK(DescriptorArray::kNotFound ==
   2804          map->instance_descriptors()->Search(
   2805              *name, map->NumberOfOwnDescriptors()));
   2806 
   2807   // Ensure the descriptor array does not get too big.
   2808   if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors) {
   2809     return MaybeHandle<Map>();
   2810   }
   2811 
   2812   Isolate* isolate = map->GetIsolate();
   2813 
   2814   // Compute the new index for new field.
   2815   int index = map->NextFreePropertyIndex();
   2816 
   2817   if (map->instance_type() == JS_CONTEXT_EXTENSION_OBJECT_TYPE) {
   2818     representation = Representation::Tagged();
   2819     type = FieldType::Any(isolate);
   2820   }
   2821 
   2822   Handle<Object> wrapped_type(WrapType(type));
   2823 
   2824   DataDescriptor new_field_desc(name, index, wrapped_type, attributes,
   2825                                 representation);
   2826   Handle<Map> new_map = Map::CopyAddDescriptor(map, &new_field_desc, flag);
   2827   int unused_property_fields = new_map->unused_property_fields() - 1;
   2828   if (unused_property_fields < 0) {
   2829     unused_property_fields += JSObject::kFieldsAdded;
   2830   }
   2831   new_map->set_unused_property_fields(unused_property_fields);
   2832   return new_map;
   2833 }
   2834 
   2835 
   2836 MaybeHandle<Map> Map::CopyWithConstant(Handle<Map> map,
   2837                                        Handle<Name> name,
   2838                                        Handle<Object> constant,
   2839                                        PropertyAttributes attributes,
   2840                                        TransitionFlag flag) {
   2841   // Ensure the descriptor array does not get too big.
   2842   if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors) {
   2843     return MaybeHandle<Map>();
   2844   }
   2845 
   2846   // Allocate new instance descriptors with (name, constant) added.
   2847   DataConstantDescriptor new_constant_desc(name, constant, attributes);
   2848   return Map::CopyAddDescriptor(map, &new_constant_desc, flag);
   2849 }
   2850 
   2851 
   2852 void JSObject::AddSlowProperty(Handle<JSObject> object,
   2853                                Handle<Name> name,
   2854                                Handle<Object> value,
   2855                                PropertyAttributes attributes) {
   2856   DCHECK(!object->HasFastProperties());
   2857   Isolate* isolate = object->GetIsolate();
   2858   if (object->IsJSGlobalObject()) {
   2859     Handle<GlobalDictionary> dict(object->global_dictionary());
   2860     PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell);
   2861     int entry = dict->FindEntry(name);
   2862     // If there's a cell there, just invalidate and set the property.
   2863     if (entry != GlobalDictionary::kNotFound) {
   2864       PropertyCell::UpdateCell(dict, entry, value, details);
   2865       // TODO(ishell): move this to UpdateCell.
   2866       // Need to adjust the details.
   2867       int index = dict->NextEnumerationIndex();
   2868       dict->SetNextEnumerationIndex(index + 1);
   2869       PropertyCell* cell = PropertyCell::cast(dict->ValueAt(entry));
   2870       details = cell->property_details().set_index(index);
   2871       cell->set_property_details(details);
   2872 
   2873     } else {
   2874       auto cell = isolate->factory()->NewPropertyCell();
   2875       cell->set_value(*value);
   2876       auto cell_type = value->IsUndefined(isolate)
   2877                            ? PropertyCellType::kUndefined
   2878                            : PropertyCellType::kConstant;
   2879       details = details.set_cell_type(cell_type);
   2880       value = cell;
   2881 
   2882       Handle<GlobalDictionary> result =
   2883           GlobalDictionary::Add(dict, name, value, details);
   2884       if (*dict != *result) object->set_properties(*result);
   2885     }
   2886   } else {
   2887     Handle<NameDictionary> dict(object->property_dictionary());
   2888     PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell);
   2889     Handle<NameDictionary> result =
   2890         NameDictionary::Add(dict, name, value, details);
   2891     if (*dict != *result) object->set_properties(*result);
   2892   }
   2893 }
   2894 
   2895 
   2896 const char* Representation::Mnemonic() const {
   2897   switch (kind_) {
   2898     case kNone: return "v";
   2899     case kTagged: return "t";
   2900     case kSmi: return "s";
   2901     case kDouble: return "d";
   2902     case kInteger32: return "i";
   2903     case kHeapObject: return "h";
   2904     case kExternal: return "x";
   2905     default:
   2906       UNREACHABLE();
   2907       return NULL;
   2908   }
   2909 }
   2910 
   2911 bool Map::InstancesNeedRewriting(Map* target) {
   2912   int target_number_of_fields = target->NumberOfFields();
   2913   int target_inobject = target->GetInObjectProperties();
   2914   int target_unused = target->unused_property_fields();
   2915   int old_number_of_fields;
   2916 
   2917   return InstancesNeedRewriting(target, target_number_of_fields,
   2918                                 target_inobject, target_unused,
   2919                                 &old_number_of_fields);
   2920 }
   2921 
   2922 bool Map::InstancesNeedRewriting(Map* target, int target_number_of_fields,
   2923                                  int target_inobject, int target_unused,
   2924                                  int* old_number_of_fields) {
   2925   // If fields were added (or removed), rewrite the instance.
   2926   *old_number_of_fields = NumberOfFields();
   2927   DCHECK(target_number_of_fields >= *old_number_of_fields);
   2928   if (target_number_of_fields != *old_number_of_fields) return true;
   2929 
   2930   // If smi descriptors were replaced by double descriptors, rewrite.
   2931   DescriptorArray* old_desc = instance_descriptors();
   2932   DescriptorArray* new_desc = target->instance_descriptors();
   2933   int limit = NumberOfOwnDescriptors();
   2934   for (int i = 0; i < limit; i++) {
   2935     if (new_desc->GetDetails(i).representation().IsDouble() !=
   2936         old_desc->GetDetails(i).representation().IsDouble()) {
   2937       return true;
   2938     }
   2939   }
   2940 
   2941   // If no fields were added, and no inobject properties were removed, setting
   2942   // the map is sufficient.
   2943   if (target_inobject == GetInObjectProperties()) return false;
   2944   // In-object slack tracking may have reduced the object size of the new map.
   2945   // In that case, succeed if all existing fields were inobject, and they still
   2946   // fit within the new inobject size.
   2947   DCHECK(target_inobject < GetInObjectProperties());
   2948   if (target_number_of_fields <= target_inobject) {
   2949     DCHECK(target_number_of_fields + target_unused == target_inobject);
   2950     return false;
   2951   }
   2952   // Otherwise, properties will need to be moved to the backing store.
   2953   return true;
   2954 }
   2955 
   2956 
   2957 // static
   2958 void JSObject::UpdatePrototypeUserRegistration(Handle<Map> old_map,
   2959                                                Handle<Map> new_map,
   2960                                                Isolate* isolate) {
   2961   if (!old_map->is_prototype_map()) return;
   2962   DCHECK(new_map->is_prototype_map());
   2963   bool was_registered = JSObject::UnregisterPrototypeUser(old_map, isolate);
   2964   new_map->set_prototype_info(old_map->prototype_info());
   2965   old_map->set_prototype_info(Smi::FromInt(0));
   2966   if (FLAG_trace_prototype_users) {
   2967     PrintF("Moving prototype_info %p from map %p to map %p.\n",
   2968            reinterpret_cast<void*>(new_map->prototype_info()),
   2969            reinterpret_cast<void*>(*old_map),
   2970            reinterpret_cast<void*>(*new_map));
   2971   }
   2972   if (was_registered) {
   2973     if (new_map->prototype_info()->IsPrototypeInfo()) {
   2974       // The new map isn't registered with its prototype yet; reflect this fact
   2975       // in the PrototypeInfo it just inherited from the old map.
   2976       PrototypeInfo::cast(new_map->prototype_info())
   2977           ->set_registry_slot(PrototypeInfo::UNREGISTERED);
   2978     }
   2979     JSObject::LazyRegisterPrototypeUser(new_map, isolate);
   2980   }
   2981 }
   2982 
   2983 namespace {
   2984 // To migrate a fast instance to a fast map:
   2985 // - First check whether the instance needs to be rewritten. If not, simply
   2986 //   change the map.
   2987 // - Otherwise, allocate a fixed array large enough to hold all fields, in
   2988 //   addition to unused space.
   2989 // - Copy all existing properties in, in the following order: backing store
   2990 //   properties, unused fields, inobject properties.
   2991 // - If all allocation succeeded, commit the state atomically:
   2992 //   * Copy inobject properties from the backing store back into the object.
   2993 //   * Trim the difference in instance size of the object. This also cleanly
   2994 //     frees inobject properties that moved to the backing store.
   2995 //   * If there are properties left in the backing store, trim of the space used
   2996 //     to temporarily store the inobject properties.
   2997 //   * If there are properties left in the backing store, install the backing
   2998 //     store.
   2999 void MigrateFastToFast(Handle<JSObject> object, Handle<Map> new_map) {
   3000   Isolate* isolate = object->GetIsolate();
   3001   Handle<Map> old_map(object->map());
   3002   // In case of a regular transition.
   3003   if (new_map->GetBackPointer() == *old_map) {
   3004     // If the map does not add named properties, simply set the map.
   3005     if (old_map->NumberOfOwnDescriptors() ==
   3006         new_map->NumberOfOwnDescriptors()) {
   3007       object->synchronized_set_map(*new_map);
   3008       return;
   3009     }
   3010 
   3011     PropertyDetails details = new_map->GetLastDescriptorDetails();
   3012     // Either new_map adds an kDescriptor property, or a kField property for
   3013     // which there is still space, and which does not require a mutable double
   3014     // box (an out-of-object double).
   3015     if (details.location() == kDescriptor ||
   3016         (old_map->unused_property_fields() > 0 &&
   3017          ((FLAG_unbox_double_fields && object->properties()->length() == 0) ||
   3018           !details.representation().IsDouble()))) {
   3019       object->synchronized_set_map(*new_map);
   3020       return;
   3021     }
   3022 
   3023     // If there is still space in the object, we need to allocate a mutable
   3024     // double box.
   3025     if (old_map->unused_property_fields() > 0) {
   3026       FieldIndex index =
   3027           FieldIndex::ForDescriptor(*new_map, new_map->LastAdded());
   3028       DCHECK(details.representation().IsDouble());
   3029       DCHECK(!new_map->IsUnboxedDoubleField(index));
   3030       Handle<Object> value = isolate->factory()->NewHeapNumber(0, MUTABLE);
   3031       object->RawFastPropertyAtPut(index, *value);
   3032       object->synchronized_set_map(*new_map);
   3033       return;
   3034     }
   3035 
   3036     // This migration is a transition from a map that has run out of property
   3037     // space. Extend the backing store.
   3038     int grow_by = new_map->unused_property_fields() + 1;
   3039     Handle<FixedArray> old_storage = handle(object->properties(), isolate);
   3040     Handle<FixedArray> new_storage =
   3041         isolate->factory()->CopyFixedArrayAndGrow(old_storage, grow_by);
   3042 
   3043     // Properly initialize newly added property.
   3044     Handle<Object> value;
   3045     if (details.representation().IsDouble()) {
   3046       value = isolate->factory()->NewHeapNumber(0, MUTABLE);
   3047     } else {
   3048       value = isolate->factory()->uninitialized_value();
   3049     }
   3050     DCHECK_EQ(DATA, details.type());
   3051     int target_index = details.field_index() - new_map->GetInObjectProperties();
   3052     DCHECK(target_index >= 0);  // Must be a backing store index.
   3053     new_storage->set(target_index, *value);
   3054 
   3055     // From here on we cannot fail and we shouldn't GC anymore.
   3056     DisallowHeapAllocation no_allocation;
   3057 
   3058     // Set the new property value and do the map transition.
   3059     object->set_properties(*new_storage);
   3060     object->synchronized_set_map(*new_map);
   3061     return;
   3062   }
   3063 
   3064   int old_number_of_fields;
   3065   int number_of_fields = new_map->NumberOfFields();
   3066   int inobject = new_map->GetInObjectProperties();
   3067   int unused = new_map->unused_property_fields();
   3068 
   3069   // Nothing to do if no functions were converted to fields and no smis were
   3070   // converted to doubles.
   3071   if (!old_map->InstancesNeedRewriting(*new_map, number_of_fields, inobject,
   3072                                        unused, &old_number_of_fields)) {
   3073     object->synchronized_set_map(*new_map);
   3074     return;
   3075   }
   3076 
   3077   int total_size = number_of_fields + unused;
   3078   int external = total_size - inobject;
   3079 
   3080   Handle<FixedArray> array = isolate->factory()->NewFixedArray(total_size);
   3081 
   3082   Handle<DescriptorArray> old_descriptors(old_map->instance_descriptors());
   3083   Handle<DescriptorArray> new_descriptors(new_map->instance_descriptors());
   3084   int old_nof = old_map->NumberOfOwnDescriptors();
   3085   int new_nof = new_map->NumberOfOwnDescriptors();
   3086 
   3087   // This method only supports generalizing instances to at least the same
   3088   // number of properties.
   3089   DCHECK(old_nof <= new_nof);
   3090 
   3091   for (int i = 0; i < old_nof; i++) {
   3092     PropertyDetails details = new_descriptors->GetDetails(i);
   3093     if (details.type() != DATA) continue;
   3094     PropertyDetails old_details = old_descriptors->GetDetails(i);
   3095     Representation old_representation = old_details.representation();
   3096     Representation representation = details.representation();
   3097     Handle<Object> value;
   3098     if (old_details.type() == ACCESSOR_CONSTANT) {
   3099       // In case of kAccessor -> kData property reconfiguration, the property
   3100       // must already be prepared for data or certain type.
   3101       DCHECK(!details.representation().IsNone());
   3102       if (details.representation().IsDouble()) {
   3103         value = isolate->factory()->NewHeapNumber(0, MUTABLE);
   3104       } else {
   3105         value = isolate->factory()->uninitialized_value();
   3106       }
   3107     } else if (old_details.type() == DATA_CONSTANT) {
   3108       value = handle(old_descriptors->GetValue(i), isolate);
   3109       DCHECK(!old_representation.IsDouble() && !representation.IsDouble());
   3110     } else {
   3111       FieldIndex index = FieldIndex::ForDescriptor(*old_map, i);
   3112       if (object->IsUnboxedDoubleField(index)) {
   3113         double old = object->RawFastDoublePropertyAt(index);
   3114         value = isolate->factory()->NewHeapNumber(
   3115             old, representation.IsDouble() ? MUTABLE : IMMUTABLE);
   3116 
   3117       } else {
   3118         value = handle(object->RawFastPropertyAt(index), isolate);
   3119         if (!old_representation.IsDouble() && representation.IsDouble()) {
   3120           if (old_representation.IsNone()) {
   3121             value = handle(Smi::FromInt(0), isolate);
   3122           }
   3123           value = Object::NewStorageFor(isolate, value, representation);
   3124         } else if (old_representation.IsDouble() &&
   3125                    !representation.IsDouble()) {
   3126           value = Object::WrapForRead(isolate, value, old_representation);
   3127         }
   3128       }
   3129     }
   3130     DCHECK(!(representation.IsDouble() && value->IsSmi()));
   3131     int target_index = new_descriptors->GetFieldIndex(i) - inobject;
   3132     if (target_index < 0) target_index += total_size;
   3133     array->set(target_index, *value);
   3134   }
   3135 
   3136   for (int i = old_nof; i < new_nof; i++) {
   3137     PropertyDetails details = new_descriptors->GetDetails(i);
   3138     if (details.type() != DATA) continue;
   3139     Handle<Object> value;
   3140     if (details.representation().IsDouble()) {
   3141       value = isolate->factory()->NewHeapNumber(0, MUTABLE);
   3142     } else {
   3143       value = isolate->factory()->uninitialized_value();
   3144     }
   3145     int target_index = new_descriptors->GetFieldIndex(i) - inobject;
   3146     if (target_index < 0) target_index += total_size;
   3147     array->set(target_index, *value);
   3148   }
   3149 
   3150   // From here on we cannot fail and we shouldn't GC anymore.
   3151   DisallowHeapAllocation no_allocation;
   3152 
   3153   Heap* heap = isolate->heap();
   3154 
   3155   // Copy (real) inobject properties. If necessary, stop at number_of_fields to
   3156   // avoid overwriting |one_pointer_filler_map|.
   3157   int limit = Min(inobject, number_of_fields);
   3158   for (int i = 0; i < limit; i++) {
   3159     FieldIndex index = FieldIndex::ForPropertyIndex(*new_map, i);
   3160     Object* value = array->get(external + i);
   3161     // Can't use JSObject::FastPropertyAtPut() because proper map was not set
   3162     // yet.
   3163     if (new_map->IsUnboxedDoubleField(index)) {
   3164       DCHECK(value->IsMutableHeapNumber());
   3165       object->RawFastDoublePropertyAtPut(index,
   3166                                          HeapNumber::cast(value)->value());
   3167       if (i < old_number_of_fields && !old_map->IsUnboxedDoubleField(index)) {
   3168         // Transition from tagged to untagged slot.
   3169         heap->ClearRecordedSlot(*object,
   3170                                 HeapObject::RawField(*object, index.offset()));
   3171       }
   3172     } else {
   3173       object->RawFastPropertyAtPut(index, value);
   3174     }
   3175   }
   3176 
   3177 
   3178   // If there are properties in the new backing store, trim it to the correct
   3179   // size and install the backing store into the object.
   3180   if (external > 0) {
   3181     heap->RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>(*array, inobject);
   3182     object->set_properties(*array);
   3183   }
   3184 
   3185   // Create filler object past the new instance size.
   3186   int new_instance_size = new_map->instance_size();
   3187   int instance_size_delta = old_map->instance_size() - new_instance_size;
   3188   DCHECK(instance_size_delta >= 0);
   3189 
   3190   if (instance_size_delta > 0) {
   3191     Address address = object->address();
   3192     heap->CreateFillerObjectAt(address + new_instance_size, instance_size_delta,
   3193                                ClearRecordedSlots::kYes);
   3194     heap->AdjustLiveBytes(*object, -instance_size_delta,
   3195                           Heap::CONCURRENT_TO_SWEEPER);
   3196   }
   3197 
   3198   // We are storing the new map using release store after creating a filler for
   3199   // the left-over space to avoid races with the sweeper thread.
   3200   object->synchronized_set_map(*new_map);
   3201 }
   3202 
   3203 void MigrateFastToSlow(Handle<JSObject> object, Handle<Map> new_map,
   3204                        int expected_additional_properties) {
   3205   // The global object is always normalized.
   3206   DCHECK(!object->IsJSGlobalObject());
   3207   // JSGlobalProxy must never be normalized
   3208   DCHECK(!object->IsJSGlobalProxy());
   3209 
   3210   Isolate* isolate = object->GetIsolate();
   3211   HandleScope scope(isolate);
   3212   Handle<Map> map(object->map());
   3213 
   3214   // Allocate new content.
   3215   int real_size = map->NumberOfOwnDescriptors();
   3216   int property_count = real_size;
   3217   if (expected_additional_properties > 0) {
   3218     property_count += expected_additional_properties;
   3219   } else {
   3220     property_count += 2;  // Make space for two more properties.
   3221   }
   3222   Handle<NameDictionary> dictionary =
   3223       NameDictionary::New(isolate, property_count);
   3224 
   3225   Handle<DescriptorArray> descs(map->instance_descriptors());
   3226   for (int i = 0; i < real_size; i++) {
   3227     PropertyDetails details = descs->GetDetails(i);
   3228     Handle<Name> key(descs->GetKey(i));
   3229     switch (details.type()) {
   3230       case DATA_CONSTANT: {
   3231         Handle<Object> value(descs->GetConstant(i), isolate);
   3232         PropertyDetails d(details.attributes(), DATA, i + 1,
   3233                           PropertyCellType::kNoCell);
   3234         dictionary = NameDictionary::Add(dictionary, key, value, d);
   3235         break;
   3236       }
   3237       case DATA: {
   3238         FieldIndex index = FieldIndex::ForDescriptor(*map, i);
   3239         Handle<Object> value;
   3240         if (object->IsUnboxedDoubleField(index)) {
   3241           double old_value = object->RawFastDoublePropertyAt(index);
   3242           value = isolate->factory()->NewHeapNumber(old_value);
   3243         } else {
   3244           value = handle(object->RawFastPropertyAt(index), isolate);
   3245           if (details.representation().IsDouble()) {
   3246             DCHECK(value->IsMutableHeapNumber());
   3247             Handle<HeapNumber> old = Handle<HeapNumber>::cast(value);
   3248             value = isolate->factory()->NewHeapNumber(old->value());
   3249           }
   3250         }
   3251         PropertyDetails d(details.attributes(), DATA, i + 1,
   3252                           PropertyCellType::kNoCell);
   3253         dictionary = NameDictionary::Add(dictionary, key, value, d);
   3254         break;
   3255       }
   3256       case ACCESSOR: {
   3257         FieldIndex index = FieldIndex::ForDescriptor(*map, i);
   3258         Handle<Object> value(object->RawFastPropertyAt(index), isolate);
   3259         PropertyDetails d(details.attributes(), ACCESSOR_CONSTANT, i + 1,
   3260                           PropertyCellType::kNoCell);
   3261         dictionary = NameDictionary::Add(dictionary, key, value, d);
   3262         break;
   3263       }
   3264       case ACCESSOR_CONSTANT: {
   3265         Handle<Object> value(descs->GetCallbacksObject(i), isolate);
   3266         PropertyDetails d(details.attributes(), ACCESSOR_CONSTANT, i + 1,
   3267                           PropertyCellType::kNoCell);
   3268         dictionary = NameDictionary::Add(dictionary, key, value, d);
   3269         break;
   3270       }
   3271     }
   3272   }
   3273 
   3274   // Copy the next enumeration index from instance descriptor.
   3275   dictionary->SetNextEnumerationIndex(real_size + 1);
   3276 
   3277   // From here on we cannot fail and we shouldn't GC anymore.
   3278   DisallowHeapAllocation no_allocation;
   3279 
   3280   // Resize the object in the heap if necessary.
   3281   int new_instance_size = new_map->instance_size();
   3282   int instance_size_delta = map->instance_size() - new_instance_size;
   3283   DCHECK(instance_size_delta >= 0);
   3284 
   3285   if (instance_size_delta > 0) {
   3286     Heap* heap = isolate->heap();
   3287     heap->CreateFillerObjectAt(object->address() + new_instance_size,
   3288                                instance_size_delta, ClearRecordedSlots::kYes);
   3289     heap->AdjustLiveBytes(*object, -instance_size_delta,
   3290                           Heap::CONCURRENT_TO_SWEEPER);
   3291   }
   3292 
   3293   // We are storing the new map using release store after creating a filler for
   3294   // the left-over space to avoid races with the sweeper thread.
   3295   object->synchronized_set_map(*new_map);
   3296 
   3297   object->set_properties(*dictionary);
   3298 
   3299   // Ensure that in-object space of slow-mode object does not contain random
   3300   // garbage.
   3301   int inobject_properties = new_map->GetInObjectProperties();
   3302   for (int i = 0; i < inobject_properties; i++) {
   3303     FieldIndex index = FieldIndex::ForPropertyIndex(*new_map, i);
   3304     object->RawFastPropertyAtPut(index, Smi::FromInt(0));
   3305   }
   3306 
   3307   isolate->counters()->props_to_dictionary()->Increment();
   3308 
   3309 #ifdef DEBUG
   3310   if (FLAG_trace_normalization) {
   3311     OFStream os(stdout);
   3312     os << "Object properties have been normalized:\n";
   3313     object->Print(os);
   3314   }
   3315 #endif
   3316 }
   3317 
   3318 }  // namespace
   3319 
   3320 void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map,
   3321                             int expected_additional_properties) {
   3322   if (object->map() == *new_map) return;
   3323   Handle<Map> old_map(object->map());
   3324   if (old_map->is_prototype_map()) {
   3325     // If this object is a prototype (the callee will check), invalidate any
   3326     // prototype chains involving it.
   3327     InvalidatePrototypeChains(object->map());
   3328 
   3329     // If the map was registered with its prototype before, ensure that it
   3330     // registers with its new prototype now. This preserves the invariant that
   3331     // when a map on a prototype chain is registered with its prototype, then
   3332     // all prototypes further up the chain are also registered with their
   3333     // respective prototypes.
   3334     UpdatePrototypeUserRegistration(old_map, new_map, new_map->GetIsolate());
   3335   }
   3336 
   3337   if (old_map->is_dictionary_map()) {
   3338     // For slow-to-fast migrations JSObject::MigrateSlowToFast()
   3339     // must be used instead.
   3340     CHECK(new_map->is_dictionary_map());
   3341 
   3342     // Slow-to-slow migration is trivial.
   3343     object->set_map(*new_map);
   3344   } else if (!new_map->is_dictionary_map()) {
   3345     MigrateFastToFast(object, new_map);
   3346     if (old_map->is_prototype_map()) {
   3347       DCHECK(!old_map->is_stable());
   3348       DCHECK(new_map->is_stable());
   3349       // Clear out the old descriptor array to avoid problems to sharing
   3350       // the descriptor array without using an explicit.
   3351       old_map->InitializeDescriptors(
   3352           old_map->GetHeap()->empty_descriptor_array(),
   3353           LayoutDescriptor::FastPointerLayout());
   3354       // Ensure that no transition was inserted for prototype migrations.
   3355       DCHECK_EQ(
   3356           0, TransitionArray::NumberOfTransitions(old_map->raw_transitions()));
   3357       DCHECK(new_map->GetBackPointer()->IsUndefined(new_map->GetIsolate()));
   3358     }
   3359   } else {
   3360     MigrateFastToSlow(object, new_map, expected_additional_properties);
   3361   }
   3362 
   3363   // Careful: Don't allocate here!
   3364   // For some callers of this method, |object| might be in an inconsistent
   3365   // state now: the new map might have a new elements_kind, but the object's
   3366   // elements pointer hasn't been updated yet. Callers will fix this, but in
   3367   // the meantime, (indirectly) calling JSObjectVerify() must be avoided.
   3368   // When adding code here, add a DisallowHeapAllocation too.
   3369 }
   3370 
   3371 int Map::NumberOfFields() {
   3372   DescriptorArray* descriptors = instance_descriptors();
   3373   int result = 0;
   3374   for (int i = 0; i < NumberOfOwnDescriptors(); i++) {
   3375     if (descriptors->GetDetails(i).location() == kField) result++;
   3376   }
   3377   return result;
   3378 }
   3379 
   3380 Handle<Map> Map::CopyGeneralizeAllRepresentations(
   3381     Handle<Map> map, ElementsKind elements_kind, int modify_index,
   3382     StoreMode store_mode, PropertyKind kind, PropertyAttributes attributes,
   3383     const char* reason) {
   3384   Isolate* isolate = map->GetIsolate();
   3385   Handle<DescriptorArray> old_descriptors(map->instance_descriptors(), isolate);
   3386   int number_of_own_descriptors = map->NumberOfOwnDescriptors();
   3387   Handle<DescriptorArray> descriptors =
   3388       DescriptorArray::CopyUpTo(old_descriptors, number_of_own_descriptors);
   3389 
   3390   for (int i = 0; i < number_of_own_descriptors; i++) {
   3391     descriptors->SetRepresentation(i, Representation::Tagged());
   3392     if (descriptors->GetDetails(i).type() == DATA) {
   3393       descriptors->SetValue(i, FieldType::Any());
   3394     }
   3395   }
   3396 
   3397   Handle<LayoutDescriptor> new_layout_descriptor(
   3398       LayoutDescriptor::FastPointerLayout(), isolate);
   3399   Handle<Map> new_map = CopyReplaceDescriptors(
   3400       map, descriptors, new_layout_descriptor, OMIT_TRANSITION,
   3401       MaybeHandle<Name>(), reason, SPECIAL_TRANSITION);
   3402 
   3403   // Unless the instance is being migrated, ensure that modify_index is a field.
   3404   if (modify_index >= 0) {
   3405     PropertyDetails details = descriptors->GetDetails(modify_index);
   3406     if (store_mode == FORCE_FIELD &&
   3407         (details.type() != DATA || details.attributes() != attributes)) {
   3408       int field_index = details.type() == DATA ? details.field_index()
   3409                                                : new_map->NumberOfFields();
   3410       DataDescriptor d(handle(descriptors->GetKey(modify_index), isolate),
   3411                        field_index, attributes, Representation::Tagged());
   3412       descriptors->Replace(modify_index, &d);
   3413       if (details.type() != DATA) {
   3414         int unused_property_fields = new_map->unused_property_fields() - 1;
   3415         if (unused_property_fields < 0) {
   3416           unused_property_fields += JSObject::kFieldsAdded;
   3417         }
   3418         new_map->set_unused_property_fields(unused_property_fields);
   3419       }
   3420     } else {
   3421       DCHECK(details.attributes() == attributes);
   3422     }
   3423 
   3424     if (FLAG_trace_generalization) {
   3425       MaybeHandle<FieldType> field_type = FieldType::None(isolate);
   3426       if (details.type() == DATA) {
   3427         field_type = handle(
   3428             map->instance_descriptors()->GetFieldType(modify_index), isolate);
   3429       }
   3430       map->PrintGeneralization(
   3431           stdout, reason, modify_index, new_map->NumberOfOwnDescriptors(),
   3432           new_map->NumberOfOwnDescriptors(),
   3433           details.type() == DATA_CONSTANT && store_mode == FORCE_FIELD,
   3434           details.representation(), Representation::Tagged(), field_type,
   3435           MaybeHandle<Object>(), FieldType::Any(isolate),
   3436           MaybeHandle<Object>());
   3437     }
   3438   }
   3439   new_map->set_elements_kind(elements_kind);
   3440   return new_map;
   3441 }
   3442 
   3443 
   3444 void Map::DeprecateTransitionTree() {
   3445   if (is_deprecated()) return;
   3446   Object* transitions = raw_transitions();
   3447   int num_transitions = TransitionArray::NumberOfTransitions(transitions);
   3448   for (int i = 0; i < num_transitions; ++i) {
   3449     TransitionArray::GetTarget(transitions, i)->DeprecateTransitionTree();
   3450   }
   3451   deprecate();
   3452   dependent_code()->DeoptimizeDependentCodeGroup(
   3453       GetIsolate(), DependentCode::kTransitionGroup);
   3454   NotifyLeafMapLayoutChange();
   3455 }
   3456 
   3457 
   3458 static inline bool EqualImmutableValues(Object* obj1, Object* obj2) {
   3459   if (obj1 == obj2) return true;  // Valid for both kData and kAccessor kinds.
   3460   // TODO(ishell): compare AccessorPairs.
   3461   return false;
   3462 }
   3463 
   3464 
   3465 // Installs |new_descriptors| over the current instance_descriptors to ensure
   3466 // proper sharing of descriptor arrays.
   3467 void Map::ReplaceDescriptors(DescriptorArray* new_descriptors,
   3468                              LayoutDescriptor* new_layout_descriptor) {
   3469   Isolate* isolate = GetIsolate();
   3470   // Don't overwrite the empty descriptor array or initial map's descriptors.
   3471   if (NumberOfOwnDescriptors() == 0 || GetBackPointer()->IsUndefined(isolate)) {
   3472     return;
   3473   }
   3474 
   3475   DescriptorArray* to_replace = instance_descriptors();
   3476   isolate->heap()->incremental_marking()->IterateBlackObject(to_replace);
   3477   Map* current = this;
   3478   while (current->instance_descriptors() == to_replace) {
   3479     Object* next = current->GetBackPointer();
   3480     if (next->IsUndefined(isolate)) break;  // Stop overwriting at initial map.
   3481     current->SetEnumLength(kInvalidEnumCacheSentinel);
   3482     current->UpdateDescriptors(new_descriptors, new_layout_descriptor);
   3483     current = Map::cast(next);
   3484   }
   3485   set_owns_descriptors(false);
   3486 }
   3487 
   3488 
   3489 Map* Map::FindRootMap() {
   3490   Map* result = this;
   3491   Isolate* isolate = GetIsolate();
   3492   while (true) {
   3493     Object* back = result->GetBackPointer();
   3494     if (back->IsUndefined(isolate)) {
   3495       // Initial map always owns descriptors and doesn't have unused entries
   3496       // in the descriptor array.
   3497       DCHECK(result->owns_descriptors());
   3498       DCHECK_EQ(result->NumberOfOwnDescriptors(),
   3499                 result->instance_descriptors()->number_of_descriptors());
   3500       return result;
   3501     }
   3502     result = Map::cast(back);
   3503   }
   3504 }
   3505 
   3506 
   3507 Map* Map::FindLastMatchMap(int verbatim,
   3508                            int length,
   3509                            DescriptorArray* descriptors) {
   3510   DisallowHeapAllocation no_allocation;
   3511 
   3512   // This can only be called on roots of transition trees.
   3513   DCHECK_EQ(verbatim, NumberOfOwnDescriptors());
   3514 
   3515   Map* current = this;
   3516 
   3517   for (int i = verbatim; i < length; i++) {
   3518     Name* name = descriptors->GetKey(i);
   3519     PropertyDetails details = descriptors->GetDetails(i);
   3520     Map* next = TransitionArray::SearchTransition(current, details.kind(), name,
   3521                                                   details.attributes());
   3522     if (next == NULL) break;
   3523     DescriptorArray* next_descriptors = next->instance_descriptors();
   3524 
   3525     PropertyDetails next_details = next_descriptors->GetDetails(i);
   3526     DCHECK_EQ(details.kind(), next_details.kind());
   3527     DCHECK_EQ(details.attributes(), next_details.attributes());
   3528     if (details.location() != next_details.location()) break;
   3529     if (!details.representation().Equals(next_details.representation())) break;
   3530 
   3531     if (next_details.location() == kField) {
   3532       FieldType* next_field_type = next_descriptors->GetFieldType(i);
   3533       if (!descriptors->GetFieldType(i)->NowIs(next_field_type)) {
   3534         break;
   3535       }
   3536     } else {
   3537       if (!EqualImmutableValues(descriptors->GetValue(i),
   3538                                 next_descriptors->GetValue(i))) {
   3539         break;
   3540       }
   3541     }
   3542     current = next;
   3543   }
   3544   return current;
   3545 }
   3546 
   3547 
   3548 Map* Map::FindFieldOwner(int descriptor) {
   3549   DisallowHeapAllocation no_allocation;
   3550   DCHECK_EQ(DATA, instance_descriptors()->GetDetails(descriptor).type());
   3551   Map* result = this;
   3552   Isolate* isolate = GetIsolate();
   3553   while (true) {
   3554     Object* back = result->GetBackPointer();
   3555     if (back->IsUndefined(isolate)) break;
   3556     Map* parent = Map::cast(back);
   3557     if (parent->NumberOfOwnDescriptors() <= descriptor) break;
   3558     result = parent;
   3559   }
   3560   return result;
   3561 }
   3562 
   3563 
   3564 void Map::UpdateFieldType(int descriptor, Handle<Name> name,
   3565                           Representation new_representation,
   3566                           Handle<Object> new_wrapped_type) {
   3567   DCHECK(new_wrapped_type->IsSmi() || new_wrapped_type->IsWeakCell());
   3568   // We store raw pointers in the queue, so no allocations are allowed.
   3569   DisallowHeapAllocation no_allocation;
   3570   PropertyDetails details = instance_descriptors()->GetDetails(descriptor);
   3571   if (details.type() != DATA) return;
   3572 
   3573   Zone zone(GetIsolate()->allocator());
   3574   ZoneQueue<Map*> backlog(&zone);
   3575   backlog.push(this);
   3576 
   3577   while (!backlog.empty()) {
   3578     Map* current = backlog.front();
   3579     backlog.pop();
   3580 
   3581     Object* transitions = current->raw_transitions();
   3582     int num_transitions = TransitionArray::NumberOfTransitions(transitions);
   3583     for (int i = 0; i < num_transitions; ++i) {
   3584       Map* target = TransitionArray::GetTarget(transitions, i);
   3585       backlog.push(target);
   3586     }
   3587     DescriptorArray* descriptors = current->instance_descriptors();
   3588     PropertyDetails details = descriptors->GetDetails(descriptor);
   3589 
   3590     // It is allowed to change representation here only from None to something.
   3591     DCHECK(details.representation().Equals(new_representation) ||
   3592            details.representation().IsNone());
   3593 
   3594     // Skip if already updated the shared descriptor.
   3595     if (descriptors->GetValue(descriptor) != *new_wrapped_type) {
   3596       DataDescriptor d(name, descriptors->GetFieldIndex(descriptor),
   3597                        new_wrapped_type, details.attributes(),
   3598                        new_representation);
   3599       descriptors->Replace(descriptor, &d);
   3600     }
   3601   }
   3602 }
   3603 
   3604 bool FieldTypeIsCleared(Representation rep, FieldType* type) {
   3605   return type->IsNone() && rep.IsHeapObject();
   3606 }
   3607 
   3608 
   3609 // static
   3610 Handle<FieldType> Map::GeneralizeFieldType(Representation rep1,
   3611                                            Handle<FieldType> type1,
   3612                                            Representation rep2,
   3613                                            Handle<FieldType> type2,
   3614                                            Isolate* isolate) {
   3615   // Cleared field types need special treatment. They represent lost knowledge,
   3616   // so we must be conservative, so their generalization with any other type
   3617   // is "Any".
   3618   if (FieldTypeIsCleared(rep1, *type1) || FieldTypeIsCleared(rep2, *type2)) {
   3619     return FieldType::Any(isolate);
   3620   }
   3621   if (type1->NowIs(type2)) return type2;
   3622   if (type2->NowIs(type1)) return type1;
   3623   return FieldType::Any(isolate);
   3624 }
   3625 
   3626 
   3627 // static
   3628 void Map::GeneralizeFieldType(Handle<Map> map, int modify_index,
   3629                               Representation new_representation,
   3630                               Handle<FieldType> new_field_type) {
   3631   Isolate* isolate = map->GetIsolate();
   3632 
   3633   // Check if we actually need to generalize the field type at all.
   3634   Handle<DescriptorArray> old_descriptors(map->instance_descriptors(), isolate);
   3635   Representation old_representation =
   3636       old_descriptors->GetDetails(modify_index).representation();
   3637   Handle<FieldType> old_field_type(old_descriptors->GetFieldType(modify_index),
   3638                                    isolate);
   3639 
   3640   if (old_representation.Equals(new_representation) &&
   3641       !FieldTypeIsCleared(new_representation, *new_field_type) &&
   3642       // Checking old_field_type for being cleared is not necessary because
   3643       // the NowIs check below would fail anyway in that case.
   3644       new_field_type->NowIs(old_field_type)) {
   3645     DCHECK(Map::GeneralizeFieldType(old_representation, old_field_type,
   3646                                     new_representation, new_field_type, isolate)
   3647                ->NowIs(old_field_type));
   3648     return;
   3649   }
   3650 
   3651   // Determine the field owner.
   3652   Handle<Map> field_owner(map->FindFieldOwner(modify_index), isolate);
   3653   Handle<DescriptorArray> descriptors(
   3654       field_owner->instance_descriptors(), isolate);
   3655   DCHECK_EQ(*old_field_type, descriptors->GetFieldType(modify_index));
   3656 
   3657   new_field_type =
   3658       Map::GeneralizeFieldType(old_representation, old_field_type,
   3659                                new_representation, new_field_type, isolate);
   3660 
   3661   PropertyDetails details = descriptors->GetDetails(modify_index);
   3662   Handle<Name> name(descriptors->GetKey(modify_index));
   3663 
   3664   Handle<Object> wrapped_type(WrapType(new_field_type));
   3665   field_owner->UpdateFieldType(modify_index, name, new_representation,
   3666                                wrapped_type);
   3667   field_owner->dependent_code()->DeoptimizeDependentCodeGroup(
   3668       isolate, DependentCode::kFieldTypeGroup);
   3669 
   3670   if (FLAG_trace_generalization) {
   3671     map->PrintGeneralization(
   3672         stdout, "field type generalization", modify_index,
   3673         map->NumberOfOwnDescriptors(), map->NumberOfOwnDescriptors(), false,
   3674         details.representation(), details.representation(), old_field_type,
   3675         MaybeHandle<Object>(), new_field_type, MaybeHandle<Object>());
   3676   }
   3677 }
   3678 
   3679 static inline Handle<FieldType> GetFieldType(
   3680     Isolate* isolate, Handle<DescriptorArray> descriptors, int descriptor,
   3681     PropertyLocation location, Representation representation) {
   3682 #ifdef DEBUG
   3683   PropertyDetails details = descriptors->GetDetails(descriptor);
   3684   DCHECK_EQ(kData, details.kind());
   3685   DCHECK_EQ(details.location(), location);
   3686 #endif
   3687   if (location == kField) {
   3688     return handle(descriptors->GetFieldType(descriptor), isolate);
   3689   } else {
   3690     return descriptors->GetValue(descriptor)
   3691         ->OptimalType(isolate, representation);
   3692   }
   3693 }
   3694 
   3695 // Reconfigures elements kind to |new_elements_kind| and/or property at
   3696 // |modify_index| with |new_kind|, |new_attributes|, |store_mode| and/or
   3697 // |new_representation|/|new_field_type|.
   3698 // If |modify_index| is negative then no properties are reconfigured but the
   3699 // map is migrated to the up-to-date non-deprecated state.
   3700 //
   3701 // This method rewrites or completes the transition tree to reflect the new
   3702 // change. To avoid high degrees over polymorphism, and to stabilize quickly,
   3703 // on every rewrite the new type is deduced by merging the current type with
   3704 // any potential new (partial) version of the type in the transition tree.
   3705 // To do this, on each rewrite:
   3706 // - Search the root of the transition tree using FindRootMap.
   3707 // - Find/create a |root_map| with requested |new_elements_kind|.
   3708 // - Find |target_map|, the newest matching version of this map using the
   3709 //   virtually "enhanced" |old_map|'s descriptor array (i.e. whose entry at
   3710 //   |modify_index| is considered to be of |new_kind| and having
   3711 //   |new_attributes|) to walk the transition tree.
   3712 // - Merge/generalize the "enhanced" descriptor array of the |old_map| and
   3713 //   descriptor array of the |target_map|.
   3714 // - Generalize the |modify_index| descriptor using |new_representation| and
   3715 //   |new_field_type|.
   3716 // - Walk the tree again starting from the root towards |target_map|. Stop at
   3717 //   |split_map|, the first map who's descriptor array does not match the merged
   3718 //   descriptor array.
   3719 // - If |target_map| == |split_map|, |target_map| is in the expected state.
   3720 //   Return it.
   3721 // - Otherwise, invalidate the outdated transition target from |target_map|, and
   3722 //   replace its transition tree with a new branch for the updated descriptors.
   3723 Handle<Map> Map::Reconfigure(Handle<Map> old_map,
   3724                              ElementsKind new_elements_kind, int modify_index,
   3725                              PropertyKind new_kind,
   3726                              PropertyAttributes new_attributes,
   3727                              Representation new_representation,
   3728                              Handle<FieldType> new_field_type,
   3729                              StoreMode store_mode) {
   3730   DCHECK_NE(kAccessor, new_kind);  // TODO(ishell): not supported yet.
   3731   DCHECK(store_mode != FORCE_FIELD || modify_index >= 0);
   3732   Isolate* isolate = old_map->GetIsolate();
   3733 
   3734   Handle<DescriptorArray> old_descriptors(
   3735       old_map->instance_descriptors(), isolate);
   3736   int old_nof = old_map->NumberOfOwnDescriptors();
   3737 
   3738   // If it's just a representation generalization case (i.e. property kind and
   3739   // attributes stays unchanged) it's fine to transition from None to anything
   3740   // but double without any modification to the object, because the default
   3741   // uninitialized value for representation None can be overwritten by both
   3742   // smi and tagged values. Doubles, however, would require a box allocation.
   3743   if (modify_index >= 0 && !new_representation.IsNone() &&
   3744       !new_representation.IsDouble() &&
   3745       old_map->elements_kind() == new_elements_kind) {
   3746     PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
   3747     Representation old_representation = old_details.representation();
   3748 
   3749     if (old_representation.IsNone()) {
   3750       DCHECK_EQ(new_kind, old_details.kind());
   3751       DCHECK_EQ(new_attributes, old_details.attributes());
   3752       DCHECK_EQ(DATA, old_details.type());
   3753       if (FLAG_trace_generalization) {
   3754         old_map->PrintGeneralization(
   3755             stdout, "uninitialized field", modify_index,
   3756             old_map->NumberOfOwnDescriptors(),
   3757             old_map->NumberOfOwnDescriptors(), false, old_representation,
   3758             new_representation,
   3759             handle(old_descriptors->GetFieldType(modify_index), isolate),
   3760             MaybeHandle<Object>(), new_field_type, MaybeHandle<Object>());
   3761       }
   3762       Handle<Map> field_owner(old_map->FindFieldOwner(modify_index), isolate);
   3763 
   3764       GeneralizeFieldType(field_owner, modify_index, new_representation,
   3765                           new_field_type);
   3766       DCHECK(old_descriptors->GetDetails(modify_index)
   3767                  .representation()
   3768                  .Equals(new_representation));
   3769       DCHECK(
   3770           old_descriptors->GetFieldType(modify_index)->NowIs(new_field_type));
   3771       return old_map;
   3772     }
   3773   }
   3774 
   3775   // Check the state of the root map.
   3776   Handle<Map> root_map(old_map->FindRootMap(), isolate);
   3777   if (!old_map->EquivalentToForTransition(*root_map)) {
   3778     return CopyGeneralizeAllRepresentations(
   3779         old_map, new_elements_kind, modify_index, store_mode, new_kind,
   3780         new_attributes, "GenAll_NotEquivalent");
   3781   }
   3782 
   3783   ElementsKind from_kind = root_map->elements_kind();
   3784   ElementsKind to_kind = new_elements_kind;
   3785   // TODO(ishell): Add a test for SLOW_SLOPPY_ARGUMENTS_ELEMENTS.
   3786   if (from_kind != to_kind && to_kind != DICTIONARY_ELEMENTS &&
   3787       to_kind != SLOW_STRING_WRAPPER_ELEMENTS &&
   3788       to_kind != SLOW_SLOPPY_ARGUMENTS_ELEMENTS &&
   3789       !(IsTransitionableFastElementsKind(from_kind) &&
   3790         IsMoreGeneralElementsKindTransition(from_kind, to_kind))) {
   3791     return CopyGeneralizeAllRepresentations(
   3792         old_map, to_kind, modify_index, store_mode, new_kind, new_attributes,
   3793         "GenAll_InvalidElementsTransition");
   3794   }
   3795   int root_nof = root_map->NumberOfOwnDescriptors();
   3796   if (modify_index >= 0 && modify_index < root_nof) {
   3797     PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
   3798     if (old_details.kind() != new_kind ||
   3799         old_details.attributes() != new_attributes) {
   3800       return CopyGeneralizeAllRepresentations(
   3801           old_map, to_kind, modify_index, store_mode, new_kind, new_attributes,
   3802           "GenAll_RootModification1");
   3803     }
   3804     if ((old_details.type() != DATA && store_mode == FORCE_FIELD) ||
   3805         (old_details.type() == DATA &&
   3806          (!new_field_type->NowIs(old_descriptors->GetFieldType(modify_index)) ||
   3807           !new_representation.fits_into(old_details.representation())))) {
   3808       return CopyGeneralizeAllRepresentations(
   3809           old_map, to_kind, modify_index, store_mode, new_kind, new_attributes,
   3810           "GenAll_RootModification2");
   3811     }
   3812   }
   3813 
   3814   // From here on, use the map with correct elements kind as root map.
   3815   if (from_kind != to_kind) {
   3816     root_map = Map::AsElementsKind(root_map, to_kind);
   3817   }
   3818 
   3819   Handle<Map> target_map = root_map;
   3820   for (int i = root_nof; i < old_nof; ++i) {
   3821     PropertyDetails old_details = old_descriptors->GetDetails(i);
   3822     PropertyKind next_kind;
   3823     PropertyLocation next_location;
   3824     PropertyAttributes next_attributes;
   3825     Representation next_representation;
   3826     bool property_kind_reconfiguration = false;
   3827 
   3828     if (modify_index == i) {
   3829       DCHECK_EQ(FORCE_FIELD, store_mode);
   3830       property_kind_reconfiguration = old_details.kind() != new_kind;
   3831 
   3832       next_kind = new_kind;
   3833       next_location = kField;
   3834       next_attributes = new_attributes;
   3835       // If property kind is not reconfigured merge the result with
   3836       // representation/field type from the old descriptor.
   3837       next_representation = new_representation;
   3838       if (!property_kind_reconfiguration) {
   3839         next_representation =
   3840             next_representation.generalize(old_details.representation());
   3841       }
   3842 
   3843     } else {
   3844       next_kind = old_details.kind();
   3845       next_location = old_details.location();
   3846       next_attributes = old_details.attributes();
   3847       next_representation = old_details.representation();
   3848     }
   3849     Map* transition = TransitionArray::SearchTransition(
   3850         *target_map, next_kind, old_descriptors->GetKey(i), next_attributes);
   3851     if (transition == NULL) break;
   3852     Handle<Map> tmp_map(transition, isolate);
   3853 
   3854     Handle<DescriptorArray> tmp_descriptors = handle(
   3855         tmp_map->instance_descriptors(), isolate);
   3856 
   3857     // Check if target map is incompatible.
   3858     PropertyDetails tmp_details = tmp_descriptors->GetDetails(i);
   3859     DCHECK_EQ(next_kind, tmp_details.kind());
   3860     DCHECK_EQ(next_attributes, tmp_details.attributes());
   3861     if (next_kind == kAccessor &&
   3862         !EqualImmutableValues(old_descriptors->GetValue(i),
   3863                               tmp_descriptors->GetValue(i))) {
   3864       return CopyGeneralizeAllRepresentations(
   3865           old_map, to_kind, modify_index, store_mode, new_kind, new_attributes,
   3866           "GenAll_Incompatible");
   3867     }
   3868     if (next_location == kField && tmp_details.location() == kDescriptor) break;
   3869 
   3870     Representation tmp_representation = tmp_details.representation();
   3871     if (!next_representation.fits_into(tmp_representation)) break;
   3872 
   3873     PropertyLocation old_location = old_details.location();
   3874     PropertyLocation tmp_location = tmp_details.location();
   3875     if (tmp_location == kField) {
   3876       if (next_kind == kData) {
   3877         Handle<FieldType> next_field_type;
   3878         if (modify_index == i) {
   3879           next_field_type = new_field_type;
   3880           if (!property_kind_reconfiguration) {
   3881             Handle<FieldType> old_field_type =
   3882                 GetFieldType(isolate, old_descriptors, i,
   3883                              old_details.location(), tmp_representation);
   3884             Representation old_representation = old_details.representation();
   3885             next_field_type = GeneralizeFieldType(
   3886                 old_representation, old_field_type, new_representation,
   3887                 next_field_type, isolate);
   3888           }
   3889         } else {
   3890           Handle<FieldType> old_field_type =
   3891               GetFieldType(isolate, old_descriptors, i, old_details.location(),
   3892                            tmp_representation);
   3893           next_field_type = old_field_type;
   3894         }
   3895         GeneralizeFieldType(tmp_map, i, tmp_representation, next_field_type);
   3896       }
   3897     } else if (old_location == kField ||
   3898                !EqualImmutableValues(old_descriptors->GetValue(i),
   3899                                      tmp_descriptors->GetValue(i))) {
   3900       break;
   3901     }
   3902     DCHECK(!tmp_map->is_deprecated());
   3903     target_map = tmp_map;
   3904   }
   3905 
   3906   // Directly change the map if the target map is more general.
   3907   Handle<DescriptorArray> target_descriptors(
   3908       target_map->instance_descriptors(), isolate);
   3909   int target_nof = target_map->NumberOfOwnDescriptors();
   3910   if (target_nof == old_nof &&
   3911       (store_mode != FORCE_FIELD ||
   3912        (modify_index >= 0 &&
   3913         target_descriptors->GetDetails(modify_index).location() == kField))) {
   3914 #ifdef DEBUG
   3915     if (modify_index >= 0) {
   3916       PropertyDetails details = target_descriptors->GetDetails(modify_index);
   3917       DCHECK_EQ(new_kind, details.kind());
   3918       DCHECK_EQ(new_attributes, details.attributes());
   3919       DCHECK(new_representation.fits_into(details.representation()));
   3920       DCHECK(details.location() != kField ||
   3921              new_field_type->NowIs(
   3922                  target_descriptors->GetFieldType(modify_index)));
   3923     }
   3924 #endif
   3925     if (*target_map != *old_map) {
   3926       old_map->NotifyLeafMapLayoutChange();
   3927     }
   3928     return target_map;
   3929   }
   3930 
   3931   // Find the last compatible target map in the transition tree.
   3932   for (int i = target_nof; i < old_nof; ++i) {
   3933     PropertyDetails old_details = old_descriptors->GetDetails(i);
   3934     PropertyKind next_kind;
   3935     PropertyAttributes next_attributes;
   3936     if (modify_index == i) {
   3937       next_kind = new_kind;
   3938       next_attributes = new_attributes;
   3939     } else {
   3940       next_kind = old_details.kind();
   3941       next_attributes = old_details.attributes();
   3942     }
   3943     Map* transition = TransitionArray::SearchTransition(
   3944         *target_map, next_kind, old_descriptors->GetKey(i), next_attributes);
   3945     if (transition == NULL) break;
   3946     Handle<Map> tmp_map(transition, isolate);
   3947     Handle<DescriptorArray> tmp_descriptors(
   3948         tmp_map->instance_descriptors(), isolate);
   3949 
   3950     // Check if target map is compatible.
   3951 #ifdef DEBUG
   3952     PropertyDetails tmp_details = tmp_descriptors->GetDetails(i);
   3953     DCHECK_EQ(next_kind, tmp_details.kind());
   3954     DCHECK_EQ(next_attributes, tmp_details.attributes());
   3955 #endif
   3956     if (next_kind == kAccessor &&
   3957         !EqualImmutableValues(old_descriptors->GetValue(i),
   3958                               tmp_descriptors->GetValue(i))) {
   3959       return CopyGeneralizeAllRepresentations(
   3960           old_map, to_kind, modify_index, store_mode, new_kind, new_attributes,
   3961           "GenAll_Incompatible");
   3962     }
   3963     DCHECK(!tmp_map->is_deprecated());
   3964     target_map = tmp_map;
   3965   }
   3966   target_nof = target_map->NumberOfOwnDescriptors();
   3967   target_descriptors = handle(target_map->instance_descriptors(), isolate);
   3968 
   3969   // Allocate a new descriptor array large enough to hold the required
   3970   // descriptors, with minimally the exact same size as the old descriptor
   3971   // array.
   3972   int new_slack = Max(
   3973       old_nof, old_descriptors->number_of_descriptors()) - old_nof;
   3974   Handle<DescriptorArray> new_descriptors = DescriptorArray::Allocate(
   3975       isolate, old_nof, new_slack);
   3976   DCHECK(new_descriptors->length() > target_descriptors->length() ||
   3977          new_descriptors->NumberOfSlackDescriptors() > 0 ||
   3978          new_descriptors->number_of_descriptors() ==
   3979          old_descriptors->number_of_descriptors());
   3980   DCHECK(new_descriptors->number_of_descriptors() == old_nof);
   3981 
   3982   // 0 -> |root_nof|
   3983   int current_offset = 0;
   3984   for (int i = 0; i < root_nof; ++i) {
   3985     PropertyDetails old_details = old_descriptors->GetDetails(i);
   3986     if (old_details.location() == kField) {
   3987       current_offset += old_details.field_width_in_words();
   3988     }
   3989     Descriptor d(handle(old_descriptors->GetKey(i), isolate),
   3990                  handle(old_descriptors->GetValue(i), isolate),
   3991                  old_details);
   3992     new_descriptors->Set(i, &d);
   3993   }
   3994 
   3995   // |root_nof| -> |target_nof|
   3996   for (int i = root_nof; i < target_nof; ++i) {
   3997     Handle<Name> target_key(target_descriptors->GetKey(i), isolate);
   3998     PropertyDetails old_details = old_descriptors->GetDetails(i);
   3999     PropertyDetails target_details = target_descriptors->GetDetails(i);
   4000 
   4001     PropertyKind next_kind;
   4002     PropertyAttributes next_attributes;
   4003     PropertyLocation next_location;
   4004     Representation next_representation;
   4005     bool property_kind_reconfiguration = false;
   4006 
   4007     if (modify_index == i) {
   4008       DCHECK_EQ(FORCE_FIELD, store_mode);
   4009       property_kind_reconfiguration = old_details.kind() != new_kind;
   4010 
   4011       next_kind = new_kind;
   4012       next_attributes = new_attributes;
   4013       next_location = kField;
   4014 
   4015       // Merge new representation/field type with ones from the target
   4016       // descriptor. If property kind is not reconfigured merge the result with
   4017       // representation/field type from the old descriptor.
   4018       next_representation =
   4019           new_representation.generalize(target_details.representation());
   4020       if (!property_kind_reconfiguration) {
   4021         next_representation =
   4022             next_representation.generalize(old_details.representation());
   4023       }
   4024     } else {
   4025       // Merge old_descriptor and target_descriptor entries.
   4026       DCHECK_EQ(target_details.kind(), old_details.kind());
   4027       next_kind = target_details.kind();
   4028       next_attributes = target_details.attributes();
   4029       next_location =
   4030           old_details.location() == kField ||
   4031                   target_details.location() == kField ||
   4032                   !EqualImmutableValues(target_descriptors->GetValue(i),
   4033                                         old_descriptors->GetValue(i))
   4034               ? kField
   4035               : kDescriptor;
   4036 
   4037       next_representation = old_details.representation().generalize(
   4038           target_details.representation());
   4039     }
   4040     DCHECK_EQ(next_kind, target_details.kind());
   4041     DCHECK_EQ(next_attributes, target_details.attributes());
   4042 
   4043     if (next_location == kField) {
   4044       if (next_kind == kData) {
   4045         Handle<FieldType> target_field_type =
   4046             GetFieldType(isolate, target_descriptors, i,
   4047                          target_details.location(), next_representation);
   4048 
   4049         Handle<FieldType> next_field_type;
   4050         if (modify_index == i) {
   4051           next_field_type = GeneralizeFieldType(
   4052               target_details.representation(), target_field_type,
   4053               new_representation, new_field_type, isolate);
   4054           if (!property_kind_reconfiguration) {
   4055             Handle<FieldType> old_field_type =
   4056                 GetFieldType(isolate, old_descriptors, i,
   4057                              old_details.location(), next_representation);
   4058             next_field_type = GeneralizeFieldType(
   4059                 old_details.representation(), old_field_type,
   4060                 next_representation, next_field_type, isolate);
   4061           }
   4062         } else {
   4063           Handle<FieldType> old_field_type =
   4064               GetFieldType(isolate, old_descriptors, i, old_details.location(),
   4065                            next_representation);
   4066           next_field_type = GeneralizeFieldType(
   4067               old_details.representation(), old_field_type, next_representation,
   4068               target_field_type, isolate);
   4069         }
   4070         Handle<Object> wrapped_type(WrapType(next_field_type));
   4071         DataDescriptor d(target_key, current_offset, wrapped_type,
   4072                          next_attributes, next_representation);
   4073         current_offset += d.GetDetails().field_width_in_words();
   4074         new_descriptors->Set(i, &d);
   4075       } else {
   4076         UNIMPLEMENTED();  // TODO(ishell): implement.
   4077       }
   4078     } else {
   4079       PropertyDetails details(next_attributes, next_kind, next_location,
   4080                               next_representation);
   4081       Descriptor d(target_key, handle(target_descriptors->GetValue(i), isolate),
   4082                    details);
   4083       new_descriptors->Set(i, &d);
   4084     }
   4085   }
   4086 
   4087   // |target_nof| -> |old_nof|
   4088   for (int i = target_nof; i < old_nof; ++i) {
   4089     PropertyDetails old_details = old_descriptors->GetDetails(i);
   4090     Handle<Name> old_key(old_descriptors->GetKey(i), isolate);
   4091 
   4092     // Merge old_descriptor entry and modified details together.
   4093     PropertyKind next_kind;
   4094     PropertyAttributes next_attributes;
   4095     PropertyLocation next_location;
   4096     Representation next_representation;
   4097     bool property_kind_reconfiguration = false;
   4098 
   4099     if (modify_index == i) {
   4100       DCHECK_EQ(FORCE_FIELD, store_mode);
   4101       // In case of property kind reconfiguration it is not necessary to
   4102       // take into account representation/field type of the old descriptor.
   4103       property_kind_reconfiguration = old_details.kind() != new_kind;
   4104 
   4105       next_kind = new_kind;
   4106       next_attributes = new_attributes;
   4107       next_location = kField;
   4108       next_representation = new_representation;
   4109       if (!property_kind_reconfiguration) {
   4110         next_representation =
   4111             next_representation.generalize(old_details.representation());
   4112       }
   4113     } else {
   4114       next_kind = old_details.kind();
   4115       next_attributes = old_details.attributes();
   4116       next_location = old_details.location();
   4117       next_representation = old_details.representation();
   4118     }
   4119 
   4120     if (next_location == kField) {
   4121       if (next_kind == kData) {
   4122         Handle<FieldType> next_field_type;
   4123         if (modify_index == i) {
   4124           next_field_type = new_field_type;
   4125           if (!property_kind_reconfiguration) {
   4126             Handle<FieldType> old_field_type =
   4127                 GetFieldType(isolate, old_descriptors, i,
   4128                              old_details.location(), next_representation);
   4129             next_field_type = GeneralizeFieldType(
   4130                 old_details.representation(), old_field_type,
   4131                 next_representation, next_field_type, isolate);
   4132           }
   4133         } else {
   4134           Handle<FieldType> old_field_type =
   4135               GetFieldType(isolate, old_descriptors, i, old_details.location(),
   4136                            next_representation);
   4137           next_field_type = old_field_type;
   4138         }
   4139 
   4140         Handle<Object> wrapped_type(WrapType(next_field_type));
   4141 
   4142         DataDescriptor d(old_key, current_offset, wrapped_type, next_attributes,
   4143                          next_representation);
   4144         current_offset += d.GetDetails().field_width_in_words();
   4145         new_descriptors->Set(i, &d);
   4146       } else {
   4147         UNIMPLEMENTED();  // TODO(ishell): implement.
   4148       }
   4149     } else {
   4150       PropertyDetails details(next_attributes, next_kind, next_location,
   4151                               next_representation);
   4152       Descriptor d(old_key, handle(old_descriptors->GetValue(i), isolate),
   4153                    details);
   4154       new_descriptors->Set(i, &d);
   4155     }
   4156   }
   4157 
   4158   new_descriptors->Sort();
   4159 
   4160   DCHECK(store_mode != FORCE_FIELD ||
   4161          new_descriptors->GetDetails(modify_index).location() == kField);
   4162 
   4163   Handle<Map> split_map(root_map->FindLastMatchMap(
   4164           root_nof, old_nof, *new_descriptors), isolate);
   4165   int split_nof = split_map->NumberOfOwnDescriptors();
   4166   DCHECK_NE(old_nof, split_nof);
   4167 
   4168   PropertyKind split_kind;
   4169   PropertyAttributes split_attributes;
   4170   if (modify_index == split_nof) {
   4171     split_kind = new_kind;
   4172     split_attributes = new_attributes;
   4173   } else {
   4174     PropertyDetails split_prop_details = old_descriptors->GetDetails(split_nof);
   4175     split_kind = split_prop_details.kind();
   4176     split_attributes = split_prop_details.attributes();
   4177   }
   4178 
   4179   // Invalidate a transition target at |key|.
   4180   Map* maybe_transition = TransitionArray::SearchTransition(
   4181       *split_map, split_kind, old_descriptors->GetKey(split_nof),
   4182       split_attributes);
   4183   if (maybe_transition != NULL) {
   4184     maybe_transition->DeprecateTransitionTree();
   4185   }
   4186 
   4187   // If |maybe_transition| is not NULL then the transition array already
   4188   // contains entry for given descriptor. This means that the transition
   4189   // could be inserted regardless of whether transitions array is full or not.
   4190   if (maybe_transition == NULL &&
   4191       !TransitionArray::CanHaveMoreTransitions(split_map)) {
   4192     return CopyGeneralizeAllRepresentations(
   4193         old_map, to_kind, modify_index, store_mode, new_kind, new_attributes,
   4194         "GenAll_CantHaveMoreTransitions");
   4195   }
   4196 
   4197   old_map->NotifyLeafMapLayoutChange();
   4198 
   4199   if (FLAG_trace_generalization && modify_index >= 0) {
   4200     PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
   4201     PropertyDetails new_details = new_descriptors->GetDetails(modify_index);
   4202     MaybeHandle<FieldType> old_field_type;
   4203     MaybeHandle<FieldType> new_field_type;
   4204     MaybeHandle<Object> old_value;
   4205     MaybeHandle<Object> new_value;
   4206     if (old_details.type() == DATA) {
   4207       old_field_type =
   4208           handle(old_descriptors->GetFieldType(modify_index), isolate);
   4209     } else {
   4210       old_value = handle(old_descriptors->GetValue(modify_index), isolate);
   4211     }
   4212     if (new_details.type() == DATA) {
   4213       new_field_type =
   4214           handle(new_descriptors->GetFieldType(modify_index), isolate);
   4215     } else {
   4216       new_value = handle(new_descriptors->GetValue(modify_index), isolate);
   4217     }
   4218 
   4219     old_map->PrintGeneralization(
   4220         stdout, "", modify_index, split_nof, old_nof,
   4221         old_details.location() == kDescriptor && store_mode == FORCE_FIELD,
   4222         old_details.representation(), new_details.representation(),
   4223         old_field_type, old_value, new_field_type, new_value);
   4224   }
   4225 
   4226   Handle<LayoutDescriptor> new_layout_descriptor =
   4227       LayoutDescriptor::New(split_map, new_descriptors, old_nof);
   4228 
   4229   Handle<Map> new_map =
   4230       AddMissingTransitions(split_map, new_descriptors, new_layout_descriptor);
   4231 
   4232   // Deprecated part of the transition tree is no longer reachable, so replace
   4233   // current instance descriptors in the "survived" part of the tree with
   4234   // the new descriptors to maintain descriptors sharing invariant.
   4235   split_map->ReplaceDescriptors(*new_descriptors, *new_layout_descriptor);
   4236   return new_map;
   4237 }
   4238 
   4239 
   4240 // Generalize the representation of all DATA descriptors.
   4241 Handle<Map> Map::GeneralizeAllFieldRepresentations(
   4242     Handle<Map> map) {
   4243   Handle<DescriptorArray> descriptors(map->instance_descriptors());
   4244   for (int i = 0; i < map->NumberOfOwnDescriptors(); ++i) {
   4245     PropertyDetails details = descriptors->GetDetails(i);
   4246     if (details.type() == DATA) {
   4247       map = ReconfigureProperty(map, i, kData, details.attributes(),
   4248                                 Representation::Tagged(),
   4249                                 FieldType::Any(map->GetIsolate()), FORCE_FIELD);
   4250     }
   4251   }
   4252   return map;
   4253 }
   4254 
   4255 
   4256 // static
   4257 MaybeHandle<Map> Map::TryUpdate(Handle<Map> old_map) {
   4258   DisallowHeapAllocation no_allocation;
   4259   DisallowDeoptimization no_deoptimization(old_map->GetIsolate());
   4260 
   4261   if (!old_map->is_deprecated()) return old_map;
   4262 
   4263   // Check the state of the root map.
   4264   Map* root_map = old_map->FindRootMap();
   4265   if (!old_map->EquivalentToForTransition(root_map)) return MaybeHandle<Map>();
   4266 
   4267   ElementsKind from_kind = root_map->elements_kind();
   4268   ElementsKind to_kind = old_map->elements_kind();
   4269   if (from_kind != to_kind) {
   4270     // Try to follow existing elements kind transitions.
   4271     root_map = root_map->LookupElementsTransitionMap(to_kind);
   4272     if (root_map == NULL) return MaybeHandle<Map>();
   4273     // From here on, use the map with correct elements kind as root map.
   4274   }
   4275   Map* new_map = root_map->TryReplayPropertyTransitions(*old_map);
   4276   if (new_map == nullptr) return MaybeHandle<Map>();
   4277   return handle(new_map);
   4278 }
   4279 
   4280 Map* Map::TryReplayPropertyTransitions(Map* old_map) {
   4281   DisallowHeapAllocation no_allocation;
   4282   DisallowDeoptimization no_deoptimization(GetIsolate());
   4283 
   4284   int root_nof = NumberOfOwnDescriptors();
   4285 
   4286   int old_nof = old_map->NumberOfOwnDescriptors();
   4287   DescriptorArray* old_descriptors = old_map->instance_descriptors();
   4288 
   4289   Map* new_map = this;
   4290   for (int i = root_nof; i < old_nof; ++i) {
   4291     PropertyDetails old_details = old_descriptors->GetDetails(i);
   4292     Map* transition = TransitionArray::SearchTransition(
   4293         new_map, old_details.kind(), old_descriptors->GetKey(i),
   4294         old_details.attributes());
   4295     if (transition == NULL) return nullptr;
   4296     new_map = transition;
   4297     DescriptorArray* new_descriptors = new_map->instance_descriptors();
   4298 
   4299     PropertyDetails new_details = new_descriptors->GetDetails(i);
   4300     DCHECK_EQ(old_details.kind(), new_details.kind());
   4301     DCHECK_EQ(old_details.attributes(), new_details.attributes());
   4302     if (!old_details.representation().fits_into(new_details.representation())) {
   4303       return nullptr;
   4304     }
   4305     switch (new_details.type()) {
   4306       case DATA: {
   4307         FieldType* new_type = new_descriptors->GetFieldType(i);
   4308         // Cleared field types need special treatment. They represent lost
   4309         // knowledge, so we must first generalize the new_type to "Any".
   4310         if (FieldTypeIsCleared(new_details.representation(), new_type)) {
   4311           return nullptr;
   4312         }
   4313         PropertyType old_property_type = old_details.type();
   4314         if (old_property_type == DATA) {
   4315           FieldType* old_type = old_descriptors->GetFieldType(i);
   4316           if (FieldTypeIsCleared(old_details.representation(), old_type) ||
   4317               !old_type->NowIs(new_type)) {
   4318             return nullptr;
   4319           }
   4320         } else {
   4321           DCHECK(old_property_type == DATA_CONSTANT);
   4322           Object* old_value = old_descriptors->GetValue(i);
   4323           if (!new_type->NowContains(old_value)) {
   4324             return nullptr;
   4325           }
   4326         }
   4327         break;
   4328       }
   4329       case ACCESSOR: {
   4330 #ifdef DEBUG
   4331         FieldType* new_type = new_descriptors->GetFieldType(i);
   4332         DCHECK(new_type->IsAny());
   4333 #endif
   4334         break;
   4335       }
   4336 
   4337       case DATA_CONSTANT:
   4338       case ACCESSOR_CONSTANT: {
   4339         Object* old_value = old_descriptors->GetValue(i);
   4340         Object* new_value = new_descriptors->GetValue(i);
   4341         if (old_details.location() == kField || old_value != new_value) {
   4342           return nullptr;
   4343         }
   4344         break;
   4345       }
   4346     }
   4347   }
   4348   if (new_map->NumberOfOwnDescriptors() != old_nof) return nullptr;
   4349   return new_map;
   4350 }
   4351 
   4352 
   4353 // static
   4354 Handle<Map> Map::Update(Handle<Map> map) {
   4355   if (!map->is_deprecated()) return map;
   4356   return ReconfigureProperty(map, -1, kData, NONE, Representation::None(),
   4357                              FieldType::None(map->GetIsolate()),
   4358                              ALLOW_IN_DESCRIPTOR);
   4359 }
   4360 
   4361 Maybe<bool> JSObject::SetPropertyWithInterceptor(LookupIterator* it,
   4362                                                  ShouldThrow should_throw,
   4363                                                  Handle<Object> value) {
   4364   DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
   4365   return SetPropertyWithInterceptorInternal(it, it->GetInterceptor(),
   4366                                             should_throw, value);
   4367 }
   4368 
   4369 MaybeHandle<Object> Object::SetProperty(Handle<Object> object,
   4370                                         Handle<Name> name, Handle<Object> value,
   4371                                         LanguageMode language_mode,
   4372                                         StoreFromKeyed store_mode) {
   4373   LookupIterator it(object, name);
   4374   MAYBE_RETURN_NULL(SetProperty(&it, value, language_mode, store_mode));
   4375   return value;
   4376 }
   4377 
   4378 
   4379 Maybe<bool> Object::SetPropertyInternal(LookupIterator* it,
   4380                                         Handle<Object> value,
   4381                                         LanguageMode language_mode,
   4382                                         StoreFromKeyed store_mode,
   4383                                         bool* found) {
   4384   it->UpdateProtector();
   4385   DCHECK(it->IsFound());
   4386   ShouldThrow should_throw =
   4387       is_sloppy(language_mode) ? DONT_THROW : THROW_ON_ERROR;
   4388 
   4389   // Make sure that the top context does not change when doing callbacks or
   4390   // interceptor calls.
   4391   AssertNoContextChange ncc(it->isolate());
   4392 
   4393   do {
   4394     switch (it->state()) {
   4395       case LookupIterator::NOT_FOUND:
   4396         UNREACHABLE();
   4397 
   4398       case LookupIterator::ACCESS_CHECK:
   4399         if (it->HasAccess()) break;
   4400         // Check whether it makes sense to reuse the lookup iterator. Here it
   4401         // might still call into setters up the prototype chain.
   4402         return JSObject::SetPropertyWithFailedAccessCheck(it, value,
   4403                                                           should_throw);
   4404 
   4405       case LookupIterator::JSPROXY:
   4406         return JSProxy::SetProperty(it->GetHolder<JSProxy>(), it->GetName(),
   4407                                     value, it->GetReceiver(), language_mode);
   4408 
   4409       case LookupIterator::INTERCEPTOR: {
   4410         Handle<Map> store_target_map;
   4411         if (it->GetReceiver()->IsJSObject()) {
   4412           store_target_map = handle(it->GetStoreTarget()->map(), it->isolate());
   4413         }
   4414         if (it->HolderIsReceiverOrHiddenPrototype()) {
   4415           Maybe<bool> result =
   4416               JSObject::SetPropertyWithInterceptor(it, should_throw, value);
   4417           if (result.IsNothing() || result.FromJust()) return result;
   4418           // Interceptor modified the store target but failed to set the
   4419           // property.
   4420           Utils::ApiCheck(store_target_map.is_null() ||
   4421                               *store_target_map == it->GetStoreTarget()->map(),
   4422                           it->IsElement() ? "v8::IndexedPropertySetterCallback"
   4423                                           : "v8::NamedPropertySetterCallback",
   4424                           "Interceptor silently changed store target.");
   4425         } else {
   4426           Maybe<PropertyAttributes> maybe_attributes =
   4427               JSObject::GetPropertyAttributesWithInterceptor(it);
   4428           if (!maybe_attributes.IsJust()) return Nothing<bool>();
   4429           if ((maybe_attributes.FromJust() & READ_ONLY) != 0) {
   4430             return WriteToReadOnlyProperty(it, value, should_throw);
   4431           }
   4432           // Interceptor modified the store target but failed to set the
   4433           // property.
   4434           Utils::ApiCheck(store_target_map.is_null() ||
   4435                               *store_target_map == it->GetStoreTarget()->map(),
   4436                           it->IsElement() ? "v8::IndexedPropertySetterCallback"
   4437                                           : "v8::NamedPropertySetterCallback",
   4438                           "Interceptor silently changed store target.");
   4439           if (maybe_attributes.FromJust() == ABSENT) break;
   4440           *found = false;
   4441           return Nothing<bool>();
   4442         }
   4443         break;
   4444       }
   4445 
   4446       case LookupIterator::ACCESSOR: {
   4447         if (it->IsReadOnly()) {
   4448           return WriteToReadOnlyProperty(it, value, should_throw);
   4449         }
   4450         Handle<Object> accessors = it->GetAccessors();
   4451         if (accessors->IsAccessorInfo() &&
   4452             !it->HolderIsReceiverOrHiddenPrototype() &&
   4453             AccessorInfo::cast(*accessors)->is_special_data_property()) {
   4454           *found = false;
   4455           return Nothing<bool>();
   4456         }
   4457         return SetPropertyWithAccessor(it, value, should_throw);
   4458       }
   4459       case LookupIterator::INTEGER_INDEXED_EXOTIC:
   4460         // TODO(verwaest): We should throw an exception if holder is receiver.
   4461         return Just(true);
   4462 
   4463       case LookupIterator::DATA:
   4464         if (it->IsReadOnly()) {
   4465           return WriteToReadOnlyProperty(it, value, should_throw);
   4466         }
   4467         if (it->HolderIsReceiverOrHiddenPrototype()) {
   4468           return SetDataProperty(it, value);
   4469         }
   4470       // Fall through.
   4471       case LookupIterator::TRANSITION:
   4472         *found = false;
   4473         return Nothing<bool>();
   4474     }
   4475     it->Next();
   4476   } while (it->IsFound());
   4477 
   4478   *found = false;
   4479   return Nothing<bool>();
   4480 }
   4481 
   4482 
   4483 Maybe<bool> Object::SetProperty(LookupIterator* it, Handle<Object> value,
   4484                                 LanguageMode language_mode,
   4485                                 StoreFromKeyed store_mode) {
   4486   if (it->IsFound()) {
   4487     bool found = true;
   4488     Maybe<bool> result =
   4489         SetPropertyInternal(it, value, language_mode, store_mode, &found);
   4490     if (found) return result;
   4491   }
   4492 
   4493   // If the receiver is the JSGlobalObject, the store was contextual. In case
   4494   // the property did not exist yet on the global object itself, we have to
   4495   // throw a reference error in strict mode.  In sloppy mode, we continue.
   4496   if (is_strict(language_mode) && it->GetReceiver()->IsJSGlobalObject()) {
   4497     it->isolate()->Throw(*it->isolate()->factory()->NewReferenceError(
   4498         MessageTemplate::kNotDefined, it->name()));
   4499     return Nothing<bool>();
   4500   }
   4501 
   4502   ShouldThrow should_throw =
   4503       is_sloppy(language_mode) ? DONT_THROW : THROW_ON_ERROR;
   4504   return AddDataProperty(it, value, NONE, should_throw, store_mode);
   4505 }
   4506 
   4507 
   4508 Maybe<bool> Object::SetSuperProperty(LookupIterator* it, Handle<Object> value,
   4509                                      LanguageMode language_mode,
   4510                                      StoreFromKeyed store_mode) {
   4511   Isolate* isolate = it->isolate();
   4512 
   4513   if (it->IsFound()) {
   4514     bool found = true;
   4515     Maybe<bool> result =
   4516         SetPropertyInternal(it, value, language_mode, store_mode, &found);
   4517     if (found) return result;
   4518   }
   4519 
   4520   it->UpdateProtector();
   4521 
   4522   // The property either doesn't exist on the holder or exists there as a data
   4523   // property.
   4524 
   4525   ShouldThrow should_throw =
   4526       is_sloppy(language_mode) ? DONT_THROW : THROW_ON_ERROR;
   4527 
   4528   if (!it->GetReceiver()->IsJSReceiver()) {
   4529     return WriteToReadOnlyProperty(it, value, should_throw);
   4530   }
   4531   Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(it->GetReceiver());
   4532 
   4533   LookupIterator::Configuration c = LookupIterator::OWN;
   4534   LookupIterator own_lookup =
   4535       it->IsElement() ? LookupIterator(isolate, receiver, it->index(), c)
   4536                       : LookupIterator(receiver, it->name(), c);
   4537 
   4538   for (; own_lookup.IsFound(); own_lookup.Next()) {
   4539     switch (own_lookup.state()) {
   4540       case LookupIterator::ACCESS_CHECK:
   4541         if (!own_lookup.HasAccess()) {
   4542           return JSObject::SetPropertyWithFailedAccessCheck(&own_lookup, value,
   4543                                                             should_throw);
   4544         }
   4545         break;
   4546 
   4547       case LookupIterator::ACCESSOR:
   4548         if (own_lookup.GetAccessors()->IsAccessorInfo()) {
   4549           if (own_lookup.IsReadOnly()) {
   4550             return WriteToReadOnlyProperty(&own_lookup, value, should_throw);
   4551           }
   4552           return JSObject::SetPropertyWithAccessor(&own_lookup, value,
   4553                                                    should_throw);
   4554         }
   4555       // Fall through.
   4556       case LookupIterator::INTEGER_INDEXED_EXOTIC:
   4557         return RedefineIncompatibleProperty(isolate, it->GetName(), value,
   4558                                             should_throw);
   4559 
   4560       case LookupIterator::DATA: {
   4561         if (own_lookup.IsReadOnly()) {
   4562           return WriteToReadOnlyProperty(&own_lookup, value, should_throw);
   4563         }
   4564         return SetDataProperty(&own_lookup, value);
   4565       }
   4566 
   4567       case LookupIterator::INTERCEPTOR:
   4568       case LookupIterator::JSPROXY: {
   4569         PropertyDescriptor desc;
   4570         Maybe<bool> owned =
   4571             JSReceiver::GetOwnPropertyDescriptor(&own_lookup, &desc);
   4572         MAYBE_RETURN(owned, Nothing<bool>());
   4573         if (!owned.FromJust()) {
   4574           return JSReceiver::CreateDataProperty(&own_lookup, value,
   4575                                                 should_throw);
   4576         }
   4577         if (PropertyDescriptor::IsAccessorDescriptor(&desc) ||
   4578             !desc.writable()) {
   4579           return RedefineIncompatibleProperty(isolate, it->GetName(), value,
   4580                                               should_throw);
   4581         }
   4582 
   4583         PropertyDescriptor value_desc;
   4584         value_desc.set_value(value);
   4585         return JSReceiver::DefineOwnProperty(isolate, receiver, it->GetName(),
   4586                                              &value_desc, should_throw);
   4587       }
   4588 
   4589       case LookupIterator::NOT_FOUND:
   4590       case LookupIterator::TRANSITION:
   4591         UNREACHABLE();
   4592     }
   4593   }
   4594 
   4595   return AddDataProperty(&own_lookup, value, NONE, should_throw, store_mode);
   4596 }
   4597 
   4598 MaybeHandle<Object> Object::ReadAbsentProperty(LookupIterator* it) {
   4599   return it->isolate()->factory()->undefined_value();
   4600 }
   4601 
   4602 MaybeHandle<Object> Object::ReadAbsentProperty(Isolate* isolate,
   4603                                                Handle<Object> receiver,
   4604                                                Handle<Object> name) {
   4605   return isolate->factory()->undefined_value();
   4606 }
   4607 
   4608 
   4609 Maybe<bool> Object::CannotCreateProperty(Isolate* isolate,
   4610                                          Handle<Object> receiver,
   4611                                          Handle<Object> name,
   4612                                          Handle<Object> value,
   4613                                          ShouldThrow should_throw) {
   4614   RETURN_FAILURE(
   4615       isolate, should_throw,
   4616       NewTypeError(MessageTemplate::kStrictCannotCreateProperty, name,
   4617                    Object::TypeOf(isolate, receiver), receiver));
   4618 }
   4619 
   4620 
   4621 Maybe<bool> Object::WriteToReadOnlyProperty(LookupIterator* it,
   4622                                             Handle<Object> value,
   4623                                             ShouldThrow should_throw) {
   4624   return WriteToReadOnlyProperty(it->isolate(), it->GetReceiver(),
   4625                                  it->GetName(), value, should_throw);
   4626 }
   4627 
   4628 
   4629 Maybe<bool> Object::WriteToReadOnlyProperty(Isolate* isolate,
   4630                                             Handle<Object> receiver,
   4631                                             Handle<Object> name,
   4632                                             Handle<Object> value,
   4633                                             ShouldThrow should_throw) {
   4634   RETURN_FAILURE(isolate, should_throw,
   4635                  NewTypeError(MessageTemplate::kStrictReadOnlyProperty, name,
   4636                               Object::TypeOf(isolate, receiver), receiver));
   4637 }
   4638 
   4639 
   4640 Maybe<bool> Object::RedefineIncompatibleProperty(Isolate* isolate,
   4641                                                  Handle<Object> name,
   4642                                                  Handle<Object> value,
   4643                                                  ShouldThrow should_throw) {
   4644   RETURN_FAILURE(isolate, should_throw,
   4645                  NewTypeError(MessageTemplate::kRedefineDisallowed, name));
   4646 }
   4647 
   4648 
   4649 Maybe<bool> Object::SetDataProperty(LookupIterator* it, Handle<Object> value) {
   4650   // Proxies are handled elsewhere. Other non-JSObjects cannot have own
   4651   // properties.
   4652   Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver());
   4653 
   4654   // Store on the holder which may be hidden behind the receiver.
   4655   DCHECK(it->HolderIsReceiverOrHiddenPrototype());
   4656 
   4657   Handle<Object> to_assign = value;
   4658   // Convert the incoming value to a number for storing into typed arrays.
   4659   if (it->IsElement() && receiver->HasFixedTypedArrayElements()) {
   4660     if (!value->IsNumber() && !value->IsUndefined(it->isolate())) {
   4661       ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   4662           it->isolate(), to_assign, Object::ToNumber(value), Nothing<bool>());
   4663       // We have to recheck the length. However, it can only change if the
   4664       // underlying buffer was neutered, so just check that.
   4665       if (Handle<JSArrayBufferView>::cast(receiver)->WasNeutered()) {
   4666         return Just(true);
   4667         // TODO(neis): According to the spec, this should throw a TypeError.
   4668       }
   4669     }
   4670   }
   4671 
   4672   // Possibly migrate to the most up-to-date map that will be able to store
   4673   // |value| under it->name().
   4674   it->PrepareForDataProperty(to_assign);
   4675 
   4676   // Write the property value.
   4677   it->WriteDataValue(to_assign);
   4678 
   4679 #if VERIFY_HEAP
   4680   if (FLAG_verify_heap) {
   4681     receiver->JSObjectVerify();
   4682   }
   4683 #endif
   4684   return Just(true);
   4685 }
   4686 
   4687 
   4688 Maybe<bool> Object::AddDataProperty(LookupIterator* it, Handle<Object> value,
   4689                                     PropertyAttributes attributes,
   4690                                     ShouldThrow should_throw,
   4691                                     StoreFromKeyed store_mode) {
   4692   if (!it->GetReceiver()->IsJSObject()) {
   4693     if (it->GetReceiver()->IsJSProxy() && it->GetName()->IsPrivate()) {
   4694       RETURN_FAILURE(it->isolate(), should_throw,
   4695                      NewTypeError(MessageTemplate::kProxyPrivate));
   4696     }
   4697     return CannotCreateProperty(it->isolate(), it->GetReceiver(), it->GetName(),
   4698                                 value, should_throw);
   4699   }
   4700 
   4701   DCHECK_NE(LookupIterator::INTEGER_INDEXED_EXOTIC, it->state());
   4702 
   4703   Handle<JSObject> receiver = it->GetStoreTarget();
   4704 
   4705   // If the receiver is a JSGlobalProxy, store on the prototype (JSGlobalObject)
   4706   // instead. If the prototype is Null, the proxy is detached.
   4707   if (receiver->IsJSGlobalProxy()) return Just(true);
   4708 
   4709   Isolate* isolate = it->isolate();
   4710 
   4711   if (it->ExtendingNonExtensible(receiver)) {
   4712     RETURN_FAILURE(
   4713         isolate, should_throw,
   4714         NewTypeError(MessageTemplate::kObjectNotExtensible, it->GetName()));
   4715   }
   4716 
   4717   if (it->IsElement()) {
   4718     if (receiver->IsJSArray()) {
   4719       Handle<JSArray> array = Handle<JSArray>::cast(receiver);
   4720       if (JSArray::WouldChangeReadOnlyLength(array, it->index())) {
   4721         RETURN_FAILURE(array->GetIsolate(), should_throw,
   4722                        NewTypeError(MessageTemplate::kStrictReadOnlyProperty,
   4723                                     isolate->factory()->length_string(),
   4724                                     Object::TypeOf(isolate, array), array));
   4725       }
   4726 
   4727       if (FLAG_trace_external_array_abuse &&
   4728           array->HasFixedTypedArrayElements()) {
   4729         CheckArrayAbuse(array, "typed elements write", it->index(), true);
   4730       }
   4731 
   4732       if (FLAG_trace_js_array_abuse && !array->HasFixedTypedArrayElements()) {
   4733         CheckArrayAbuse(array, "elements write", it->index(), false);
   4734       }
   4735     }
   4736 
   4737     Maybe<bool> result = JSObject::AddDataElement(receiver, it->index(), value,
   4738                                                   attributes, should_throw);
   4739     JSObject::ValidateElements(receiver);
   4740     return result;
   4741   } else {
   4742     it->UpdateProtector();
   4743     // Migrate to the most up-to-date map that will be able to store |value|
   4744     // under it->name() with |attributes|.
   4745     it->PrepareTransitionToDataProperty(receiver, value, attributes,
   4746                                         store_mode);
   4747     DCHECK_EQ(LookupIterator::TRANSITION, it->state());
   4748     it->ApplyTransitionToDataProperty(receiver);
   4749 
   4750     // TODO(verwaest): Encapsulate dictionary handling better.
   4751     if (receiver->map()->is_dictionary_map()) {
   4752       // TODO(dcarney): just populate TransitionPropertyCell here?
   4753       JSObject::AddSlowProperty(receiver, it->name(), value, attributes);
   4754     } else {
   4755       // Write the property value.
   4756       it->WriteDataValue(value);
   4757     }
   4758 
   4759 #if VERIFY_HEAP
   4760     if (FLAG_verify_heap) {
   4761       receiver->JSObjectVerify();
   4762     }
   4763 #endif
   4764   }
   4765 
   4766   return Just(true);
   4767 }
   4768 
   4769 
   4770 void Map::EnsureDescriptorSlack(Handle<Map> map, int slack) {
   4771   // Only supports adding slack to owned descriptors.
   4772   DCHECK(map->owns_descriptors());
   4773 
   4774   Handle<DescriptorArray> descriptors(map->instance_descriptors());
   4775   int old_size = map->NumberOfOwnDescriptors();
   4776   if (slack <= descriptors->NumberOfSlackDescriptors()) return;
   4777 
   4778   Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo(
   4779       descriptors, old_size, slack);
   4780 
   4781   DisallowHeapAllocation no_allocation;
   4782   // The descriptors are still the same, so keep the layout descriptor.
   4783   LayoutDescriptor* layout_descriptor = map->GetLayoutDescriptor();
   4784 
   4785   if (old_size == 0) {
   4786     map->UpdateDescriptors(*new_descriptors, layout_descriptor);
   4787     return;
   4788   }
   4789 
   4790   // If the source descriptors had an enum cache we copy it. This ensures
   4791   // that the maps to which we push the new descriptor array back can rely
   4792   // on a cache always being available once it is set. If the map has more
   4793   // enumerated descriptors than available in the original cache, the cache
   4794   // will be lazily replaced by the extended cache when needed.
   4795   if (descriptors->HasEnumCache()) {
   4796     new_descriptors->CopyEnumCacheFrom(*descriptors);
   4797   }
   4798 
   4799   Isolate* isolate = map->GetIsolate();
   4800   // Replace descriptors by new_descriptors in all maps that share it.
   4801   isolate->heap()->incremental_marking()->IterateBlackObject(*descriptors);
   4802 
   4803   Map* current = *map;
   4804   while (current->instance_descriptors() == *descriptors) {
   4805     Object* next = current->GetBackPointer();
   4806     if (next->IsUndefined(isolate)) break;  // Stop overwriting at initial map.
   4807     current->UpdateDescriptors(*new_descriptors, layout_descriptor);
   4808     current = Map::cast(next);
   4809   }
   4810   map->UpdateDescriptors(*new_descriptors, layout_descriptor);
   4811 }
   4812 
   4813 
   4814 template<class T>
   4815 static int AppendUniqueCallbacks(NeanderArray* callbacks,
   4816                                  Handle<typename T::Array> array,
   4817                                  int valid_descriptors) {
   4818   int nof_callbacks = callbacks->length();
   4819 
   4820   Isolate* isolate = array->GetIsolate();
   4821   // Ensure the keys are unique names before writing them into the
   4822   // instance descriptor. Since it may cause a GC, it has to be done before we
   4823   // temporarily put the heap in an invalid state while appending descriptors.
   4824   for (int i = 0; i < nof_callbacks; ++i) {
   4825     Handle<AccessorInfo> entry(AccessorInfo::cast(callbacks->get(i)));
   4826     if (entry->name()->IsUniqueName()) continue;
   4827     Handle<String> key =
   4828         isolate->factory()->InternalizeString(
   4829             Handle<String>(String::cast(entry->name())));
   4830     entry->set_name(*key);
   4831   }
   4832 
   4833   // Fill in new callback descriptors.  Process the callbacks from
   4834   // back to front so that the last callback with a given name takes
   4835   // precedence over previously added callbacks with that name.
   4836   for (int i = nof_callbacks - 1; i >= 0; i--) {
   4837     Handle<AccessorInfo> entry(AccessorInfo::cast(callbacks->get(i)));
   4838     Handle<Name> key(Name::cast(entry->name()));
   4839     // Check if a descriptor with this name already exists before writing.
   4840     if (!T::Contains(key, entry, valid_descriptors, array)) {
   4841       T::Insert(key, entry, valid_descriptors, array);
   4842       valid_descriptors++;
   4843     }
   4844   }
   4845 
   4846   return valid_descriptors;
   4847 }
   4848 
   4849 struct DescriptorArrayAppender {
   4850   typedef DescriptorArray Array;
   4851   static bool Contains(Handle<Name> key,
   4852                        Handle<AccessorInfo> entry,
   4853                        int valid_descriptors,
   4854                        Handle<DescriptorArray> array) {
   4855     DisallowHeapAllocation no_gc;
   4856     return array->Search(*key, valid_descriptors) != DescriptorArray::kNotFound;
   4857   }
   4858   static void Insert(Handle<Name> key,
   4859                      Handle<AccessorInfo> entry,
   4860                      int valid_descriptors,
   4861                      Handle<DescriptorArray> array) {
   4862     DisallowHeapAllocation no_gc;
   4863     AccessorConstantDescriptor desc(key, entry, entry->property_attributes());
   4864     array->Append(&desc);
   4865   }
   4866 };
   4867 
   4868 
   4869 struct FixedArrayAppender {
   4870   typedef FixedArray Array;
   4871   static bool Contains(Handle<Name> key,
   4872                        Handle<AccessorInfo> entry,
   4873                        int valid_descriptors,
   4874                        Handle<FixedArray> array) {
   4875     for (int i = 0; i < valid_descriptors; i++) {
   4876       if (*key == AccessorInfo::cast(array->get(i))->name()) return true;
   4877     }
   4878     return false;
   4879   }
   4880   static void Insert(Handle<Name> key,
   4881                      Handle<AccessorInfo> entry,
   4882                      int valid_descriptors,
   4883                      Handle<FixedArray> array) {
   4884     DisallowHeapAllocation no_gc;
   4885     array->set(valid_descriptors, *entry);
   4886   }
   4887 };
   4888 
   4889 
   4890 void Map::AppendCallbackDescriptors(Handle<Map> map,
   4891                                     Handle<Object> descriptors) {
   4892   int nof = map->NumberOfOwnDescriptors();
   4893   Handle<DescriptorArray> array(map->instance_descriptors());
   4894   NeanderArray callbacks(descriptors);
   4895   DCHECK(array->NumberOfSlackDescriptors() >= callbacks.length());
   4896   nof = AppendUniqueCallbacks<DescriptorArrayAppender>(&callbacks, array, nof);
   4897   map->SetNumberOfOwnDescriptors(nof);
   4898 }
   4899 
   4900 
   4901 int AccessorInfo::AppendUnique(Handle<Object> descriptors,
   4902                                Handle<FixedArray> array,
   4903                                int valid_descriptors) {
   4904   NeanderArray callbacks(descriptors);
   4905   DCHECK(array->length() >= callbacks.length() + valid_descriptors);
   4906   return AppendUniqueCallbacks<FixedArrayAppender>(&callbacks,
   4907                                                    array,
   4908                                                    valid_descriptors);
   4909 }
   4910 
   4911 
   4912 static bool ContainsMap(MapHandleList* maps, Map* map) {
   4913   DCHECK_NOT_NULL(map);
   4914   for (int i = 0; i < maps->length(); ++i) {
   4915     if (!maps->at(i).is_null() && *maps->at(i) == map) return true;
   4916   }
   4917   return false;
   4918 }
   4919 
   4920 Map* Map::FindElementsKindTransitionedMap(MapHandleList* candidates) {
   4921   DisallowHeapAllocation no_allocation;
   4922   DisallowDeoptimization no_deoptimization(GetIsolate());
   4923 
   4924   ElementsKind kind = elements_kind();
   4925   bool packed = IsFastPackedElementsKind(kind);
   4926 
   4927   Map* transition = nullptr;
   4928   if (IsTransitionableFastElementsKind(kind)) {
   4929     // Check the state of the root map.
   4930     Map* root_map = FindRootMap();
   4931     if (!EquivalentToForTransition(root_map)) return nullptr;
   4932     root_map = root_map->LookupElementsTransitionMap(kind);
   4933     DCHECK_NOT_NULL(root_map);
   4934     // Starting from the next existing elements kind transition try to
   4935     // replay the property transitions that does not involve instance rewriting
   4936     // (ElementsTransitionAndStoreStub does not support that).
   4937     for (root_map = root_map->ElementsTransitionMap();
   4938          root_map != nullptr && root_map->has_fast_elements();
   4939          root_map = root_map->ElementsTransitionMap()) {
   4940       Map* current = root_map->TryReplayPropertyTransitions(this);
   4941       if (current == nullptr) continue;
   4942       if (InstancesNeedRewriting(current)) continue;
   4943 
   4944       if (ContainsMap(candidates, current) &&
   4945           (packed || !IsFastPackedElementsKind(current->elements_kind()))) {
   4946         transition = current;
   4947         packed = packed && IsFastPackedElementsKind(current->elements_kind());
   4948       }
   4949     }
   4950   }
   4951   return transition;
   4952 }
   4953 
   4954 
   4955 static Map* FindClosestElementsTransition(Map* map, ElementsKind to_kind) {
   4956   // Ensure we are requested to search elements kind transition "near the root".
   4957   DCHECK_EQ(map->FindRootMap()->NumberOfOwnDescriptors(),
   4958             map->NumberOfOwnDescriptors());
   4959   Map* current_map = map;
   4960 
   4961   ElementsKind kind = map->elements_kind();
   4962   while (kind != to_kind) {
   4963     Map* next_map = current_map->ElementsTransitionMap();
   4964     if (next_map == nullptr) return current_map;
   4965     kind = next_map->elements_kind();
   4966     current_map = next_map;
   4967   }
   4968 
   4969   DCHECK_EQ(to_kind, current_map->elements_kind());
   4970   return current_map;
   4971 }
   4972 
   4973 
   4974 Map* Map::LookupElementsTransitionMap(ElementsKind to_kind) {
   4975   Map* to_map = FindClosestElementsTransition(this, to_kind);
   4976   if (to_map->elements_kind() == to_kind) return to_map;
   4977   return nullptr;
   4978 }
   4979 
   4980 
   4981 bool Map::IsMapInArrayPrototypeChain() {
   4982   Isolate* isolate = GetIsolate();
   4983   if (isolate->initial_array_prototype()->map() == this) {
   4984     return true;
   4985   }
   4986 
   4987   if (isolate->initial_object_prototype()->map() == this) {
   4988     return true;
   4989   }
   4990 
   4991   return false;
   4992 }
   4993 
   4994 
   4995 Handle<WeakCell> Map::WeakCellForMap(Handle<Map> map) {
   4996   Isolate* isolate = map->GetIsolate();
   4997   if (map->weak_cell_cache()->IsWeakCell()) {
   4998     return Handle<WeakCell>(WeakCell::cast(map->weak_cell_cache()));
   4999   }
   5000   Handle<WeakCell> weak_cell = isolate->factory()->NewWeakCell(map);
   5001   map->set_weak_cell_cache(*weak_cell);
   5002   return weak_cell;
   5003 }
   5004 
   5005 
   5006 static Handle<Map> AddMissingElementsTransitions(Handle<Map> map,
   5007                                                  ElementsKind to_kind) {
   5008   DCHECK(IsTransitionElementsKind(map->elements_kind()));
   5009 
   5010   Handle<Map> current_map = map;
   5011 
   5012   ElementsKind kind = map->elements_kind();
   5013   TransitionFlag flag;
   5014   if (map->is_prototype_map()) {
   5015     flag = OMIT_TRANSITION;
   5016   } else {
   5017     flag = INSERT_TRANSITION;
   5018     if (IsFastElementsKind(kind)) {
   5019       while (kind != to_kind && !IsTerminalElementsKind(kind)) {
   5020         kind = GetNextTransitionElementsKind(kind);
   5021         current_map = Map::CopyAsElementsKind(current_map, kind, flag);
   5022       }
   5023     }
   5024   }
   5025 
   5026   // In case we are exiting the fast elements kind system, just add the map in
   5027   // the end.
   5028   if (kind != to_kind) {
   5029     current_map = Map::CopyAsElementsKind(current_map, to_kind, flag);
   5030   }
   5031 
   5032   DCHECK(current_map->elements_kind() == to_kind);
   5033   return current_map;
   5034 }
   5035 
   5036 
   5037 Handle<Map> Map::TransitionElementsTo(Handle<Map> map,
   5038                                       ElementsKind to_kind) {
   5039   ElementsKind from_kind = map->elements_kind();
   5040   if (from_kind == to_kind) return map;
   5041 
   5042   Isolate* isolate = map->GetIsolate();
   5043   Context* native_context = isolate->context()->native_context();
   5044   if (from_kind == FAST_SLOPPY_ARGUMENTS_ELEMENTS) {
   5045     if (*map == native_context->fast_aliased_arguments_map()) {
   5046       DCHECK_EQ(SLOW_SLOPPY_ARGUMENTS_ELEMENTS, to_kind);
   5047       return handle(native_context->slow_aliased_arguments_map());
   5048     }
   5049   } else if (from_kind == SLOW_SLOPPY_ARGUMENTS_ELEMENTS) {
   5050     if (*map == native_context->slow_aliased_arguments_map()) {
   5051       DCHECK_EQ(FAST_SLOPPY_ARGUMENTS_ELEMENTS, to_kind);
   5052       return handle(native_context->fast_aliased_arguments_map());
   5053     }
   5054   } else if (IsFastElementsKind(from_kind) && IsFastElementsKind(to_kind)) {
   5055     // Reuse map transitions for JSArrays.
   5056     DisallowHeapAllocation no_gc;
   5057     if (native_context->get(Context::ArrayMapIndex(from_kind)) == *map) {
   5058       Object* maybe_transitioned_map =
   5059           native_context->get(Context::ArrayMapIndex(to_kind));
   5060       if (maybe_transitioned_map->IsMap()) {
   5061         return handle(Map::cast(maybe_transitioned_map), isolate);
   5062       }
   5063     }
   5064   }
   5065 
   5066   DCHECK(!map->IsUndefined(isolate));
   5067   // Check if we can go back in the elements kind transition chain.
   5068   if (IsHoleyElementsKind(from_kind) &&
   5069       to_kind == GetPackedElementsKind(from_kind) &&
   5070       map->GetBackPointer()->IsMap() &&
   5071       Map::cast(map->GetBackPointer())->elements_kind() == to_kind) {
   5072     return handle(Map::cast(map->GetBackPointer()));
   5073   }
   5074 
   5075   bool allow_store_transition = IsTransitionElementsKind(from_kind);
   5076   // Only store fast element maps in ascending generality.
   5077   if (IsFastElementsKind(to_kind)) {
   5078     allow_store_transition =
   5079         allow_store_transition && IsTransitionableFastElementsKind(from_kind) &&
   5080         IsMoreGeneralElementsKindTransition(from_kind, to_kind);
   5081   }
   5082 
   5083   if (!allow_store_transition) {
   5084     return Map::CopyAsElementsKind(map, to_kind, OMIT_TRANSITION);
   5085   }
   5086 
   5087   return Map::ReconfigureElementsKind(map, to_kind);
   5088 }
   5089 
   5090 
   5091 // static
   5092 Handle<Map> Map::AsElementsKind(Handle<Map> map, ElementsKind kind) {
   5093   Handle<Map> closest_map(FindClosestElementsTransition(*map, kind));
   5094 
   5095   if (closest_map->elements_kind() == kind) {
   5096     return closest_map;
   5097   }
   5098 
   5099   return AddMissingElementsTransitions(closest_map, kind);
   5100 }
   5101 
   5102 
   5103 Handle<Map> JSObject::GetElementsTransitionMap(Handle<JSObject> object,
   5104                                                ElementsKind to_kind) {
   5105   Handle<Map> map(object->map());
   5106   return Map::TransitionElementsTo(map, to_kind);
   5107 }
   5108 
   5109 
   5110 void JSProxy::Revoke(Handle<JSProxy> proxy) {
   5111   Isolate* isolate = proxy->GetIsolate();
   5112   if (!proxy->IsRevoked()) proxy->set_handler(isolate->heap()->null_value());
   5113   DCHECK(proxy->IsRevoked());
   5114 }
   5115 
   5116 
   5117 Maybe<bool> JSProxy::HasProperty(Isolate* isolate, Handle<JSProxy> proxy,
   5118                                  Handle<Name> name) {
   5119   DCHECK(!name->IsPrivate());
   5120   STACK_CHECK(isolate, Nothing<bool>());
   5121   // 1. (Assert)
   5122   // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O.
   5123   Handle<Object> handler(proxy->handler(), isolate);
   5124   // 3. If handler is null, throw a TypeError exception.
   5125   // 4. Assert: Type(handler) is Object.
   5126   if (proxy->IsRevoked()) {
   5127     isolate->Throw(*isolate->factory()->NewTypeError(
   5128         MessageTemplate::kProxyRevoked, isolate->factory()->has_string()));
   5129     return Nothing<bool>();
   5130   }
   5131   // 5. Let target be the value of the [[ProxyTarget]] internal slot of O.
   5132   Handle<JSReceiver> target(proxy->target(), isolate);
   5133   // 6. Let trap be ? GetMethod(handler, "has").
   5134   Handle<Object> trap;
   5135   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   5136       isolate, trap, Object::GetMethod(Handle<JSReceiver>::cast(handler),
   5137                                        isolate->factory()->has_string()),
   5138       Nothing<bool>());
   5139   // 7. If trap is undefined, then
   5140   if (trap->IsUndefined(isolate)) {
   5141     // 7a. Return target.[[HasProperty]](P).
   5142     return JSReceiver::HasProperty(target, name);
   5143   }
   5144   // 8. Let booleanTrapResult be ToBoolean(? Call(trap, handler, target, P)).
   5145   Handle<Object> trap_result_obj;
   5146   Handle<Object> args[] = {target, name};
   5147   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   5148       isolate, trap_result_obj,
   5149       Execution::Call(isolate, trap, handler, arraysize(args), args),
   5150       Nothing<bool>());
   5151   bool boolean_trap_result = trap_result_obj->BooleanValue();
   5152   // 9. If booleanTrapResult is false, then:
   5153   if (!boolean_trap_result) {
   5154     // 9a. Let targetDesc be ? target.[[GetOwnProperty]](P).
   5155     PropertyDescriptor target_desc;
   5156     Maybe<bool> target_found = JSReceiver::GetOwnPropertyDescriptor(
   5157         isolate, target, name, &target_desc);
   5158     MAYBE_RETURN(target_found, Nothing<bool>());
   5159     // 9b. If targetDesc is not undefined, then:
   5160     if (target_found.FromJust()) {
   5161       // 9b i. If targetDesc.[[Configurable]] is false, throw a TypeError
   5162       //       exception.
   5163       if (!target_desc.configurable()) {
   5164         isolate->Throw(*isolate->factory()->NewTypeError(
   5165             MessageTemplate::kProxyHasNonConfigurable, name));
   5166         return Nothing<bool>();
   5167       }
   5168       // 9b ii. Let extensibleTarget be ? IsExtensible(target).
   5169       Maybe<bool> extensible_target = JSReceiver::IsExtensible(target);
   5170       MAYBE_RETURN(extensible_target, Nothing<bool>());
   5171       // 9b iii. If extensibleTarget is false, throw a TypeError exception.
   5172       if (!extensible_target.FromJust()) {
   5173         isolate->Throw(*isolate->factory()->NewTypeError(
   5174             MessageTemplate::kProxyHasNonExtensible, name));
   5175         return Nothing<bool>();
   5176       }
   5177     }
   5178   }
   5179   // 10. Return booleanTrapResult.
   5180   return Just(boolean_trap_result);
   5181 }
   5182 
   5183 
   5184 Maybe<bool> JSProxy::SetProperty(Handle<JSProxy> proxy, Handle<Name> name,
   5185                                  Handle<Object> value, Handle<Object> receiver,
   5186                                  LanguageMode language_mode) {
   5187   DCHECK(!name->IsPrivate());
   5188   Isolate* isolate = proxy->GetIsolate();
   5189   STACK_CHECK(isolate, Nothing<bool>());
   5190   Factory* factory = isolate->factory();
   5191   Handle<String> trap_name = factory->set_string();
   5192   ShouldThrow should_throw =
   5193       is_sloppy(language_mode) ? DONT_THROW : THROW_ON_ERROR;
   5194 
   5195   if (proxy->IsRevoked()) {
   5196     isolate->Throw(
   5197         *factory->NewTypeError(MessageTemplate::kProxyRevoked, trap_name));
   5198     return Nothing<bool>();
   5199   }
   5200   Handle<JSReceiver> target(proxy->target(), isolate);
   5201   Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate);
   5202 
   5203   Handle<Object> trap;
   5204   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   5205       isolate, trap, Object::GetMethod(handler, trap_name), Nothing<bool>());
   5206   if (trap->IsUndefined(isolate)) {
   5207     LookupIterator it =
   5208         LookupIterator::PropertyOrElement(isolate, receiver, name, target);
   5209     return Object::SetSuperProperty(&it, value, language_mode,
   5210                                     Object::MAY_BE_STORE_FROM_KEYED);
   5211   }
   5212 
   5213   Handle<Object> trap_result;
   5214   Handle<Object> args[] = {target, name, value, receiver};
   5215   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   5216       isolate, trap_result,
   5217       Execution::Call(isolate, trap, handler, arraysize(args), args),
   5218       Nothing<bool>());
   5219   if (!trap_result->BooleanValue()) {
   5220     RETURN_FAILURE(isolate, should_throw,
   5221                    NewTypeError(MessageTemplate::kProxyTrapReturnedFalsishFor,
   5222                                 trap_name, name));
   5223   }
   5224 
   5225   // Enforce the invariant.
   5226   PropertyDescriptor target_desc;
   5227   Maybe<bool> owned =
   5228       JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, &target_desc);
   5229   MAYBE_RETURN(owned, Nothing<bool>());
   5230   if (owned.FromJust()) {
   5231     bool inconsistent = PropertyDescriptor::IsDataDescriptor(&target_desc) &&
   5232                         !target_desc.configurable() &&
   5233                         !target_desc.writable() &&
   5234                         !value->SameValue(*target_desc.value());
   5235     if (inconsistent) {
   5236       isolate->Throw(*isolate->factory()->NewTypeError(
   5237           MessageTemplate::kProxySetFrozenData, name));
   5238       return Nothing<bool>();
   5239     }
   5240     inconsistent = PropertyDescriptor::IsAccessorDescriptor(&target_desc) &&
   5241                    !target_desc.configurable() &&
   5242                    target_desc.set()->IsUndefined(isolate);
   5243     if (inconsistent) {
   5244       isolate->Throw(*isolate->factory()->NewTypeError(
   5245           MessageTemplate::kProxySetFrozenAccessor, name));
   5246       return Nothing<bool>();
   5247     }
   5248   }
   5249   return Just(true);
   5250 }
   5251 
   5252 
   5253 Maybe<bool> JSProxy::DeletePropertyOrElement(Handle<JSProxy> proxy,
   5254                                              Handle<Name> name,
   5255                                              LanguageMode language_mode) {
   5256   DCHECK(!name->IsPrivate());
   5257   ShouldThrow should_throw =
   5258       is_sloppy(language_mode) ? DONT_THROW : THROW_ON_ERROR;
   5259   Isolate* isolate = proxy->GetIsolate();
   5260   STACK_CHECK(isolate, Nothing<bool>());
   5261   Factory* factory = isolate->factory();
   5262   Handle<String> trap_name = factory->deleteProperty_string();
   5263 
   5264   if (proxy->IsRevoked()) {
   5265     isolate->Throw(
   5266         *factory->NewTypeError(MessageTemplate::kProxyRevoked, trap_name));
   5267     return Nothing<bool>();
   5268   }
   5269   Handle<JSReceiver> target(proxy->target(), isolate);
   5270   Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate);
   5271 
   5272   Handle<Object> trap;
   5273   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   5274       isolate, trap, Object::GetMethod(handler, trap_name), Nothing<bool>());
   5275   if (trap->IsUndefined(isolate)) {
   5276     return JSReceiver::DeletePropertyOrElement(target, name, language_mode);
   5277   }
   5278 
   5279   Handle<Object> trap_result;
   5280   Handle<Object> args[] = {target, name};
   5281   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   5282       isolate, trap_result,
   5283       Execution::Call(isolate, trap, handler, arraysize(args), args),
   5284       Nothing<bool>());
   5285   if (!trap_result->BooleanValue()) {
   5286     RETURN_FAILURE(isolate, should_throw,
   5287                    NewTypeError(MessageTemplate::kProxyTrapReturnedFalsishFor,
   5288                                 trap_name, name));
   5289   }
   5290 
   5291   // Enforce the invariant.
   5292   PropertyDescriptor target_desc;
   5293   Maybe<bool> owned =
   5294       JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, &target_desc);
   5295   MAYBE_RETURN(owned, Nothing<bool>());
   5296   if (owned.FromJust() && !target_desc.configurable()) {
   5297     isolate->Throw(*factory->NewTypeError(
   5298         MessageTemplate::kProxyDeletePropertyNonConfigurable, name));
   5299     return Nothing<bool>();
   5300   }
   5301   return Just(true);
   5302 }
   5303 
   5304 
   5305 // static
   5306 MaybeHandle<JSProxy> JSProxy::New(Isolate* isolate, Handle<Object> target,
   5307                                   Handle<Object> handler) {
   5308   if (!target->IsJSReceiver()) {
   5309     THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kProxyNonObject),
   5310                     JSProxy);
   5311   }
   5312   if (target->IsJSProxy() && JSProxy::cast(*target)->IsRevoked()) {
   5313     THROW_NEW_ERROR(isolate,
   5314                     NewTypeError(MessageTemplate::kProxyHandlerOrTargetRevoked),
   5315                     JSProxy);
   5316   }
   5317   if (!handler->IsJSReceiver()) {
   5318     THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kProxyNonObject),
   5319                     JSProxy);
   5320   }
   5321   if (handler->IsJSProxy() && JSProxy::cast(*handler)->IsRevoked()) {
   5322     THROW_NEW_ERROR(isolate,
   5323                     NewTypeError(MessageTemplate::kProxyHandlerOrTargetRevoked),
   5324                     JSProxy);
   5325   }
   5326   return isolate->factory()->NewJSProxy(Handle<JSReceiver>::cast(target),
   5327                                         Handle<JSReceiver>::cast(handler));
   5328 }
   5329 
   5330 
   5331 // static
   5332 MaybeHandle<Context> JSProxy::GetFunctionRealm(Handle<JSProxy> proxy) {
   5333   DCHECK(proxy->map()->is_constructor());
   5334   if (proxy->IsRevoked()) {
   5335     THROW_NEW_ERROR(proxy->GetIsolate(),
   5336                     NewTypeError(MessageTemplate::kProxyRevoked), Context);
   5337   }
   5338   Handle<JSReceiver> target(JSReceiver::cast(proxy->target()));
   5339   return JSReceiver::GetFunctionRealm(target);
   5340 }
   5341 
   5342 
   5343 // static
   5344 MaybeHandle<Context> JSBoundFunction::GetFunctionRealm(
   5345     Handle<JSBoundFunction> function) {
   5346   DCHECK(function->map()->is_constructor());
   5347   return JSReceiver::GetFunctionRealm(
   5348       handle(function->bound_target_function()));
   5349 }
   5350 
   5351 // static
   5352 MaybeHandle<String> JSBoundFunction::GetName(Isolate* isolate,
   5353                                              Handle<JSBoundFunction> function) {
   5354   Handle<String> prefix = isolate->factory()->bound__string();
   5355   if (!function->bound_target_function()->IsJSFunction()) return prefix;
   5356   Handle<JSFunction> target(JSFunction::cast(function->bound_target_function()),
   5357                             isolate);
   5358   Handle<Object> target_name = JSFunction::GetName(isolate, target);
   5359   if (!target_name->IsString()) return prefix;
   5360   Factory* factory = isolate->factory();
   5361   return factory->NewConsString(prefix, Handle<String>::cast(target_name));
   5362 }
   5363 
   5364 // static
   5365 Handle<Object> JSFunction::GetName(Isolate* isolate,
   5366                                    Handle<JSFunction> function) {
   5367   if (function->shared()->name_should_print_as_anonymous()) {
   5368     return isolate->factory()->anonymous_string();
   5369   }
   5370   return handle(function->shared()->name(), isolate);
   5371 }
   5372 
   5373 // static
   5374 MaybeHandle<Smi> JSFunction::GetLength(Isolate* isolate,
   5375                                        Handle<JSFunction> function) {
   5376   int length = 0;
   5377   if (function->shared()->is_compiled()) {
   5378     length = function->shared()->length();
   5379   } else {
   5380     // If the function isn't compiled yet, the length is not computed
   5381     // correctly yet. Compile it now and return the right length.
   5382     if (Compiler::Compile(function, Compiler::KEEP_EXCEPTION)) {
   5383       length = function->shared()->length();
   5384     }
   5385     if (isolate->has_pending_exception()) return MaybeHandle<Smi>();
   5386   }
   5387   return handle(Smi::FromInt(length), isolate);
   5388 }
   5389 
   5390 // static
   5391 Handle<Context> JSFunction::GetFunctionRealm(Handle<JSFunction> function) {
   5392   DCHECK(function->map()->is_constructor());
   5393   return handle(function->context()->native_context());
   5394 }
   5395 
   5396 
   5397 // static
   5398 MaybeHandle<Context> JSObject::GetFunctionRealm(Handle<JSObject> object) {
   5399   DCHECK(object->map()->is_constructor());
   5400   DCHECK(!object->IsJSFunction());
   5401   return handle(object->GetCreationContext());
   5402 }
   5403 
   5404 
   5405 // static
   5406 MaybeHandle<Context> JSReceiver::GetFunctionRealm(Handle<JSReceiver> receiver) {
   5407   if (receiver->IsJSProxy()) {
   5408     return JSProxy::GetFunctionRealm(Handle<JSProxy>::cast(receiver));
   5409   }
   5410 
   5411   if (receiver->IsJSFunction()) {
   5412     return JSFunction::GetFunctionRealm(Handle<JSFunction>::cast(receiver));
   5413   }
   5414 
   5415   if (receiver->IsJSBoundFunction()) {
   5416     return JSBoundFunction::GetFunctionRealm(
   5417         Handle<JSBoundFunction>::cast(receiver));
   5418   }
   5419 
   5420   return JSObject::GetFunctionRealm(Handle<JSObject>::cast(receiver));
   5421 }
   5422 
   5423 
   5424 Maybe<PropertyAttributes> JSProxy::GetPropertyAttributes(LookupIterator* it) {
   5425   PropertyDescriptor desc;
   5426   Maybe<bool> found = JSProxy::GetOwnPropertyDescriptor(
   5427       it->isolate(), it->GetHolder<JSProxy>(), it->GetName(), &desc);
   5428   MAYBE_RETURN(found, Nothing<PropertyAttributes>());
   5429   if (!found.FromJust()) return Just(ABSENT);
   5430   return Just(desc.ToAttributes());
   5431 }
   5432 
   5433 
   5434 void JSObject::AllocateStorageForMap(Handle<JSObject> object, Handle<Map> map) {
   5435   DCHECK(object->map()->GetInObjectProperties() ==
   5436          map->GetInObjectProperties());
   5437   ElementsKind obj_kind = object->map()->elements_kind();
   5438   ElementsKind map_kind = map->elements_kind();
   5439   if (map_kind != obj_kind) {
   5440     ElementsKind to_kind = GetMoreGeneralElementsKind(map_kind, obj_kind);
   5441     if (IsDictionaryElementsKind(obj_kind)) {
   5442       to_kind = obj_kind;
   5443     }
   5444     if (IsDictionaryElementsKind(to_kind)) {
   5445       NormalizeElements(object);
   5446     } else {
   5447       TransitionElementsKind(object, to_kind);
   5448     }
   5449     map = Map::ReconfigureElementsKind(map, to_kind);
   5450   }
   5451   JSObject::MigrateToMap(object, map);
   5452 }
   5453 
   5454 
   5455 void JSObject::MigrateInstance(Handle<JSObject> object) {
   5456   Handle<Map> original_map(object->map());
   5457   Handle<Map> map = Map::Update(original_map);
   5458   map->set_migration_target(true);
   5459   MigrateToMap(object, map);
   5460   if (FLAG_trace_migration) {
   5461     object->PrintInstanceMigration(stdout, *original_map, *map);
   5462   }
   5463 #if VERIFY_HEAP
   5464   if (FLAG_verify_heap) {
   5465     object->JSObjectVerify();
   5466   }
   5467 #endif
   5468 }
   5469 
   5470 
   5471 // static
   5472 bool JSObject::TryMigrateInstance(Handle<JSObject> object) {
   5473   Isolate* isolate = object->GetIsolate();
   5474   DisallowDeoptimization no_deoptimization(isolate);
   5475   Handle<Map> original_map(object->map(), isolate);
   5476   Handle<Map> new_map;
   5477   if (!Map::TryUpdate(original_map).ToHandle(&new_map)) {
   5478     return false;
   5479   }
   5480   JSObject::MigrateToMap(object, new_map);
   5481   if (FLAG_trace_migration) {
   5482     object->PrintInstanceMigration(stdout, *original_map, object->map());
   5483   }
   5484 #if VERIFY_HEAP
   5485   if (FLAG_verify_heap) {
   5486     object->JSObjectVerify();
   5487   }
   5488 #endif
   5489   return true;
   5490 }
   5491 
   5492 
   5493 void JSObject::AddProperty(Handle<JSObject> object, Handle<Name> name,
   5494                            Handle<Object> value,
   5495                            PropertyAttributes attributes) {
   5496   LookupIterator it(object, name, object, LookupIterator::OWN_SKIP_INTERCEPTOR);
   5497   CHECK_NE(LookupIterator::ACCESS_CHECK, it.state());
   5498 #ifdef DEBUG
   5499   uint32_t index;
   5500   DCHECK(!object->IsJSProxy());
   5501   DCHECK(!name->AsArrayIndex(&index));
   5502   Maybe<PropertyAttributes> maybe = GetPropertyAttributes(&it);
   5503   DCHECK(maybe.IsJust());
   5504   DCHECK(!it.IsFound());
   5505   DCHECK(object->map()->is_extensible() || name->IsPrivate());
   5506 #endif
   5507   CHECK(AddDataProperty(&it, value, attributes, THROW_ON_ERROR,
   5508                         CERTAINLY_NOT_STORE_FROM_KEYED)
   5509             .IsJust());
   5510 }
   5511 
   5512 
   5513 // Reconfigures a property to a data property with attributes, even if it is not
   5514 // reconfigurable.
   5515 // Requires a LookupIterator that does not look at the prototype chain beyond
   5516 // hidden prototypes.
   5517 MaybeHandle<Object> JSObject::DefineOwnPropertyIgnoreAttributes(
   5518     LookupIterator* it, Handle<Object> value, PropertyAttributes attributes,
   5519     AccessorInfoHandling handling) {
   5520   MAYBE_RETURN_NULL(DefineOwnPropertyIgnoreAttributes(
   5521       it, value, attributes, THROW_ON_ERROR, handling));
   5522   return value;
   5523 }
   5524 
   5525 
   5526 Maybe<bool> JSObject::DefineOwnPropertyIgnoreAttributes(
   5527     LookupIterator* it, Handle<Object> value, PropertyAttributes attributes,
   5528     ShouldThrow should_throw, AccessorInfoHandling handling) {
   5529   it->UpdateProtector();
   5530   Handle<JSObject> object = Handle<JSObject>::cast(it->GetReceiver());
   5531 
   5532   for (; it->IsFound(); it->Next()) {
   5533     switch (it->state()) {
   5534       case LookupIterator::JSPROXY:
   5535       case LookupIterator::NOT_FOUND:
   5536       case LookupIterator::TRANSITION:
   5537         UNREACHABLE();
   5538 
   5539       case LookupIterator::ACCESS_CHECK:
   5540         if (!it->HasAccess()) {
   5541           it->isolate()->ReportFailedAccessCheck(it->GetHolder<JSObject>());
   5542           RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(), Nothing<bool>());
   5543           return Just(true);
   5544         }
   5545         break;
   5546 
   5547       // If there's an interceptor, try to store the property with the
   5548       // interceptor.
   5549       // In case of success, the attributes will have been reset to the default
   5550       // attributes of the interceptor, rather than the incoming attributes.
   5551       //
   5552       // TODO(verwaest): JSProxy afterwards verify the attributes that the
   5553       // JSProxy claims it has, and verifies that they are compatible. If not,
   5554       // they throw. Here we should do the same.
   5555       case LookupIterator::INTERCEPTOR:
   5556         if (handling == DONT_FORCE_FIELD) {
   5557           Maybe<bool> result =
   5558               JSObject::SetPropertyWithInterceptor(it, should_throw, value);
   5559           if (result.IsNothing() || result.FromJust()) return result;
   5560         }
   5561         break;
   5562 
   5563       case LookupIterator::ACCESSOR: {
   5564         Handle<Object> accessors = it->GetAccessors();
   5565 
   5566         // Special handling for AccessorInfo, which behaves like a data
   5567         // property.
   5568         if (accessors->IsAccessorInfo() && handling == DONT_FORCE_FIELD) {
   5569           PropertyAttributes current_attributes = it->property_attributes();
   5570           // Ensure the context isn't changed after calling into accessors.
   5571           AssertNoContextChange ncc(it->isolate());
   5572 
   5573           // Update the attributes before calling the setter. The setter may
   5574           // later change the shape of the property.
   5575           if (current_attributes != attributes) {
   5576             it->TransitionToAccessorPair(accessors, attributes);
   5577           }
   5578 
   5579           Maybe<bool> result =
   5580               JSObject::SetPropertyWithAccessor(it, value, should_throw);
   5581 
   5582           if (current_attributes == attributes || result.IsNothing()) {
   5583             return result;
   5584           }
   5585 
   5586         } else {
   5587           it->ReconfigureDataProperty(value, attributes);
   5588         }
   5589 
   5590         return Just(true);
   5591       }
   5592       case LookupIterator::INTEGER_INDEXED_EXOTIC:
   5593         return RedefineIncompatibleProperty(it->isolate(), it->GetName(), value,
   5594                                             should_throw);
   5595 
   5596       case LookupIterator::DATA: {
   5597         // Regular property update if the attributes match.
   5598         if (it->property_attributes() == attributes) {
   5599           return SetDataProperty(it, value);
   5600         }
   5601 
   5602         // Special case: properties of typed arrays cannot be reconfigured to
   5603         // non-writable nor to non-enumerable.
   5604         if (it->IsElement() && object->HasFixedTypedArrayElements()) {
   5605           return RedefineIncompatibleProperty(it->isolate(), it->GetName(),
   5606                                               value, should_throw);
   5607         }
   5608 
   5609         // Reconfigure the data property if the attributes mismatch.
   5610         it->ReconfigureDataProperty(value, attributes);
   5611 
   5612         return Just(true);
   5613       }
   5614     }
   5615   }
   5616 
   5617   return AddDataProperty(it, value, attributes, should_throw,
   5618