Home | History | Annotate | Download | only in src
      1 // Copyright 2015 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "src/objects.h"
      6 
      7 #include <cmath>
      8 #include <iomanip>
      9 #include <memory>
     10 #include <sstream>
     11 #include <unordered_map>
     12 #include <unordered_set>
     13 
     14 #include "src/objects-inl.h"
     15 
     16 #include "src/accessors.h"
     17 #include "src/allocation-site-scopes.h"
     18 #include "src/api-arguments-inl.h"
     19 #include "src/api-natives.h"
     20 #include "src/api.h"
     21 #include "src/arguments.h"
     22 #include "src/base/bits.h"
     23 #include "src/base/utils/random-number-generator.h"
     24 #include "src/bootstrapper.h"
     25 #include "src/code-stubs.h"
     26 #include "src/codegen.h"
     27 #include "src/compilation-dependencies.h"
     28 #include "src/compiler.h"
     29 #include "src/counters-inl.h"
     30 #include "src/counters.h"
     31 #include "src/date.h"
     32 #include "src/debug/debug-evaluate.h"
     33 #include "src/debug/debug.h"
     34 #include "src/deoptimizer.h"
     35 #include "src/elements.h"
     36 #include "src/execution.h"
     37 #include "src/field-index-inl.h"
     38 #include "src/field-index.h"
     39 #include "src/field-type.h"
     40 #include "src/frames-inl.h"
     41 #include "src/full-codegen/full-codegen.h"
     42 #include "src/globals.h"
     43 #include "src/ic/ic.h"
     44 #include "src/identity-map.h"
     45 #include "src/interpreter/bytecode-array-iterator.h"
     46 #include "src/interpreter/bytecode-decoder.h"
     47 #include "src/interpreter/interpreter.h"
     48 #include "src/isolate-inl.h"
     49 #include "src/keys.h"
     50 #include "src/list.h"
     51 #include "src/log.h"
     52 #include "src/lookup.h"
     53 #include "src/macro-assembler.h"
     54 #include "src/map-updater.h"
     55 #include "src/messages.h"
     56 #include "src/objects-body-descriptors-inl.h"
     57 #include "src/property-descriptor.h"
     58 #include "src/prototype.h"
     59 #include "src/regexp/jsregexp.h"
     60 #include "src/safepoint-table.h"
     61 #include "src/snapshot/code-serializer.h"
     62 #include "src/source-position-table.h"
     63 #include "src/string-builder.h"
     64 #include "src/string-search.h"
     65 #include "src/string-stream.h"
     66 #include "src/utils.h"
     67 #include "src/wasm/wasm-module.h"
     68 #include "src/wasm/wasm-objects.h"
     69 #include "src/zone/zone.h"
     70 
     71 #ifdef ENABLE_DISASSEMBLER
     72 #include "src/disasm.h"
     73 #include "src/disassembler.h"
     74 #include "src/eh-frame.h"
     75 #endif
     76 
     77 namespace v8 {
     78 namespace internal {
     79 
     80 std::ostream& operator<<(std::ostream& os, InstanceType instance_type) {
     81   switch (instance_type) {
     82 #define WRITE_TYPE(TYPE) \
     83   case TYPE:             \
     84     return os << #TYPE;
     85     INSTANCE_TYPE_LIST(WRITE_TYPE)
     86 #undef WRITE_TYPE
     87   }
     88   UNREACHABLE();
     89   return os << "UNKNOWN";  // Keep the compiler happy.
     90 }
     91 
     92 Handle<FieldType> Object::OptimalType(Isolate* isolate,
     93                                       Representation representation) {
     94   if (representation.IsNone()) return FieldType::None(isolate);
     95   if (FLAG_track_field_types) {
     96     if (representation.IsHeapObject() && IsHeapObject()) {
     97       // We can track only JavaScript objects with stable maps.
     98       Handle<Map> map(HeapObject::cast(this)->map(), isolate);
     99       if (map->is_stable() && map->IsJSReceiverMap()) {
    100         return FieldType::Class(map, isolate);
    101       }
    102     }
    103   }
    104   return FieldType::Any(isolate);
    105 }
    106 
    107 
    108 MaybeHandle<JSReceiver> Object::ToObject(Isolate* isolate,
    109                                          Handle<Object> object,
    110                                          Handle<Context> native_context) {
    111   if (object->IsJSReceiver()) return Handle<JSReceiver>::cast(object);
    112   Handle<JSFunction> constructor;
    113   if (object->IsSmi()) {
    114     constructor = handle(native_context->number_function(), isolate);
    115   } else {
    116     int constructor_function_index =
    117         Handle<HeapObject>::cast(object)->map()->GetConstructorFunctionIndex();
    118     if (constructor_function_index == Map::kNoConstructorFunctionIndex) {
    119       THROW_NEW_ERROR(isolate,
    120                       NewTypeError(MessageTemplate::kUndefinedOrNullToObject),
    121                       JSReceiver);
    122     }
    123     constructor = handle(
    124         JSFunction::cast(native_context->get(constructor_function_index)),
    125         isolate);
    126   }
    127   Handle<JSObject> result = isolate->factory()->NewJSObject(constructor);
    128   Handle<JSValue>::cast(result)->set_value(*object);
    129   return result;
    130 }
    131 
    132 // ES6 section 9.2.1.2, OrdinaryCallBindThis for sloppy callee.
    133 // static
    134 MaybeHandle<JSReceiver> Object::ConvertReceiver(Isolate* isolate,
    135                                                 Handle<Object> object) {
    136   if (object->IsJSReceiver()) return Handle<JSReceiver>::cast(object);
    137   if (*object == isolate->heap()->null_value() ||
    138       object->IsUndefined(isolate)) {
    139     return isolate->global_proxy();
    140   }
    141   return Object::ToObject(isolate, object);
    142 }
    143 
    144 // static
    145 MaybeHandle<Object> Object::ConvertToNumber(Isolate* isolate,
    146                                             Handle<Object> input) {
    147   while (true) {
    148     if (input->IsNumber()) {
    149       return input;
    150     }
    151     if (input->IsString()) {
    152       return String::ToNumber(Handle<String>::cast(input));
    153     }
    154     if (input->IsOddball()) {
    155       return Oddball::ToNumber(Handle<Oddball>::cast(input));
    156     }
    157     if (input->IsSymbol()) {
    158       THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kSymbolToNumber),
    159                       Object);
    160     }
    161     ASSIGN_RETURN_ON_EXCEPTION(
    162         isolate, input, JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(input),
    163                                                 ToPrimitiveHint::kNumber),
    164         Object);
    165   }
    166 }
    167 
    168 // static
    169 MaybeHandle<Object> Object::ConvertToInteger(Isolate* isolate,
    170                                              Handle<Object> input) {
    171   ASSIGN_RETURN_ON_EXCEPTION(isolate, input, ConvertToNumber(isolate, input),
    172                              Object);
    173   if (input->IsSmi()) return input;
    174   return isolate->factory()->NewNumber(DoubleToInteger(input->Number()));
    175 }
    176 
    177 // static
    178 MaybeHandle<Object> Object::ConvertToInt32(Isolate* isolate,
    179                                            Handle<Object> input) {
    180   ASSIGN_RETURN_ON_EXCEPTION(isolate, input, ConvertToNumber(isolate, input),
    181                              Object);
    182   if (input->IsSmi()) return input;
    183   return isolate->factory()->NewNumberFromInt(DoubleToInt32(input->Number()));
    184 }
    185 
    186 // static
    187 MaybeHandle<Object> Object::ConvertToUint32(Isolate* isolate,
    188                                             Handle<Object> input) {
    189   ASSIGN_RETURN_ON_EXCEPTION(isolate, input, ConvertToNumber(isolate, input),
    190                              Object);
    191   if (input->IsSmi()) return handle(Smi::cast(*input)->ToUint32Smi(), isolate);
    192   return isolate->factory()->NewNumberFromUint(DoubleToUint32(input->Number()));
    193 }
    194 
    195 // static
    196 MaybeHandle<Name> Object::ConvertToName(Isolate* isolate,
    197                                         Handle<Object> input) {
    198   ASSIGN_RETURN_ON_EXCEPTION(
    199       isolate, input, Object::ToPrimitive(input, ToPrimitiveHint::kString),
    200       Name);
    201   if (input->IsName()) return Handle<Name>::cast(input);
    202   return ToString(isolate, input);
    203 }
    204 
    205 // ES6 7.1.14
    206 // static
    207 MaybeHandle<Object> Object::ConvertToPropertyKey(Isolate* isolate,
    208                                                  Handle<Object> value) {
    209   // 1. Let key be ToPrimitive(argument, hint String).
    210   MaybeHandle<Object> maybe_key =
    211       Object::ToPrimitive(value, ToPrimitiveHint::kString);
    212   // 2. ReturnIfAbrupt(key).
    213   Handle<Object> key;
    214   if (!maybe_key.ToHandle(&key)) return key;
    215   // 3. If Type(key) is Symbol, then return key.
    216   if (key->IsSymbol()) return key;
    217   // 4. Return ToString(key).
    218   // Extending spec'ed behavior, we'd be happy to return an element index.
    219   if (key->IsSmi()) return key;
    220   if (key->IsHeapNumber()) {
    221     uint32_t uint_value;
    222     if (value->ToArrayLength(&uint_value) &&
    223         uint_value <= static_cast<uint32_t>(Smi::kMaxValue)) {
    224       return handle(Smi::FromInt(static_cast<int>(uint_value)), isolate);
    225     }
    226   }
    227   return Object::ToString(isolate, key);
    228 }
    229 
    230 // static
    231 MaybeHandle<String> Object::ConvertToString(Isolate* isolate,
    232                                             Handle<Object> input) {
    233   while (true) {
    234     if (input->IsOddball()) {
    235       return handle(Handle<Oddball>::cast(input)->to_string(), isolate);
    236     }
    237     if (input->IsNumber()) {
    238       return isolate->factory()->NumberToString(input);
    239     }
    240     if (input->IsSymbol()) {
    241       THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kSymbolToString),
    242                       String);
    243     }
    244     ASSIGN_RETURN_ON_EXCEPTION(
    245         isolate, input, JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(input),
    246                                                 ToPrimitiveHint::kString),
    247         String);
    248     // The previous isString() check happened in Object::ToString and thus we
    249     // put it at the end of the loop in this helper.
    250     if (input->IsString()) {
    251       return Handle<String>::cast(input);
    252     }
    253   }
    254 }
    255 
    256 namespace {
    257 
    258 bool IsErrorObject(Isolate* isolate, Handle<Object> object) {
    259   if (!object->IsJSReceiver()) return false;
    260   Handle<Symbol> symbol = isolate->factory()->stack_trace_symbol();
    261   return JSReceiver::HasOwnProperty(Handle<JSReceiver>::cast(object), symbol)
    262       .FromMaybe(false);
    263 }
    264 
    265 Handle<String> AsStringOrEmpty(Isolate* isolate, Handle<Object> object) {
    266   return object->IsString() ? Handle<String>::cast(object)
    267                             : isolate->factory()->empty_string();
    268 }
    269 
    270 Handle<String> NoSideEffectsErrorToString(Isolate* isolate,
    271                                           Handle<Object> input) {
    272   Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(input);
    273 
    274   Handle<Name> name_key = isolate->factory()->name_string();
    275   Handle<Object> name = JSReceiver::GetDataProperty(receiver, name_key);
    276   Handle<String> name_str = AsStringOrEmpty(isolate, name);
    277 
    278   Handle<Name> msg_key = isolate->factory()->message_string();
    279   Handle<Object> msg = JSReceiver::GetDataProperty(receiver, msg_key);
    280   Handle<String> msg_str = AsStringOrEmpty(isolate, msg);
    281 
    282   if (name_str->length() == 0) return msg_str;
    283   if (msg_str->length() == 0) return name_str;
    284 
    285   IncrementalStringBuilder builder(isolate);
    286   builder.AppendString(name_str);
    287   builder.AppendCString(": ");
    288   builder.AppendString(msg_str);
    289 
    290   return builder.Finish().ToHandleChecked();
    291 }
    292 
    293 }  // namespace
    294 
    295 // static
    296 Handle<String> Object::NoSideEffectsToString(Isolate* isolate,
    297                                              Handle<Object> input) {
    298   DisallowJavascriptExecution no_js(isolate);
    299 
    300   if (input->IsString() || input->IsNumber() || input->IsOddball()) {
    301     return Object::ToString(isolate, input).ToHandleChecked();
    302   } else if (input->IsFunction()) {
    303     // -- F u n c t i o n
    304     Handle<String> fun_str;
    305     if (input->IsJSBoundFunction()) {
    306       fun_str = JSBoundFunction::ToString(Handle<JSBoundFunction>::cast(input));
    307     } else {
    308       DCHECK(input->IsJSFunction());
    309       fun_str = JSFunction::ToString(Handle<JSFunction>::cast(input));
    310     }
    311 
    312     if (fun_str->length() > 128) {
    313       IncrementalStringBuilder builder(isolate);
    314       builder.AppendString(isolate->factory()->NewSubString(fun_str, 0, 111));
    315       builder.AppendCString("...<omitted>...");
    316       builder.AppendString(isolate->factory()->NewSubString(
    317           fun_str, fun_str->length() - 2, fun_str->length()));
    318 
    319       return builder.Finish().ToHandleChecked();
    320     }
    321     return fun_str;
    322   } else if (input->IsSymbol()) {
    323     // -- S y m b o l
    324     Handle<Symbol> symbol = Handle<Symbol>::cast(input);
    325 
    326     IncrementalStringBuilder builder(isolate);
    327     builder.AppendCString("Symbol(");
    328     if (symbol->name()->IsString()) {
    329       builder.AppendString(handle(String::cast(symbol->name()), isolate));
    330     }
    331     builder.AppendCharacter(')');
    332 
    333     return builder.Finish().ToHandleChecked();
    334   } else if (input->IsJSReceiver()) {
    335     // -- J S R e c e i v e r
    336     Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(input);
    337     Handle<Object> to_string = JSReceiver::GetDataProperty(
    338         receiver, isolate->factory()->toString_string());
    339 
    340     if (IsErrorObject(isolate, input) ||
    341         *to_string == *isolate->error_to_string()) {
    342       // When internally formatting error objects, use a side-effects-free
    343       // version of Error.prototype.toString independent of the actually
    344       // installed toString method.
    345       return NoSideEffectsErrorToString(isolate, input);
    346     } else if (*to_string == *isolate->object_to_string()) {
    347       Handle<Object> ctor = JSReceiver::GetDataProperty(
    348           receiver, isolate->factory()->constructor_string());
    349       if (ctor->IsFunction()) {
    350         Handle<String> ctor_name;
    351         if (ctor->IsJSBoundFunction()) {
    352           ctor_name = JSBoundFunction::GetName(
    353                           isolate, Handle<JSBoundFunction>::cast(ctor))
    354                           .ToHandleChecked();
    355         } else if (ctor->IsJSFunction()) {
    356           Handle<Object> ctor_name_obj =
    357               JSFunction::GetName(isolate, Handle<JSFunction>::cast(ctor));
    358           ctor_name = AsStringOrEmpty(isolate, ctor_name_obj);
    359         }
    360 
    361         if (ctor_name->length() != 0) {
    362           IncrementalStringBuilder builder(isolate);
    363           builder.AppendCString("#<");
    364           builder.AppendString(ctor_name);
    365           builder.AppendCString(">");
    366 
    367           return builder.Finish().ToHandleChecked();
    368         }
    369       }
    370     }
    371   }
    372 
    373   // At this point, input is either none of the above or a JSReceiver.
    374 
    375   Handle<JSReceiver> receiver;
    376   if (input->IsJSReceiver()) {
    377     receiver = Handle<JSReceiver>::cast(input);
    378   } else {
    379     // This is the only case where Object::ToObject throws.
    380     DCHECK(!input->IsSmi());
    381     int constructor_function_index =
    382         Handle<HeapObject>::cast(input)->map()->GetConstructorFunctionIndex();
    383     if (constructor_function_index == Map::kNoConstructorFunctionIndex) {
    384       return isolate->factory()->NewStringFromAsciiChecked("[object Unknown]");
    385     }
    386 
    387     receiver = Object::ToObject(isolate, input, isolate->native_context())
    388                    .ToHandleChecked();
    389   }
    390 
    391   Handle<String> builtin_tag = handle(receiver->class_name(), isolate);
    392   Handle<Object> tag_obj = JSReceiver::GetDataProperty(
    393       receiver, isolate->factory()->to_string_tag_symbol());
    394   Handle<String> tag =
    395       tag_obj->IsString() ? Handle<String>::cast(tag_obj) : builtin_tag;
    396 
    397   IncrementalStringBuilder builder(isolate);
    398   builder.AppendCString("[object ");
    399   builder.AppendString(tag);
    400   builder.AppendCString("]");
    401 
    402   return builder.Finish().ToHandleChecked();
    403 }
    404 
    405 // static
    406 MaybeHandle<Object> Object::ConvertToLength(Isolate* isolate,
    407                                             Handle<Object> input) {
    408   ASSIGN_RETURN_ON_EXCEPTION(isolate, input, ToNumber(input), Object);
    409   if (input->IsSmi()) {
    410     int value = std::max(Smi::cast(*input)->value(), 0);
    411     return handle(Smi::FromInt(value), isolate);
    412   }
    413   double len = DoubleToInteger(input->Number());
    414   if (len <= 0.0) {
    415     return handle(Smi::kZero, isolate);
    416   } else if (len >= kMaxSafeInteger) {
    417     len = kMaxSafeInteger;
    418   }
    419   return isolate->factory()->NewNumber(len);
    420 }
    421 
    422 // static
    423 MaybeHandle<Object> Object::ConvertToIndex(
    424     Isolate* isolate, Handle<Object> input,
    425     MessageTemplate::Template error_index) {
    426   if (input->IsUndefined(isolate)) return handle(Smi::kZero, isolate);
    427   ASSIGN_RETURN_ON_EXCEPTION(isolate, input, ToNumber(input), Object);
    428   if (input->IsSmi() && Smi::cast(*input)->value() >= 0) return input;
    429   double len = DoubleToInteger(input->Number()) + 0.0;
    430   auto js_len = isolate->factory()->NewNumber(len);
    431   if (len < 0.0 || len > kMaxSafeInteger) {
    432     THROW_NEW_ERROR(isolate, NewRangeError(error_index, js_len), Object);
    433   }
    434   return js_len;
    435 }
    436 
    437 bool Object::BooleanValue() {
    438   if (IsSmi()) return Smi::cast(this)->value() != 0;
    439   DCHECK(IsHeapObject());
    440   Isolate* isolate = HeapObject::cast(this)->GetIsolate();
    441   if (IsBoolean()) return IsTrue(isolate);
    442   if (IsNullOrUndefined(isolate)) return false;
    443   if (IsUndetectable()) return false;  // Undetectable object is false.
    444   if (IsString()) return String::cast(this)->length() != 0;
    445   if (IsHeapNumber()) return HeapNumber::cast(this)->HeapNumberBooleanValue();
    446   return true;
    447 }
    448 
    449 
    450 namespace {
    451 
    452 // TODO(bmeurer): Maybe we should introduce a marker interface Number,
    453 // where we put all these methods at some point?
    454 ComparisonResult NumberCompare(double x, double y) {
    455   if (std::isnan(x) || std::isnan(y)) {
    456     return ComparisonResult::kUndefined;
    457   } else if (x < y) {
    458     return ComparisonResult::kLessThan;
    459   } else if (x > y) {
    460     return ComparisonResult::kGreaterThan;
    461   } else {
    462     return ComparisonResult::kEqual;
    463   }
    464 }
    465 
    466 
    467 bool NumberEquals(double x, double y) {
    468   // Must check explicitly for NaN's on Windows, but -0 works fine.
    469   if (std::isnan(x)) return false;
    470   if (std::isnan(y)) return false;
    471   return x == y;
    472 }
    473 
    474 
    475 bool NumberEquals(const Object* x, const Object* y) {
    476   return NumberEquals(x->Number(), y->Number());
    477 }
    478 
    479 
    480 bool NumberEquals(Handle<Object> x, Handle<Object> y) {
    481   return NumberEquals(*x, *y);
    482 }
    483 
    484 }  // namespace
    485 
    486 
    487 // static
    488 Maybe<ComparisonResult> Object::Compare(Handle<Object> x, Handle<Object> y) {
    489   // ES6 section 7.2.11 Abstract Relational Comparison step 3 and 4.
    490   if (!Object::ToPrimitive(x, ToPrimitiveHint::kNumber).ToHandle(&x) ||
    491       !Object::ToPrimitive(y, ToPrimitiveHint::kNumber).ToHandle(&y)) {
    492     return Nothing<ComparisonResult>();
    493   }
    494   if (x->IsString() && y->IsString()) {
    495     // ES6 section 7.2.11 Abstract Relational Comparison step 5.
    496     return Just(
    497         String::Compare(Handle<String>::cast(x), Handle<String>::cast(y)));
    498   }
    499   // ES6 section 7.2.11 Abstract Relational Comparison step 6.
    500   if (!Object::ToNumber(x).ToHandle(&x) || !Object::ToNumber(y).ToHandle(&y)) {
    501     return Nothing<ComparisonResult>();
    502   }
    503   return Just(NumberCompare(x->Number(), y->Number()));
    504 }
    505 
    506 
    507 // static
    508 Maybe<bool> Object::Equals(Handle<Object> x, Handle<Object> y) {
    509   // This is the generic version of Abstract Equality Comparison; a version in
    510   // JavaScript land is available in the EqualStub and NotEqualStub. Whenever
    511   // you change something functionality wise in here, remember to update the
    512   // TurboFan code stubs as well.
    513   while (true) {
    514     if (x->IsNumber()) {
    515       if (y->IsNumber()) {
    516         return Just(NumberEquals(x, y));
    517       } else if (y->IsBoolean()) {
    518         return Just(NumberEquals(*x, Handle<Oddball>::cast(y)->to_number()));
    519       } else if (y->IsString()) {
    520         return Just(NumberEquals(x, String::ToNumber(Handle<String>::cast(y))));
    521       } else if (y->IsJSReceiver()) {
    522         if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(y))
    523                  .ToHandle(&y)) {
    524           return Nothing<bool>();
    525         }
    526       } else {
    527         return Just(false);
    528       }
    529     } else if (x->IsString()) {
    530       if (y->IsString()) {
    531         return Just(
    532             String::Equals(Handle<String>::cast(x), Handle<String>::cast(y)));
    533       } else if (y->IsNumber()) {
    534         x = String::ToNumber(Handle<String>::cast(x));
    535         return Just(NumberEquals(x, y));
    536       } else if (y->IsBoolean()) {
    537         x = String::ToNumber(Handle<String>::cast(x));
    538         return Just(NumberEquals(*x, Handle<Oddball>::cast(y)->to_number()));
    539       } else if (y->IsJSReceiver()) {
    540         if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(y))
    541                  .ToHandle(&y)) {
    542           return Nothing<bool>();
    543         }
    544       } else {
    545         return Just(false);
    546       }
    547     } else if (x->IsBoolean()) {
    548       if (y->IsOddball()) {
    549         return Just(x.is_identical_to(y));
    550       } else if (y->IsNumber()) {
    551         return Just(NumberEquals(Handle<Oddball>::cast(x)->to_number(), *y));
    552       } else if (y->IsString()) {
    553         y = String::ToNumber(Handle<String>::cast(y));
    554         return Just(NumberEquals(Handle<Oddball>::cast(x)->to_number(), *y));
    555       } else if (y->IsJSReceiver()) {
    556         if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(y))
    557                  .ToHandle(&y)) {
    558           return Nothing<bool>();
    559         }
    560         x = Oddball::ToNumber(Handle<Oddball>::cast(x));
    561       } else {
    562         return Just(false);
    563       }
    564     } else if (x->IsSymbol()) {
    565       if (y->IsSymbol()) {
    566         return Just(x.is_identical_to(y));
    567       } else if (y->IsJSReceiver()) {
    568         if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(y))
    569                  .ToHandle(&y)) {
    570           return Nothing<bool>();
    571         }
    572       } else {
    573         return Just(false);
    574       }
    575     } else if (x->IsJSReceiver()) {
    576       if (y->IsJSReceiver()) {
    577         return Just(x.is_identical_to(y));
    578       } else if (y->IsUndetectable()) {
    579         return Just(x->IsUndetectable());
    580       } else if (y->IsBoolean()) {
    581         y = Oddball::ToNumber(Handle<Oddball>::cast(y));
    582       } else if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(x))
    583                       .ToHandle(&x)) {
    584         return Nothing<bool>();
    585       }
    586     } else {
    587       return Just(x->IsUndetectable() && y->IsUndetectable());
    588     }
    589   }
    590 }
    591 
    592 
    593 bool Object::StrictEquals(Object* that) {
    594   if (this->IsNumber()) {
    595     if (!that->IsNumber()) return false;
    596     return NumberEquals(this, that);
    597   } else if (this->IsString()) {
    598     if (!that->IsString()) return false;
    599     return String::cast(this)->Equals(String::cast(that));
    600   }
    601   return this == that;
    602 }
    603 
    604 
    605 // static
    606 Handle<String> Object::TypeOf(Isolate* isolate, Handle<Object> object) {
    607   if (object->IsNumber()) return isolate->factory()->number_string();
    608   if (object->IsOddball()) return handle(Oddball::cast(*object)->type_of());
    609   if (object->IsUndetectable()) {
    610     return isolate->factory()->undefined_string();
    611   }
    612   if (object->IsString()) return isolate->factory()->string_string();
    613   if (object->IsSymbol()) return isolate->factory()->symbol_string();
    614   if (object->IsString()) return isolate->factory()->string_string();
    615   if (object->IsCallable()) return isolate->factory()->function_string();
    616   return isolate->factory()->object_string();
    617 }
    618 
    619 
    620 // static
    621 MaybeHandle<Object> Object::Multiply(Isolate* isolate, Handle<Object> lhs,
    622                                      Handle<Object> rhs) {
    623   if (!lhs->IsNumber() || !rhs->IsNumber()) {
    624     ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(lhs), Object);
    625     ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(rhs), Object);
    626   }
    627   return isolate->factory()->NewNumber(lhs->Number() * rhs->Number());
    628 }
    629 
    630 
    631 // static
    632 MaybeHandle<Object> Object::Divide(Isolate* isolate, Handle<Object> lhs,
    633                                    Handle<Object> rhs) {
    634   if (!lhs->IsNumber() || !rhs->IsNumber()) {
    635     ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(lhs), Object);
    636     ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(rhs), Object);
    637   }
    638   return isolate->factory()->NewNumber(lhs->Number() / rhs->Number());
    639 }
    640 
    641 
    642 // static
    643 MaybeHandle<Object> Object::Modulus(Isolate* isolate, Handle<Object> lhs,
    644                                     Handle<Object> rhs) {
    645   if (!lhs->IsNumber() || !rhs->IsNumber()) {
    646     ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(lhs), Object);
    647     ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(rhs), Object);
    648   }
    649   return isolate->factory()->NewNumber(modulo(lhs->Number(), rhs->Number()));
    650 }
    651 
    652 
    653 // static
    654 MaybeHandle<Object> Object::Add(Isolate* isolate, Handle<Object> lhs,
    655                                 Handle<Object> rhs) {
    656   if (lhs->IsNumber() && rhs->IsNumber()) {
    657     return isolate->factory()->NewNumber(lhs->Number() + rhs->Number());
    658   } else if (lhs->IsString() && rhs->IsString()) {
    659     return isolate->factory()->NewConsString(Handle<String>::cast(lhs),
    660                                              Handle<String>::cast(rhs));
    661   }
    662   ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToPrimitive(lhs), Object);
    663   ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToPrimitive(rhs), Object);
    664   if (lhs->IsString() || rhs->IsString()) {
    665     ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToString(isolate, rhs),
    666                                Object);
    667     ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToString(isolate, lhs),
    668                                Object);
    669     return isolate->factory()->NewConsString(Handle<String>::cast(lhs),
    670                                              Handle<String>::cast(rhs));
    671   }
    672   ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(rhs), Object);
    673   ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(lhs), Object);
    674   return isolate->factory()->NewNumber(lhs->Number() + rhs->Number());
    675 }
    676 
    677 
    678 // static
    679 MaybeHandle<Object> Object::Subtract(Isolate* isolate, Handle<Object> lhs,
    680                                      Handle<Object> rhs) {
    681   if (!lhs->IsNumber() || !rhs->IsNumber()) {
    682     ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(lhs), Object);
    683     ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(rhs), Object);
    684   }
    685   return isolate->factory()->NewNumber(lhs->Number() - rhs->Number());
    686 }
    687 
    688 
    689 // static
    690 MaybeHandle<Object> Object::ShiftLeft(Isolate* isolate, Handle<Object> lhs,
    691                                       Handle<Object> rhs) {
    692   if (!lhs->IsNumber() || !rhs->IsNumber()) {
    693     ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(lhs), Object);
    694     ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(rhs), Object);
    695   }
    696   return isolate->factory()->NewNumberFromInt(NumberToInt32(*lhs)
    697                                               << (NumberToUint32(*rhs) & 0x1F));
    698 }
    699 
    700 
    701 // static
    702 MaybeHandle<Object> Object::ShiftRight(Isolate* isolate, Handle<Object> lhs,
    703                                        Handle<Object> rhs) {
    704   if (!lhs->IsNumber() || !rhs->IsNumber()) {
    705     ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(lhs), Object);
    706     ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(rhs), Object);
    707   }
    708   return isolate->factory()->NewNumberFromInt(NumberToInt32(*lhs) >>
    709                                               (NumberToUint32(*rhs) & 0x1F));
    710 }
    711 
    712 
    713 // static
    714 MaybeHandle<Object> Object::ShiftRightLogical(Isolate* isolate,
    715                                               Handle<Object> lhs,
    716                                               Handle<Object> rhs) {
    717   if (!lhs->IsNumber() || !rhs->IsNumber()) {
    718     ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(lhs), Object);
    719     ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(rhs), Object);
    720   }
    721   return isolate->factory()->NewNumberFromUint(NumberToUint32(*lhs) >>
    722                                                (NumberToUint32(*rhs) & 0x1F));
    723 }
    724 
    725 
    726 // static
    727 MaybeHandle<Object> Object::BitwiseAnd(Isolate* isolate, Handle<Object> lhs,
    728                                        Handle<Object> rhs) {
    729   if (!lhs->IsNumber() || !rhs->IsNumber()) {
    730     ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(lhs), Object);
    731     ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(rhs), Object);
    732   }
    733   return isolate->factory()->NewNumberFromInt(NumberToInt32(*lhs) &
    734                                               NumberToInt32(*rhs));
    735 }
    736 
    737 
    738 // static
    739 MaybeHandle<Object> Object::BitwiseOr(Isolate* isolate, Handle<Object> lhs,
    740                                       Handle<Object> rhs) {
    741   if (!lhs->IsNumber() || !rhs->IsNumber()) {
    742     ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(lhs), Object);
    743     ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(rhs), Object);
    744   }
    745   return isolate->factory()->NewNumberFromInt(NumberToInt32(*lhs) |
    746                                               NumberToInt32(*rhs));
    747 }
    748 
    749 
    750 // static
    751 MaybeHandle<Object> Object::BitwiseXor(Isolate* isolate, Handle<Object> lhs,
    752                                        Handle<Object> rhs) {
    753   if (!lhs->IsNumber() || !rhs->IsNumber()) {
    754     ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(lhs), Object);
    755     ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(rhs), Object);
    756   }
    757   return isolate->factory()->NewNumberFromInt(NumberToInt32(*lhs) ^
    758                                               NumberToInt32(*rhs));
    759 }
    760 
    761 // static
    762 MaybeHandle<Object> Object::OrdinaryHasInstance(Isolate* isolate,
    763                                                 Handle<Object> callable,
    764                                                 Handle<Object> object) {
    765   // The {callable} must have a [[Call]] internal method.
    766   if (!callable->IsCallable()) return isolate->factory()->false_value();
    767 
    768   // Check if {callable} is a bound function, and if so retrieve its
    769   // [[BoundTargetFunction]] and use that instead of {callable}.
    770   if (callable->IsJSBoundFunction()) {
    771     Handle<Object> bound_callable(
    772         Handle<JSBoundFunction>::cast(callable)->bound_target_function(),
    773         isolate);
    774     return Object::InstanceOf(isolate, object, bound_callable);
    775   }
    776 
    777   // If {object} is not a receiver, return false.
    778   if (!object->IsJSReceiver()) return isolate->factory()->false_value();
    779 
    780   // Get the "prototype" of {callable}; raise an error if it's not a receiver.
    781   Handle<Object> prototype;
    782   ASSIGN_RETURN_ON_EXCEPTION(
    783       isolate, prototype,
    784       Object::GetProperty(callable, isolate->factory()->prototype_string()),
    785       Object);
    786   if (!prototype->IsJSReceiver()) {
    787     THROW_NEW_ERROR(
    788         isolate,
    789         NewTypeError(MessageTemplate::kInstanceofNonobjectProto, prototype),
    790         Object);
    791   }
    792 
    793   // Return whether or not {prototype} is in the prototype chain of {object}.
    794   Maybe<bool> result = JSReceiver::HasInPrototypeChain(
    795       isolate, Handle<JSReceiver>::cast(object), prototype);
    796   if (result.IsNothing()) return MaybeHandle<Object>();
    797   return isolate->factory()->ToBoolean(result.FromJust());
    798 }
    799 
    800 // static
    801 MaybeHandle<Object> Object::InstanceOf(Isolate* isolate, Handle<Object> object,
    802                                        Handle<Object> callable) {
    803   // The {callable} must be a receiver.
    804   if (!callable->IsJSReceiver()) {
    805     THROW_NEW_ERROR(isolate,
    806                     NewTypeError(MessageTemplate::kNonObjectInInstanceOfCheck),
    807                     Object);
    808   }
    809 
    810   // Lookup the @@hasInstance method on {callable}.
    811   Handle<Object> inst_of_handler;
    812   ASSIGN_RETURN_ON_EXCEPTION(
    813       isolate, inst_of_handler,
    814       JSReceiver::GetMethod(Handle<JSReceiver>::cast(callable),
    815                             isolate->factory()->has_instance_symbol()),
    816       Object);
    817   if (!inst_of_handler->IsUndefined(isolate)) {
    818     // Call the {inst_of_handler} on the {callable}.
    819     Handle<Object> result;
    820     ASSIGN_RETURN_ON_EXCEPTION(
    821         isolate, result,
    822         Execution::Call(isolate, inst_of_handler, callable, 1, &object),
    823         Object);
    824     return isolate->factory()->ToBoolean(result->BooleanValue());
    825   }
    826 
    827   // The {callable} must have a [[Call]] internal method.
    828   if (!callable->IsCallable()) {
    829     THROW_NEW_ERROR(
    830         isolate, NewTypeError(MessageTemplate::kNonCallableInInstanceOfCheck),
    831         Object);
    832   }
    833 
    834   // Fall back to OrdinaryHasInstance with {callable} and {object}.
    835   Handle<Object> result;
    836   ASSIGN_RETURN_ON_EXCEPTION(
    837       isolate, result,
    838       JSReceiver::OrdinaryHasInstance(isolate, callable, object), Object);
    839   return result;
    840 }
    841 
    842 Maybe<bool> Object::IsArray(Handle<Object> object) {
    843   if (object->IsJSArray()) return Just(true);
    844   if (object->IsJSProxy()) {
    845     Handle<JSProxy> proxy = Handle<JSProxy>::cast(object);
    846     Isolate* isolate = proxy->GetIsolate();
    847     if (proxy->IsRevoked()) {
    848       isolate->Throw(*isolate->factory()->NewTypeError(
    849           MessageTemplate::kProxyRevoked,
    850           isolate->factory()->NewStringFromAsciiChecked("IsArray")));
    851       return Nothing<bool>();
    852     }
    853     return Object::IsArray(handle(proxy->target(), isolate));
    854   }
    855   return Just(false);
    856 }
    857 
    858 
    859 // static
    860 MaybeHandle<Object> Object::GetMethod(Handle<JSReceiver> receiver,
    861                                       Handle<Name> name) {
    862   Handle<Object> func;
    863   Isolate* isolate = receiver->GetIsolate();
    864   ASSIGN_RETURN_ON_EXCEPTION(isolate, func,
    865                              JSReceiver::GetProperty(receiver, name), Object);
    866   if (func->IsNullOrUndefined(isolate)) {
    867     return isolate->factory()->undefined_value();
    868   }
    869   if (!func->IsCallable()) {
    870     THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kPropertyNotFunction,
    871                                           func, name, receiver),
    872                     Object);
    873   }
    874   return func;
    875 }
    876 
    877 namespace {
    878 MaybeHandle<FixedArray> CreateListFromArrayLikeFastPath(
    879     Isolate* isolate, Handle<Object> object, ElementTypes element_types) {
    880   if (element_types != ElementTypes::kAll || !object->IsJSArray()) {
    881     return MaybeHandle<FixedArray>();
    882   }
    883   Handle<JSArray> array = Handle<JSArray>::cast(object);
    884   uint32_t length;
    885   if (!array->HasArrayPrototype(isolate) ||
    886       !array->length()->ToUint32(&length) || !array->HasFastElements() ||
    887       !JSObject::PrototypeHasNoElements(isolate, *array)) {
    888     return MaybeHandle<FixedArray>();
    889   }
    890   return array->GetElementsAccessor()->CreateListFromArray(isolate, array);
    891 }
    892 }  // namespace
    893 
    894 // static
    895 MaybeHandle<FixedArray> Object::CreateListFromArrayLike(
    896     Isolate* isolate, Handle<Object> object, ElementTypes element_types) {
    897   // Fast-path for JS_ARRAY_TYPE.
    898   MaybeHandle<FixedArray> fast_result =
    899       CreateListFromArrayLikeFastPath(isolate, object, element_types);
    900   if (!fast_result.is_null()) return fast_result;
    901   // 1. ReturnIfAbrupt(object).
    902   // 2. (default elementTypes -- not applicable.)
    903   // 3. If Type(obj) is not Object, throw a TypeError exception.
    904   if (!object->IsJSReceiver()) {
    905     THROW_NEW_ERROR(isolate,
    906                     NewTypeError(MessageTemplate::kCalledOnNonObject,
    907                                  isolate->factory()->NewStringFromAsciiChecked(
    908                                      "CreateListFromArrayLike")),
    909                     FixedArray);
    910   }
    911 
    912   // 4. Let len be ? ToLength(? Get(obj, "length")).
    913   Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(object);
    914   Handle<Object> raw_length_number;
    915   ASSIGN_RETURN_ON_EXCEPTION(isolate, raw_length_number,
    916                              Object::GetLengthFromArrayLike(isolate, receiver),
    917                              FixedArray);
    918   uint32_t len;
    919   if (!raw_length_number->ToUint32(&len) ||
    920       len > static_cast<uint32_t>(FixedArray::kMaxLength)) {
    921     THROW_NEW_ERROR(isolate,
    922                     NewRangeError(MessageTemplate::kInvalidArrayLength),
    923                     FixedArray);
    924   }
    925   // 5. Let list be an empty List.
    926   Handle<FixedArray> list = isolate->factory()->NewFixedArray(len);
    927   // 6. Let index be 0.
    928   // 7. Repeat while index < len:
    929   for (uint32_t index = 0; index < len; ++index) {
    930     // 7a. Let indexName be ToString(index).
    931     // 7b. Let next be ? Get(obj, indexName).
    932     Handle<Object> next;
    933     ASSIGN_RETURN_ON_EXCEPTION(isolate, next,
    934                                JSReceiver::GetElement(isolate, receiver, index),
    935                                FixedArray);
    936     switch (element_types) {
    937       case ElementTypes::kAll:
    938         // Nothing to do.
    939         break;
    940       case ElementTypes::kStringAndSymbol: {
    941         // 7c. If Type(next) is not an element of elementTypes, throw a
    942         //     TypeError exception.
    943         if (!next->IsName()) {
    944           THROW_NEW_ERROR(isolate,
    945                           NewTypeError(MessageTemplate::kNotPropertyName, next),
    946                           FixedArray);
    947         }
    948         // 7d. Append next as the last element of list.
    949         // Internalize on the fly so we can use pointer identity later.
    950         next = isolate->factory()->InternalizeName(Handle<Name>::cast(next));
    951         break;
    952       }
    953     }
    954     list->set(index, *next);
    955     // 7e. Set index to index + 1. (See loop header.)
    956   }
    957   // 8. Return list.
    958   return list;
    959 }
    960 
    961 
    962 // static
    963 MaybeHandle<Object> Object::GetLengthFromArrayLike(Isolate* isolate,
    964                                                    Handle<Object> object) {
    965   Handle<Object> val;
    966   Handle<Object> key = isolate->factory()->length_string();
    967   ASSIGN_RETURN_ON_EXCEPTION(
    968       isolate, val, Runtime::GetObjectProperty(isolate, object, key), Object);
    969   return Object::ToLength(isolate, val);
    970 }
    971 
    972 // static
    973 Maybe<bool> JSReceiver::HasProperty(LookupIterator* it) {
    974   for (; it->IsFound(); it->Next()) {
    975     switch (it->state()) {
    976       case LookupIterator::NOT_FOUND:
    977       case LookupIterator::TRANSITION:
    978         UNREACHABLE();
    979       case LookupIterator::JSPROXY:
    980         return JSProxy::HasProperty(it->isolate(), it->GetHolder<JSProxy>(),
    981                                     it->GetName());
    982       case LookupIterator::INTERCEPTOR: {
    983         Maybe<PropertyAttributes> result =
    984             JSObject::GetPropertyAttributesWithInterceptor(it);
    985         if (result.IsNothing()) return Nothing<bool>();
    986         if (result.FromJust() != ABSENT) return Just(true);
    987         break;
    988       }
    989       case LookupIterator::ACCESS_CHECK: {
    990         if (it->HasAccess()) break;
    991         Maybe<PropertyAttributes> result =
    992             JSObject::GetPropertyAttributesWithFailedAccessCheck(it);
    993         if (result.IsNothing()) return Nothing<bool>();
    994         return Just(result.FromJust() != ABSENT);
    995       }
    996       case LookupIterator::INTEGER_INDEXED_EXOTIC:
    997         // TypedArray out-of-bounds access.
    998         return Just(false);
    999       case LookupIterator::ACCESSOR:
   1000       case LookupIterator::DATA:
   1001         return Just(true);
   1002     }
   1003   }
   1004   return Just(false);
   1005 }
   1006 
   1007 
   1008 // static
   1009 MaybeHandle<Object> Object::GetProperty(LookupIterator* it) {
   1010   for (; it->IsFound(); it->Next()) {
   1011     switch (it->state()) {
   1012       case LookupIterator::NOT_FOUND:
   1013       case LookupIterator::TRANSITION:
   1014         UNREACHABLE();
   1015       case LookupIterator::JSPROXY: {
   1016         bool was_found;
   1017         MaybeHandle<Object> result =
   1018             JSProxy::GetProperty(it->isolate(), it->GetHolder<JSProxy>(),
   1019                                  it->GetName(), it->GetReceiver(), &was_found);
   1020         if (!was_found) it->NotFound();
   1021         return result;
   1022       }
   1023       case LookupIterator::INTERCEPTOR: {
   1024         bool done;
   1025         Handle<Object> result;
   1026         ASSIGN_RETURN_ON_EXCEPTION(
   1027             it->isolate(), result,
   1028             JSObject::GetPropertyWithInterceptor(it, &done), Object);
   1029         if (done) return result;
   1030         break;
   1031       }
   1032       case LookupIterator::ACCESS_CHECK:
   1033         if (it->HasAccess()) break;
   1034         return JSObject::GetPropertyWithFailedAccessCheck(it);
   1035       case LookupIterator::ACCESSOR:
   1036         return GetPropertyWithAccessor(it);
   1037       case LookupIterator::INTEGER_INDEXED_EXOTIC:
   1038         return it->isolate()->factory()->undefined_value();
   1039       case LookupIterator::DATA:
   1040         return it->GetDataValue();
   1041     }
   1042   }
   1043   return it->isolate()->factory()->undefined_value();
   1044 }
   1045 
   1046 
   1047 // static
   1048 MaybeHandle<Object> JSProxy::GetProperty(Isolate* isolate,
   1049                                          Handle<JSProxy> proxy,
   1050                                          Handle<Name> name,
   1051                                          Handle<Object> receiver,
   1052                                          bool* was_found) {
   1053   *was_found = true;
   1054   if (receiver->IsJSGlobalObject()) {
   1055     THROW_NEW_ERROR(
   1056         isolate,
   1057         NewTypeError(MessageTemplate::kReadGlobalReferenceThroughProxy, name),
   1058         Object);
   1059   }
   1060 
   1061   DCHECK(!name->IsPrivate());
   1062   STACK_CHECK(isolate, MaybeHandle<Object>());
   1063   Handle<Name> trap_name = isolate->factory()->get_string();
   1064   // 1. Assert: IsPropertyKey(P) is true.
   1065   // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O.
   1066   Handle<Object> handler(proxy->handler(), isolate);
   1067   // 3. If handler is null, throw a TypeError exception.
   1068   // 4. Assert: Type(handler) is Object.
   1069   if (proxy->IsRevoked()) {
   1070     THROW_NEW_ERROR(isolate,
   1071                     NewTypeError(MessageTemplate::kProxyRevoked, trap_name),
   1072                     Object);
   1073   }
   1074   // 5. Let target be the value of the [[ProxyTarget]] internal slot of O.
   1075   Handle<JSReceiver> target(proxy->target(), isolate);
   1076   // 6. Let trap be ? GetMethod(handler, "get").
   1077   Handle<Object> trap;
   1078   ASSIGN_RETURN_ON_EXCEPTION(
   1079       isolate, trap,
   1080       Object::GetMethod(Handle<JSReceiver>::cast(handler), trap_name), Object);
   1081   // 7. If trap is undefined, then
   1082   if (trap->IsUndefined(isolate)) {
   1083     // 7.a Return target.[[Get]](P, Receiver).
   1084     LookupIterator it =
   1085         LookupIterator::PropertyOrElement(isolate, receiver, name, target);
   1086     MaybeHandle<Object> result = Object::GetProperty(&it);
   1087     *was_found = it.IsFound();
   1088     return result;
   1089   }
   1090   // 8. Let trapResult be ? Call(trap, handler, target, P, Receiver).
   1091   Handle<Object> trap_result;
   1092   Handle<Object> args[] = {target, name, receiver};
   1093   ASSIGN_RETURN_ON_EXCEPTION(
   1094       isolate, trap_result,
   1095       Execution::Call(isolate, trap, handler, arraysize(args), args), Object);
   1096   // 9. Let targetDesc be ? target.[[GetOwnProperty]](P).
   1097   PropertyDescriptor target_desc;
   1098   Maybe<bool> target_found =
   1099       JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, &target_desc);
   1100   MAYBE_RETURN_NULL(target_found);
   1101   // 10. If targetDesc is not undefined, then
   1102   if (target_found.FromJust()) {
   1103     // 10.a. If IsDataDescriptor(targetDesc) and targetDesc.[[Configurable]] is
   1104     //       false and targetDesc.[[Writable]] is false, then
   1105     // 10.a.i. If SameValue(trapResult, targetDesc.[[Value]]) is false,
   1106     //        throw a TypeError exception.
   1107     bool inconsistent = PropertyDescriptor::IsDataDescriptor(&target_desc) &&
   1108                         !target_desc.configurable() &&
   1109                         !target_desc.writable() &&
   1110                         !trap_result->SameValue(*target_desc.value());
   1111     if (inconsistent) {
   1112       THROW_NEW_ERROR(
   1113           isolate, NewTypeError(MessageTemplate::kProxyGetNonConfigurableData,
   1114                                 name, target_desc.value(), trap_result),
   1115           Object);
   1116     }
   1117     // 10.b. If IsAccessorDescriptor(targetDesc) and targetDesc.[[Configurable]]
   1118     //       is false and targetDesc.[[Get]] is undefined, then
   1119     // 10.b.i. If trapResult is not undefined, throw a TypeError exception.
   1120     inconsistent = PropertyDescriptor::IsAccessorDescriptor(&target_desc) &&
   1121                    !target_desc.configurable() &&
   1122                    target_desc.get()->IsUndefined(isolate) &&
   1123                    !trap_result->IsUndefined(isolate);
   1124     if (inconsistent) {
   1125       THROW_NEW_ERROR(
   1126           isolate,
   1127           NewTypeError(MessageTemplate::kProxyGetNonConfigurableAccessor, name,
   1128                        trap_result),
   1129           Object);
   1130     }
   1131   }
   1132   // 11. Return trap_result
   1133   return trap_result;
   1134 }
   1135 
   1136 
   1137 Handle<Object> JSReceiver::GetDataProperty(LookupIterator* it) {
   1138   for (; it->IsFound(); it->Next()) {
   1139     switch (it->state()) {
   1140       case LookupIterator::INTERCEPTOR:
   1141       case LookupIterator::NOT_FOUND:
   1142       case LookupIterator::TRANSITION:
   1143         UNREACHABLE();
   1144       case LookupIterator::ACCESS_CHECK:
   1145         // Support calling this method without an active context, but refuse
   1146         // access to access-checked objects in that case.
   1147         if (it->isolate()->context() != nullptr && it->HasAccess()) continue;
   1148       // Fall through.
   1149       case LookupIterator::JSPROXY:
   1150         it->NotFound();
   1151         return it->isolate()->factory()->undefined_value();
   1152       case LookupIterator::ACCESSOR:
   1153         // TODO(verwaest): For now this doesn't call into AccessorInfo, since
   1154         // clients don't need it. Update once relevant.
   1155         it->NotFound();
   1156         return it->isolate()->factory()->undefined_value();
   1157       case LookupIterator::INTEGER_INDEXED_EXOTIC:
   1158         return it->isolate()->factory()->undefined_value();
   1159       case LookupIterator::DATA:
   1160         return it->GetDataValue();
   1161     }
   1162   }
   1163   return it->isolate()->factory()->undefined_value();
   1164 }
   1165 
   1166 
   1167 bool Object::ToInt32(int32_t* value) {
   1168   if (IsSmi()) {
   1169     *value = Smi::cast(this)->value();
   1170     return true;
   1171   }
   1172   if (IsHeapNumber()) {
   1173     double num = HeapNumber::cast(this)->value();
   1174     if (FastI2D(FastD2I(num)) == num) {
   1175       *value = FastD2I(num);
   1176       return true;
   1177     }
   1178   }
   1179   return false;
   1180 }
   1181 
   1182 Handle<SharedFunctionInfo> FunctionTemplateInfo::GetOrCreateSharedFunctionInfo(
   1183     Isolate* isolate, Handle<FunctionTemplateInfo> info) {
   1184   Object* current_info = info->shared_function_info();
   1185   if (current_info->IsSharedFunctionInfo()) {
   1186     return handle(SharedFunctionInfo::cast(current_info), isolate);
   1187   }
   1188 
   1189   Handle<Object> class_name(info->class_name(), isolate);
   1190   Handle<String> name = class_name->IsString()
   1191                             ? Handle<String>::cast(class_name)
   1192                             : isolate->factory()->empty_string();
   1193   Handle<Code> code;
   1194   if (info->call_code()->IsCallHandlerInfo() &&
   1195       CallHandlerInfo::cast(info->call_code())->fast_handler()->IsCode()) {
   1196     code = isolate->builtins()->HandleFastApiCall();
   1197   } else {
   1198     code = isolate->builtins()->HandleApiCall();
   1199   }
   1200   bool is_constructor = !info->remove_prototype();
   1201   Handle<SharedFunctionInfo> result =
   1202       isolate->factory()->NewSharedFunctionInfo(name, code, is_constructor);
   1203   if (is_constructor) {
   1204     result->SetConstructStub(*isolate->builtins()->JSConstructStubApi());
   1205   }
   1206 
   1207   result->set_length(info->length());
   1208   if (class_name->IsString()) result->set_instance_class_name(*class_name);
   1209   result->set_api_func_data(*info);
   1210   result->DontAdaptArguments();
   1211   DCHECK(result->IsApiFunction());
   1212 
   1213   info->set_shared_function_info(*result);
   1214   return result;
   1215 }
   1216 
   1217 bool FunctionTemplateInfo::IsTemplateFor(Map* map) {
   1218   // There is a constraint on the object; check.
   1219   if (!map->IsJSObjectMap()) return false;
   1220   // Fetch the constructor function of the object.
   1221   Object* cons_obj = map->GetConstructor();
   1222   if (!cons_obj->IsJSFunction()) return false;
   1223   JSFunction* fun = JSFunction::cast(cons_obj);
   1224   // Iterate through the chain of inheriting function templates to
   1225   // see if the required one occurs.
   1226   for (Object* type = fun->shared()->function_data();
   1227        type->IsFunctionTemplateInfo();
   1228        type = FunctionTemplateInfo::cast(type)->parent_template()) {
   1229     if (type == this) return true;
   1230   }
   1231   // Didn't find the required type in the inheritance chain.
   1232   return false;
   1233 }
   1234 
   1235 
   1236 // static
   1237 Handle<TemplateList> TemplateList::New(Isolate* isolate, int size) {
   1238   Handle<FixedArray> list =
   1239       isolate->factory()->NewFixedArray(kLengthIndex + size);
   1240   list->set(kLengthIndex, Smi::kZero);
   1241   return Handle<TemplateList>::cast(list);
   1242 }
   1243 
   1244 // static
   1245 Handle<TemplateList> TemplateList::Add(Isolate* isolate,
   1246                                        Handle<TemplateList> list,
   1247                                        Handle<i::Object> value) {
   1248   STATIC_ASSERT(kFirstElementIndex == 1);
   1249   int index = list->length() + 1;
   1250   Handle<i::FixedArray> fixed_array = Handle<FixedArray>::cast(list);
   1251   fixed_array = FixedArray::SetAndGrow(fixed_array, index, value);
   1252   fixed_array->set(kLengthIndex, Smi::FromInt(index));
   1253   return Handle<TemplateList>::cast(fixed_array);
   1254 }
   1255 
   1256 // static
   1257 MaybeHandle<JSObject> JSObject::New(Handle<JSFunction> constructor,
   1258                                     Handle<JSReceiver> new_target,
   1259                                     Handle<AllocationSite> site) {
   1260   // If called through new, new.target can be:
   1261   // - a subclass of constructor,
   1262   // - a proxy wrapper around constructor, or
   1263   // - the constructor itself.
   1264   // If called through Reflect.construct, it's guaranteed to be a constructor.
   1265   Isolate* const isolate = constructor->GetIsolate();
   1266   DCHECK(constructor->IsConstructor());
   1267   DCHECK(new_target->IsConstructor());
   1268   DCHECK(!constructor->has_initial_map() ||
   1269          constructor->initial_map()->instance_type() != JS_FUNCTION_TYPE);
   1270 
   1271   Handle<Map> initial_map;
   1272   ASSIGN_RETURN_ON_EXCEPTION(
   1273       isolate, initial_map,
   1274       JSFunction::GetDerivedMap(isolate, constructor, new_target), JSObject);
   1275   Handle<JSObject> result =
   1276       isolate->factory()->NewJSObjectFromMap(initial_map, NOT_TENURED, site);
   1277   isolate->counters()->constructed_objects()->Increment();
   1278   isolate->counters()->constructed_objects_runtime()->Increment();
   1279   return result;
   1280 }
   1281 
   1282 void JSObject::EnsureWritableFastElements(Handle<JSObject> object) {
   1283   DCHECK(object->HasFastSmiOrObjectElements() ||
   1284          object->HasFastStringWrapperElements());
   1285   FixedArray* raw_elems = FixedArray::cast(object->elements());
   1286   Heap* heap = object->GetHeap();
   1287   if (raw_elems->map() != heap->fixed_cow_array_map()) return;
   1288   Isolate* isolate = heap->isolate();
   1289   Handle<FixedArray> elems(raw_elems, isolate);
   1290   Handle<FixedArray> writable_elems = isolate->factory()->CopyFixedArrayWithMap(
   1291       elems, isolate->factory()->fixed_array_map());
   1292   object->set_elements(*writable_elems);
   1293   isolate->counters()->cow_arrays_converted()->Increment();
   1294 }
   1295 
   1296 
   1297 // ES6 9.5.1
   1298 // static
   1299 MaybeHandle<Object> JSProxy::GetPrototype(Handle<JSProxy> proxy) {
   1300   Isolate* isolate = proxy->GetIsolate();
   1301   Handle<String> trap_name = isolate->factory()->getPrototypeOf_string();
   1302 
   1303   STACK_CHECK(isolate, MaybeHandle<Object>());
   1304 
   1305   // 1. Let handler be the value of the [[ProxyHandler]] internal slot.
   1306   // 2. If handler is null, throw a TypeError exception.
   1307   // 3. Assert: Type(handler) is Object.
   1308   // 4. Let target be the value of the [[ProxyTarget]] internal slot.
   1309   if (proxy->IsRevoked()) {
   1310     THROW_NEW_ERROR(isolate,
   1311                     NewTypeError(MessageTemplate::kProxyRevoked, trap_name),
   1312                     Object);
   1313   }
   1314   Handle<JSReceiver> target(proxy->target(), isolate);
   1315   Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate);
   1316 
   1317   // 5. Let trap be ? GetMethod(handler, "getPrototypeOf").
   1318   Handle<Object> trap;
   1319   ASSIGN_RETURN_ON_EXCEPTION(isolate, trap, GetMethod(handler, trap_name),
   1320                              Object);
   1321   // 6. If trap is undefined, then return target.[[GetPrototypeOf]]().
   1322   if (trap->IsUndefined(isolate)) {
   1323     return JSReceiver::GetPrototype(isolate, target);
   1324   }
   1325   // 7. Let handlerProto be ? Call(trap, handler, target).
   1326   Handle<Object> argv[] = {target};
   1327   Handle<Object> handler_proto;
   1328   ASSIGN_RETURN_ON_EXCEPTION(
   1329       isolate, handler_proto,
   1330       Execution::Call(isolate, trap, handler, arraysize(argv), argv), Object);
   1331   // 8. If Type(handlerProto) is neither Object nor Null, throw a TypeError.
   1332   if (!(handler_proto->IsJSReceiver() || handler_proto->IsNull(isolate))) {
   1333     THROW_NEW_ERROR(isolate,
   1334                     NewTypeError(MessageTemplate::kProxyGetPrototypeOfInvalid),
   1335                     Object);
   1336   }
   1337   // 9. Let extensibleTarget be ? IsExtensible(target).
   1338   Maybe<bool> is_extensible = JSReceiver::IsExtensible(target);
   1339   MAYBE_RETURN_NULL(is_extensible);
   1340   // 10. If extensibleTarget is true, return handlerProto.
   1341   if (is_extensible.FromJust()) return handler_proto;
   1342   // 11. Let targetProto be ? target.[[GetPrototypeOf]]().
   1343   Handle<Object> target_proto;
   1344   ASSIGN_RETURN_ON_EXCEPTION(isolate, target_proto,
   1345                              JSReceiver::GetPrototype(isolate, target), Object);
   1346   // 12. If SameValue(handlerProto, targetProto) is false, throw a TypeError.
   1347   if (!handler_proto->SameValue(*target_proto)) {
   1348     THROW_NEW_ERROR(
   1349         isolate,
   1350         NewTypeError(MessageTemplate::kProxyGetPrototypeOfNonExtensible),
   1351         Object);
   1352   }
   1353   // 13. Return handlerProto.
   1354   return handler_proto;
   1355 }
   1356 
   1357 MaybeHandle<Object> Object::GetPropertyWithAccessor(LookupIterator* it) {
   1358   Isolate* isolate = it->isolate();
   1359   Handle<Object> structure = it->GetAccessors();
   1360   Handle<Object> receiver = it->GetReceiver();
   1361 
   1362   // We should never get here to initialize a const with the hole value since a
   1363   // const declaration would conflict with the getter.
   1364   DCHECK(!structure->IsForeign());
   1365 
   1366   // API style callbacks.
   1367   if (structure->IsAccessorInfo()) {
   1368     Handle<JSObject> holder = it->GetHolder<JSObject>();
   1369     Handle<Name> name = it->GetName();
   1370     Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(structure);
   1371     if (!info->IsCompatibleReceiver(*receiver)) {
   1372       THROW_NEW_ERROR(isolate,
   1373                       NewTypeError(MessageTemplate::kIncompatibleMethodReceiver,
   1374                                    name, receiver),
   1375                       Object);
   1376     }
   1377 
   1378     v8::AccessorNameGetterCallback call_fun =
   1379         v8::ToCData<v8::AccessorNameGetterCallback>(info->getter());
   1380     if (call_fun == nullptr) return isolate->factory()->undefined_value();
   1381 
   1382     if (info->is_sloppy() && !receiver->IsJSReceiver()) {
   1383       ASSIGN_RETURN_ON_EXCEPTION(isolate, receiver,
   1384                                  Object::ConvertReceiver(isolate, receiver),
   1385                                  Object);
   1386     }
   1387 
   1388     PropertyCallbackArguments args(isolate, info->data(), *receiver, *holder,
   1389                                    Object::DONT_THROW);
   1390     Handle<Object> result = args.Call(call_fun, name);
   1391     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
   1392     if (result.is_null()) return isolate->factory()->undefined_value();
   1393     Handle<Object> reboxed_result = handle(*result, isolate);
   1394     if (info->replace_on_access() && receiver->IsJSReceiver()) {
   1395       args.Call(reinterpret_cast<GenericNamedPropertySetterCallback>(
   1396                     &Accessors::ReconfigureToDataProperty),
   1397                 name, result);
   1398       RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
   1399     }
   1400     return reboxed_result;
   1401   }
   1402 
   1403   // AccessorPair with 'cached' private property.
   1404   if (it->TryLookupCachedProperty()) {
   1405     return Object::GetProperty(it);
   1406   }
   1407 
   1408   // Regular accessor.
   1409   Handle<Object> getter(AccessorPair::cast(*structure)->getter(), isolate);
   1410   if (getter->IsFunctionTemplateInfo()) {
   1411     return Builtins::InvokeApiFunction(
   1412         isolate, false, Handle<FunctionTemplateInfo>::cast(getter), receiver, 0,
   1413         nullptr, isolate->factory()->undefined_value());
   1414   } else if (getter->IsCallable()) {
   1415     // TODO(rossberg): nicer would be to cast to some JSCallable here...
   1416     return Object::GetPropertyWithDefinedGetter(
   1417         receiver, Handle<JSReceiver>::cast(getter));
   1418   }
   1419   // Getter is not a function.
   1420   return isolate->factory()->undefined_value();
   1421 }
   1422 
   1423 // static
   1424 Address AccessorInfo::redirect(Isolate* isolate, Address address,
   1425                                AccessorComponent component) {
   1426   ApiFunction fun(address);
   1427   DCHECK_EQ(ACCESSOR_GETTER, component);
   1428   ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL;
   1429   return ExternalReference(&fun, type, isolate).address();
   1430 }
   1431 
   1432 Address AccessorInfo::redirected_getter() const {
   1433   Address accessor = v8::ToCData<Address>(getter());
   1434   if (accessor == nullptr) return nullptr;
   1435   return redirect(GetIsolate(), accessor, ACCESSOR_GETTER);
   1436 }
   1437 
   1438 bool AccessorInfo::IsCompatibleReceiverMap(Isolate* isolate,
   1439                                            Handle<AccessorInfo> info,
   1440                                            Handle<Map> map) {
   1441   if (!info->HasExpectedReceiverType()) return true;
   1442   if (!map->IsJSObjectMap()) return false;
   1443   return FunctionTemplateInfo::cast(info->expected_receiver_type())
   1444       ->IsTemplateFor(*map);
   1445 }
   1446 
   1447 Maybe<bool> Object::SetPropertyWithAccessor(LookupIterator* it,
   1448                                             Handle<Object> value,
   1449                                             ShouldThrow should_throw) {
   1450   Isolate* isolate = it->isolate();
   1451   Handle<Object> structure = it->GetAccessors();
   1452   Handle<Object> receiver = it->GetReceiver();
   1453 
   1454   // We should never get here to initialize a const with the hole value since a
   1455   // const declaration would conflict with the setter.
   1456   DCHECK(!structure->IsForeign());
   1457 
   1458   // API style callbacks.
   1459   if (structure->IsAccessorInfo()) {
   1460     Handle<JSObject> holder = it->GetHolder<JSObject>();
   1461     Handle<Name> name = it->GetName();
   1462     Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(structure);
   1463     if (!info->IsCompatibleReceiver(*receiver)) {
   1464       isolate->Throw(*isolate->factory()->NewTypeError(
   1465           MessageTemplate::kIncompatibleMethodReceiver, name, receiver));
   1466       return Nothing<bool>();
   1467     }
   1468 
   1469     // The actual type of call_fun is either v8::AccessorNameSetterCallback or
   1470     // i::Accesors::AccessorNameBooleanSetterCallback, depending on whether the
   1471     // AccessorInfo was created by the API or internally (see accessors.cc).
   1472     // Here we handle both cases using GenericNamedPropertySetterCallback and
   1473     // its Call method.
   1474     GenericNamedPropertySetterCallback call_fun =
   1475         v8::ToCData<GenericNamedPropertySetterCallback>(info->setter());
   1476 
   1477     if (call_fun == nullptr) {
   1478       // TODO(verwaest): We should not get here anymore once all AccessorInfos
   1479       // are marked as special_data_property. They cannot both be writable and
   1480       // not have a setter.
   1481       return Just(true);
   1482     }
   1483 
   1484     if (info->is_sloppy() && !receiver->IsJSReceiver()) {
   1485       ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   1486           isolate, receiver, Object::ConvertReceiver(isolate, receiver),
   1487           Nothing<bool>());
   1488     }
   1489 
   1490     PropertyCallbackArguments args(isolate, info->data(), *receiver, *holder,
   1491                                    should_throw);
   1492     Handle<Object> result = args.Call(call_fun, name, value);
   1493     // In the case of AccessorNameSetterCallback, we know that the result value
   1494     // cannot have been set, so the result of Call will be null.  In the case of
   1495     // AccessorNameBooleanSetterCallback, the result will either be null
   1496     // (signalling an exception) or a boolean Oddball.
   1497     RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
   1498     if (result.is_null()) return Just(true);
   1499     DCHECK(result->BooleanValue() || should_throw == DONT_THROW);
   1500     return Just(result->BooleanValue());
   1501   }
   1502 
   1503   // Regular accessor.
   1504   Handle<Object> setter(AccessorPair::cast(*structure)->setter(), isolate);
   1505   if (setter->IsFunctionTemplateInfo()) {
   1506     Handle<Object> argv[] = {value};
   1507     RETURN_ON_EXCEPTION_VALUE(
   1508         isolate, Builtins::InvokeApiFunction(
   1509                      isolate, false, Handle<FunctionTemplateInfo>::cast(setter),
   1510                      receiver, arraysize(argv), argv,
   1511                      isolate->factory()->undefined_value()),
   1512         Nothing<bool>());
   1513     return Just(true);
   1514   } else if (setter->IsCallable()) {
   1515     // TODO(rossberg): nicer would be to cast to some JSCallable here...
   1516     return SetPropertyWithDefinedSetter(
   1517         receiver, Handle<JSReceiver>::cast(setter), value, should_throw);
   1518   }
   1519 
   1520   RETURN_FAILURE(isolate, should_throw,
   1521                  NewTypeError(MessageTemplate::kNoSetterInCallback,
   1522                               it->GetName(), it->GetHolder<JSObject>()));
   1523 }
   1524 
   1525 
   1526 MaybeHandle<Object> Object::GetPropertyWithDefinedGetter(
   1527     Handle<Object> receiver,
   1528     Handle<JSReceiver> getter) {
   1529   Isolate* isolate = getter->GetIsolate();
   1530 
   1531   // Platforms with simulators like arm/arm64 expose a funny issue. If the
   1532   // simulator has a separate JS stack pointer from the C++ stack pointer, it
   1533   // can miss C++ stack overflows in the stack guard at the start of JavaScript
   1534   // functions. It would be very expensive to check the C++ stack pointer at
   1535   // that location. The best solution seems to be to break the impasse by
   1536   // adding checks at possible recursion points. What's more, we don't put
   1537   // this stack check behind the USE_SIMULATOR define in order to keep
   1538   // behavior the same between hardware and simulators.
   1539   StackLimitCheck check(isolate);
   1540   if (check.JsHasOverflowed()) {
   1541     isolate->StackOverflow();
   1542     return MaybeHandle<Object>();
   1543   }
   1544 
   1545   return Execution::Call(isolate, getter, receiver, 0, NULL);
   1546 }
   1547 
   1548 
   1549 Maybe<bool> Object::SetPropertyWithDefinedSetter(Handle<Object> receiver,
   1550                                                  Handle<JSReceiver> setter,
   1551                                                  Handle<Object> value,
   1552                                                  ShouldThrow should_throw) {
   1553   Isolate* isolate = setter->GetIsolate();
   1554 
   1555   Handle<Object> argv[] = { value };
   1556   RETURN_ON_EXCEPTION_VALUE(isolate, Execution::Call(isolate, setter, receiver,
   1557                                                      arraysize(argv), argv),
   1558                             Nothing<bool>());
   1559   return Just(true);
   1560 }
   1561 
   1562 
   1563 // static
   1564 bool JSObject::AllCanRead(LookupIterator* it) {
   1565   // Skip current iteration, it's in state ACCESS_CHECK or INTERCEPTOR, both of
   1566   // which have already been checked.
   1567   DCHECK(it->state() == LookupIterator::ACCESS_CHECK ||
   1568          it->state() == LookupIterator::INTERCEPTOR);
   1569   for (it->Next(); it->IsFound(); it->Next()) {
   1570     if (it->state() == LookupIterator::ACCESSOR) {
   1571       auto accessors = it->GetAccessors();
   1572       if (accessors->IsAccessorInfo()) {
   1573         if (AccessorInfo::cast(*accessors)->all_can_read()) return true;
   1574       }
   1575     } else if (it->state() == LookupIterator::INTERCEPTOR) {
   1576       if (it->GetInterceptor()->all_can_read()) return true;
   1577     } else if (it->state() == LookupIterator::JSPROXY) {
   1578       // Stop lookupiterating. And no, AllCanNotRead.
   1579       return false;
   1580     }
   1581   }
   1582   return false;
   1583 }
   1584 
   1585 namespace {
   1586 
   1587 MaybeHandle<Object> GetPropertyWithInterceptorInternal(
   1588     LookupIterator* it, Handle<InterceptorInfo> interceptor, bool* done) {
   1589   *done = false;
   1590   Isolate* isolate = it->isolate();
   1591   // Make sure that the top context does not change when doing callbacks or
   1592   // interceptor calls.
   1593   AssertNoContextChange ncc(isolate);
   1594 
   1595   if (interceptor->getter()->IsUndefined(isolate)) {
   1596     return isolate->factory()->undefined_value();
   1597   }
   1598 
   1599   Handle<JSObject> holder = it->GetHolder<JSObject>();
   1600   Handle<Object> result;
   1601   Handle<Object> receiver = it->GetReceiver();
   1602   if (!receiver->IsJSReceiver()) {
   1603     ASSIGN_RETURN_ON_EXCEPTION(
   1604         isolate, receiver, Object::ConvertReceiver(isolate, receiver), Object);
   1605   }
   1606   PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
   1607                                  *holder, Object::DONT_THROW);
   1608 
   1609   if (it->IsElement()) {
   1610     uint32_t index = it->index();
   1611     v8::IndexedPropertyGetterCallback getter =
   1612         v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter());
   1613     result = args.Call(getter, index);
   1614   } else {
   1615     Handle<Name> name = it->name();
   1616     DCHECK(!name->IsPrivate());
   1617 
   1618     if (name->IsSymbol() && !interceptor->can_intercept_symbols()) {
   1619       return isolate->factory()->undefined_value();
   1620     }
   1621 
   1622     v8::GenericNamedPropertyGetterCallback getter =
   1623         v8::ToCData<v8::GenericNamedPropertyGetterCallback>(
   1624             interceptor->getter());
   1625     result = args.Call(getter, name);
   1626   }
   1627 
   1628   RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
   1629   if (result.is_null()) return isolate->factory()->undefined_value();
   1630   *done = true;
   1631   // Rebox handle before return
   1632   return handle(*result, isolate);
   1633 }
   1634 
   1635 Maybe<PropertyAttributes> GetPropertyAttributesWithInterceptorInternal(
   1636     LookupIterator* it, Handle<InterceptorInfo> interceptor) {
   1637   Isolate* isolate = it->isolate();
   1638   // Make sure that the top context does not change when doing
   1639   // callbacks or interceptor calls.
   1640   AssertNoContextChange ncc(isolate);
   1641   HandleScope scope(isolate);
   1642 
   1643   Handle<JSObject> holder = it->GetHolder<JSObject>();
   1644   if (!it->IsElement() && it->name()->IsSymbol() &&
   1645       !interceptor->can_intercept_symbols()) {
   1646     return Just(ABSENT);
   1647   }
   1648   Handle<Object> receiver = it->GetReceiver();
   1649   if (!receiver->IsJSReceiver()) {
   1650     ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, receiver,
   1651                                      Object::ConvertReceiver(isolate, receiver),
   1652                                      Nothing<PropertyAttributes>());
   1653   }
   1654   PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
   1655                                  *holder, Object::DONT_THROW);
   1656   if (!interceptor->query()->IsUndefined(isolate)) {
   1657     Handle<Object> result;
   1658     if (it->IsElement()) {
   1659       uint32_t index = it->index();
   1660       v8::IndexedPropertyQueryCallback query =
   1661           v8::ToCData<v8::IndexedPropertyQueryCallback>(interceptor->query());
   1662       result = args.Call(query, index);
   1663     } else {
   1664       Handle<Name> name = it->name();
   1665       DCHECK(!name->IsPrivate());
   1666       v8::GenericNamedPropertyQueryCallback query =
   1667           v8::ToCData<v8::GenericNamedPropertyQueryCallback>(
   1668               interceptor->query());
   1669       result = args.Call(query, name);
   1670     }
   1671     if (!result.is_null()) {
   1672       int32_t value;
   1673       CHECK(result->ToInt32(&value));
   1674       return Just(static_cast<PropertyAttributes>(value));
   1675     }
   1676   } else if (!interceptor->getter()->IsUndefined(isolate)) {
   1677     // TODO(verwaest): Use GetPropertyWithInterceptor?
   1678     Handle<Object> result;
   1679     if (it->IsElement()) {
   1680       uint32_t index = it->index();
   1681       v8::IndexedPropertyGetterCallback getter =
   1682           v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter());
   1683       result = args.Call(getter, index);
   1684     } else {
   1685       Handle<Name> name = it->name();
   1686       DCHECK(!name->IsPrivate());
   1687       v8::GenericNamedPropertyGetterCallback getter =
   1688           v8::ToCData<v8::GenericNamedPropertyGetterCallback>(
   1689               interceptor->getter());
   1690       result = args.Call(getter, name);
   1691     }
   1692     if (!result.is_null()) return Just(DONT_ENUM);
   1693   }
   1694 
   1695   RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<PropertyAttributes>());
   1696   return Just(ABSENT);
   1697 }
   1698 
   1699 Maybe<bool> SetPropertyWithInterceptorInternal(
   1700     LookupIterator* it, Handle<InterceptorInfo> interceptor,
   1701     Object::ShouldThrow should_throw, Handle<Object> value) {
   1702   Isolate* isolate = it->isolate();
   1703   // Make sure that the top context does not change when doing callbacks or
   1704   // interceptor calls.
   1705   AssertNoContextChange ncc(isolate);
   1706 
   1707   if (interceptor->setter()->IsUndefined(isolate)) return Just(false);
   1708 
   1709   Handle<JSObject> holder = it->GetHolder<JSObject>();
   1710   bool result;
   1711   Handle<Object> receiver = it->GetReceiver();
   1712   if (!receiver->IsJSReceiver()) {
   1713     ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, receiver,
   1714                                      Object::ConvertReceiver(isolate, receiver),
   1715                                      Nothing<bool>());
   1716   }
   1717   PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
   1718                                  *holder, should_throw);
   1719 
   1720   if (it->IsElement()) {
   1721     uint32_t index = it->index();
   1722     v8::IndexedPropertySetterCallback setter =
   1723         v8::ToCData<v8::IndexedPropertySetterCallback>(interceptor->setter());
   1724     // TODO(neis): In the future, we may want to actually return the
   1725     // interceptor's result, which then should be a boolean.
   1726     result = !args.Call(setter, index, value).is_null();
   1727   } else {
   1728     Handle<Name> name = it->name();
   1729     DCHECK(!name->IsPrivate());
   1730 
   1731     if (name->IsSymbol() && !interceptor->can_intercept_symbols()) {
   1732       return Just(false);
   1733     }
   1734 
   1735     v8::GenericNamedPropertySetterCallback setter =
   1736         v8::ToCData<v8::GenericNamedPropertySetterCallback>(
   1737             interceptor->setter());
   1738     result = !args.Call(setter, name, value).is_null();
   1739   }
   1740 
   1741   RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(), Nothing<bool>());
   1742   return Just(result);
   1743 }
   1744 
   1745 Maybe<bool> DefinePropertyWithInterceptorInternal(
   1746     LookupIterator* it, Handle<InterceptorInfo> interceptor,
   1747     Object::ShouldThrow should_throw, PropertyDescriptor& desc) {
   1748   Isolate* isolate = it->isolate();
   1749   // Make sure that the top context does not change when doing callbacks or
   1750   // interceptor calls.
   1751   AssertNoContextChange ncc(isolate);
   1752 
   1753   if (interceptor->definer()->IsUndefined(isolate)) return Just(false);
   1754 
   1755   Handle<JSObject> holder = it->GetHolder<JSObject>();
   1756   bool result;
   1757   Handle<Object> receiver = it->GetReceiver();
   1758   if (!receiver->IsJSReceiver()) {
   1759     ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, receiver,
   1760                                      Object::ConvertReceiver(isolate, receiver),
   1761                                      Nothing<bool>());
   1762   }
   1763   PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
   1764                                  *holder, should_throw);
   1765 
   1766   std::unique_ptr<v8::PropertyDescriptor> descriptor(
   1767       new v8::PropertyDescriptor());
   1768   if (PropertyDescriptor::IsAccessorDescriptor(&desc)) {
   1769     descriptor.reset(new v8::PropertyDescriptor(
   1770         v8::Utils::ToLocal(desc.get()), v8::Utils::ToLocal(desc.set())));
   1771   } else if (PropertyDescriptor::IsDataDescriptor(&desc)) {
   1772     if (desc.has_writable()) {
   1773       descriptor.reset(new v8::PropertyDescriptor(
   1774           v8::Utils::ToLocal(desc.value()), desc.writable()));
   1775     } else {
   1776       descriptor.reset(
   1777           new v8::PropertyDescriptor(v8::Utils::ToLocal(desc.value())));
   1778     }
   1779   }
   1780   if (desc.has_enumerable()) {
   1781     descriptor->set_enumerable(desc.enumerable());
   1782   }
   1783   if (desc.has_configurable()) {
   1784     descriptor->set_configurable(desc.configurable());
   1785   }
   1786 
   1787   if (it->IsElement()) {
   1788     uint32_t index = it->index();
   1789     v8::IndexedPropertyDefinerCallback definer =
   1790         v8::ToCData<v8::IndexedPropertyDefinerCallback>(interceptor->definer());
   1791     result = !args.Call(definer, index, *descriptor).is_null();
   1792   } else {
   1793     Handle<Name> name = it->name();
   1794     DCHECK(!name->IsPrivate());
   1795 
   1796     if (name->IsSymbol() && !interceptor->can_intercept_symbols()) {
   1797       return Just(false);
   1798     }
   1799 
   1800     v8::GenericNamedPropertyDefinerCallback definer =
   1801         v8::ToCData<v8::GenericNamedPropertyDefinerCallback>(
   1802             interceptor->definer());
   1803     result = !args.Call(definer, name, *descriptor).is_null();
   1804   }
   1805 
   1806   RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(), Nothing<bool>());
   1807   return Just(result);
   1808 }
   1809 
   1810 }  // namespace
   1811 
   1812 MaybeHandle<Object> JSObject::GetPropertyWithFailedAccessCheck(
   1813     LookupIterator* it) {
   1814   Isolate* isolate = it->isolate();
   1815   Handle<JSObject> checked = it->GetHolder<JSObject>();
   1816   Handle<InterceptorInfo> interceptor =
   1817       it->GetInterceptorForFailedAccessCheck();
   1818   if (interceptor.is_null()) {
   1819     while (AllCanRead(it)) {
   1820       if (it->state() == LookupIterator::ACCESSOR) {
   1821         return GetPropertyWithAccessor(it);
   1822       }
   1823       DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
   1824       bool done;
   1825       Handle<Object> result;
   1826       ASSIGN_RETURN_ON_EXCEPTION(isolate, result,
   1827                                  GetPropertyWithInterceptor(it, &done), Object);
   1828       if (done) return result;
   1829     }
   1830 
   1831   } else {
   1832     Handle<Object> result;
   1833     bool done;
   1834     ASSIGN_RETURN_ON_EXCEPTION(
   1835         isolate, result,
   1836         GetPropertyWithInterceptorInternal(it, interceptor, &done), Object);
   1837     if (done) return result;
   1838   }
   1839 
   1840   // Cross-Origin [[Get]] of Well-Known Symbols does not throw, and returns
   1841   // undefined.
   1842   Handle<Name> name = it->GetName();
   1843   if (name->IsSymbol() && Symbol::cast(*name)->is_well_known_symbol()) {
   1844     return it->factory()->undefined_value();
   1845   }
   1846 
   1847   isolate->ReportFailedAccessCheck(checked);
   1848   RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
   1849   return it->factory()->undefined_value();
   1850 }
   1851 
   1852 
   1853 Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithFailedAccessCheck(
   1854     LookupIterator* it) {
   1855   Isolate* isolate = it->isolate();
   1856   Handle<JSObject> checked = it->GetHolder<JSObject>();
   1857   Handle<InterceptorInfo> interceptor =
   1858       it->GetInterceptorForFailedAccessCheck();
   1859   if (interceptor.is_null()) {
   1860     while (AllCanRead(it)) {
   1861       if (it->state() == LookupIterator::ACCESSOR) {
   1862         return Just(it->property_attributes());
   1863       }
   1864       DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
   1865       auto result = GetPropertyAttributesWithInterceptor(it);
   1866       if (isolate->has_scheduled_exception()) break;
   1867       if (result.IsJust() && result.FromJust() != ABSENT) return result;
   1868     }
   1869   } else {
   1870     Maybe<PropertyAttributes> result =
   1871         GetPropertyAttributesWithInterceptorInternal(it, interceptor);
   1872     if (isolate->has_pending_exception()) return Nothing<PropertyAttributes>();
   1873     if (result.FromMaybe(ABSENT) != ABSENT) return result;
   1874   }
   1875   isolate->ReportFailedAccessCheck(checked);
   1876   RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<PropertyAttributes>());
   1877   return Just(ABSENT);
   1878 }
   1879 
   1880 
   1881 // static
   1882 bool JSObject::AllCanWrite(LookupIterator* it) {
   1883   for (; it->IsFound() && it->state() != LookupIterator::JSPROXY; it->Next()) {
   1884     if (it->state() == LookupIterator::ACCESSOR) {
   1885       Handle<Object> accessors = it->GetAccessors();
   1886       if (accessors->IsAccessorInfo()) {
   1887         if (AccessorInfo::cast(*accessors)->all_can_write()) return true;
   1888       }
   1889     }
   1890   }
   1891   return false;
   1892 }
   1893 
   1894 
   1895 Maybe<bool> JSObject::SetPropertyWithFailedAccessCheck(
   1896     LookupIterator* it, Handle<Object> value, ShouldThrow should_throw) {
   1897   Isolate* isolate = it->isolate();
   1898   Handle<JSObject> checked = it->GetHolder<JSObject>();
   1899   Handle<InterceptorInfo> interceptor =
   1900       it->GetInterceptorForFailedAccessCheck();
   1901   if (interceptor.is_null()) {
   1902     if (AllCanWrite(it)) {
   1903       return SetPropertyWithAccessor(it, value, should_throw);
   1904     }
   1905   } else {
   1906     Maybe<bool> result = SetPropertyWithInterceptorInternal(
   1907         it, interceptor, should_throw, value);
   1908     if (isolate->has_pending_exception()) return Nothing<bool>();
   1909     if (result.IsJust()) return result;
   1910   }
   1911   isolate->ReportFailedAccessCheck(checked);
   1912   RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
   1913   return Just(true);
   1914 }
   1915 
   1916 
   1917 void JSObject::SetNormalizedProperty(Handle<JSObject> object,
   1918                                      Handle<Name> name,
   1919                                      Handle<Object> value,
   1920                                      PropertyDetails details) {
   1921   DCHECK(!object->HasFastProperties());
   1922   if (!name->IsUniqueName()) {
   1923     name = object->GetIsolate()->factory()->InternalizeString(
   1924         Handle<String>::cast(name));
   1925   }
   1926 
   1927   if (object->IsJSGlobalObject()) {
   1928     Handle<GlobalDictionary> dictionary(object->global_dictionary());
   1929 
   1930     int entry = dictionary->FindEntry(name);
   1931     if (entry == GlobalDictionary::kNotFound) {
   1932       Isolate* isolate = object->GetIsolate();
   1933       auto cell = isolate->factory()->NewPropertyCell();
   1934       cell->set_value(*value);
   1935       auto cell_type = value->IsUndefined(isolate)
   1936                            ? PropertyCellType::kUndefined
   1937                            : PropertyCellType::kConstant;
   1938       details = details.set_cell_type(cell_type);
   1939       value = cell;
   1940       dictionary = GlobalDictionary::Add(dictionary, name, value, details);
   1941       object->set_properties(*dictionary);
   1942     } else {
   1943       Handle<PropertyCell> cell =
   1944           PropertyCell::PrepareForValue(dictionary, entry, value, details);
   1945       cell->set_value(*value);
   1946     }
   1947   } else {
   1948     Handle<NameDictionary> dictionary(object->property_dictionary());
   1949 
   1950     int entry = dictionary->FindEntry(name);
   1951     if (entry == NameDictionary::kNotFound) {
   1952       dictionary = NameDictionary::Add(dictionary, name, value, details);
   1953       object->set_properties(*dictionary);
   1954     } else {
   1955       PropertyDetails original_details = dictionary->DetailsAt(entry);
   1956       int enumeration_index = original_details.dictionary_index();
   1957       DCHECK(enumeration_index > 0);
   1958       details = details.set_index(enumeration_index);
   1959       dictionary->SetEntry(entry, name, value, details);
   1960     }
   1961   }
   1962 }
   1963 
   1964 // static
   1965 Maybe<bool> JSReceiver::HasInPrototypeChain(Isolate* isolate,
   1966                                             Handle<JSReceiver> object,
   1967                                             Handle<Object> proto) {
   1968   PrototypeIterator iter(isolate, object, kStartAtReceiver);
   1969   while (true) {
   1970     if (!iter.AdvanceFollowingProxies()) return Nothing<bool>();
   1971     if (iter.IsAtEnd()) return Just(false);
   1972     if (PrototypeIterator::GetCurrent(iter).is_identical_to(proto)) {
   1973       return Just(true);
   1974     }
   1975   }
   1976 }
   1977 
   1978 namespace {
   1979 
   1980 bool HasExcludedProperty(
   1981     const ScopedVector<Handle<Object>>* excluded_properties,
   1982     Handle<Object> search_element) {
   1983   // TODO(gsathya): Change this to be a hashtable.
   1984   for (int i = 0; i < excluded_properties->length(); i++) {
   1985     if (search_element->SameValue(*excluded_properties->at(i))) {
   1986       return true;
   1987     }
   1988   }
   1989 
   1990   return false;
   1991 }
   1992 
   1993 MUST_USE_RESULT Maybe<bool> FastAssign(
   1994     Handle<JSReceiver> target, Handle<Object> source,
   1995     const ScopedVector<Handle<Object>>* excluded_properties, bool use_set) {
   1996   // Non-empty strings are the only non-JSReceivers that need to be handled
   1997   // explicitly by Object.assign.
   1998   if (!source->IsJSReceiver()) {
   1999     return Just(!source->IsString() || String::cast(*source)->length() == 0);
   2000   }
   2001 
   2002   // If the target is deprecated, the object will be updated on first store. If
   2003   // the source for that store equals the target, this will invalidate the
   2004   // cached representation of the source. Preventively upgrade the target.
   2005   // Do this on each iteration since any property load could cause deprecation.
   2006   if (target->map()->is_deprecated()) {
   2007     JSObject::MigrateInstance(Handle<JSObject>::cast(target));
   2008   }
   2009 
   2010   Isolate* isolate = target->GetIsolate();
   2011   Handle<Map> map(JSReceiver::cast(*source)->map(), isolate);
   2012 
   2013   if (!map->IsJSObjectMap()) return Just(false);
   2014   if (!map->OnlyHasSimpleProperties()) return Just(false);
   2015 
   2016   Handle<JSObject> from = Handle<JSObject>::cast(source);
   2017   if (from->elements() != isolate->heap()->empty_fixed_array()) {
   2018     return Just(false);
   2019   }
   2020 
   2021   Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate);
   2022   int length = map->NumberOfOwnDescriptors();
   2023 
   2024   bool stable = true;
   2025 
   2026   for (int i = 0; i < length; i++) {
   2027     Handle<Name> next_key(descriptors->GetKey(i), isolate);
   2028     Handle<Object> prop_value;
   2029     // Directly decode from the descriptor array if |from| did not change shape.
   2030     if (stable) {
   2031       PropertyDetails details = descriptors->GetDetails(i);
   2032       if (!details.IsEnumerable()) continue;
   2033       if (details.kind() == kData) {
   2034         if (details.location() == kDescriptor) {
   2035           prop_value = handle(descriptors->GetValue(i), isolate);
   2036         } else {
   2037           Representation representation = details.representation();
   2038           FieldIndex index = FieldIndex::ForDescriptor(*map, i);
   2039           prop_value = JSObject::FastPropertyAt(from, representation, index);
   2040         }
   2041       } else {
   2042         ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   2043             isolate, prop_value, JSReceiver::GetProperty(from, next_key),
   2044             Nothing<bool>());
   2045         stable = from->map() == *map;
   2046       }
   2047     } else {
   2048       // If the map did change, do a slower lookup. We are still guaranteed that
   2049       // the object has a simple shape, and that the key is a name.
   2050       LookupIterator it(from, next_key, from,
   2051                         LookupIterator::OWN_SKIP_INTERCEPTOR);
   2052       if (!it.IsFound()) continue;
   2053       DCHECK(it.state() == LookupIterator::DATA ||
   2054              it.state() == LookupIterator::ACCESSOR);
   2055       if (!it.IsEnumerable()) continue;
   2056       ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   2057           isolate, prop_value, Object::GetProperty(&it), Nothing<bool>());
   2058     }
   2059 
   2060     if (use_set) {
   2061       LookupIterator it(target, next_key, target);
   2062       bool call_to_js = it.IsFound() && it.state() != LookupIterator::DATA;
   2063       Maybe<bool> result = Object::SetProperty(
   2064           &it, prop_value, STRICT, Object::CERTAINLY_NOT_STORE_FROM_KEYED);
   2065       if (result.IsNothing()) return result;
   2066       if (stable && call_to_js) stable = from->map() == *map;
   2067     } else {
   2068       if (excluded_properties != nullptr &&
   2069           HasExcludedProperty(excluded_properties, next_key)) {
   2070         continue;
   2071       }
   2072 
   2073       // 4a ii 2. Perform ? CreateDataProperty(target, nextKey, propValue).
   2074       bool success;
   2075       LookupIterator it = LookupIterator::PropertyOrElement(
   2076           isolate, target, next_key, &success, LookupIterator::OWN);
   2077       CHECK(success);
   2078       CHECK(
   2079           JSObject::CreateDataProperty(&it, prop_value, Object::THROW_ON_ERROR)
   2080               .FromJust());
   2081     }
   2082   }
   2083 
   2084   return Just(true);
   2085 }
   2086 }  // namespace
   2087 
   2088 // static
   2089 Maybe<bool> JSReceiver::SetOrCopyDataProperties(
   2090     Isolate* isolate, Handle<JSReceiver> target, Handle<Object> source,
   2091     const ScopedVector<Handle<Object>>* excluded_properties, bool use_set) {
   2092   Maybe<bool> fast_assign =
   2093       FastAssign(target, source, excluded_properties, use_set);
   2094   if (fast_assign.IsNothing()) return Nothing<bool>();
   2095   if (fast_assign.FromJust()) return Just(true);
   2096 
   2097   Handle<JSReceiver> from = Object::ToObject(isolate, source).ToHandleChecked();
   2098   // 3b. Let keys be ? from.[[OwnPropertyKeys]]().
   2099   Handle<FixedArray> keys;
   2100   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   2101       isolate, keys,
   2102       KeyAccumulator::GetKeys(from, KeyCollectionMode::kOwnOnly, ALL_PROPERTIES,
   2103                               GetKeysConversion::kKeepNumbers),
   2104       Nothing<bool>());
   2105 
   2106   // 4. Repeat for each element nextKey of keys in List order,
   2107   for (int j = 0; j < keys->length(); ++j) {
   2108     Handle<Object> next_key(keys->get(j), isolate);
   2109     // 4a i. Let desc be ? from.[[GetOwnProperty]](nextKey).
   2110     PropertyDescriptor desc;
   2111     Maybe<bool> found =
   2112         JSReceiver::GetOwnPropertyDescriptor(isolate, from, next_key, &desc);
   2113     if (found.IsNothing()) return Nothing<bool>();
   2114     // 4a ii. If desc is not undefined and desc.[[Enumerable]] is true, then
   2115     if (found.FromJust() && desc.enumerable()) {
   2116       // 4a ii 1. Let propValue be ? Get(from, nextKey).
   2117       Handle<Object> prop_value;
   2118       ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   2119           isolate, prop_value,
   2120           Runtime::GetObjectProperty(isolate, from, next_key), Nothing<bool>());
   2121 
   2122       if (use_set) {
   2123         // 4c ii 2. Let status be ? Set(to, nextKey, propValue, true).
   2124         Handle<Object> status;
   2125         ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   2126             isolate, status, Runtime::SetObjectProperty(
   2127                                  isolate, target, next_key, prop_value, STRICT),
   2128             Nothing<bool>());
   2129       } else {
   2130         if (excluded_properties != nullptr &&
   2131             HasExcludedProperty(excluded_properties, next_key)) {
   2132           continue;
   2133         }
   2134 
   2135         // 4a ii 2. Perform ! CreateDataProperty(target, nextKey, propValue).
   2136         bool success;
   2137         LookupIterator it = LookupIterator::PropertyOrElement(
   2138             isolate, target, next_key, &success, LookupIterator::OWN);
   2139         CHECK(success);
   2140         CHECK(JSObject::CreateDataProperty(&it, prop_value,
   2141                                            Object::THROW_ON_ERROR)
   2142                   .FromJust());
   2143       }
   2144     }
   2145   }
   2146 
   2147   return Just(true);
   2148 }
   2149 
   2150 Map* Object::GetPrototypeChainRootMap(Isolate* isolate) {
   2151   DisallowHeapAllocation no_alloc;
   2152   if (IsSmi()) {
   2153     Context* native_context = isolate->context()->native_context();
   2154     return native_context->number_function()->initial_map();
   2155   }
   2156 
   2157   // The object is either a number, a string, a symbol, a boolean, a real JS
   2158   // object, or a Harmony proxy.
   2159   HeapObject* heap_object = HeapObject::cast(this);
   2160   return heap_object->map()->GetPrototypeChainRootMap(isolate);
   2161 }
   2162 
   2163 Map* Map::GetPrototypeChainRootMap(Isolate* isolate) {
   2164   DisallowHeapAllocation no_alloc;
   2165   if (IsJSReceiverMap()) {
   2166     return this;
   2167   }
   2168   int constructor_function_index = GetConstructorFunctionIndex();
   2169   if (constructor_function_index != Map::kNoConstructorFunctionIndex) {
   2170     Context* native_context = isolate->context()->native_context();
   2171     JSFunction* constructor_function =
   2172         JSFunction::cast(native_context->get(constructor_function_index));
   2173     return constructor_function->initial_map();
   2174   }
   2175   return isolate->heap()->null_value()->map();
   2176 }
   2177 
   2178 namespace {
   2179 
   2180 // Returns a non-SMI for JSObjects, but returns the hash code for simple
   2181 // objects.  This avoids a double lookup in the cases where we know we will
   2182 // add the hash to the JSObject if it does not already exist.
   2183 Object* GetSimpleHash(Object* object) {
   2184   // The object is either a Smi, a HeapNumber, a name, an odd-ball, a real JS
   2185   // object, or a Harmony proxy.
   2186   if (object->IsSmi()) {
   2187     uint32_t hash =
   2188         ComputeIntegerHash(Smi::cast(object)->value(), kZeroHashSeed);
   2189     return Smi::FromInt(hash & Smi::kMaxValue);
   2190   }
   2191   if (object->IsHeapNumber()) {
   2192     double num = HeapNumber::cast(object)->value();
   2193     if (std::isnan(num)) return Smi::FromInt(Smi::kMaxValue);
   2194     if (i::IsMinusZero(num)) num = 0;
   2195     if (IsSmiDouble(num)) {
   2196       return Smi::FromInt(FastD2I(num))->GetHash();
   2197     }
   2198     uint32_t hash = ComputeLongHash(double_to_uint64(num));
   2199     return Smi::FromInt(hash & Smi::kMaxValue);
   2200   }
   2201   if (object->IsName()) {
   2202     uint32_t hash = Name::cast(object)->Hash();
   2203     return Smi::FromInt(hash);
   2204   }
   2205   if (object->IsOddball()) {
   2206     uint32_t hash = Oddball::cast(object)->to_string()->Hash();
   2207     return Smi::FromInt(hash);
   2208   }
   2209   DCHECK(object->IsJSReceiver());
   2210   // Simply return the receiver as it is guaranteed to not be a SMI.
   2211   return object;
   2212 }
   2213 
   2214 }  // namespace
   2215 
   2216 Object* Object::GetHash() {
   2217   Object* hash = GetSimpleHash(this);
   2218   if (hash->IsSmi()) return hash;
   2219 
   2220   DisallowHeapAllocation no_gc;
   2221   DCHECK(IsJSReceiver());
   2222   JSReceiver* receiver = JSReceiver::cast(this);
   2223   Isolate* isolate = receiver->GetIsolate();
   2224   return JSReceiver::GetIdentityHash(isolate, handle(receiver, isolate));
   2225 }
   2226 
   2227 Smi* Object::GetOrCreateHash(Isolate* isolate, Handle<Object> object) {
   2228   Object* hash = GetSimpleHash(*object);
   2229   if (hash->IsSmi()) return Smi::cast(hash);
   2230 
   2231   DCHECK(object->IsJSReceiver());
   2232   return JSReceiver::GetOrCreateIdentityHash(isolate,
   2233                                              Handle<JSReceiver>::cast(object));
   2234 }
   2235 
   2236 
   2237 bool Object::SameValue(Object* other) {
   2238   if (other == this) return true;
   2239 
   2240   // The object is either a number, a name, an odd-ball,
   2241   // a real JS object, or a Harmony proxy.
   2242   if (IsNumber() && other->IsNumber()) {
   2243     double this_value = Number();
   2244     double other_value = other->Number();
   2245     // SameValue(NaN, NaN) is true.
   2246     if (this_value != other_value) {
   2247       return std::isnan(this_value) && std::isnan(other_value);
   2248     }
   2249     // SameValue(0.0, -0.0) is false.
   2250     return (std::signbit(this_value) == std::signbit(other_value));
   2251   }
   2252   if (IsString() && other->IsString()) {
   2253     return String::cast(this)->Equals(String::cast(other));
   2254   }
   2255   return false;
   2256 }
   2257 
   2258 
   2259 bool Object::SameValueZero(Object* other) {
   2260   if (other == this) return true;
   2261 
   2262   // The object is either a number, a name, an odd-ball,
   2263   // a real JS object, or a Harmony proxy.
   2264   if (IsNumber() && other->IsNumber()) {
   2265     double this_value = Number();
   2266     double other_value = other->Number();
   2267     // +0 == -0 is true
   2268     return this_value == other_value ||
   2269            (std::isnan(this_value) && std::isnan(other_value));
   2270   }
   2271   if (IsString() && other->IsString()) {
   2272     return String::cast(this)->Equals(String::cast(other));
   2273   }
   2274   return false;
   2275 }
   2276 
   2277 
   2278 MaybeHandle<Object> Object::ArraySpeciesConstructor(
   2279     Isolate* isolate, Handle<Object> original_array) {
   2280   Handle<Object> default_species = isolate->array_function();
   2281   if (original_array->IsJSArray() &&
   2282       Handle<JSArray>::cast(original_array)->HasArrayPrototype(isolate) &&
   2283       isolate->IsArraySpeciesLookupChainIntact()) {
   2284     return default_species;
   2285   }
   2286   Handle<Object> constructor = isolate->factory()->undefined_value();
   2287   Maybe<bool> is_array = Object::IsArray(original_array);
   2288   MAYBE_RETURN_NULL(is_array);
   2289   if (is_array.FromJust()) {
   2290     ASSIGN_RETURN_ON_EXCEPTION(
   2291         isolate, constructor,
   2292         Object::GetProperty(original_array,
   2293                             isolate->factory()->constructor_string()),
   2294         Object);
   2295     if (constructor->IsConstructor()) {
   2296       Handle<Context> constructor_context;
   2297       ASSIGN_RETURN_ON_EXCEPTION(
   2298           isolate, constructor_context,
   2299           JSReceiver::GetFunctionRealm(Handle<JSReceiver>::cast(constructor)),
   2300           Object);
   2301       if (*constructor_context != *isolate->native_context() &&
   2302           *constructor == constructor_context->array_function()) {
   2303         constructor = isolate->factory()->undefined_value();
   2304       }
   2305     }
   2306     if (constructor->IsJSReceiver()) {
   2307       ASSIGN_RETURN_ON_EXCEPTION(
   2308           isolate, constructor,
   2309           JSReceiver::GetProperty(Handle<JSReceiver>::cast(constructor),
   2310                                   isolate->factory()->species_symbol()),
   2311           Object);
   2312       if (constructor->IsNull(isolate)) {
   2313         constructor = isolate->factory()->undefined_value();
   2314       }
   2315     }
   2316   }
   2317   if (constructor->IsUndefined(isolate)) {
   2318     return default_species;
   2319   } else {
   2320     if (!constructor->IsConstructor()) {
   2321       THROW_NEW_ERROR(isolate,
   2322           NewTypeError(MessageTemplate::kSpeciesNotConstructor),
   2323           Object);
   2324     }
   2325     return constructor;
   2326   }
   2327 }
   2328 
   2329 bool Object::IterationHasObservableEffects() {
   2330   // Check that this object is an array.
   2331   if (!IsJSArray()) return true;
   2332   JSArray* spread_array = JSArray::cast(this);
   2333   Isolate* isolate = spread_array->GetIsolate();
   2334 
   2335   // Check that we have the original ArrayPrototype.
   2336   JSObject* array_proto = JSObject::cast(spread_array->map()->prototype());
   2337   if (!isolate->is_initial_array_prototype(array_proto)) return true;
   2338 
   2339   // Check that the ArrayPrototype hasn't been modified in a way that would
   2340   // affect iteration.
   2341   if (!isolate->IsArrayIteratorLookupChainIntact()) return true;
   2342 
   2343   // Check that the map of the initial array iterator hasn't changed.
   2344   Map* iterator_map = isolate->initial_array_iterator_prototype()->map();
   2345   if (!isolate->is_initial_array_iterator_prototype_map(iterator_map)) {
   2346     return true;
   2347   }
   2348 
   2349   // For FastPacked kinds, iteration will have the same effect as simply
   2350   // accessing each property in order.
   2351   ElementsKind array_kind = spread_array->GetElementsKind();
   2352   if (IsFastPackedElementsKind(array_kind)) return false;
   2353 
   2354   // For FastHoley kinds, an element access on a hole would cause a lookup on
   2355   // the prototype. This could have different results if the prototype has been
   2356   // changed.
   2357   if (IsFastHoleyElementsKind(array_kind) &&
   2358       isolate->IsFastArrayConstructorPrototypeChainIntact()) {
   2359     return false;
   2360   }
   2361   return true;
   2362 }
   2363 
   2364 void Object::ShortPrint(FILE* out) {
   2365   OFStream os(out);
   2366   os << Brief(this);
   2367 }
   2368 
   2369 
   2370 void Object::ShortPrint(StringStream* accumulator) {
   2371   std::ostringstream os;
   2372   os << Brief(this);
   2373   accumulator->Add(os.str().c_str());
   2374 }
   2375 
   2376 
   2377 void Object::ShortPrint(std::ostream& os) { os << Brief(this); }
   2378 
   2379 
   2380 std::ostream& operator<<(std::ostream& os, const Brief& v) {
   2381   if (v.value->IsSmi()) {
   2382     Smi::cast(v.value)->SmiPrint(os);
   2383   } else {
   2384     // TODO(svenpanne) Const-correct HeapObjectShortPrint!
   2385     HeapObject* obj = const_cast<HeapObject*>(HeapObject::cast(v.value));
   2386     obj->HeapObjectShortPrint(os);
   2387   }
   2388   return os;
   2389 }
   2390 
   2391 void Smi::SmiPrint(std::ostream& os) const {  // NOLINT
   2392   os << value();
   2393 }
   2394 
   2395 
   2396 // Should a word be prefixed by 'a' or 'an' in order to read naturally in
   2397 // English?  Returns false for non-ASCII or words that don't start with
   2398 // a capital letter.  The a/an rule follows pronunciation in English.
   2399 // We don't use the BBC's overcorrect "an historic occasion" though if
   2400 // you speak a dialect you may well say "an 'istoric occasion".
   2401 static bool AnWord(String* str) {
   2402   if (str->length() == 0) return false;  // A nothing.
   2403   int c0 = str->Get(0);
   2404   int c1 = str->length() > 1 ? str->Get(1) : 0;
   2405   if (c0 == 'U') {
   2406     if (c1 > 'Z') {
   2407       return true;  // An Umpire, but a UTF8String, a U.
   2408     }
   2409   } else if (c0 == 'A' || c0 == 'E' || c0 == 'I' || c0 == 'O') {
   2410     return true;    // An Ape, an ABCBook.
   2411   } else if ((c1 == 0 || (c1 >= 'A' && c1 <= 'Z')) &&
   2412            (c0 == 'F' || c0 == 'H' || c0 == 'M' || c0 == 'N' || c0 == 'R' ||
   2413             c0 == 'S' || c0 == 'X')) {
   2414     return true;    // An MP3File, an M.
   2415   }
   2416   return false;
   2417 }
   2418 
   2419 
   2420 Handle<String> String::SlowFlatten(Handle<ConsString> cons,
   2421                                    PretenureFlag pretenure) {
   2422   DCHECK(cons->second()->length() != 0);
   2423 
   2424   // TurboFan can create cons strings with empty first parts.
   2425   while (cons->first()->length() == 0) {
   2426     // We do not want to call this function recursively. Therefore we call
   2427     // String::Flatten only in those cases where String::SlowFlatten is not
   2428     // called again.
   2429     if (cons->second()->IsConsString() && !cons->second()->IsFlat()) {
   2430       cons = handle(ConsString::cast(cons->second()));
   2431     } else {
   2432       return String::Flatten(handle(cons->second()));
   2433     }
   2434   }
   2435 
   2436   DCHECK(AllowHeapAllocation::IsAllowed());
   2437   Isolate* isolate = cons->GetIsolate();
   2438   int length = cons->length();
   2439   PretenureFlag tenure = isolate->heap()->InNewSpace(*cons) ? pretenure
   2440                                                             : TENURED;
   2441   Handle<SeqString> result;
   2442   if (cons->IsOneByteRepresentation()) {
   2443     Handle<SeqOneByteString> flat = isolate->factory()->NewRawOneByteString(
   2444         length, tenure).ToHandleChecked();
   2445     DisallowHeapAllocation no_gc;
   2446     WriteToFlat(*cons, flat->GetChars(), 0, length);
   2447     result = flat;
   2448   } else {
   2449     Handle<SeqTwoByteString> flat = isolate->factory()->NewRawTwoByteString(
   2450         length, tenure).ToHandleChecked();
   2451     DisallowHeapAllocation no_gc;
   2452     WriteToFlat(*cons, flat->GetChars(), 0, length);
   2453     result = flat;
   2454   }
   2455   cons->set_first(*result);
   2456   cons->set_second(isolate->heap()->empty_string());
   2457   DCHECK(result->IsFlat());
   2458   return result;
   2459 }
   2460 
   2461 
   2462 
   2463 bool String::MakeExternal(v8::String::ExternalStringResource* resource) {
   2464   // Externalizing twice leaks the external resource, so it's
   2465   // prohibited by the API.
   2466   DCHECK(!this->IsExternalString());
   2467   DCHECK(!resource->IsCompressible());
   2468 #ifdef ENABLE_SLOW_DCHECKS
   2469   if (FLAG_enable_slow_asserts) {
   2470     // Assert that the resource and the string are equivalent.
   2471     DCHECK(static_cast<size_t>(this->length()) == resource->length());
   2472     ScopedVector<uc16> smart_chars(this->length());
   2473     String::WriteToFlat(this, smart_chars.start(), 0, this->length());
   2474     DCHECK(memcmp(smart_chars.start(),
   2475                   resource->data(),
   2476                   resource->length() * sizeof(smart_chars[0])) == 0);
   2477   }
   2478 #endif  // DEBUG
   2479   int size = this->Size();  // Byte size of the original string.
   2480   // Abort if size does not allow in-place conversion.
   2481   if (size < ExternalString::kShortSize) return false;
   2482   Heap* heap = GetHeap();
   2483   bool is_one_byte = this->IsOneByteRepresentation();
   2484   bool is_internalized = this->IsInternalizedString();
   2485   bool has_pointers = StringShape(this).IsIndirect();
   2486 
   2487   // Morph the string to an external string by replacing the map and
   2488   // reinitializing the fields.  This won't work if the space the existing
   2489   // string occupies is too small for a regular  external string.
   2490   // Instead, we resort to a short external string instead, omitting
   2491   // the field caching the address of the backing store.  When we encounter
   2492   // short external strings in generated code, we need to bailout to runtime.
   2493   Map* new_map;
   2494   if (size < ExternalString::kSize) {
   2495     new_map = is_internalized
   2496         ? (is_one_byte
   2497            ? heap->short_external_internalized_string_with_one_byte_data_map()
   2498            : heap->short_external_internalized_string_map())
   2499         : (is_one_byte ? heap->short_external_string_with_one_byte_data_map()
   2500                        : heap->short_external_string_map());
   2501   } else {
   2502     new_map = is_internalized
   2503         ? (is_one_byte
   2504            ? heap->external_internalized_string_with_one_byte_data_map()
   2505            : heap->external_internalized_string_map())
   2506         : (is_one_byte ? heap->external_string_with_one_byte_data_map()
   2507                        : heap->external_string_map());
   2508   }
   2509 
   2510   // Byte size of the external String object.
   2511   int new_size = this->SizeFromMap(new_map);
   2512   heap->CreateFillerObjectAt(this->address() + new_size, size - new_size,
   2513                              ClearRecordedSlots::kNo);
   2514   if (has_pointers) {
   2515     heap->ClearRecordedSlotRange(this->address(), this->address() + new_size);
   2516   }
   2517 
   2518   // We are storing the new map using release store after creating a filler for
   2519   // the left-over space to avoid races with the sweeper thread.
   2520   this->synchronized_set_map(new_map);
   2521 
   2522   ExternalTwoByteString* self = ExternalTwoByteString::cast(this);
   2523   self->set_resource(resource);
   2524   if (is_internalized) self->Hash();  // Force regeneration of the hash value.
   2525 
   2526   heap->AdjustLiveBytes(this, new_size - size);
   2527   return true;
   2528 }
   2529 
   2530 
   2531 bool String::MakeExternal(v8::String::ExternalOneByteStringResource* resource) {
   2532   // Externalizing twice leaks the external resource, so it's
   2533   // prohibited by the API.
   2534   DCHECK(!this->IsExternalString());
   2535   DCHECK(!resource->IsCompressible());
   2536 #ifdef ENABLE_SLOW_DCHECKS
   2537   if (FLAG_enable_slow_asserts) {
   2538     // Assert that the resource and the string are equivalent.
   2539     DCHECK(static_cast<size_t>(this->length()) == resource->length());
   2540     if (this->IsTwoByteRepresentation()) {
   2541       ScopedVector<uint16_t> smart_chars(this->length());
   2542       String::WriteToFlat(this, smart_chars.start(), 0, this->length());
   2543       DCHECK(String::IsOneByte(smart_chars.start(), this->length()));
   2544     }
   2545     ScopedVector<char> smart_chars(this->length());
   2546     String::WriteToFlat(this, smart_chars.start(), 0, this->length());
   2547     DCHECK(memcmp(smart_chars.start(),
   2548                   resource->data(),
   2549                   resource->length() * sizeof(smart_chars[0])) == 0);
   2550   }
   2551 #endif  // DEBUG
   2552   int size = this->Size();  // Byte size of the original string.
   2553   // Abort if size does not allow in-place conversion.
   2554   if (size < ExternalString::kShortSize) return false;
   2555   Heap* heap = GetHeap();
   2556   bool is_internalized = this->IsInternalizedString();
   2557   bool has_pointers = StringShape(this).IsIndirect();
   2558 
   2559   // Morph the string to an external string by replacing the map and
   2560   // reinitializing the fields.  This won't work if the space the existing
   2561   // string occupies is too small for a regular  external string.
   2562   // Instead, we resort to a short external string instead, omitting
   2563   // the field caching the address of the backing store.  When we encounter
   2564   // short external strings in generated code, we need to bailout to runtime.
   2565   Map* new_map;
   2566   if (size < ExternalString::kSize) {
   2567     new_map = is_internalized
   2568                   ? heap->short_external_one_byte_internalized_string_map()
   2569                   : heap->short_external_one_byte_string_map();
   2570   } else {
   2571     new_map = is_internalized
   2572                   ? heap->external_one_byte_internalized_string_map()
   2573                   : heap->external_one_byte_string_map();
   2574   }
   2575 
   2576   // Byte size of the external String object.
   2577   int new_size = this->SizeFromMap(new_map);
   2578   heap->CreateFillerObjectAt(this->address() + new_size, size - new_size,
   2579                              ClearRecordedSlots::kNo);
   2580   if (has_pointers) {
   2581     heap->ClearRecordedSlotRange(this->address(), this->address() + new_size);
   2582   }
   2583 
   2584   // We are storing the new map using release store after creating a filler for
   2585   // the left-over space to avoid races with the sweeper thread.
   2586   this->synchronized_set_map(new_map);
   2587 
   2588   ExternalOneByteString* self = ExternalOneByteString::cast(this);
   2589   self->set_resource(resource);
   2590   if (is_internalized) self->Hash();  // Force regeneration of the hash value.
   2591 
   2592   heap->AdjustLiveBytes(this, new_size - size);
   2593   return true;
   2594 }
   2595 
   2596 void String::StringShortPrint(StringStream* accumulator, bool show_details) {
   2597   int len = length();
   2598   if (len > kMaxShortPrintLength) {
   2599     accumulator->Add("<Very long string[%u]>", len);
   2600     return;
   2601   }
   2602 
   2603   if (!LooksValid()) {
   2604     accumulator->Add("<Invalid String>");
   2605     return;
   2606   }
   2607 
   2608   StringCharacterStream stream(this);
   2609 
   2610   bool truncated = false;
   2611   if (len > kMaxShortPrintLength) {
   2612     len = kMaxShortPrintLength;
   2613     truncated = true;
   2614   }
   2615   bool one_byte = true;
   2616   for (int i = 0; i < len; i++) {
   2617     uint16_t c = stream.GetNext();
   2618 
   2619     if (c < 32 || c >= 127) {
   2620       one_byte = false;
   2621     }
   2622   }
   2623   stream.Reset(this);
   2624   if (one_byte) {
   2625     if (show_details) accumulator->Add("<String[%u]: ", length());
   2626     for (int i = 0; i < len; i++) {
   2627       accumulator->Put(static_cast<char>(stream.GetNext()));
   2628     }
   2629     if (show_details) accumulator->Put('>');
   2630   } else {
   2631     // Backslash indicates that the string contains control
   2632     // characters and that backslashes are therefore escaped.
   2633     if (show_details) accumulator->Add("<String[%u]\\: ", length());
   2634     for (int i = 0; i < len; i++) {
   2635       uint16_t c = stream.GetNext();
   2636       if (c == '\n') {
   2637         accumulator->Add("\\n");
   2638       } else if (c == '\r') {
   2639         accumulator->Add("\\r");
   2640       } else if (c == '\\') {
   2641         accumulator->Add("\\\\");
   2642       } else if (c < 32 || c > 126) {
   2643         accumulator->Add("\\x%02x", c);
   2644       } else {
   2645         accumulator->Put(static_cast<char>(c));
   2646       }
   2647     }
   2648     if (truncated) {
   2649       accumulator->Put('.');
   2650       accumulator->Put('.');
   2651       accumulator->Put('.');
   2652     }
   2653     if (show_details) accumulator->Put('>');
   2654   }
   2655   return;
   2656 }
   2657 
   2658 
   2659 void String::PrintUC16(std::ostream& os, int start, int end) {  // NOLINT
   2660   if (end < 0) end = length();
   2661   StringCharacterStream stream(this, start);
   2662   for (int i = start; i < end && stream.HasMore(); i++) {
   2663     os << AsUC16(stream.GetNext());
   2664   }
   2665 }
   2666 
   2667 
   2668 void JSObject::JSObjectShortPrint(StringStream* accumulator) {
   2669   switch (map()->instance_type()) {
   2670     case JS_ARRAY_TYPE: {
   2671       double length = JSArray::cast(this)->length()->IsUndefined(GetIsolate())
   2672                           ? 0
   2673                           : JSArray::cast(this)->length()->Number();
   2674       accumulator->Add("<JS Array[%u]>", static_cast<uint32_t>(length));
   2675       break;
   2676     }
   2677     case JS_BOUND_FUNCTION_TYPE: {
   2678       JSBoundFunction* bound_function = JSBoundFunction::cast(this);
   2679       accumulator->Add("<JS BoundFunction");
   2680       accumulator->Add(
   2681           " (BoundTargetFunction %p)>",
   2682           reinterpret_cast<void*>(bound_function->bound_target_function()));
   2683       break;
   2684     }
   2685     case JS_WEAK_MAP_TYPE: {
   2686       accumulator->Add("<JS WeakMap>");
   2687       break;
   2688     }
   2689     case JS_WEAK_SET_TYPE: {
   2690       accumulator->Add("<JS WeakSet>");
   2691       break;
   2692     }
   2693     case JS_REGEXP_TYPE: {
   2694       accumulator->Add("<JS RegExp>");
   2695       break;
   2696     }
   2697     case JS_FUNCTION_TYPE: {
   2698       JSFunction* function = JSFunction::cast(this);
   2699       Object* fun_name = function->shared()->DebugName();
   2700       bool printed = false;
   2701       if (fun_name->IsString()) {
   2702         String* str = String::cast(fun_name);
   2703         if (str->length() > 0) {
   2704           accumulator->Add("<JS Function ");
   2705           accumulator->Put(str);
   2706           printed = true;
   2707         }
   2708       }
   2709       if (!printed) {
   2710         accumulator->Add("<JS Function");
   2711       }
   2712       if (FLAG_trace_file_names) {
   2713         Object* source_name =
   2714             Script::cast(function->shared()->script())->name();
   2715         if (source_name->IsString()) {
   2716           String* str = String::cast(source_name);
   2717           if (str->length() > 0) {
   2718             accumulator->Add(" <");
   2719             accumulator->Put(str);
   2720             accumulator->Add(">");
   2721           }
   2722         }
   2723       }
   2724       accumulator->Add(" (SharedFunctionInfo %p)",
   2725                        reinterpret_cast<void*>(function->shared()));
   2726       accumulator->Put('>');
   2727       break;
   2728     }
   2729     case JS_GENERATOR_OBJECT_TYPE: {
   2730       accumulator->Add("<JS Generator>");
   2731       break;
   2732     }
   2733     // All other JSObjects are rather similar to each other (JSObject,
   2734     // JSGlobalProxy, JSGlobalObject, JSUndetectable, JSValue).
   2735     default: {
   2736       Map* map_of_this = map();
   2737       Heap* heap = GetHeap();
   2738       Object* constructor = map_of_this->GetConstructor();
   2739       bool printed = false;
   2740       if (constructor->IsHeapObject() &&
   2741           !heap->Contains(HeapObject::cast(constructor))) {
   2742         accumulator->Add("!!!INVALID CONSTRUCTOR!!!");
   2743       } else {
   2744         bool global_object = IsJSGlobalProxy();
   2745         if (constructor->IsJSFunction()) {
   2746           if (!heap->Contains(JSFunction::cast(constructor)->shared())) {
   2747             accumulator->Add("!!!INVALID SHARED ON CONSTRUCTOR!!!");
   2748           } else {
   2749             Object* constructor_name =
   2750                 JSFunction::cast(constructor)->shared()->name();
   2751             if (constructor_name->IsString()) {
   2752               String* str = String::cast(constructor_name);
   2753               if (str->length() > 0) {
   2754                 bool vowel = AnWord(str);
   2755                 accumulator->Add("<%sa%s ",
   2756                        global_object ? "Global Object: " : "",
   2757                        vowel ? "n" : "");
   2758                 accumulator->Put(str);
   2759                 accumulator->Add(" with %smap %p",
   2760                     map_of_this->is_deprecated() ? "deprecated " : "",
   2761                     map_of_this);
   2762                 printed = true;
   2763               }
   2764             }
   2765           }
   2766         }
   2767         if (!printed) {
   2768           accumulator->Add("<JS %sObject", global_object ? "Global " : "");
   2769         }
   2770       }
   2771       if (IsJSValue()) {
   2772         accumulator->Add(" value = ");
   2773         JSValue::cast(this)->value()->ShortPrint(accumulator);
   2774       }
   2775       accumulator->Put('>');
   2776       break;
   2777     }
   2778   }
   2779 }
   2780 
   2781 
   2782 void JSObject::PrintElementsTransition(
   2783     FILE* file, Handle<JSObject> object,
   2784     ElementsKind from_kind, Handle<FixedArrayBase> from_elements,
   2785     ElementsKind to_kind, Handle<FixedArrayBase> to_elements) {
   2786   if (from_kind != to_kind) {
   2787     OFStream os(file);
   2788     os << "elements transition [" << ElementsKindToString(from_kind) << " -> "
   2789        << ElementsKindToString(to_kind) << "] in ";
   2790     JavaScriptFrame::PrintTop(object->GetIsolate(), file, false, true);
   2791     PrintF(file, " for ");
   2792     object->ShortPrint(file);
   2793     PrintF(file, " from ");
   2794     from_elements->ShortPrint(file);
   2795     PrintF(file, " to ");
   2796     to_elements->ShortPrint(file);
   2797     PrintF(file, "\n");
   2798   }
   2799 }
   2800 
   2801 
   2802 // static
   2803 MaybeHandle<JSFunction> Map::GetConstructorFunction(
   2804     Handle<Map> map, Handle<Context> native_context) {
   2805   if (map->IsPrimitiveMap()) {
   2806     int const constructor_function_index = map->GetConstructorFunctionIndex();
   2807     if (constructor_function_index != kNoConstructorFunctionIndex) {
   2808       return handle(
   2809           JSFunction::cast(native_context->get(constructor_function_index)));
   2810     }
   2811   }
   2812   return MaybeHandle<JSFunction>();
   2813 }
   2814 
   2815 
   2816 void Map::PrintReconfiguration(FILE* file, int modify_index, PropertyKind kind,
   2817                                PropertyAttributes attributes) {
   2818   OFStream os(file);
   2819   os << "[reconfiguring]";
   2820   Name* name = instance_descriptors()->GetKey(modify_index);
   2821   if (name->IsString()) {
   2822     String::cast(name)->PrintOn(file);
   2823   } else {
   2824     os << "{symbol " << static_cast<void*>(name) << "}";
   2825   }
   2826   os << ": " << (kind == kData ? "kData" : "ACCESSORS") << ", attrs: ";
   2827   os << attributes << " [";
   2828   JavaScriptFrame::PrintTop(GetIsolate(), file, false, true);
   2829   os << "]\n";
   2830 }
   2831 
   2832 void Map::PrintGeneralization(
   2833     FILE* file, const char* reason, int modify_index, int split,
   2834     int descriptors, bool descriptor_to_field,
   2835     Representation old_representation, Representation new_representation,
   2836     MaybeHandle<FieldType> old_field_type, MaybeHandle<Object> old_value,
   2837     MaybeHandle<FieldType> new_field_type, MaybeHandle<Object> new_value) {
   2838   OFStream os(file);
   2839   os << "[generalizing]";
   2840   Name* name = instance_descriptors()->GetKey(modify_index);
   2841   if (name->IsString()) {
   2842     String::cast(name)->PrintOn(file);
   2843   } else {
   2844     os << "{symbol " << static_cast<void*>(name) << "}";
   2845   }
   2846   os << ":";
   2847   if (descriptor_to_field) {
   2848     os << "c";
   2849   } else {
   2850     os << old_representation.Mnemonic() << "{";
   2851     if (old_field_type.is_null()) {
   2852       os << Brief(*(old_value.ToHandleChecked()));
   2853     } else {
   2854       old_field_type.ToHandleChecked()->PrintTo(os);
   2855     }
   2856     os << "}";
   2857   }
   2858   os << "->" << new_representation.Mnemonic() << "{";
   2859   if (new_field_type.is_null()) {
   2860     os << Brief(*(new_value.ToHandleChecked()));
   2861   } else {
   2862     new_field_type.ToHandleChecked()->PrintTo(os);
   2863   }
   2864   os << "} (";
   2865   if (strlen(reason) > 0) {
   2866     os << reason;
   2867   } else {
   2868     os << "+" << (descriptors - split) << " maps";
   2869   }
   2870   os << ") [";
   2871   JavaScriptFrame::PrintTop(GetIsolate(), file, false, true);
   2872   os << "]\n";
   2873 }
   2874 
   2875 
   2876 void JSObject::PrintInstanceMigration(FILE* file,
   2877                                       Map* original_map,
   2878                                       Map* new_map) {
   2879   PrintF(file, "[migrating]");
   2880   DescriptorArray* o = original_map->instance_descriptors();
   2881   DescriptorArray* n = new_map->instance_descriptors();
   2882   for (int i = 0; i < original_map->NumberOfOwnDescriptors(); i++) {
   2883     Representation o_r = o->GetDetails(i).representation();
   2884     Representation n_r = n->GetDetails(i).representation();
   2885     if (!o_r.Equals(n_r)) {
   2886       String::cast(o->GetKey(i))->PrintOn(file);
   2887       PrintF(file, ":%s->%s ", o_r.Mnemonic(), n_r.Mnemonic());
   2888     } else if (o->GetDetails(i).location() == kDescriptor &&
   2889                n->GetDetails(i).location() == kField) {
   2890       Name* name = o->GetKey(i);
   2891       if (name->IsString()) {
   2892         String::cast(name)->PrintOn(file);
   2893       } else {
   2894         PrintF(file, "{symbol %p}", static_cast<void*>(name));
   2895       }
   2896       PrintF(file, " ");
   2897     }
   2898   }
   2899   PrintF(file, "\n");
   2900 }
   2901 
   2902 
   2903 void HeapObject::HeapObjectShortPrint(std::ostream& os) {  // NOLINT
   2904   Heap* heap = GetHeap();
   2905   Isolate* isolate = heap->isolate();
   2906   if (!heap->Contains(this)) {
   2907     os << "!!!INVALID POINTER!!!";
   2908     return;
   2909   }
   2910   if (!heap->Contains(map())) {
   2911     os << "!!!INVALID MAP!!!";
   2912     return;
   2913   }
   2914 
   2915   os << this << " ";
   2916 
   2917   if (IsString()) {
   2918     HeapStringAllocator allocator;
   2919     StringStream accumulator(&allocator);
   2920     String::cast(this)->StringShortPrint(&accumulator);
   2921     os << accumulator.ToCString().get();
   2922     return;
   2923   }
   2924   if (IsJSObject()) {
   2925     HeapStringAllocator allocator;
   2926     StringStream accumulator(&allocator);
   2927     JSObject::cast(this)->JSObjectShortPrint(&accumulator);
   2928     os << accumulator.ToCString().get();
   2929     return;
   2930   }
   2931   switch (map()->instance_type()) {
   2932     case MAP_TYPE:
   2933       os << "<Map(" << ElementsKindToString(Map::cast(this)->elements_kind())
   2934          << ")>";
   2935       break;
   2936     case FIXED_ARRAY_TYPE:
   2937       os << "<FixedArray[" << FixedArray::cast(this)->length() << "]>";
   2938       break;
   2939     case FIXED_DOUBLE_ARRAY_TYPE:
   2940       os << "<FixedDoubleArray[" << FixedDoubleArray::cast(this)->length()
   2941          << "]>";
   2942       break;
   2943     case BYTE_ARRAY_TYPE:
   2944       os << "<ByteArray[" << ByteArray::cast(this)->length() << "]>";
   2945       break;
   2946     case BYTECODE_ARRAY_TYPE:
   2947       os << "<BytecodeArray[" << BytecodeArray::cast(this)->length() << "]>";
   2948       break;
   2949     case TRANSITION_ARRAY_TYPE:
   2950       os << "<TransitionArray[" << TransitionArray::cast(this)->length()
   2951          << "]>";
   2952       break;
   2953     case FREE_SPACE_TYPE:
   2954       os << "<FreeSpace[" << FreeSpace::cast(this)->size() << "]>";
   2955       break;
   2956 #define TYPED_ARRAY_SHORT_PRINT(Type, type, TYPE, ctype, size)                \
   2957   case FIXED_##TYPE##_ARRAY_TYPE:                                             \
   2958     os << "<Fixed" #Type "Array[" << Fixed##Type##Array::cast(this)->length() \
   2959        << "]>";                                                               \
   2960     break;
   2961 
   2962     TYPED_ARRAYS(TYPED_ARRAY_SHORT_PRINT)
   2963 #undef TYPED_ARRAY_SHORT_PRINT
   2964 
   2965     case SHARED_FUNCTION_INFO_TYPE: {
   2966       SharedFunctionInfo* shared = SharedFunctionInfo::cast(this);
   2967       std::unique_ptr<char[]> debug_name = shared->DebugName()->ToCString();
   2968       if (debug_name[0] != 0) {
   2969         os << "<SharedFunctionInfo " << debug_name.get() << ">";
   2970       } else {
   2971         os << "<SharedFunctionInfo>";
   2972       }
   2973       break;
   2974     }
   2975     case JS_MESSAGE_OBJECT_TYPE:
   2976       os << "<JSMessageObject>";
   2977       break;
   2978 #define MAKE_STRUCT_CASE(NAME, Name, name) \
   2979   case NAME##_TYPE:                        \
   2980     os << "<" #Name ">";                   \
   2981     break;
   2982   STRUCT_LIST(MAKE_STRUCT_CASE)
   2983 #undef MAKE_STRUCT_CASE
   2984     case CODE_TYPE: {
   2985       Code* code = Code::cast(this);
   2986       os << "<Code: " << Code::Kind2String(code->kind()) << ">";
   2987       break;
   2988     }
   2989     case ODDBALL_TYPE: {
   2990       if (IsUndefined(isolate)) {
   2991         os << "<undefined>";
   2992       } else if (IsTheHole(isolate)) {
   2993         os << "<the hole>";
   2994       } else if (IsNull(isolate)) {
   2995         os << "<null>";
   2996       } else if (IsTrue(isolate)) {
   2997         os << "<true>";
   2998       } else if (IsFalse(isolate)) {
   2999         os << "<false>";
   3000       } else {
   3001         os << "<Odd Oddball: ";
   3002         os << Oddball::cast(this)->to_string()->ToCString().get();
   3003         os << ">";
   3004       }
   3005       break;
   3006     }
   3007     case SYMBOL_TYPE: {
   3008       Symbol* symbol = Symbol::cast(this);
   3009       symbol->SymbolShortPrint(os);
   3010       break;
   3011     }
   3012     case HEAP_NUMBER_TYPE: {
   3013       os << "<Number: ";
   3014       HeapNumber::cast(this)->HeapNumberPrint(os);
   3015       os << ">";
   3016       break;
   3017     }
   3018     case MUTABLE_HEAP_NUMBER_TYPE: {
   3019       os << "<MutableNumber: ";
   3020       HeapNumber::cast(this)->HeapNumberPrint(os);
   3021       os << '>';
   3022       break;
   3023     }
   3024     case JS_PROXY_TYPE:
   3025       os << "<JSProxy>";
   3026       break;
   3027     case FOREIGN_TYPE:
   3028       os << "<Foreign>";
   3029       break;
   3030     case CELL_TYPE: {
   3031       os << "Cell for ";
   3032       HeapStringAllocator allocator;
   3033       StringStream accumulator(&allocator);
   3034       Cell::cast(this)->value()->ShortPrint(&accumulator);
   3035       os << accumulator.ToCString().get();
   3036       break;
   3037     }
   3038     case PROPERTY_CELL_TYPE: {
   3039       os << "PropertyCell for ";
   3040       HeapStringAllocator allocator;
   3041       StringStream accumulator(&allocator);
   3042       PropertyCell* cell = PropertyCell::cast(this);
   3043       cell->value()->ShortPrint(&accumulator);
   3044       os << accumulator.ToCString().get();
   3045       break;
   3046     }
   3047     case WEAK_CELL_TYPE: {
   3048       os << "WeakCell for ";
   3049       HeapStringAllocator allocator;
   3050       StringStream accumulator(&allocator);
   3051       WeakCell::cast(this)->value()->ShortPrint(&accumulator);
   3052       os << accumulator.ToCString().get();
   3053       break;
   3054     }
   3055     default:
   3056       os << "<Other heap object (" << map()->instance_type() << ")>";
   3057       break;
   3058   }
   3059 }
   3060 
   3061 
   3062 void HeapObject::Iterate(ObjectVisitor* v) { IterateFast<ObjectVisitor>(v); }
   3063 
   3064 
   3065 void HeapObject::IterateBody(ObjectVisitor* v) {
   3066   Map* m = map();
   3067   IterateBodyFast<ObjectVisitor>(m->instance_type(), SizeFromMap(m), v);
   3068 }
   3069 
   3070 
   3071 void HeapObject::IterateBody(InstanceType type, int object_size,
   3072                              ObjectVisitor* v) {
   3073   IterateBodyFast<ObjectVisitor>(type, object_size, v);
   3074 }
   3075 
   3076 
   3077 struct CallIsValidSlot {
   3078   template <typename BodyDescriptor>
   3079   static bool apply(HeapObject* obj, int offset, int) {
   3080     return BodyDescriptor::IsValidSlot(obj, offset);
   3081   }
   3082 };
   3083 
   3084 
   3085 bool HeapObject::IsValidSlot(int offset) {
   3086   DCHECK_NE(0, offset);
   3087   return BodyDescriptorApply<CallIsValidSlot, bool>(map()->instance_type(),
   3088                                                     this, offset, 0);
   3089 }
   3090 
   3091 
   3092 bool HeapNumber::HeapNumberBooleanValue() {
   3093   return DoubleToBoolean(value());
   3094 }
   3095 
   3096 
   3097 void HeapNumber::HeapNumberPrint(std::ostream& os) {  // NOLINT
   3098   os << value();
   3099 }
   3100 
   3101 
   3102 #define FIELD_ADDR_CONST(p, offset) \
   3103   (reinterpret_cast<const byte*>(p) + offset - kHeapObjectTag)
   3104 
   3105 #define READ_INT32_FIELD(p, offset) \
   3106   (*reinterpret_cast<const int32_t*>(FIELD_ADDR_CONST(p, offset)))
   3107 
   3108 #define READ_INT64_FIELD(p, offset) \
   3109   (*reinterpret_cast<const int64_t*>(FIELD_ADDR_CONST(p, offset)))
   3110 
   3111 #define READ_BYTE_FIELD(p, offset) \
   3112   (*reinterpret_cast<const byte*>(FIELD_ADDR_CONST(p, offset)))
   3113 
   3114 String* JSReceiver::class_name() {
   3115   if (IsFunction()) {
   3116     return GetHeap()->Function_string();
   3117   }
   3118   Object* maybe_constructor = map()->GetConstructor();
   3119   if (maybe_constructor->IsJSFunction()) {
   3120     JSFunction* constructor = JSFunction::cast(maybe_constructor);
   3121     return String::cast(constructor->shared()->instance_class_name());
   3122   }
   3123   // If the constructor is not present, return "Object".
   3124   return GetHeap()->Object_string();
   3125 }
   3126 
   3127 
   3128 // static
   3129 Handle<String> JSReceiver::GetConstructorName(Handle<JSReceiver> receiver) {
   3130   Isolate* isolate = receiver->GetIsolate();
   3131 
   3132   // If the object was instantiated simply with base == new.target, the
   3133   // constructor on the map provides the most accurate name.
   3134   // Don't provide the info for prototypes, since their constructors are
   3135   // reclaimed and replaced by Object in OptimizeAsPrototype.
   3136   if (!receiver->IsJSProxy() && receiver->map()->new_target_is_base() &&
   3137       !receiver->map()->is_prototype_map()) {
   3138     Object* maybe_constructor = receiver->map()->GetConstructor();
   3139     if (maybe_constructor->IsJSFunction()) {
   3140       JSFunction* constructor = JSFunction::cast(maybe_constructor);
   3141       String* name = String::cast(constructor->shared()->name());
   3142       if (name->length() == 0) name = constructor->shared()->inferred_name();
   3143       if (name->length() != 0 &&
   3144           !name->Equals(isolate->heap()->Object_string())) {
   3145         return handle(name, isolate);
   3146       }
   3147     }
   3148   }
   3149 
   3150   Handle<Object> maybe_tag = JSReceiver::GetDataProperty(
   3151       receiver, isolate->factory()->to_string_tag_symbol());
   3152   if (maybe_tag->IsString()) return Handle<String>::cast(maybe_tag);
   3153 
   3154   PrototypeIterator iter(isolate, receiver);
   3155   if (iter.IsAtEnd()) return handle(receiver->class_name());
   3156   Handle<JSReceiver> start = PrototypeIterator::GetCurrent<JSReceiver>(iter);
   3157   LookupIterator it(receiver, isolate->factory()->constructor_string(), start,
   3158                     LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
   3159   Handle<Object> maybe_constructor = JSReceiver::GetDataProperty(&it);
   3160   Handle<String> result = isolate->factory()->Object_string();
   3161   if (maybe_constructor->IsJSFunction()) {
   3162     JSFunction* constructor = JSFunction::cast(*maybe_constructor);
   3163     String* name = String::cast(constructor->shared()->name());
   3164     if (name->length() == 0) name = constructor->shared()->inferred_name();
   3165     if (name->length() > 0) result = handle(name, isolate);
   3166   }
   3167 
   3168   return result.is_identical_to(isolate->factory()->Object_string())
   3169              ? handle(receiver->class_name())
   3170              : result;
   3171 }
   3172 
   3173 Handle<Context> JSReceiver::GetCreationContext() {
   3174   JSReceiver* receiver = this;
   3175   while (receiver->IsJSBoundFunction()) {
   3176     receiver = JSBoundFunction::cast(receiver)->bound_target_function();
   3177   }
   3178   Object* constructor = receiver->map()->GetConstructor();
   3179   JSFunction* function;
   3180   if (constructor->IsJSFunction()) {
   3181     function = JSFunction::cast(constructor);
   3182   } else {
   3183     // Functions have null as a constructor,
   3184     // but any JSFunction knows its context immediately.
   3185     CHECK(receiver->IsJSFunction());
   3186     function = JSFunction::cast(receiver);
   3187   }
   3188 
   3189   return function->has_context()
   3190              ? Handle<Context>(function->context()->native_context())
   3191              : Handle<Context>::null();
   3192 }
   3193 
   3194 Handle<Object> Map::WrapFieldType(Handle<FieldType> type) {
   3195   if (type->IsClass()) return Map::WeakCellForMap(type->AsClass());
   3196   return type;
   3197 }
   3198 
   3199 FieldType* Map::UnwrapFieldType(Object* wrapped_type) {
   3200   Object* value = wrapped_type;
   3201   if (value->IsWeakCell()) {
   3202     if (WeakCell::cast(value)->cleared()) return FieldType::None();
   3203     value = WeakCell::cast(value)->value();
   3204   }
   3205   return FieldType::cast(value);
   3206 }
   3207 
   3208 MaybeHandle<Map> Map::CopyWithField(Handle<Map> map, Handle<Name> name,
   3209                                     Handle<FieldType> type,
   3210                                     PropertyAttributes attributes,
   3211                                     PropertyConstness constness,
   3212                                     Representation representation,
   3213                                     TransitionFlag flag) {
   3214   DCHECK(DescriptorArray::kNotFound ==
   3215          map->instance_descriptors()->Search(
   3216              *name, map->NumberOfOwnDescriptors()));
   3217 
   3218   // Ensure the descriptor array does not get too big.
   3219   if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors) {
   3220     return MaybeHandle<Map>();
   3221   }
   3222 
   3223   Isolate* isolate = map->GetIsolate();
   3224 
   3225   // Compute the new index for new field.
   3226   int index = map->NextFreePropertyIndex();
   3227 
   3228   if (map->instance_type() == JS_CONTEXT_EXTENSION_OBJECT_TYPE) {
   3229     representation = Representation::Tagged();
   3230     type = FieldType::Any(isolate);
   3231   }
   3232 
   3233   Handle<Object> wrapped_type(WrapFieldType(type));
   3234 
   3235   DCHECK_IMPLIES(!FLAG_track_constant_fields, constness == kMutable);
   3236   Descriptor d = Descriptor::DataField(name, index, attributes, constness,
   3237                                        representation, wrapped_type);
   3238   Handle<Map> new_map = Map::CopyAddDescriptor(map, &d, flag);
   3239   int unused_property_fields = new_map->unused_property_fields() - 1;
   3240   if (unused_property_fields < 0) {
   3241     unused_property_fields += JSObject::kFieldsAdded;
   3242   }
   3243   new_map->set_unused_property_fields(unused_property_fields);
   3244   return new_map;
   3245 }
   3246 
   3247 
   3248 MaybeHandle<Map> Map::CopyWithConstant(Handle<Map> map,
   3249                                        Handle<Name> name,
   3250                                        Handle<Object> constant,
   3251                                        PropertyAttributes attributes,
   3252                                        TransitionFlag flag) {
   3253   // Ensure the descriptor array does not get too big.
   3254   if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors) {
   3255     return MaybeHandle<Map>();
   3256   }
   3257 
   3258   if (FLAG_track_constant_fields) {
   3259     Isolate* isolate = map->GetIsolate();
   3260     Representation representation = constant->OptimalRepresentation();
   3261     Handle<FieldType> type = constant->OptimalType(isolate, representation);
   3262     return CopyWithField(map, name, type, attributes, kConst, representation,
   3263                          flag);
   3264   } else {
   3265     // Allocate new instance descriptors with (name, constant) added.
   3266     Descriptor d = Descriptor::DataConstant(name, 0, constant, attributes);
   3267     Handle<Map> new_map = Map::CopyAddDescriptor(map, &d, flag);
   3268     return new_map;
   3269   }
   3270 }
   3271 
   3272 const char* Representation::Mnemonic() const {
   3273   switch (kind_) {
   3274     case kNone: return "v";
   3275     case kTagged: return "t";
   3276     case kSmi: return "s";
   3277     case kDouble: return "d";
   3278     case kInteger32: return "i";
   3279     case kHeapObject: return "h";
   3280     case kExternal: return "x";
   3281     default:
   3282       UNREACHABLE();
   3283       return NULL;
   3284   }
   3285 }
   3286 
   3287 bool Map::TransitionRemovesTaggedField(Map* target) {
   3288   int inobject = GetInObjectProperties();
   3289   int target_inobject = target->GetInObjectProperties();
   3290   for (int i = target_inobject; i < inobject; i++) {
   3291     FieldIndex index = FieldIndex::ForPropertyIndex(this, i);
   3292     if (!IsUnboxedDoubleField(index)) return true;
   3293   }
   3294   return false;
   3295 }
   3296 
   3297 bool Map::TransitionChangesTaggedFieldToUntaggedField(Map* target) {
   3298   int inobject = GetInObjectProperties();
   3299   int target_inobject = target->GetInObjectProperties();
   3300   int limit = Min(inobject, target_inobject);
   3301   for (int i = 0; i < limit; i++) {
   3302     FieldIndex index = FieldIndex::ForPropertyIndex(target, i);
   3303     if (!IsUnboxedDoubleField(index) && target->IsUnboxedDoubleField(index)) {
   3304       return true;
   3305     }
   3306   }
   3307   return false;
   3308 }
   3309 
   3310 bool Map::TransitionRequiresSynchronizationWithGC(Map* target) {
   3311   return TransitionRemovesTaggedField(target) ||
   3312          TransitionChangesTaggedFieldToUntaggedField(target);
   3313 }
   3314 
   3315 bool Map::InstancesNeedRewriting(Map* target) {
   3316   int target_number_of_fields = target->NumberOfFields();
   3317   int target_inobject = target->GetInObjectProperties();
   3318   int target_unused = target->unused_property_fields();
   3319   int old_number_of_fields;
   3320 
   3321   return InstancesNeedRewriting(target, target_number_of_fields,
   3322                                 target_inobject, target_unused,
   3323                                 &old_number_of_fields);
   3324 }
   3325 
   3326 bool Map::InstancesNeedRewriting(Map* target, int target_number_of_fields,
   3327                                  int target_inobject, int target_unused,
   3328                                  int* old_number_of_fields) {
   3329   // If fields were added (or removed), rewrite the instance.
   3330   *old_number_of_fields = NumberOfFields();
   3331   DCHECK(target_number_of_fields >= *old_number_of_fields);
   3332   if (target_number_of_fields != *old_number_of_fields) return true;
   3333 
   3334   // If smi descriptors were replaced by double descriptors, rewrite.
   3335   DescriptorArray* old_desc = instance_descriptors();
   3336   DescriptorArray* new_desc = target->instance_descriptors();
   3337   int limit = NumberOfOwnDescriptors();
   3338   for (int i = 0; i < limit; i++) {
   3339     if (new_desc->GetDetails(i).representation().IsDouble() !=
   3340         old_desc->GetDetails(i).representation().IsDouble()) {
   3341       return true;
   3342     }
   3343   }
   3344 
   3345   // If no fields were added, and no inobject properties were removed, setting
   3346   // the map is sufficient.
   3347   if (target_inobject == GetInObjectProperties()) return false;
   3348   // In-object slack tracking may have reduced the object size of the new map.
   3349   // In that case, succeed if all existing fields were inobject, and they still
   3350   // fit within the new inobject size.
   3351   DCHECK(target_inobject < GetInObjectProperties());
   3352   if (target_number_of_fields <= target_inobject) {
   3353     DCHECK(target_number_of_fields + target_unused == target_inobject);
   3354     return false;
   3355   }
   3356   // Otherwise, properties will need to be moved to the backing store.
   3357   return true;
   3358 }
   3359 
   3360 
   3361 // static
   3362 void JSObject::UpdatePrototypeUserRegistration(Handle<Map> old_map,
   3363                                                Handle<Map> new_map,
   3364                                                Isolate* isolate) {
   3365   DCHECK(old_map->is_prototype_map());
   3366   DCHECK(new_map->is_prototype_map());
   3367   bool was_registered = JSObject::UnregisterPrototypeUser(old_map, isolate);
   3368   new_map->set_prototype_info(old_map->prototype_info());
   3369   old_map->set_prototype_info(Smi::kZero);
   3370   if (FLAG_trace_prototype_users) {
   3371     PrintF("Moving prototype_info %p from map %p to map %p.\n",
   3372            reinterpret_cast<void*>(new_map->prototype_info()),
   3373            reinterpret_cast<void*>(*old_map),
   3374            reinterpret_cast<void*>(*new_map));
   3375   }
   3376   if (was_registered) {
   3377     if (new_map->prototype_info()->IsPrototypeInfo()) {
   3378       // The new map isn't registered with its prototype yet; reflect this fact
   3379       // in the PrototypeInfo it just inherited from the old map.
   3380       PrototypeInfo::cast(new_map->prototype_info())
   3381           ->set_registry_slot(PrototypeInfo::UNREGISTERED);
   3382     }
   3383     JSObject::LazyRegisterPrototypeUser(new_map, isolate);
   3384   }
   3385 }
   3386 
   3387 namespace {
   3388 // To migrate a fast instance to a fast map:
   3389 // - First check whether the instance needs to be rewritten. If not, simply
   3390 //   change the map.
   3391 // - Otherwise, allocate a fixed array large enough to hold all fields, in
   3392 //   addition to unused space.
   3393 // - Copy all existing properties in, in the following order: backing store
   3394 //   properties, unused fields, inobject properties.
   3395 // - If all allocation succeeded, commit the state atomically:
   3396 //   * Copy inobject properties from the backing store back into the object.
   3397 //   * Trim the difference in instance size of the object. This also cleanly
   3398 //     frees inobject properties that moved to the backing store.
   3399 //   * If there are properties left in the backing store, trim of the space used
   3400 //     to temporarily store the inobject properties.
   3401 //   * If there are properties left in the backing store, install the backing
   3402 //     store.
   3403 void MigrateFastToFast(Handle<JSObject> object, Handle<Map> new_map) {
   3404   Isolate* isolate = object->GetIsolate();
   3405   Handle<Map> old_map(object->map());
   3406   // In case of a regular transition.
   3407   if (new_map->GetBackPointer() == *old_map) {
   3408     // If the map does not add named properties, simply set the map.
   3409     if (old_map->NumberOfOwnDescriptors() ==
   3410         new_map->NumberOfOwnDescriptors()) {
   3411       object->synchronized_set_map(*new_map);
   3412       return;
   3413     }
   3414 
   3415     PropertyDetails details = new_map->GetLastDescriptorDetails();
   3416     // Either new_map adds an kDescriptor property, or a kField property for
   3417     // which there is still space, and which does not require a mutable double
   3418     // box (an out-of-object double).
   3419     if (details.location() == kDescriptor ||
   3420         (old_map->unused_property_fields() > 0 &&
   3421          ((FLAG_unbox_double_fields && object->properties()->length() == 0) ||
   3422           !details.representation().IsDouble()))) {
   3423       object->synchronized_set_map(*new_map);
   3424       return;
   3425     }
   3426 
   3427     // If there is still space in the object, we need to allocate a mutable
   3428     // double box.
   3429     if (old_map->unused_property_fields() > 0) {
   3430       FieldIndex index =
   3431           FieldIndex::ForDescriptor(*new_map, new_map->LastAdded());
   3432       DCHECK(details.representation().IsDouble());
   3433       DCHECK(!new_map->IsUnboxedDoubleField(index));
   3434       Handle<Object> value = isolate->factory()->NewMutableHeapNumber();
   3435       object->RawFastPropertyAtPut(index, *value);
   3436       object->synchronized_set_map(*new_map);
   3437       return;
   3438     }
   3439 
   3440     // This migration is a transition from a map that has run out of property
   3441     // space. Extend the backing store.
   3442     int grow_by = new_map->unused_property_fields() + 1;
   3443     Handle<FixedArray> old_storage = handle(object->properties(), isolate);
   3444     Handle<FixedArray> new_storage =
   3445         isolate->factory()->CopyFixedArrayAndGrow(old_storage, grow_by);
   3446 
   3447     // Properly initialize newly added property.
   3448     Handle<Object> value;
   3449     if (details.representation().IsDouble()) {
   3450       value = isolate->factory()->NewMutableHeapNumber();
   3451     } else {
   3452       value = isolate->factory()->uninitialized_value();
   3453     }
   3454     DCHECK_EQ(kField, details.location());
   3455     DCHECK_EQ(kData, details.kind());
   3456     int target_index = details.field_index() - new_map->GetInObjectProperties();
   3457     DCHECK(target_index >= 0);  // Must be a backing store index.
   3458     new_storage->set(target_index, *value);
   3459 
   3460     // From here on we cannot fail and we shouldn't GC anymore.
   3461     DisallowHeapAllocation no_allocation;
   3462 
   3463     // Set the new property value and do the map transition.
   3464     object->set_properties(*new_storage);
   3465     object->synchronized_set_map(*new_map);
   3466     return;
   3467   }
   3468 
   3469   int old_number_of_fields;
   3470   int number_of_fields = new_map->NumberOfFields();
   3471   int inobject = new_map->GetInObjectProperties();
   3472   int unused = new_map->unused_property_fields();
   3473 
   3474   // Nothing to do if no functions were converted to fields and no smis were
   3475   // converted to doubles.
   3476   if (!old_map->InstancesNeedRewriting(*new_map, number_of_fields, inobject,
   3477                                        unused, &old_number_of_fields)) {
   3478     object->synchronized_set_map(*new_map);
   3479     return;
   3480   }
   3481 
   3482   int total_size = number_of_fields + unused;
   3483   int external = total_size - inobject;
   3484 
   3485   Handle<FixedArray> array = isolate->factory()->NewFixedArray(total_size);
   3486 
   3487   Handle<DescriptorArray> old_descriptors(old_map->instance_descriptors());
   3488   Handle<DescriptorArray> new_descriptors(new_map->instance_descriptors());
   3489   int old_nof = old_map->NumberOfOwnDescriptors();
   3490   int new_nof = new_map->NumberOfOwnDescriptors();
   3491 
   3492   // This method only supports generalizing instances to at least the same
   3493   // number of properties.
   3494   DCHECK(old_nof <= new_nof);
   3495 
   3496   for (int i = 0; i < old_nof; i++) {
   3497     PropertyDetails details = new_descriptors->GetDetails(i);
   3498     if (details.location() != kField) continue;
   3499     DCHECK_EQ(kData, details.kind());
   3500     PropertyDetails old_details = old_descriptors->GetDetails(i);
   3501     Representation old_representation = old_details.representation();
   3502     Representation representation = details.representation();
   3503     Handle<Object> value;
   3504     if (old_details.location() == kDescriptor) {
   3505       if (old_details.kind() == kAccessor) {
   3506         // In case of kAccessor -> kData property reconfiguration, the property
   3507         // must already be prepared for data of certain type.
   3508         DCHECK(!details.representation().IsNone());
   3509         if (details.representation().IsDouble()) {
   3510           value = isolate->factory()->NewMutableHeapNumber();
   3511         } else {
   3512           value = isolate->factory()->uninitialized_value();
   3513         }
   3514       } else {
   3515         DCHECK_EQ(kData, old_details.kind());
   3516         value = handle(old_descriptors->GetValue(i), isolate);
   3517         DCHECK(!old_representation.IsDouble() && !representation.IsDouble());
   3518       }
   3519     } else {
   3520       DCHECK_EQ(kField, old_details.location());
   3521       FieldIndex index = FieldIndex::ForDescriptor(*old_map, i);
   3522       if (object->IsUnboxedDoubleField(index)) {
   3523         uint64_t old_bits = object->RawFastDoublePropertyAsBitsAt(index);
   3524         value = isolate->factory()->NewHeapNumberFromBits(
   3525             old_bits, representation.IsDouble() ? MUTABLE : IMMUTABLE);
   3526 
   3527       } else {
   3528         value = handle(object->RawFastPropertyAt(index), isolate);
   3529         if (!old_representation.IsDouble() && representation.IsDouble()) {
   3530           DCHECK_IMPLIES(old_representation.IsNone(),
   3531                          value->IsUninitialized(isolate));
   3532           value = Object::NewStorageFor(isolate, value, representation);
   3533         } else if (old_representation.IsDouble() &&
   3534                    !representation.IsDouble()) {
   3535           value = Object::WrapForRead(isolate, value, old_representation);
   3536         }
   3537       }
   3538     }
   3539     DCHECK(!(representation.IsDouble() && value->IsSmi()));
   3540     int target_index = new_descriptors->GetFieldIndex(i) - inobject;
   3541     if (target_index < 0) target_index += total_size;
   3542     array->set(target_index, *value);
   3543   }
   3544 
   3545   for (int i = old_nof; i < new_nof; i++) {
   3546     PropertyDetails details = new_descriptors->GetDetails(i);
   3547     if (details.location() != kField) continue;
   3548     DCHECK_EQ(kData, details.kind());
   3549     Handle<Object> value;
   3550     if (details.representation().IsDouble()) {
   3551       value = isolate->factory()->NewMutableHeapNumber();
   3552     } else {
   3553       value = isolate->factory()->uninitialized_value();
   3554     }
   3555     int target_index = new_descriptors->GetFieldIndex(i) - inobject;
   3556     if (target_index < 0) target_index += total_size;
   3557     array->set(target_index, *value);
   3558   }
   3559 
   3560   // From here on we cannot fail and we shouldn't GC anymore.
   3561   DisallowHeapAllocation no_allocation;
   3562 
   3563   Heap* heap = isolate->heap();
   3564 
   3565   heap->NotifyObjectLayoutChange(*object, no_allocation);
   3566 
   3567   // Copy (real) inobject properties. If necessary, stop at number_of_fields to
   3568   // avoid overwriting |one_pointer_filler_map|.
   3569   int limit = Min(inobject, number_of_fields);
   3570   for (int i = 0; i < limit; i++) {
   3571     FieldIndex index = FieldIndex::ForPropertyIndex(*new_map, i);
   3572     Object* value = array->get(external + i);
   3573     // Can't use JSObject::FastPropertyAtPut() because proper map was not set
   3574     // yet.
   3575     if (new_map->IsUnboxedDoubleField(index)) {
   3576       DCHECK(value->IsMutableHeapNumber());
   3577       // Ensure that all bits of the double value are preserved.
   3578       object->RawFastDoublePropertyAsBitsAtPut(
   3579           index, HeapNumber::cast(value)->value_as_bits());
   3580       if (i < old_number_of_fields && !old_map->IsUnboxedDoubleField(index)) {
   3581         // Transition from tagged to untagged slot.
   3582         heap->ClearRecordedSlot(*object,
   3583                                 HeapObject::RawField(*object, index.offset()));
   3584       } else {
   3585         DCHECK(!heap->HasRecordedSlot(
   3586             *object, HeapObject::RawField(*object, index.offset())));
   3587       }
   3588     } else {
   3589       object->RawFastPropertyAtPut(index, value);
   3590     }
   3591   }
   3592 
   3593 
   3594   // If there are properties in the new backing store, trim it to the correct
   3595   // size and install the backing store into the object.
   3596   if (external > 0) {
   3597     heap->RightTrimFixedArray(*array, inobject);
   3598     object->set_properties(*array);
   3599   }
   3600 
   3601   // Create filler object past the new instance size.
   3602   int new_instance_size = new_map->instance_size();
   3603   int instance_size_delta = old_map->instance_size() - new_instance_size;
   3604   DCHECK(instance_size_delta >= 0);
   3605 
   3606   if (instance_size_delta > 0) {
   3607     Address address = object->address();
   3608     heap->CreateFillerObjectAt(address + new_instance_size, instance_size_delta,
   3609                                ClearRecordedSlots::kYes);
   3610     heap->AdjustLiveBytes(*object, -instance_size_delta);
   3611   }
   3612 
   3613   // We are storing the new map using release store after creating a filler for
   3614   // the left-over space to avoid races with the sweeper thread.
   3615   object->synchronized_set_map(*new_map);
   3616 }
   3617 
   3618 void MigrateFastToSlow(Handle<JSObject> object, Handle<Map> new_map,
   3619                        int expected_additional_properties) {
   3620   // The global object is always normalized.
   3621   DCHECK(!object->IsJSGlobalObject());
   3622   // JSGlobalProxy must never be normalized
   3623   DCHECK(!object->IsJSGlobalProxy());
   3624 
   3625   Isolate* isolate = object->GetIsolate();
   3626   HandleScope scope(isolate);
   3627   Handle<Map> map(object->map());
   3628 
   3629   // Allocate new content.
   3630   int real_size = map->NumberOfOwnDescriptors();
   3631   int property_count = real_size;
   3632   if (expected_additional_properties > 0) {
   3633     property_count += expected_additional_properties;
   3634   } else {
   3635     // Make space for two more properties.
   3636     property_count += NameDictionary::kInitialCapacity;
   3637   }
   3638   Handle<NameDictionary> dictionary =
   3639       NameDictionary::New(isolate, property_count);
   3640 
   3641   Handle<DescriptorArray> descs(map->instance_descriptors());
   3642   for (int i = 0; i < real_size; i++) {
   3643     PropertyDetails details = descs->GetDetails(i);
   3644     Handle<Name> key(descs->GetKey(i));
   3645     Handle<Object> value;
   3646     if (details.location() == kField) {
   3647       FieldIndex index = FieldIndex::ForDescriptor(*map, i);
   3648       if (details.kind() == kData) {
   3649         if (object->IsUnboxedDoubleField(index)) {
   3650           double old_value = object->RawFastDoublePropertyAt(index);
   3651           value = isolate->factory()->NewHeapNumber(old_value);
   3652         } else {
   3653           value = handle(object->RawFastPropertyAt(index), isolate);
   3654           if (details.representation().IsDouble()) {
   3655             DCHECK(value->IsMutableHeapNumber());
   3656             Handle<HeapNumber> old = Handle<HeapNumber>::cast(value);
   3657             value = isolate->factory()->NewHeapNumber(old->value());
   3658           }
   3659         }
   3660       } else {
   3661         DCHECK_EQ(kAccessor, details.kind());
   3662         value = handle(object->RawFastPropertyAt(index), isolate);
   3663       }
   3664 
   3665     } else {
   3666       DCHECK_EQ(kDescriptor, details.location());
   3667       value = handle(descs->GetValue(i), isolate);
   3668     }
   3669     DCHECK(!value.is_null());
   3670     PropertyDetails d(details.kind(), details.attributes(), i + 1,
   3671                       PropertyCellType::kNoCell);
   3672     dictionary = NameDictionary::Add(dictionary, key, value, d);
   3673   }
   3674 
   3675   // Copy the next enumeration index from instance descriptor.
   3676   dictionary->SetNextEnumerationIndex(real_size + 1);
   3677 
   3678   // From here on we cannot fail and we shouldn't GC anymore.
   3679   DisallowHeapAllocation no_allocation;
   3680 
   3681   Heap* heap = isolate->heap();
   3682   heap->NotifyObjectLayoutChange(*object, no_allocation);
   3683 
   3684   // Resize the object in the heap if necessary.
   3685   int new_instance_size = new_map->instance_size();
   3686   int instance_size_delta = map->instance_size() - new_instance_size;
   3687   DCHECK(instance_size_delta >= 0);
   3688 
   3689   if (instance_size_delta > 0) {
   3690     heap->CreateFillerObjectAt(object->address() + new_instance_size,
   3691                                instance_size_delta, ClearRecordedSlots::kYes);
   3692     heap->AdjustLiveBytes(*object, -instance_size_delta);
   3693   }
   3694 
   3695   // We are storing the new map using release store after creating a filler for
   3696   // the left-over space to avoid races with the sweeper thread.
   3697   object->synchronized_set_map(*new_map);
   3698 
   3699   object->set_properties(*dictionary);
   3700 
   3701   // Ensure that in-object space of slow-mode object does not contain random
   3702   // garbage.
   3703   int inobject_properties = new_map->GetInObjectProperties();
   3704   if (inobject_properties) {
   3705     Heap* heap = isolate->heap();
   3706     heap->ClearRecordedSlotRange(
   3707         object->address() + map->GetInObjectPropertyOffset(0),
   3708         object->address() + new_instance_size);
   3709 
   3710     for (int i = 0; i < inobject_properties; i++) {
   3711       FieldIndex index = FieldIndex::ForPropertyIndex(*new_map, i);
   3712       object->RawFastPropertyAtPut(index, Smi::kZero);
   3713     }
   3714   }
   3715 
   3716   isolate->counters()->props_to_dictionary()->Increment();
   3717 
   3718 #ifdef DEBUG
   3719   if (FLAG_trace_normalization) {
   3720     OFStream os(stdout);
   3721     os << "Object properties have been normalized:\n";
   3722     object->Print(os);
   3723   }
   3724 #endif
   3725 }
   3726 
   3727 }  // namespace
   3728 
   3729 // static
   3730 void JSObject::NotifyMapChange(Handle<Map> old_map, Handle<Map> new_map,
   3731                                Isolate* isolate) {
   3732   if (!old_map->is_prototype_map()) return;
   3733 
   3734   InvalidatePrototypeChains(*old_map);
   3735 
   3736   // If the map was registered with its prototype before, ensure that it
   3737   // registers with its new prototype now. This preserves the invariant that
   3738   // when a map on a prototype chain is registered with its prototype, then
   3739   // all prototypes further up the chain are also registered with their
   3740   // respective prototypes.
   3741   UpdatePrototypeUserRegistration(old_map, new_map, isolate);
   3742 }
   3743 
   3744 void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map,
   3745                             int expected_additional_properties) {
   3746   if (object->map() == *new_map) return;
   3747   Handle<Map> old_map(object->map());
   3748   NotifyMapChange(old_map, new_map, new_map->GetIsolate());
   3749 
   3750   if (old_map->is_dictionary_map()) {
   3751     // For slow-to-fast migrations JSObject::MigrateSlowToFast()
   3752     // must be used instead.
   3753     CHECK(new_map->is_dictionary_map());
   3754 
   3755     // Slow-to-slow migration is trivial.
   3756     object->set_map(*new_map);
   3757   } else if (!new_map->is_dictionary_map()) {
   3758     MigrateFastToFast(object, new_map);
   3759     if (old_map->is_prototype_map()) {
   3760       DCHECK(!old_map->is_stable());
   3761       DCHECK(new_map->is_stable());
   3762       // Clear out the old descriptor array to avoid problems to sharing
   3763       // the descriptor array without using an explicit.
   3764       old_map->InitializeDescriptors(
   3765           old_map->GetHeap()->empty_descriptor_array(),
   3766           LayoutDescriptor::FastPointerLayout());
   3767       // Ensure that no transition was inserted for prototype migrations.
   3768       DCHECK_EQ(
   3769           0, TransitionArray::NumberOfTransitions(old_map->raw_transitions()));
   3770       DCHECK(new_map->GetBackPointer()->IsUndefined(new_map->GetIsolate()));
   3771     }
   3772   } else {
   3773     MigrateFastToSlow(object, new_map, expected_additional_properties);
   3774   }
   3775 
   3776   // Careful: Don't allocate here!
   3777   // For some callers of this method, |object| might be in an inconsistent
   3778   // state now: the new map might have a new elements_kind, but the object's
   3779   // elements pointer hasn't been updated yet. Callers will fix this, but in
   3780   // the meantime, (indirectly) calling JSObjectVerify() must be avoided.
   3781   // When adding code here, add a DisallowHeapAllocation too.
   3782 }
   3783 
   3784 void JSObject::ForceSetPrototype(Handle<JSObject> object,
   3785                                  Handle<Object> proto) {
   3786   // object.__proto__ = proto;
   3787   Handle<Map> old_map = Handle<Map>(object->map());
   3788   Handle<Map> new_map = Map::Copy(old_map, "ForceSetPrototype");
   3789   Map::SetPrototype(new_map, proto, FAST_PROTOTYPE);
   3790   JSObject::MigrateToMap(object, new_map);
   3791 }
   3792 
   3793 int Map::NumberOfFields() {
   3794   DescriptorArray* descriptors = instance_descriptors();
   3795   int result = 0;
   3796   for (int i = 0; i < NumberOfOwnDescriptors(); i++) {
   3797     if (descriptors->GetDetails(i).location() == kField) result++;
   3798   }
   3799   return result;
   3800 }
   3801 
   3802 void DescriptorArray::GeneralizeAllFields() {
   3803   int length = number_of_descriptors();
   3804   for (int i = 0; i < length; i++) {
   3805     PropertyDetails details = GetDetails(i);
   3806     details = details.CopyWithRepresentation(Representation::Tagged());
   3807     if (details.location() == kField) {
   3808       DCHECK_EQ(kData, details.kind());
   3809       details = details.CopyWithConstness(kMutable);
   3810       SetValue(i, FieldType::Any());
   3811     }
   3812     set(ToDetailsIndex(i), details.AsSmi());
   3813   }
   3814 }
   3815 
   3816 Handle<Map> Map::CopyGeneralizeAllFields(Handle<Map> map,
   3817                                          ElementsKind elements_kind,
   3818                                          int modify_index, PropertyKind kind,
   3819                                          PropertyAttributes attributes,
   3820                                          const char* reason) {
   3821   Isolate* isolate = map->GetIsolate();
   3822   Handle<DescriptorArray> old_descriptors(map->instance_descriptors(), isolate);
   3823   int number_of_own_descriptors = map->NumberOfOwnDescriptors();
   3824   Handle<DescriptorArray> descriptors =
   3825       DescriptorArray::CopyUpTo(old_descriptors, number_of_own_descriptors);
   3826   descriptors->GeneralizeAllFields();
   3827 
   3828   Handle<LayoutDescriptor> new_layout_descriptor(
   3829       LayoutDescriptor::FastPointerLayout(), isolate);
   3830   Handle<Map> new_map = CopyReplaceDescriptors(
   3831       map, descriptors, new_layout_descriptor, OMIT_TRANSITION,
   3832       MaybeHandle<Name>(), reason, SPECIAL_TRANSITION);
   3833 
   3834   // Unless the instance is being migrated, ensure that modify_index is a field.
   3835   if (modify_index >= 0) {
   3836     PropertyDetails details = descriptors->GetDetails(modify_index);
   3837     if (details.constness() != kMutable || details.location() != kField ||
   3838         details.attributes() != attributes) {
   3839       int field_index = details.location() == kField
   3840                             ? details.field_index()
   3841                             : new_map->NumberOfFields();
   3842       Descriptor d = Descriptor::DataField(
   3843           handle(descriptors->GetKey(modify_index), isolate), field_index,
   3844           attributes, Representation::Tagged());
   3845       descriptors->Replace(modify_index, &d);
   3846       if (details.location() != kField) {
   3847         int unused_property_fields = new_map->unused_property_fields() - 1;
   3848         if (unused_property_fields < 0) {
   3849           unused_property_fields += JSObject::kFieldsAdded;
   3850         }
   3851         new_map->set_unused_property_fields(unused_property_fields);
   3852       }
   3853     } else {
   3854       DCHECK(details.attributes() == attributes);
   3855     }
   3856 
   3857     if (FLAG_trace_generalization) {
   3858       MaybeHandle<FieldType> field_type = FieldType::None(isolate);
   3859       if (details.location() == kField) {
   3860         field_type = handle(
   3861             map->instance_descriptors()->GetFieldType(modify_index), isolate);
   3862       }
   3863       map->PrintGeneralization(
   3864           stdout, reason, modify_index, new_map->NumberOfOwnDescriptors(),
   3865           new_map->NumberOfOwnDescriptors(), details.location() == kDescriptor,
   3866           details.representation(), Representation::Tagged(), field_type,
   3867           MaybeHandle<Object>(), FieldType::Any(isolate),
   3868           MaybeHandle<Object>());
   3869     }
   3870   }
   3871   new_map->set_elements_kind(elements_kind);
   3872   return new_map;
   3873 }
   3874 
   3875 
   3876 void Map::DeprecateTransitionTree() {
   3877   if (is_deprecated()) return;
   3878   Object* transitions = raw_transitions();
   3879   int num_transitions = TransitionArray::NumberOfTransitions(transitions);
   3880   for (int i = 0; i < num_transitions; ++i) {
   3881     TransitionArray::GetTarget(transitions, i)->DeprecateTransitionTree();
   3882   }
   3883   deprecate();
   3884   dependent_code()->DeoptimizeDependentCodeGroup(
   3885       GetIsolate(), DependentCode::kTransitionGroup);
   3886   NotifyLeafMapLayoutChange();
   3887 }
   3888 
   3889 
   3890 // Installs |new_descriptors| over the current instance_descriptors to ensure
   3891 // proper sharing of descriptor arrays.
   3892 void Map::ReplaceDescriptors(DescriptorArray* new_descriptors,
   3893                              LayoutDescriptor* new_layout_descriptor) {
   3894   Isolate* isolate = GetIsolate();
   3895   // Don't overwrite the empty descriptor array or initial map's descriptors.
   3896   if (NumberOfOwnDescriptors() == 0 || GetBackPointer()->IsUndefined(isolate)) {
   3897     return;
   3898   }
   3899 
   3900   DescriptorArray* to_replace = instance_descriptors();
   3901   isolate->heap()->incremental_marking()->IterateBlackObject(to_replace);
   3902   Map* current = this;
   3903   while (current->instance_descriptors() == to_replace) {
   3904     Object* next = current->GetBackPointer();
   3905     if (next->IsUndefined(isolate)) break;  // Stop overwriting at initial map.
   3906     current->SetEnumLength(kInvalidEnumCacheSentinel);
   3907     current->UpdateDescriptors(new_descriptors, new_layout_descriptor);
   3908     current = Map::cast(next);
   3909   }
   3910   set_owns_descriptors(false);
   3911 }
   3912 
   3913 
   3914 Map* Map::FindRootMap() {
   3915   Map* result = this;
   3916   Isolate* isolate = GetIsolate();
   3917   while (true) {
   3918     Object* back = result->GetBackPointer();
   3919     if (back->IsUndefined(isolate)) {
   3920       // Initial map always owns descriptors and doesn't have unused entries
   3921       // in the descriptor array.
   3922       DCHECK(result->owns_descriptors());
   3923       DCHECK_EQ(result->NumberOfOwnDescriptors(),
   3924                 result->instance_descriptors()->number_of_descriptors());
   3925       return result;
   3926     }
   3927     result = Map::cast(back);
   3928   }
   3929 }
   3930 
   3931 
   3932 Map* Map::FindFieldOwner(int descriptor) {
   3933   DisallowHeapAllocation no_allocation;
   3934   DCHECK_EQ(kField, instance_descriptors()->GetDetails(descriptor).location());
   3935   Map* result = this;
   3936   Isolate* isolate = GetIsolate();
   3937   while (true) {
   3938     Object* back = result->GetBackPointer();
   3939     if (back->IsUndefined(isolate)) break;
   3940     Map* parent = Map::cast(back);
   3941     if (parent->NumberOfOwnDescriptors() <= descriptor) break;
   3942     result = parent;
   3943   }
   3944   return result;
   3945 }
   3946 
   3947 void Map::UpdateFieldType(int descriptor, Handle<Name> name,
   3948                           PropertyConstness new_constness,
   3949                           Representation new_representation,
   3950                           Handle<Object> new_wrapped_type) {
   3951   DCHECK(new_wrapped_type->IsSmi() || new_wrapped_type->IsWeakCell());
   3952   // We store raw pointers in the queue, so no allocations are allowed.
   3953   DisallowHeapAllocation no_allocation;
   3954   PropertyDetails details = instance_descriptors()->GetDetails(descriptor);
   3955   if (details.location() != kField) return;
   3956   DCHECK_EQ(kData, details.kind());
   3957 
   3958   Zone zone(GetIsolate()->allocator(), ZONE_NAME);
   3959   ZoneQueue<Map*> backlog(&zone);
   3960   backlog.push(this);
   3961 
   3962   while (!backlog.empty()) {
   3963     Map* current = backlog.front();
   3964     backlog.pop();
   3965 
   3966     Object* transitions = current->raw_transitions();
   3967     int num_transitions = TransitionArray::NumberOfTransitions(transitions);
   3968     for (int i = 0; i < num_transitions; ++i) {
   3969       Map* target = TransitionArray::GetTarget(transitions, i);
   3970       backlog.push(target);
   3971     }
   3972     DescriptorArray* descriptors = current->instance_descriptors();
   3973     PropertyDetails details = descriptors->GetDetails(descriptor);
   3974 
   3975     // Currently constness change implies map change.
   3976     DCHECK_EQ(new_constness, details.constness());
   3977 
   3978     // It is allowed to change representation here only from None to something.
   3979     DCHECK(details.representation().Equals(new_representation) ||
   3980            details.representation().IsNone());
   3981 
   3982     // Skip if already updated the shared descriptor.
   3983     if (descriptors->GetValue(descriptor) != *new_wrapped_type) {
   3984       DCHECK_IMPLIES(!FLAG_track_constant_fields, new_constness == kMutable);
   3985       Descriptor d = Descriptor::DataField(
   3986           name, descriptors->GetFieldIndex(descriptor), details.attributes(),
   3987           new_constness, new_representation, new_wrapped_type);
   3988       descriptors->Replace(descriptor, &d);
   3989     }
   3990   }
   3991 }
   3992 
   3993 bool FieldTypeIsCleared(Representation rep, FieldType* type) {
   3994   return type->IsNone() && rep.IsHeapObject();
   3995 }
   3996 
   3997 
   3998 // static
   3999 Handle<FieldType> Map::GeneralizeFieldType(Representation rep1,
   4000                                            Handle<FieldType> type1,
   4001                                            Representation rep2,
   4002                                            Handle<FieldType> type2,
   4003                                            Isolate* isolate) {
   4004   // Cleared field types need special treatment. They represent lost knowledge,
   4005   // so we must be conservative, so their generalization with any other type
   4006   // is "Any".
   4007   if (FieldTypeIsCleared(rep1, *type1) || FieldTypeIsCleared(rep2, *type2)) {
   4008     return FieldType::Any(isolate);
   4009   }
   4010   if (type1->NowIs(type2)) return type2;
   4011   if (type2->NowIs(type1)) return type1;
   4012   return FieldType::Any(isolate);
   4013 }
   4014 
   4015 
   4016 // static
   4017 void Map::GeneralizeField(Handle<Map> map, int modify_index,
   4018                           PropertyConstness new_constness,
   4019                           Representation new_representation,
   4020                           Handle<FieldType> new_field_type) {
   4021   Isolate* isolate = map->GetIsolate();
   4022 
   4023   // Check if we actually need to generalize the field type at all.
   4024   Handle<DescriptorArray> old_descriptors(map->instance_descriptors(), isolate);
   4025   PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
   4026   PropertyConstness old_constness = old_details.constness();
   4027   Representation old_representation = old_details.representation();
   4028   Handle<FieldType> old_field_type(old_descriptors->GetFieldType(modify_index),
   4029                                    isolate);
   4030 
   4031   if (old_constness == new_constness &&
   4032       old_representation.Equals(new_representation) &&
   4033       !FieldTypeIsCleared(new_representation, *new_field_type) &&
   4034       // Checking old_field_type for being cleared is not necessary because
   4035       // the NowIs check below would fail anyway in that case.
   4036       new_field_type->NowIs(old_field_type)) {
   4037     DCHECK(GeneralizeFieldType(old_representation, old_field_type,
   4038                                new_representation, new_field_type, isolate)
   4039                ->NowIs(old_field_type));
   4040     return;
   4041   }
   4042 
   4043   // Determine the field owner.
   4044   Handle<Map> field_owner(map->FindFieldOwner(modify_index), isolate);
   4045   Handle<DescriptorArray> descriptors(
   4046       field_owner->instance_descriptors(), isolate);
   4047   DCHECK_EQ(*old_field_type, descriptors->GetFieldType(modify_index));
   4048 
   4049   new_field_type =
   4050       Map::GeneralizeFieldType(old_representation, old_field_type,
   4051                                new_representation, new_field_type, isolate);
   4052 
   4053   PropertyDetails details = descriptors->GetDetails(modify_index);
   4054   Handle<Name> name(descriptors->GetKey(modify_index));
   4055 
   4056   Handle<Object> wrapped_type(WrapFieldType(new_field_type));
   4057   field_owner->UpdateFieldType(modify_index, name, new_constness,
   4058                                new_representation, wrapped_type);
   4059   field_owner->dependent_code()->DeoptimizeDependentCodeGroup(
   4060       isolate, DependentCode::kFieldOwnerGroup);
   4061 
   4062   if (FLAG_trace_generalization) {
   4063     map->PrintGeneralization(
   4064         stdout, "field type generalization", modify_index,
   4065         map->NumberOfOwnDescriptors(), map->NumberOfOwnDescriptors(), false,
   4066         details.representation(), details.representation(), old_field_type,
   4067         MaybeHandle<Object>(), new_field_type, MaybeHandle<Object>());
   4068   }
   4069 }
   4070 
   4071 // TODO(ishell): remove.
   4072 // static
   4073 Handle<Map> Map::ReconfigureProperty(Handle<Map> map, int modify_index,
   4074                                      PropertyKind new_kind,
   4075                                      PropertyAttributes new_attributes,
   4076                                      Representation new_representation,
   4077                                      Handle<FieldType> new_field_type) {
   4078   DCHECK_EQ(kData, new_kind);  // Only kData case is supported.
   4079   MapUpdater mu(map->GetIsolate(), map);
   4080   return mu.ReconfigureToDataField(modify_index, new_attributes, kConst,
   4081                                    new_representation, new_field_type);
   4082 }
   4083 
   4084 // TODO(ishell): remove.
   4085 // static
   4086 Handle<Map> Map::ReconfigureElementsKind(Handle<Map> map,
   4087                                          ElementsKind new_elements_kind) {
   4088   MapUpdater mu(map->GetIsolate(), map);
   4089   return mu.ReconfigureElementsKind(new_elements_kind);
   4090 }
   4091 
   4092 // Generalize all fields and update the transition tree.
   4093 Handle<Map> Map::GeneralizeAllFields(Handle<Map> map) {
   4094   Isolate* isolate = map->GetIsolate();
   4095   Handle<FieldType> any_type = FieldType::Any(isolate);
   4096 
   4097   Handle<DescriptorArray> descriptors(map->instance_descriptors());
   4098   for (int i = 0; i < map->NumberOfOwnDescriptors(); ++i) {
   4099     PropertyDetails details = descriptors->GetDetails(i);
   4100     if (details.location() == kField) {
   4101       DCHECK_EQ(kData, details.kind());
   4102       MapUpdater mu(isolate, map);
   4103       map = mu.ReconfigureToDataField(i, details.attributes(), kMutable,
   4104                                       Representation::Tagged(), any_type);
   4105     }
   4106   }
   4107   return map;
   4108 }
   4109 
   4110 
   4111 // static
   4112 MaybeHandle<Map> Map::TryUpdate(Handle<Map> old_map) {
   4113   DisallowHeapAllocation no_allocation;
   4114   DisallowDeoptimization no_deoptimization(old_map->GetIsolate());
   4115 
   4116   if (!old_map->is_deprecated()) return old_map;
   4117 
   4118   // Check the state of the root map.
   4119   Map* root_map = old_map->FindRootMap();
   4120   if (!old_map->EquivalentToForTransition(root_map)) return MaybeHandle<Map>();
   4121 
   4122   ElementsKind from_kind = root_map->elements_kind();
   4123   ElementsKind to_kind = old_map->elements_kind();
   4124   if (from_kind != to_kind) {
   4125     // Try to follow existing elements kind transitions.
   4126     root_map = root_map->LookupElementsTransitionMap(to_kind);
   4127     if (root_map == NULL) return MaybeHandle<Map>();
   4128     // From here on, use the map with correct elements kind as root map.
   4129   }
   4130   Map* new_map = root_map->TryReplayPropertyTransitions(*old_map);
   4131   if (new_map == nullptr) return MaybeHandle<Map>();
   4132   return handle(new_map);
   4133 }
   4134 
   4135 Map* Map::TryReplayPropertyTransitions(Map* old_map) {
   4136   DisallowHeapAllocation no_allocation;
   4137   DisallowDeoptimization no_deoptimization(GetIsolate());
   4138 
   4139   int root_nof = NumberOfOwnDescriptors();
   4140 
   4141   int old_nof = old_map->NumberOfOwnDescriptors();
   4142   DescriptorArray* old_descriptors = old_map->instance_descriptors();
   4143 
   4144   Map* new_map = this;
   4145   for (int i = root_nof; i < old_nof; ++i) {
   4146     PropertyDetails old_details = old_descriptors->GetDetails(i);
   4147     Map* transition = TransitionArray::SearchTransition(
   4148         new_map, old_details.kind(), old_descriptors->GetKey(i),
   4149         old_details.attributes());
   4150     if (transition == NULL) return nullptr;
   4151     new_map = transition;
   4152     DescriptorArray* new_descriptors = new_map->instance_descriptors();
   4153 
   4154     PropertyDetails new_details = new_descriptors->GetDetails(i);
   4155     DCHECK_EQ(old_details.kind(), new_details.kind());
   4156     DCHECK_EQ(old_details.attributes(), new_details.attributes());
   4157     if (!IsGeneralizableTo(old_details.constness(), new_details.constness())) {
   4158       return nullptr;
   4159     }
   4160     DCHECK(IsGeneralizableTo(old_details.location(), new_details.location()));
   4161     if (!old_details.representation().fits_into(new_details.representation())) {
   4162       return nullptr;
   4163     }
   4164     if (new_details.location() == kField) {
   4165       if (new_details.kind() == kData) {
   4166         FieldType* new_type = new_descriptors->GetFieldType(i);
   4167         // Cleared field types need special treatment. They represent lost
   4168         // knowledge, so we must first generalize the new_type to "Any".
   4169         if (FieldTypeIsCleared(new_details.representation(), new_type)) {
   4170           return nullptr;
   4171         }
   4172         DCHECK_EQ(kData, old_details.kind());
   4173         if (old_details.location() == kField) {
   4174           FieldType* old_type = old_descriptors->GetFieldType(i);
   4175           if (FieldTypeIsCleared(old_details.representation(), old_type) ||
   4176               !old_type->NowIs(new_type)) {
   4177             return nullptr;
   4178           }
   4179         } else {
   4180           DCHECK_EQ(kDescriptor, old_details.location());
   4181           DCHECK(!FLAG_track_constant_fields);
   4182           Object* old_value = old_descriptors->GetValue(i);
   4183           if (!new_type->NowContains(old_value)) {
   4184             return nullptr;
   4185           }
   4186         }
   4187 
   4188       } else {
   4189         DCHECK_EQ(kAccessor, new_details.kind());
   4190 #ifdef DEBUG
   4191         FieldType* new_type = new_descriptors->GetFieldType(i);
   4192         DCHECK(new_type->IsAny());
   4193 #endif
   4194         UNREACHABLE();
   4195       }
   4196     } else {
   4197       DCHECK_EQ(kDescriptor, new_details.location());
   4198       Object* old_value = old_descriptors->GetValue(i);
   4199       Object* new_value = new_descriptors->GetValue(i);
   4200       if (old_details.location() == kField || old_value != new_value) {
   4201         return nullptr;
   4202       }
   4203     }
   4204   }
   4205   if (new_map->NumberOfOwnDescriptors() != old_nof) return nullptr;
   4206   return new_map;
   4207 }
   4208 
   4209 
   4210 // static
   4211 Handle<Map> Map::Update(Handle<Map> map) {
   4212   if (!map->is_deprecated()) return map;
   4213   MapUpdater mu(map->GetIsolate(), map);
   4214   return mu.Update();
   4215 }
   4216 
   4217 Maybe<bool> JSObject::SetPropertyWithInterceptor(LookupIterator* it,
   4218                                                  ShouldThrow should_throw,
   4219                                                  Handle<Object> value) {
   4220   DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
   4221   return SetPropertyWithInterceptorInternal(it, it->GetInterceptor(),
   4222                                             should_throw, value);
   4223 }
   4224 
   4225 MaybeHandle<Object> Object::SetProperty(Handle<Object> object,
   4226                                         Handle<Name> name, Handle<Object> value,
   4227                                         LanguageMode language_mode,
   4228                                         StoreFromKeyed store_mode) {
   4229   LookupIterator it(object, name);
   4230   MAYBE_RETURN_NULL(SetProperty(&it, value, language_mode, store_mode));
   4231   return value;
   4232 }
   4233 
   4234 
   4235 Maybe<bool> Object::SetPropertyInternal(LookupIterator* it,
   4236                                         Handle<Object> value,
   4237                                         LanguageMode language_mode,
   4238                                         StoreFromKeyed store_mode,
   4239                                         bool* found) {
   4240   it->UpdateProtector();
   4241   DCHECK(it->IsFound());
   4242   ShouldThrow should_throw =
   4243       is_sloppy(language_mode) ? DONT_THROW : THROW_ON_ERROR;
   4244 
   4245   // Make sure that the top context does not change when doing callbacks or
   4246   // interceptor calls.
   4247   AssertNoContextChange ncc(it->isolate());
   4248 
   4249   do {
   4250     switch (it->state()) {
   4251       case LookupIterator::NOT_FOUND:
   4252         UNREACHABLE();
   4253 
   4254       case LookupIterator::ACCESS_CHECK:
   4255         if (it->HasAccess()) break;
   4256         // Check whether it makes sense to reuse the lookup iterator. Here it
   4257         // might still call into setters up the prototype chain.
   4258         return JSObject::SetPropertyWithFailedAccessCheck(it, value,
   4259                                                           should_throw);
   4260 
   4261       case LookupIterator::JSPROXY:
   4262         return JSProxy::SetProperty(it->GetHolder<JSProxy>(), it->GetName(),
   4263                                     value, it->GetReceiver(), language_mode);
   4264 
   4265       case LookupIterator::INTERCEPTOR: {
   4266         if (it->HolderIsReceiverOrHiddenPrototype()) {
   4267           Maybe<bool> result =
   4268               JSObject::SetPropertyWithInterceptor(it, should_throw, value);
   4269           if (result.IsNothing() || result.FromJust()) return result;
   4270         } else {
   4271           Maybe<PropertyAttributes> maybe_attributes =
   4272               JSObject::GetPropertyAttributesWithInterceptor(it);
   4273           if (!maybe_attributes.IsJust()) return Nothing<bool>();
   4274           if ((maybe_attributes.FromJust() & READ_ONLY) != 0) {
   4275             return WriteToReadOnlyProperty(it, value, should_throw);
   4276           }
   4277           if (maybe_attributes.FromJust() == ABSENT) break;
   4278           *found = false;
   4279           return Nothing<bool>();
   4280         }
   4281         break;
   4282       }
   4283 
   4284       case LookupIterator::ACCESSOR: {
   4285         if (it->IsReadOnly()) {
   4286           return WriteToReadOnlyProperty(it, value, should_throw);
   4287         }
   4288         Handle<Object> accessors = it->GetAccessors();
   4289         if (accessors->IsAccessorInfo() &&
   4290             !it->HolderIsReceiverOrHiddenPrototype() &&
   4291             AccessorInfo::cast(*accessors)->is_special_data_property()) {
   4292           *found = false;
   4293           return Nothing<bool>();
   4294         }
   4295         return SetPropertyWithAccessor(it, value, should_throw);
   4296       }
   4297       case LookupIterator::INTEGER_INDEXED_EXOTIC:
   4298         // TODO(verwaest): We should throw an exception if holder is receiver.
   4299         return Just(true);
   4300 
   4301       case LookupIterator::DATA:
   4302         if (it->IsReadOnly()) {
   4303           return WriteToReadOnlyProperty(it, value, should_throw);
   4304         }
   4305         if (it->HolderIsReceiverOrHiddenPrototype()) {
   4306           return SetDataProperty(it, value);
   4307         }
   4308       // Fall through.
   4309       case LookupIterator::TRANSITION:
   4310         *found = false;
   4311         return Nothing<bool>();
   4312     }
   4313     it->Next();
   4314   } while (it->IsFound());
   4315 
   4316   *found = false;
   4317   return Nothing<bool>();
   4318 }
   4319 
   4320 
   4321 Maybe<bool> Object::SetProperty(LookupIterator* it, Handle<Object> value,
   4322                                 LanguageMode language_mode,
   4323                                 StoreFromKeyed store_mode) {
   4324   if (it->IsFound()) {
   4325     bool found = true;
   4326     Maybe<bool> result =
   4327         SetPropertyInternal(it, value, language_mode, store_mode, &found);
   4328     if (found) return result;
   4329   }
   4330 
   4331   // If the receiver is the JSGlobalObject, the store was contextual. In case
   4332   // the property did not exist yet on the global object itself, we have to
   4333   // throw a reference error in strict mode.  In sloppy mode, we continue.
   4334   if (is_strict(language_mode) && it->GetReceiver()->IsJSGlobalObject()) {
   4335     it->isolate()->Throw(*it->isolate()->factory()->NewReferenceError(
   4336         MessageTemplate::kNotDefined, it->name()));
   4337     return Nothing<bool>();
   4338   }
   4339 
   4340   ShouldThrow should_throw =
   4341       is_sloppy(language_mode) ? DONT_THROW : THROW_ON_ERROR;
   4342   return AddDataProperty(it, value, NONE, should_throw, store_mode);
   4343 }
   4344 
   4345 
   4346 Maybe<bool> Object::SetSuperProperty(LookupIterator* it, Handle<Object> value,
   4347                                      LanguageMode language_mode,
   4348                                      StoreFromKeyed store_mode) {
   4349   Isolate* isolate = it->isolate();
   4350 
   4351   if (it->IsFound()) {
   4352     bool found = true;
   4353     Maybe<bool> result =
   4354         SetPropertyInternal(it, value, language_mode, store_mode, &found);
   4355     if (found) return result;
   4356   }
   4357 
   4358   it->UpdateProtector();
   4359 
   4360   // The property either doesn't exist on the holder or exists there as a data
   4361   // property.
   4362 
   4363   ShouldThrow should_throw =
   4364       is_sloppy(language_mode) ? DONT_THROW : THROW_ON_ERROR;
   4365 
   4366   if (!it->GetReceiver()->IsJSReceiver()) {
   4367     return WriteToReadOnlyProperty(it, value, should_throw);
   4368   }
   4369   Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(it->GetReceiver());
   4370 
   4371   LookupIterator::Configuration c = LookupIterator::OWN;
   4372   LookupIterator own_lookup =
   4373       it->IsElement() ? LookupIterator(isolate, receiver, it->index(), c)
   4374                       : LookupIterator(receiver, it->name(), c);
   4375 
   4376   for (; own_lookup.IsFound(); own_lookup.Next()) {
   4377     switch (own_lookup.state()) {
   4378       case LookupIterator::ACCESS_CHECK:
   4379         if (!own_lookup.HasAccess()) {
   4380           return JSObject::SetPropertyWithFailedAccessCheck(&own_lookup, value,
   4381                                                             should_throw);
   4382         }
   4383         break;
   4384 
   4385       case LookupIterator::ACCESSOR:
   4386         if (own_lookup.GetAccessors()->IsAccessorInfo()) {
   4387           if (own_lookup.IsReadOnly()) {
   4388             return WriteToReadOnlyProperty(&own_lookup, value, should_throw);
   4389           }
   4390           return JSObject::SetPropertyWithAccessor(&own_lookup, value,
   4391                                                    should_throw);
   4392         }
   4393       // Fall through.
   4394       case LookupIterator::INTEGER_INDEXED_EXOTIC:
   4395         return RedefineIncompatibleProperty(isolate, it->GetName(), value,
   4396                                             should_throw);
   4397 
   4398       case LookupIterator::DATA: {
   4399         if (own_lookup.IsReadOnly()) {
   4400           return WriteToReadOnlyProperty(&own_lookup, value, should_throw);
   4401         }
   4402         return SetDataProperty(&own_lookup, value);
   4403       }
   4404 
   4405       case LookupIterator::INTERCEPTOR:
   4406       case LookupIterator::JSPROXY: {
   4407         PropertyDescriptor desc;
   4408         Maybe<bool> owned =
   4409             JSReceiver::GetOwnPropertyDescriptor(&own_lookup, &desc);
   4410         MAYBE_RETURN(owned, Nothing<bool>());
   4411         if (!owned.FromJust()) {
   4412           return JSReceiver::CreateDataProperty(&own_lookup, value,
   4413                                                 should_throw);
   4414         }
   4415         if (PropertyDescriptor::IsAccessorDescriptor(&desc) ||
   4416             !desc.writable()) {
   4417           return RedefineIncompatibleProperty(isolate, it->GetName(), value,
   4418                                               should_throw);
   4419         }
   4420 
   4421         PropertyDescriptor value_desc;
   4422         value_desc.set_value(value);
   4423         return JSReceiver::DefineOwnProperty(isolate, receiver, it->GetName(),
   4424                                              &value_desc, should_throw);
   4425       }
   4426 
   4427       case LookupIterator::NOT_FOUND:
   4428       case LookupIterator::TRANSITION:
   4429         UNREACHABLE();
   4430     }
   4431   }
   4432 
   4433   return AddDataProperty(&own_lookup, value, NONE, should_throw, store_mode);
   4434 }
   4435 
   4436 Maybe<bool> Object::CannotCreateProperty(Isolate* isolate,
   4437                                          Handle<Object> receiver,
   4438                                          Handle<Object> name,
   4439                                          Handle<Object> value,
   4440                                          ShouldThrow should_throw) {
   4441   RETURN_FAILURE(
   4442       isolate, should_throw,
   4443       NewTypeError(MessageTemplate::kStrictCannotCreateProperty, name,
   4444                    Object::TypeOf(isolate, receiver), receiver));
   4445 }
   4446 
   4447 
   4448 Maybe<bool> Object::WriteToReadOnlyProperty(LookupIterator* it,
   4449                                             Handle<Object> value,
   4450                                             ShouldThrow should_throw) {
   4451   return WriteToReadOnlyProperty(it->isolate(), it->GetReceiver(),
   4452                                  it->GetName(), value, should_throw);
   4453 }
   4454 
   4455 
   4456 Maybe<bool> Object::WriteToReadOnlyProperty(Isolate* isolate,
   4457                                             Handle<Object> receiver,
   4458                                             Handle<Object> name,
   4459                                             Handle<Object> value,
   4460                                             ShouldThrow should_throw) {
   4461   RETURN_FAILURE(isolate, should_throw,
   4462                  NewTypeError(MessageTemplate::kStrictReadOnlyProperty, name,
   4463                               Object::TypeOf(isolate, receiver), receiver));
   4464 }
   4465 
   4466 
   4467 Maybe<bool> Object::RedefineIncompatibleProperty(Isolate* isolate,
   4468                                                  Handle<Object> name,
   4469                                                  Handle<Object> value,
   4470                                                  ShouldThrow should_throw) {
   4471   RETURN_FAILURE(isolate, should_throw,
   4472                  NewTypeError(MessageTemplate::kRedefineDisallowed, name));
   4473 }
   4474 
   4475 
   4476 Maybe<bool> Object::SetDataProperty(LookupIterator* it, Handle<Object> value) {
   4477   // Proxies are handled elsewhere. Other non-JSObjects cannot have own
   4478   // properties.
   4479   Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver());
   4480 
   4481   // Store on the holder which may be hidden behind the receiver.
   4482   DCHECK(it->HolderIsReceiverOrHiddenPrototype());
   4483 
   4484   Handle<Object> to_assign = value;
   4485   // Convert the incoming value to a number for storing into typed arrays.
   4486   if (it->IsElement() && receiver->HasFixedTypedArrayElements()) {
   4487     if (!value->IsNumber() && !value->IsUndefined(it->isolate())) {
   4488       ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   4489           it->isolate(), to_assign, Object::ToNumber(value), Nothing<bool>());
   4490       // We have to recheck the length. However, it can only change if the
   4491       // underlying buffer was neutered, so just check that.
   4492       if (Handle<JSArrayBufferView>::cast(receiver)->WasNeutered()) {
   4493         return Just(true);
   4494         // TODO(neis): According to the spec, this should throw a TypeError.
   4495       }
   4496     }
   4497   }
   4498 
   4499   // Possibly migrate to the most up-to-date map that will be able to store
   4500   // |value| under it->name().
   4501   it->PrepareForDataProperty(to_assign);
   4502 
   4503   // Write the property value.
   4504   it->WriteDataValue(to_assign, false);
   4505 
   4506 #if VERIFY_HEAP
   4507   if (FLAG_verify_heap) {
   4508     receiver->JSObjectVerify();
   4509   }
   4510 #endif
   4511   return Just(true);
   4512 }
   4513 
   4514 
   4515 Maybe<bool> Object::AddDataProperty(LookupIterator* it, Handle<Object> value,
   4516                                     PropertyAttributes attributes,
   4517                                     ShouldThrow should_throw,
   4518                                     StoreFromKeyed store_mode) {
   4519   if (!it->GetReceiver()->IsJSObject()) {
   4520     if (it->GetReceiver()->IsJSProxy() && it->GetName()->IsPrivate()) {
   4521       RETURN_FAILURE(it->isolate(), should_throw,
   4522                      NewTypeError(MessageTemplate::kProxyPrivate));
   4523     }
   4524     return CannotCreateProperty(it->isolate(), it->GetReceiver(), it->GetName(),
   4525                                 value, should_throw);
   4526   }
   4527 
   4528   DCHECK_NE(LookupIterator::INTEGER_INDEXED_EXOTIC, it->state());
   4529 
   4530   Handle<JSObject> receiver = it->GetStoreTarget();
   4531 
   4532   // If the receiver is a JSGlobalProxy, store on the prototype (JSGlobalObject)
   4533   // instead. If the prototype is Null, the proxy is detached.
   4534   if (receiver->IsJSGlobalProxy()) return Just(true);
   4535 
   4536   Isolate* isolate = it->isolate();
   4537 
   4538   if (it->ExtendingNonExtensible(receiver)) {
   4539     RETURN_FAILURE(
   4540         isolate, should_throw,
   4541         NewTypeError(MessageTemplate::kObjectNotExtensible, it->GetName()));
   4542   }
   4543 
   4544   if (it->IsElement()) {
   4545     if (receiver->IsJSArray()) {
   4546       Handle<JSArray> array = Handle<JSArray>::cast(receiver);
   4547       if (JSArray::WouldChangeReadOnlyLength(array, it->index())) {
   4548         RETURN_FAILURE(array->GetIsolate(), should_throw,
   4549                        NewTypeError(MessageTemplate::kStrictReadOnlyProperty,
   4550                                     isolate->factory()->length_string(),
   4551                                     Object::TypeOf(isolate, array), array));
   4552       }
   4553 
   4554       if (FLAG_trace_external_array_abuse &&
   4555           array->HasFixedTypedArrayElements()) {
   4556         CheckArrayAbuse(array, "typed elements write", it->index(), true);
   4557       }
   4558 
   4559       if (FLAG_trace_js_array_abuse && !array->HasFixedTypedArrayElements()) {
   4560         CheckArrayAbuse(array, "elements write", it->index(), false);
   4561       }
   4562     }
   4563 
   4564     Maybe<bool> result = JSObject::AddDataElement(receiver, it->index(), value,
   4565                                                   attributes, should_throw);
   4566     JSObject::ValidateElements(receiver);
   4567     return result;
   4568   } else {
   4569     it->UpdateProtector();
   4570     // Migrate to the most up-to-date map that will be able to store |value|
   4571     // under it->name() with |attributes|.
   4572     it->PrepareTransitionToDataProperty(receiver, value, attributes,
   4573                                         store_mode);
   4574     DCHECK_EQ(LookupIterator::TRANSITION, it->state());
   4575     it->ApplyTransitionToDataProperty(receiver);
   4576 
   4577     // Write the property value.
   4578     it->WriteDataValue(value, true);
   4579 
   4580 #if VERIFY_HEAP
   4581     if (FLAG_verify_heap) {
   4582       receiver->JSObjectVerify();
   4583     }
   4584 #endif
   4585   }
   4586 
   4587   return Just(true);
   4588 }
   4589 
   4590 
   4591 void Map::EnsureDescriptorSlack(Handle<Map> map, int slack) {
   4592   // Only supports adding slack to owned descriptors.
   4593   DCHECK(map->owns_descriptors());
   4594 
   4595   Handle<DescriptorArray> descriptors(map->instance_descriptors());
   4596   int old_size = map->NumberOfOwnDescriptors();
   4597   if (slack <= descriptors->NumberOfSlackDescriptors()) return;
   4598 
   4599   Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo(
   4600       descriptors, old_size, slack);
   4601 
   4602   DisallowHeapAllocation no_allocation;
   4603   // The descriptors are still the same, so keep the layout descriptor.
   4604   LayoutDescriptor* layout_descriptor = map->GetLayoutDescriptor();
   4605 
   4606   if (old_size == 0) {
   4607     map->UpdateDescriptors(*new_descriptors, layout_descriptor);
   4608     return;
   4609   }
   4610 
   4611   // If the source descriptors had an enum cache we copy it. This ensures
   4612   // that the maps to which we push the new descriptor array back can rely
   4613   // on a cache always being available once it is set. If the map has more
   4614   // enumerated descriptors than available in the original cache, the cache
   4615   // will be lazily replaced by the extended cache when needed.
   4616   if (descriptors->HasEnumCache()) {
   4617     new_descriptors->CopyEnumCacheFrom(*descriptors);
   4618   }
   4619 
   4620   Isolate* isolate = map->GetIsolate();
   4621   // Replace descriptors by new_descriptors in all maps that share it.
   4622   isolate->heap()->incremental_marking()->IterateBlackObject(*descriptors);
   4623 
   4624   Map* current = *map;
   4625   while (current->instance_descriptors() == *descriptors) {
   4626     Object* next = current->GetBackPointer();
   4627     if (next->IsUndefined(isolate)) break;  // Stop overwriting at initial map.
   4628     current->UpdateDescriptors(*new_descriptors, layout_descriptor);
   4629     current = Map::cast(next);
   4630   }
   4631   map->UpdateDescriptors(*new_descriptors, layout_descriptor);
   4632 }
   4633 
   4634 // static
   4635 Handle<Map> Map::GetObjectCreateMap(Handle<HeapObject> prototype) {
   4636   Isolate* isolate = prototype->GetIsolate();
   4637   Handle<Map> map(isolate->native_context()->object_function()->initial_map(),
   4638                   isolate);
   4639   if (map->prototype() == *prototype) return map;
   4640   if (prototype->IsNull(isolate)) {
   4641     return isolate->slow_object_with_null_prototype_map();
   4642   }
   4643   if (prototype->IsJSObject()) {
   4644     Handle<JSObject> js_prototype = Handle<JSObject>::cast(prototype);
   4645     if (!js_prototype->map()->is_prototype_map()) {
   4646       JSObject::OptimizeAsPrototype(js_prototype, FAST_PROTOTYPE);
   4647     }
   4648     Handle<PrototypeInfo> info =
   4649         Map::GetOrCreatePrototypeInfo(js_prototype, isolate);
   4650     // TODO(verwaest): Use inobject slack tracking for this map.
   4651     if (info->HasObjectCreateMap()) {
   4652       map = handle(info->ObjectCreateMap(), isolate);
   4653     } else {
   4654       map = Map::CopyInitialMap(map);
   4655       Map::SetPrototype(map, prototype, FAST_PROTOTYPE);
   4656       PrototypeInfo::SetObjectCreateMap(info, map);
   4657     }
   4658     return map;
   4659   }
   4660 
   4661   return Map::TransitionToPrototype(map, prototype, REGULAR_PROTOTYPE);
   4662 }
   4663 
   4664 template <class T>
   4665 static int AppendUniqueCallbacks(Handle<TemplateList> callbacks,
   4666                                  Handle<typename T::Array> array,
   4667                                  int valid_descriptors) {
   4668   int nof_callbacks = callbacks->length();
   4669 
   4670   Isolate* isolate = array->GetIsolate();
   4671   // Ensure the keys are unique names before writing them into the
   4672   // instance descriptor. Since it may cause a GC, it has to be done before we
   4673   // temporarily put the heap in an invalid state while appending descriptors.
   4674   for (int i = 0; i < nof_callbacks; ++i) {
   4675     Handle<AccessorInfo> entry(AccessorInfo::cast(callbacks->get(i)));
   4676     if (entry->name()->IsUniqueName()) continue;
   4677     Handle<String> key =
   4678         isolate->factory()->InternalizeString(
   4679             Handle<String>(String::cast(entry->name())));
   4680     entry->set_name(*key);
   4681   }
   4682 
   4683   // Fill in new callback descriptors.  Process the callbacks from
   4684   // back to front so that the last callback with a given name takes
   4685   // precedence over previously added callbacks with that name.
   4686   for (int i = nof_callbacks - 1; i >= 0; i--) {
   4687     Handle<AccessorInfo> entry(AccessorInfo::cast(callbacks->get(i)));
   4688     Handle<Name> key(Name::cast(entry->name()));
   4689     // Check if a descriptor with this name already exists before writing.
   4690     if (!T::Contains(key, entry, valid_descriptors, array)) {
   4691       T::Insert(key, entry, valid_descriptors, array);
   4692       valid_descriptors++;
   4693     }
   4694   }
   4695 
   4696   return valid_descriptors;
   4697 }
   4698 
   4699 struct DescriptorArrayAppender {
   4700   typedef DescriptorArray Array;
   4701   static bool Contains(Handle<Name> key,
   4702                        Handle<AccessorInfo> entry,
   4703                        int valid_descriptors,
   4704                        Handle<DescriptorArray> array) {
   4705     DisallowHeapAllocation no_gc;
   4706     return array->Search(*key, valid_descriptors) != DescriptorArray::kNotFound;
   4707   }
   4708   static void Insert(Handle<Name> key,
   4709                      Handle<AccessorInfo> entry,
   4710                      int valid_descriptors,
   4711                      Handle<DescriptorArray> array) {
   4712     DisallowHeapAllocation no_gc;
   4713     Descriptor d =
   4714         Descriptor::AccessorConstant(key, entry, entry->property_attributes());
   4715     array->Append(&d);
   4716   }
   4717 };
   4718 
   4719 
   4720 struct FixedArrayAppender {
   4721   typedef FixedArray Array;
   4722   static bool Contains(Handle<Name> key,
   4723                        Handle<AccessorInfo> entry,
   4724                        int valid_descriptors,
   4725                        Handle<FixedArray> array) {
   4726     for (int i = 0; i < valid_descriptors; i++) {
   4727       if (*key == AccessorInfo::cast(array->get(i))->name()) return true;
   4728     }
   4729     return false;
   4730   }
   4731   static void Insert(Handle<Name> key,
   4732                      Handle<AccessorInfo> entry,
   4733                      int valid_descriptors,
   4734                      Handle<FixedArray> array) {
   4735     DisallowHeapAllocation no_gc;
   4736     array->set(valid_descriptors, *entry);
   4737   }
   4738 };
   4739 
   4740 
   4741 void Map::AppendCallbackDescriptors(Handle<Map> map,
   4742                                     Handle<Object> descriptors) {
   4743   int nof = map->NumberOfOwnDescriptors();
   4744   Handle<DescriptorArray> array(map->instance_descriptors());
   4745   Handle<TemplateList> callbacks = Handle<TemplateList>::cast(descriptors);
   4746   DCHECK_GE(array->NumberOfSlackDescriptors(), callbacks->length());
   4747   nof = AppendUniqueCallbacks<DescriptorArrayAppender>(callbacks, array, nof);
   4748   map->SetNumberOfOwnDescriptors(nof);
   4749 }
   4750 
   4751 
   4752 int AccessorInfo::AppendUnique(Handle<Object> descriptors,
   4753                                Handle<FixedArray> array,
   4754                                int valid_descriptors) {
   4755   Handle<TemplateList> callbacks = Handle<TemplateList>::cast(descriptors);
   4756   DCHECK_GE(array->length(), callbacks->length() + valid_descriptors);
   4757   return AppendUniqueCallbacks<FixedArrayAppender>(callbacks, array,
   4758                                                    valid_descriptors);
   4759 }
   4760 
   4761 
   4762 static bool ContainsMap(MapHandleList* maps, Map* map) {
   4763   DCHECK_NOT_NULL(map);
   4764   for (int i = 0; i < maps->length(); ++i) {
   4765     if (!maps->at(i).is_null() && *maps->at(i) == map) return true;
   4766   }
   4767   return false;
   4768 }
   4769 
   4770 Map* Map::FindElementsKindTransitionedMap(MapHandleList* candidates) {
   4771   DisallowHeapAllocation no_allocation;
   4772   DisallowDeoptimization no_deoptimization(GetIsolate());
   4773 
   4774   ElementsKind kind = elements_kind();
   4775   bool packed = IsFastPackedElementsKind(kind);
   4776 
   4777   Map* transition = nullptr;
   4778   if (IsTransitionableFastElementsKind(kind)) {
   4779     // Check the state of the root map.
   4780     Map* root_map = FindRootMap();
   4781     if (!EquivalentToForTransition(root_map)) return nullptr;
   4782     root_map = root_map->LookupElementsTransitionMap(kind);
   4783     DCHECK_NOT_NULL(root_map);
   4784     // Starting from the next existing elements kind transition try to
   4785     // replay the property transitions that does not involve instance rewriting
   4786     // (ElementsTransitionAndStoreStub does not support that).
   4787     for (root_map = root_map->ElementsTransitionMap();
   4788          root_map != nullptr && root_map->has_fast_elements();
   4789          root_map = root_map->ElementsTransitionMap()) {
   4790       Map* current = root_map->TryReplayPropertyTransitions(this);
   4791       if (current == nullptr) continue;
   4792       if (InstancesNeedRewriting(current)) continue;
   4793 
   4794       if (ContainsMap(candidates, current) &&
   4795           (packed || !IsFastPackedElementsKind(current->elements_kind()))) {
   4796         transition = current;
   4797         packed = packed && IsFastPackedElementsKind(current->elements_kind());
   4798       }
   4799     }
   4800   }
   4801   return transition;
   4802 }
   4803 
   4804 
   4805 static Map* FindClosestElementsTransition(Map* map, ElementsKind to_kind) {
   4806   // Ensure we are requested to search elements kind transition "near the root".
   4807   DCHECK_EQ(map->FindRootMap()->NumberOfOwnDescriptors(),
   4808             map->NumberOfOwnDescriptors());
   4809   Map* current_map = map;
   4810 
   4811   ElementsKind kind = map->elements_kind();
   4812   while (kind != to_kind) {
   4813     Map* next_map = current_map->ElementsTransitionMap();
   4814     if (next_map == nullptr) return current_map;
   4815     kind = next_map->elements_kind();
   4816     current_map = next_map;
   4817   }
   4818 
   4819   DCHECK_EQ(to_kind, current_map->elements_kind());
   4820   return current_map;
   4821 }
   4822 
   4823 
   4824 Map* Map::LookupElementsTransitionMap(ElementsKind to_kind) {
   4825   Map* to_map = FindClosestElementsTransition(this, to_kind);
   4826   if (to_map->elements_kind() == to_kind) return to_map;
   4827   return nullptr;
   4828 }
   4829 
   4830 
   4831 bool Map::IsMapInArrayPrototypeChain() {
   4832   Isolate* isolate = GetIsolate();
   4833   if (isolate->initial_array_prototype()->map() == this) {
   4834     return true;
   4835   }
   4836 
   4837   if (isolate->initial_object_prototype()->map() == this) {
   4838     return true;
   4839   }
   4840 
   4841   return false;
   4842 }
   4843 
   4844 
   4845 Handle<WeakCell> Map::WeakCellForMap(Handle<Map> map) {
   4846   Isolate* isolate = map->GetIsolate();
   4847   if (map->weak_cell_cache()->IsWeakCell()) {
   4848     return Handle<WeakCell>(WeakCell::cast(map->weak_cell_cache()));
   4849   }
   4850   Handle<WeakCell> weak_cell = isolate->factory()->NewWeakCell(map);
   4851   map->set_weak_cell_cache(*weak_cell);
   4852   return weak_cell;
   4853 }
   4854 
   4855 
   4856 static Handle<Map> AddMissingElementsTransitions(Handle<Map> map,
   4857                                                  ElementsKind to_kind) {
   4858   DCHECK(IsTransitionElementsKind(map->elements_kind()));
   4859 
   4860   Handle<Map> current_map = map;
   4861 
   4862   ElementsKind kind = map->elements_kind();
   4863   TransitionFlag flag;
   4864   if (map->is_prototype_map()) {
   4865     flag = OMIT_TRANSITION;
   4866   } else {
   4867     flag = INSERT_TRANSITION;
   4868     if (IsFastElementsKind(kind)) {
   4869       while (kind != to_kind && !IsTerminalElementsKind(kind)) {
   4870         kind = GetNextTransitionElementsKind(kind);
   4871         current_map = Map::CopyAsElementsKind(current_map, kind, flag);
   4872       }
   4873     }
   4874   }
   4875 
   4876   // In case we are exiting the fast elements kind system, just add the map in
   4877   // the end.
   4878   if (kind != to_kind) {
   4879     current_map = Map::CopyAsElementsKind(current_map, to_kind, flag);
   4880   }
   4881 
   4882   DCHECK(current_map->elements_kind() == to_kind);
   4883   return current_map;
   4884 }
   4885 
   4886 
   4887 Handle<Map> Map::TransitionElementsTo(Handle<Map> map,
   4888                                       ElementsKind to_kind) {
   4889   ElementsKind from_kind = map->elements_kind();
   4890   if (from_kind == to_kind) return map;
   4891 
   4892   Isolate* isolate = map->GetIsolate();
   4893   Context* native_context = isolate->context()->native_context();
   4894   if (from_kind == FAST_SLOPPY_ARGUMENTS_ELEMENTS) {
   4895     if (*map == native_context->fast_aliased_arguments_map()) {
   4896       DCHECK_EQ(SLOW_SLOPPY_ARGUMENTS_ELEMENTS, to_kind);
   4897       return handle(native_context->slow_aliased_arguments_map());
   4898     }
   4899   } else if (from_kind == SLOW_SLOPPY_ARGUMENTS_ELEMENTS) {
   4900     if (*map == native_context->slow_aliased_arguments_map()) {
   4901       DCHECK_EQ(FAST_SLOPPY_ARGUMENTS_ELEMENTS, to_kind);
   4902       return handle(native_context->fast_aliased_arguments_map());
   4903     }
   4904   } else if (IsFastElementsKind(from_kind) && IsFastElementsKind(to_kind)) {
   4905     // Reuse map transitions for JSArrays.
   4906     DisallowHeapAllocation no_gc;
   4907     if (native_context->get(Context::ArrayMapIndex(from_kind)) == *map) {
   4908       Object* maybe_transitioned_map =
   4909           native_context->get(Context::ArrayMapIndex(to_kind));
   4910       if (maybe_transitioned_map->IsMap()) {
   4911         return handle(Map::cast(maybe_transitioned_map), isolate);
   4912       }
   4913     }
   4914   }
   4915 
   4916   DCHECK(!map->IsUndefined(isolate));
   4917   // Check if we can go back in the elements kind transition chain.
   4918   if (IsHoleyElementsKind(from_kind) &&
   4919       to_kind == GetPackedElementsKind(from_kind) &&
   4920       map->GetBackPointer()->IsMap() &&
   4921       Map::cast(map->GetBackPointer())->elements_kind() == to_kind) {
   4922     return handle(Map::cast(map->GetBackPointer()));
   4923   }
   4924 
   4925   bool allow_store_transition = IsTransitionElementsKind(from_kind);
   4926   // Only store fast element maps in ascending generality.
   4927   if (IsFastElementsKind(to_kind)) {
   4928     allow_store_transition =
   4929         allow_store_transition && IsTransitionableFastElementsKind(from_kind) &&
   4930         IsMoreGeneralElementsKindTransition(from_kind, to_kind);
   4931   }
   4932 
   4933   if (!allow_store_transition) {
   4934     return Map::CopyAsElementsKind(map, to_kind, OMIT_TRANSITION);
   4935   }
   4936 
   4937   return Map::ReconfigureElementsKind(map, to_kind);
   4938 }
   4939 
   4940 
   4941 // static
   4942 Handle<Map> Map::AsElementsKind(Handle<Map> map, ElementsKind kind) {
   4943   Handle<Map> closest_map(FindClosestElementsTransition(*map, kind));
   4944 
   4945   if (closest_map->elements_kind() == kind) {
   4946     return closest_map;
   4947   }
   4948 
   4949   return AddMissingElementsTransitions(closest_map, kind);
   4950 }
   4951 
   4952 
   4953 Handle<Map> JSObject::GetElementsTransitionMap(Handle<JSObject> object,
   4954                                                ElementsKind to_kind) {
   4955   Handle<Map> map(object->map());
   4956   return Map::TransitionElementsTo(map, to_kind);
   4957 }
   4958 
   4959 
   4960 void JSProxy::Revoke(Handle<JSProxy> proxy) {
   4961   Isolate* isolate = proxy->GetIsolate();
   4962   if (!proxy->IsRevoked()) proxy->set_handler(isolate->heap()->null_value());
   4963   DCHECK(proxy->IsRevoked());
   4964 }
   4965 
   4966 
   4967 Maybe<bool> JSProxy::HasProperty(Isolate* isolate, Handle<JSProxy> proxy,
   4968                                  Handle<Name> name) {
   4969   DCHECK(!name->IsPrivate());
   4970   STACK_CHECK(isolate, Nothing<bool>());
   4971   // 1. (Assert)
   4972   // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O.
   4973   Handle<Object> handler(proxy->handler(), isolate);
   4974   // 3. If handler is null, throw a TypeError exception.
   4975   // 4. Assert: Type(handler) is Object.
   4976   if (proxy->IsRevoked()) {
   4977     isolate->Throw(*isolate->factory()->NewTypeError(
   4978         MessageTemplate::kProxyRevoked, isolate->factory()->has_string()));
   4979     return Nothing<bool>();
   4980   }
   4981   // 5. Let target be the value of the [[ProxyTarget]] internal slot of O.
   4982   Handle<JSReceiver> target(proxy->target(), isolate);
   4983   // 6. Let trap be ? GetMethod(handler, "has").
   4984   Handle<Object> trap;
   4985   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   4986       isolate, trap, Object::GetMethod(Handle<JSReceiver>::cast(handler),
   4987                                        isolate->factory()->has_string()),
   4988       Nothing<bool>());
   4989   // 7. If trap is undefined, then
   4990   if (trap->IsUndefined(isolate)) {
   4991     // 7a. Return target.[[HasProperty]](P).
   4992     return JSReceiver::HasProperty(target, name);
   4993   }
   4994   // 8. Let booleanTrapResult be ToBoolean(? Call(trap, handler, target, P)).
   4995   Handle<Object> trap_result_obj;
   4996   Handle<Object> args[] = {target, name};
   4997   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   4998       isolate, trap_result_obj,
   4999       Execution::Call(isolate, trap, handler, arraysize(args), args),
   5000       Nothing<bool>());
   5001   bool boolean_trap_result = trap_result_obj->BooleanValue();
   5002   // 9. If booleanTrapResult is false, then:
   5003   if (!boolean_trap_result) {
   5004     // 9a. Let targetDesc be ? target.[[GetOwnProperty]](P).
   5005     PropertyDescriptor target_desc;
   5006     Maybe<bool> target_found = JSReceiver::GetOwnPropertyDescriptor(
   5007         isolate, target, name, &target_desc);
   5008     MAYBE_RETURN(target_found, Nothing<bool>());
   5009     // 9b. If targetDesc is not undefined, then:
   5010     if (target_found.FromJust()) {
   5011       // 9b i. If targetDesc.[[Configurable]] is false, throw a TypeError
   5012       //       exception.
   5013       if (!target_desc.configurable()) {
   5014         isolate->Throw(*isolate->factory()->NewTypeError(
   5015             MessageTemplate::kProxyHasNonConfigurable, name));
   5016         return Nothing<bool>();
   5017       }
   5018       // 9b ii. Let extensibleTarget be ? IsExtensible(target).
   5019       Maybe<bool> extensible_target = JSReceiver::IsExtensible(target);
   5020       MAYBE_RETURN(extensible_target, Nothing<bool>());
   5021       // 9b iii. If extensibleTarget is false, throw a TypeError exception.
   5022       if (!extensible_target.FromJust()) {
   5023         isolate->Throw(*isolate->factory()->NewTypeError(
   5024             MessageTemplate::kProxyHasNonExtensible, name));
   5025         return Nothing<bool>();
   5026       }
   5027     }
   5028   }
   5029   // 10. Return booleanTrapResult.
   5030   return Just(boolean_trap_result);
   5031 }
   5032 
   5033 
   5034 Maybe<bool> JSProxy::SetProperty(Handle<JSProxy> proxy, Handle<Name> name,
   5035                                  Handle<Object> value, Handle<Object> receiver,
   5036                                  LanguageMode language_mode) {
   5037   DCHECK(!name->IsPrivate());
   5038   Isolate* isolate = proxy->GetIsolate();
   5039   STACK_CHECK(isolate, Nothing<bool>());
   5040   Factory* factory = isolate->factory();
   5041   Handle<String> trap_name = factory->set_string();
   5042   ShouldThrow should_throw =
   5043       is_sloppy(language_mode) ? DONT_THROW : THROW_ON_ERROR;
   5044 
   5045   if (proxy->IsRevoked()) {
   5046     isolate->Throw(
   5047         *factory->NewTypeError(MessageTemplate::kProxyRevoked, trap_name));
   5048     return Nothing<bool>();
   5049   }
   5050   Handle<JSReceiver> target(proxy->target(), isolate);
   5051   Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate);
   5052 
   5053   Handle<Object> trap;
   5054   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   5055       isolate, trap, Object::GetMethod(handler, trap_name), Nothing<bool>());
   5056   if (trap->IsUndefined(isolate)) {
   5057     LookupIterator it =
   5058         LookupIterator::PropertyOrElement(isolate, receiver, name, target);
   5059     return Object::SetSuperProperty(&it, value, language_mode,
   5060                                     Object::MAY_BE_STORE_FROM_KEYED);
   5061   }
   5062 
   5063   Handle<Object> trap_result;
   5064   Handle<Object> args[] = {target, name, value, receiver};
   5065   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   5066       isolate, trap_result,
   5067       Execution::Call(isolate, trap, handler, arraysize(args), args),
   5068       Nothing<bool>());
   5069   if (!trap_result->BooleanValue()) {
   5070     RETURN_FAILURE(isolate, should_throw,
   5071                    NewTypeError(MessageTemplate::kProxyTrapReturnedFalsishFor,
   5072                                 trap_name, name));
   5073   }
   5074 
   5075   // Enforce the invariant.
   5076   PropertyDescriptor target_desc;
   5077   Maybe<bool> owned =
   5078       JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, &target_desc);
   5079   MAYBE_RETURN(owned, Nothing<bool>());
   5080   if (owned.FromJust()) {
   5081     bool inconsistent = PropertyDescriptor::IsDataDescriptor(&target_desc) &&
   5082                         !target_desc.configurable() &&
   5083                         !target_desc.writable() &&
   5084                         !value->SameValue(*target_desc.value());
   5085     if (inconsistent) {
   5086       isolate->Throw(*isolate->factory()->NewTypeError(
   5087           MessageTemplate::kProxySetFrozenData, name));
   5088       return Nothing<bool>();
   5089     }
   5090     inconsistent = PropertyDescriptor::IsAccessorDescriptor(&target_desc) &&
   5091                    !target_desc.configurable() &&
   5092                    target_desc.set()->IsUndefined(isolate);
   5093     if (inconsistent) {
   5094       isolate->Throw(*isolate->factory()->NewTypeError(
   5095           MessageTemplate::kProxySetFrozenAccessor, name));
   5096       return Nothing<bool>();
   5097     }
   5098   }
   5099   return Just(true);
   5100 }
   5101 
   5102 
   5103 Maybe<bool> JSProxy::DeletePropertyOrElement(Handle<JSProxy> proxy,
   5104                                              Handle<Name> name,
   5105                                              LanguageMode language_mode) {
   5106   DCHECK(!name->IsPrivate());
   5107   ShouldThrow should_throw =
   5108       is_sloppy(language_mode) ? DONT_THROW : THROW_ON_ERROR;
   5109   Isolate* isolate = proxy->GetIsolate();
   5110   STACK_CHECK(isolate, Nothing<bool>());
   5111   Factory* factory = isolate->factory();
   5112   Handle<String> trap_name = factory->deleteProperty_string();
   5113 
   5114   if (proxy->IsRevoked()) {
   5115     isolate->Throw(
   5116         *factory->NewTypeError(MessageTemplate::kProxyRevoked, trap_name));
   5117     return Nothing<bool>();
   5118   }
   5119   Handle<JSReceiver> target(proxy->target(), isolate);
   5120   Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate);
   5121 
   5122   Handle<Object> trap;
   5123   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   5124       isolate, trap, Object::GetMethod(handler, trap_name), Nothing<bool>());
   5125   if (trap->IsUndefined(isolate)) {
   5126     return JSReceiver::DeletePropertyOrElement(target, name, language_mode);
   5127   }
   5128 
   5129   Handle<Object> trap_result;
   5130   Handle<Object> args[] = {target, name};
   5131   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   5132       isolate, trap_result,
   5133       Execution::Call(isolate, trap, handler, arraysize(args), args),
   5134       Nothing<bool>());
   5135   if (!trap_result->BooleanValue()) {
   5136     RETURN_FAILURE(isolate, should_throw,
   5137                    NewTypeError(MessageTemplate::kProxyTrapReturnedFalsishFor,
   5138                                 trap_name, name));
   5139   }
   5140 
   5141   // Enforce the invariant.
   5142   PropertyDescriptor target_desc;
   5143   Maybe<bool> owned =
   5144       JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, &target_desc);
   5145   MAYBE_RETURN(owned, Nothing<bool>());
   5146   if (owned.FromJust() && !target_desc.configurable()) {
   5147     isolate->Throw(*factory->NewTypeError(
   5148         MessageTemplate::kProxyDeletePropertyNonConfigurable, name));
   5149     return Nothing<bool>();
   5150   }
   5151   return Just(true);
   5152 }
   5153 
   5154 
   5155 // static
   5156 MaybeHandle<JSProxy> JSProxy::New(Isolate* isolate, Handle<Object> target,
   5157                                   Handle<Object> handler) {
   5158   if (!target->IsJSReceiver()) {
   5159     THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kProxyNonObject),
   5160                     JSProxy);
   5161   }
   5162   if (target->IsJSProxy() && JSProxy::cast(*target)->IsRevoked()) {
   5163     THROW_NEW_ERROR(isolate,
   5164                     NewTypeError(MessageTemplate::kProxyHandlerOrTargetRevoked),
   5165                     JSProxy);
   5166   }
   5167   if (!handler->IsJSReceiver()) {
   5168     THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kProxyNonObject),
   5169                     JSProxy);
   5170   }
   5171   if (handler->IsJSProxy() && JSProxy::cast(*handler)->IsRevoked()) {
   5172     THROW_NEW_ERROR(isolate,
   5173                     NewTypeError(MessageTemplate::kProxyHandlerOrTargetRevoked),
   5174                     JSProxy);
   5175   }
   5176   return isolate->factory()->NewJSProxy(Handle<JSReceiver>::cast(target),
   5177                                         Handle<JSReceiver>::cast(handler));
   5178 }
   5179 
   5180 
   5181 // static
   5182 MaybeHandle<Context> JSProxy::GetFunctionRealm(Handle<JSProxy> proxy) {
   5183   DCHECK(proxy->map()->is_constructor());
   5184   if (proxy->IsRevoked()) {
   5185     THROW_NEW_ERROR(proxy->GetIsolate(),
   5186                     NewTypeError(MessageTemplate::kProxyRevoked), Context);
   5187   }
   5188   Handle<JSReceiver> target(JSReceiver::cast(proxy->target()));
   5189   return JSReceiver::GetFunctionRealm(target);
   5190 }
   5191 
   5192 
   5193 // static
   5194 MaybeHandle<Context> JSBoundFunction::GetFunctionRealm(
   5195     Handle<JSBoundFunction> function) {
   5196   DCHECK(function->map()->is_constructor());
   5197   return JSReceiver::GetFunctionRealm(
   5198       handle(function->bound_target_function()));
   5199 }
   5200 
   5201 // static
   5202 MaybeHandle<String> JSBoundFunction::GetName(Isolate* isolate,
   5203                                              Handle<JSBoundFunction> function) {
   5204   Handle<String> prefix = isolate->factory()->bound__string();
   5205   if (!function->bound_target_function()->IsJSFunction()) return prefix;
   5206   Handle<JSFunction> target(JSFunction::cast(function->bound_target_function()),
   5207                             isolate);
   5208   Handle<Object> target_name = JSFunction::GetName(isolate, target);
   5209   if (!target_name->IsString()) return prefix;
   5210   Factory* factory = isolate->factory();
   5211   return factory->NewConsString(prefix, Handle<String>::cast(target_name));
   5212 }
   5213 
   5214 // static
   5215 Handle<Object> JSFunction::GetName(Isolate* isolate,
   5216                                    Handle<JSFunction> function) {
   5217   if (function->shared()->name_should_print_as_anonymous()) {
   5218     return isolate->factory()->anonymous_string();
   5219   }
   5220   return handle(function->shared()->name(), isolate);
   5221 }
   5222 
   5223 // static
   5224 MaybeHandle<Smi> JSFunction::GetLength(Isolate* isolate,
   5225                                        Handle<JSFunction> function) {
   5226   int length = 0;
   5227   if (function->shared()->is_compiled()) {
   5228     length = function->shared()->length();
   5229   } else {
   5230     // If the function isn't compiled yet, the length is not computed
   5231     // correctly yet. Compile it now and return the right length.
   5232     if (Compiler::Compile(function, Compiler::KEEP_EXCEPTION)) {
   5233       length = function->shared()->length();
   5234     }
   5235     if (isolate->has_pending_exception()) return MaybeHandle<Smi>();
   5236   }
   5237   return handle(Smi::FromInt(length), isolate);
   5238 }
   5239 
   5240 // static
   5241 Handle<Context> JSFunction::GetFunctionRealm(Handle<JSFunction> function) {
   5242   DCHECK(function->map()->is_constructor());
   5243   return handle(function->context()->native_context());
   5244 }
   5245 
   5246 
   5247 // static
   5248 MaybeHandle<Context> JSObject::GetFunctionRealm(Handle<JSObject> object) {
   5249   DCHECK(object->map()->is_constructor());
   5250   DCHECK(!object->IsJSFunction());
   5251   return object->GetCreationContext();
   5252 }
   5253 
   5254 
   5255 // static
   5256 MaybeHandle<Context> JSReceiver::GetFunctionRealm(Handle<JSReceiver> receiver) {
   5257   if (receiver->IsJSProxy()) {
   5258     return JSProxy::GetFunctionRealm(Handle<JSProxy>::cast(receiver));
   5259   }
   5260 
   5261   if (receiver->IsJSFunction()) {
   5262     return JSFunction::GetFunctionRealm(Handle<JSFunction>::cast(receiver));
   5263   }
   5264 
   5265   if (receiver->IsJSBoundFunction()) {
   5266     return JSBoundFunction::GetFunctionRealm(
   5267         Handle<JSBoundFunction>::cast(receiver));
   5268   }
   5269 
   5270   return JSObject::GetFunctionRealm(Handle<JSObject>::cast(receiver));
   5271 }
   5272 
   5273 
   5274 Maybe<PropertyAttributes> JSProxy::GetPropertyAttributes(LookupIterator* it) {
   5275   PropertyDescriptor desc;
   5276   Maybe<bool> found = JSProxy::GetOwnPropertyDescriptor(
   5277       it->isolate(), it->GetHolder<JSProxy>(), it->GetName(), &desc);
   5278   MAYBE_RETURN(found, Nothing<PropertyAttributes>());
   5279   if (!found.FromJust()) return Just(ABSENT);
   5280   return Just(desc.ToAttributes());
   5281 }
   5282 
   5283 
   5284 void JSObject::AllocateStorageForMap(Handle<JSObject> object, Handle<Map> map) {
   5285   DCHECK(object->map()->GetInObjectProperties() ==
   5286          map->GetInObjectProperties());
   5287   ElementsKind obj_kind = object->map()->elements_kind();
   5288   ElementsKind map_kind = map->elements_kind();
   5289   if (map_kind != obj_kind) {
   5290     ElementsKind to_kind = GetMoreGeneralElementsKind(map_kind, obj_kind);
   5291     if (IsDictionaryElementsKind(obj_kind)) {
   5292       to_kind = obj_kind;
   5293     }
   5294     if (IsDictionaryElementsKind(to_kind)) {
   5295       NormalizeElements(object);
   5296     } else {
   5297       TransitionElementsKind(object, to_kind);
   5298     }
   5299     map = Map::ReconfigureElementsKind(map, to_kind);
   5300   }
   5301   JSObject::MigrateToMap(object, map);
   5302 }
   5303 
   5304 
   5305 void JSObject::MigrateInstance(Handle<JSObject> object) {
   5306   Handle<Map> original_map(object->map());
   5307   Handle<Map> map = Map::Update(original_map);
   5308   map->set_migration_target(true);
   5309   MigrateToMap(object, map);
   5310   if (FLAG_trace_migration) {
   5311     object->PrintInstanceMigration(stdout, *original_map, *map);
   5312   }
   5313 #if VERIFY_HEAP
   5314   if (FLAG_verify_heap) {
   5315     object->JSObjectVerify();
   5316   }
   5317 #endif
   5318 }
   5319 
   5320 
   5321 // static
   5322 bool JSObject::TryMigrateInstance(Handle<JSObject> object) {
   5323   Isolate* isolate = object->GetIsolate();
   5324   DisallowDeoptimization no_deoptimization(isolate);
   5325   Handle<Map> original_map(object->map(), isolate);
   5326   Handle<Map> new_map;
   5327   if (!Map::TryUpdate(original_map).ToHandle(&new_map)) {
   5328     return false;
   5329   }
   5330   JSObject::MigrateToMap(object, new_map);
   5331   if (FLAG_trace_migration) {
   5332     object->PrintInstanceMigration(stdout, *original_map, object->map());
   5333   }
   5334 #if VERIFY_HEAP
   5335   if (FLAG_verify_heap) {
   5336     object->JSObjectVerify();
   5337   }
   5338 #endif
   5339   return true;
   5340 }
   5341 
   5342 
   5343 void JSObject::AddProperty(Handle<JSObject> object, Handle<Name> name,
   5344                            Handle<Object> value,
   5345                            PropertyAttributes attributes) {
   5346   LookupIterator it(object, name, object, LookupIterator::OWN_SKIP_INTERCEPTOR);
   5347   CHECK_NE(LookupIterator::ACCESS_CHECK, it.state());
   5348 #ifdef DEBUG
   5349   uint32_t index;
   5350   DCHECK(!object->IsJSProxy());
   5351   DCHECK(!name->AsArrayIndex(&index));
   5352   Maybe<PropertyAttributes> maybe = GetPropertyAttributes(&it);
   5353   DCHECK(maybe.IsJust());
   5354   DCHECK(!it.IsFound());
   5355   DCHECK(object->map()->is_extensible() || name->IsPrivate());
   5356 #endif
   5357   CHECK(AddDataProperty(&it, value, attributes, THROW_ON_ERROR,
   5358                         CERTAINLY_NOT_STORE_FROM_KEYED)
   5359             .IsJust());
   5360 }
   5361 
   5362 
   5363 // Reconfigures a property to a data property with attributes, even if it is not
   5364 // reconfigurable.
   5365 // Requires a LookupIterator that does not look at the prototype chain beyond
   5366 // hidden prototypes.
   5367 MaybeHandle<Object> JSObject::DefineOwnPropertyIgnoreAttributes(
   5368     LookupIterator* it, Handle<Object> value, PropertyAttributes attributes,
   5369     AccessorInfoHandling handling) {
   5370   MAYBE_RETURN_NULL(DefineOwnPropertyIgnoreAttributes(
   5371       it, value, attributes, THROW_ON_ERROR, handling));
   5372   return value;
   5373 }
   5374 
   5375 
   5376 Maybe<bool> JSObject::DefineOwnPropertyIgnoreAttributes(
   5377     LookupIterator* it, Handle<Object> value, PropertyAttributes attributes,
   5378     ShouldThrow should_throw, AccessorInfoHandling handling) {
   5379   it->UpdateProtector();
   5380   Handle<JSObject> object = Handle<JSObject>::cast(it->GetReceiver());
   5381 
   5382   for (; it->IsFound(); it->Next()) {
   5383     switch (it->state()) {
   5384       case LookupIterator::JSPROXY:
   5385       case LookupIterator::NOT_FOUND:
   5386       case LookupIterator::TRANSITION:
   5387         UNREACHABLE();
   5388 
   5389       case LookupIterator::ACCESS_CHECK:
   5390         if (!it->HasAccess()) {
   5391           it->isolate()->ReportFailedAccessCheck(it->GetHolder<JSObject>());
   5392           RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(), Nothing<bool>());
   5393           return Just(true);
   5394         }
   5395         break;
   5396 
   5397       // If there's an interceptor, try to store the property with the
   5398       // interceptor.
   5399       // In case of success, the attributes will have been reset to the default
   5400       // attributes of the interceptor, rather than the incoming attributes.
   5401       //
   5402       // TODO(verwaest): JSProxy afterwards verify the attributes that the
   5403       // JSProxy claims it has, and verifies that they are compatible. If not,
   5404       // they throw. Here we should do the same.
   5405       case LookupIterator::INTERCEPTOR:
   5406         if (handling == DONT_FORCE_FIELD) {
   5407           Maybe<bool> result =
   5408               JSObject::SetPropertyWithInterceptor(it, should_throw, value);
   5409           if (result.IsNothing() || result.FromJust()) return result;
   5410         }
   5411         break;
   5412 
   5413       case LookupIterator::ACCESSOR: {
   5414         Handle<Object> accessors = it->GetAccessors();
   5415 
   5416         // Special handling for AccessorInfo, which behaves like a data
   5417         // property.
   5418         if (accessors->IsAccessorInfo() && handling == DONT_FORCE_FIELD) {
   5419           PropertyAttributes current_attributes = it->property_attributes();
   5420           // Ensure the context isn't changed after calling into accessors.
   5421           AssertNoContextChange ncc(it->isolate());
   5422 
   5423           // Update the attributes before calling the setter. The setter may
   5424           // later change the shape of the property.
   5425           if (current_attributes != attributes) {
   5426             it->TransitionToAccessorPair(accessors, attributes);
   5427           }
   5428 
   5429           return JSObject::SetPropertyWithAccessor(it, value, should_throw);
   5430         }
   5431 
   5432         it->ReconfigureDataProperty(value, attributes);
   5433         return Just(true);
   5434       }
   5435       case LookupIterator::INTEGER_INDEXED_EXOTIC:
   5436         return RedefineIncompatibleProperty(it->isolate(), it->GetName(), value,
   5437                                             should_throw);
   5438 
   5439       case LookupIterator::DATA: {
   5440         // Regular property update if the attributes match.
   5441         if (it->property_attributes() == attributes) {
   5442           return SetDataProperty(it, value);
   5443         }
   5444 
   5445         // Special case: properties of typed arrays cannot be reconfigured to
   5446         // non-writable nor to non-enumerable.
   5447         if (it->IsElement() && object->HasFixedTypedArrayElements()) {
   5448           return RedefineIncompatibleProperty(it->isolate(), it->GetName(),
   5449                                               value, should_throw);
   5450         }
   5451 
   5452         // Reconfigure the data property if the attributes mismatch.
   5453         it->ReconfigureDataProperty(value, attributes);
   5454 
   5455         return Just(true);
   5456       }
   5457     }
   5458   }
   5459 
   5460   return AddDataProperty(it, value, attributes, should_throw,
   5461                          CERTAINLY_NOT_STORE_FROM_KEYED);
   5462 }
   5463 
   5464 MaybeHandle<Object> JSObject::SetOwnPropertyIgnoreAttributes(
   5465     Handle<JSObject> object, Handle<Name> name, Handle<Object> value,
   5466     PropertyAttributes attributes) {
   5467   DCHECK(!value->IsTheHole(object->GetIsolate()));
   5468   LookupIterator it(object, name, object, LookupIterator::OWN);
   5469   return DefineOwnPropertyIgnoreAttributes(&it, value, attributes);
   5470 }
   5471 
   5472 MaybeHandle<Object> JSObject::SetOwnElementIgnoreAttributes(
   5473     Handle<JSObject> object, uint32_t index, Handle<Object> value,
   5474     PropertyAttributes attributes) {
   5475   Isolate* isolate = object->GetIsolate();
   5476   LookupIterator it(isolate, object, index, object, LookupIterator::OWN);
   5477   return DefineOwnPropertyIgnoreAttributes(&it, value, attributes);
   5478 }
   5479 
   5480 MaybeHandle<Object> JSObject::DefinePropertyOrElementIgnoreAttributes(
   5481     Handle<JSObject> object, Handle<Name> name, Handle<Object> value,
   5482     PropertyAttributes attributes) {
   5483   Isolate* isolate = object->GetIsolate();
   5484   LookupIterator it = LookupIterator::PropertyOrElement(
   5485       isolate, object, name, object, LookupIterator::OWN);
   5486   return DefineOwnPropertyIgnoreAttributes(&it, value, attributes);
   5487 }
   5488 
   5489 Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithInterceptor(
   5490     LookupIterator* it) {
   5491   return GetPropertyAttributesWithInterceptorInternal(it, it->GetInterceptor());
   5492 }
   5493 
   5494 Maybe<PropertyAttributes> JSReceiver::GetPropertyAttributes(
   5495     LookupIterator* it) {
   5496   for (; it->IsFound(); it->Next()) {
   5497     switch (it->state()) {
   5498       case LookupIterator::NOT_FOUND:
   5499       case LookupIterator::TRANSITION:
   5500         UNREACHABLE();
   5501       case LookupIterator::JSPROXY:
   5502         return JSProxy::GetPropertyAttributes(it);
   5503       case LookupIterator::INTERCEPTOR: {
   5504         Maybe<PropertyAttributes> result =
   5505             JSObject::GetPropertyAttributesWithInterceptor(it);
   5506         if (!result.IsJust()) return result;
   5507         if (result.FromJust() != ABSENT) return result;
   5508         break;
   5509       }
   5510       case LookupIterator::ACCESS_CHECK:
   5511         if (it->HasAccess()) break;
   5512         return JSObject::GetPropertyAttributesWithFailedAccessCheck(it);
   5513       case LookupIterator::INTEGER_INDEXED_EXOTIC:
   5514         return Just(ABSENT);
   5515       case LookupIterator::ACCESSOR:
   5516       case LookupIterator::DATA:
   5517         return Just(it->property_attributes());
   5518     }
   5519   }
   5520   return Just(ABSENT);
   5521 }
   5522 
   5523 
   5524 Handle<NormalizedMapCache> NormalizedMapCache::New(Isolate* isolate) {
   5525   Handle<FixedArray> array(
   5526       isolate->factory()->NewFixedArray(kEntries, TENURED));
   5527   return Handle<NormalizedMapCache>::cast(array);
   5528 }
   5529 
   5530 
   5531 MaybeHandle<Map> NormalizedMapCache::Get(Handle<Map> fast_map,
   5532                                          PropertyNormalizationMode mode) {
   5533   DisallowHeapAllocation no_gc;
   5534   Object* value = FixedArray::get(GetIndex(fast_map));
   5535   if (!value->IsMap() ||
   5536       !Map::cast(value)->EquivalentToForNormalization(*fast_map, mode)) {
   5537     return MaybeHandle<Map>();
   5538   }
   5539   return handle(Map::cast(value));
   5540 }
   5541 
   5542 
   5543 void NormalizedMapCache::Set(Handle<Map> fast_map,
   5544                              Handle<Map> normalized_map) {
   5545   DisallowHeapAllocation no_gc;
   5546   DCHECK(normalized_map->is_dictionary_map());
   5547   FixedArray::set(GetIndex(fast_map), *normalized_map);
   5548 }
   5549 
   5550 
   5551 void NormalizedMapCache::Clear() {
   5552   int entries = length();
   5553   for (int i = 0; i != entries; i++) {
   5554     set_undefined(i);
   5555   }
   5556 }
   5557 
   5558 
   5559 void HeapObject::UpdateMapCodeCache(Handle<HeapObject> object,
   5560                                     Handle<Name> name,
   5561                                     Handle<Code> code) {
   5562   Handle<Map> map(object->map());
   5563   Map::UpdateCodeCache(map, name, code);
   5564 }
   5565 
   5566 
   5567 void JSObject::NormalizeProperties(Handle<JSObject> object,
   5568                                    PropertyNormalizationMode mode,
   5569                                    int expected_additional_properties,
   5570                                    const char* reason) {
   5571   if (!object->HasFastProperties()) return;
   5572 
   5573   Handle<Map> map(object->map());
   5574   Handle<Map> new_map = Map::Normalize(map, mode, reason);
   5575 
   5576   MigrateToMap(object, new_map, expected_additional_properties);
   5577 }
   5578 
   5579 
   5580 void JSObject::MigrateSlowToFast(Handle<JSObject> object,
   5581                                  int unused_property_fields,
   5582                                  const char* reason) {
   5583   if (object->HasFastProperties()) return;
   5584   DCHECK(!object->IsJSGlobalObject());
   5585   Isolate* isolate = object->GetIsolate();
   5586   Factory* factory = isolate->factory();
   5587   Handle<NameDictionary> dictionary(object->property_dictionary());
   5588 
   5589   // Make sure we preserve dictionary representation if there are too many
   5590   // descriptors.
   5591   int number_of_elements = dictionary->NumberOfElements();
   5592   if (number_of_elements > kMaxNumberOfDescriptors) return;
   5593 
   5594   Handle<FixedArray> iteration_order;
   5595   if (number_of_elements != dictionary->NextEnumerationIndex()) {
   5596     iteration_order =
   5597         NameDictionary::DoGenerateNewEnumerationIndices(dictionary);
   5598   } else {
   5599     iteration_order = NameDictionary::IterationIndices(dictionary);
   5600   }
   5601 
   5602   int instance_descriptor_length = iteration_order->length();
   5603   int number_of_fields = 0;
   5604 
   5605   // Compute the length of the instance descriptor.
   5606   for (int i = 0; i < instance_descriptor_length; i++) {
   5607     int index = Smi::cast(iteration_order->get(i))->value();
   5608     DCHECK(dictionary->IsKey(isolate, dictionary->KeyAt(index)));
   5609 
   5610     PropertyKind kind = dictionary->DetailsAt(index).kind();
   5611     if (kind == kData) {
   5612       if (FLAG_track_constant_fields) {
   5613         number_of_fields += 1;
   5614       } else {
   5615         Object* value = dictionary->ValueAt(index);
   5616         if (!value->IsJSFunction()) {
   5617           number_of_fields += 1;
   5618         }
   5619       }
   5620     }
   5621   }
   5622 
   5623   Handle<Map> old_map(object->map(), isolate);
   5624 
   5625   int inobject_props = old_map->GetInObjectProperties();
   5626 
   5627   // Allocate new map.
   5628   Handle<Map> new_map = Map::CopyDropDescriptors(old_map);
   5629   new_map->set_dictionary_map(false);
   5630 
   5631   NotifyMapChange(old_map, new_map, isolate);
   5632 
   5633 #if TRACE_MAPS
   5634   if (FLAG_trace_maps) {
   5635     PrintF("[TraceMaps: SlowToFast from= %p to= %p reason= %s ]\n",
   5636            reinterpret_cast<void*>(*old_map), reinterpret_cast<void*>(*new_map),
   5637            reason);
   5638   }
   5639 #endif
   5640 
   5641   if (instance_descriptor_length == 0) {
   5642     DisallowHeapAllocation no_gc;
   5643     DCHECK_LE(unused_property_fields, inobject_props);
   5644     // Transform the object.
   5645     new_map->set_unused_property_fields(inobject_props);
   5646     object->synchronized_set_map(*new_map);
   5647     object->set_properties(isolate->heap()->empty_fixed_array());
   5648     // Check that it really works.
   5649     DCHECK(object->HasFastProperties());
   5650     return;
   5651   }
   5652 
   5653   // Allocate the instance descriptor.
   5654   Handle<DescriptorArray> descriptors = DescriptorArray::Allocate(
   5655       isolate, instance_descriptor_length, 0, TENURED);
   5656 
   5657   int number_of_allocated_fields =
   5658       number_of_fields + unused_property_fields - inobject_props;
   5659   if (number_of_allocated_fields < 0) {
   5660     // There is enough inobject space for all fields (including unused).
   5661     number_of_allocated_fields = 0;
   5662     unused_property_fields = inobject_props - number_of_fields;
   5663   }
   5664 
   5665   // Allocate the fixed array for the fields.
   5666   Handle<FixedArray> fields = factory->NewFixedArray(
   5667       number_of_allocated_fields);
   5668 
   5669   // Fill in the instance descriptor and the fields.
   5670   int current_offset = 0;
   5671   for (int i = 0; i < instance_descriptor_length; i++) {
   5672     int index = Smi::cast(iteration_order->get(i))->value();
   5673     Object* k = dictionary->KeyAt(index);
   5674     DCHECK(dictionary->IsKey(k));
   5675     // Dictionary keys are internalized upon insertion.
   5676     // TODO(jkummerow): Turn this into a DCHECK if it's not hit in the wild.
   5677     CHECK(k->IsUniqueName());
   5678     Handle<Name> key(Name::cast(k), isolate);
   5679 
   5680     Object* value = dictionary->ValueAt(index);
   5681 
   5682     PropertyDetails details = dictionary->DetailsAt(index);
   5683     DCHECK_EQ(kField, details.location());
   5684     DCHECK_EQ(kMutable, details.constness());
   5685     int enumeration_index = details.dictionary_index();
   5686 
   5687     Descriptor d;
   5688     if (details.kind() == kData) {
   5689       if (!FLAG_track_constant_fields && value->IsJSFunction()) {
   5690         d = Descriptor::DataConstant(key, handle(value, isolate),
   5691                                      details.attributes());
   5692       } else {
   5693         d = Descriptor::DataField(
   5694             key, current_offset, details.attributes(), kDefaultFieldConstness,
   5695             // TODO(verwaest): value->OptimalRepresentation();
   5696             Representation::Tagged(), FieldType::Any(isolate));
   5697       }
   5698     } else {
   5699       DCHECK_EQ(kAccessor, details.kind());
   5700       d = Descriptor::AccessorConstant(key, handle(value, isolate),
   5701                                        details.attributes());
   5702     }
   5703     details = d.GetDetails();
   5704     if (details.location() == kField) {
   5705       if (current_offset < inobject_props) {
   5706         object->InObjectPropertyAtPut(current_offset, value,
   5707                                       UPDATE_WRITE_BARRIER);
   5708       } else {
   5709         int offset = current_offset - inobject_props;
   5710         fields->set(offset, value);
   5711       }
   5712       current_offset += details.field_width_in_words();
   5713     }
   5714     descriptors->Set(enumeration_index - 1, &d);
   5715   }
   5716   DCHECK(current_offset == number_of_fields);
   5717 
   5718   descriptors->Sort();
   5719 
   5720   Handle<LayoutDescriptor> layout_descriptor = LayoutDescriptor::New(
   5721       new_map, descriptors, descriptors->number_of_descriptors());
   5722 
   5723   DisallowHeapAllocation no_gc;
   5724   new_map->InitializeDescriptors(*descriptors, *layout_descriptor);
   5725   new_map->set_unused_property_fields(unused_property_fields);
   5726 
   5727   // Transform the object.
   5728   object->synchronized_set_map(*new_map);
   5729 
   5730   object->set_properties(*fields);
   5731   DCHECK(object->IsJSObject());
   5732 
   5733   // Check that it really works.
   5734   DCHECK(object->HasFastProperties());
   5735 }
   5736 
   5737 
   5738 void JSObject::ResetElements(Handle<JSObject> object) {
   5739   Isolate* isolate = object->GetIsolate();
   5740   CHECK(object->map() != isolate->heap()->sloppy_arguments_elements_map());
   5741   if (object->map()->has_dictionary_elements()) {
   5742     Handle<SeededNumberDictionary> new_elements =
   5743         SeededNumberDictionary::New(isolate, 0);
   5744     object->set_elements(*new_elements);
   5745   } else {
   5746     object->set_elements(object->map()->GetInitialElements());
   5747   }
   5748 }
   5749 
   5750 
   5751 void JSObject::RequireSlowElements(SeededNumberDictionary* dictionary) {
   5752   if (dictionary->requires_slow_elements()) return;
   5753   dictionary->set_requires_slow_elements();
   5754   if (map()->is_prototype_map()) {
   5755     // If this object is a prototype (the callee will check), invalidate any
   5756     // prototype chains involving it.
   5757     InvalidatePrototypeChains(map());
   5758   }
   5759 }
   5760 
   5761 
   5762 Handle<SeededNumberDictionary> JSObject::NormalizeElements(
   5763     Handle<JSObject> object) {
   5764   DCHECK(!object->HasFixedTypedArrayElements());
   5765   Isolate* isolate = object->GetIsolate();
   5766   bool is_arguments = object->HasSloppyArgumentsElements();
   5767   {
   5768     DisallowHeapAllocation no_gc;
   5769     FixedArrayBase* elements = object->elements();
   5770 
   5771     if (is_arguments) {
   5772       FixedArray* parameter_map = FixedArray::cast(elements);
   5773       elements = FixedArrayBase::cast(parameter_map->get(1));
   5774     }
   5775 
   5776     if (elements->IsDictionary()) {
   5777       return handle(SeededNumberDictionary::cast(elements), isolate);
   5778     }
   5779   }
   5780 
   5781   DCHECK(object->HasFastSmiOrObjectElements() ||
   5782          object->HasFastDoubleElements() ||
   5783          object->HasFastArgumentsElements() ||
   5784          object->HasFastStringWrapperElements());
   5785 
   5786   Handle<SeededNumberDictionary> dictionary =
   5787       object->GetElementsAccessor()->Normalize(object);
   5788 
   5789   // Switch to using the dictionary as the backing storage for elements.
   5790   ElementsKind target_kind = is_arguments
   5791                                  ? SLOW_SLOPPY_ARGUMENTS_ELEMENTS
   5792                                  : object->HasFastStringWrapperElements()
   5793                                        ? SLOW_STRING_WRAPPER_ELEMENTS
   5794                                        : DICTIONARY_ELEMENTS;
   5795   Handle<Map> new_map = JSObject::GetElementsTransitionMap(object, target_kind);
   5796   // Set the new map first to satify the elements type assert in set_elements().
   5797   JSObject::MigrateToMap(object, new_map);
   5798 
   5799   if (is_arguments) {
   5800     FixedArray::cast(object->elements())->set(1, *dictionary);
   5801   } else {
   5802     object->set_elements(*dictionary);
   5803   }
   5804 
   5805   isolate->counters()->elements_to_dictionary()->Increment();
   5806 
   5807 #ifdef DEBUG
   5808   if (FLAG_trace_normalization) {
   5809     OFStream os(stdout);
   5810     os << "Object elements have been normalized:\n";
   5811     object->Print(os);
   5812   }
   5813 #endif
   5814 
   5815   DCHECK(object->HasDictionaryElements() ||
   5816          object->HasSlowArgumentsElements() ||
   5817          object->HasSlowStringWrapperElements());
   5818   return dictionary;
   5819 }
   5820 
   5821 
   5822 template <typename ProxyType>
   5823 static Smi* GetOrCreateIdentityHashHelper(Isolate* isolate,
   5824                                           Handle<ProxyType> proxy) {
   5825   Object* maybe_hash = proxy->hash();
   5826   if (maybe_hash->IsSmi()) return Smi::cast(maybe_hash);
   5827 
   5828   Smi* hash = Smi::FromInt(isolate->GenerateIdentityHash(Smi::kMaxValue));
   5829   proxy->set_hash(hash);
   5830   return hash;
   5831 }
   5832 
   5833 // static
   5834 Object* JSObject::GetIdentityHash(Isolate* isolate, Handle<JSObject> object) {
   5835   if (object->IsJSGlobalProxy()) {
   5836     return JSGlobalProxy::cast(*object)->hash();
   5837   }
   5838   Handle<Name> hash_code_symbol = isolate->factory()->hash_code_symbol();
   5839   return *JSReceiver::GetDataProperty(object, hash_code_symbol);
   5840 }
   5841 
   5842 // static
   5843 Smi* JSObject::GetOrCreateIdentityHash(Isolate* isolate,
   5844                                        Handle<JSObject> object) {
   5845   if (object->IsJSGlobalProxy()) {
   5846     return GetOrCreateIdentityHashHelper(isolate,
   5847                                          Handle<JSGlobalProxy>::cast(object));
   5848   }
   5849 
   5850   Handle<Name> hash_code_symbol = isolate->factory()->hash_code_symbol();
   5851   LookupIterator it(object, hash_code_symbol, object, LookupIterator::OWN);
   5852   if (it.IsFound()) {
   5853     DCHECK_EQ(LookupIterator::DATA, it.state());
   5854     Object* maybe_hash = *it.GetDataValue();
   5855     if (maybe_hash->IsSmi()) return Smi::cast(maybe_hash);
   5856   }
   5857 
   5858   Smi* hash = Smi::FromInt(isolate->GenerateIdentityHash(Smi::kMaxValue));
   5859   CHECK(AddDataProperty(&it, handle(hash, isolate), NONE, THROW_ON_ERROR,
   5860                         CERTAINLY_NOT_STORE_FROM_KEYED)
   5861             .IsJust());
   5862   return hash;
   5863 }
   5864 
   5865 // static
   5866 Object* JSProxy::GetIdentityHash(Handle<JSProxy> proxy) {
   5867   return proxy->hash();
   5868 }
   5869 
   5870 Smi* JSProxy::GetOrCreateIdentityHash(Isolate* isolate, Handle<JSProxy> proxy) {
   5871   return GetOrCreateIdentityHashHelper(isolate, proxy);
   5872 }
   5873 
   5874 
   5875 Maybe<bool> JSObject::DeletePropertyWithInterceptor(LookupIterator* it,
   5876                                                     ShouldThrow should_throw) {
   5877   Isolate* isolate = it->isolate();
   5878   // Make sure that the top context does not change when doing callbacks or
   5879   // interceptor calls.
   5880   AssertNoContextChange ncc(isolate);
   5881 
   5882   DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
   5883   Handle<InterceptorInfo> interceptor(it->GetInterceptor());
   5884   if (interceptor->deleter()->IsUndefined(isolate)) return Nothing<bool>();
   5885 
   5886   Handle<JSObject> holder = it->GetHolder<JSObject>();
   5887   Handle<Object> receiver = it->GetReceiver();
   5888   if (!receiver->IsJSReceiver()) {
   5889     ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, receiver,
   5890                                      Object::ConvertReceiver(isolate, receiver),
   5891                                      Nothing<bool>());
   5892   }
   5893 
   5894   PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
   5895                                  *holder, should_throw);
   5896   Handle<Object> result;
   5897   if (it->IsElement()) {
   5898     uint32_t index = it->index();
   5899     v8::IndexedPropertyDeleterCallback deleter =
   5900         v8::ToCData<v8::IndexedPropertyDeleterCallback>(interceptor->deleter());
   5901     result = args.Call(deleter, index);
   5902   } else if (it->name()->IsSymbol() && !interceptor->can_intercept_symbols()) {
   5903     return Nothing<bool>();
   5904   } else {
   5905     Handle<Name> name = it->name();
   5906     DCHECK(!name->IsPrivate());
   5907     v8::GenericNamedPropertyDeleterCallback deleter =
   5908         v8::ToCData<v8::GenericNamedPropertyDeleterCallback>(
   5909             interceptor->deleter());
   5910     result = args.Call(deleter, name);
   5911   }
   5912 
   5913   RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
   5914   if (result.is_null()) return Nothing<bool>();
   5915 
   5916   DCHECK(result->IsBoolean());
   5917   // Rebox CustomArguments::kReturnValueOffset before returning.
   5918   return Just(result->IsTrue(isolate));
   5919 }
   5920 
   5921 
   5922 void JSReceiver::DeleteNormalizedProperty(Handle<JSReceiver> object,
   5923                                           Handle<Name> name, int entry) {
   5924   DCHECK(!object->HasFastProperties());
   5925   Isolate* isolate = object->GetIsolate();
   5926 
   5927   if (object->IsJSGlobalObject()) {
   5928     // If we have a global object, invalidate the cell and swap in a new one.
   5929     Handle<GlobalDictionary> dictionary(
   5930         JSObject::cast(*object)->global_dictionary());
   5931     DCHECK_NE(GlobalDictionary::kNotFound, entry);
   5932 
   5933     auto cell = PropertyCell::InvalidateEntry(dictionary, entry);
   5934     cell->set_value(isolate->heap()->the_hole_value());
   5935     cell->set_property_details(
   5936         PropertyDetails::Empty(PropertyCellType::kUninitialized));
   5937   } else {
   5938     Handle<NameDictionary> dictionary(object->property_dictionary());
   5939     DCHECK_NE(NameDictionary::kNotFound, entry);
   5940 
   5941     NameDictionary::DeleteProperty(dictionary, entry);
   5942     Handle<NameDictionary> new_properties =
   5943         NameDictionary::Shrink(dictionary, name);
   5944     object->set_properties(*new_properties);
   5945   }
   5946 }
   5947 
   5948 
   5949 Maybe<bool> JSReceiver::DeleteProperty(LookupIterator* it,
   5950                                        LanguageMode language_mode) {
   5951   it->UpdateProtector();
   5952 
   5953   Isolate* isolate = it->isolate();
   5954 
   5955   if (it->state() == LookupIterator::JSPROXY) {
   5956     return JSProxy::DeletePropertyOrElement(it->GetHolder<JSProxy>(),
   5957                                             it->GetName(), language_mode);
   5958   }
   5959 
   5960   if (it->GetReceiver()->IsJSProxy()) {
   5961     if (it->state() != LookupIterator::NOT_FOUND) {
   5962       DCHECK_EQ(LookupIterator::DATA, it->state());
   5963       DCHECK(it->name()->IsPrivate());
   5964       it->Delete();
   5965     }
   5966     return Just(true);
   5967   }
   5968   Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver());
   5969 
   5970   for (; it->IsFound(); it->Next()) {
   5971     switch (it->state()) {
   5972       case LookupIterator::JSPROXY:
   5973       case LookupIterator::NOT_FOUND:
   5974       case LookupIterator::TRANSITION:
   5975         UNREACHABLE();
   5976       case LookupIterator::ACCESS_CHECK:
   5977         if (it->HasAccess()) break;
   5978         isolate->ReportFailedAccessCheck(it->GetHolder<JSObject>());
   5979         RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
   5980         return Just(false);
   5981       case LookupIterator::INTERCEPTOR: {
   5982         ShouldThrow should_throw =
   5983             is_sloppy(language_mode) ? DONT_THROW : THROW_ON_ERROR;
   5984         Maybe<bool> result =
   5985             JSObject::DeletePropertyWithInterceptor(it, should_throw);
   5986         // An exception was thrown in the interceptor. Propagate.
   5987         if (isolate->has_pending_exception()) return Nothing<bool>();
   5988         // Delete with interceptor succeeded. Return result.
   5989         // TODO(neis): In strict mode, we should probably throw if the
   5990         // interceptor returns false.
   5991         if (result.IsJust()) return result;
   5992         break;
   5993       }
   5994       case LookupIterator::INTEGER_INDEXED_EXOTIC:
   5995         return Just(true);
   5996       case LookupIterator::DATA:
   5997       case LookupIterator::ACCESSOR: {
   5998         if (!it->IsConfigurable()) {
   5999           // Fail if the property is not configurable.
   6000           if (is_strict(language_mode)) {
   6001             isolate->Throw(*isolate->factory()->NewTypeError(
   6002                 MessageTemplate::kStrictDeleteProperty, it->GetName(),
   6003                 receiver));
   6004             return Nothing<bool>();
   6005           }
   6006           return Just(false);
   6007         }
   6008 
   6009         it->Delete();
   6010 
   6011         return Just(true);
   6012       }
   6013     }
   6014   }
   6015 
   6016   return Just(true);
   6017 }
   6018 
   6019 
   6020 Maybe<bool> JSReceiver::DeleteElement(Handle<JSReceiver> object, uint32_t index,
   6021                                       LanguageMode language_mode) {
   6022   LookupIterator it(object->GetIsolate(), object, index, object,
   6023                     LookupIterator::OWN);
   6024   return DeleteProperty(&it, language_mode);
   6025 }
   6026 
   6027 
   6028 Maybe<bool> JSReceiver::DeleteProperty(Handle<JSReceiver> object,
   6029                                        Handle<Name> name,
   6030                                        LanguageMode language_mode) {
   6031   LookupIterator it(object, name, object, LookupIterator::OWN);
   6032   return DeleteProperty(&it, language_mode);
   6033 }
   6034 
   6035 
   6036 Maybe<bool> JSReceiver::DeletePropertyOrElement(Handle<JSReceiver> object,
   6037                                                 Handle<Name> name,
   6038                                                 LanguageMode language_mode) {
   6039   LookupIterator it = LookupIterator::PropertyOrElement(
   6040       name->GetIsolate(), object, name, object, LookupIterator::OWN);
   6041   return DeleteProperty(&it, language_mode);
   6042 }
   6043 
   6044 // ES6 19.1.2.4
   6045 // static
   6046 Object* JSReceiver::DefineProperty(Isolate* isolate, Handle<Object> object,
   6047                                    Handle<Object> key,
   6048                                    Handle<Object> attributes) {
   6049   // 1. If Type(O) is not Object, throw a TypeError exception.
   6050   if (!object->IsJSReceiver()) {
   6051     Handle<String> fun_name =
   6052         isolate->factory()->InternalizeUtf8String("Object.defineProperty");
   6053     THROW_NEW_ERROR_RETURN_FAILURE(
   6054         isolate, NewTypeError(MessageTemplate::kCalledOnNonObject, fun_name));
   6055   }
   6056   // 2. Let key be ToPropertyKey(P).
   6057   // 3. ReturnIfAbrupt(key).
   6058   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, key, ToPropertyKey(isolate, key));
   6059   // 4. Let desc be ToPropertyDescriptor(Attributes).
   6060   // 5. ReturnIfAbrupt(desc).
   6061   PropertyDescriptor desc;
   6062   if (!PropertyDescriptor::ToPropertyDescriptor(isolate, attributes, &desc)) {
   6063     return isolate->heap()->exception();
   6064   }
   6065   // 6. Let success be DefinePropertyOrThrow(O,key, desc).
   6066   Maybe<bool> success = DefineOwnProperty(
   6067       isolate, Handle<JSReceiver>::cast(object), key, &desc, THROW_ON_ERROR);
   6068   // 7. ReturnIfAbrupt(success).
   6069   MAYBE_RETURN(success, isolate->heap()->exception());
   6070   CHECK(success.FromJust());
   6071   // 8. Return O.
   6072   return *object;
   6073 }
   6074 
   6075 
   6076 // ES6 19.1.2.3.1
   6077 // static
   6078 MaybeHandle<Object> JSReceiver::DefineProperties(Isolate* isolate,
   6079                                                  Handle<Object> object,
   6080                                                  Handle<Object> properties) {
   6081   // 1. If Type(O) is not Object, throw a TypeError exception.
   6082   if (!object->IsJSReceiver()) {
   6083     Handle<String> fun_name =
   6084         isolate->factory()->InternalizeUtf8String("Object.defineProperties");
   6085     THROW_NEW_ERROR(isolate,
   6086                     NewTypeError(MessageTemplate::kCalledOnNonObject, fun_name),
   6087                     Object);
   6088   }
   6089   // 2. Let props be ToObject(Properties).
   6090   // 3. ReturnIfAbrupt(props).
   6091   Handle<JSReceiver> props;
   6092   ASSIGN_RETURN_ON_EXCEPTION(isolate, props,
   6093                              Object::ToObject(isolate, properties), Object);
   6094 
   6095   // 4. Let keys be props.[[OwnPropertyKeys]]().
   6096   // 5. ReturnIfAbrupt(keys).
   6097   Handle<FixedArray> keys;
   6098   ASSIGN_RETURN_ON_EXCEPTION(
   6099       isolate, keys, KeyAccumulator::GetKeys(props, KeyCollectionMode::kOwnOnly,
   6100                                              ALL_PROPERTIES),
   6101       Object);
   6102   // 6. Let descriptors be an empty List.
   6103   int capacity = keys->length();
   6104   std::vector<PropertyDescriptor> descriptors(capacity);
   6105   size_t descriptors_index = 0;
   6106   // 7. Repeat for each element nextKey of keys in List order,
   6107   for (int i = 0; i < keys->length(); ++i) {
   6108     Handle<Object> next_key(keys->get(i), isolate);
   6109     // 7a. Let propDesc be props.[[GetOwnProperty]](nextKey).
   6110     // 7b. ReturnIfAbrupt(propDesc).
   6111     bool success = false;
   6112     LookupIterator it = LookupIterator::PropertyOrElement(
   6113         isolate, props, next_key, &success, LookupIterator::OWN);
   6114     DCHECK(success);
   6115     Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
   6116     if (!maybe.IsJust()) return MaybeHandle<Object>();
   6117     PropertyAttributes attrs = maybe.FromJust();
   6118     // 7c. If propDesc is not undefined and propDesc.[[Enumerable]] is true:
   6119     if (attrs == ABSENT) continue;
   6120     if (attrs & DONT_ENUM) continue;
   6121     // 7c i. Let descObj be Get(props, nextKey).
   6122     // 7c ii. ReturnIfAbrupt(descObj).
   6123     Handle<Object> desc_obj;
   6124     ASSIGN_RETURN_ON_EXCEPTION(isolate, desc_obj, Object::GetProperty(&it),
   6125                                Object);
   6126     // 7c iii. Let desc be ToPropertyDescriptor(descObj).
   6127     success = PropertyDescriptor::ToPropertyDescriptor(
   6128         isolate, desc_obj, &descriptors[descriptors_index]);
   6129     // 7c iv. ReturnIfAbrupt(desc).
   6130     if (!success) return MaybeHandle<Object>();
   6131     // 7c v. Append the pair (a two element List) consisting of nextKey and
   6132     //       desc to the end of descriptors.
   6133     descriptors[descriptors_index].set_name(next_key);
   6134     descriptors_index++;
   6135   }
   6136   // 8. For each pair from descriptors in list order,
   6137   for (size_t i = 0; i < descriptors_index; ++i) {
   6138     PropertyDescriptor* desc = &descriptors[i];
   6139     // 8a. Let P be the first element of pair.
   6140     // 8b. Let desc be the second element of pair.
   6141     // 8c. Let status be DefinePropertyOrThrow(O, P, desc).
   6142     Maybe<bool> status =
   6143         DefineOwnProperty(isolate, Handle<JSReceiver>::cast(object),
   6144                           desc->name(), desc, THROW_ON_ERROR);
   6145     // 8d. ReturnIfAbrupt(status).
   6146     if (!status.IsJust()) return MaybeHandle<Object>();
   6147     CHECK(status.FromJust());
   6148   }
   6149   // 9. Return o.
   6150   return object;
   6151 }
   6152 
   6153 
   6154 // static
   6155 Maybe<bool> JSReceiver::DefineOwnProperty(Isolate* isolate,
   6156                                           Handle<JSReceiver> object,
   6157                                           Handle<Object> key,
   6158                                           PropertyDescriptor* desc,
   6159                                           ShouldThrow should_throw) {
   6160   if (object->IsJSArray()) {
   6161     return JSArray::DefineOwnProperty(isolate, Handle<JSArray>::cast(object),
   6162                                       key, desc, should_throw);
   6163   }
   6164   if (object->IsJSProxy()) {
   6165     return JSProxy::DefineOwnProperty(isolate, Handle<JSProxy>::cast(object),
   6166                                       key, desc, should_throw);
   6167   }
   6168   if (object->IsJSTypedArray()) {
   6169     return JSTypedArray::DefineOwnProperty(
   6170         isolate, Handle<JSTypedArray>::cast(object), key, desc, should_throw);
   6171   }
   6172   // TODO(neis): Special case for JSModuleNamespace?
   6173 
   6174   // OrdinaryDefineOwnProperty, by virtue of calling
   6175   // DefineOwnPropertyIgnoreAttributes, can handle arguments
   6176   // (ES#sec-arguments-exotic-objects-defineownproperty-p-desc).
   6177   return OrdinaryDefineOwnProperty(isolate, Handle<JSObject>::cast(object), key,
   6178                                    desc, should_throw);
   6179 }
   6180 
   6181 
   6182 // static
   6183 Maybe<bool> JSReceiver::OrdinaryDefineOwnProperty(Isolate* isolate,
   6184                                                   Handle<JSObject> object,
   6185                                                   Handle<Object> key,
   6186                                                   PropertyDescriptor* desc,
   6187                                                   ShouldThrow should_throw) {
   6188   bool success = false;
   6189   DCHECK(key->IsName() || key->IsNumber());  // |key| is a PropertyKey...
   6190   LookupIterator it = LookupIterator::PropertyOrElement(
   6191       isolate, object, key, &success, LookupIterator::OWN);
   6192   DCHECK(success);  // ...so creating a LookupIterator can't fail.
   6193 
   6194   // Deal with access checks first.
   6195   if (it.state() == LookupIterator::ACCESS_CHECK) {
   6196     if (!it.HasAccess()) {
   6197       isolate->ReportFailedAccessCheck(it.GetHolder<JSObject>());
   6198       RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
   6199       return Just(true);
   6200     }
   6201     it.Next();
   6202   }
   6203 
   6204   // Handle interceptor
   6205   if (it.state() == LookupIterator::INTERCEPTOR) {
   6206     if (it.HolderIsReceiverOrHiddenPrototype()) {
   6207       Maybe<bool> result = DefinePropertyWithInterceptorInternal(
   6208           &it, it.GetInterceptor(), should_throw, *desc);
   6209       if (result.IsNothing() || result.FromJust()) {
   6210         return result;
   6211       }
   6212     }
   6213   }
   6214 
   6215   return OrdinaryDefineOwnProperty(&it, desc, should_throw);
   6216 }
   6217 
   6218 
   6219 // ES6 9.1.6.1
   6220 // static
   6221 Maybe<bool> JSReceiver::OrdinaryDefineOwnProperty(LookupIterator* it,
   6222                                                   PropertyDescriptor* desc,
   6223                                                   ShouldThrow should_throw) {
   6224   Isolate* isolate = it->isolate();
   6225   // 1. Let current be O.[[GetOwnProperty]](P).
   6226   // 2. ReturnIfAbrupt(current).
   6227   PropertyDescriptor current;
   6228   MAYBE_RETURN(GetOwnPropertyDescriptor(it, &current), Nothing<bool>());
   6229 
   6230   // TODO(jkummerow/verwaest): It would be nice if we didn't have to reset
   6231   // the iterator every time. Currently, the reasons why we need it are:
   6232   // - handle interceptors correctly
   6233   // - handle accessors correctly (which might change the holder's map)
   6234   it->Restart();
   6235   // 3. Let extensible be the value of the [[Extensible]] internal slot of O.
   6236   Handle<JSObject> object = Handle<JSObject>::cast(it->GetReceiver());
   6237   bool extensible = JSObject::IsExtensible(object);
   6238 
   6239   return ValidateAndApplyPropertyDescriptor(isolate, it, extensible, desc,
   6240                                             &current, should_throw);
   6241 }
   6242 
   6243 
   6244 // ES6 9.1.6.2
   6245 // static
   6246 Maybe<bool> JSReceiver::IsCompatiblePropertyDescriptor(
   6247     Isolate* isolate, bool extensible, PropertyDescriptor* desc,
   6248     PropertyDescriptor* current, Handle<Name> property_name,
   6249     ShouldThrow should_throw) {
   6250   // 1. Return ValidateAndApplyPropertyDescriptor(undefined, undefined,
   6251   //    Extensible, Desc, Current).
   6252   return ValidateAndApplyPropertyDescriptor(
   6253       isolate, NULL, extensible, desc, current, should_throw, property_name);
   6254 }
   6255 
   6256 
   6257 // ES6 9.1.6.3
   6258 // static
   6259 Maybe<bool> JSReceiver::ValidateAndApplyPropertyDescriptor(
   6260     Isolate* isolate, LookupIterator* it, bool extensible,
   6261     PropertyDescriptor* desc, PropertyDescriptor* current,
   6262     ShouldThrow should_throw, Handle<Name> property_name) {
   6263   // We either need a LookupIterator, or a property name.
   6264   DCHECK((it == NULL) != property_name.is_null());
   6265   Handle<JSObject> object;
   6266   if (it != NULL) object = Handle<JSObject>::cast(it->GetReceiver());
   6267   bool desc_is_data_descriptor = PropertyDescriptor::IsDataDescriptor(desc);
   6268   bool desc_is_accessor_descriptor =
   6269       PropertyDescriptor::IsAccessorDescriptor(desc);
   6270   bool desc_is_generic_descriptor =
   6271       PropertyDescriptor::IsGenericDescriptor(desc);
   6272   // 1. (Assert)
   6273   // 2. If current is undefined, then
   6274   if (current->is_empty()) {
   6275     // 2a. If extensible is false, return false.
   6276     if (!extensible) {
   6277       RETURN_FAILURE(isolate, should_throw,
   6278                      NewTypeError(MessageTemplate::kDefineDisallowed,
   6279                                   it != NULL ? it->GetName() : property_name));
   6280     }
   6281     // 2c. If IsGenericDescriptor(Desc) or IsDataDescriptor(Desc) is true, then:
   6282     // (This is equivalent to !IsAccessorDescriptor(desc).)
   6283     DCHECK((desc_is_generic_descriptor || desc_is_data_descriptor) ==
   6284            !desc_is_accessor_descriptor);
   6285     if (!desc_is_accessor_descriptor) {
   6286       // 2c i. If O is not undefined, create an own data property named P of
   6287       // object O whose [[Value]], [[Writable]], [[Enumerable]] and
   6288       // [[Configurable]] attribute values are described by Desc. If the value
   6289       // of an attribute field of Desc is absent, the attribute of the newly
   6290       // created property is set to its default value.
   6291       if (it != NULL) {
   6292         if (!desc->has_writable()) desc->set_writable(false);
   6293         if (!desc->has_enumerable()) desc->set_enumerable(false);
   6294         if (!desc->has_configurable()) desc->set_configurable(false);
   6295         Handle<Object> value(
   6296             desc->has_value()
   6297                 ? desc->value()
   6298                 : Handle<Object>::cast(isolate->factory()->undefined_value()));
   6299         MaybeHandle<Object> result =
   6300             JSObject::DefineOwnPropertyIgnoreAttributes(it, value,
   6301                                                         desc->ToAttributes());
   6302         if (result.is_null()) return Nothing<bool>();
   6303       }
   6304     } else {
   6305       // 2d. Else Desc must be an accessor Property Descriptor,
   6306       DCHECK(desc_is_accessor_descriptor);
   6307       // 2d i. If O is not undefined, create an own accessor property named P
   6308       // of object O whose [[Get]], [[Set]], [[Enumerable]] and
   6309       // [[Configurable]] attribute values are described by Desc. If the value
   6310       // of an attribute field of Desc is absent, the attribute of the newly
   6311       // created property is set to its default value.
   6312       if (it != NULL) {
   6313         if (!desc->has_enumerable()) desc->set_enumerable(false);
   6314         if (!desc->has_configurable()) desc->set_configurable(false);
   6315         Handle<Object> getter(
   6316             desc->has_get()
   6317                 ? desc->get()
   6318                 : Handle<Object>::cast(isolate->factory()->null_value()));
   6319         Handle<Object> setter(
   6320             desc->has_set()
   6321                 ? desc->set()
   6322                 : Handle<Object>::cast(isolate->factory()->null_value()));
   6323         MaybeHandle<Object> result =
   6324             JSObject::DefineAccessor(it, getter, setter, desc->ToAttributes());
   6325         if (result.is_null()) return Nothing<bool>();
   6326       }
   6327     }
   6328     // 2e. Return true.
   6329     return Just(true);
   6330   }
   6331   // 3. Return true, if every field in Desc is absent.
   6332   // 4. Return true, if every field in Desc also occurs in current and the
   6333   // value of every field in Desc is the same value as the corresponding field
   6334   // in current when compared using the SameValue algorithm.
   6335   if ((!desc->has_enumerable() ||
   6336        desc->enumerable() == current->enumerable()) &&
   6337       (!desc->has_configurable() ||
   6338        desc->configurable() == current->configurable()) &&
   6339       (!desc->has_value() ||
   6340        (current->has_value() && current->value()->SameValue(*desc->value()))) &&
   6341       (!desc->has_writable() ||
   6342        (current->has_writable() && current->writable() == desc->writable())) &&
   6343       (!desc->has_get() ||
   6344        (current->has_get() && current->get()->SameValue(*desc->get()))) &&
   6345       (!desc->has_set() ||
   6346        (current->has_set() && current->set()->SameValue(*desc->set())))) {
   6347     return Just(true);
   6348   }
   6349   // 5. If the [[Configurable]] field of current is false, then
   6350   if (!current->configurable()) {
   6351     // 5a. Return false, if the [[Configurable]] field of Desc is true.
   6352     if (desc->has_configurable() && desc->configurable()) {
   6353       RETURN_FAILURE(isolate, should_throw,
   6354                      NewTypeError(MessageTemplate::kRedefineDisallowed,
   6355                                   it != NULL ? it->GetName() : property_name));
   6356     }
   6357     // 5b. Return false, if the [[Enumerable]] field of Desc is present and the
   6358     // [[Enumerable]] fields of current and Desc are the Boolean negation of
   6359     // each other.
   6360     if (desc->has_enumerable() && desc->enumerable() != current->enumerable()) {
   6361       RETURN_FAILURE(isolate, should_throw,
   6362                      NewTypeError(MessageTemplate::kRedefineDisallowed,
   6363                                   it != NULL ? it->GetName() : property_name));
   6364     }
   6365   }
   6366 
   6367   bool current_is_data_descriptor =
   6368       PropertyDescriptor::IsDataDescriptor(current);
   6369   // 6. If IsGenericDescriptor(Desc) is true, no further validation is required.
   6370   if (desc_is_generic_descriptor) {
   6371     // Nothing to see here.
   6372 
   6373     // 7. Else if IsDataDescriptor(current) and IsDataDescriptor(Desc) have
   6374     // different results, then:
   6375   } else if (current_is_data_descriptor != desc_is_data_descriptor) {
   6376     // 7a. Return false, if the [[Configurable]] field of current is false.
   6377     if (!current->configurable()) {
   6378       RETURN_FAILURE(isolate, should_throw,
   6379                      NewTypeError(MessageTemplate::kRedefineDisallowed,
   6380                                   it != NULL ? it->GetName() : property_name));
   6381     }
   6382     // 7b. If IsDataDescriptor(current) is true, then:
   6383     if (current_is_data_descriptor) {
   6384       // 7b i. If O is not undefined, convert the property named P of object O
   6385       // from a data property to an accessor property. Preserve the existing
   6386       // values of the converted property's [[Configurable]] and [[Enumerable]]
   6387       // attributes and set the rest of the property's attributes to their
   6388       // default values.
   6389       // --> Folded into step 10.
   6390     } else {
   6391       // 7c i. If O is not undefined, convert the property named P of object O
   6392       // from an accessor property to a data property. Preserve the existing
   6393       // values of the converted propertys [[Configurable]] and [[Enumerable]]
   6394       // attributes and set the rest of the propertys attributes to their
   6395       // default values.
   6396       // --> Folded into step 10.
   6397     }
   6398 
   6399     // 8. Else if IsDataDescriptor(current) and IsDataDescriptor(Desc) are both
   6400     // true, then:
   6401   } else if (current_is_data_descriptor && desc_is_data_descriptor) {
   6402     // 8a. If the [[Configurable]] field of current is false, then:
   6403     if (!current->configurable()) {
   6404       // 8a i. Return false, if the [[Writable]] field of current is false and
   6405       // the [[Writable]] field of Desc is true.
   6406       if (!current->writable() && desc->has_writable() && desc->writable()) {
   6407         RETURN_FAILURE(
   6408             isolate, should_throw,
   6409             NewTypeError(MessageTemplate::kRedefineDisallowed,
   6410                          it != NULL ? it->GetName() : property_name));
   6411       }
   6412       // 8a ii. If the [[Writable]] field of current is false, then:
   6413       if (!current->writable()) {
   6414         // 8a ii 1. Return false, if the [[Value]] field of Desc is present and
   6415         // SameValue(Desc.[[Value]], current.[[Value]]) is false.
   6416         if (desc->has_value() && !desc->value()->SameValue(*current->value())) {
   6417           RETURN_FAILURE(
   6418               isolate, should_throw,
   6419               NewTypeError(MessageTemplate::kRedefineDisallowed,
   6420                            it != NULL ? it->GetName() : property_name));
   6421         }
   6422       }
   6423     }
   6424   } else {
   6425     // 9. Else IsAccessorDescriptor(current) and IsAccessorDescriptor(Desc)
   6426     // are both true,
   6427     DCHECK(PropertyDescriptor::IsAccessorDescriptor(current) &&
   6428            desc_is_accessor_descriptor);
   6429     // 9a. If the [[Configurable]] field of current is false, then:
   6430     if (!current->configurable()) {
   6431       // 9a i. Return false, if the [[Set]] field of Desc is present and
   6432       // SameValue(Desc.[[Set]], current.[[Set]]) is false.
   6433       if (desc->has_set() && !desc->set()->SameValue(*current->set())) {
   6434         RETURN_FAILURE(
   6435             isolate, should_throw,
   6436             NewTypeError(MessageTemplate::kRedefineDisallowed,
   6437                          it != NULL ? it->GetName() : property_name));
   6438       }
   6439       // 9a ii. Return false, if the [[Get]] field of Desc is present and
   6440       // SameValue(Desc.[[Get]], current.[[Get]]) is false.
   6441       if (desc->has_get() && !desc->get()->SameValue(*current->get())) {
   6442         RETURN_FAILURE(
   6443             isolate, should_throw,
   6444             NewTypeError(MessageTemplate::kRedefineDisallowed,
   6445                          it != NULL ? it->GetName() : property_name));
   6446       }
   6447     }
   6448   }
   6449 
   6450   // 10. If O is not undefined, then:
   6451   if (it != NULL) {
   6452     // 10a. For each field of Desc that is present, set the corresponding
   6453     // attribute of the property named P of object O to the value of the field.
   6454     PropertyAttributes attrs = NONE;
   6455 
   6456     if (desc->has_enumerable()) {
   6457       attrs = static_cast<PropertyAttributes>(
   6458           attrs | (desc->enumerable() ? NONE : DONT_ENUM));
   6459     } else {
   6460       attrs = static_cast<PropertyAttributes>(
   6461           attrs | (current->enumerable() ? NONE : DONT_ENUM));
   6462     }
   6463     if (desc->has_configurable()) {
   6464       attrs = static_cast<PropertyAttributes>(
   6465           attrs | (desc->configurable() ? NONE : DONT_DELETE));
   6466     } else {
   6467       attrs = static_cast<PropertyAttributes>(
   6468           attrs | (current->configurable() ? NONE : DONT_DELETE));
   6469     }
   6470     if (desc_is_data_descriptor ||
   6471         (desc_is_generic_descriptor && current_is_data_descriptor)) {
   6472       if (desc->has_writable()) {
   6473         attrs = static_cast<PropertyAttributes>(
   6474             attrs | (desc->writable() ? NONE : READ_ONLY));
   6475       } else {
   6476         attrs = static_cast<PropertyAttributes>(
   6477             attrs | (current->writable() ? NONE : READ_ONLY));
   6478       }
   6479       Handle<Object> value(
   6480           desc->has_value() ? desc->value()
   6481                             : current->has_value()
   6482                                   ? current->value()
   6483                                   : Handle<Object>::cast(
   6484                                         isolate->factory()->undefined_value()));
   6485       MaybeHandle<Object> result =
   6486           JSObject::DefineOwnPropertyIgnoreAttributes(it, value, attrs);
   6487       if (result.is_null()) return Nothing<bool>();
   6488     } else {
   6489       DCHECK(desc_is_accessor_descriptor ||
   6490              (desc_is_generic_descriptor &&
   6491               PropertyDescriptor::IsAccessorDescriptor(current)));
   6492       Handle<Object> getter(
   6493           desc->has_get()
   6494               ? desc->get()
   6495               : current->has_get()
   6496                     ? current->get()
   6497                     : Handle<Object>::cast(isolate->factory()->null_value()));
   6498       Handle<Object> setter(
   6499           desc->has_set()
   6500               ? desc->set()
   6501               : current->has_set()
   6502                     ? current->set()
   6503                     : Handle<Object>::cast(isolate->factory()->null_value()));
   6504       MaybeHandle<Object> result =
   6505           JSObject::DefineAccessor(it, getter, setter, attrs);
   6506       if (result.is_null()) return Nothing<bool>();
   6507     }
   6508   }
   6509 
   6510   // 11. Return true.
   6511   return Just(true);
   6512 }
   6513 
   6514 
   6515 // static
   6516 Maybe<bool> JSReceiver::CreateDataProperty(LookupIterator* it,
   6517                                            Handle<Object> value,
   6518                                            ShouldThrow should_throw) {
   6519   DCHECK(!it->check_prototype_chain());
   6520   Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(it->GetReceiver());
   6521   Isolate* isolate = receiver->GetIsolate();
   6522 
   6523   if (receiver->IsJSObject()) {
   6524     return JSObject::CreateDataProperty(it, value, should_throw);  // Shortcut.
   6525   }
   6526 
   6527   PropertyDescriptor new_desc;
   6528   new_desc.set_value(value);
   6529   new_desc.set_writable(true);
   6530   new_desc.set_enumerable(true);
   6531   new_desc.set_configurable(true);
   6532 
   6533   return JSReceiver::DefineOwnProperty(isolate, receiver, it->GetName(),
   6534                                        &new_desc, should_throw);
   6535 }
   6536 
   6537 Maybe<bool> JSObject::CreateDataProperty(LookupIterator* it,
   6538                                          Handle<Object> value,
   6539                                          ShouldThrow should_throw) {
   6540   DCHECK(it->GetReceiver()->IsJSObject());
   6541   MAYBE_RETURN(JSReceiver::GetPropertyAttributes(it), Nothing<bool>());
   6542   Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(it->GetReceiver());
   6543   Isolate* isolate = receiver->GetIsolate();
   6544 
   6545   if (it->IsFound()) {
   6546     Maybe<PropertyAttributes> attributes = GetPropertyAttributes(it);
   6547     MAYBE_RETURN(attributes, Nothing<bool>());
   6548     if ((attributes.FromJust() & DONT_DELETE) != 0) {
   6549       RETURN_FAILURE(
   6550           isolate, should_throw,
   6551           NewTypeError(MessageTemplate::kRedefineDisallowed, it->GetName()));
   6552     }
   6553   } else {
   6554     if (!JSObject::IsExtensible(Handle<JSObject>::cast(it->GetReceiver()))) {
   6555       RETURN_FAILURE(
   6556           isolate, should_throw,
   6557           NewTypeError(MessageTemplate::kDefineDisallowed, it->GetName()));
   6558     }
   6559   }
   6560 
   6561   RETURN_ON_EXCEPTION_VALUE(it->isolate(),
   6562                             DefineOwnPropertyIgnoreAttributes(it, value, NONE),
   6563                             Nothing<bool>());
   6564 
   6565   return Just(true);
   6566 }
   6567 
   6568 
   6569 // TODO(jkummerow): Consider unification with FastAsArrayLength() in
   6570 // accessors.cc.
   6571 bool PropertyKeyToArrayLength(Handle<Object> value, uint32_t* length) {
   6572   DCHECK(value->IsNumber() || value->IsName());
   6573   if (value->ToArrayLength(length)) return true;
   6574   if (value->IsString()) return String::cast(*value)->AsArrayIndex(length);
   6575   return false;
   6576 }
   6577 
   6578 bool PropertyKeyToArrayIndex(Handle<Object> index_obj, uint32_t* output) {
   6579   return PropertyKeyToArrayLength(index_obj, output) && *output != kMaxUInt32;
   6580 }
   6581 
   6582 
   6583 // ES6 9.4.2.1
   6584 // static
   6585 Maybe<bool> JSArray::DefineOwnProperty(Isolate* isolate, Handle<JSArray> o,
   6586                                        Handle<Object> name,
   6587                                        PropertyDescriptor* desc,
   6588                                        ShouldThrow should_throw) {
   6589   // 1. Assert: IsPropertyKey(P) is true. ("P" is |name|.)
   6590   // 2. If P is "length", then:
   6591   // TODO(jkummerow): Check if we need slow string comparison.
   6592   if (*name == isolate->heap()->length_string()) {
   6593     // 2a. Return ArraySetLength(A, Desc).
   6594     return ArraySetLength(isolate, o, desc, should_throw);
   6595   }
   6596   // 3. Else if P is an array index, then:
   6597   uint32_t index = 0;
   6598   if (PropertyKeyToArrayIndex(name, &index)) {
   6599     // 3a. Let oldLenDesc be OrdinaryGetOwnProperty(A, "length").
   6600     PropertyDescriptor old_len_desc;
   6601     Maybe<bool> success = GetOwnPropertyDescriptor(
   6602         isolate, o, isolate->factory()->length_string(), &old_len_desc);
   6603     // 3b. (Assert)
   6604     DCHECK(success.FromJust());
   6605     USE(success);
   6606     // 3c. Let oldLen be oldLenDesc.[[Value]].
   6607     uint32_t old_len = 0;
   6608     CHECK(old_len_desc.value()->ToArrayLength(&old_len));
   6609     // 3d. Let index be ToUint32(P).
   6610     // (Already done above.)
   6611     // 3e. (Assert)
   6612     // 3f. If index >= oldLen and oldLenDesc.[[Writable]] is false,
   6613     //     return false.
   6614     if (index >= old_len && old_len_desc.has_writable() &&
   6615         !old_len_desc.writable()) {
   6616       RETURN_FAILURE(isolate, should_throw,
   6617                      NewTypeError(MessageTemplate::kDefineDisallowed, name));
   6618     }
   6619     // 3g. Let succeeded be OrdinaryDefineOwnProperty(A, P, Desc).
   6620     Maybe<bool> succeeded =
   6621         OrdinaryDefineOwnProperty(isolate, o, name, desc, should_throw);
   6622     // 3h. Assert: succeeded is not an abrupt completion.
   6623     //     In our case, if should_throw == THROW_ON_ERROR, it can be!
   6624     // 3i. If succeeded is false, return false.
   6625     if (succeeded.IsNothing() || !succeeded.FromJust()) return succeeded;
   6626     // 3j. If index >= oldLen, then:
   6627     if (index >= old_len) {
   6628       // 3j i. Set oldLenDesc.[[Value]] to index + 1.
   6629       old_len_desc.set_value(isolate->factory()->NewNumberFromUint(index + 1));
   6630       // 3j ii. Let succeeded be
   6631       //        OrdinaryDefineOwnProperty(A, "length", oldLenDesc).
   6632       succeeded = OrdinaryDefineOwnProperty(isolate, o,
   6633                                             isolate->factory()->length_string(),
   6634                                             &old_len_desc, should_throw);
   6635       // 3j iii. Assert: succeeded is true.
   6636       DCHECK(succeeded.FromJust());
   6637       USE(succeeded);
   6638     }
   6639     // 3k. Return true.
   6640     return Just(true);
   6641   }
   6642 
   6643   // 4. Return OrdinaryDefineOwnProperty(A, P, Desc).
   6644   return OrdinaryDefineOwnProperty(isolate, o, name, desc, should_throw);
   6645 }
   6646 
   6647 
   6648 // Part of ES6 9.4.2.4 ArraySetLength.
   6649 // static
   6650 bool JSArray::AnythingToArrayLength(Isolate* isolate,
   6651                                     Handle<Object> length_object,
   6652                                     uint32_t* output) {
   6653   // Fast path: check numbers and strings that can be converted directly
   6654   // and unobservably.
   6655   if (length_object->ToArrayLength(output)) return true;
   6656   if (length_object->IsString() &&
   6657       Handle<String>::cast(length_object)->AsArrayIndex(output)) {
   6658     return true;
   6659   }
   6660   // Slow path: follow steps in ES6 9.4.2.4 "ArraySetLength".
   6661   // 3. Let newLen be ToUint32(Desc.[[Value]]).
   6662   Handle<Object> uint32_v;
   6663   if (!Object::ToUint32(isolate, length_object).ToHandle(&uint32_v)) {
   6664     // 4. ReturnIfAbrupt(newLen).
   6665     return false;
   6666   }
   6667   // 5. Let numberLen be ToNumber(Desc.[[Value]]).
   6668   Handle<Object> number_v;
   6669   if (!Object::ToNumber(length_object).ToHandle(&number_v)) {
   6670     // 6. ReturnIfAbrupt(newLen).
   6671     return false;
   6672   }
   6673   // 7. If newLen != numberLen, throw a RangeError exception.
   6674   if (uint32_v->Number() != number_v->Number()) {
   6675     Handle<Object> exception =
   6676         isolate->factory()->NewRangeError(MessageTemplate::kInvalidArrayLength);
   6677     isolate->Throw(*exception);
   6678     return false;
   6679   }
   6680   CHECK(uint32_v->ToArrayLength(output));
   6681   return true;
   6682 }
   6683 
   6684 
   6685 // ES6 9.4.2.4
   6686 // static
   6687 Maybe<bool> JSArray::ArraySetLength(Isolate* isolate, Handle<JSArray> a,
   6688                                     PropertyDescriptor* desc,
   6689                                     ShouldThrow should_throw) {
   6690   // 1. If the [[Value]] field of Desc is absent, then
   6691   if (!desc->has_value()) {
   6692     // 1a. Return OrdinaryDefineOwnProperty(A, "length", Desc).
   6693     return OrdinaryDefineOwnProperty(
   6694         isolate, a, isolate->factory()->length_string(), desc, should_throw);
   6695   }
   6696   // 2. Let newLenDesc be a copy of Desc.
   6697   // (Actual copying is not necessary.)
   6698   PropertyDescriptor* new_len_desc = desc;
   6699   // 3. - 7. Convert Desc.[[Value]] to newLen.
   6700   uint32_t new_len = 0;
   6701   if (!AnythingToArrayLength(isolate, desc->value(), &new_len)) {
   6702     DCHECK(isolate->has_pending_exception());
   6703     return Nothing<bool>();
   6704   }
   6705   // 8. Set newLenDesc.[[Value]] to newLen.
   6706   // (Done below, if needed.)
   6707   // 9. Let oldLenDesc be OrdinaryGetOwnProperty(A, "length").
   6708   PropertyDescriptor old_len_desc;
   6709   Maybe<bool> success = GetOwnPropertyDescriptor(
   6710       isolate, a, isolate->factory()->length_string(), &old_len_desc);
   6711   // 10. (Assert)
   6712   DCHECK(success.FromJust());
   6713   USE(success);
   6714   // 11. Let oldLen be oldLenDesc.[[Value]].
   6715   uint32_t old_len = 0;
   6716   CHECK(old_len_desc.value()->ToArrayLength(&old_len));
   6717   // 12. If newLen >= oldLen, then
   6718   if (new_len >= old_len) {
   6719     // 8. Set newLenDesc.[[Value]] to newLen.
   6720     // 12a. Return OrdinaryDefineOwnProperty(A, "length", newLenDesc).
   6721     new_len_desc->set_value(isolate->factory()->NewNumberFromUint(new_len));
   6722     return OrdinaryDefineOwnProperty(isolate, a,
   6723                                      isolate->factory()->length_string(),
   6724                                      new_len_desc, should_throw);
   6725   }
   6726   // 13. If oldLenDesc.[[Writable]] is false, return false.
   6727   if (!old_len_desc.writable()) {
   6728     RETURN_FAILURE(isolate, should_throw,
   6729                    NewTypeError(MessageTemplate::kRedefineDisallowed,
   6730                                 isolate->factory()->length_string()));
   6731   }
   6732   // 14. If newLenDesc.[[Writable]] is absent or has the value true,
   6733   // let newWritable be true.
   6734   bool new_writable = false;
   6735   if (!new_len_desc->has_writable() || new_len_desc->writable()) {
   6736     new_writable = true;
   6737   } else {
   6738     // 15. Else,
   6739     // 15a. Need to defer setting the [[Writable]] attribute to false in case
   6740     //      any elements cannot be deleted.
   6741     // 15b. Let newWritable be false. (It's initialized as "false" anyway.)
   6742     // 15c. Set newLenDesc.[[Writable]] to true.
   6743     // (Not needed.)
   6744   }
   6745   // Most of steps 16 through 19 is implemented by JSArray::SetLength.
   6746   JSArray::SetLength(a, new_len);
   6747   // Steps 19d-ii, 20.
   6748   if (!new_writable) {
   6749     PropertyDescriptor readonly;
   6750     readonly.set_writable(false);
   6751     Maybe<bool> success = OrdinaryDefineOwnProperty(
   6752         isolate, a, isolate->factory()->length_string(), &readonly,
   6753         should_throw);
   6754     DCHECK(success.FromJust());
   6755     USE(success);
   6756   }
   6757   uint32_t actual_new_len = 0;
   6758   CHECK(a->length()->ToArrayLength(&actual_new_len));
   6759   // Steps 19d-v, 21. Return false if there were non-deletable elements.
   6760   bool result = actual_new_len == new_len;
   6761   if (!result) {
   6762     RETURN_FAILURE(
   6763         isolate, should_throw,
   6764         NewTypeError(MessageTemplate::kStrictDeleteProperty,
   6765                      isolate->factory()->NewNumberFromUint(actual_new_len - 1),
   6766                      a));
   6767   }
   6768   return Just(result);
   6769 }
   6770 
   6771 
   6772 // ES6 9.5.6
   6773 // static
   6774 Maybe<bool> JSProxy::DefineOwnProperty(Isolate* isolate, Handle<JSProxy> proxy,
   6775                                        Handle<Object> key,
   6776                                        PropertyDescriptor* desc,
   6777                                        ShouldThrow should_throw) {
   6778   STACK_CHECK(isolate, Nothing<bool>());
   6779   if (key->IsSymbol() && Handle<Symbol>::cast(key)->IsPrivate()) {
   6780     return SetPrivateProperty(isolate, proxy, Handle<Symbol>::cast(key), desc,
   6781                               should_throw);
   6782   }
   6783   Handle<String> trap_name = isolate->factory()->defineProperty_string();
   6784   // 1. Assert: IsPropertyKey(P) is true.
   6785   DCHECK(key->IsName() || key->IsNumber());
   6786   // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O.
   6787   Handle<Object> handler(proxy->handler(), isolate);
   6788   // 3. If handler is null, throw a TypeError exception.
   6789   // 4. Assert: Type(handler) is Object.
   6790   if (proxy->IsRevoked()) {
   6791     isolate->Throw(*isolate->factory()->NewTypeError(
   6792         MessageTemplate::kProxyRevoked, trap_name));
   6793     return Nothing<bool>();
   6794   }
   6795   // 5. Let target be the value of the [[ProxyTarget]] internal slot of O.
   6796   Handle<JSReceiver> target(proxy->target(), isolate);
   6797   // 6. Let trap be ? GetMethod(handler, "defineProperty").
   6798   Handle<Object> trap;
   6799   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   6800       isolate, trap,
   6801       Object::GetMethod(Handle<JSReceiver>::cast(handler), trap_name),
   6802       Nothing<bool>());
   6803   // 7. If trap is undefined, then:
   6804   if (trap->IsUndefined(isolate)) {
   6805     // 7a. Return target.[[DefineOwnProperty]](P, Desc).
   6806     return JSReceiver::DefineOwnProperty(isolate, target, key, desc,
   6807                                          should_throw);
   6808   }
   6809   // 8. Let descObj be FromPropertyDescriptor(Desc).
   6810   Handle<Object> desc_obj = desc->ToObject(isolate);
   6811   // 9. Let booleanTrapResult be
   6812   //    ToBoolean(? Call(trap, handler, target, P, descObj)).
   6813   Handle<Name> property_name =
   6814       key->IsName()
   6815           ? Handle<Name>::cast(key)
   6816           : Handle<Name>::cast(isolate->factory()->NumberToString(key));
   6817   // Do not leak private property names.
   6818   DCHECK(!property_name->IsPrivate());
   6819   Handle<Object> trap_result_obj;
   6820   Handle<Object> args[] = {target, property_name, desc_obj};
   6821   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   6822       isolate, trap_result_obj,
   6823       Execution::Call(isolate, trap, handler, arraysize(args), args),
   6824       Nothing<bool>());
   6825   // 10. If booleanTrapResult is false, return false.
   6826   if (!trap_result_obj->BooleanValue()) {
   6827     RETURN_FAILURE(isolate, should_throw,
   6828                    NewTypeError(MessageTemplate::kProxyTrapReturnedFalsishFor,
   6829                                 trap_name, property_name));
   6830   }
   6831   // 11. Let targetDesc be ? target.[[GetOwnProperty]](P).
   6832   PropertyDescriptor target_desc;
   6833   Maybe<bool> target_found =
   6834       JSReceiver::GetOwnPropertyDescriptor(isolate, target, key, &target_desc);
   6835   MAYBE_RETURN(target_found, Nothing<bool>());
   6836   // 12. Let extensibleTarget be ? IsExtensible(target).
   6837   Maybe<bool> maybe_extensible = JSReceiver::IsExtensible(target);
   6838   MAYBE_RETURN(maybe_extensible, Nothing<bool>());
   6839   bool extensible_target = maybe_extensible.FromJust();
   6840   // 13. If Desc has a [[Configurable]] field and if Desc.[[Configurable]]
   6841   //     is false, then:
   6842   // 13a. Let settingConfigFalse be true.
   6843   // 14. Else let settingConfigFalse be false.
   6844   bool setting_config_false = desc->has_configurable() && !desc->configurable();
   6845   // 15. If targetDesc is undefined, then
   6846   if (!target_found.FromJust()) {
   6847     // 15a. If extensibleTarget is false, throw a TypeError exception.
   6848     if (!extensible_target) {
   6849       isolate->Throw(*isolate->factory()->NewTypeError(
   6850           MessageTemplate::kProxyDefinePropertyNonExtensible, property_name));
   6851       return Nothing<bool>();
   6852     }
   6853     // 15b. If settingConfigFalse is true, throw a TypeError exception.
   6854     if (setting_config_false) {
   6855       isolate->Throw(*isolate->factory()->NewTypeError(
   6856           MessageTemplate::kProxyDefinePropertyNonConfigurable, property_name));
   6857       return Nothing<bool>();
   6858     }
   6859   } else {
   6860     // 16. Else targetDesc is not undefined,
   6861     // 16a. If IsCompatiblePropertyDescriptor(extensibleTarget, Desc,
   6862     //      targetDesc) is false, throw a TypeError exception.
   6863     Maybe<bool> valid =
   6864         IsCompatiblePropertyDescriptor(isolate, extensible_target, desc,
   6865                                        &target_desc, property_name, DONT_THROW);
   6866     MAYBE_RETURN(valid, Nothing<bool>());
   6867     if (!valid.FromJust()) {
   6868       isolate->Throw(*isolate->factory()->NewTypeError(
   6869           MessageTemplate::kProxyDefinePropertyIncompatible, property_name));
   6870       return Nothing<bool>();
   6871     }
   6872     // 16b. If settingConfigFalse is true and targetDesc.[[Configurable]] is
   6873     //      true, throw a TypeError exception.
   6874     if (setting_config_false && target_desc.configurable()) {
   6875       isolate->Throw(*isolate->factory()->NewTypeError(
   6876           MessageTemplate::kProxyDefinePropertyNonConfigurable, property_name));
   6877       return Nothing<bool>();
   6878     }
   6879   }
   6880   // 17. Return true.
   6881   return Just(true);
   6882 }
   6883 
   6884 
   6885 // static
   6886 Maybe<bool> JSProxy::SetPrivateProperty(Isolate* isolate, Handle<JSProxy> proxy,
   6887                                         Handle<Symbol> private_name,
   6888                                         PropertyDescriptor* desc,
   6889                                         ShouldThrow should_throw) {
   6890   // Despite the generic name, this can only add private data properties.
   6891   if (!PropertyDescriptor::IsDataDescriptor(desc) ||
   6892       desc->ToAttributes() != DONT_ENUM) {
   6893     RETURN_FAILURE(isolate, should_throw,
   6894                    NewTypeError(MessageTemplate::kProxyPrivate));
   6895   }
   6896   DCHECK(proxy->map()->is_dictionary_map());
   6897   Handle<Object> value =
   6898       desc->has_value()
   6899           ? desc->value()
   6900           : Handle<Object>::cast(isolate->factory()->undefined_value());
   6901 
   6902   LookupIterator it(proxy, private_name, proxy);
   6903 
   6904   if (it.IsFound()) {
   6905     DCHECK_EQ(LookupIterator::DATA, it.state());
   6906     DCHECK_EQ(DONT_ENUM, it.property_attributes());
   6907     it.WriteDataValue(value, false);
   6908     return Just(true);
   6909   }
   6910 
   6911   Handle<NameDictionary> dict(proxy->property_dictionary());
   6912   PropertyDetails details(kData, DONT_ENUM, 0, PropertyCellType::kNoCell);
   6913   Handle<NameDictionary> result =
   6914       NameDictionary::Add(dict, private_name, value, details);
   6915   if (!dict.is_identical_to(result)) proxy->set_properties(*result);
   6916   return Just(true);
   6917 }
   6918 
   6919 
   6920 // static
   6921 Maybe<bool> JSReceiver::GetOwnPropertyDescriptor(Isolate* isolate,
   6922                                                  Handle<JSReceiver> object,
   6923                                                  Handle<Object> key,
   6924                                                  PropertyDescriptor* desc) {
   6925   bool success = false;
   6926   DCHECK(key->IsName() || key->IsNumber());  // |key| is a PropertyKey...
   6927   LookupIterator it = LookupIterator::PropertyOrElement(
   6928       isolate, object, key, &success, LookupIterator::OWN);
   6929   DCHECK(success);  // ...so creating a LookupIterator can't fail.
   6930   return GetOwnPropertyDescriptor(&it, desc);
   6931 }
   6932 
   6933 namespace {
   6934 
   6935 Maybe<bool> GetPropertyDescriptorWithInterceptor(LookupIterator* it,
   6936                                                  PropertyDescriptor* desc) {
   6937   bool has_access = true;
   6938   if (it->state() == LookupIterator::ACCESS_CHECK) {
   6939     has_access = it->HasAccess() || JSObject::AllCanRead(it);
   6940     it->Next();
   6941   }
   6942 
   6943   if (has_access && it->state() == LookupIterator::INTERCEPTOR) {
   6944     Isolate* isolate = it->isolate();
   6945     Handle<InterceptorInfo> interceptor = it->GetInterceptor();
   6946     if (!interceptor->descriptor()->IsUndefined(isolate)) {
   6947       Handle<Object> result;
   6948       Handle<JSObject> holder = it->GetHolder<JSObject>();
   6949 
   6950       Handle<Object> receiver = it->GetReceiver();
   6951       if (!receiver->IsJSReceiver()) {
   6952         ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   6953             isolate, receiver, Object::ConvertReceiver(isolate, receiver),
   6954             Nothing<bool>());
   6955       }
   6956 
   6957       PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
   6958                                      *holder, Object::DONT_THROW);
   6959       if (it->IsElement()) {
   6960         uint32_t index = it->index();
   6961         v8::IndexedPropertyDescriptorCallback descriptorCallback =
   6962             v8::ToCData<v8::IndexedPropertyDescriptorCallback>(
   6963                 interceptor->descriptor());
   6964 
   6965         result = args.Call(descriptorCallback, index);
   6966       } else {
   6967         Handle<Name> name = it->name();
   6968         DCHECK(!name->IsPrivate());
   6969         v8::GenericNamedPropertyDescriptorCallback descriptorCallback =
   6970             v8::ToCData<v8::GenericNamedPropertyDescriptorCallback>(
   6971                 interceptor->descriptor());
   6972         result = args.Call(descriptorCallback, name);
   6973       }
   6974       if (!result.is_null()) {
   6975         // Request successfully intercepted, try to set the property
   6976         // descriptor.
   6977         Utils::ApiCheck(
   6978             PropertyDescriptor::ToPropertyDescriptor(isolate, result, desc),
   6979             it->IsElement() ? "v8::IndexedPropertyDescriptorCallback"
   6980                             : "v8::NamedPropertyDescriptorCallback",
   6981             "Invalid property descriptor.");
   6982 
   6983         return Just(true);
   6984       }
   6985     }
   6986   }
   6987   it->Restart();
   6988   return Just(false);
   6989 }
   6990 }  // namespace
   6991 
   6992 // ES6 9.1.5.1
   6993 // Returns true on success, false if the property didn't exist, nothing if
   6994 // an exception was thrown.
   6995 // static
   6996 Maybe<bool> JSReceiver::GetOwnPropertyDescriptor(LookupIterator* it,
   6997                                                  PropertyDescriptor* desc) {
   6998   Isolate* isolate = it->isolate();
   6999   // "Virtual" dispatch.
   7000   if (it->IsFound() && it->GetHolder<JSReceiver>()->IsJSProxy()) {
   7001     return JSProxy::GetOwnPropertyDescriptor(isolate, it->GetHolder<JSProxy>(),
   7002                                              it->GetName(), desc);
   7003   }
   7004 
   7005   Maybe<bool> intercepted = GetPropertyDescriptorWithInterceptor(it, desc);
   7006   MAYBE_RETURN(intercepted, Nothing<bool>());
   7007   if (intercepted.FromJust()) {
   7008     return Just(true);
   7009   }
   7010 
   7011   // Request was not intercepted, continue as normal.
   7012   // 1. (Assert)
   7013   // 2. If O does not have an own property with key P, return undefined.
   7014   Maybe<PropertyAttributes> maybe = JSObject::GetPropertyAttributes(it);
   7015   MAYBE_RETURN(maybe, Nothing<bool>());
   7016   PropertyAttributes attrs = maybe.FromJust();
   7017   if (attrs == ABSENT) return Just(false);
   7018   DCHECK(!isolate->has_pending_exception());
   7019 
   7020   // 3. Let D be a newly created Property Descriptor with no fields.
   7021   DCHECK(desc->is_empty());
   7022   // 4. Let X be O's own property whose key is P.
   7023   // 5. If X is a data property, then
   7024   bool is_accessor_pair = it->state() == LookupIterator::ACCESSOR &&
   7025                           it->GetAccessors()->IsAccessorPair();
   7026   if (!is_accessor_pair) {
   7027     // 5a. Set D.[[Value]] to the value of X's [[Value]] attribute.
   7028     Handle<Object> value;
   7029     if (!Object::GetProperty(it).ToHandle(&value)) {
   7030       DCHECK(isolate->has_pending_exception());
   7031       return Nothing<bool>();
   7032     }
   7033     desc->set_value(value);
   7034     // 5b. Set D.[[Writable]] to the value of X's [[Writable]] attribute
   7035     desc->set_writable((attrs & READ_ONLY) == 0);
   7036   } else {
   7037     // 6. Else X is an accessor property, so
   7038     Handle<AccessorPair> accessors =
   7039         Handle<AccessorPair>::cast(it->GetAccessors());
   7040     // 6a. Set D.[[Get]] to the value of X's [[Get]] attribute.
   7041     desc->set_get(AccessorPair::GetComponent(accessors, ACCESSOR_GETTER));
   7042     // 6b. Set D.[[Set]] to the value of X's [[Set]] attribute.
   7043     desc->set_set(AccessorPair::GetComponent(accessors, ACCESSOR_SETTER));
   7044   }
   7045 
   7046   // 7. Set D.[[Enumerable]] to the value of X's [[Enumerable]] attribute.
   7047   desc->set_enumerable((attrs & DONT_ENUM) == 0);
   7048   // 8. Set D.[[Configurable]] to the value of X's [[Configurable]] attribute.
   7049   desc->set_configurable((attrs & DONT_DELETE) == 0);
   7050   // 9. Return D.
   7051   DCHECK(PropertyDescriptor::IsAccessorDescriptor(desc) !=
   7052          PropertyDescriptor::IsDataDescriptor(desc));
   7053   return Just(true);
   7054 }
   7055 
   7056 
   7057 // ES6 9.5.5
   7058 // static
   7059 Maybe<bool> JSProxy::GetOwnPropertyDescriptor(Isolate* isolate,
   7060                                               Handle<JSProxy> proxy,
   7061                                               Handle<Name> name,
   7062                                               PropertyDescriptor* desc) {
   7063   DCHECK(!name->IsPrivate());
   7064   STACK_CHECK(isolate, Nothing<bool>());
   7065 
   7066   Handle<String> trap_name =
   7067       isolate->factory()->getOwnPropertyDescriptor_string();
   7068   // 1. (Assert)
   7069   // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O.
   7070   Handle<Object> handler(proxy->handler(), isolate);
   7071   // 3. If handler is null, throw a TypeError exception.
   7072   // 4. Assert: Type(handler) is Object.
   7073   if (proxy->IsRevoked()) {
   7074     isolate->Throw(*isolate->factory()->NewTypeError(
   7075         MessageTemplate::kProxyRevoked, trap_name));
   7076     return Nothing<bool>();
   7077   }
   7078   // 5. Let target be the value of the [[ProxyTarget]] internal slot of O.
   7079   Handle<JSReceiver> target(proxy->target(), isolate);
   7080   // 6. Let trap be ? GetMethod(handler, "getOwnPropertyDescriptor").
   7081   Handle<Object> trap;
   7082   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   7083       isolate, trap,
   7084       Object::GetMethod(Handle<JSReceiver>::cast(handler), trap_name),
   7085       Nothing<bool>());
   7086   // 7. If trap is undefined, then
   7087   if (trap->IsUndefined(isolate)) {
   7088     // 7a. Return target.[[GetOwnProperty]](P).
   7089     return JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, desc);
   7090   }
   7091   // 8. Let trapResultObj be ? Call(trap, handler, target, P).
   7092   Handle<Object> trap_result_obj;
   7093   Handle<Object> args[] = {target, name};
   7094   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   7095       isolate, trap_result_obj,
   7096       Execution::Call(isolate, trap, handler, arraysize(args), args),
   7097       Nothing<bool>());
   7098   // 9. If Type(trapResultObj) is neither Object nor Undefined, throw a
   7099   //    TypeError exception.
   7100   if (!trap_result_obj->IsJSReceiver() &&
   7101       !trap_result_obj->IsUndefined(isolate)) {
   7102     isolate->Throw(*isolate->factory()->NewTypeError(
   7103         MessageTemplate::kProxyGetOwnPropertyDescriptorInvalid, name));
   7104     return Nothing<bool>();
   7105   }
   7106   // 10. Let targetDesc be ? target.[[GetOwnProperty]](P).
   7107   PropertyDescriptor target_desc;
   7108   Maybe<bool> found =
   7109       JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, &target_desc);
   7110   MAYBE_RETURN(found, Nothing<bool>());
   7111   // 11. If trapResultObj is undefined, then
   7112   if (trap_result_obj->IsUndefined(isolate)) {
   7113     // 11a. If targetDesc is undefined, return undefined.
   7114     if (!found.FromJust()) return Just(false);
   7115     // 11b. If targetDesc.[[Configurable]] is false, throw a TypeError
   7116     //      exception.
   7117     if (!target_desc.configurable()) {
   7118       isolate->Throw(*isolate->factory()->NewTypeError(
   7119           MessageTemplate::kProxyGetOwnPropertyDescriptorUndefined, name));
   7120       return Nothing<bool>();
   7121     }
   7122     // 11c. Let extensibleTarget be ? IsExtensible(target).
   7123     Maybe<bool> extensible_target = JSReceiver::IsExtensible(target);
   7124     MAYBE_RETURN(extensible_target, Nothing<bool>());
   7125     // 11d. (Assert)
   7126     // 11e. If extensibleTarget is false, throw a TypeError exception.
   7127     if (!extensible_target.FromJust()) {
   7128       isolate->Throw(*isolate->factory()->NewTypeError(
   7129           MessageTemplate::kProxyGetOwnPropertyDescriptorNonExtensible, name));
   7130       return Nothing<bool>();
   7131     }
   7132     // 11f. Return undefined.
   7133     return Just(false);
   7134   }
   7135   // 12. Let extensibleTarget be ? IsExtensible(target).
   7136   Maybe<bool> extensible_target = JSReceiver::IsExtensible(target);
   7137   MAYBE_RETURN(extensible_target, Nothing<bool>());
   7138   // 13. Let resultDesc be ? ToPropertyDescriptor(trapResultObj).
   7139   if (!PropertyDescriptor::ToPropertyDescriptor(isolate, trap_result_obj,
   7140                                                 desc)) {
   7141     DCHECK(isolate->has_pending_exception());
   7142     return Nothing<bool>();
   7143   }
   7144   // 14. Call CompletePropertyDescriptor(resultDesc).
   7145   PropertyDescriptor::CompletePropertyDescriptor(isolate, desc);
   7146   // 15. Let valid be IsCompatiblePropertyDescriptor (extensibleTarget,
   7147   //     resultDesc, targetDesc).
   7148   Maybe<bool> valid =
   7149       IsCompatiblePropertyDescriptor(isolate, extensible_target.FromJust(),
   7150                                      desc, &target_desc, name, DONT_THROW);
   7151   MAYBE_RETURN(valid, Nothing<bool>());
   7152   // 16. If valid is false, throw a TypeError exception.
   7153   if (!valid.FromJust()) {
   7154     isolate->Throw(*isolate->factory()->NewTypeError(
   7155         MessageTemplate::kProxyGetOwnPropertyDescriptorIncompatible, name));
   7156     return Nothing<bool>();
   7157   }
   7158   // 17. If resultDesc.[[Configurable]] is false, then
   7159   if (!desc->configurable()) {
   7160     // 17a. If targetDesc is undefined or targetDesc.[[Configurable]] is true:
   7161     if (target_desc.is_empty() || target_desc.configurable()) {
   7162       // 17a i. Throw a TypeError exception.
   7163       isolate->Throw(*isolate->factory()->NewTypeError(
   7164           MessageTemplate::kProxyGetOwnPropertyDescriptorNonConfigurable,
   7165           name));
   7166       return Nothing<bool>();
   7167     }
   7168   }
   7169   // 18. Return resultDesc.
   7170   return Just(true);
   7171 }
   7172 
   7173 
   7174 bool JSObject::ReferencesObjectFromElements(FixedArray* elements,
   7175                                             ElementsKind kind,
   7176                                             Object* object) {
   7177   Isolate* isolate = elements->GetIsolate();
   7178   if (IsFastObjectElementsKind(kind) || kind == FAST_STRING_WRAPPER_ELEMENTS) {
   7179     int length = IsJSArray()
   7180         ? Smi::cast(JSArray::cast(this)->length())->value()
   7181         : elements->length();
   7182     for (int i = 0; i < length; ++i) {
   7183       Object* element = elements->get(i);
   7184       if (!element->IsTheHole(isolate) && element == object) return true;
   7185     }
   7186   } else {
   7187     DCHECK(kind == DICTIONARY_ELEMENTS || kind == SLOW_STRING_WRAPPER_ELEMENTS);
   7188     Object* key =
   7189         SeededNumberDictionary::cast(elements)->SlowReverseLookup(object);
   7190     if (!key->IsUndefined(isolate)) return true;
   7191   }
   7192   return false;
   7193 }
   7194 
   7195 
   7196 // Check whether this object references another object.
   7197 bool JSObject::ReferencesObject(Object* obj) {
   7198   Map* map_of_this = map();
   7199   Heap* heap = GetHeap();
   7200   DisallowHeapAllocation no_allocation;
   7201 
   7202   // Is the object the constructor for this object?
   7203   if (map_of_this->GetConstructor() == obj) {
   7204     return true;
   7205   }
   7206 
   7207   // Is the object the prototype for this object?
   7208   if (map_of_this->prototype() == obj) {
   7209     return true;
   7210   }
   7211 
   7212   // Check if the object is among the named properties.
   7213   Object* key = SlowReverseLookup(obj);
   7214   if (!key->IsUndefined(heap->isolate())) {
   7215     return true;
   7216   }
   7217 
   7218   // Check if the object is among the indexed properties.
   7219   ElementsKind kind = GetElementsKind();
   7220   switch (kind) {
   7221     // Raw pixels and external arrays do not reference other
   7222     // objects.
   7223 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                        \
   7224     case TYPE##_ELEMENTS:                                                      \
   7225       break;
   7226 
   7227     TYPED_ARRAYS(TYPED_ARRAY_CASE)
   7228 #undef TYPED_ARRAY_CASE
   7229 
   7230     case FAST_DOUBLE_ELEMENTS:
   7231     case FAST_HOLEY_DOUBLE_ELEMENTS:
   7232       break;
   7233     case FAST_SMI_ELEMENTS:
   7234     case FAST_HOLEY_SMI_ELEMENTS:
   7235       break;
   7236     case FAST_ELEMENTS:
   7237     case FAST_HOLEY_ELEMENTS:
   7238     case DICTIONARY_ELEMENTS:
   7239     case FAST_STRING_WRAPPER_ELEMENTS:
   7240     case SLOW_STRING_WRAPPER_ELEMENTS: {
   7241       FixedArray* elements = FixedArray::cast(this->elements());
   7242       if (ReferencesObjectFromElements(elements, kind, obj)) return true;
   7243       break;
   7244     }
   7245     case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
   7246     case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: {
   7247       FixedArray* parameter_map = FixedArray::cast(elements());
   7248       // Check the mapped parameters.
   7249       int length = parameter_map->length();
   7250       for (int i = 2; i < length; ++i) {
   7251         Object* value = parameter_map->get(i);
   7252         if (!value->IsTheHole(heap->isolate()) && value == obj) return true;
   7253       }
   7254       // Check the arguments.
   7255       FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
   7256       kind = arguments->IsDictionary() ? DICTIONARY_ELEMENTS :
   7257           FAST_HOLEY_ELEMENTS;
   7258       if (ReferencesObjectFromElements(arguments, kind, obj)) return true;
   7259       break;
   7260     }
   7261     case NO_ELEMENTS:
   7262       break;
   7263   }
   7264 
   7265   // For functions check the context.
   7266   if (IsJSFunction()) {
   7267     // Get the constructor function for arguments array.
   7268     Map* arguments_map =
   7269         heap->isolate()->context()->native_context()->sloppy_arguments_map();
   7270     JSFunction* arguments_function =
   7271         JSFunction::cast(arguments_map->GetConstructor());
   7272 
   7273     // Get the context and don't check if it is the native context.
   7274     JSFunction* f = JSFunction::cast(this);
   7275     Context* context = f->context();
   7276     if (context->IsNativeContext()) {
   7277       return false;
   7278     }
   7279 
   7280     // Check the non-special context slots.
   7281     for (int i = Context::MIN_CONTEXT_SLOTS; i < context->length(); i++) {
   7282       // Only check JS objects.
   7283       if (context->get(i)->IsJSObject()) {
   7284         JSObject* ctxobj = JSObject::cast(context->get(i));
   7285         // If it is an arguments array check the content.
   7286         if (ctxobj->map()->GetConstructor() == arguments_function) {
   7287           if (ctxobj->ReferencesObject(obj)) {
   7288             return true;
   7289           }
   7290         } else if (ctxobj == obj) {
   7291           return true;
   7292         }
   7293       }
   7294     }
   7295 
   7296     // Check the context extension (if any) if it can have references.
   7297     if (context->has_extension() && !context->IsCatchContext()) {
   7298       // With harmony scoping, a JSFunction may have a script context.
   7299       // TODO(mvstanton): walk into the ScopeInfo.
   7300       if (context->IsScriptContext()) {
   7301         return false;
   7302       }
   7303 
   7304       return context->extension_object()->ReferencesObject(obj);
   7305     }
   7306   }
   7307 
   7308   // No references to object.
   7309   return false;
   7310 }
   7311 
   7312 
   7313 Maybe<bool> JSReceiver::SetIntegrityLevel(Handle<JSReceiver> receiver,
   7314                                           IntegrityLevel level,
   7315                                           ShouldThrow should_throw) {
   7316   DCHECK(level == SEALED || level == FROZEN);
   7317 
   7318   if (receiver->IsJSObject()) {
   7319     Handle<JSObject> object = Handle<JSObject>::cast(receiver);
   7320     if (!object->HasSloppyArgumentsElements()) {  // Fast path.
   7321       if (level == SEALED) {
   7322         return JSObject::PreventExtensionsWithTransition<SEALED>(object,
   7323                                                                  should_throw);
   7324       } else {
   7325         return JSObject::PreventExtensionsWithTransition<FROZEN>(object,
   7326                                                                  should_throw);
   7327       }
   7328     }
   7329   }
   7330 
   7331   Isolate* isolate = receiver->GetIsolate();
   7332 
   7333   MAYBE_RETURN(JSReceiver::PreventExtensions(receiver, should_throw),
   7334                Nothing<bool>());
   7335 
   7336   Handle<FixedArray> keys;
   7337   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   7338       isolate, keys, JSReceiver::OwnPropertyKeys(receiver), Nothing<bool>());
   7339 
   7340   PropertyDescriptor no_conf;
   7341   no_conf.set_configurable(false);
   7342 
   7343   PropertyDescriptor no_conf_no_write;
   7344   no_conf_no_write.set_configurable(false);
   7345   no_conf_no_write.set_writable(false);
   7346 
   7347   if (level == SEALED) {
   7348     for (int i = 0; i < keys->length(); ++i) {
   7349       Handle<Object> key(keys->get(i), isolate);
   7350       MAYBE_RETURN(
   7351           DefineOwnProperty(isolate, receiver, key, &no_conf, THROW_ON_ERROR),
   7352           Nothing<bool>());
   7353     }
   7354     return Just(true);
   7355   }
   7356 
   7357   for (int i = 0; i < keys->length(); ++i) {
   7358     Handle<Object> key(keys->get(i), isolate);
   7359     PropertyDescriptor current_desc;
   7360     Maybe<bool> owned = JSReceiver::GetOwnPropertyDescriptor(
   7361         isolate, receiver, key, &current_desc);
   7362     MAYBE_RETURN(owned, Nothing<bool>());
   7363     if (owned.FromJust()) {
   7364       PropertyDescriptor desc =
   7365           PropertyDescriptor::IsAccessorDescriptor(&current_desc)
   7366               ? no_conf
   7367               : no_conf_no_write;
   7368       MAYBE_RETURN(
   7369           DefineOwnProperty(isolate, receiver, key, &desc, THROW_ON_ERROR),
   7370           Nothing<bool>());
   7371     }
   7372   }
   7373   return Just(true);
   7374 }
   7375 
   7376 
   7377 Maybe<bool> JSReceiver::TestIntegrityLevel(Handle<JSReceiver> object,
   7378                                            IntegrityLevel level) {
   7379   DCHECK(level == SEALED || level == FROZEN);
   7380   Isolate* isolate = object->GetIsolate();
   7381 
   7382   Maybe<bool> extensible = JSReceiver::IsExtensible(object);
   7383   MAYBE_RETURN(extensible, Nothing<bool>());
   7384   if (extensible.FromJust()) return Just(false);
   7385 
   7386   Handle<FixedArray> keys;
   7387   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   7388       isolate, keys, JSReceiver::OwnPropertyKeys(object), Nothing<bool>());
   7389 
   7390   for (int i = 0; i < keys->length(); ++i) {
   7391     Handle<Object> key(keys->get(i), isolate);
   7392     PropertyDescriptor current_desc;
   7393     Maybe<bool> owned = JSReceiver::GetOwnPropertyDescriptor(
   7394         isolate, object, key, &current_desc);
   7395     MAYBE_RETURN(owned, Nothing<bool>());
   7396     if (owned.FromJust()) {
   7397       if (current_desc.configurable()) return Just(false);
   7398       if (level == FROZEN &&
   7399           PropertyDescriptor::IsDataDescriptor(&current_desc) &&
   7400           current_desc.writable()) {
   7401         return Just(false);
   7402       }
   7403     }
   7404   }
   7405   return Just(true);
   7406 }
   7407 
   7408 
   7409 Maybe<bool> JSReceiver::PreventExtensions(Handle<JSReceiver> object,
   7410                                           ShouldThrow should_throw) {
   7411   if (object->IsJSProxy()) {
   7412     return JSProxy::PreventExtensions(Handle<JSProxy>::cast(object),
   7413                                       should_throw);
   7414   }
   7415   DCHECK(object->IsJSObject());
   7416   return JSObject::PreventExtensions(Handle<JSObject>::cast(object),
   7417                                      should_throw);
   7418 }
   7419 
   7420 
   7421 Maybe<bool> JSProxy::PreventExtensions(Handle<JSProxy> proxy,
   7422                                        ShouldThrow should_throw) {
   7423   Isolate* isolate = proxy->GetIsolate();
   7424   STACK_CHECK(isolate, Nothing<bool>());
   7425   Factory* factory = isolate->factory();
   7426   Handle<String> trap_name = factory->preventExtensions_string();
   7427 
   7428   if (proxy->IsRevoked()) {
   7429     isolate->Throw(
   7430         *factory->NewTypeError(MessageTemplate::kProxyRevoked, trap_name));
   7431     return Nothing<bool>();
   7432   }
   7433   Handle<JSReceiver> target(proxy->target(), isolate);
   7434   Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate);
   7435 
   7436   Handle<Object> trap;
   7437   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   7438       isolate, trap, Object::GetMethod(handler, trap_name), Nothing<bool>());
   7439   if (trap->IsUndefined(isolate)) {
   7440     return JSReceiver::PreventExtensions(target, should_throw);
   7441   }
   7442 
   7443   Handle<Object> trap_result;
   7444   Handle<Object> args[] = {target};
   7445   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   7446       isolate, trap_result,
   7447       Execution::Call(isolate, trap, handler, arraysize(args), args),
   7448       Nothing<bool>());
   7449   if (!trap_result->BooleanValue()) {
   7450     RETURN_FAILURE(
   7451         isolate, should_throw,
   7452         NewTypeError(MessageTemplate::kProxyTrapReturnedFalsish, trap_name));
   7453   }
   7454 
   7455   // Enforce the invariant.
   7456   Maybe<bool> target_result = JSReceiver::IsExtensible(target);
   7457   MAYBE_RETURN(target_result, Nothing<bool>());
   7458   if (target_result.FromJust()) {
   7459     isolate->Throw(*factory->NewTypeError(
   7460         MessageTemplate::kProxyPreventExtensionsExtensible));
   7461     return Nothing<bool>();
   7462   }
   7463   return Just(true);
   7464 }
   7465 
   7466 
   7467 Maybe<bool> JSObject::PreventExtensions(Handle<JSObject> object,
   7468                                         ShouldThrow should_throw) {
   7469   Isolate* isolate = object->GetIsolate();
   7470 
   7471   if (!object->HasSloppyArgumentsElements()) {
   7472     return PreventExtensionsWithTransition<NONE>(object, should_throw);
   7473   }
   7474 
   7475   if (object->IsAccessCheckNeeded() &&
   7476       !isolate->MayAccess(handle(isolate->context()), object)) {
   7477     isolate->ReportFailedAccessCheck(object);
   7478     RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
   7479     RETURN_FAILURE(isolate, should_throw,
   7480                    NewTypeError(MessageTemplate::kNoAccess));
   7481   }
   7482 
   7483   if (!object->map()->is_extensible()) return Just(true);
   7484 
   7485   if (object->IsJSGlobalProxy()) {
   7486     PrototypeIterator iter(isolate, object);
   7487     if (iter.IsAtEnd()) return Just(true);
   7488     DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
   7489     return PreventExtensions(PrototypeIterator::GetCurrent<JSObject>(iter),
   7490                              should_throw);
   7491   }
   7492 
   7493   if (!object->HasFixedTypedArrayElements()) {
   7494     // If there are fast elements we normalize.
   7495     Handle<SeededNumberDictionary> dictionary = NormalizeElements(object);
   7496     DCHECK(object->HasDictionaryElements() ||
   7497            object->HasSlowArgumentsElements());
   7498 
   7499     // Make sure that we never go back to fast case.
   7500     object->RequireSlowElements(*dictionary);
   7501   }
   7502 
   7503   // Do a map transition, other objects with this map may still
   7504   // be extensible.
   7505   // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps.
   7506   Handle<Map> new_map = Map::Copy(handle(object->map()), "PreventExtensions");
   7507 
   7508   new_map->set_is_extensible(false);
   7509   JSObject::MigrateToMap(object, new_map);
   7510   DCHECK(!object->map()->is_extensible());
   7511 
   7512   return Just(true);
   7513 }
   7514 
   7515 
   7516 Maybe<bool> JSReceiver::IsExtensible(Handle<JSReceiver> object) {
   7517   if (object->IsJSProxy()) {
   7518     return JSProxy::IsExtensible(Handle<JSProxy>::cast(object));
   7519   }
   7520   return Just(JSObject::IsExtensible(Handle<JSObject>::cast(object)));
   7521 }
   7522 
   7523 
   7524 Maybe<bool> JSProxy::IsExtensible(Handle<JSProxy> proxy) {
   7525   Isolate* isolate = proxy->GetIsolate();
   7526   STACK_CHECK(isolate, Nothing<bool>());
   7527   Factory* factory = isolate->factory();
   7528   Handle<String> trap_name = factory->isExtensible_string();
   7529 
   7530   if (proxy->IsRevoked()) {
   7531     isolate->Throw(
   7532         *factory->NewTypeError(MessageTemplate::kProxyRevoked, trap_name));
   7533     return Nothing<bool>();
   7534   }
   7535   Handle<JSReceiver> target(proxy->target(), isolate);
   7536   Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate);
   7537 
   7538   Handle<Object> trap;
   7539   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   7540       isolate, trap, Object::GetMethod(handler, trap_name), Nothing<bool>());
   7541   if (trap->IsUndefined(isolate)) {
   7542     return JSReceiver::IsExtensible(target);
   7543   }
   7544 
   7545   Handle<Object> trap_result;
   7546   Handle<Object> args[] = {target};
   7547   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   7548       isolate, trap_result,
   7549       Execution::Call(isolate, trap, handler, arraysize(args), args),
   7550       Nothing<bool>());
   7551 
   7552   // Enforce the invariant.
   7553   Maybe<bool> target_result = JSReceiver::IsExtensible(target);
   7554   MAYBE_RETURN(target_result, Nothing<bool>());
   7555   if (target_result.FromJust() != trap_result->BooleanValue()) {
   7556     isolate->Throw(
   7557         *factory->NewTypeError(MessageTemplate::kProxyIsExtensibleInconsistent,
   7558                                factory->ToBoolean(target_result.FromJust())));
   7559     return Nothing<bool>();
   7560   }
   7561   return target_result;
   7562 }
   7563 
   7564 
   7565 bool JSObject::IsExtensible(Handle<JSObject> object) {
   7566   Isolate* isolate = object->GetIsolate();
   7567   if (object->IsAccessCheckNeeded() &&
   7568       !isolate->MayAccess(handle(isolate->context()), object)) {
   7569     return true;
   7570   }
   7571   if (object->IsJSGlobalProxy()) {
   7572     PrototypeIterator iter(isolate, *object);
   7573     if (iter.IsAtEnd()) return false;
   7574     DCHECK(iter.GetCurrent()->IsJSGlobalObject());
   7575     return iter.GetCurrent<JSObject>()->map()->is_extensible();
   7576   }
   7577   return object->map()->is_extensible();
   7578 }
   7579 
   7580 namespace {
   7581 
   7582 template <typename Dictionary>
   7583 void DictionaryDetailsAtPut(Isolate* isolate, Handle<Dictionary> dictionary,
   7584                             int entry, PropertyDetails details) {
   7585   dictionary->DetailsAtPut(entry, details);
   7586 }
   7587 
   7588 template <>
   7589 void DictionaryDetailsAtPut<GlobalDictionary>(
   7590     Isolate* isolate, Handle<GlobalDictionary> dictionary, int entry,
   7591     PropertyDetails details) {
   7592   Object* value = dictionary->ValueAt(entry);
   7593   DCHECK(value->IsPropertyCell());
   7594   value = PropertyCell::cast(value)->value();
   7595   if (value->IsTheHole(isolate)) return;
   7596   PropertyCell::PrepareForValue(dictionary, entry, handle(value, isolate),
   7597                                 details);
   7598 }
   7599 
   7600 template <typename Dictionary>
   7601 void ApplyAttributesToDictionary(Isolate* isolate,
   7602                                  Handle<Dictionary> dictionary,
   7603                                  const PropertyAttributes attributes) {
   7604   int capacity = dictionary->Capacity();
   7605   for (int i = 0; i < capacity; i++) {
   7606     Object* k = dictionary->KeyAt(i);
   7607     if (dictionary->IsKey(isolate, k) &&
   7608         !(k->IsSymbol() && Symbol::cast(k)->is_private())) {
   7609       PropertyDetails details = dictionary->DetailsAt(i);
   7610       int attrs = attributes;
   7611       // READ_ONLY is an invalid attribute for JS setters/getters.
   7612       if ((attributes & READ_ONLY) && details.kind() == kAccessor) {
   7613         Object* v = dictionary->ValueAt(i);
   7614         if (v->IsPropertyCell()) v = PropertyCell::cast(v)->value();
   7615         if (v->IsAccessorPair()) attrs &= ~READ_ONLY;
   7616       }
   7617       details = details.CopyAddAttributes(
   7618           static_cast<PropertyAttributes>(attrs));
   7619       DictionaryDetailsAtPut<Dictionary>(isolate, dictionary, i, details);
   7620     }
   7621   }
   7622 }
   7623 
   7624 }  // namespace
   7625 
   7626 template <PropertyAttributes attrs>
   7627 Maybe<bool> JSObject::PreventExtensionsWithTransition(
   7628     Handle<JSObject> object, ShouldThrow should_throw) {
   7629   STATIC_ASSERT(attrs == NONE || attrs == SEALED || attrs == FROZEN);
   7630 
   7631   // Sealing/freezing sloppy arguments should be handled elsewhere.
   7632   DCHECK(!object->HasSloppyArgumentsElements());
   7633 
   7634   Isolate* isolate = object->GetIsolate();
   7635   if (object->IsAccessCheckNeeded() &&
   7636       !isolate->MayAccess(handle(isolate->context()), object)) {
   7637     isolate->ReportFailedAccessCheck(object);
   7638     RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
   7639     RETURN_FAILURE(isolate, should_throw,
   7640                    NewTypeError(MessageTemplate::kNoAccess));
   7641   }
   7642 
   7643   if (attrs == NONE && !object->map()->is_extensible()) return Just(true);
   7644 
   7645   if (object->IsJSGlobalProxy()) {
   7646     PrototypeIterator iter(isolate, object);
   7647     if (iter.IsAtEnd()) return Just(true);
   7648     DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
   7649     return PreventExtensionsWithTransition<attrs>(
   7650         PrototypeIterator::GetCurrent<JSObject>(iter), should_throw);
   7651   }
   7652 
   7653   Handle<SeededNumberDictionary> new_element_dictionary;
   7654   if (!object->HasFixedTypedArrayElements() &&
   7655       !object->HasDictionaryElements() &&
   7656       !object->HasSlowStringWrapperElements()) {
   7657     int length =
   7658         object->IsJSArray()
   7659             ? Smi::cast(Handle<JSArray>::cast(object)->length())->value()
   7660             : object->elements()->length();
   7661     new_element_dictionary =
   7662         length == 0 ? isolate->factory()->empty_slow_element_dictionary()
   7663                     : object->GetElementsAccessor()->Normalize(object);
   7664   }
   7665 
   7666   Handle<Symbol> transition_marker;
   7667   if (attrs == NONE) {
   7668     transition_marker = isolate->factory()->nonextensible_symbol();
   7669   } else if (attrs == SEALED) {
   7670     transition_marker = isolate->factory()->sealed_symbol();
   7671   } else {
   7672     DCHECK(attrs == FROZEN);
   7673     transition_marker = isolate->factory()->frozen_symbol();
   7674   }
   7675 
   7676   Handle<Map> old_map(object->map(), isolate);
   7677   Map* transition =
   7678       TransitionArray::SearchSpecial(*old_map, *transition_marker);
   7679   if (transition != NULL) {
   7680     Handle<Map> transition_map(transition, isolate);
   7681     DCHECK(transition_map->has_dictionary_elements() ||
   7682            transition_map->has_fixed_typed_array_elements() ||
   7683            transition_map->elements_kind() == SLOW_STRING_WRAPPER_ELEMENTS);
   7684     DCHECK(!transition_map->is_extensible());
   7685     JSObject::MigrateToMap(object, transition_map);
   7686   } else if (TransitionArray::CanHaveMoreTransitions(old_map)) {
   7687     // Create a new descriptor array with the appropriate property attributes
   7688     Handle<Map> new_map = Map::CopyForPreventExtensions(
   7689         old_map, attrs, transition_marker, "CopyForPreventExtensions");
   7690     JSObject::MigrateToMap(object, new_map);
   7691   } else {
   7692     DCHECK(old_map->is_dictionary_map() || !old_map->is_prototype_map());
   7693     // Slow path: need to normalize properties for safety
   7694     NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0,
   7695                         "SlowPreventExtensions");
   7696 
   7697     // Create a new map, since other objects with this map may be extensible.
   7698     // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps.
   7699     Handle<Map> new_map =
   7700         Map::Copy(handle(object->map()), "SlowCopyForPreventExtensions");
   7701     new_map->set_is_extensible(false);
   7702     if (!new_element_dictionary.is_null()) {
   7703       ElementsKind new_kind =
   7704           IsStringWrapperElementsKind(old_map->elements_kind())
   7705               ? SLOW_STRING_WRAPPER_ELEMENTS
   7706               : DICTIONARY_ELEMENTS;
   7707       new_map->set_elements_kind(new_kind);
   7708     }
   7709     JSObject::MigrateToMap(object, new_map);
   7710 
   7711     if (attrs != NONE) {
   7712       if (object->IsJSGlobalObject()) {
   7713         Handle<GlobalDictionary> dictionary(object->global_dictionary(),
   7714                                             isolate);
   7715         ApplyAttributesToDictionary(isolate, dictionary, attrs);
   7716       } else {
   7717         Handle<NameDictionary> dictionary(object->property_dictionary(),
   7718                                           isolate);
   7719         ApplyAttributesToDictionary(isolate, dictionary, attrs);
   7720       }
   7721     }
   7722   }
   7723 
   7724   // Both seal and preventExtensions always go through without modifications to
   7725   // typed array elements. Freeze works only if there are no actual elements.
   7726   if (object->HasFixedTypedArrayElements()) {
   7727     if (attrs == FROZEN &&
   7728         JSArrayBufferView::cast(*object)->byte_length()->Number() > 0) {
   7729       isolate->Throw(*isolate->factory()->NewTypeError(
   7730           MessageTemplate::kCannotFreezeArrayBufferView));
   7731       return Nothing<bool>();
   7732     }
   7733     return Just(true);
   7734   }
   7735 
   7736   DCHECK(object->map()->has_dictionary_elements() ||
   7737          object->map()->elements_kind() == SLOW_STRING_WRAPPER_ELEMENTS);
   7738   if (!new_element_dictionary.is_null()) {
   7739     object->set_elements(*new_element_dictionary);
   7740   }
   7741 
   7742   if (object->elements() != isolate->heap()->empty_slow_element_dictionary()) {
   7743     Handle<SeededNumberDictionary> dictionary(object->element_dictionary(),
   7744                                               isolate);
   7745     // Make sure we never go back to the fast case
   7746     object->RequireSlowElements(*dictionary);
   7747     if (attrs != NONE) {
   7748       ApplyAttributesToDictionary(isolate, dictionary, attrs);
   7749     }
   7750   }
   7751 
   7752   return Just(true);
   7753 }
   7754 
   7755 
   7756 Handle<Object> JSObject::FastPropertyAt(Handle<JSObject> object,
   7757                                         Representation representation,
   7758                                         FieldIndex index) {
   7759   Isolate* isolate = object->GetIsolate();
   7760   if (object->IsUnboxedDoubleField(index)) {
   7761     double value = object->RawFastDoublePropertyAt(index);
   7762     return isolate->factory()->NewHeapNumber(value);
   7763   }
   7764   Handle<Object> raw_value(object->RawFastPropertyAt(index), isolate);
   7765   return Object::WrapForRead(isolate, raw_value, representation);
   7766 }
   7767 
   7768 template <class ContextObject>
   7769 class JSObjectWalkVisitor {
   7770  public:
   7771   JSObjectWalkVisitor(ContextObject* site_context, bool copying,
   7772                       JSObject::DeepCopyHints hints)
   7773     : site_context_(site_context),
   7774       copying_(copying),
   7775       hints_(hints) {}
   7776 
   7777   MUST_USE_RESULT MaybeHandle<JSObject> StructureWalk(Handle<JSObject> object);
   7778 
   7779  protected:
   7780   MUST_USE_RESULT inline MaybeHandle<JSObject> VisitElementOrProperty(
   7781       Handle<JSObject> object,
   7782       Handle<JSObject> value) {
   7783     Handle<AllocationSite> current_site = site_context()->EnterNewScope();
   7784     MaybeHandle<JSObject> copy_of_value = StructureWalk(value);
   7785     site_context()->ExitScope(current_site, value);
   7786     return copy_of_value;
   7787   }
   7788 
   7789   inline ContextObject* site_context() { return site_context_; }
   7790   inline Isolate* isolate() { return site_context()->isolate(); }
   7791 
   7792   inline bool copying() const { return copying_; }
   7793 
   7794  private:
   7795   ContextObject* site_context_;
   7796   const bool copying_;
   7797   const JSObject::DeepCopyHints hints_;
   7798 };
   7799 
   7800 template <class ContextObject>
   7801 MaybeHandle<JSObject> JSObjectWalkVisitor<ContextObject>::StructureWalk(
   7802     Handle<JSObject> object) {
   7803   Isolate* isolate = this->isolate();
   7804   bool copying = this->copying();
   7805   bool shallow = hints_ == JSObject::kObjectIsShallow;
   7806 
   7807   if (!shallow) {
   7808     StackLimitCheck check(isolate);
   7809 
   7810     if (check.HasOverflowed()) {
   7811       isolate->StackOverflow();
   7812       return MaybeHandle<JSObject>();
   7813     }
   7814   }
   7815 
   7816   if (object->map()->is_deprecated()) {
   7817     JSObject::MigrateInstance(object);
   7818   }
   7819 
   7820   Handle<JSObject> copy;
   7821   if (copying) {
   7822     // JSFunction objects are not allowed to be in normal boilerplates at all.
   7823     DCHECK(!object->IsJSFunction());
   7824     Handle<AllocationSite> site_to_pass;
   7825     if (site_context()->ShouldCreateMemento(object)) {
   7826       site_to_pass = site_context()->current();
   7827     }
   7828     copy = isolate->factory()->CopyJSObjectWithAllocationSite(
   7829         object, site_to_pass);
   7830   } else {
   7831     copy = object;
   7832   }
   7833 
   7834   DCHECK(copying || copy.is_identical_to(object));
   7835 
   7836   ElementsKind kind = copy->GetElementsKind();
   7837   if (copying && IsFastSmiOrObjectElementsKind(kind) &&
   7838       FixedArray::cast(copy->elements())->map() ==
   7839         isolate->heap()->fixed_cow_array_map()) {
   7840     isolate->counters()->cow_arrays_created_runtime()->Increment();
   7841   }
   7842 
   7843   if (!shallow) {
   7844     HandleScope scope(isolate);
   7845 
   7846     // Deep copy own properties.
   7847     if (copy->HasFastProperties()) {
   7848       Handle<DescriptorArray> descriptors(copy->map()->instance_descriptors());
   7849       int limit = copy->map()->NumberOfOwnDescriptors();
   7850       for (int i = 0; i < limit; i++) {
   7851         PropertyDetails details = descriptors->GetDetails(i);
   7852         if (details.location() != kField) continue;
   7853         DCHECK_EQ(kData, details.kind());
   7854         FieldIndex index = FieldIndex::ForDescriptor(copy->map(), i);
   7855         if (object->IsUnboxedDoubleField(index)) {
   7856           if (copying) {
   7857             // Ensure that all bits of the double value are preserved.
   7858             uint64_t value = object->RawFastDoublePropertyAsBitsAt(index);
   7859             copy->RawFastDoublePropertyAsBitsAtPut(index, value);
   7860           }
   7861         } else {
   7862           Handle<Object> value(object->RawFastPropertyAt(index), isolate);
   7863           if (value->IsJSObject()) {
   7864             ASSIGN_RETURN_ON_EXCEPTION(
   7865                 isolate, value,
   7866                 VisitElementOrProperty(copy, Handle<JSObject>::cast(value)),
   7867                 JSObject);
   7868             if (copying) {
   7869               copy->FastPropertyAtPut(index, *value);
   7870             }
   7871           } else {
   7872             if (copying) {
   7873               Representation representation = details.representation();
   7874               value = Object::NewStorageFor(isolate, value, representation);
   7875               copy->FastPropertyAtPut(index, *value);
   7876             }
   7877           }
   7878         }
   7879       }
   7880     } else {
   7881       // Only deep copy fields from the object literal expression.
   7882       // In particular, don't try to copy the length attribute of
   7883       // an array.
   7884       PropertyFilter filter = static_cast<PropertyFilter>(
   7885           ONLY_WRITABLE | ONLY_ENUMERABLE | ONLY_CONFIGURABLE);
   7886       KeyAccumulator accumulator(isolate, KeyCollectionMode::kOwnOnly, filter);
   7887       accumulator.CollectOwnPropertyNames(copy, copy);
   7888       Handle<FixedArray> names = accumulator.GetKeys();
   7889       for (int i = 0; i < names->length(); i++) {
   7890         DCHECK(names->get(i)->IsName());
   7891         Handle<Name> name(Name::cast(names->get(i)));
   7892         Handle<Object> value =
   7893             JSObject::GetProperty(copy, name).ToHandleChecked();
   7894         if (value->IsJSObject()) {
   7895           Handle<JSObject> result;
   7896           ASSIGN_RETURN_ON_EXCEPTION(
   7897               isolate, result,
   7898               VisitElementOrProperty(copy, Handle<JSObject>::cast(value)),
   7899               JSObject);
   7900           if (copying) {
   7901             // Creating object copy for literals. No strict mode needed.
   7902             JSObject::SetProperty(copy, name, result, SLOPPY).Assert();
   7903           }
   7904         }
   7905       }
   7906     }
   7907 
   7908     // Deep copy own elements.
   7909     switch (kind) {
   7910       case FAST_ELEMENTS:
   7911       case FAST_HOLEY_ELEMENTS: {
   7912         Handle<FixedArray> elements(FixedArray::cast(copy->elements()));
   7913         if (elements->map() == isolate->heap()->fixed_cow_array_map()) {
   7914 #ifdef DEBUG
   7915           for (int i = 0; i < elements->length(); i++) {
   7916             DCHECK(!elements->get(i)->IsJSObject());
   7917           }
   7918 #endif
   7919         } else {
   7920           for (int i = 0; i < elements->length(); i++) {
   7921             Handle<Object> value(elements->get(i), isolate);
   7922             if (value->IsJSObject()) {
   7923               Handle<JSObject> result;
   7924               ASSIGN_RETURN_ON_EXCEPTION(
   7925                   isolate, result,
   7926                   VisitElementOrProperty(copy, Handle<JSObject>::cast(value)),
   7927                   JSObject);
   7928               if (copying) {
   7929                 elements->set(i, *result);
   7930               }
   7931             }
   7932           }
   7933         }
   7934         break;
   7935       }
   7936       case DICTIONARY_ELEMENTS: {
   7937         Handle<SeededNumberDictionary> element_dictionary(
   7938             copy->element_dictionary());
   7939         int capacity = element_dictionary->Capacity();
   7940         for (int i = 0; i < capacity; i++) {
   7941           Object* k = element_dictionary->KeyAt(i);
   7942           if (element_dictionary->IsKey(isolate, k)) {
   7943             Handle<Object> value(element_dictionary->ValueAt(i), isolate);
   7944             if (value->IsJSObject()) {
   7945               Handle<JSObject> result;
   7946               ASSIGN_RETURN_ON_EXCEPTION(
   7947                   isolate, result,
   7948                   VisitElementOrProperty(copy, Handle<JSObject>::cast(value)),
   7949                   JSObject);
   7950               if (copying) {
   7951                 element_dictionary->ValueAtPut(i, *result);
   7952               }
   7953             }
   7954           }
   7955         }
   7956         break;
   7957       }
   7958       case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
   7959       case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
   7960         UNIMPLEMENTED();
   7961         break;
   7962       case FAST_STRING_WRAPPER_ELEMENTS:
   7963       case SLOW_STRING_WRAPPER_ELEMENTS:
   7964         UNREACHABLE();
   7965         break;
   7966 
   7967 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                        \
   7968       case TYPE##_ELEMENTS:                                                    \
   7969 
   7970       TYPED_ARRAYS(TYPED_ARRAY_CASE)
   7971 #undef TYPED_ARRAY_CASE
   7972       // Typed elements cannot be created using an object literal.
   7973       UNREACHABLE();
   7974       break;
   7975 
   7976       case FAST_SMI_ELEMENTS:
   7977       case FAST_HOLEY_SMI_ELEMENTS:
   7978       case FAST_DOUBLE_ELEMENTS:
   7979       case FAST_HOLEY_DOUBLE_ELEMENTS:
   7980       case NO_ELEMENTS:
   7981         // No contained objects, nothing to do.
   7982         break;
   7983     }
   7984   }
   7985 
   7986   return copy;
   7987 }
   7988 
   7989 
   7990 MaybeHandle<JSObject> JSObject::DeepWalk(
   7991     Handle<JSObject> object,
   7992     AllocationSiteCreationContext* site_context) {
   7993   JSObjectWalkVisitor<AllocationSiteCreationContext> v(site_context, false,
   7994                                                        kNoHints);
   7995   MaybeHandle<JSObject> result = v.StructureWalk(object);
   7996   Handle<JSObject> for_assert;
   7997   DCHECK(!result.ToHandle(&for_assert) || for_assert.is_identical_to(object));
   7998   return result;
   7999 }
   8000 
   8001 
   8002 MaybeHandle<JSObject> JSObject::DeepCopy(
   8003     Handle<JSObject> object,
   8004     AllocationSiteUsageContext* site_context,
   8005     DeepCopyHints hints) {
   8006   JSObjectWalkVisitor<AllocationSiteUsageContext> v(site_context, true, hints);
   8007   MaybeHandle<JSObject> copy = v.StructureWalk(object);
   8008   Handle<JSObject> for_assert;
   8009   DCHECK(!copy.ToHandle(&for_assert) || !for_assert.is_identical_to(object));
   8010   return copy;
   8011 }
   8012 
   8013 // static
   8014 MaybeHandle<Object> JSReceiver::ToPrimitive(Handle<JSReceiver> receiver,
   8015                                             ToPrimitiveHint hint) {
   8016   Isolate* const isolate = receiver->GetIsolate();
   8017   Handle<Object> exotic_to_prim;
   8018   ASSIGN_RETURN_ON_EXCEPTION(
   8019       isolate, exotic_to_prim,
   8020       GetMethod(receiver, isolate->factory()->to_primitive_symbol()), Object);
   8021   if (!exotic_to_prim->IsUndefined(isolate)) {
   8022     Handle<Object> hint_string =
   8023         isolate->factory()->ToPrimitiveHintString(hint);
   8024     Handle<Object> result;
   8025     ASSIGN_RETURN_ON_EXCEPTION(
   8026         isolate, result,
   8027         Execution::Call(isolate, exotic_to_prim, receiver, 1, &hint_string),
   8028         Object);
   8029     if (result->IsPrimitive()) return result;
   8030     THROW_NEW_ERROR(isolate,
   8031                     NewTypeError(MessageTemplate::kCannotConvertToPrimitive),
   8032                     Object);
   8033   }
   8034   return OrdinaryToPrimitive(receiver, (hint == ToPrimitiveHint::kString)
   8035                                            ? OrdinaryToPrimitiveHint::kString
   8036                                            : OrdinaryToPrimitiveHint::kNumber);
   8037 }
   8038 
   8039 
   8040 // static
   8041 MaybeHandle<Object> JSReceiver::OrdinaryToPrimitive(
   8042     Handle<JSReceiver> receiver, OrdinaryToPrimitiveHint hint) {
   8043   Isolate* const isolate = receiver->GetIsolate();
   8044   Handle<String> method_names[2];
   8045   switch (hint) {
   8046     case OrdinaryToPrimitiveHint::kNumber:
   8047       method_names[0] = isolate->factory()->valueOf_string();
   8048       method_names[1] = isolate->factory()->toString_string();
   8049       break;
   8050     case OrdinaryToPrimitiveHint::kString:
   8051       method_names[0] = isolate->factory()->toString_string();
   8052       method_names[1] = isolate->factory()->valueOf_string();
   8053       break;
   8054   }
   8055   for (Handle<String> name : method_names) {
   8056     Handle<Object> method;
   8057     ASSIGN_RETURN_ON_EXCEPTION(isolate, method,
   8058                                JSReceiver::GetProperty(receiver, name), Object);
   8059     if (method->IsCallable()) {
   8060       Handle<Object> result;
   8061       ASSIGN_RETURN_ON_EXCEPTION(
   8062           isolate, result, Execution::Call(isolate, method, receiver, 0, NULL),
   8063           Object);
   8064       if (result->IsPrimitive()) return result;
   8065     }
   8066   }
   8067   THROW_NEW_ERROR(isolate,
   8068                   NewTypeError(MessageTemplate::kCannotConvertToPrimitive),
   8069                   Object);
   8070 }
   8071 
   8072 
   8073 // TODO(cbruni/jkummerow): Consider moving this into elements.cc.
   8074 bool JSObject::HasEnumerableElements() {
   8075   // TODO(cbruni): cleanup
   8076   JSObject* object = this;
   8077   switch (object->GetElementsKind()) {
   8078     case FAST_SMI_ELEMENTS:
   8079     case FAST_ELEMENTS:
   8080     case FAST_DOUBLE_ELEMENTS: {
   8081       int length = object->IsJSArray()
   8082                        ? Smi::cast(JSArray::cast(object)->length())->value()
   8083                        : object->elements()->length();
   8084       return length > 0;
   8085     }
   8086     case FAST_HOLEY_SMI_ELEMENTS:
   8087     case FAST_HOLEY_ELEMENTS: {
   8088       FixedArray* elements = FixedArray::cast(object->elements());
   8089       int length = object->IsJSArray()
   8090                        ? Smi::cast(JSArray::cast(object)->length())->value()
   8091                        : elements->length();
   8092       Isolate* isolate = GetIsolate();
   8093       for (int i = 0; i < length; i++) {
   8094         if (!elements->is_the_hole(isolate, i)) return true;
   8095       }
   8096       return false;
   8097     }
   8098     case FAST_HOLEY_DOUBLE_ELEMENTS: {
   8099       int length = object->IsJSArray()
   8100                        ? Smi::cast(JSArray::cast(object)->length())->value()
   8101                        : object->elements()->length();
   8102       // Zero-length arrays would use the empty FixedArray...
   8103       if (length == 0) return false;
   8104       // ...so only cast to FixedDoubleArray otherwise.
   8105       FixedDoubleArray* elements = FixedDoubleArray::cast(object->elements());
   8106       for (int i = 0; i < length; i++) {
   8107         if (!elements->is_the_hole(i)) return true;
   8108       }
   8109       return false;
   8110     }
   8111 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
   8112     case TYPE##_ELEMENTS:
   8113 
   8114       TYPED_ARRAYS(TYPED_ARRAY_CASE)
   8115 #undef TYPED_ARRAY_CASE
   8116       {
   8117         int length = object->elements()->length();
   8118         return length > 0;
   8119       }
   8120     case DICTIONARY_ELEMENTS: {
   8121       SeededNumberDictionary* elements =
   8122           SeededNumberDictionary::cast(object->elements());
   8123       return elements->NumberOfElementsFilterAttributes(ONLY_ENUMERABLE) > 0;
   8124     }
   8125     case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
   8126     case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
   8127       // We're approximating non-empty arguments objects here.
   8128       return true;
   8129     case FAST_STRING_WRAPPER_ELEMENTS:
   8130     case SLOW_STRING_WRAPPER_ELEMENTS:
   8131       if (String::cast(JSValue::cast(object)->value())->length() > 0) {
   8132         return true;
   8133       }
   8134       return object->elements()->length() > 0;
   8135     case NO_ELEMENTS:
   8136       return false;
   8137   }
   8138   UNREACHABLE();
   8139   return true;
   8140 }
   8141 
   8142 
   8143 int Map::NumberOfDescribedProperties(DescriptorFlag which,
   8144                                      PropertyFilter filter) {
   8145   int result = 0;
   8146   DescriptorArray* descs = instance_descriptors();
   8147   int limit = which == ALL_DESCRIPTORS
   8148       ? descs->number_of_descriptors()
   8149       : NumberOfOwnDescriptors();
   8150   for (int i = 0; i < limit; i++) {
   8151     if ((descs->GetDetails(i).attributes() & filter) == 0 &&
   8152         !descs->GetKey(i)->FilterKey(filter)) {
   8153       result++;
   8154     }
   8155   }
   8156   return result;
   8157 }
   8158 
   8159 
   8160 int Map::NextFreePropertyIndex() {
   8161   int free_index = 0;
   8162   int number_of_own_descriptors = NumberOfOwnDescriptors();
   8163   DescriptorArray* descs = instance_descriptors();
   8164   for (int i = 0; i < number_of_own_descriptors; i++) {
   8165     PropertyDetails details = descs->GetDetails(i);
   8166     if (details.location() == kField) {
   8167       int candidate = details.field_index() + details.field_width_in_words();
   8168       if (candidate > free_index) free_index = candidate;
   8169     }
   8170   }
   8171   return free_index;
   8172 }
   8173 
   8174 
   8175 bool Map::OnlyHasSimpleProperties() {
   8176   // Wrapped string elements aren't explicitly stored in the elements backing
   8177   // store, but are loaded indirectly from the underlying string.
   8178   return !IsStringWrapperElementsKind(elements_kind()) &&
   8179          !IsSpecialReceiverMap() && !has_hidden_prototype() &&
   8180          !is_dictionary_map();
   8181 }
   8182 
   8183 MUST_USE_RESULT Maybe<bool> FastGetOwnValuesOrEntries(
   8184     Isolate* isolate, Handle<JSReceiver> receiver, bool get_entries,
   8185     Handle<FixedArray>* result) {
   8186   Handle<Map> map(JSReceiver::cast(*receiver)->map(), isolate);
   8187 
   8188   if (!map->IsJSObjectMap()) return Just(false);
   8189   if (!map->OnlyHasSimpleProperties()) return Just(false);
   8190 
   8191   Handle<JSObject> object(JSObject::cast(*receiver));
   8192 
   8193   Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate);
   8194   int number_of_own_descriptors = map->NumberOfOwnDescriptors();
   8195   int number_of_own_elements =
   8196       object->GetElementsAccessor()->GetCapacity(*object, object->elements());
   8197   Handle<FixedArray> values_or_entries = isolate->factory()->NewFixedArray(
   8198       number_of_own_descriptors + number_of_own_elements);
   8199   int count = 0;
   8200 
   8201   if (object->elements() != isolate->heap()->empty_fixed_array()) {
   8202     MAYBE_RETURN(object->GetElementsAccessor()->CollectValuesOrEntries(
   8203                      isolate, object, values_or_entries, get_entries, &count,
   8204                      ENUMERABLE_STRINGS),
   8205                  Nothing<bool>());
   8206   }
   8207 
   8208   bool stable = object->map() == *map;
   8209 
   8210   for (int index = 0; index < number_of_own_descriptors; index++) {
   8211     Handle<Name> next_key(descriptors->GetKey(index), isolate);
   8212     if (!next_key->IsString()) continue;
   8213     Handle<Object> prop_value;
   8214 
   8215     // Directly decode from the descriptor array if |from| did not change shape.
   8216     if (stable) {
   8217       PropertyDetails details = descriptors->GetDetails(index);
   8218       if (!details.IsEnumerable()) continue;
   8219       if (details.kind() == kData) {
   8220         if (details.location() == kDescriptor) {
   8221           prop_value = handle(descriptors->GetValue(index), isolate);
   8222         } else {
   8223           Representation representation = details.representation();
   8224           FieldIndex field_index = FieldIndex::ForDescriptor(*map, index);
   8225           prop_value =
   8226               JSObject::FastPropertyAt(object, representation, field_index);
   8227         }
   8228       } else {
   8229         ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   8230             isolate, prop_value, JSReceiver::GetProperty(object, next_key),
   8231             Nothing<bool>());
   8232         stable = object->map() == *map;
   8233       }
   8234     } else {
   8235       // If the map did change, do a slower lookup. We are still guaranteed that
   8236       // the object has a simple shape, and that the key is a name.
   8237       LookupIterator it(object, next_key, LookupIterator::OWN_SKIP_INTERCEPTOR);
   8238       if (!it.IsFound()) continue;
   8239       DCHECK(it.state() == LookupIterator::DATA ||
   8240              it.state() == LookupIterator::ACCESSOR);
   8241       if (!it.IsEnumerable()) continue;
   8242       ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   8243           isolate, prop_value, Object::GetProperty(&it), Nothing<bool>());
   8244     }
   8245 
   8246     if (get_entries) {
   8247       prop_value = MakeEntryPair(isolate, next_key, prop_value);
   8248     }
   8249 
   8250     values_or_entries->set(count, *prop_value);
   8251     count++;
   8252   }
   8253 
   8254   if (count < values_or_entries->length()) values_or_entries->Shrink(count);
   8255   *result = values_or_entries;
   8256   return Just(true);
   8257 }
   8258 
   8259 MaybeHandle<FixedArray> GetOwnValuesOrEntries(Isolate* isolate,
   8260                                               Handle<JSReceiver> object,
   8261                                               PropertyFilter filter,
   8262                                               bool get_entries) {
   8263   Handle<FixedArray> values_or_entries;
   8264   if (filter == ENUMERABLE_STRINGS) {
   8265     Maybe<bool> fast_values_or_entries = FastGetOwnValuesOrEntries(
   8266         isolate, object, get_entries, &values_or_entries);
   8267     if (fast_values_or_entries.IsNothing()) return MaybeHandle<FixedArray>();
   8268     if (fast_values_or_entries.FromJust()) return values_or_entries;
   8269   }
   8270 
   8271   PropertyFilter key_filter =
   8272       static_cast<PropertyFilter>(filter & ~ONLY_ENUMERABLE);
   8273 
   8274   Handle<FixedArray> keys;
   8275   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   8276       isolate, keys,
   8277       KeyAccumulator::GetKeys(object, KeyCollectionMode::kOwnOnly, key_filter,
   8278                               GetKeysConversion::kConvertToString),
   8279       MaybeHandle<FixedArray>());
   8280 
   8281   values_or_entries = isolate->factory()->NewFixedArray(keys->length());
   8282   int length = 0;
   8283 
   8284   for (int i = 0; i < keys->length(); ++i) {
   8285     Handle<Name> key = Handle<Name>::cast(handle(keys->get(i), isolate));
   8286 
   8287     if (filter & ONLY_ENUMERABLE) {
   8288       PropertyDescriptor descriptor;
   8289       Maybe<bool> did_get_descriptor = JSReceiver::GetOwnPropertyDescriptor(
   8290           isolate, object, key, &descriptor);
   8291       MAYBE_RETURN(did_get_descriptor, MaybeHandle<FixedArray>());
   8292       if (!did_get_descriptor.FromJust() || !descriptor.enumerable()) continue;
   8293     }
   8294 
   8295     Handle<Object> value;
   8296     ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   8297         isolate, value, JSReceiver::GetPropertyOrElement(object, key),
   8298         MaybeHandle<FixedArray>());
   8299 
   8300     if (get_entries) {
   8301       Handle<FixedArray> entry_storage =
   8302           isolate->factory()->NewUninitializedFixedArray(2);
   8303       entry_storage->set(0, *key);
   8304       entry_storage->set(1, *value);
   8305       value = isolate->factory()->NewJSArrayWithElements(entry_storage,
   8306                                                          FAST_ELEMENTS, 2);
   8307     }
   8308 
   8309     values_or_entries->set(length, *value);
   8310     length++;
   8311   }
   8312   if (length < values_or_entries->length()) values_or_entries->Shrink(length);
   8313   return values_or_entries;
   8314 }
   8315 
   8316 MaybeHandle<FixedArray> JSReceiver::GetOwnValues(Handle<JSReceiver> object,
   8317                                                  PropertyFilter filter) {
   8318   return GetOwnValuesOrEntries(object->GetIsolate(), object, filter, false);
   8319 }
   8320 
   8321 MaybeHandle<FixedArray> JSReceiver::GetOwnEntries(Handle<JSReceiver> object,
   8322                                                   PropertyFilter filter) {
   8323   return GetOwnValuesOrEntries(object->GetIsolate(), object, filter, true);
   8324 }
   8325 
   8326 bool Map::DictionaryElementsInPrototypeChainOnly() {
   8327   if (IsDictionaryElementsKind(elements_kind())) {
   8328     return false;
   8329   }
   8330 
   8331   for (PrototypeIterator iter(this); !iter.IsAtEnd(); iter.Advance()) {
   8332     // Be conservative, don't walk into proxies.
   8333     if (iter.GetCurrent()->IsJSProxy()) return true;
   8334     // String wrappers have non-configurable, non-writable elements.
   8335     if (iter.GetCurrent()->IsStringWrapper()) return true;
   8336     JSObject* current = iter.GetCurrent<JSObject>();
   8337 
   8338     if (current->HasDictionaryElements() &&
   8339         current->element_dictionary()->requires_slow_elements()) {
   8340       return true;
   8341     }
   8342 
   8343     if (current->HasSlowArgumentsElements()) {
   8344       FixedArray* parameter_map = FixedArray::cast(current->elements());
   8345       Object* arguments = parameter_map->get(1);
   8346       if (SeededNumberDictionary::cast(arguments)->requires_slow_elements()) {
   8347         return true;
   8348       }
   8349     }
   8350   }
   8351 
   8352   return false;
   8353 }
   8354 
   8355 
   8356 MaybeHandle<Object> JSObject::DefineAccessor(Handle<JSObject> object,
   8357                                              Handle<Name> name,
   8358                                              Handle<Object> getter,
   8359                                              Handle<Object> setter,
   8360                                              PropertyAttributes attributes) {
   8361   Isolate* isolate = object->GetIsolate();
   8362 
   8363   LookupIterator it = LookupIterator::PropertyOrElement(
   8364       isolate, object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
   8365   return DefineAccessor(&it, getter, setter, attributes);
   8366 }
   8367 
   8368 
   8369 MaybeHandle<Object> JSObject::DefineAccessor(LookupIterator* it,
   8370                                              Handle<Object> getter,
   8371                                              Handle<Object> setter,
   8372                                              PropertyAttributes attributes) {
   8373   Isolate* isolate = it->isolate();
   8374 
   8375   it->UpdateProtector();
   8376 
   8377   if (it->state() == LookupIterator::ACCESS_CHECK) {
   8378     if (!it->HasAccess()) {
   8379       isolate->ReportFailedAccessCheck(it->GetHolder<JSObject>());
   8380       RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
   8381       return isolate->factory()->undefined_value();
   8382     }
   8383     it->Next();
   8384   }
   8385 
   8386   Handle<JSObject> object = Handle<JSObject>::cast(it->GetReceiver());
   8387   // Ignore accessors on typed arrays.
   8388   if (it->IsElement() && object->HasFixedTypedArrayElements()) {
   8389     return it->factory()->undefined_value();
   8390   }
   8391 
   8392   DCHECK(getter->IsCallable() || getter->IsUndefined(isolate) ||
   8393          getter->IsNull(isolate) || getter->IsFunctionTemplateInfo());
   8394   DCHECK(setter->IsCallable() || setter->IsUndefined(isolate) ||
   8395          setter->IsNull(isolate) || setter->IsFunctionTemplateInfo());
   8396   it->TransitionToAccessorProperty(getter, setter, attributes);
   8397 
   8398   return isolate->factory()->undefined_value();
   8399 }
   8400 
   8401 
   8402 MaybeHandle<Object> JSObject::SetAccessor(Handle<JSObject> object,
   8403                                           Handle<AccessorInfo> info) {
   8404   Isolate* isolate = object->GetIsolate();
   8405   Handle<Name> name(Name::cast(info->name()), isolate);
   8406 
   8407   LookupIterator it = LookupIterator::PropertyOrElement(
   8408       isolate, object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
   8409 
   8410   // Duplicate ACCESS_CHECK outside of GetPropertyAttributes for the case that
   8411   // the FailedAccessCheckCallbackFunction doesn't throw an exception.
   8412   //
   8413   // TODO(verwaest): Force throw an exception if the callback doesn't, so we can
   8414   // remove reliance on default return values.
   8415   if (it.state() == LookupIterator::ACCESS_CHECK) {
   8416     if (!it.HasAccess()) {
   8417       isolate->ReportFailedAccessCheck(object);
   8418       RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
   8419       return it.factory()->undefined_value();
   8420     }
   8421     it.Next();
   8422   }
   8423 
   8424   // Ignore accessors on typed arrays.
   8425   if (it.IsElement() && object->HasFixedTypedArrayElements()) {
   8426     return it.factory()->undefined_value();
   8427   }
   8428 
   8429   CHECK(GetPropertyAttributes(&it).IsJust());
   8430 
   8431   // ES5 forbids turning a property into an accessor if it's not
   8432   // configurable. See 8.6.1 (Table 5).
   8433   if (it.IsFound() && !it.IsConfigurable()) {
   8434     return it.factory()->undefined_value();
   8435   }
   8436 
   8437   it.TransitionToAccessorPair(info, info->property_attributes());
   8438 
   8439   return object;
   8440 }
   8441 
   8442 Object* JSObject::SlowReverseLookup(Object* value) {
   8443   if (HasFastProperties()) {
   8444     int number_of_own_descriptors = map()->NumberOfOwnDescriptors();
   8445     DescriptorArray* descs = map()->instance_descriptors();
   8446     bool value_is_number = value->IsNumber();
   8447     for (int i = 0; i < number_of_own_descriptors; i++) {
   8448       PropertyDetails details = descs->GetDetails(i);
   8449       if (details.location() == kField) {
   8450         DCHECK_EQ(kData, details.kind());
   8451         FieldIndex field_index = FieldIndex::ForDescriptor(map(), i);
   8452         if (IsUnboxedDoubleField(field_index)) {
   8453           if (value_is_number) {
   8454             double property = RawFastDoublePropertyAt(field_index);
   8455             if (property == value->Number()) {
   8456               return descs->GetKey(i);
   8457             }
   8458           }
   8459         } else {
   8460           Object* property = RawFastPropertyAt(field_index);
   8461           if (field_index.is_double()) {
   8462             DCHECK(property->IsMutableHeapNumber());
   8463             if (value_is_number && property->Number() == value->Number()) {
   8464               return descs->GetKey(i);
   8465             }
   8466           } else if (property == value) {
   8467             return descs->GetKey(i);
   8468           }
   8469         }
   8470       } else {
   8471         DCHECK_EQ(kDescriptor, details.location());
   8472         if (details.kind() == kData) {
   8473           if (descs->GetValue(i) == value) {
   8474             return descs->GetKey(i);
   8475           }
   8476         }
   8477       }
   8478     }
   8479     return GetHeap()->undefined_value();
   8480   } else if (IsJSGlobalObject()) {
   8481     return global_dictionary()->SlowReverseLookup(value);
   8482   } else {
   8483     return property_dictionary()->SlowReverseLookup(value);
   8484   }
   8485 }
   8486 
   8487 
   8488 Handle<Map> Map::RawCopy(Handle<Map> map, int instance_size) {
   8489   Isolate* isolate = map->GetIsolate();
   8490   Handle<Map> result =
   8491       isolate->factory()->NewMap(map->instance_type(), instance_size);
   8492   Handle<Object> prototype(map->prototype(), isolate);
   8493   Map::SetPrototype(result, prototype);
   8494   result->set_constructor_or_backpointer(map->GetConstructor());
   8495   result->set_bit_field(map->bit_field());
   8496   result->set_bit_field2(map->bit_field2());
   8497   int new_bit_field3 = map->bit_field3();
   8498   new_bit_field3 = OwnsDescriptors::update(new_bit_field3, true);
   8499   new_bit_field3 = NumberOfOwnDescriptorsBits::update(new_bit_field3, 0);
   8500   new_bit_field3 = EnumLengthBits::update(new_bit_field3,
   8501                                           kInvalidEnumCacheSentinel);
   8502   new_bit_field3 = Deprecated::update(new_bit_field3, false);
   8503   if (!map->is_dictionary_map()) {
   8504     new_bit_field3 = IsUnstable::update(new_bit_field3, false);
   8505   }
   8506   result->set_bit_field3(new_bit_field3);
   8507   return result;
   8508 }
   8509 
   8510 
   8511 Handle<Map> Map::Normalize(Handle<Map> fast_map, PropertyNormalizationMode mode,
   8512                            const char* reason) {
   8513   DCHECK(!fast_map->is_dictionary_map());
   8514 
   8515   Isolate* isolate = fast_map->GetIsolate();
   8516   Handle<Object> maybe_cache(isolate->native_context()->normalized_map_cache(),
   8517                              isolate);
   8518   bool use_cache =
   8519       !fast_map->is_prototype_map() && !maybe_cache->IsUndefined(isolate);
   8520   Handle<NormalizedMapCache> cache;
   8521   if (use_cache) cache = Handle<NormalizedMapCache>::cast(maybe_cache);
   8522 
   8523   Handle<Map> new_map;
   8524   if (use_cache && cache->Get(fast_map, mode).ToHandle(&new_map)) {
   8525 #ifdef VERIFY_HEAP
   8526     if (FLAG_verify_heap) new_map->DictionaryMapVerify();
   8527 #endif
   8528 #ifdef ENABLE_SLOW_DCHECKS
   8529     if (FLAG_enable_slow_asserts) {
   8530       // The cached map should match newly created normalized map bit-by-bit,
   8531       // except for the code cache, which can contain some ics which can be
   8532       // applied to the shared map, dependent code and weak cell cache.
   8533       Handle<Map> fresh = Map::CopyNormalized(fast_map, mode);
   8534 
   8535       if (new_map->is_prototype_map()) {
   8536         // For prototype maps, the PrototypeInfo is not copied.
   8537         DCHECK(memcmp(fresh->address(), new_map->address(),
   8538                       kTransitionsOrPrototypeInfoOffset) == 0);
   8539         DCHECK(fresh->raw_transitions() == Smi::kZero);
   8540         STATIC_ASSERT(kDescriptorsOffset ==
   8541                       kTransitionsOrPrototypeInfoOffset + kPointerSize);
   8542         DCHECK(memcmp(HeapObject::RawField(*fresh, kDescriptorsOffset),
   8543                       HeapObject::RawField(*new_map, kDescriptorsOffset),
   8544                       kCodeCacheOffset - kDescriptorsOffset) == 0);
   8545       } else {
   8546         DCHECK(memcmp(fresh->address(), new_map->address(),
   8547                       Map::kCodeCacheOffset) == 0);
   8548       }
   8549       STATIC_ASSERT(Map::kDependentCodeOffset ==
   8550                     Map::kCodeCacheOffset + kPointerSize);
   8551       STATIC_ASSERT(Map::kWeakCellCacheOffset ==
   8552                     Map::kDependentCodeOffset + kPointerSize);
   8553       int offset = Map::kWeakCellCacheOffset + kPointerSize;
   8554       DCHECK(memcmp(fresh->address() + offset,
   8555                     new_map->address() + offset,
   8556                     Map::kSize - offset) == 0);
   8557     }
   8558 #endif
   8559   } else {
   8560     new_map = Map::CopyNormalized(fast_map, mode);
   8561     if (use_cache) {
   8562       cache->Set(fast_map, new_map);
   8563       isolate->counters()->maps_normalized()->Increment();
   8564     }
   8565 #if TRACE_MAPS
   8566     if (FLAG_trace_maps) {
   8567       PrintF("[TraceMaps: Normalize from= %p to= %p reason= %s ]\n",
   8568              reinterpret_cast<void*>(*fast_map),
   8569              reinterpret_cast<void*>(*new_map), reason);
   8570     }
   8571 #endif
   8572   }
   8573   fast_map->NotifyLeafMapLayoutChange();
   8574   return new_map;
   8575 }
   8576 
   8577 
   8578 Handle<Map> Map::CopyNormalized(Handle<Map> map,
   8579                                 PropertyNormalizationMode mode) {
   8580   int new_instance_size = map->instance_size();
   8581   if (mode == CLEAR_INOBJECT_PROPERTIES) {
   8582     new_instance_size -= map->GetInObjectProperties() * kPointerSize;
   8583   }
   8584 
   8585   Handle<Map> result = RawCopy(map, new_instance_size);
   8586 
   8587   if (mode != CLEAR_INOBJECT_PROPERTIES) {
   8588     result->SetInObjectProperties(map->GetInObjectProperties());
   8589   }
   8590 
   8591   result->set_dictionary_map(true);
   8592   result->set_migration_target(false);
   8593   result->set_construction_counter(kNoSlackTracking);
   8594 
   8595 #ifdef VERIFY_HEAP
   8596   if (FLAG_verify_heap) result->DictionaryMapVerify();
   8597 #endif
   8598 
   8599   return result;
   8600 }
   8601 
   8602 // Return an immutable prototype exotic object version of the input map.
   8603 // Never even try to cache it in the transition tree, as it is intended
   8604 // for the global object and its prototype chain, and excluding it saves
   8605 // memory on the map transition tree.
   8606 
   8607 // static
   8608 Handle<Map> Map::TransitionToImmutableProto(Handle<Map> map) {
   8609   Handle<Map> new_map = Map::Copy(map, "ImmutablePrototype");
   8610   new_map->set_immutable_proto(true);
   8611   return new_map;
   8612 }
   8613 
   8614 Handle<Map> Map::CopyInitialMap(Handle<Map> map, int instance_size,
   8615                                 int in_object_properties,
   8616                                 int unused_property_fields) {
   8617 #ifdef DEBUG
   8618   Isolate* isolate = map->GetIsolate();
   8619   // Strict function maps have Function as a constructor but the
   8620   // Function's initial map is a sloppy function map. Same holds for
   8621   // GeneratorFunction / AsyncFunction and its initial map.
   8622   Object* constructor = map->GetConstructor();
   8623   DCHECK(constructor->IsJSFunction());
   8624   DCHECK(*map == JSFunction::cast(constructor)->initial_map() ||
   8625          *map == *isolate->strict_function_map() ||
   8626          *map == *isolate->generator_function_map() ||
   8627          *map == *isolate->async_function_map());
   8628 #endif
   8629   // Initial maps must always own their descriptors and it's descriptor array
   8630   // does not contain descriptors that do not belong to the map.
   8631   DCHECK(map->owns_descriptors());
   8632   DCHECK_EQ(map->NumberOfOwnDescriptors(),
   8633             map->instance_descriptors()->number_of_descriptors());
   8634 
   8635   Handle<Map> result = RawCopy(map, instance_size);
   8636 
   8637   // Please note instance_type and instance_size are set when allocated.
   8638   result->SetInObjectProperties(in_object_properties);
   8639   result->set_unused_property_fields(unused_property_fields);
   8640 
   8641   int number_of_own_descriptors = map->NumberOfOwnDescriptors();
   8642   if (number_of_own_descriptors > 0) {
   8643     // The copy will use the same descriptors array.
   8644     result->UpdateDescriptors(map->instance_descriptors(),
   8645                               map->GetLayoutDescriptor());
   8646     result->SetNumberOfOwnDescriptors(number_of_own_descriptors);
   8647 
   8648     DCHECK_EQ(result->NumberOfFields(),
   8649               in_object_properties - unused_property_fields);
   8650   }
   8651 
   8652   return result;
   8653 }
   8654 
   8655 
   8656 Handle<Map> Map::CopyDropDescriptors(Handle<Map> map) {
   8657   Handle<Map> result = RawCopy(map, map->instance_size());
   8658 
   8659   // Please note instance_type and instance_size are set when allocated.
   8660   if (map->IsJSObjectMap()) {
   8661     result->SetInObjectProperties(map->GetInObjectProperties());
   8662     result->set_unused_property_fields(map->unused_property_fields());
   8663   }
   8664   result->ClearCodeCache(map->GetHeap());
   8665   map->NotifyLeafMapLayoutChange();
   8666   return result;
   8667 }
   8668 
   8669 
   8670 Handle<Map> Map::ShareDescriptor(Handle<Map> map,
   8671                                  Handle<DescriptorArray> descriptors,
   8672                                  Descriptor* descriptor) {
   8673   // Sanity check. This path is only to be taken if the map owns its descriptor
   8674   // array, implying that its NumberOfOwnDescriptors equals the number of
   8675   // descriptors in the descriptor array.
   8676   DCHECK_EQ(map->NumberOfOwnDescriptors(),
   8677             map->instance_descriptors()->number_of_descriptors());
   8678 
   8679   Handle<Map> result = CopyDropDescriptors(map);
   8680   Handle<Name> name = descriptor->GetKey();
   8681 
   8682   // Ensure there's space for the new descriptor in the shared descriptor array.
   8683   if (descriptors->NumberOfSlackDescriptors() == 0) {
   8684     int old_size = descriptors->number_of_descriptors();
   8685     if (old_size == 0) {
   8686       descriptors = DescriptorArray::Allocate(map->GetIsolate(), 0, 1);
   8687     } else {
   8688       int slack = SlackForArraySize(old_size, kMaxNumberOfDescriptors);
   8689       EnsureDescriptorSlack(map, slack);
   8690       descriptors = handle(map->instance_descriptors());
   8691     }
   8692   }
   8693 
   8694   Handle<LayoutDescriptor> layout_descriptor =
   8695       FLAG_unbox_double_fields
   8696           ? LayoutDescriptor::ShareAppend(map, descriptor->GetDetails())
   8697           : handle(LayoutDescriptor::FastPointerLayout(), map->GetIsolate());
   8698 
   8699   {
   8700     DisallowHeapAllocation no_gc;
   8701     descriptors->Append(descriptor);
   8702     result->InitializeDescriptors(*descriptors, *layout_descriptor);
   8703   }
   8704 
   8705   DCHECK(result->NumberOfOwnDescriptors() == map->NumberOfOwnDescriptors() + 1);
   8706   ConnectTransition(map, result, name, SIMPLE_PROPERTY_TRANSITION);
   8707 
   8708   return result;
   8709 }
   8710 
   8711 
   8712 #if TRACE_MAPS
   8713 
   8714 // static
   8715 void Map::TraceTransition(const char* what, Map* from, Map* to, Name* name) {
   8716   if (FLAG_trace_maps) {
   8717     PrintF("[TraceMaps: %s from= %p to= %p name= ", what,
   8718            reinterpret_cast<void*>(from), reinterpret_cast<void*>(to));
   8719     name->NameShortPrint();
   8720     PrintF(" ]\n");
   8721   }
   8722 }
   8723 
   8724 
   8725 // static
   8726 void Map::TraceAllTransitions(Map* map) {
   8727   Object* transitions = map->raw_transitions();
   8728   int num_transitions = TransitionArray::NumberOfTransitions(transitions);
   8729   for (int i = -0; i < num_transitions; ++i) {
   8730     Map* target = TransitionArray::GetTarget(transitions, i);
   8731     Name* key = TransitionArray::GetKey(transitions, i);
   8732     Map::TraceTransition("Transition", map, target, key);
   8733     Map::TraceAllTransitions(target);
   8734   }
   8735 }
   8736 
   8737 #endif  // TRACE_MAPS
   8738 
   8739 
   8740 void Map::ConnectTransition(Handle<Map> parent, Handle<Map> child,
   8741                             Handle<Name> name, SimpleTransitionFlag flag) {
   8742   if (!parent->GetBackPointer()->IsUndefined(parent->GetIsolate())) {
   8743     parent->set_owns_descriptors(false);
   8744   } else {
   8745     // |parent| is initial map and it must keep the ownership, there must be no
   8746     // descriptors in the descriptors array that do not belong to the map.
   8747     DCHECK(parent->owns_descriptors());
   8748     DCHECK_EQ(parent->NumberOfOwnDescriptors(),
   8749               parent->instance_descriptors()->number_of_descriptors());
   8750   }
   8751   if (parent->is_prototype_map()) {
   8752     DCHECK(child->is_prototype_map());
   8753 #if TRACE_MAPS
   8754     Map::TraceTransition("NoTransition", *parent, *child, *name);
   8755 #endif
   8756   } else {
   8757     TransitionArray::Insert(parent, name, child, flag);
   8758 #if TRACE_MAPS
   8759     Map::TraceTransition("Transition", *parent, *child, *name);
   8760 #endif
   8761   }
   8762 }
   8763 
   8764 
   8765 Handle<Map> Map::CopyReplaceDescriptors(
   8766     Handle<Map> map, Handle<DescriptorArray> descriptors,
   8767     Handle<LayoutDescriptor> layout_descriptor, TransitionFlag flag,
   8768     MaybeHandle<Name> maybe_name, const char* reason,
   8769     SimpleTransitionFlag simple_flag) {
   8770   DCHECK(descriptors->IsSortedNoDuplicates());
   8771 
   8772   Handle<Map> result = CopyDropDescriptors(map);
   8773 
   8774   if (!map->is_prototype_map()) {
   8775     if (flag == INSERT_TRANSITION &&
   8776         TransitionArray::CanHaveMoreTransitions(map)) {
   8777       result->InitializeDescriptors(*descriptors, *layout_descriptor);
   8778 
   8779       Handle<Name> name;
   8780       CHECK(maybe_name.ToHandle(&name));
   8781       ConnectTransition(map, result, name, simple_flag);
   8782     } else {
   8783       descriptors->GeneralizeAllFields();
   8784       result->InitializeDescriptors(*descriptors,
   8785                                     LayoutDescriptor::FastPointerLayout());
   8786     }
   8787   } else {
   8788     result->InitializeDescriptors(*descriptors, *layout_descriptor);
   8789   }
   8790 #if TRACE_MAPS
   8791   if (FLAG_trace_maps &&
   8792       // Mirror conditions above that did not call ConnectTransition().
   8793       (map->is_prototype_map() ||
   8794        !(flag == INSERT_TRANSITION &&
   8795          TransitionArray::CanHaveMoreTransitions(map)))) {
   8796     PrintF("[TraceMaps: ReplaceDescriptors from= %p to= %p reason= %s ]\n",
   8797            reinterpret_cast<void*>(*map), reinterpret_cast<void*>(*result),
   8798            reason);
   8799   }
   8800 #endif
   8801 
   8802   return result;
   8803 }
   8804 
   8805 
   8806 // Creates transition tree starting from |split_map| and adding all descriptors
   8807 // starting from descriptor with index |split_map|.NumberOfOwnDescriptors().
   8808 // The way how it is done is tricky because of GC and special descriptors
   8809 // marking logic.
   8810 Handle<Map> Map::AddMissingTransitions(
   8811     Handle<Map> split_map, Handle<DescriptorArray> descriptors,
   8812     Handle<LayoutDescriptor> full_layout_descriptor) {
   8813   DCHECK(descriptors->IsSortedNoDuplicates());
   8814   int split_nof = split_map->NumberOfOwnDescriptors();
   8815   int nof_descriptors = descriptors->number_of_descriptors();
   8816   DCHECK_LT(split_nof, nof_descriptors);
   8817 
   8818   // Start with creating last map which will own full descriptors array.
   8819   // This is necessary to guarantee that GC will mark the whole descriptor
   8820   // array if any of the allocations happening below fail.
   8821   // Number of unused properties is temporarily incorrect and the layout
   8822   // descriptor could unnecessarily be in slow mode but we will fix after
   8823   // all the other intermediate maps are created.
   8824   Handle<Map> last_map = CopyDropDescriptors(split_map);
   8825   last_map->InitializeDescriptors(*descriptors, *full_layout_descriptor);
   8826   last_map->set_unused_property_fields(0);
   8827 
   8828   // During creation of intermediate maps we violate descriptors sharing
   8829   // invariant since the last map is not yet connected to the transition tree
   8830   // we create here. But it is safe because GC never trims map's descriptors
   8831   // if there are no dead transitions from that map and this is exactly the
   8832   // case for all the intermediate maps we create here.
   8833   Handle<Map> map = split_map;
   8834   for (int i = split_nof; i < nof_descriptors - 1; ++i) {
   8835     Handle<Map> new_map = CopyDropDescriptors(map);
   8836     InstallDescriptors(map, new_map, i, descriptors, full_layout_descriptor);
   8837     map = new_map;
   8838   }
   8839   map->NotifyLeafMapLayoutChange();
   8840   InstallDescriptors(map, last_map, nof_descriptors - 1, descriptors,
   8841                      full_layout_descriptor);
   8842   return last_map;
   8843 }
   8844 
   8845 
   8846 // Since this method is used to rewrite an existing transition tree, it can
   8847 // always insert transitions without checking.
   8848 void Map::InstallDescriptors(Handle<Map> parent, Handle<Map> child,
   8849                              int new_descriptor,
   8850                              Handle<DescriptorArray> descriptors,
   8851                              Handle<LayoutDescriptor> full_layout_descriptor) {
   8852   DCHECK(descriptors->IsSortedNoDuplicates());
   8853 
   8854   child->set_instance_descriptors(*descriptors);
   8855   child->SetNumberOfOwnDescriptors(new_descriptor + 1);
   8856 
   8857   int unused_property_fields = parent->unused_property_fields();
   8858   PropertyDetails details = descriptors->GetDetails(new_descriptor);
   8859   if (details.location() == kField) {
   8860     unused_property_fields = parent->unused_property_fields() - 1;
   8861     if (unused_property_fields < 0) {
   8862       unused_property_fields += JSObject::kFieldsAdded;
   8863     }
   8864   }
   8865   child->set_unused_property_fields(unused_property_fields);
   8866 
   8867   if (FLAG_unbox_double_fields) {
   8868     Handle<LayoutDescriptor> layout_descriptor =
   8869         LayoutDescriptor::AppendIfFastOrUseFull(parent, details,
   8870                                                 full_layout_descriptor);
   8871     child->set_layout_descriptor(*layout_descriptor);
   8872 #ifdef VERIFY_HEAP
   8873     // TODO(ishell): remove these checks from VERIFY_HEAP mode.
   8874     if (FLAG_verify_heap) {
   8875       CHECK(child->layout_descriptor()->IsConsistentWithMap(*child));
   8876     }
   8877 #else
   8878     SLOW_DCHECK(child->layout_descriptor()->IsConsistentWithMap(*child));
   8879 #endif
   8880     child->set_visitor_id(Heap::GetStaticVisitorIdForMap(*child));
   8881   }
   8882 
   8883   Handle<Name> name = handle(descriptors->GetKey(new_descriptor));
   8884   ConnectTransition(parent, child, name, SIMPLE_PROPERTY_TRANSITION);
   8885 }
   8886 
   8887 
   8888 Handle<Map> Map::CopyAsElementsKind(Handle<Map> map, ElementsKind kind,
   8889                                     TransitionFlag flag) {
   8890   Map* maybe_elements_transition_map = NULL;
   8891   if (flag == INSERT_TRANSITION) {
   8892     // Ensure we are requested to add elements kind transition "near the root".
   8893     DCHECK_EQ(map->FindRootMap()->NumberOfOwnDescriptors(),
   8894               map->NumberOfOwnDescriptors());
   8895 
   8896     maybe_elements_transition_map = map->ElementsTransitionMap();
   8897     DCHECK(maybe_elements_transition_map == NULL ||
   8898            (maybe_elements_transition_map->elements_kind() ==
   8899                 DICTIONARY_ELEMENTS &&
   8900             kind == DICTIONARY_ELEMENTS));
   8901     DCHECK(!IsFastElementsKind(kind) ||
   8902            IsMoreGeneralElementsKindTransition(map->elements_kind(), kind));
   8903     DCHECK(kind != map->elements_kind());
   8904   }
   8905 
   8906   bool insert_transition = flag == INSERT_TRANSITION &&
   8907                            TransitionArray::CanHaveMoreTransitions(map) &&
   8908                            maybe_elements_transition_map == NULL;
   8909 
   8910   if (insert_transition) {
   8911     Handle<Map> new_map = CopyForTransition(map, "CopyAsElementsKind");
   8912     new_map->set_elements_kind(kind);
   8913 
   8914     Isolate* isolate = map->GetIsolate();
   8915     Handle<Name> name = isolate->factory()->elements_transition_symbol();
   8916     ConnectTransition(map, new_map, name, SPECIAL_TRANSITION);
   8917     return new_map;
   8918   }
   8919 
   8920   // Create a new free-floating map only if we are not allowed to store it.
   8921   Handle<Map> new_map = Copy(map, "CopyAsElementsKind");
   8922   new_map->set_elements_kind(kind);
   8923   return new_map;
   8924 }
   8925 
   8926 
   8927 Handle<Map> Map::AsLanguageMode(Handle<Map> initial_map,
   8928                                 LanguageMode language_mode, FunctionKind kind) {
   8929   DCHECK_EQ(JS_FUNCTION_TYPE, initial_map->instance_type());
   8930   // Initial map for sloppy mode function is stored in the function
   8931   // constructor. Initial maps for strict mode are cached as special transitions
   8932   // using |strict_function_transition_symbol| as a key.
   8933   if (language_mode == SLOPPY) return initial_map;
   8934   Isolate* isolate = initial_map->GetIsolate();
   8935 
   8936   int map_index = Context::FunctionMapIndex(language_mode, kind);
   8937   Handle<Map> function_map(
   8938       Map::cast(isolate->native_context()->get(map_index)));
   8939 
   8940   STATIC_ASSERT(LANGUAGE_END == 2);
   8941   DCHECK_EQ(STRICT, language_mode);
   8942   Handle<Symbol> transition_symbol =
   8943       isolate->factory()->strict_function_transition_symbol();
   8944   Map* maybe_transition =
   8945       TransitionArray::SearchSpecial(*initial_map, *transition_symbol);
   8946   if (maybe_transition != NULL) {
   8947     return handle(maybe_transition, isolate);
   8948   }
   8949   initial_map->NotifyLeafMapLayoutChange();
   8950 
   8951   // Create new map taking descriptors from the |function_map| and all
   8952   // the other details from the |initial_map|.
   8953   Handle<Map> map =
   8954       Map::CopyInitialMap(function_map, initial_map->instance_size(),
   8955                           initial_map->GetInObjectProperties(),
   8956                           initial_map->unused_property_fields());
   8957   map->SetConstructor(initial_map->GetConstructor());
   8958   map->set_prototype(initial_map->prototype());
   8959 
   8960   if (TransitionArray::CanHaveMoreTransitions(initial_map)) {
   8961     Map::ConnectTransition(initial_map, map, transition_symbol,
   8962                            SPECIAL_TRANSITION);
   8963   }
   8964   return map;
   8965 }
   8966 
   8967 
   8968 Handle<Map> Map::CopyForTransition(Handle<Map> map, const char* reason) {
   8969   DCHECK(!map->is_prototype_map());
   8970   Handle<Map> new_map = CopyDropDescriptors(map);
   8971 
   8972   if (map->owns_descriptors()) {
   8973     // In case the map owned its own descriptors, share the descriptors and
   8974     // transfer ownership to the new map.
   8975     // The properties did not change, so reuse descriptors.
   8976     new_map->InitializeDescriptors(map->instance_descriptors(),
   8977                                    map->GetLayoutDescriptor());
   8978   } else {
   8979     // In case the map did not own its own descriptors, a split is forced by
   8980     // copying the map; creating a new descriptor array cell.
   8981     Handle<DescriptorArray> descriptors(map->instance_descriptors());
   8982     int number_of_own_descriptors = map->NumberOfOwnDescriptors();
   8983     Handle<DescriptorArray> new_descriptors =
   8984         DescriptorArray::CopyUpTo(descriptors, number_of_own_descriptors);
   8985     Handle<LayoutDescriptor> new_layout_descriptor(map->GetLayoutDescriptor(),
   8986                                                    map->GetIsolate());
   8987     new_map->InitializeDescriptors(*new_descriptors, *new_layout_descriptor);
   8988   }
   8989 
   8990 #if TRACE_MAPS
   8991   if (FLAG_trace_maps) {
   8992     PrintF("[TraceMaps: CopyForTransition from= %p to= %p reason= %s ]\n",
   8993            reinterpret_cast<void*>(*map), reinterpret_cast<void*>(*new_map),
   8994            reason);
   8995   }
   8996 #endif
   8997 
   8998   return new_map;
   8999 }
   9000 
   9001 
   9002 Handle<Map> Map::Copy(Handle<Map> map, const char* reason) {
   9003   Handle<DescriptorArray> descriptors(map->instance_descriptors());
   9004   int number_of_own_descriptors = map->NumberOfOwnDescriptors();
   9005   Handle<DescriptorArray> new_descriptors =
   9006       DescriptorArray::CopyUpTo(descriptors, number_of_own_descriptors);
   9007   Handle<LayoutDescriptor> new_layout_descriptor(map->GetLayoutDescriptor(),
   9008                                                  map->GetIsolate());
   9009   return CopyReplaceDescriptors(map, new_descriptors, new_layout_descriptor,
   9010                                 OMIT_TRANSITION, MaybeHandle<Name>(), reason,
   9011                                 SPECIAL_TRANSITION);
   9012 }
   9013 
   9014 
   9015 Handle<Map> Map::Create(Isolate* isolate, int inobject_properties) {
   9016   Handle<Map> copy =
   9017       Copy(handle(isolate->object_function()->initial_map()), "MapCreate");
   9018 
   9019   // Check that we do not overflow the instance size when adding the extra
   9020   // inobject properties. If the instance size overflows, we allocate as many
   9021   // properties as we can as inobject properties.
   9022   int max_extra_properties =
   9023       (JSObject::kMaxInstanceSize - JSObject::kHeaderSize) >> kPointerSizeLog2;
   9024 
   9025   if (inobject_properties > max_extra_properties) {
   9026     inobject_properties = max_extra_properties;
   9027   }
   9028 
   9029   int new_instance_size =
   9030       JSObject::kHeaderSize + kPointerSize * inobject_properties;
   9031 
   9032   // Adjust the map with the extra inobject properties.
   9033   copy->SetInObjectProperties(inobject_properties);
   9034   copy->set_unused_property_fields(inobject_properties);
   9035   copy->set_instance_size(new_instance_size);
   9036   copy->set_visitor_id(Heap::GetStaticVisitorIdForMap(*copy));
   9037   return copy;
   9038 }
   9039 
   9040 
   9041 Handle<Map> Map::CopyForPreventExtensions(Handle<Map> map,
   9042                                           PropertyAttributes attrs_to_add,
   9043                                           Handle<Symbol> transition_marker,
   9044                                           const char* reason) {
   9045   int num_descriptors = map->NumberOfOwnDescriptors();
   9046   Isolate* isolate = map->GetIsolate();
   9047   Handle<DescriptorArray> new_desc = DescriptorArray::CopyUpToAddAttributes(
   9048       handle(map->instance_descriptors(), isolate), num_descriptors,
   9049       attrs_to_add);
   9050   Handle<LayoutDescriptor> new_layout_descriptor(map->GetLayoutDescriptor(),
   9051                                                  isolate);
   9052   Handle<Map> new_map = CopyReplaceDescriptors(
   9053       map, new_desc, new_layout_descriptor, INSERT_TRANSITION,
   9054       transition_marker, reason, SPECIAL_TRANSITION);
   9055   new_map->set_is_extensible(false);
   9056   if (!IsFixedTypedArrayElementsKind(map->elements_kind())) {
   9057     ElementsKind new_kind = IsStringWrapperElementsKind(map->elements_kind())
   9058                                 ? SLOW_STRING_WRAPPER_ELEMENTS
   9059                                 : DICTIONARY_ELEMENTS;
   9060     new_map->set_elements_kind(new_kind);
   9061   }
   9062   return new_map;
   9063 }
   9064 
   9065 namespace {
   9066 
   9067 bool CanHoldValue(DescriptorArray* descriptors, int descriptor,
   9068                   PropertyConstness constness, Object* value) {
   9069   PropertyDetails details = descriptors->GetDetails(descriptor);
   9070   if (details.location() == kField) {
   9071     if (details.kind() == kData) {
   9072       return IsGeneralizableTo(constness, details.constness()) &&
   9073              value->FitsRepresentation(details.representation()) &&
   9074              descriptors->GetFieldType(descriptor)->NowContains(value);
   9075     } else {
   9076       DCHECK_EQ(kAccessor, details.kind());
   9077       return false;
   9078     }
   9079 
   9080   } else {
   9081     DCHECK_EQ(kDescriptor, details.location());
   9082     DCHECK_EQ(kConst, details.constness());
   9083     if (details.kind() == kData) {
   9084       DCHECK(!FLAG_track_constant_fields);
   9085       DCHECK(descriptors->GetValue(descriptor) != value ||
   9086              value->FitsRepresentation(details.representation()));
   9087       return descriptors->GetValue(descriptor) == value;
   9088     } else {
   9089       DCHECK_EQ(kAccessor, details.kind());
   9090       return false;
   9091     }
   9092   }
   9093   UNREACHABLE();
   9094   return false;
   9095 }
   9096 
   9097 Handle<Map> UpdateDescriptorForValue(Handle<Map> map, int descriptor,
   9098                                      PropertyConstness constness,
   9099                                      Handle<Object> value) {
   9100   if (CanHoldValue(map->instance_descriptors(), descriptor, constness,
   9101                    *value)) {
   9102     return map;
   9103   }
   9104 
   9105   Isolate* isolate = map->GetIsolate();
   9106   PropertyAttributes attributes =
   9107       map->instance_descriptors()->GetDetails(descriptor).attributes();
   9108   Representation representation = value->OptimalRepresentation();
   9109   Handle<FieldType> type = value->OptimalType(isolate, representation);
   9110 
   9111   MapUpdater mu(isolate, map);
   9112   return mu.ReconfigureToDataField(descriptor, attributes, constness,
   9113                                    representation, type);
   9114 }
   9115 
   9116 }  // namespace
   9117 
   9118 // static
   9119 Handle<Map> Map::PrepareForDataProperty(Handle<Map> map, int descriptor,
   9120                                         PropertyConstness constness,
   9121                                         Handle<Object> value) {
   9122   // Dictionaries can store any property value.
   9123   DCHECK(!map->is_dictionary_map());
   9124   // Update to the newest map before storing the property.
   9125   return UpdateDescriptorForValue(Update(map), descriptor, constness, value);
   9126 }
   9127 
   9128 Handle<Map> Map::TransitionToDataProperty(Handle<Map> map, Handle<Name> name,
   9129                                           Handle<Object> value,
   9130                                           PropertyAttributes attributes,
   9131                                           PropertyConstness constness,
   9132                                           StoreFromKeyed store_mode) {
   9133   RuntimeCallTimerScope stats_scope(
   9134       *map, map->is_prototype_map()
   9135                 ? &RuntimeCallStats::PrototypeMap_TransitionToDataProperty
   9136                 : &RuntimeCallStats::Map_TransitionToDataProperty);
   9137 
   9138   DCHECK(name->IsUniqueName());
   9139   DCHECK(!map->is_dictionary_map());
   9140 
   9141   // Migrate to the newest map before storing the property.
   9142   map = Update(map);
   9143 
   9144   Map* maybe_transition =
   9145       TransitionArray::SearchTransition(*map, kData, *name, attributes);
   9146   if (maybe_transition != NULL) {
   9147     Handle<Map> transition(maybe_transition);
   9148     int descriptor = transition->LastAdded();
   9149 
   9150     DCHECK_EQ(attributes, transition->instance_descriptors()
   9151                               ->GetDetails(descriptor)
   9152                               .attributes());
   9153 
   9154     return UpdateDescriptorForValue(transition, descriptor, constness, value);
   9155   }
   9156 
   9157   TransitionFlag flag = INSERT_TRANSITION;
   9158   MaybeHandle<Map> maybe_map;
   9159   if (!FLAG_track_constant_fields && value->IsJSFunction()) {
   9160     maybe_map = Map::CopyWithConstant(map, name, value, attributes, flag);
   9161   } else if (!map->TooManyFastProperties(store_mode)) {
   9162     Isolate* isolate = name->GetIsolate();
   9163     Representation representation = value->OptimalRepresentation();
   9164     Handle<FieldType> type = value->OptimalType(isolate, representation);
   9165     maybe_map = Map::CopyWithField(map, name, type, attributes, constness,
   9166                                    representation, flag);
   9167   }
   9168 
   9169   Handle<Map> result;
   9170   if (!maybe_map.ToHandle(&result)) {
   9171 #if TRACE_MAPS
   9172     if (FLAG_trace_maps) {
   9173       Vector<char> name_buffer = Vector<char>::New(100);
   9174       name->NameShortPrint(name_buffer);
   9175       Vector<char> buffer = Vector<char>::New(128);
   9176       SNPrintF(buffer, "TooManyFastProperties %s", name_buffer.start());
   9177       return Map::Normalize(map, CLEAR_INOBJECT_PROPERTIES, buffer.start());
   9178     }
   9179 #endif
   9180     return Map::Normalize(map, CLEAR_INOBJECT_PROPERTIES,
   9181                           "TooManyFastProperties");
   9182   }
   9183 
   9184   return result;
   9185 }
   9186 
   9187 
   9188 Handle<Map> Map::ReconfigureExistingProperty(Handle<Map> map, int descriptor,
   9189                                              PropertyKind kind,
   9190                                              PropertyAttributes attributes) {
   9191   // Dictionaries have to be reconfigured in-place.
   9192   DCHECK(!map->is_dictionary_map());
   9193 
   9194   if (!map->GetBackPointer()->IsMap()) {
   9195     // There is no benefit from reconstructing transition tree for maps without
   9196     // back pointers.
   9197     return CopyGeneralizeAllFields(map, map->elements_kind(), descriptor, kind,
   9198                                    attributes,
   9199                                    "GenAll_AttributesMismatchProtoMap");
   9200   }
   9201 
   9202   if (FLAG_trace_generalization) {
   9203     map->PrintReconfiguration(stdout, descriptor, kind, attributes);
   9204   }
   9205 
   9206   Isolate* isolate = map->GetIsolate();
   9207 
   9208   MapUpdater mu(isolate, map);
   9209   DCHECK_EQ(kData, kind);  // Only kData case is supported so far.
   9210   Handle<Map> new_map = mu.ReconfigureToDataField(
   9211       descriptor, attributes, kDefaultFieldConstness, Representation::None(),
   9212       FieldType::None(isolate));
   9213   return new_map;
   9214 }
   9215 
   9216 Handle<Map> Map::TransitionToAccessorProperty(Isolate* isolate, Handle<Map> map,
   9217                                               Handle<Name> name, int descriptor,
   9218                                               Handle<Object> getter,
   9219                                               Handle<Object> setter,
   9220                                               PropertyAttributes attributes) {
   9221   RuntimeCallTimerScope stats_scope(
   9222       isolate,
   9223       map->is_prototype_map()
   9224           ? &RuntimeCallStats::PrototypeMap_TransitionToAccessorProperty
   9225           : &RuntimeCallStats::Map_TransitionToAccessorProperty);
   9226 
   9227   // At least one of the accessors needs to be a new value.
   9228   DCHECK(!getter->IsNull(isolate) || !setter->IsNull(isolate));
   9229   DCHECK(name->IsUniqueName());
   9230 
   9231   // Dictionary maps can always have additional data properties.
   9232   if (map->is_dictionary_map()) return map;
   9233 
   9234   // Migrate to the newest map before transitioning to the new property.
   9235   map = Update(map);
   9236 
   9237   PropertyNormalizationMode mode = map->is_prototype_map()
   9238                                        ? KEEP_INOBJECT_PROPERTIES
   9239                                        : CLEAR_INOBJECT_PROPERTIES;
   9240 
   9241   Map* maybe_transition =
   9242       TransitionArray::SearchTransition(*map, kAccessor, *name, attributes);
   9243   if (maybe_transition != NULL) {
   9244     Handle<Map> transition(maybe_transition, isolate);
   9245     DescriptorArray* descriptors = transition->instance_descriptors();
   9246     int descriptor = transition->LastAdded();
   9247     DCHECK(descriptors->GetKey(descriptor)->Equals(*name));
   9248 
   9249     DCHECK_EQ(kAccessor, descriptors->GetDetails(descriptor).kind());
   9250     DCHECK_EQ(attributes, descriptors->GetDetails(descriptor).attributes());
   9251 
   9252     Handle<Object> maybe_pair(descriptors->GetValue(descriptor), isolate);
   9253     if (!maybe_pair->IsAccessorPair()) {
   9254       return Map::Normalize(map, mode, "TransitionToAccessorFromNonPair");
   9255     }
   9256 
   9257     Handle<AccessorPair> pair = Handle<AccessorPair>::cast(maybe_pair);
   9258     if (!pair->Equals(*getter, *setter)) {
   9259       return Map::Normalize(map, mode, "TransitionToDifferentAccessor");
   9260     }
   9261 
   9262     return transition;
   9263   }
   9264 
   9265   Handle<AccessorPair> pair;
   9266   DescriptorArray* old_descriptors = map->instance_descriptors();
   9267   if (descriptor != DescriptorArray::kNotFound) {
   9268     if (descriptor != map->LastAdded()) {
   9269       return Map::Normalize(map, mode, "AccessorsOverwritingNonLast");
   9270     }
   9271     PropertyDetails old_details = old_descriptors->GetDetails(descriptor);
   9272     if (old_details.kind() != kAccessor) {
   9273       return Map::Normalize(map, mode, "AccessorsOverwritingNonAccessors");
   9274     }
   9275 
   9276     if (old_details.attributes() != attributes) {
   9277       return Map::Normalize(map, mode, "AccessorsWithAttributes");
   9278     }
   9279 
   9280     Handle<Object> maybe_pair(old_descriptors->GetValue(descriptor), isolate);
   9281     if (!maybe_pair->IsAccessorPair()) {
   9282       return Map::Normalize(map, mode, "AccessorsOverwritingNonPair");
   9283     }
   9284 
   9285     Handle<AccessorPair> current_pair = Handle<AccessorPair>::cast(maybe_pair);
   9286     if (current_pair->Equals(*getter, *setter)) return map;
   9287 
   9288     bool overwriting_accessor = false;
   9289     if (!getter->IsNull(isolate) &&
   9290         !current_pair->get(ACCESSOR_GETTER)->IsNull(isolate) &&
   9291         current_pair->get(ACCESSOR_GETTER) != *getter) {
   9292       overwriting_accessor = true;
   9293     }
   9294     if (!setter->IsNull(isolate) &&
   9295         !current_pair->get(ACCESSOR_SETTER)->IsNull(isolate) &&
   9296         current_pair->get(ACCESSOR_SETTER) != *setter) {
   9297       overwriting_accessor = true;
   9298     }
   9299     if (overwriting_accessor) {
   9300       return Map::Normalize(map, mode, "AccessorsOverwritingAccessors");
   9301     }
   9302 
   9303     pair = AccessorPair::Copy(Handle<AccessorPair>::cast(maybe_pair));
   9304   } else if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors ||
   9305              map->TooManyFastProperties(CERTAINLY_NOT_STORE_FROM_KEYED)) {
   9306     return Map::Normalize(map, CLEAR_INOBJECT_PROPERTIES, "TooManyAccessors");
   9307   } else {
   9308     pair = isolate->factory()->NewAccessorPair();
   9309   }
   9310 
   9311   pair->SetComponents(*getter, *setter);
   9312 
   9313   TransitionFlag flag = INSERT_TRANSITION;
   9314   Descriptor d = Descriptor::AccessorConstant(name, pair, attributes);
   9315   return Map::CopyInsertDescriptor(map, &d, flag);
   9316 }
   9317 
   9318 
   9319 Handle<Map> Map::CopyAddDescriptor(Handle<Map> map,
   9320                                    Descriptor* descriptor,
   9321                                    TransitionFlag flag) {
   9322   Handle<DescriptorArray> descriptors(map->instance_descriptors());
   9323 
   9324   // Share descriptors only if map owns descriptors and it not an initial map.
   9325   if (flag == INSERT_TRANSITION && map->owns_descriptors() &&
   9326       !map->GetBackPointer()->IsUndefined(map->GetIsolate()) &&
   9327       TransitionArray::CanHaveMoreTransitions(map)) {
   9328     return ShareDescriptor(map, descriptors, descriptor);
   9329   }
   9330 
   9331   int nof = map->NumberOfOwnDescriptors();
   9332   Handle<DescriptorArray> new_descriptors =
   9333       DescriptorArray::CopyUpTo(descriptors, nof, 1);
   9334   new_descriptors->Append(descriptor);
   9335 
   9336   Handle<LayoutDescriptor> new_layout_descriptor =
   9337       FLAG_unbox_double_fields
   9338           ? LayoutDescriptor::New(map, new_descriptors, nof + 1)
   9339           : handle(LayoutDescriptor::FastPointerLayout(), map->GetIsolate());
   9340 
   9341   return CopyReplaceDescriptors(map, new_descriptors, new_layout_descriptor,
   9342                                 flag, descriptor->GetKey(), "CopyAddDescriptor",
   9343                                 SIMPLE_PROPERTY_TRANSITION);
   9344 }
   9345 
   9346 
   9347 Handle<Map> Map::CopyInsertDescriptor(Handle<Map> map,
   9348                                       Descriptor* descriptor,
   9349                                       TransitionFlag flag) {
   9350   Handle<DescriptorArray> old_descriptors(map->instance_descriptors());
   9351 
   9352   // We replace the key if it is already present.
   9353   int index = old_descriptors->SearchWithCache(map->GetIsolate(),
   9354                                                *descriptor->GetKey(), *map);
   9355   if (index != DescriptorArray::kNotFound) {
   9356     return CopyReplaceDescriptor(map, old_descriptors, descriptor, index, flag);
   9357   }
   9358   return CopyAddDescriptor(map, descriptor, flag);
   9359 }
   9360 
   9361 
   9362 Handle<DescriptorArray> DescriptorArray::CopyUpTo(
   9363     Handle<DescriptorArray> desc,
   9364     int enumeration_index,
   9365     int slack) {
   9366   return DescriptorArray::CopyUpToAddAttributes(
   9367       desc, enumeration_index, NONE, slack);
   9368 }
   9369 
   9370 
   9371 Handle<DescriptorArray> DescriptorArray::CopyUpToAddAttributes(
   9372     Handle<DescriptorArray> desc,
   9373     int enumeration_index,
   9374     PropertyAttributes attributes,
   9375     int slack) {
   9376   if (enumeration_index + slack == 0) {
   9377     return desc->GetIsolate()->factory()->empty_descriptor_array();
   9378   }
   9379 
   9380   int size = enumeration_index;
   9381 
   9382   Handle<DescriptorArray> descriptors =
   9383       DescriptorArray::Allocate(desc->GetIsolate(), size, slack);
   9384 
   9385   if (attributes != NONE) {
   9386     for (int i = 0; i < size; ++i) {
   9387       Object* value = desc->GetValue(i);
   9388       Name* key = desc->GetKey(i);
   9389       PropertyDetails details = desc->GetDetails(i);
   9390       // Bulk attribute changes never affect private properties.
   9391       if (!key->IsPrivate()) {
   9392         int mask = DONT_DELETE | DONT_ENUM;
   9393         // READ_ONLY is an invalid attribute for JS setters/getters.
   9394         if (details.kind() != kAccessor || !value->IsAccessorPair()) {
   9395           mask |= READ_ONLY;
   9396         }
   9397         details = details.CopyAddAttributes(
   9398             static_cast<PropertyAttributes>(attributes & mask));
   9399       }
   9400       descriptors->Set(i, key, value, details);
   9401     }
   9402   } else {
   9403     for (int i = 0; i < size; ++i) {
   9404       descriptors->CopyFrom(i, *desc);
   9405     }
   9406   }
   9407 
   9408   if (desc->number_of_descriptors() != enumeration_index) descriptors->Sort();
   9409 
   9410   return descriptors;
   9411 }
   9412 
   9413 
   9414 bool DescriptorArray::IsEqualUpTo(DescriptorArray* desc, int nof_descriptors) {
   9415   for (int i = 0; i < nof_descriptors; i++) {
   9416     if (GetKey(i) != desc->GetKey(i) || GetValue(i) != desc->GetValue(i)) {
   9417       return false;
   9418     }
   9419     PropertyDetails details = GetDetails(i);
   9420     PropertyDetails other_details = desc->GetDetails(i);
   9421     if (details.kind() != other_details.kind() ||
   9422         details.location() != other_details.location() ||
   9423         !details.representation().Equals(other_details.representation())) {
   9424       return false;
   9425     }
   9426   }
   9427   return true;
   9428 }
   9429 
   9430 
   9431 Handle<Map> Map::CopyReplaceDescriptor(Handle<Map> map,
   9432                                        Handle<DescriptorArray> descriptors,
   9433                                        Descriptor* descriptor,
   9434                                        int insertion_index,
   9435                                        TransitionFlag flag) {
   9436   Handle<Name> key = descriptor->GetKey();
   9437   DCHECK(*key == descriptors->GetKey(insertion_index));
   9438 
   9439   Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo(
   9440       descriptors, map->NumberOfOwnDescriptors());
   9441 
   9442   new_descriptors->Replace(insertion_index, descriptor);
   9443   Handle<LayoutDescriptor> new_layout_descriptor = LayoutDescriptor::New(
   9444       map, new_descriptors, new_descriptors->number_of_descriptors());
   9445 
   9446   SimpleTransitionFlag simple_flag =
   9447       (insertion_index == descriptors->number_of_descriptors() - 1)
   9448           ? SIMPLE_PROPERTY_TRANSITION
   9449           : PROPERTY_TRANSITION;
   9450   return CopyReplaceDescriptors(map, new_descriptors, new_layout_descriptor,
   9451                                 flag, key, "CopyReplaceDescriptor",
   9452                                 simple_flag);
   9453 }
   9454 
   9455 // Helper class to manage a Map's code cache. The layout depends on the number
   9456 // of entries; this is worthwhile because most code caches are very small,
   9457 // but some are huge (thousands of entries).
   9458 // For zero entries, the EmptyFixedArray is used.
   9459 // For one entry, we use a 2-element FixedArray containing [name, code].
   9460 // For 2..100 entries, we use a FixedArray with linear lookups, the layout is:
   9461 //   [0] - number of slots that are currently in use
   9462 //   [1] - first name
   9463 //   [2] - first code
   9464 //   [3] - second name
   9465 //   [4] - second code
   9466 //   etc.
   9467 // For more than 128 entries, we use a CodeCacheHashTable.
   9468 class CodeCache : public AllStatic {
   9469  public:
   9470   // Returns the new cache, to be stored on the map.
   9471   static Handle<FixedArray> Put(Isolate* isolate, Handle<FixedArray> cache,
   9472                                 Handle<Name> name, Handle<Code> code) {
   9473     int length = cache->length();
   9474     if (length == 0) return PutFirstElement(isolate, name, code);
   9475     if (length == kEntrySize) {
   9476       return PutSecondElement(isolate, cache, name, code);
   9477     }
   9478     if (length <= kLinearMaxSize) {
   9479       Handle<FixedArray> result = PutLinearElement(isolate, cache, name, code);
   9480       if (!result.is_null()) return result;
   9481       // Fall through if linear storage is getting too large.
   9482     }
   9483     return PutHashTableElement(isolate, cache, name, code);
   9484   }
   9485 
   9486   static Code* Lookup(FixedArray* cache, Name* name, Code::Flags flags) {
   9487     int length = cache->length();
   9488     if (length == 0) return nullptr;
   9489     if (length == kEntrySize) return OneElementLookup(cache, name, flags);
   9490     if (!cache->IsCodeCacheHashTable()) {
   9491       return LinearLookup(cache, name, flags);
   9492     } else {
   9493       return CodeCacheHashTable::cast(cache)->Lookup(name, flags);
   9494     }
   9495   }
   9496 
   9497  private:
   9498   static const int kNameIndex = 0;
   9499   static const int kCodeIndex = 1;
   9500   static const int kEntrySize = 2;
   9501 
   9502   static const int kLinearUsageIndex = 0;
   9503   static const int kLinearReservedSlots = 1;
   9504   static const int kLinearInitialCapacity = 2;
   9505   static const int kLinearMaxSize = 257;  // == LinearSizeFor(128);
   9506 
   9507   static const int kHashTableInitialCapacity = 200;  // Number of entries.
   9508 
   9509   static int LinearSizeFor(int entries) {
   9510     return kLinearReservedSlots + kEntrySize * entries;
   9511   }
   9512 
   9513   static int LinearNewSize(int old_size) {
   9514     int old_entries = (old_size - kLinearReservedSlots) / kEntrySize;
   9515     return LinearSizeFor(old_entries * 2);
   9516   }
   9517 
   9518   static Code* OneElementLookup(FixedArray* cache, Name* name,
   9519                                 Code::Flags flags) {
   9520     DCHECK_EQ(cache->length(), kEntrySize);
   9521     if (cache->get(kNameIndex) != name) return nullptr;
   9522     Code* maybe_code = Code::cast(cache->get(kCodeIndex));
   9523     if (maybe_code->flags() != flags) return nullptr;
   9524     return maybe_code;
   9525   }
   9526 
   9527   static Code* LinearLookup(FixedArray* cache, Name* name, Code::Flags flags) {
   9528     DCHECK_GE(cache->length(), kEntrySize);
   9529     DCHECK(!cache->IsCodeCacheHashTable());
   9530     int usage = GetLinearUsage(cache);
   9531     for (int i = kLinearReservedSlots; i < usage; i += kEntrySize) {
   9532       if (cache->get(i + kNameIndex) != name) continue;
   9533       Code* code = Code::cast(cache->get(i + kCodeIndex));
   9534       if (code->flags() == flags) return code;
   9535     }
   9536     return nullptr;
   9537   }
   9538 
   9539   static Handle<FixedArray> PutFirstElement(Isolate* isolate, Handle<Name> name,
   9540                                             Handle<Code> code) {
   9541     Handle<FixedArray> cache = isolate->factory()->NewFixedArray(kEntrySize);
   9542     cache->set(kNameIndex, *name);
   9543     cache->set(kCodeIndex, *code);
   9544     return cache;
   9545   }
   9546 
   9547   static Handle<FixedArray> PutSecondElement(Isolate* isolate,
   9548                                              Handle<FixedArray> cache,
   9549                                              Handle<Name> name,
   9550                                              Handle<Code> code) {
   9551     DCHECK_EQ(cache->length(), kEntrySize);
   9552     Handle<FixedArray> new_cache = isolate->factory()->NewFixedArray(
   9553         LinearSizeFor(kLinearInitialCapacity));
   9554     new_cache->set(kLinearReservedSlots + kNameIndex, cache->get(kNameIndex));
   9555     new_cache->set(kLinearReservedSlots + kCodeIndex, cache->get(kCodeIndex));
   9556     new_cache->set(LinearSizeFor(1) + kNameIndex, *name);
   9557     new_cache->set(LinearSizeFor(1) + kCodeIndex, *code);
   9558     new_cache->set(kLinearUsageIndex, Smi::FromInt(LinearSizeFor(2)));
   9559     return new_cache;
   9560   }
   9561 
   9562   static Handle<FixedArray> PutLinearElement(Isolate* isolate,
   9563                                              Handle<FixedArray> cache,
   9564                                              Handle<Name> name,
   9565                                              Handle<Code> code) {
   9566     int length = cache->length();
   9567     int usage = GetLinearUsage(*cache);
   9568     DCHECK_LE(usage, length);
   9569     // Check if we need to grow.
   9570     if (usage == length) {
   9571       int new_length = LinearNewSize(length);
   9572       if (new_length > kLinearMaxSize) return Handle<FixedArray>::null();
   9573       Handle<FixedArray> new_cache =
   9574           isolate->factory()->NewFixedArray(new_length);
   9575       for (int i = kLinearReservedSlots; i < length; i++) {
   9576         new_cache->set(i, cache->get(i));
   9577       }
   9578       cache = new_cache;
   9579     }
   9580     // Store new entry.
   9581     DCHECK_GE(cache->length(), usage + kEntrySize);
   9582     cache->set(usage + kNameIndex, *name);
   9583     cache->set(usage + kCodeIndex, *code);
   9584     cache->set(kLinearUsageIndex, Smi::FromInt(usage + kEntrySize));
   9585     return cache;
   9586   }
   9587 
   9588   static Handle<FixedArray> PutHashTableElement(Isolate* isolate,
   9589                                                 Handle<FixedArray> cache,
   9590                                                 Handle<Name> name,
   9591                                                 Handle<Code> code) {
   9592     // Check if we need to transition from linear to hash table storage.
   9593     if (!cache->IsCodeCacheHashTable()) {
   9594       // Check that the initial hash table capacity is large enough.
   9595       DCHECK_EQ(kLinearMaxSize, LinearSizeFor(128));
   9596       STATIC_ASSERT(kHashTableInitialCapacity > 128);
   9597 
   9598       int length = cache->length();
   9599       // Only migrate from linear storage when it's full.
   9600       DCHECK_EQ(length, GetLinearUsage(*cache));
   9601       DCHECK_EQ(length, kLinearMaxSize);
   9602       Handle<CodeCacheHashTable> table =
   9603           CodeCacheHashTable::New(isolate, kHashTableInitialCapacity);
   9604       HandleScope scope(isolate);
   9605       for (int i = kLinearReservedSlots; i < length; i += kEntrySize) {
   9606         Handle<Name> old_name(Name::cast(cache->get(i + kNameIndex)), isolate);
   9607         Handle<Code> old_code(Code::cast(cache->get(i + kCodeIndex)), isolate);
   9608         CodeCacheHashTable::Put(table, old_name, old_code);
   9609       }
   9610       cache = table;
   9611     }
   9612     // Store new entry.
   9613     DCHECK(cache->IsCodeCacheHashTable());
   9614     return CodeCacheHashTable::Put(Handle<CodeCacheHashTable>::cast(cache),
   9615                                    name, code);
   9616   }
   9617 
   9618   static inline int GetLinearUsage(FixedArray* linear_cache) {
   9619     DCHECK_GT(linear_cache->length(), kEntrySize);
   9620     return Smi::cast(linear_cache->get(kLinearUsageIndex))->value();
   9621   }
   9622 };
   9623 
   9624 void Map::UpdateCodeCache(Handle<Map> map,
   9625                           Handle<Name> name,
   9626                           Handle<Code> code) {
   9627   Isolate* isolate = map->GetIsolate();
   9628   Handle<FixedArray> cache(map->code_cache(), isolate);
   9629   Handle<FixedArray> new_cache = CodeCache::Put(isolate, cache, name, code);
   9630   map->set_code_cache(*new_cache);
   9631 }
   9632 
   9633 Code* Map::LookupInCodeCache(Name* name, Code::Flags flags) {
   9634   return CodeCache::Lookup(code_cache(), name, flags);
   9635 }
   9636 
   9637 
   9638 // The key in the code cache hash table consists of the property name and the
   9639 // code object. The actual match is on the name and the code flags. If a key
   9640 // is created using the flags and not a code object it can only be used for
   9641 // lookup not to create a new entry.
   9642 class CodeCacheHashTableKey : public HashTableKey {
   9643  public:
   9644   CodeCacheHashTableKey(Handle<Name> name, Code::Flags flags)
   9645       : name_(name), flags_(flags), code_() {
   9646     DCHECK(name_->IsUniqueName());
   9647   }
   9648 
   9649   CodeCacheHashTableKey(Handle<Name> name, Handle<Code> code)
   9650       : name_(name), flags_(code->flags()), code_(code) {
   9651     DCHECK(name_->IsUniqueName());
   9652   }
   9653 
   9654   bool IsMatch(Object* other) override {
   9655     DCHECK(other->IsFixedArray());
   9656     FixedArray* pair = FixedArray::cast(other);
   9657     Name* name = Name::cast(pair->get(0));
   9658     Code::Flags flags = Code::cast(pair->get(1))->flags();
   9659     if (flags != flags_) return false;
   9660     DCHECK(name->IsUniqueName());
   9661     return *name_ == name;
   9662   }
   9663 
   9664   static uint32_t NameFlagsHashHelper(Name* name, Code::Flags flags) {
   9665     return name->Hash() ^ flags;
   9666   }
   9667 
   9668   uint32_t Hash() override { return NameFlagsHashHelper(*name_, flags_); }
   9669 
   9670   uint32_t HashForObject(Object* obj) override {
   9671     FixedArray* pair = FixedArray::cast(obj);
   9672     Name* name = Name::cast(pair->get(0));
   9673     Code* code = Code::cast(pair->get(1));
   9674     return NameFlagsHashHelper(name, code->flags());
   9675   }
   9676 
   9677   MUST_USE_RESULT Handle<Object> AsHandle(Isolate* isolate) override {
   9678     Handle<Code> code = code_.ToHandleChecked();
   9679     Handle<FixedArray> pair = isolate->factory()->NewFixedArray(2);
   9680     pair->set(0, *name_);
   9681     pair->set(1, *code);
   9682     return pair;
   9683   }
   9684 
   9685  private:
   9686   Handle<Name> name_;
   9687   Code::Flags flags_;
   9688   // TODO(jkummerow): We should be able to get by without this.
   9689   MaybeHandle<Code> code_;
   9690 };
   9691 
   9692 
   9693 Handle<CodeCacheHashTable> CodeCacheHashTable::Put(
   9694     Handle<CodeCacheHashTable> cache, Handle<Name> name, Handle<Code> code) {
   9695   CodeCacheHashTableKey key(name, code);
   9696 
   9697   Handle<CodeCacheHashTable> new_cache = EnsureCapacity(cache, 1, &key);
   9698 
   9699   int entry = new_cache->FindInsertionEntry(key.Hash());
   9700   Handle<Object> k = key.AsHandle(cache->GetIsolate());
   9701 
   9702   new_cache->set(EntryToIndex(entry), *k);
   9703   new_cache->ElementAdded();
   9704   return new_cache;
   9705 }
   9706 
   9707 Code* CodeCacheHashTable::Lookup(Name* name, Code::Flags flags) {
   9708   DisallowHeapAllocation no_alloc;
   9709   CodeCacheHashTableKey key(handle(name), flags);
   9710   int entry = FindEntry(&key);
   9711   if (entry == kNotFound) return nullptr;
   9712   return Code::cast(FixedArray::cast(get(EntryToIndex(entry)))->get(1));
   9713 }
   9714 
   9715 Handle<FixedArray> FixedArray::SetAndGrow(Handle<FixedArray> array, int index,
   9716                                           Handle<Object> value) {
   9717   if (index < array->length()) {
   9718     array->set(index, *value);
   9719     return array;
   9720   }
   9721   int capacity = array->length();
   9722   do {
   9723     capacity = JSObject::NewElementsCapacity(capacity);
   9724   } while (capacity <= index);
   9725   Handle<FixedArray> new_array =
   9726       array->GetIsolate()->factory()->NewUninitializedFixedArray(capacity);
   9727   array->CopyTo(0, *new_array, 0, array->length());
   9728   new_array->FillWithHoles(array->length(), new_array->length());
   9729   new_array->set(index, *value);
   9730   return new_array;
   9731 }
   9732 
   9733 void FixedArray::Shrink(int new_length) {
   9734   DCHECK(0 <= new_length && new_length <= length());
   9735   if (new_length < length()) {
   9736     GetHeap()->RightTrimFixedArray(this, length() - new_length);
   9737   }
   9738 }
   9739 
   9740 
   9741 void FixedArray::CopyTo(int pos, FixedArray* dest, int dest_pos, int len) {
   9742   DisallowHeapAllocation no_gc;
   9743   WriteBarrierMode mode = dest->GetWriteBarrierMode(no_gc);
   9744   for (int index = 0; index < len; index++) {
   9745     dest->set(dest_pos+index, get(pos+index), mode);
   9746   }
   9747 }
   9748 
   9749 #ifdef DEBUG
   9750 bool FixedArray::IsEqualTo(FixedArray* other) {
   9751   if (length() != other->length()) return false;
   9752   for (int i = 0 ; i < length(); ++i) {
   9753     if (get(i) != other->get(i)) return false;
   9754   }
   9755   return true;
   9756 }
   9757 #endif
   9758 
   9759 
   9760 // static
   9761 void WeakFixedArray::Set(Handle<WeakFixedArray> array, int index,
   9762                          Handle<HeapObject> value) {
   9763   DCHECK(array->IsEmptySlot(index));  // Don't overwrite anything.
   9764   Handle<WeakCell> cell =
   9765       value->IsMap() ? Map::WeakCellForMap(Handle<Map>::cast(value))
   9766                      : array->GetIsolate()->factory()->NewWeakCell(value);
   9767   Handle<FixedArray>::cast(array)->set(index + kFirstIndex, *cell);
   9768   if (FLAG_trace_weak_arrays) {
   9769     PrintF("[WeakFixedArray: storing at index %d ]\n", index);
   9770   }
   9771   array->set_last_used_index(index);
   9772 }
   9773 
   9774 
   9775 // static
   9776 Handle<WeakFixedArray> WeakFixedArray::Add(Handle<Object> maybe_array,
   9777                                            Handle<HeapObject> value,
   9778                                            int* assigned_index) {
   9779   Handle<WeakFixedArray> array =
   9780       (maybe_array.is_null() || !maybe_array->IsWeakFixedArray())
   9781           ? Allocate(value->GetIsolate(), 1, Handle<WeakFixedArray>::null())
   9782           : Handle<WeakFixedArray>::cast(maybe_array);
   9783   // Try to store the new entry if there's room. Optimize for consecutive
   9784   // accesses.
   9785   int first_index = array->last_used_index();
   9786   int length = array->Length();
   9787   if (length > 0) {
   9788     for (int i = first_index;;) {
   9789       if (array->IsEmptySlot((i))) {
   9790         WeakFixedArray::Set(array, i, value);
   9791         if (assigned_index != NULL) *assigned_index = i;
   9792         return array;
   9793       }
   9794       if (FLAG_trace_weak_arrays) {
   9795         PrintF("[WeakFixedArray: searching for free slot]\n");
   9796       }
   9797       i = (i + 1) % length;
   9798       if (i == first_index) break;
   9799     }
   9800   }
   9801 
   9802   // No usable slot found, grow the array.
   9803   int new_length = length == 0 ? 1 : length + (length >> 1) + 4;
   9804   Handle<WeakFixedArray> new_array =
   9805       Allocate(array->GetIsolate(), new_length, array);
   9806   if (FLAG_trace_weak_arrays) {
   9807     PrintF("[WeakFixedArray: growing to size %d ]\n", new_length);
   9808   }
   9809   WeakFixedArray::Set(new_array, length, value);
   9810   if (assigned_index != NULL) *assigned_index = length;
   9811   return new_array;
   9812 }
   9813 
   9814 
   9815 template <class CompactionCallback>
   9816 void WeakFixedArray::Compact() {
   9817   FixedArray* array = FixedArray::cast(this);
   9818   int new_length = kFirstIndex;
   9819   for (int i = kFirstIndex; i < array->length(); i++) {
   9820     Object* element = array->get(i);
   9821     if (element->IsSmi()) continue;
   9822     if (WeakCell::cast(element)->cleared()) continue;
   9823     Object* value = WeakCell::cast(element)->value();
   9824     CompactionCallback::Callback(value, i - kFirstIndex,
   9825                                  new_length - kFirstIndex);
   9826     array->set(new_length++, element);
   9827   }
   9828   array->Shrink(new_length);
   9829   set_last_used_index(0);
   9830 }
   9831 
   9832 
   9833 void WeakFixedArray::Iterator::Reset(Object* maybe_array) {
   9834   if (maybe_array->IsWeakFixedArray()) {
   9835     list_ = WeakFixedArray::cast(maybe_array);
   9836     index_ = 0;
   9837 #ifdef DEBUG
   9838     last_used_index_ = list_->last_used_index();
   9839 #endif  // DEBUG
   9840   }
   9841 }
   9842 
   9843 
   9844 void JSObject::PrototypeRegistryCompactionCallback::Callback(Object* value,
   9845                                                              int old_index,
   9846                                                              int new_index) {
   9847   DCHECK(value->IsMap() && Map::cast(value)->is_prototype_map());
   9848   Map* map = Map::cast(value);
   9849   DCHECK(map->prototype_info()->IsPrototypeInfo());
   9850   PrototypeInfo* proto_info = PrototypeInfo::cast(map->prototype_info());
   9851   DCHECK_EQ(old_index, proto_info->registry_slot());
   9852   proto_info->set_registry_slot(new_index);
   9853 }
   9854 
   9855 
   9856 template void WeakFixedArray::Compact<WeakFixedArray::NullCallback>();
   9857 template void
   9858 WeakFixedArray::Compact<JSObject::PrototypeRegistryCompactionCallback>();
   9859 
   9860 
   9861 bool WeakFixedArray::Remove(Handle<HeapObject> value) {
   9862   if (Length() == 0) return false;
   9863   // Optimize for the most recently added element to be removed again.
   9864   int first_index = last_used_index();
   9865   for (int i = first_index;;) {
   9866     if (Get(i) == *value) {
   9867       Clear(i);
   9868       // Users of WeakFixedArray should make sure that there are no duplicates.
   9869       return true;
   9870     }
   9871     i = (i + 1) % Length();
   9872     if (i == first_index) return false;
   9873   }
   9874   UNREACHABLE();
   9875 }
   9876 
   9877 
   9878 // static
   9879 Handle<WeakFixedArray> WeakFixedArray::Allocate(
   9880     Isolate* isolate, int size, Handle<WeakFixedArray> initialize_from) {
   9881   DCHECK(0 <= size);
   9882   Handle<FixedArray> result =
   9883       isolate->factory()->NewUninitializedFixedArray(size + kFirstIndex);
   9884   int index = 0;
   9885   if (!initialize_from.is_null()) {
   9886     DCHECK(initialize_from->Length() <= size);
   9887     Handle<FixedArray> raw_source = Handle<FixedArray>::cast(initialize_from);
   9888     // Copy the entries without compacting, since the PrototypeInfo relies on
   9889     // the index of the entries not to change.
   9890     while (index < raw_source->length()) {
   9891       result->set(index, raw_source->get(index));
   9892       index++;
   9893     }
   9894   }
   9895   while (index < result->length()) {
   9896     result->set(index, Smi::kZero);
   9897     index++;
   9898   }
   9899   return Handle<WeakFixedArray>::cast(result);
   9900 }
   9901 
   9902 
   9903 Handle<ArrayList> ArrayList::Add(Handle<ArrayList> array, Handle<Object> obj,
   9904                                  AddMode mode) {
   9905   int length = array->Length();
   9906   array = EnsureSpace(array, length + 1);
   9907   if (mode == kReloadLengthAfterAllocation) {
   9908     DCHECK(array->Length() <= length);
   9909     length = array->Length();
   9910   }
   9911   array->Set(length, *obj);
   9912   array->SetLength(length + 1);
   9913   return array;
   9914 }
   9915 
   9916 Handle<ArrayList> ArrayList::Add(Handle<ArrayList> array, Handle<Object> obj1,
   9917                                  Handle<Object> obj2, AddMode mode) {
   9918   int length = array->Length();
   9919   array = EnsureSpace(array, length + 2);
   9920   if (mode == kReloadLengthAfterAllocation) {
   9921     length = array->Length();
   9922   }
   9923   array->Set(length, *obj1);
   9924   array->Set(length + 1, *obj2);
   9925   array->SetLength(length + 2);
   9926   return array;
   9927 }
   9928 
   9929 Handle<ArrayList> ArrayList::New(Isolate* isolate, int size) {
   9930   Handle<ArrayList> result = Handle<ArrayList>::cast(
   9931       isolate->factory()->NewFixedArray(size + kFirstIndex));
   9932   result->SetLength(0);
   9933   return result;
   9934 }
   9935 
   9936 bool ArrayList::IsFull() {
   9937   int capacity = length();
   9938   return kFirstIndex + Length() == capacity;
   9939 }
   9940 
   9941 namespace {
   9942 
   9943 Handle<FixedArray> EnsureSpaceInFixedArray(Handle<FixedArray> array,
   9944                                            int length) {
   9945   int capacity = array->length();
   9946   if (capacity < length) {
   9947     Isolate* isolate = array->GetIsolate();
   9948     int new_capacity = length;
   9949     new_capacity = new_capacity + Max(new_capacity / 2, 2);
   9950     int grow_by = new_capacity - capacity;
   9951     array = Handle<ArrayList>::cast(
   9952         isolate->factory()->CopyFixedArrayAndGrow(array, grow_by));
   9953   }
   9954   return array;
   9955 }
   9956 
   9957 }  // namespace
   9958 
   9959 Handle<ArrayList> ArrayList::EnsureSpace(Handle<ArrayList> array, int length) {
   9960   const bool empty = (array->length() == 0);
   9961   auto ret = Handle<ArrayList>::cast(
   9962       EnsureSpaceInFixedArray(array, kFirstIndex + length));
   9963   if (empty) ret->SetLength(0);
   9964   return ret;
   9965 }
   9966 
   9967 Handle<RegExpMatchInfo> RegExpMatchInfo::ReserveCaptures(
   9968     Handle<RegExpMatchInfo> match_info, int capture_count) {
   9969   DCHECK_GE(match_info->length(), kLastMatchOverhead);
   9970   const int required_length = kFirstCaptureIndex + capture_count;
   9971   Handle<FixedArray> result =
   9972       EnsureSpaceInFixedArray(match_info, required_length);
   9973   return Handle<RegExpMatchInfo>::cast(result);
   9974 }
   9975 
   9976 // static
   9977 Handle<FrameArray> FrameArray::AppendJSFrame(Handle<FrameArray> in,
   9978                                              Handle<Object> receiver,
   9979                                              Handle<JSFunction> function,
   9980                                              Handle<AbstractCode> code,
   9981                                              int offset, int flags) {
   9982   const int frame_count = in->FrameCount();
   9983   const int new_length = LengthFor(frame_count + 1);
   9984   Handle<FrameArray> array = EnsureSpace(in, new_length);
   9985   array->SetReceiver(frame_count, *receiver);
   9986   array->SetFunction(frame_count, *function);
   9987   array->SetCode(frame_count, *code);
   9988   array->SetOffset(frame_count, Smi::FromInt(offset));
   9989   array->SetFlags(frame_count, Smi::FromInt(flags));
   9990   array->set(kFrameCountIndex, Smi::FromInt(frame_count + 1));
   9991   return array;
   9992 }
   9993 
   9994 // static
   9995 Handle<FrameArray> FrameArray::AppendWasmFrame(Handle<FrameArray> in,
   9996                                                Handle<Object> wasm_instance,
   9997                                                int wasm_function_index,
   9998                                                Handle<AbstractCode> code,
   9999                                                int offset, int flags) {
   10000   const int frame_count = in->FrameCount();
   10001   const int new_length = LengthFor(frame_count + 1);
   10002   Handle<FrameArray> array = EnsureSpace(in, new_length);
   10003   array->SetWasmInstance(frame_count, *wasm_instance);
   10004   array->SetWasmFunctionIndex(frame_count, Smi::FromInt(wasm_function_index));
   10005   array->SetCode(frame_count, *code);
   10006   array->SetOffset(frame_count, Smi::FromInt(offset));
   10007   array->SetFlags(frame_count, Smi::FromInt(flags));
   10008   array->set(kFrameCountIndex, Smi::FromInt(frame_count + 1));
   10009   return array;
   10010 }
   10011 
   10012 void FrameArray::ShrinkToFit() { Shrink(LengthFor(FrameCount())); }
   10013 
   10014 // static
   10015 Handle<FrameArray> FrameArray::EnsureSpace(Handle<FrameArray> array,
   10016                                            int length) {
   10017   return Handle<FrameArray>::cast(EnsureSpaceInFixedArray(array, length));
   10018 }
   10019 
   10020 Handle<DescriptorArray> DescriptorArray::Allocate(Isolate* isolate,
   10021                                                   int number_of_descriptors,
   10022                                                   int slack,
   10023                                                   PretenureFlag pretenure) {
   10024   DCHECK(0 <= number_of_descriptors);
   10025   Factory* factory = isolate->factory();
   10026   // Do not use DescriptorArray::cast on incomplete object.
   10027   int size = number_of_descriptors + slack;
   10028   if (size == 0) return factory->empty_descriptor_array();
   10029   // Allocate the array of keys.
   10030   Handle<FixedArray> result =
   10031       factory->NewFixedArray(LengthFor(size), pretenure);
   10032 
   10033   result->set(kDescriptorLengthIndex, Smi::FromInt(number_of_descriptors));
   10034   result->set(kEnumCacheIndex, Smi::kZero);
   10035   return Handle<DescriptorArray>::cast(result);
   10036 }
   10037 
   10038 void DescriptorArray::ClearEnumCache() { set(kEnumCacheIndex, Smi::kZero); }
   10039 
   10040 void DescriptorArray::Replace(int index, Descriptor* descriptor) {
   10041   descriptor->SetSortedKeyIndex(GetSortedKeyIndex(index));
   10042   Set(index, descriptor);
   10043 }
   10044 
   10045 
   10046 // static
   10047 void DescriptorArray::SetEnumCache(Handle<DescriptorArray> descriptors,
   10048                                    Isolate* isolate,
   10049                                    Handle<FixedArray> new_cache,
   10050                                    Handle<FixedArray> new_index_cache) {
   10051   DCHECK(!descriptors->IsEmpty());
   10052   FixedArray* bridge_storage;
   10053   bool needs_new_enum_cache = !descriptors->HasEnumCache();
   10054   if (needs_new_enum_cache) {
   10055     bridge_storage = *isolate->factory()->NewFixedArray(
   10056         DescriptorArray::kEnumCacheBridgeLength);
   10057   } else {
   10058     bridge_storage = FixedArray::cast(descriptors->get(kEnumCacheIndex));
   10059   }
   10060   bridge_storage->set(kEnumCacheBridgeCacheIndex, *new_cache);
   10061   bridge_storage->set(
   10062       kEnumCacheBridgeIndicesCacheIndex,
   10063       new_index_cache.is_null() ? Object::cast(Smi::kZero) : *new_index_cache);
   10064   if (needs_new_enum_cache) {
   10065     descriptors->set(kEnumCacheIndex, bridge_storage);
   10066   }
   10067 }
   10068 
   10069 void DescriptorArray::CopyFrom(int index, DescriptorArray* src) {
   10070   PropertyDetails details = src->GetDetails(index);
   10071   Set(index, src->GetKey(index), src->GetValue(index), details);
   10072 }
   10073 
   10074 void DescriptorArray::Sort() {
   10075   // In-place heap sort.
   10076   int len = number_of_descriptors();
   10077   // Reset sorting since the descriptor array might contain invalid pointers.
   10078   for (int i = 0; i < len; ++i) SetSortedKey(i, i);
   10079   // Bottom-up max-heap construction.
   10080   // Index of the last node with children
   10081   const int max_parent_index = (len / 2) - 1;
   10082   for (int i = max_parent_index; i >= 0; --i) {
   10083     int parent_index = i;
   10084     const uint32_t parent_hash = GetSortedKey(i)->Hash();
   10085     while (parent_index <= max_parent_index) {
   10086       int child_index = 2 * parent_index + 1;
   10087       uint32_t child_hash = GetSortedKey(child_index)->Hash();
   10088       if (child_index + 1 < len) {
   10089         uint32_t right_child_hash = GetSortedKey(child_index + 1)->Hash();
   10090         if (right_child_hash > child_hash) {
   10091           child_index++;
   10092           child_hash = right_child_hash;
   10093         }
   10094       }
   10095       if (child_hash <= parent_hash) break;
   10096       SwapSortedKeys(parent_index, child_index);
   10097       // Now element at child_index could be < its children.
   10098       parent_index = child_index;  // parent_hash remains correct.
   10099     }
   10100   }
   10101 
   10102   // Extract elements and create sorted array.
   10103   for (int i = len - 1; i > 0; --i) {
   10104     // Put max element at the back of the array.
   10105     SwapSortedKeys(0, i);
   10106     // Shift down the new top element.
   10107     int parent_index = 0;
   10108     const uint32_t parent_hash = GetSortedKey(parent_index)->Hash();
   10109     const int max_parent_index = (i / 2) - 1;
   10110     while (parent_index <= max_parent_index) {
   10111       int child_index = parent_index * 2 + 1;
   10112       uint32_t child_hash = GetSortedKey(child_index)->Hash();
   10113       if (child_index + 1 < i) {
   10114         uint32_t right_child_hash = GetSortedKey(child_index + 1)->Hash();
   10115         if (right_child_hash > child_hash) {
   10116           child_index++;
   10117           child_hash = right_child_hash;
   10118         }
   10119       }
   10120       if (child_hash <= parent_hash) break;
   10121       SwapSortedKeys(parent_index, child_index);
   10122       parent_index = child_index;
   10123     }
   10124   }
   10125   DCHECK(IsSortedNoDuplicates());
   10126 }
   10127 
   10128 
   10129 Handle<AccessorPair> AccessorPair::Copy(Handle<AccessorPair> pair) {
   10130   Handle<AccessorPair> copy = pair->GetIsolate()->factory()->NewAccessorPair();
   10131   copy->set_getter(pair->getter());
   10132   copy->set_setter(pair->setter());
   10133   return copy;
   10134 }
   10135 
   10136 Handle<Object> AccessorPair::GetComponent(Handle<AccessorPair> accessor_pair,
   10137                                           AccessorComponent component) {
   10138   Object* accessor = accessor_pair->get(component);
   10139   if (accessor->IsFunctionTemplateInfo()) {
   10140     return ApiNatives::InstantiateFunction(
   10141                handle(FunctionTemplateInfo::cast(accessor)))
   10142         .ToHandleChecked();
   10143   }
   10144   Isolate* isolate = accessor_pair->GetIsolate();
   10145   if (accessor->IsNull(isolate)) {
   10146     return isolate->factory()->undefined_value();
   10147   }
   10148   return handle(accessor, isolate);
   10149 }
   10150 
   10151 Handle<DeoptimizationInputData> DeoptimizationInputData::New(
   10152     Isolate* isolate, int deopt_entry_count, PretenureFlag pretenure) {
   10153   return Handle<DeoptimizationInputData>::cast(
   10154       isolate->factory()->NewFixedArray(LengthFor(deopt_entry_count),
   10155                                         pretenure));
   10156 }
   10157 
   10158 
   10159 Handle<DeoptimizationOutputData> DeoptimizationOutputData::New(
   10160     Isolate* isolate,
   10161     int number_of_deopt_points,
   10162     PretenureFlag pretenure) {
   10163   Handle<FixedArray> result;
   10164   if (number_of_deopt_points == 0) {
   10165     result = isolate->factory()->empty_fixed_array();
   10166   } else {
   10167     result = isolate->factory()->NewFixedArray(
   10168         LengthOfFixedArray(number_of_deopt_points), pretenure);
   10169   }
   10170   return Handle<DeoptimizationOutputData>::cast(result);
   10171 }
   10172 
   10173 SharedFunctionInfo* DeoptimizationInputData::GetInlinedFunction(int index) {
   10174   if (index == -1) {
   10175     return SharedFunctionInfo::cast(SharedFunctionInfo());
   10176   } else {
   10177     return SharedFunctionInfo::cast(LiteralArray()->get(index));
   10178   }
   10179 }
   10180 
   10181 int HandlerTable::LookupRange(int pc_offset, int* data_out,
   10182                               CatchPrediction* prediction_out) {
   10183   int innermost_handler = -1;
   10184 #ifdef DEBUG
   10185   // Assuming that ranges are well nested, we don't need to track the innermost
   10186   // offsets. This is just to verify that the table is actually well nested.
   10187   int innermost_start = std::numeric_limits<int>::min();
   10188   int innermost_end = std::numeric_limits<int>::max();
   10189 #endif
   10190   for (int i = 0; i < length(); i += kRangeEntrySize) {
   10191     int start_offset = Smi::cast(get(i + kRangeStartIndex))->value();
   10192     int end_offset = Smi::cast(get(i + kRangeEndIndex))->value();
   10193     int handler_field = Smi::cast(get(i + kRangeHandlerIndex))->value();
   10194     int handler_offset = HandlerOffsetField::decode(handler_field);
   10195     CatchPrediction prediction = HandlerPredictionField::decode(handler_field);
   10196     int handler_data = Smi::cast(get(i + kRangeDataIndex))->value();
   10197     if (pc_offset >= start_offset && pc_offset < end_offset) {
   10198       DCHECK_GE(start_offset, innermost_start);
   10199       DCHECK_LT(end_offset, innermost_end);
   10200       innermost_handler = handler_offset;
   10201 #ifdef DEBUG
   10202       innermost_start = start_offset;
   10203       innermost_end = end_offset;
   10204 #endif
   10205       if (data_out) *data_out = handler_data;
   10206       if (prediction_out) *prediction_out = prediction;
   10207     }
   10208   }
   10209   return innermost_handler;
   10210 }
   10211 
   10212 
   10213 // TODO(turbofan): Make sure table is sorted and use binary search.
   10214 int HandlerTable::LookupReturn(int pc_offset) {
   10215   for (int i = 0; i < length(); i += kReturnEntrySize) {
   10216     int return_offset = Smi::cast(get(i + kReturnOffsetIndex))->value();
   10217     int handler_field = Smi::cast(get(i + kReturnHandlerIndex))->value();
   10218     if (pc_offset == return_offset) {
   10219       return HandlerOffsetField::decode(handler_field);
   10220     }
   10221   }
   10222   return -1;
   10223 }
   10224 
   10225 
   10226 #ifdef DEBUG
   10227 bool DescriptorArray::IsEqualTo(DescriptorArray* other) {
   10228   if (IsEmpty()) return other->IsEmpty();
   10229   if (other->IsEmpty()) return false;
   10230   if (length() != other->length()) return false;
   10231   for (int i = 0; i < length(); ++i) {
   10232     if (get(i) != other->get(i)) return false;
   10233   }
   10234   return true;
   10235 }
   10236 #endif
   10237 
   10238 // static
   10239 Handle<String> String::Trim(Handle<String> string, TrimMode mode) {
   10240   Isolate* const isolate = string->GetIsolate();
   10241   string = String::Flatten(string);
   10242   int const length = string->length();
   10243 
   10244   // Perform left trimming if requested.
   10245   int left = 0;
   10246   UnicodeCache* unicode_cache = isolate->unicode_cache();
   10247   if (mode == kTrim || mode == kTrimLeft) {
   10248     while (left < length &&
   10249            unicode_cache->IsWhiteSpaceOrLineTerminator(string->Get(left))) {
   10250       left++;
   10251     }
   10252   }
   10253 
   10254   // Perform right trimming if requested.
   10255   int right = length;
   10256   if (mode == kTrim || mode == kTrimRight) {
   10257     while (
   10258         right > left &&
   10259         unicode_cache->IsWhiteSpaceOrLineTerminator(string->Get(right - 1))) {
   10260       right--;
   10261     }
   10262   }
   10263 
   10264   return isolate->factory()->NewSubString(string, left, right);
   10265 }
   10266 
   10267 bool String::LooksValid() { return GetIsolate()->heap()->Contains(this); }
   10268 
   10269 // static
   10270 MaybeHandle<String> Name::ToFunctionName(Handle<Name> name) {
   10271   if (name->IsString()) return Handle<String>::cast(name);
   10272   // ES6 section 9.2.11 SetFunctionName, step 4.
   10273   Isolate* const isolate = name->GetIsolate();
   10274   Handle<Object> description(Handle<Symbol>::cast(name)->name(), isolate);
   10275   if (description->IsUndefined(isolate)) {
   10276     return isolate->factory()->empty_string();
   10277   }
   10278   IncrementalStringBuilder builder(isolate);
   10279   builder.AppendCharacter('[');
   10280   builder.AppendString(Handle<String>::cast(description));
   10281   builder.AppendCharacter(']');
   10282   return builder.Finish();
   10283 }
   10284 
   10285 // static
   10286 MaybeHandle<String> Name::ToFunctionName(Handle<Name> name,
   10287                                          Handle<String> prefix) {
   10288   Handle<String> name_string;
   10289   Isolate* const isolate = name->GetIsolate();
   10290   ASSIGN_RETURN_ON_EXCEPTION(isolate, name_string, ToFunctionName(name),
   10291                              String);
   10292   IncrementalStringBuilder builder(isolate);
   10293   builder.AppendString(prefix);
   10294   builder.AppendCharacter(' ');
   10295   builder.AppendString(name_string);
   10296   return builder.Finish();
   10297 }
   10298 
   10299 namespace {
   10300 
   10301 bool AreDigits(const uint8_t* s, int from, int to) {
   10302   for (int i = from; i < to; i++) {
   10303     if (s[i] < '0' || s[i] > '9') return false;
   10304   }
   10305 
   10306   return true;
   10307 }
   10308 
   10309 
   10310 int ParseDecimalInteger(const uint8_t* s, int from, int to) {
   10311   DCHECK(to - from < 10);  // Overflow is not possible.
   10312   DCHECK(from < to);
   10313   int d = s[from] - '0';
   10314 
   10315   for (int i = from + 1; i < to; i++) {
   10316     d = 10 * d + (s[i] - '0');
   10317   }
   10318 
   10319   return d;
   10320 }
   10321 
   10322 }  // namespace
   10323 
   10324 
   10325 // static
   10326 Handle<Object> String::ToNumber(Handle<String> subject) {
   10327   Isolate* const isolate = subject->GetIsolate();
   10328 
   10329   // Flatten {subject} string first.
   10330   subject = String::Flatten(subject);
   10331 
   10332   // Fast array index case.
   10333   uint32_t index;
   10334   if (subject->AsArrayIndex(&index)) {
   10335     return isolate->factory()->NewNumberFromUint(index);
   10336   }
   10337 
   10338   // Fast case: short integer or some sorts of junk values.
   10339   if (subject->IsSeqOneByteString()) {
   10340     int len = subject->length();
   10341     if (len == 0) return handle(Smi::kZero, isolate);
   10342 
   10343     DisallowHeapAllocation no_gc;
   10344     uint8_t const* data = Handle<SeqOneByteString>::cast(subject)->GetChars();
   10345     bool minus = (data[0] == '-');
   10346     int start_pos = (minus ? 1 : 0);
   10347 
   10348     if (start_pos == len) {
   10349       return isolate->factory()->nan_value();
   10350     } else if (data[start_pos] > '9') {
   10351       // Fast check for a junk value. A valid string may start from a
   10352       // whitespace, a sign ('+' or '-'), the decimal point, a decimal digit
   10353       // or the 'I' character ('Infinity'). All of that have codes not greater
   10354       // than '9' except 'I' and &nbsp;.
   10355       if (data[start_pos] != 'I' && data[start_pos] != 0xa0) {
   10356         return isolate->factory()->nan_value();
   10357       }
   10358     } else if (len - start_pos < 10 && AreDigits(data, start_pos, len)) {
   10359       // The maximal/minimal smi has 10 digits. If the string has less digits
   10360       // we know it will fit into the smi-data type.
   10361       int d = ParseDecimalInteger(data, start_pos, len);
   10362       if (minus) {
   10363         if (d == 0) return isolate->factory()->minus_zero_value();
   10364         d = -d;
   10365       } else if (!subject->HasHashCode() && len <= String::kMaxArrayIndexSize &&
   10366                  (len == 1 || data[0] != '0')) {
   10367         // String hash is not calculated yet but all the data are present.
   10368         // Update the hash field to speed up sequential convertions.
   10369         uint32_t hash = StringHasher::MakeArrayIndexHash(d, len);
   10370 #ifdef DEBUG
   10371         subject->Hash();  // Force hash calculation.
   10372         DCHECK_EQ(static_cast<int>(subject->hash_field()),
   10373                   static_cast<int>(hash));
   10374 #endif
   10375         subject->set_hash_field(hash);
   10376       }
   10377       return handle(Smi::FromInt(d), isolate);
   10378     }
   10379   }
   10380 
   10381   // Slower case.
   10382   int flags = ALLOW_HEX | ALLOW_OCTAL | ALLOW_BINARY;
   10383   return isolate->factory()->NewNumber(
   10384       StringToDouble(isolate->unicode_cache(), subject, flags));
   10385 }
   10386 
   10387 
   10388 String::FlatContent String::GetFlatContent() {
   10389   DCHECK(!AllowHeapAllocation::IsAllowed());
   10390   int length = this->length();
   10391   StringShape shape(this);
   10392   String* string = this;
   10393   int offset = 0;
   10394   if (shape.representation_tag() == kConsStringTag) {
   10395     ConsString* cons = ConsString::cast(string);
   10396     if (cons->second()->length() != 0) {
   10397       return FlatContent();
   10398     }
   10399     string = cons->first();
   10400     shape = StringShape(string);
   10401   } else if (shape.representation_tag() == kSlicedStringTag) {
   10402     SlicedString* slice = SlicedString::cast(string);
   10403     offset = slice->offset();
   10404     string = slice->parent();
   10405     shape = StringShape(string);
   10406     DCHECK(shape.representation_tag() != kConsStringTag &&
   10407            shape.representation_tag() != kSlicedStringTag);
   10408   }
   10409   if (shape.representation_tag() == kThinStringTag) {
   10410     ThinString* thin = ThinString::cast(string);
   10411     string = thin->actual();
   10412     shape = StringShape(string);
   10413     DCHECK(!shape.IsCons());
   10414     DCHECK(!shape.IsSliced());
   10415   }
   10416   if (shape.encoding_tag() == kOneByteStringTag) {
   10417     const uint8_t* start;
   10418     if (shape.representation_tag() == kSeqStringTag) {
   10419       start = SeqOneByteString::cast(string)->GetChars();
   10420     } else {
   10421       start = ExternalOneByteString::cast(string)->GetChars();
   10422     }
   10423     return FlatContent(start + offset, length);
   10424   } else {
   10425     DCHECK(shape.encoding_tag() == kTwoByteStringTag);
   10426     const uc16* start;
   10427     if (shape.representation_tag() == kSeqStringTag) {
   10428       start = SeqTwoByteString::cast(string)->GetChars();
   10429     } else {
   10430       start = ExternalTwoByteString::cast(string)->GetChars();
   10431     }
   10432     return FlatContent(start + offset, length);
   10433   }
   10434 }
   10435 
   10436 std::unique_ptr<char[]> String::ToCString(AllowNullsFlag allow_nulls,
   10437                                           RobustnessFlag robust_flag,
   10438                                           int offset, int length,
   10439                                           int* length_return) {
   10440   if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) {
   10441     return std::unique_ptr<char[]>();
   10442   }
   10443   // Negative length means the to the end of the string.
   10444   if (length < 0) length = kMaxInt - offset;
   10445 
   10446   // Compute the size of the UTF-8 string. Start at the specified offset.
   10447   StringCharacterStream stream(this, offset);
   10448   int character_position = offset;
   10449   int utf8_bytes = 0;
   10450   int last = unibrow::Utf16::kNoPreviousCharacter;
   10451   while (stream.HasMore() && character_position++ < offset + length) {
   10452     uint16_t character = stream.GetNext();
   10453     utf8_bytes += unibrow::Utf8::Length(character, last);
   10454     last = character;
   10455   }
   10456 
   10457   if (length_return) {
   10458     *length_return = utf8_bytes;
   10459   }
   10460 
   10461   char* result = NewArray<char>(utf8_bytes + 1);
   10462 
   10463   // Convert the UTF-16 string to a UTF-8 buffer. Start at the specified offset.
   10464   stream.Reset(this, offset);
   10465   character_position = offset;
   10466   int utf8_byte_position = 0;
   10467   last = unibrow::Utf16::kNoPreviousCharacter;
   10468   while (stream.HasMore() && character_position++ < offset + length) {
   10469     uint16_t character = stream.GetNext();
   10470     if (allow_nulls == DISALLOW_NULLS && character == 0) {
   10471       character = ' ';
   10472     }
   10473     utf8_byte_position +=
   10474         unibrow::Utf8::Encode(result + utf8_byte_position, character, last);
   10475     last = character;
   10476   }
   10477   result[utf8_byte_position] = 0;
   10478   return std::unique_ptr<char[]>(result);
   10479 }
   10480 
   10481 std::unique_ptr<char[]> String::ToCString(AllowNullsFlag allow_nulls,
   10482                                           RobustnessFlag robust_flag,
   10483                                           int* length_return) {
   10484   return ToCString(allow_nulls, robust_flag, 0, -1, length_return);
   10485 }
   10486 
   10487 
   10488 const uc16* String::GetTwoByteData(unsigned start) {
   10489   DCHECK(!IsOneByteRepresentationUnderneath());
   10490   switch (StringShape(this).representation_tag()) {
   10491     case kSeqStringTag:
   10492       return SeqTwoByteString::cast(this)->SeqTwoByteStringGetData(start);
   10493     case kExternalStringTag:
   10494       return ExternalTwoByteString::cast(this)->
   10495         ExternalTwoByteStringGetData(start);
   10496     case kSlicedStringTag: {
   10497       SlicedString* slice = SlicedString::cast(this);
   10498       return slice->parent()->GetTwoByteData(start + slice->offset());
   10499     }
   10500     case kConsStringTag:
   10501     case kThinStringTag:
   10502       UNREACHABLE();
   10503       return NULL;
   10504   }
   10505   UNREACHABLE();
   10506   return NULL;
   10507 }
   10508 
   10509 
   10510 const uc16* SeqTwoByteString::SeqTwoByteStringGetData(unsigned start) {
   10511   return reinterpret_cast<uc16*>(
   10512       reinterpret_cast<char*>(this) - kHeapObjectTag + kHeaderSize) + start;
   10513 }
   10514 
   10515 
   10516 void Relocatable::PostGarbageCollectionProcessing(Isolate* isolate) {
   10517   Relocatable* current = isolate->relocatable_top();
   10518   while (current != NULL) {
   10519     current->PostGarbageCollection();
   10520     current = current->prev_;
   10521   }
   10522 }
   10523 
   10524 
   10525 // Reserve space for statics needing saving and restoring.
   10526 int Relocatable::ArchiveSpacePerThread() {
   10527   return sizeof(Relocatable*);  // NOLINT
   10528 }
   10529 
   10530 
   10531 // Archive statics that are thread-local.
   10532 char* Relocatable::ArchiveState(Isolate* isolate, char* to) {
   10533   *reinterpret_cast<Relocatable**>(to) = isolate->relocatable_top();
   10534   isolate->set_relocatable_top(NULL);
   10535   return to + ArchiveSpacePerThread();
   10536 }
   10537 
   10538 
   10539 // Restore statics that are thread-local.
   10540 char* Relocatable::RestoreState(Isolate* isolate, char* from) {
   10541   isolate->set_relocatable_top(*reinterpret_cast<Relocatable**>(from));
   10542   return from + ArchiveSpacePerThread();
   10543 }
   10544 
   10545 
   10546 char* Relocatable::Iterate(ObjectVisitor* v, char* thread_storage) {
   10547   Relocatable* top = *reinterpret_cast<Relocatable**>(thread_storage);
   10548   Iterate(v, top);
   10549   return thread_storage + ArchiveSpacePerThread();
   10550 }
   10551 
   10552 
   10553 void Relocatable::Iterate(Isolate* isolate, ObjectVisitor* v) {
   10554   Iterate(v, isolate->relocatable_top());
   10555 }
   10556 
   10557 
   10558 void Relocatable::Iterate(ObjectVisitor* v, Relocatable* top) {
   10559   Relocatable* current = top;
   10560   while (current != NULL) {
   10561     current->IterateInstance(v);
   10562     current = current->prev_;
   10563   }
   10564 }
   10565 
   10566 
   10567 FlatStringReader::FlatStringReader(Isolate* isolate, Handle<String> str)
   10568     : Relocatable(isolate),
   10569       str_(str.location()),
   10570       length_(str->length()) {
   10571   PostGarbageCollection();
   10572 }
   10573 
   10574 
   10575 FlatStringReader::FlatStringReader(Isolate* isolate, Vector<const char> input)
   10576     : Relocatable(isolate),
   10577       str_(0),
   10578       is_one_byte_(true),
   10579       length_(input.length()),
   10580       start_(input.start()) {}
   10581 
   10582 
   10583 void FlatStringReader::PostGarbageCollection() {
   10584   if (str_ == NULL) return;
   10585   Handle<String> str(str_);
   10586   DCHECK(str->IsFlat());
   10587   DisallowHeapAllocation no_gc;
   10588   // This does not actually prevent the vector from being relocated later.
   10589   String::FlatContent content = str->GetFlatContent();
   10590   DCHECK(content.IsFlat());
   10591   is_one_byte_ = content.IsOneByte();
   10592   if (is_one_byte_) {
   10593     start_ = content.ToOneByteVector().start();
   10594   } else {
   10595     start_ = content.ToUC16Vector().start();
   10596   }
   10597 }
   10598 
   10599 
   10600 void ConsStringIterator::Initialize(ConsString* cons_string, int offset) {
   10601   DCHECK(cons_string != NULL);
   10602   root_ = cons_string;
   10603   consumed_ = offset;
   10604   // Force stack blown condition to trigger restart.
   10605   depth_ = 1;
   10606   maximum_depth_ = kStackSize + depth_;
   10607   DCHECK(StackBlown());
   10608 }
   10609 
   10610 
   10611 String* ConsStringIterator::Continue(int* offset_out) {
   10612   DCHECK(depth_ != 0);
   10613   DCHECK_EQ(0, *offset_out);
   10614   bool blew_stack = StackBlown();
   10615   String* string = NULL;
   10616   // Get the next leaf if there is one.
   10617   if (!blew_stack) string = NextLeaf(&blew_stack);
   10618   // Restart search from root.
   10619   if (blew_stack) {
   10620     DCHECK(string == NULL);
   10621     string = Search(offset_out);
   10622   }
   10623   // Ensure future calls return null immediately.
   10624   if (string == NULL) Reset(NULL);
   10625   return string;
   10626 }
   10627 
   10628 
   10629 String* ConsStringIterator::Search(int* offset_out) {
   10630   ConsString* cons_string = root_;
   10631   // Reset the stack, pushing the root string.
   10632   depth_ = 1;
   10633   maximum_depth_ = 1;
   10634   frames_[0] = cons_string;
   10635   const int consumed = consumed_;
   10636   int offset = 0;
   10637   while (true) {
   10638     // Loop until the string is found which contains the target offset.
   10639     String* string = cons_string->first();
   10640     int length = string->length();
   10641     int32_t type;
   10642     if (consumed < offset + length) {
   10643       // Target offset is in the left branch.
   10644       // Keep going if we're still in a ConString.
   10645       type = string->map()->instance_type();
   10646       if ((type & kStringRepresentationMask) == kConsStringTag) {
   10647         cons_string = ConsString::cast(string);
   10648         PushLeft(cons_string);
   10649         continue;
   10650       }
   10651       // Tell the stack we're done descending.
   10652       AdjustMaximumDepth();
   10653     } else {
   10654       // Descend right.
   10655       // Update progress through the string.
   10656       offset += length;
   10657       // Keep going if we're still in a ConString.
   10658       string = cons_string->second();
   10659       type = string->map()->instance_type();
   10660       if ((type & kStringRepresentationMask) == kConsStringTag) {
   10661         cons_string = ConsString::cast(string);
   10662         PushRight(cons_string);
   10663         continue;
   10664       }
   10665       // Need this to be updated for the current string.
   10666       length = string->length();
   10667       // Account for the possibility of an empty right leaf.
   10668       // This happens only if we have asked for an offset outside the string.
   10669       if (length == 0) {
   10670         // Reset so future operations will return null immediately.
   10671         Reset(NULL);
   10672         return NULL;
   10673       }
   10674       // Tell the stack we're done descending.
   10675       AdjustMaximumDepth();
   10676       // Pop stack so next iteration is in correct place.
   10677       Pop();
   10678     }
   10679     DCHECK(length != 0);
   10680     // Adjust return values and exit.
   10681     consumed_ = offset + length;
   10682     *offset_out = consumed - offset;
   10683     return string;
   10684   }
   10685   UNREACHABLE();
   10686   return NULL;
   10687 }
   10688 
   10689 
   10690 String* ConsStringIterator::NextLeaf(bool* blew_stack) {
   10691   while (true) {
   10692     // Tree traversal complete.
   10693     if (depth_ == 0) {
   10694       *blew_stack = false;
   10695       return NULL;
   10696     }
   10697     // We've lost track of higher nodes.
   10698     if (StackBlown()) {
   10699       *blew_stack = true;
   10700       return NULL;
   10701     }
   10702     // Go right.
   10703     ConsString* cons_string = frames_[OffsetForDepth(depth_ - 1)];
   10704     String* string = cons_string->second();
   10705     int32_t type = string->map()->instance_type();
   10706     if ((type & kStringRepresentationMask) != kConsStringTag) {
   10707       // Pop stack so next iteration is in correct place.
   10708       Pop();
   10709       int length = string->length();
   10710       // Could be a flattened ConsString.
   10711       if (length == 0) continue;
   10712       consumed_ += length;
   10713       return string;
   10714     }
   10715     cons_string = ConsString::cast(string);
   10716     PushRight(cons_string);
   10717     // Need to traverse all the way left.
   10718     while (true) {
   10719       // Continue left.
   10720       string = cons_string->first();
   10721       type = string->map()->instance_type();
   10722       if ((type & kStringRepresentationMask) != kConsStringTag) {
   10723         AdjustMaximumDepth();
   10724         int length = string->length();
   10725         if (length == 0) break;  // Skip empty left-hand sides of ConsStrings.
   10726         consumed_ += length;
   10727         return string;
   10728       }
   10729       cons_string = ConsString::cast(string);
   10730       PushLeft(cons_string);
   10731     }
   10732   }
   10733   UNREACHABLE();
   10734   return NULL;
   10735 }
   10736 
   10737 
   10738 uint16_t ConsString::ConsStringGet(int index) {
   10739   DCHECK(index >= 0 && index < this->length());
   10740 
   10741   // Check for a flattened cons string
   10742   if (second()->length() == 0) {
   10743     String* left = first();
   10744     return left->Get(index);
   10745   }
   10746 
   10747   String* string = String::cast(this);
   10748 
   10749   while (true) {
   10750     if (StringShape(string).IsCons()) {
   10751       ConsString* cons_string = ConsString::cast(string);
   10752       String* left = cons_string->first();
   10753       if (left->length() > index) {
   10754         string = left;
   10755       } else {
   10756         index -= left->length();
   10757         string = cons_string->second();
   10758       }
   10759     } else {
   10760       return string->Get(index);
   10761     }
   10762   }
   10763 
   10764   UNREACHABLE();
   10765   return 0;
   10766 }
   10767 
   10768 uint16_t ThinString::ThinStringGet(int index) { return actual()->Get(index); }
   10769 
   10770 uint16_t SlicedString::SlicedStringGet(int index) {
   10771   return parent()->Get(offset() + index);
   10772 }
   10773 
   10774 
   10775 template <typename sinkchar>
   10776 void String::WriteToFlat(String* src,
   10777                          sinkchar* sink,
   10778                          int f,
   10779                          int t) {
   10780   String* source = src;
   10781   int from = f;
   10782   int to = t;
   10783   while (true) {
   10784     DCHECK(0 <= from && from <= to && to <= source->length());
   10785     switch (StringShape(source).full_representation_tag()) {
   10786       case kOneByteStringTag | kExternalStringTag: {
   10787         CopyChars(sink, ExternalOneByteString::cast(source)->GetChars() + from,
   10788                   to - from);
   10789         return;
   10790       }
   10791       case kTwoByteStringTag | kExternalStringTag: {
   10792         const uc16* data =
   10793             ExternalTwoByteString::cast(source)->GetChars();
   10794         CopyChars(sink,
   10795                   data + from,
   10796                   to - from);
   10797         return;
   10798       }
   10799       case kOneByteStringTag | kSeqStringTag: {
   10800         CopyChars(sink,
   10801                   SeqOneByteString::cast(source)->GetChars() + from,
   10802                   to - from);
   10803         return;
   10804       }
   10805       case kTwoByteStringTag | kSeqStringTag: {
   10806         CopyChars(sink,
   10807                   SeqTwoByteString::cast(source)->GetChars() + from,
   10808                   to - from);
   10809         return;
   10810       }
   10811       case kOneByteStringTag | kConsStringTag:
   10812       case kTwoByteStringTag | kConsStringTag: {
   10813         ConsString* cons_string = ConsString::cast(source);
   10814         String* first = cons_string->first();
   10815         int boundary = first->length();
   10816         if (to - boundary >= boundary - from) {
   10817           // Right hand side is longer.  Recurse over left.
   10818           if (from < boundary) {
   10819             WriteToFlat(first, sink, from, boundary);
   10820             if (from == 0 && cons_string->second() == first) {
   10821               CopyChars(sink + boundary, sink, boundary);
   10822               return;
   10823             }
   10824             sink += boundary - from;
   10825             from = 0;
   10826           } else {
   10827             from -= boundary;
   10828           }
   10829           to -= boundary;
   10830           source = cons_string->second();
   10831         } else {
   10832           // Left hand side is longer.  Recurse over right.
   10833           if (to > boundary) {
   10834             String* second = cons_string->second();
   10835             // When repeatedly appending to a string, we get a cons string that
   10836             // is unbalanced to the left, a list, essentially.  We inline the
   10837             // common case of sequential one-byte right child.
   10838             if (to - boundary == 1) {
   10839               sink[boundary - from] = static_cast<sinkchar>(second->Get(0));
   10840             } else if (second->IsSeqOneByteString()) {
   10841               CopyChars(sink + boundary - from,
   10842                         SeqOneByteString::cast(second)->GetChars(),
   10843                         to - boundary);
   10844             } else {
   10845               WriteToFlat(second,
   10846                           sink + boundary - from,
   10847                           0,
   10848                           to - boundary);
   10849             }
   10850             to = boundary;
   10851           }
   10852           source = first;
   10853         }
   10854         break;
   10855       }
   10856       case kOneByteStringTag | kSlicedStringTag:
   10857       case kTwoByteStringTag | kSlicedStringTag: {
   10858         SlicedString* slice = SlicedString::cast(source);
   10859         unsigned offset = slice->offset();
   10860         WriteToFlat(slice->parent(), sink, from + offset, to + offset);
   10861         return;
   10862       }
   10863       case kOneByteStringTag | kThinStringTag:
   10864       case kTwoByteStringTag | kThinStringTag:
   10865         source = ThinString::cast(source)->actual();
   10866         break;
   10867     }
   10868   }
   10869 }
   10870 
   10871 
   10872 
   10873 template <typename SourceChar>
   10874 static void CalculateLineEndsImpl(Isolate* isolate,
   10875                                   List<int>* line_ends,
   10876                                   Vector<const SourceChar> src,
   10877                                   bool include_ending_line) {
   10878   const int src_len = src.length();
   10879   UnicodeCache* cache = isolate->unicode_cache();
   10880   for (int i = 0; i < src_len - 1; i++) {
   10881     SourceChar current = src[i];
   10882     SourceChar next = src[i + 1];
   10883     if (cache->IsLineTerminatorSequence(current, next)) line_ends->Add(i);
   10884   }
   10885 
   10886   if (src_len > 0 && cache->IsLineTerminatorSequence(src[src_len - 1], 0)) {
   10887     line_ends->Add(src_len - 1);
   10888   }
   10889   if (include_ending_line) {
   10890     // Include one character beyond the end of script. The rewriter uses that
   10891     // position for the implicit return statement.
   10892     line_ends->Add(src_len);
   10893   }
   10894 }
   10895 
   10896 
   10897 Handle<FixedArray> String::CalculateLineEnds(Handle<String> src,
   10898                                              bool include_ending_line) {
   10899   src = Flatten(src);
   10900   // Rough estimate of line count based on a roughly estimated average
   10901   // length of (unpacked) code.
   10902   int line_count_estimate = src->length() >> 4;
   10903   List<int> line_ends(line_count_estimate);
   10904   Isolate* isolate = src->GetIsolate();
   10905   { DisallowHeapAllocation no_allocation;  // ensure vectors stay valid.
   10906     // Dispatch on type of strings.
   10907     String::FlatContent content = src->GetFlatContent();
   10908     DCHECK(content.IsFlat());
   10909     if (content.IsOneByte()) {
   10910       CalculateLineEndsImpl(isolate,
   10911                             &line_ends,
   10912                             content.ToOneByteVector(),
   10913                             include_ending_line);
   10914     } else {
   10915       CalculateLineEndsImpl(isolate,
   10916                             &line_ends,
   10917                             content.ToUC16Vector(),
   10918                             include_ending_line);
   10919     }
   10920   }
   10921   int line_count = line_ends.length();
   10922   Handle<FixedArray> array = isolate->factory()->NewFixedArray(line_count);
   10923   for (int i = 0; i < line_count; i++) {
   10924     array->set(i, Smi::FromInt(line_ends[i]));
   10925   }
   10926   return array;
   10927 }
   10928 
   10929 
   10930 // Compares the contents of two strings by reading and comparing
   10931 // int-sized blocks of characters.
   10932 template <typename Char>
   10933 static inline bool CompareRawStringContents(const Char* const a,
   10934                                             const Char* const b,
   10935                                             int length) {
   10936   return CompareChars(a, b, length) == 0;
   10937 }
   10938 
   10939 
   10940 template<typename Chars1, typename Chars2>
   10941 class RawStringComparator : public AllStatic {
   10942  public:
   10943   static inline bool compare(const Chars1* a, const Chars2* b, int len) {
   10944     DCHECK(sizeof(Chars1) != sizeof(Chars2));
   10945     for (int i = 0; i < len; i++) {
   10946       if (a[i] != b[i]) {
   10947         return false;
   10948       }
   10949     }
   10950     return true;
   10951   }
   10952 };
   10953 
   10954 
   10955 template<>
   10956 class RawStringComparator<uint16_t, uint16_t> {
   10957  public:
   10958   static inline bool compare(const uint16_t* a, const uint16_t* b, int len) {
   10959     return CompareRawStringContents(a, b, len);
   10960   }
   10961 };
   10962 
   10963 
   10964 template<>
   10965 class RawStringComparator<uint8_t, uint8_t> {
   10966  public:
   10967   static inline bool compare(const uint8_t* a, const uint8_t* b, int len) {
   10968     return CompareRawStringContents(a, b, len);
   10969   }
   10970 };
   10971 
   10972 
   10973 class StringComparator {
   10974   class State {
   10975    public:
   10976     State() : is_one_byte_(true), length_(0), buffer8_(NULL) {}
   10977 
   10978     void Init(String* string) {
   10979       ConsString* cons_string = String::VisitFlat(this, string);
   10980       iter_.Reset(cons_string);
   10981       if (cons_string != NULL) {
   10982         int offset;
   10983         string = iter_.Next(&offset);
   10984         String::VisitFlat(this, string, offset);
   10985       }
   10986     }
   10987 
   10988     inline void VisitOneByteString(const uint8_t* chars, int length) {
   10989       is_one_byte_ = true;
   10990       buffer8_ = chars;
   10991       length_ = length;
   10992     }
   10993 
   10994     inline void VisitTwoByteString(const uint16_t* chars, int length) {
   10995       is_one_byte_ = false;
   10996       buffer16_ = chars;
   10997       length_ = length;
   10998     }
   10999 
   11000     void Advance(int consumed) {
   11001       DCHECK(consumed <= length_);
   11002       // Still in buffer.
   11003       if (length_ != consumed) {
   11004         if (is_one_byte_) {
   11005           buffer8_ += consumed;
   11006         } else {
   11007           buffer16_ += consumed;
   11008         }
   11009         length_ -= consumed;
   11010         return;
   11011       }
   11012       // Advance state.
   11013       int offset;
   11014       String* next = iter_.Next(&offset);
   11015       DCHECK_EQ(0, offset);
   11016       DCHECK(next != NULL);
   11017       String::VisitFlat(this, next);
   11018     }
   11019 
   11020     ConsStringIterator iter_;
   11021     bool is_one_byte_;
   11022     int length_;
   11023     union {
   11024       const uint8_t* buffer8_;
   11025       const uint16_t* buffer16_;
   11026     };
   11027 
   11028    private:
   11029     DISALLOW_COPY_AND_ASSIGN(State);
   11030   };
   11031 
   11032  public:
   11033   inline StringComparator() {}
   11034 
   11035   template<typename Chars1, typename Chars2>
   11036   static inline bool Equals(State* state_1, State* state_2, int to_check) {
   11037     const Chars1* a = reinterpret_cast<const Chars1*>(state_1->buffer8_);
   11038     const Chars2* b = reinterpret_cast<const Chars2*>(state_2->buffer8_);
   11039     return RawStringComparator<Chars1, Chars2>::compare(a, b, to_check);
   11040   }
   11041 
   11042   bool Equals(String* string_1, String* string_2) {
   11043     int length = string_1->length();
   11044     state_1_.Init(string_1);
   11045     state_2_.Init(string_2);
   11046     while (true) {
   11047       int to_check = Min(state_1_.length_, state_2_.length_);
   11048       DCHECK(to_check > 0 && to_check <= length);
   11049       bool is_equal;
   11050       if (state_1_.is_one_byte_) {
   11051         if (state_2_.is_one_byte_) {
   11052           is_equal = Equals<uint8_t, uint8_t>(&state_1_, &state_2_, to_check);
   11053         } else {
   11054           is_equal = Equals<uint8_t, uint16_t>(&state_1_, &state_2_, to_check);
   11055         }
   11056       } else {
   11057         if (state_2_.is_one_byte_) {
   11058           is_equal = Equals<uint16_t, uint8_t>(&state_1_, &state_2_, to_check);
   11059         } else {
   11060           is_equal = Equals<uint16_t, uint16_t>(&state_1_, &state_2_, to_check);
   11061         }
   11062       }
   11063       // Looping done.
   11064       if (!is_equal) return false;
   11065       length -= to_check;
   11066       // Exit condition. Strings are equal.
   11067       if (length == 0) return true;
   11068       state_1_.Advance(to_check);
   11069       state_2_.Advance(to_check);
   11070     }
   11071   }
   11072 
   11073  private:
   11074   State state_1_;
   11075   State state_2_;
   11076 
   11077   DISALLOW_COPY_AND_ASSIGN(StringComparator);
   11078 };
   11079 
   11080 
   11081 bool String::SlowEquals(String* other) {
   11082   DisallowHeapAllocation no_gc;
   11083   // Fast check: negative check with lengths.
   11084   int len = length();
   11085   if (len != other->length()) return false;
   11086   if (len == 0) return true;
   11087 
   11088   // Fast check: if at least one ThinString is involved, dereference it/them
   11089   // and restart.
   11090   if (this->IsThinString() || other->IsThinString()) {
   11091     if (other->IsThinString()) other = ThinString::cast(other)->actual();
   11092     if (this->IsThinString()) {
   11093       return ThinString::cast(this)->actual()->Equals(other);
   11094     } else {
   11095       return this->Equals(other);
   11096     }
   11097   }
   11098 
   11099   // Fast check: if hash code is computed for both strings
   11100   // a fast negative check can be performed.
   11101   if (HasHashCode() && other->HasHashCode()) {
   11102 #ifdef ENABLE_SLOW_DCHECKS
   11103     if (FLAG_enable_slow_asserts) {
   11104       if (Hash() != other->Hash()) {
   11105         bool found_difference = false;
   11106         for (int i = 0; i < len; i++) {
   11107           if (Get(i) != other->Get(i)) {
   11108             found_difference = true;
   11109             break;
   11110           }
   11111         }
   11112         DCHECK(found_difference);
   11113       }
   11114     }
   11115 #endif
   11116     if (Hash() != other->Hash()) return false;
   11117   }
   11118 
   11119   // We know the strings are both non-empty. Compare the first chars
   11120   // before we try to flatten the strings.
   11121   if (this->Get(0) != other->Get(0)) return false;
   11122 
   11123   if (IsSeqOneByteString() && other->IsSeqOneByteString()) {
   11124     const uint8_t* str1 = SeqOneByteString::cast(this)->GetChars();
   11125     const uint8_t* str2 = SeqOneByteString::cast(other)->GetChars();
   11126     return CompareRawStringContents(str1, str2, len);
   11127   }
   11128 
   11129   StringComparator comparator;
   11130   return comparator.Equals(this, other);
   11131 }
   11132 
   11133 
   11134 bool String::SlowEquals(Handle<String> one, Handle<String> two) {
   11135   // Fast check: negative check with lengths.
   11136   int one_length = one->length();
   11137   if (one_length != two->length()) return false;
   11138   if (one_length == 0) return true;
   11139 
   11140   // Fast check: if at least one ThinString is involved, dereference it/them
   11141   // and restart.
   11142   if (one->IsThinString() || two->IsThinString()) {
   11143     if (one->IsThinString()) one = handle(ThinString::cast(*one)->actual());
   11144     if (two->IsThinString()) two = handle(ThinString::cast(*two)->actual());
   11145     return String::Equals(one, two);
   11146   }
   11147 
   11148   // Fast check: if hash code is computed for both strings
   11149   // a fast negative check can be performed.
   11150   if (one->HasHashCode() && two->HasHashCode()) {
   11151 #ifdef ENABLE_SLOW_DCHECKS
   11152     if (FLAG_enable_slow_asserts) {
   11153       if (one->Hash() != two->Hash()) {
   11154         bool found_difference = false;
   11155         for (int i = 0; i < one_length; i++) {
   11156           if (one->Get(i) != two->Get(i)) {
   11157             found_difference = true;
   11158             break;
   11159           }
   11160         }
   11161         DCHECK(found_difference);
   11162       }
   11163     }
   11164 #endif
   11165     if (one->Hash() != two->Hash()) return false;
   11166   }
   11167 
   11168   // We know the strings are both non-empty. Compare the first chars
   11169   // before we try to flatten the strings.
   11170   if (one->Get(0) != two->Get(0)) return false;
   11171 
   11172   one = String::Flatten(one);
   11173   two = String::Flatten(two);
   11174 
   11175   DisallowHeapAllocation no_gc;
   11176   String::FlatContent flat1 = one->GetFlatContent();
   11177   String::FlatContent flat2 = two->GetFlatContent();
   11178 
   11179   if (flat1.IsOneByte() && flat2.IsOneByte()) {
   11180       return CompareRawStringContents(flat1.ToOneByteVector().start(),
   11181                                       flat2.ToOneByteVector().start(),
   11182                                       one_length);
   11183   } else {
   11184     for (int i = 0; i < one_length; i++) {
   11185       if (flat1.Get(i) != flat2.Get(i)) return false;
   11186     }
   11187     return true;
   11188   }
   11189 }
   11190 
   11191 
   11192 // static
   11193 ComparisonResult String::Compare(Handle<String> x, Handle<String> y) {
   11194   // A few fast case tests before we flatten.
   11195   if (x.is_identical_to(y)) {
   11196     return ComparisonResult::kEqual;
   11197   } else if (y->length() == 0) {
   11198     return x->length() == 0 ? ComparisonResult::kEqual
   11199                             : ComparisonResult::kGreaterThan;
   11200   } else if (x->length() == 0) {
   11201     return ComparisonResult::kLessThan;
   11202   }
   11203 
   11204   int const d = x->Get(0) - y->Get(0);
   11205   if (d < 0) {
   11206     return ComparisonResult::kLessThan;
   11207   } else if (d > 0) {
   11208     return ComparisonResult::kGreaterThan;
   11209   }
   11210 
   11211   // Slow case.
   11212   x = String::Flatten(x);
   11213   y = String::Flatten(y);
   11214 
   11215   DisallowHeapAllocation no_gc;
   11216   ComparisonResult result = ComparisonResult::kEqual;
   11217   int prefix_length = x->length();
   11218   if (y->length() < prefix_length) {
   11219     prefix_length = y->length();
   11220     result = ComparisonResult::kGreaterThan;
   11221   } else if (y->length() > prefix_length) {
   11222     result = ComparisonResult::kLessThan;
   11223   }
   11224   int r;
   11225   String::FlatContent x_content = x->GetFlatContent();
   11226   String::FlatContent y_content = y->GetFlatContent();
   11227   if (x_content.IsOneByte()) {
   11228     Vector<const uint8_t> x_chars = x_content.ToOneByteVector();
   11229     if (y_content.IsOneByte()) {
   11230       Vector<const uint8_t> y_chars = y_content.ToOneByteVector();
   11231       r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
   11232     } else {
   11233       Vector<const uc16> y_chars = y_content.ToUC16Vector();
   11234       r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
   11235     }
   11236   } else {
   11237     Vector<const uc16> x_chars = x_content.ToUC16Vector();
   11238     if (y_content.IsOneByte()) {
   11239       Vector<const uint8_t> y_chars = y_content.ToOneByteVector();
   11240       r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
   11241     } else {
   11242       Vector<const uc16> y_chars = y_content.ToUC16Vector();
   11243       r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
   11244     }
   11245   }
   11246   if (r < 0) {
   11247     result = ComparisonResult::kLessThan;
   11248   } else if (r > 0) {
   11249     result = ComparisonResult::kGreaterThan;
   11250   }
   11251   return result;
   11252 }
   11253 
   11254 Object* String::IndexOf(Isolate* isolate, Handle<Object> receiver,
   11255                         Handle<Object> search, Handle<Object> position) {
   11256   if (receiver->IsNullOrUndefined(isolate)) {
   11257     THROW_NEW_ERROR_RETURN_FAILURE(
   11258         isolate, NewTypeError(MessageTemplate::kCalledOnNullOrUndefined,
   11259                               isolate->factory()->NewStringFromAsciiChecked(
   11260                                   "String.prototype.indexOf")));
   11261   }
   11262   Handle<String> receiver_string;
   11263   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver_string,
   11264                                      Object::ToString(isolate, receiver));
   11265 
   11266   Handle<String> search_string;
   11267   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, search_string,
   11268                                      Object::ToString(isolate, search));
   11269 
   11270   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, position,
   11271                                      Object::ToInteger(isolate, position));
   11272 
   11273   uint32_t index = receiver_string->ToValidIndex(*position);
   11274   return Smi::FromInt(
   11275       String::IndexOf(isolate, receiver_string, search_string, index));
   11276 }
   11277 
   11278 namespace {
   11279 
   11280 template <typename T>
   11281 int SearchString(Isolate* isolate, String::FlatContent receiver_content,
   11282                  Vector<T> pat_vector, int start_index) {
   11283   if (receiver_content.IsOneByte()) {
   11284     return SearchString(isolate, receiver_content.ToOneByteVector(), pat_vector,
   11285                         start_index);
   11286   }
   11287   return SearchString(isolate, receiver_content.ToUC16Vector(), pat_vector,
   11288                       start_index);
   11289 }
   11290 
   11291 }  // namespace
   11292 
   11293 int String::IndexOf(Isolate* isolate, Handle<String> receiver,
   11294                     Handle<String> search, int start_index) {
   11295   DCHECK(0 <= start_index);
   11296   DCHECK(start_index <= receiver->length());
   11297 
   11298   uint32_t search_length = search->length();
   11299   if (search_length == 0) return start_index;
   11300 
   11301   uint32_t receiver_length = receiver->length();
   11302   if (start_index + search_length > receiver_length) return -1;
   11303 
   11304   receiver = String::Flatten(receiver);
   11305   search = String::Flatten(search);
   11306 
   11307   DisallowHeapAllocation no_gc;  // ensure vectors stay valid
   11308   // Extract flattened substrings of cons strings before getting encoding.
   11309   String::FlatContent receiver_content = receiver->GetFlatContent();
   11310   String::FlatContent search_content = search->GetFlatContent();
   11311 
   11312   // dispatch on type of strings
   11313   if (search_content.IsOneByte()) {
   11314     Vector<const uint8_t> pat_vector = search_content.ToOneByteVector();
   11315     return SearchString<const uint8_t>(isolate, receiver_content, pat_vector,
   11316                                        start_index);
   11317   }
   11318   Vector<const uc16> pat_vector = search_content.ToUC16Vector();
   11319   return SearchString<const uc16>(isolate, receiver_content, pat_vector,
   11320                                   start_index);
   11321 }
   11322 
   11323 MaybeHandle<String> String::GetSubstitution(Isolate* isolate, Match* match,
   11324                                             Handle<String> replacement) {
   11325   Factory* factory = isolate->factory();
   11326 
   11327   const int replacement_length = replacement->length();
   11328   const int captures_length = match->CaptureCount();
   11329 
   11330   replacement = String::Flatten(replacement);
   11331 
   11332   Handle<String> dollar_string =
   11333       factory->LookupSingleCharacterStringFromCode('$');
   11334   int next = String::IndexOf(isolate, replacement, dollar_string, 0);
   11335   if (next < 0) {
   11336     return replacement;
   11337   }
   11338 
   11339   IncrementalStringBuilder builder(isolate);
   11340 
   11341   if (next > 0) {
   11342     builder.AppendString(factory->NewSubString(replacement, 0, next));
   11343   }
   11344 
   11345   while (true) {
   11346     int pos = next + 1;
   11347     if (pos < replacement_length) {
   11348       const uint16_t peek = replacement->Get(pos);
   11349       if (peek == '$') {  // $$
   11350         pos++;
   11351         builder.AppendCharacter('$');
   11352       } else if (peek == '&') {  // $& - match
   11353         pos++;
   11354         builder.AppendString(match->GetMatch());
   11355       } else if (peek == '`') {  // $` - prefix
   11356         pos++;
   11357         builder.AppendString(match->GetPrefix());
   11358       } else if (peek == '\'') {  // $' - suffix
   11359         pos++;
   11360         builder.AppendString(match->GetSuffix());
   11361       } else if (peek >= '0' && peek <= '9') {
   11362         // Valid indices are $1 .. $9, $01 .. $09 and $10 .. $99
   11363         int scaled_index = (peek - '0');
   11364         int advance = 1;
   11365 
   11366         if (pos + 1 < replacement_length) {
   11367           const uint16_t next_peek = replacement->Get(pos + 1);
   11368           if (next_peek >= '0' && next_peek <= '9') {
   11369             const int new_scaled_index = scaled_index * 10 + (next_peek - '0');
   11370             if (new_scaled_index < captures_length) {
   11371               scaled_index = new_scaled_index;
   11372               advance = 2;
   11373             }
   11374           }
   11375         }
   11376 
   11377         if (scaled_index != 0 && scaled_index < captures_length) {
   11378           bool capture_exists;
   11379           Handle<String> capture;
   11380           ASSIGN_RETURN_ON_EXCEPTION(
   11381               isolate, capture,
   11382               match->GetCapture(scaled_index, &capture_exists), String);
   11383           if (capture_exists) builder.AppendString(capture);
   11384           pos += advance;
   11385         } else {
   11386           builder.AppendCharacter('$');
   11387         }
   11388       } else {
   11389         builder.AppendCharacter('$');
   11390       }
   11391     } else {
   11392       builder.AppendCharacter('$');
   11393     }
   11394 
   11395     // Go the the next $ in the replacement.
   11396     next = String::IndexOf(isolate, replacement, dollar_string, pos);
   11397 
   11398     // Return if there are no more $ characters in the replacement. If we
   11399     // haven't reached the end, we need to append the suffix.
   11400     if (next < 0) {
   11401       if (pos < replacement_length) {
   11402         builder.AppendString(
   11403             factory->NewSubString(replacement, pos, replacement_length));
   11404       }
   11405       return builder.Finish();
   11406     }
   11407 
   11408     // Append substring between the previous and the next $ character.
   11409     if (next > pos) {
   11410       builder.AppendString(factory->NewSubString(replacement, pos, next));
   11411     }
   11412   }
   11413 
   11414   UNREACHABLE();
   11415   return MaybeHandle<String>();
   11416 }
   11417 
   11418 namespace {  // for String.Prototype.lastIndexOf
   11419 
   11420 template <typename schar, typename pchar>
   11421 int StringMatchBackwards(Vector<const schar> subject,
   11422                          Vector<const pchar> pattern, int idx) {
   11423   int pattern_length = pattern.length();
   11424   DCHECK(pattern_length >= 1);
   11425   DCHECK(idx + pattern_length <= subject.length());
   11426 
   11427   if (sizeof(schar) == 1 && sizeof(pchar) > 1) {
   11428     for (int i = 0; i < pattern_length; i++) {
   11429       uc16 c = pattern[i];
   11430       if (c > String::kMaxOneByteCharCode) {
   11431         return -1;
   11432       }
   11433     }
   11434   }
   11435 
   11436   pchar pattern_first_char = pattern[0];
   11437   for (int i = idx; i >= 0; i--) {
   11438     if (subject[i] != pattern_first_char) continue;
   11439     int j = 1;
   11440     while (j < pattern_length) {
   11441       if (pattern[j] != subject[i + j]) {
   11442         break;
   11443       }
   11444       j++;
   11445     }
   11446     if (j == pattern_length) {
   11447       return i;
   11448     }
   11449   }
   11450   return -1;
   11451 }
   11452 
   11453 }  // namespace
   11454 
   11455 Object* String::LastIndexOf(Isolate* isolate, Handle<Object> receiver,
   11456                             Handle<Object> search, Handle<Object> position) {
   11457   if (receiver->IsNullOrUndefined(isolate)) {
   11458     THROW_NEW_ERROR_RETURN_FAILURE(
   11459         isolate, NewTypeError(MessageTemplate::kCalledOnNullOrUndefined,
   11460                               isolate->factory()->NewStringFromAsciiChecked(
   11461                                   "String.prototype.lastIndexOf")));
   11462   }
   11463   Handle<String> receiver_string;
   11464   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver_string,
   11465                                      Object::ToString(isolate, receiver));
   11466 
   11467   Handle<String> search_string;
   11468   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, search_string,
   11469                                      Object::ToString(isolate, search));
   11470 
   11471   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, position,
   11472                                      Object::ToNumber(position));
   11473 
   11474   uint32_t start_index;
   11475 
   11476   if (position->IsNaN()) {
   11477     start_index = receiver_string->length();
   11478   } else {
   11479     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, position,
   11480                                        Object::ToInteger(isolate, position));
   11481     start_index = receiver_string->ToValidIndex(*position);
   11482   }
   11483 
   11484   uint32_t pattern_length = search_string->length();
   11485   uint32_t receiver_length = receiver_string->length();
   11486 
   11487   if (start_index + pattern_length > receiver_length) {
   11488     start_index = receiver_length - pattern_length;
   11489   }
   11490 
   11491   if (pattern_length == 0) {
   11492     return Smi::FromInt(start_index);
   11493   }
   11494 
   11495   receiver_string = String::Flatten(receiver_string);
   11496   search_string = String::Flatten(search_string);
   11497 
   11498   int last_index = -1;
   11499   DisallowHeapAllocation no_gc;  // ensure vectors stay valid
   11500 
   11501   String::FlatContent receiver_content = receiver_string->GetFlatContent();
   11502   String::FlatContent search_content = search_string->GetFlatContent();
   11503 
   11504   if (search_content.IsOneByte()) {
   11505     Vector<const uint8_t> pat_vector = search_content.ToOneByteVector();
   11506     if (receiver_content.IsOneByte()) {
   11507       last_index = StringMatchBackwards(receiver_content.ToOneByteVector(),
   11508                                         pat_vector, start_index);
   11509     } else {
   11510       last_index = StringMatchBackwards(receiver_content.ToUC16Vector(),
   11511                                         pat_vector, start_index);
   11512     }
   11513   } else {
   11514     Vector<const uc16> pat_vector = search_content.ToUC16Vector();
   11515     if (receiver_content.IsOneByte()) {
   11516       last_index = StringMatchBackwards(receiver_content.ToOneByteVector(),
   11517                                         pat_vector, start_index);
   11518     } else {
   11519       last_index = StringMatchBackwards(receiver_content.ToUC16Vector(),
   11520                                         pat_vector, start_index);
   11521     }
   11522   }
   11523   return Smi::FromInt(last_index);
   11524 }
   11525 
   11526 bool String::IsUtf8EqualTo(Vector<const char> str, bool allow_prefix_match) {
   11527   int slen = length();
   11528   // Can't check exact length equality, but we can check bounds.
   11529   int str_len = str.length();
   11530   if (!allow_prefix_match &&
   11531       (str_len < slen ||
   11532           str_len > slen*static_cast<int>(unibrow::Utf8::kMaxEncodedSize))) {
   11533     return false;
   11534   }
   11535   int i;
   11536   size_t remaining_in_str = static_cast<size_t>(str_len);
   11537   const uint8_t* utf8_data = reinterpret_cast<const uint8_t*>(str.start());
   11538   for (i = 0; i < slen && remaining_in_str > 0; i++) {
   11539     size_t cursor = 0;
   11540     uint32_t r = unibrow::Utf8::ValueOf(utf8_data, remaining_in_str, &cursor);
   11541     DCHECK(cursor > 0 && cursor <= remaining_in_str);
   11542     if (r > unibrow::Utf16::kMaxNonSurrogateCharCode) {
   11543       if (i > slen - 1) return false;
   11544       if (Get(i++) != unibrow::Utf16::LeadSurrogate(r)) return false;
   11545       if (Get(i) != unibrow::Utf16::TrailSurrogate(r)) return false;
   11546     } else {
   11547       if (Get(i) != r) return false;
   11548     }
   11549     utf8_data += cursor;
   11550     remaining_in_str -= cursor;
   11551   }
   11552   return (allow_prefix_match || i == slen) && remaining_in_str == 0;
   11553 }
   11554 
   11555 
   11556 bool String::IsOneByteEqualTo(Vector<const uint8_t> str) {
   11557   int slen = length();
   11558   if (str.length() != slen) return false;
   11559   DisallowHeapAllocation no_gc;
   11560   FlatContent content = GetFlatContent();
   11561   if (content.IsOneByte()) {
   11562     return CompareChars(content.ToOneByteVector().start(),
   11563                         str.start(), slen) == 0;
   11564   }
   11565   for (int i = 0; i < slen; i++) {
   11566     if (Get(i) != static_cast<uint16_t>(str[i])) return false;
   11567   }
   11568   return true;
   11569 }
   11570 
   11571 
   11572 bool String::IsTwoByteEqualTo(Vector<const uc16> str) {
   11573   int slen = length();
   11574   if (str.length() != slen) return false;
   11575   DisallowHeapAllocation no_gc;
   11576   FlatContent content = GetFlatContent();
   11577   if (content.IsTwoByte()) {
   11578     return CompareChars(content.ToUC16Vector().start(), str.start(), slen) == 0;
   11579   }
   11580   for (int i = 0; i < slen; i++) {
   11581     if (Get(i) != str[i]) return false;
   11582   }
   11583   return true;
   11584 }
   11585 
   11586 
   11587 uint32_t String::ComputeAndSetHash() {
   11588   // Should only be called if hash code has not yet been computed.
   11589   DCHECK(!HasHashCode());
   11590 
   11591   // Store the hash code in the object.
   11592   uint32_t field = IteratingStringHasher::Hash(this, GetHeap()->HashSeed());
   11593   set_hash_field(field);
   11594 
   11595   // Check the hash code is there.
   11596   DCHECK(HasHashCode());
   11597   uint32_t result = field >> kHashShift;
   11598   DCHECK(result != 0);  // Ensure that the hash value of 0 is never computed.
   11599   return result;
   11600 }
   11601 
   11602 
   11603 bool String::ComputeArrayIndex(uint32_t* index) {
   11604   int length = this->length();
   11605   if (length == 0 || length > kMaxArrayIndexSize) return false;
   11606   StringCharacterStream stream(this);
   11607   return StringToArrayIndex(&stream, index);
   11608 }
   11609 
   11610 
   11611 bool String::SlowAsArrayIndex(uint32_t* index) {
   11612   if (length() <= kMaxCachedArrayIndexLength) {
   11613     Hash();  // force computation of hash code
   11614     uint32_t field = hash_field();
   11615     if ((field & kIsNotArrayIndexMask) != 0) return false;
   11616     // Isolate the array index form the full hash field.
   11617     *index = ArrayIndexValueBits::decode(field);
   11618     return true;
   11619   } else {
   11620     return ComputeArrayIndex(index);
   11621   }
   11622 }
   11623 
   11624 
   11625 Handle<String> SeqString::Truncate(Handle<SeqString> string, int new_length) {
   11626   Heap* heap = string->GetHeap();
   11627   if (new_length == 0) return heap->isolate()->factory()->empty_string();
   11628 
   11629   int new_size, old_size;
   11630   int old_length = string->length();
   11631   if (old_length <= new_length) return string;
   11632 
   11633   if (string->IsSeqOneByteString()) {
   11634     old_size = SeqOneByteString::SizeFor(old_length);
   11635     new_size = SeqOneByteString::SizeFor(new_length);
   11636   } else {
   11637     DCHECK(string->IsSeqTwoByteString());
   11638     old_size = SeqTwoByteString::SizeFor(old_length);
   11639     new_size = SeqTwoByteString::SizeFor(new_length);
   11640   }
   11641 
   11642   int delta = old_size - new_size;
   11643 
   11644   Address start_of_string = string->address();
   11645   DCHECK_OBJECT_ALIGNED(start_of_string);
   11646   DCHECK_OBJECT_ALIGNED(start_of_string + new_size);
   11647 
   11648   // Sizes are pointer size aligned, so that we can use filler objects
   11649   // that are a multiple of pointer size.
   11650   heap->CreateFillerObjectAt(start_of_string + new_size, delta,
   11651                              ClearRecordedSlots::kNo);
   11652   heap->AdjustLiveBytes(*string, -delta);
   11653 
   11654   // We are storing the new length using release store after creating a filler
   11655   // for the left-over space to avoid races with the sweeper thread.
   11656   string->synchronized_set_length(new_length);
   11657 
   11658   return string;
   11659 }
   11660 
   11661 
   11662 uint32_t StringHasher::MakeArrayIndexHash(uint32_t value, int length) {
   11663   // For array indexes mix the length into the hash as an array index could
   11664   // be zero.
   11665   DCHECK(length > 0);
   11666   DCHECK(length <= String::kMaxArrayIndexSize);
   11667   DCHECK(TenToThe(String::kMaxCachedArrayIndexLength) <
   11668          (1 << String::kArrayIndexValueBits));
   11669 
   11670   value <<= String::ArrayIndexValueBits::kShift;
   11671   value |= length << String::ArrayIndexLengthBits::kShift;
   11672 
   11673   DCHECK((value & String::kIsNotArrayIndexMask) == 0);
   11674   DCHECK_EQ(length <= String::kMaxCachedArrayIndexLength,
   11675             (value & String::kContainsCachedArrayIndexMask) == 0);
   11676   return value;
   11677 }
   11678 
   11679 
   11680 uint32_t StringHasher::GetHashField() {
   11681   if (length_ <= String::kMaxHashCalcLength) {
   11682     if (is_array_index_) {
   11683       return MakeArrayIndexHash(array_index_, length_);
   11684     }
   11685     return (GetHashCore(raw_running_hash_) << String::kHashShift) |
   11686            String::kIsNotArrayIndexMask;
   11687   } else {
   11688     return (length_ << String::kHashShift) | String::kIsNotArrayIndexMask;
   11689   }
   11690 }
   11691 
   11692 
   11693 uint32_t StringHasher::ComputeUtf8Hash(Vector<const char> chars,
   11694                                        uint32_t seed,
   11695                                        int* utf16_length_out) {
   11696   int vector_length = chars.length();
   11697   // Handle some edge cases
   11698   if (vector_length <= 1) {
   11699     DCHECK(vector_length == 0 ||
   11700            static_cast<uint8_t>(chars.start()[0]) <=
   11701                unibrow::Utf8::kMaxOneByteChar);
   11702     *utf16_length_out = vector_length;
   11703     return HashSequentialString(chars.start(), vector_length, seed);
   11704   }
   11705   // Start with a fake length which won't affect computation.
   11706   // It will be updated later.
   11707   StringHasher hasher(String::kMaxArrayIndexSize, seed);
   11708   size_t remaining = static_cast<size_t>(vector_length);
   11709   const uint8_t* stream = reinterpret_cast<const uint8_t*>(chars.start());
   11710   int utf16_length = 0;
   11711   bool is_index = true;
   11712   DCHECK(hasher.is_array_index_);
   11713   while (remaining > 0) {
   11714     size_t consumed = 0;
   11715     uint32_t c = unibrow::Utf8::ValueOf(stream, remaining, &consumed);
   11716     DCHECK(consumed > 0 && consumed <= remaining);
   11717     stream += consumed;
   11718     remaining -= consumed;
   11719     bool is_two_characters = c > unibrow::Utf16::kMaxNonSurrogateCharCode;
   11720     utf16_length += is_two_characters ? 2 : 1;
   11721     // No need to keep hashing. But we do need to calculate utf16_length.
   11722     if (utf16_length > String::kMaxHashCalcLength) continue;
   11723     if (is_two_characters) {
   11724       uint16_t c1 = unibrow::Utf16::LeadSurrogate(c);
   11725       uint16_t c2 = unibrow::Utf16::TrailSurrogate(c);
   11726       hasher.AddCharacter(c1);
   11727       hasher.AddCharacter(c2);
   11728       if (is_index) is_index = hasher.UpdateIndex(c1);
   11729       if (is_index) is_index = hasher.UpdateIndex(c2);
   11730     } else {
   11731       hasher.AddCharacter(c);
   11732       if (is_index) is_index = hasher.UpdateIndex(c);
   11733     }
   11734   }
   11735   *utf16_length_out = static_cast<int>(utf16_length);
   11736   // Must set length here so that hash computation is correct.
   11737   hasher.length_ = utf16_length;
   11738   return hasher.GetHashField();
   11739 }
   11740 
   11741 
   11742 void IteratingStringHasher::VisitConsString(ConsString* cons_string) {
   11743   // Run small ConsStrings through ConsStringIterator.
   11744   if (cons_string->length() < 64) {
   11745     ConsStringIterator iter(cons_string);
   11746     int offset;
   11747     String* string;
   11748     while (nullptr != (string = iter.Next(&offset))) {
   11749       DCHECK_EQ(0, offset);
   11750       String::VisitFlat(this, string, 0);
   11751     }
   11752     return;
   11753   }
   11754   // Slow case.
   11755   const int max_length = String::kMaxHashCalcLength;
   11756   int length = std::min(cons_string->length(), max_length);
   11757   if (cons_string->HasOnlyOneByteChars()) {
   11758     uint8_t* buffer = new uint8_t[length];
   11759     String::WriteToFlat(cons_string, buffer, 0, length);
   11760     AddCharacters(buffer, length);
   11761     delete[] buffer;
   11762   } else {
   11763     uint16_t* buffer = new uint16_t[length];
   11764     String::WriteToFlat(cons_string, buffer, 0, length);
   11765     AddCharacters(buffer, length);
   11766     delete[] buffer;
   11767   }
   11768 }
   11769 
   11770 
   11771 void String::PrintOn(FILE* file) {
   11772   int length = this->length();
   11773   for (int i = 0; i < length; i++) {
   11774     PrintF(file, "%c", Get(i));
   11775   }
   11776 }
   11777 
   11778 
   11779 int Map::Hash() {
   11780   // For performance reasons we only hash the 3 most variable fields of a map:
   11781   // constructor, prototype and bit_field2. For predictability reasons we
   11782   // use objects' offsets in respective pages for hashing instead of raw
   11783   // addresses.
   11784 
   11785   // Shift away the tag.
   11786   int hash = ObjectAddressForHashing(GetConstructor()) >> 2;
   11787 
   11788   // XOR-ing the prototype and constructor directly yields too many zero bits
   11789   // when the two pointers are close (which is fairly common).
   11790   // To avoid this we shift the prototype bits relatively to the constructor.
   11791   hash ^= ObjectAddressForHashing(prototype()) << (32 - kPageSizeBits);
   11792 
   11793   return hash ^ (hash >> 16) ^ bit_field2();
   11794 }
   11795 
   11796 
   11797 namespace {
   11798 
   11799 bool CheckEquivalent(Map* first, Map* second) {
   11800   return first->GetConstructor() == second->GetConstructor() &&
   11801          first->prototype() == second->prototype() &&
   11802          first->instance_type() == second->instance_type() &&
   11803          first->bit_field() == second->bit_field() &&
   11804          first->is_extensible() == second->is_extensible() &&
   11805          first->new_target_is_base() == second->new_target_is_base() &&
   11806          first->has_hidden_prototype() == second->has_hidden_prototype();
   11807 }
   11808 
   11809 }  // namespace
   11810 
   11811 
   11812 bool Map::EquivalentToForTransition(Map* other) {
   11813   if (!CheckEquivalent(this, other)) return false;
   11814   if (instance_type() == JS_FUNCTION_TYPE) {
   11815     // JSFunctions require more checks to ensure that sloppy function is
   11816     // not equvalent to strict function.
   11817     int nof = Min(NumberOfOwnDescriptors(), other->NumberOfOwnDescriptors());
   11818     return instance_descriptors()->IsEqualUpTo(other->instance_descriptors(),
   11819                                                nof);
   11820   }
   11821   return true;
   11822 }
   11823 
   11824 
   11825 bool Map::EquivalentToForNormalization(Map* other,
   11826                                        PropertyNormalizationMode mode) {
   11827   int properties =
   11828       mode == CLEAR_INOBJECT_PROPERTIES ? 0 : other->GetInObjectProperties();
   11829   return CheckEquivalent(this, other) && bit_field2() == other->bit_field2() &&
   11830          GetInObjectProperties() == properties &&
   11831          JSObject::GetInternalFieldCount(this) ==
   11832              JSObject::GetInternalFieldCount(other);
   11833 }
   11834 
   11835 
   11836 bool JSFunction::Inlines(SharedFunctionInfo* candidate) {
   11837   DisallowHeapAllocation no_gc;
   11838   if (shared() == candidate) return true;
   11839   if (code()->kind() != Code::OPTIMIZED_FUNCTION) return false;
   11840   DeoptimizationInputData* const data =
   11841       DeoptimizationInputData::cast(code()->deoptimization_data());
   11842   if (data->length() == 0) return false;
   11843   FixedArray* const literals = data->LiteralArray();
   11844   int const inlined_count = data->InlinedFunctionCount()->value();
   11845   for (int i = 0; i < inlined_count; ++i) {
   11846     if (SharedFunctionInfo::cast(literals->get(i)) == candidate) {
   11847       return true;
   11848     }
   11849   }
   11850   return false;
   11851 }
   11852 
   11853 void JSFunction::MarkForBaseline() {
   11854   Isolate* isolate = GetIsolate();
   11855   set_code_no_write_barrier(
   11856       isolate->builtins()->builtin(Builtins::kCompileBaseline));
   11857   // No write barrier required, since the builtin is part of the root set.
   11858   if (FLAG_mark_shared_functions_for_tier_up) {
   11859     shared()->set_marked_for_tier_up(true);
   11860   }
   11861 }
   11862 
   11863 void JSFunction::MarkForOptimization() {
   11864   Isolate* isolate = GetIsolate();
   11865   DCHECK(!IsOptimized());
   11866   DCHECK(shared()->allows_lazy_compilation() ||
   11867          !shared()->optimization_disabled());
   11868   set_code_no_write_barrier(
   11869       isolate->builtins()->builtin(Builtins::kCompileOptimized));
   11870   // No write barrier required, since the builtin is part of the root set.
   11871   if (FLAG_mark_shared_functions_for_tier_up) {
   11872     shared()->set_marked_for_tier_up(true);
   11873   }
   11874 }
   11875 
   11876 
   11877 void JSFunction::AttemptConcurrentOptimization() {
   11878   Isolate* isolate = GetIsolate();
   11879   if (!isolate->concurrent_recompilation_enabled() ||
   11880       isolate->bootstrapper()->IsActive()) {
   11881     MarkForOptimization();
   11882     return;
   11883   }
   11884   DCHECK(!IsInOptimizationQueue());
   11885   DCHECK(!IsOptimized());
   11886   DCHECK(shared()->allows_lazy_compilation() ||
   11887          !shared()->optimization_disabled());
   11888   DCHECK(isolate->concurrent_recompilation_enabled());
   11889   if (FLAG_trace_concurrent_recompilation) {
   11890     PrintF("  ** Marking ");
   11891     ShortPrint();
   11892     PrintF(" for concurrent recompilation.\n");
   11893   }
   11894 
   11895   set_code_no_write_barrier(
   11896       isolate->builtins()->builtin(Builtins::kCompileOptimizedConcurrent));
   11897   // No write barrier required, since the builtin is part of the root set.
   11898   if (FLAG_mark_shared_functions_for_tier_up) {
   11899     // TODO(leszeks): The compilation isn't concurrent if we trigger it using
   11900     // this bit.
   11901     shared()->set_marked_for_tier_up(true);
   11902   }
   11903 }
   11904 
   11905 // static
   11906 void SharedFunctionInfo::AddToOptimizedCodeMap(
   11907     Handle<SharedFunctionInfo> shared, Handle<Context> native_context,
   11908     Handle<Code> code, BailoutId osr_ast_id) {
   11909   Isolate* isolate = shared->GetIsolate();
   11910   if (isolate->serializer_enabled()) return;
   11911   DCHECK(code->kind() == Code::OPTIMIZED_FUNCTION);
   11912   DCHECK(native_context->IsNativeContext());
   11913   STATIC_ASSERT(kEntryLength == 2);
   11914   Handle<FixedArray> new_code_map;
   11915   int entry;
   11916 
   11917   if (!osr_ast_id.IsNone()) {
   11918     Context::AddToOptimizedCodeMap(native_context, shared, code, osr_ast_id);
   11919     return;
   11920   }
   11921 
   11922   DCHECK(osr_ast_id.IsNone());
   11923   if (shared->OptimizedCodeMapIsCleared()) {
   11924     new_code_map = isolate->factory()->NewFixedArray(kInitialLength, TENURED);
   11925     entry = kEntriesStart;
   11926   } else {
   11927     Handle<FixedArray> old_code_map(shared->optimized_code_map(), isolate);
   11928     entry = shared->SearchOptimizedCodeMapEntry(*native_context);
   11929     if (entry >= kEntriesStart) {
   11930       // Just set the code of the entry.
   11931       Handle<WeakCell> code_cell = isolate->factory()->NewWeakCell(code);
   11932       old_code_map->set(entry + kCachedCodeOffset, *code_cell);
   11933       return;
   11934     }
   11935 
   11936     // Can we reuse an entry?
   11937     DCHECK(entry < kEntriesStart);
   11938     int length = old_code_map->length();
   11939     for (int i = kEntriesStart; i < length; i += kEntryLength) {
   11940       if (WeakCell::cast(old_code_map->get(i + kContextOffset))->cleared()) {
   11941         new_code_map = old_code_map;
   11942         entry = i;
   11943         break;
   11944       }
   11945     }
   11946 
   11947     if (entry < kEntriesStart) {
   11948       // Copy old optimized code map and append one new entry.
   11949       new_code_map = isolate->factory()->CopyFixedArrayAndGrow(
   11950           old_code_map, kEntryLength, TENURED);
   11951       // TODO(mstarzinger): Temporary workaround. The allocation above might
   11952       // have flushed the optimized code map and the copy we created is full of
   11953       // holes. For now we just give up on adding the entry and pretend it got
   11954       // flushed.
   11955       if (shared->OptimizedCodeMapIsCleared()) return;
   11956       entry = old_code_map->length();
   11957     }
   11958   }
   11959 
   11960   Handle<WeakCell> code_cell = isolate->factory()->NewWeakCell(code);
   11961   WeakCell* context_cell = native_context->self_weak_cell();
   11962 
   11963   new_code_map->set(entry + kContextOffset, context_cell);
   11964   new_code_map->set(entry + kCachedCodeOffset, *code_cell);
   11965 
   11966 #ifdef DEBUG
   11967   for (int i = kEntriesStart; i < new_code_map->length(); i += kEntryLength) {
   11968     WeakCell* cell = WeakCell::cast(new_code_map->get(i + kContextOffset));
   11969     DCHECK(cell->cleared() || cell->value()->IsNativeContext());
   11970     cell = WeakCell::cast(new_code_map->get(i + kCachedCodeOffset));
   11971     DCHECK(cell->cleared() ||
   11972            (cell->value()->IsCode() &&
   11973             Code::cast(cell->value())->kind() == Code::OPTIMIZED_FUNCTION));
   11974   }
   11975 #endif
   11976 
   11977   FixedArray* old_code_map = shared->optimized_code_map();
   11978   if (old_code_map != *new_code_map) {
   11979     shared->set_optimized_code_map(*new_code_map);
   11980   }
   11981 }
   11982 
   11983 
   11984 void SharedFunctionInfo::ClearOptimizedCodeMap() {
   11985   FixedArray* empty_fixed_array = GetHeap()->empty_fixed_array();
   11986   set_optimized_code_map(empty_fixed_array, SKIP_WRITE_BARRIER);
   11987 }
   11988 
   11989 
   11990 void SharedFunctionInfo::EvictFromOptimizedCodeMap(Code* optimized_code,
   11991                                                    const char* reason) {
   11992   DisallowHeapAllocation no_gc;
   11993   Isolate* isolate = GetIsolate();
   11994   bool found = false;
   11995 
   11996   if (!OptimizedCodeMapIsCleared()) {
   11997     Heap* heap = isolate->heap();
   11998     FixedArray* code_map = optimized_code_map();
   11999     int length = code_map->length();
   12000     for (int src = kEntriesStart; src < length; src += kEntryLength) {
   12001       DCHECK(WeakCell::cast(code_map->get(src))->cleared() ||
   12002              WeakCell::cast(code_map->get(src))->value()->IsNativeContext());
   12003       found = WeakCell::cast(code_map->get(src + kCachedCodeOffset))->value() ==
   12004               optimized_code;
   12005       if (found) {
   12006         if (FLAG_trace_opt) {
   12007           PrintF("[evicting entry from optimizing code map (%s) for ", reason);
   12008           ShortPrint();
   12009           PrintF("]\n");
   12010         }
   12011         // Just clear the code.
   12012         code_map->set(src + kCachedCodeOffset, heap->empty_weak_cell(),
   12013                       SKIP_WRITE_BARRIER);
   12014       }
   12015     }
   12016   }
   12017 
   12018   if (!found) {
   12019     // We didn't find the code in here. It must be osr'd code.
   12020     isolate->EvictOSROptimizedCode(optimized_code, reason);
   12021   }
   12022 }
   12023 
   12024 // static
   12025 void JSFunction::EnsureLiterals(Handle<JSFunction> function) {
   12026   Handle<SharedFunctionInfo> shared(function->shared());
   12027   Isolate* isolate = shared->GetIsolate();
   12028 
   12029   FeedbackVectorState state = function->GetFeedbackVectorState(isolate);
   12030   switch (state) {
   12031     case TOP_LEVEL_SCRIPT_NEEDS_VECTOR: {
   12032       // A top level script didn't get it's literals installed.
   12033       Handle<FeedbackVector> feedback_vector =
   12034           FeedbackVector::New(isolate, shared);
   12035       Handle<Cell> new_cell =
   12036           isolate->factory()->NewOneClosureCell(feedback_vector);
   12037       function->set_feedback_vector_cell(*new_cell);
   12038       break;
   12039     }
   12040     case NEEDS_VECTOR: {
   12041       Handle<FeedbackVector> feedback_vector =
   12042           FeedbackVector::New(isolate, shared);
   12043       function->feedback_vector_cell()->set_value(*feedback_vector);
   12044       break;
   12045     }
   12046     case HAS_VECTOR:
   12047       // Nothing to do.
   12048       break;
   12049   }
   12050 }
   12051 
   12052 static void GetMinInobjectSlack(Map* map, void* data) {
   12053   int slack = map->unused_property_fields();
   12054   if (*reinterpret_cast<int*>(data) > slack) {
   12055     *reinterpret_cast<int*>(data) = slack;
   12056   }
   12057 }
   12058 
   12059 
   12060 static void ShrinkInstanceSize(Map* map, void* data) {
   12061   int slack = *reinterpret_cast<int*>(data);
   12062   map->SetInObjectProperties(map->GetInObjectProperties() - slack);
   12063   map->set_unused_property_fields(map->unused_property_fields() - slack);
   12064   map->set_instance_size(map->instance_size() - slack * kPointerSize);
   12065   map->set_construction_counter(Map::kNoSlackTracking);
   12066 
   12067   // Visitor id might depend on the instance size, recalculate it.
   12068   map->set_visitor_id(Heap::GetStaticVisitorIdForMap(map));
   12069 }
   12070 
   12071 static void StopSlackTracking(Map* map, void* data) {
   12072   map->set_construction_counter(Map::kNoSlackTracking);
   12073 }
   12074 
   12075 void Map::CompleteInobjectSlackTracking() {
   12076   // Has to be an initial map.
   12077   DCHECK(GetBackPointer()->IsUndefined(GetIsolate()));
   12078 
   12079   int slack = unused_property_fields();
   12080   TransitionArray::TraverseTransitionTree(this, &GetMinInobjectSlack, &slack);
   12081   if (slack != 0) {
   12082     // Resize the initial map and all maps in its transition tree.
   12083     TransitionArray::TraverseTransitionTree(this, &ShrinkInstanceSize, &slack);
   12084   } else {
   12085     TransitionArray::TraverseTransitionTree(this, &StopSlackTracking, nullptr);
   12086   }
   12087 }
   12088 
   12089 
   12090 static bool PrototypeBenefitsFromNormalization(Handle<JSObject> object) {
   12091   DisallowHeapAllocation no_gc;
   12092   if (!object->HasFastProperties()) return false;
   12093   if (object->IsJSGlobalProxy()) return false;
   12094   if (object->GetIsolate()->bootstrapper()->IsActive()) return false;
   12095   return !object->map()->is_prototype_map() ||
   12096          !object->map()->should_be_fast_prototype_map();
   12097 }
   12098 
   12099 // static
   12100 void JSObject::MakePrototypesFast(Handle<Object> receiver,
   12101                                   WhereToStart where_to_start,
   12102                                   Isolate* isolate) {
   12103   if (!receiver->IsJSReceiver()) return;
   12104   for (PrototypeIterator iter(isolate, Handle<JSReceiver>::cast(receiver),
   12105                               where_to_start);
   12106        !iter.IsAtEnd(); iter.Advance()) {
   12107     Handle<Object> current = PrototypeIterator::GetCurrent(iter);
   12108     if (!current->IsJSObject()) return;
   12109     Handle<JSObject> current_obj = Handle<JSObject>::cast(current);
   12110     Map* current_map = current_obj->map();
   12111     if (current_map->is_prototype_map()) {
   12112       // If the map is already marked as should be fast, we're done. Its
   12113       // prototypes will have been marked already as well.
   12114       if (current_map->should_be_fast_prototype_map()) return;
   12115       Handle<Map> map(current_map);
   12116       Map::SetShouldBeFastPrototypeMap(map, true, isolate);
   12117       JSObject::OptimizeAsPrototype(current_obj, FAST_PROTOTYPE);
   12118     }
   12119   }
   12120 }
   12121 
   12122 // static
   12123 void JSObject::OptimizeAsPrototype(Handle<JSObject> object,
   12124                                    PrototypeOptimizationMode mode) {
   12125   if (object->IsJSGlobalObject()) return;
   12126   if (mode == FAST_PROTOTYPE && PrototypeBenefitsFromNormalization(object)) {
   12127     // First normalize to ensure all JSFunctions are DATA_CONSTANT.
   12128     JSObject::NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, 0,
   12129                                   "NormalizeAsPrototype");
   12130   }
   12131   Handle<Map> previous_map(object->map());
   12132   if (object->map()->is_prototype_map()) {
   12133     if (object->map()->should_be_fast_prototype_map() &&
   12134         !object->HasFastProperties()) {
   12135       JSObject::MigrateSlowToFast(object, 0, "OptimizeAsPrototype");
   12136     }
   12137   } else {
   12138     if (object->map() == *previous_map) {
   12139       Handle<Map> new_map = Map::Copy(handle(object->map()), "CopyAsPrototype");
   12140       JSObject::MigrateToMap(object, new_map);
   12141     }
   12142     object->map()->set_is_prototype_map(true);
   12143 
   12144     // Replace the pointer to the exact constructor with the Object function
   12145     // from the same context if undetectable from JS. This is to avoid keeping
   12146     // memory alive unnecessarily.
   12147     Object* maybe_constructor = object->map()->GetConstructor();
   12148     if (maybe_constructor->IsJSFunction()) {
   12149       JSFunction* constructor = JSFunction::cast(maybe_constructor);
   12150       Isolate* isolate = object->GetIsolate();
   12151       if (!constructor->shared()->IsApiFunction() &&
   12152           object->class_name() == isolate->heap()->Object_string()) {
   12153         Context* context = constructor->context()->native_context();
   12154         JSFunction* object_function = context->object_function();
   12155         object->map()->SetConstructor(object_function);
   12156       }
   12157     }
   12158   }
   12159 }
   12160 
   12161 
   12162 // static
   12163 void JSObject::ReoptimizeIfPrototype(Handle<JSObject> object) {
   12164   if (!object->map()->is_prototype_map()) return;
   12165   if (!object->map()->should_be_fast_prototype_map()) return;
   12166   OptimizeAsPrototype(object, FAST_PROTOTYPE);
   12167 }
   12168 
   12169 
   12170 // static
   12171 void JSObject::LazyRegisterPrototypeUser(Handle<Map> user, Isolate* isolate) {
   12172   // Contract: In line with InvalidatePrototypeChains()'s requirements,
   12173   // leaf maps don't need to register as users, only prototypes do.
   12174   DCHECK(user->is_prototype_map());
   12175 
   12176   Handle<Map> current_user = user;
   12177   Handle<PrototypeInfo> current_user_info =
   12178       Map::GetOrCreatePrototypeInfo(user, isolate);
   12179   for (PrototypeIterator iter(user); !iter.IsAtEnd(); iter.Advance()) {
   12180     // Walk up the prototype chain as far as links haven't been registered yet.
   12181     if (current_user_info->registry_slot() != PrototypeInfo::UNREGISTERED) {
   12182       break;
   12183     }
   12184     Handle<Object> maybe_proto = PrototypeIterator::GetCurrent(iter);
   12185     // Proxies on the prototype chain are not supported. They make it
   12186     // impossible to make any assumptions about the prototype chain anyway.
   12187     if (maybe_proto->IsJSProxy()) return;
   12188     Handle<JSObject> proto = Handle<JSObject>::cast(maybe_proto);
   12189     Handle<PrototypeInfo> proto_info =
   12190         Map::GetOrCreatePrototypeInfo(proto, isolate);
   12191     Handle<Object> maybe_registry(proto_info->prototype_users(), isolate);
   12192     int slot = 0;
   12193     Handle<WeakFixedArray> new_array =
   12194         WeakFixedArray::Add(maybe_registry, current_user, &slot);
   12195     current_user_info->set_registry_slot(slot);
   12196     if (!maybe_registry.is_identical_to(new_array)) {
   12197       proto_info->set_prototype_users(*new_array);
   12198     }
   12199     if (FLAG_trace_prototype_users) {
   12200       PrintF("Registering %p as a user of prototype %p (map=%p).\n",
   12201              reinterpret_cast<void*>(*current_user),
   12202              reinterpret_cast<void*>(*proto),
   12203              reinterpret_cast<void*>(proto->map()));
   12204     }
   12205 
   12206     current_user = handle(proto->map(), isolate);
   12207     current_user_info = proto_info;
   12208   }
   12209 }
   12210 
   12211 
   12212 // Can be called regardless of whether |user| was actually registered with
   12213 // |prototype|. Returns true when there was a registration.
   12214 // static
   12215 bool JSObject::UnregisterPrototypeUser(Handle<Map> user, Isolate* isolate) {
   12216   DCHECK(user->is_prototype_map());
   12217   // If it doesn't have a PrototypeInfo, it was never registered.
   12218   if (!user->prototype_info()->IsPrototypeInfo()) return false;
   12219   // If it had no prototype before, see if it had users that might expect
   12220   // registration.
   12221   if (!user->prototype()->IsJSObject()) {
   12222     Object* users =
   12223         PrototypeInfo::cast(user->prototype_info())->prototype_users();
   12224     return users->IsWeakFixedArray();
   12225   }
   12226   Handle<JSObject> prototype(JSObject::cast(user->prototype()), isolate);
   12227   Handle<PrototypeInfo> user_info =
   12228       Map::GetOrCreatePrototypeInfo(user, isolate);
   12229   int slot = user_info->registry_slot();
   12230   if (slot == PrototypeInfo::UNREGISTERED) return false;
   12231   DCHECK(prototype->map()->is_prototype_map());
   12232   Object* maybe_proto_info = prototype->map()->prototype_info();
   12233   // User knows its registry slot, prototype info and user registry must exist.
   12234   DCHECK(maybe_proto_info->IsPrototypeInfo());
   12235   Handle<PrototypeInfo> proto_info(PrototypeInfo::cast(maybe_proto_info),
   12236                                    isolate);
   12237   Object* maybe_registry = proto_info->prototype_users();
   12238   DCHECK(maybe_registry->IsWeakFixedArray());
   12239   DCHECK(WeakFixedArray::cast(maybe_registry)->Get(slot) == *user);
   12240   WeakFixedArray::cast(maybe_registry)->Clear(slot);
   12241   if (FLAG_trace_prototype_users) {
   12242     PrintF("Unregistering %p as a user of prototype %p.\n",
   12243            reinterpret_cast<void*>(*user), reinterpret_cast<void*>(*prototype));
   12244   }
   12245   return true;
   12246 }
   12247 
   12248 
   12249 static void InvalidatePrototypeChainsInternal(Map* map) {
   12250   DCHECK(map->is_prototype_map());
   12251   if (FLAG_trace_prototype_users) {
   12252     PrintF("Invalidating prototype map %p 's cell\n",
   12253            reinterpret_cast<void*>(map));
   12254   }
   12255   Object* maybe_proto_info = map->prototype_info();
   12256   if (!maybe_proto_info->IsPrototypeInfo()) return;
   12257   PrototypeInfo* proto_info = PrototypeInfo::cast(maybe_proto_info);
   12258   Object* maybe_cell = proto_info->validity_cell();
   12259   if (maybe_cell->IsCell()) {
   12260     // Just set the value; the cell will be replaced lazily.
   12261     Cell* cell = Cell::cast(maybe_cell);
   12262     cell->set_value(Smi::FromInt(Map::kPrototypeChainInvalid));
   12263   }
   12264 
   12265   WeakFixedArray::Iterator iterator(proto_info->prototype_users());
   12266   // For now, only maps register themselves as users.
   12267   Map* user;
   12268   while ((user = iterator.Next<Map>())) {
   12269     // Walk the prototype chain (backwards, towards leaf objects) if necessary.
   12270     InvalidatePrototypeChainsInternal(user);
   12271   }
   12272 }
   12273 
   12274 
   12275 // static
   12276 void JSObject::InvalidatePrototypeChains(Map* map) {
   12277   DisallowHeapAllocation no_gc;
   12278   InvalidatePrototypeChainsInternal(map);
   12279 }
   12280 
   12281 
   12282 // static
   12283 Handle<PrototypeInfo> Map::GetOrCreatePrototypeInfo(Handle<JSObject> prototype,
   12284                                                     Isolate* isolate) {
   12285   Object* maybe_proto_info = prototype->map()->prototype_info();
   12286   if (maybe_proto_info->IsPrototypeInfo()) {
   12287     return handle(PrototypeInfo::cast(maybe_proto_info), isolate);
   12288   }
   12289   Handle<PrototypeInfo> proto_info = isolate->factory()->NewPrototypeInfo();
   12290   prototype->map()->set_prototype_info(*proto_info);
   12291   return proto_info;
   12292 }
   12293 
   12294 
   12295 // static
   12296 Handle<PrototypeInfo> Map::GetOrCreatePrototypeInfo(Handle<Map> prototype_map,
   12297                                                     Isolate* isolate) {
   12298   Object* maybe_proto_info = prototype_map->prototype_info();
   12299   if (maybe_proto_info->IsPrototypeInfo()) {
   12300     return handle(PrototypeInfo::cast(maybe_proto_info), isolate);
   12301   }
   12302   Handle<PrototypeInfo> proto_info = isolate->factory()->NewPrototypeInfo();
   12303   prototype_map->set_prototype_info(*proto_info);
   12304   return proto_info;
   12305 }
   12306 
   12307 // static
   12308 void Map::SetShouldBeFastPrototypeMap(Handle<Map> map, bool value,
   12309                                       Isolate* isolate) {
   12310   if (value == false && !map->prototype_info()->IsPrototypeInfo()) {
   12311     // "False" is the implicit default value, so there's nothing to do.
   12312     return;
   12313   }
   12314   GetOrCreatePrototypeInfo(map, isolate)->set_should_be_fast_map(value);
   12315 }
   12316 
   12317 // static
   12318 Handle<Cell> Map::GetOrCreatePrototypeChainValidityCell(Handle<Map> map,
   12319                                                         Isolate* isolate) {
   12320   Handle<Object> maybe_prototype;
   12321   if (map->IsJSGlobalObjectMap()) {
   12322     DCHECK(map->is_prototype_map());
   12323     // Global object is prototype of a global proxy and therefore we can
   12324     // use its validity cell for guarding global object's prototype change.
   12325     maybe_prototype = isolate->global_object();
   12326   } else {
   12327     maybe_prototype =
   12328         handle(map->GetPrototypeChainRootMap(isolate)->prototype(), isolate);
   12329     if (!maybe_prototype->IsJSObject()) return Handle<Cell>::null();
   12330   }
   12331   Handle<JSObject> prototype = Handle<JSObject>::cast(maybe_prototype);
   12332   // Ensure the prototype is registered with its own prototypes so its cell
   12333   // will be invalidated when necessary.
   12334   JSObject::LazyRegisterPrototypeUser(handle(prototype->map(), isolate),
   12335                                       isolate);
   12336   Handle<PrototypeInfo> proto_info =
   12337       GetOrCreatePrototypeInfo(prototype, isolate);
   12338   Object* maybe_cell = proto_info->validity_cell();
   12339   // Return existing cell if it's still valid.
   12340   if (maybe_cell->IsCell()) {
   12341     Handle<Cell> cell(Cell::cast(maybe_cell), isolate);
   12342     if (cell->value() == Smi::FromInt(Map::kPrototypeChainValid)) {
   12343       return cell;
   12344     }
   12345   }
   12346   // Otherwise create a new cell.
   12347   Handle<Cell> cell = isolate->factory()->NewCell(
   12348       handle(Smi::FromInt(Map::kPrototypeChainValid), isolate));
   12349   proto_info->set_validity_cell(*cell);
   12350   return cell;
   12351 }
   12352 
   12353 // static
   12354 Handle<WeakCell> Map::GetOrCreatePrototypeWeakCell(Handle<JSObject> prototype,
   12355                                                    Isolate* isolate) {
   12356   DCHECK(!prototype.is_null());
   12357   Handle<PrototypeInfo> proto_info =
   12358       GetOrCreatePrototypeInfo(prototype, isolate);
   12359   Object* maybe_cell = proto_info->weak_cell();
   12360   // Return existing cell if it's already created.
   12361   if (maybe_cell->IsWeakCell()) {
   12362     Handle<WeakCell> cell(WeakCell::cast(maybe_cell), isolate);
   12363     DCHECK(!cell->cleared());
   12364     return cell;
   12365   }
   12366   // Otherwise create a new cell.
   12367   Handle<WeakCell> cell = isolate->factory()->NewWeakCell(prototype);
   12368   proto_info->set_weak_cell(*cell);
   12369   return cell;
   12370 }
   12371 
   12372 // static
   12373 void Map::SetPrototype(Handle<Map> map, Handle<Object> prototype,
   12374                        PrototypeOptimizationMode proto_mode) {
   12375   RuntimeCallTimerScope stats_scope(*map, &RuntimeCallStats::Map_SetPrototype);
   12376 
   12377   bool is_hidden = false;
   12378   if (prototype->IsJSObject()) {
   12379     Handle<JSObject> prototype_jsobj = Handle<JSObject>::cast(prototype);
   12380     JSObject::OptimizeAsPrototype(prototype_jsobj, proto_mode);
   12381 
   12382     Object* maybe_constructor = prototype_jsobj->map()->GetConstructor();
   12383     if (maybe_constructor->IsJSFunction()) {
   12384       JSFunction* constructor = JSFunction::cast(maybe_constructor);
   12385       Object* data = constructor->shared()->function_data();
   12386       is_hidden = (data->IsFunctionTemplateInfo() &&
   12387                    FunctionTemplateInfo::cast(data)->hidden_prototype()) ||
   12388                   prototype->IsJSGlobalObject();
   12389     }
   12390   }
   12391   map->set_has_hidden_prototype(is_hidden);
   12392 
   12393   WriteBarrierMode wb_mode = prototype->IsNull(map->GetIsolate())
   12394                                  ? SKIP_WRITE_BARRIER
   12395                                  : UPDATE_WRITE_BARRIER;
   12396   map->set_prototype(*prototype, wb_mode);
   12397 }
   12398 
   12399 
   12400 Handle<Object> CacheInitialJSArrayMaps(
   12401     Handle<Context> native_context, Handle<Map> initial_map) {
   12402   // Replace all of the cached initial array maps in the native context with
   12403   // the appropriate transitioned elements kind maps.
   12404   Handle<Map> current_map = initial_map;
   12405   ElementsKind kind = current_map->elements_kind();
   12406   DCHECK_EQ(GetInitialFastElementsKind(), kind);
   12407   native_context->set(Context::ArrayMapIndex(kind), *current_map);
   12408   for (int i = GetSequenceIndexFromFastElementsKind(kind) + 1;
   12409        i < kFastElementsKindCount; ++i) {
   12410     Handle<Map> new_map;
   12411     ElementsKind next_kind = GetFastElementsKindFromSequenceIndex(i);
   12412     if (Map* maybe_elements_transition = current_map->ElementsTransitionMap()) {
   12413       new_map = handle(maybe_elements_transition);
   12414     } else {
   12415       new_map = Map::CopyAsElementsKind(
   12416           current_map, next_kind, INSERT_TRANSITION);
   12417     }
   12418     DCHECK_EQ(next_kind, new_map->elements_kind());
   12419     native_context->set(Context::ArrayMapIndex(next_kind), *new_map);
   12420     current_map = new_map;
   12421   }
   12422   return initial_map;
   12423 }
   12424 
   12425 
   12426 void JSFunction::SetInstancePrototype(Handle<JSFunction> function,
   12427                                       Handle<Object> value) {
   12428   Isolate* isolate = function->GetIsolate();
   12429 
   12430   DCHECK(value->IsJSReceiver());
   12431 
   12432   // Now some logic for the maps of the objects that are created by using this
   12433   // function as a constructor.
   12434   if (function->has_initial_map()) {
   12435     // If the function has allocated the initial map replace it with a
   12436     // copy containing the new prototype.  Also complete any in-object
   12437     // slack tracking that is in progress at this point because it is
   12438     // still tracking the old copy.
   12439     function->CompleteInobjectSlackTrackingIfActive();
   12440 
   12441     Handle<Map> initial_map(function->initial_map(), isolate);
   12442 
   12443     if (!initial_map->GetIsolate()->bootstrapper()->IsActive() &&
   12444         initial_map->instance_type() == JS_OBJECT_TYPE) {
   12445       // Put the value in the initial map field until an initial map is needed.
   12446       // At that point, a new initial map is created and the prototype is put
   12447       // into the initial map where it belongs.
   12448       function->set_prototype_or_initial_map(*value);
   12449     } else {
   12450       Handle<Map> new_map = Map::Copy(initial_map, "SetInstancePrototype");
   12451       JSFunction::SetInitialMap(function, new_map, value);
   12452 
   12453       // If the function is used as the global Array function, cache the
   12454       // updated initial maps (and transitioned versions) in the native context.
   12455       Handle<Context> native_context(function->context()->native_context(),
   12456                                      isolate);
   12457       Handle<Object> array_function(
   12458           native_context->get(Context::ARRAY_FUNCTION_INDEX), isolate);
   12459       if (array_function->IsJSFunction() &&
   12460           *function == JSFunction::cast(*array_function)) {
   12461         CacheInitialJSArrayMaps(native_context, new_map);
   12462       }
   12463     }
   12464 
   12465     // Deoptimize all code that embeds the previous initial map.
   12466     initial_map->dependent_code()->DeoptimizeDependentCodeGroup(
   12467         isolate, DependentCode::kInitialMapChangedGroup);
   12468   } else {
   12469     // Put the value in the initial map field until an initial map is
   12470     // needed.  At that point, a new initial map is created and the
   12471     // prototype is put into the initial map where it belongs.
   12472     function->set_prototype_or_initial_map(*value);
   12473     if (value->IsJSObject()) {
   12474       // Optimize as prototype to detach it from its transition tree.
   12475       JSObject::OptimizeAsPrototype(Handle<JSObject>::cast(value),
   12476                                     FAST_PROTOTYPE);
   12477     }
   12478   }
   12479   isolate->heap()->ClearInstanceofCache();
   12480 }
   12481 
   12482 
   12483 void JSFunction::SetPrototype(Handle<JSFunction> function,
   12484                               Handle<Object> value) {
   12485   DCHECK(function->IsConstructor() ||
   12486          IsGeneratorFunction(function->shared()->kind()));
   12487   Handle<Object> construct_prototype = value;
   12488 
   12489   // If the value is not a JSReceiver, store the value in the map's
   12490   // constructor field so it can be accessed.  Also, set the prototype
   12491   // used for constructing objects to the original object prototype.
   12492   // See ECMA-262 13.2.2.
   12493   if (!value->IsJSReceiver()) {
   12494     // Copy the map so this does not affect unrelated functions.
   12495     // Remove map transitions because they point to maps with a
   12496     // different prototype.
   12497     Handle<Map> new_map = Map::Copy(handle(function->map()), "SetPrototype");
   12498 
   12499     JSObject::MigrateToMap(function, new_map);
   12500     new_map->SetConstructor(*value);
   12501     new_map->set_non_instance_prototype(true);
   12502     Isolate* isolate = new_map->GetIsolate();
   12503 
   12504     construct_prototype = handle(
   12505         IsGeneratorFunction(function->shared()->kind())
   12506             ? function->context()
   12507                   ->native_context()
   12508                   ->initial_generator_prototype()
   12509             : function->context()->native_context()->initial_object_prototype(),
   12510         isolate);
   12511   } else {
   12512     function->map()->set_non_instance_prototype(false);
   12513   }
   12514 
   12515   return SetInstancePrototype(function, construct_prototype);
   12516 }
   12517 
   12518 
   12519 bool JSFunction::RemovePrototype() {
   12520   Context* native_context = context()->native_context();
   12521   Map* no_prototype_map =
   12522       is_strict(shared()->language_mode())
   12523           ? native_context->strict_function_without_prototype_map()
   12524           : native_context->sloppy_function_without_prototype_map();
   12525 
   12526   if (map() == no_prototype_map) return true;
   12527 
   12528 #ifdef DEBUG
   12529   if (map() != (is_strict(shared()->language_mode())
   12530                     ? native_context->strict_function_map()
   12531                     : native_context->sloppy_function_map())) {
   12532     return false;
   12533   }
   12534 #endif
   12535 
   12536   set_map(no_prototype_map);
   12537   set_prototype_or_initial_map(no_prototype_map->GetHeap()->the_hole_value());
   12538   return true;
   12539 }
   12540 
   12541 
   12542 void JSFunction::SetInitialMap(Handle<JSFunction> function, Handle<Map> map,
   12543                                Handle<Object> prototype) {
   12544   if (map->prototype() != *prototype) {
   12545     Map::SetPrototype(map, prototype, FAST_PROTOTYPE);
   12546   }
   12547   function->set_prototype_or_initial_map(*map);
   12548   map->SetConstructor(*function);
   12549 #if TRACE_MAPS
   12550   if (FLAG_trace_maps) {
   12551     PrintF("[TraceMaps: InitialMap map= %p SFI= %d_%s ]\n",
   12552            reinterpret_cast<void*>(*map), function->shared()->unique_id(),
   12553            function->shared()->DebugName()->ToCString().get());
   12554   }
   12555 #endif
   12556 }
   12557 
   12558 
   12559 #ifdef DEBUG
   12560 namespace {
   12561 
   12562 bool CanSubclassHaveInobjectProperties(InstanceType instance_type) {
   12563   switch (instance_type) {
   12564     case JS_API_OBJECT_TYPE:
   12565     case JS_ARRAY_BUFFER_TYPE:
   12566     case JS_ARRAY_TYPE:
   12567     case JS_ASYNC_FROM_SYNC_ITERATOR_TYPE:
   12568     case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
   12569     case JS_DATA_VIEW_TYPE:
   12570     case JS_DATE_TYPE:
   12571     case JS_FUNCTION_TYPE:
   12572     case JS_GENERATOR_OBJECT_TYPE:
   12573     case JS_MAP_ITERATOR_TYPE:
   12574     case JS_MAP_TYPE:
   12575     case JS_MESSAGE_OBJECT_TYPE:
   12576     case JS_OBJECT_TYPE:
   12577     case JS_ERROR_TYPE:
   12578     case JS_ARGUMENTS_TYPE:
   12579     case JS_PROMISE_TYPE:
   12580     case JS_REGEXP_TYPE:
   12581     case JS_SET_ITERATOR_TYPE:
   12582     case JS_SET_TYPE:
   12583     case JS_SPECIAL_API_OBJECT_TYPE:
   12584     case JS_TYPED_ARRAY_TYPE:
   12585     case JS_VALUE_TYPE:
   12586     case JS_WEAK_MAP_TYPE:
   12587     case JS_WEAK_SET_TYPE:
   12588       return true;
   12589 
   12590     case BYTECODE_ARRAY_TYPE:
   12591     case BYTE_ARRAY_TYPE:
   12592     case CELL_TYPE:
   12593     case CODE_TYPE:
   12594     case FILLER_TYPE:
   12595     case FIXED_ARRAY_TYPE:
   12596     case FIXED_DOUBLE_ARRAY_TYPE:
   12597     case FOREIGN_TYPE:
   12598     case FREE_SPACE_TYPE:
   12599     case HEAP_NUMBER_TYPE:
   12600     case JS_BOUND_FUNCTION_TYPE:
   12601     case JS_GLOBAL_OBJECT_TYPE:
   12602     case JS_GLOBAL_PROXY_TYPE:
   12603     case JS_PROXY_TYPE:
   12604     case MAP_TYPE:
   12605     case MUTABLE_HEAP_NUMBER_TYPE:
   12606     case ODDBALL_TYPE:
   12607     case PROPERTY_CELL_TYPE:
   12608     case SHARED_FUNCTION_INFO_TYPE:
   12609     case SYMBOL_TYPE:
   12610     case WEAK_CELL_TYPE:
   12611 
   12612 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
   12613   case FIXED_##TYPE##_ARRAY_TYPE:
   12614 #undef TYPED_ARRAY_CASE
   12615 
   12616 #define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE:
   12617       STRUCT_LIST(MAKE_STRUCT_CASE)
   12618 #undef MAKE_STRUCT_CASE
   12619       // We must not end up here for these instance types at all.
   12620       UNREACHABLE();
   12621     // Fall through.
   12622     default:
   12623       return false;
   12624   }
   12625 }
   12626 
   12627 }  // namespace
   12628 #endif
   12629 
   12630 
   12631 void JSFunction::EnsureHasInitialMap(Handle<JSFunction> function) {
   12632   DCHECK(function->IsConstructor() ||
   12633          IsResumableFunction(function->shared()->kind()));
   12634   if (function->has_initial_map()) return;
   12635   Isolate* isolate = function->GetIsolate();
   12636 
   12637   // The constructor should be compiled for the optimization hints to be
   12638   // available.
   12639   Compiler::Compile(function, Compiler::CLEAR_EXCEPTION);
   12640 
   12641   // First create a new map with the size and number of in-object properties
   12642   // suggested by the function.
   12643   InstanceType instance_type;
   12644   if (IsResumableFunction(function->shared()->kind())) {
   12645     instance_type = JS_GENERATOR_OBJECT_TYPE;
   12646   } else {
   12647     instance_type = JS_OBJECT_TYPE;
   12648   }
   12649   int instance_size;
   12650   int in_object_properties;
   12651   function->CalculateInstanceSize(instance_type, 0, &instance_size,
   12652                                   &in_object_properties);
   12653 
   12654   Handle<Map> map = isolate->factory()->NewMap(instance_type, instance_size);
   12655 
   12656   // Fetch or allocate prototype.
   12657   Handle<Object> prototype;
   12658   if (function->has_instance_prototype()) {
   12659     prototype = handle(function->instance_prototype(), isolate);
   12660   } else {
   12661     prototype = isolate->factory()->NewFunctionPrototype(function);
   12662   }
   12663   map->SetInObjectProperties(in_object_properties);
   12664   map->set_unused_property_fields(in_object_properties);
   12665   DCHECK(map->has_fast_object_elements());
   12666 
   12667   // Finally link initial map and constructor function.
   12668   DCHECK(prototype->IsJSReceiver());
   12669   JSFunction::SetInitialMap(function, map, prototype);
   12670   map->StartInobjectSlackTracking();
   12671 }
   12672 
   12673 
   12674 // static
   12675 MaybeHandle<Map> JSFunction::GetDerivedMap(Isolate* isolate,
   12676                                            Handle<JSFunction> constructor,
   12677                                            Handle<JSReceiver> new_target) {
   12678   EnsureHasInitialMap(constructor);
   12679 
   12680   Handle<Map> constructor_initial_map(constructor->initial_map(), isolate);
   12681   if (*new_target == *constructor) return constructor_initial_map;
   12682 
   12683   // Fast case, new.target is a subclass of constructor. The map is cacheable
   12684   // (and may already have been cached). new.target.prototype is guaranteed to
   12685   // be a JSReceiver.
   12686   if (new_target->IsJSFunction()) {
   12687     Handle<JSFunction> function = Handle<JSFunction>::cast(new_target);
   12688 
   12689     // Check that |function|'s initial map still in sync with the |constructor|,
   12690     // otherwise we must create a new initial map for |function|.
   12691     if (function->has_initial_map() &&
   12692         function->initial_map()->GetConstructor() == *constructor) {
   12693       return handle(function->initial_map(), isolate);
   12694     }
   12695 
   12696     // Create a new map with the size and number of in-object properties
   12697     // suggested by |function|.
   12698 
   12699     // Link initial map and constructor function if the new.target is actually a
   12700     // subclass constructor.
   12701     if (IsDerivedConstructor(function->shared()->kind())) {
   12702       Handle<Object> prototype(function->instance_prototype(), isolate);
   12703       InstanceType instance_type = constructor_initial_map->instance_type();
   12704       DCHECK(CanSubclassHaveInobjectProperties(instance_type));
   12705       int internal_fields =
   12706           JSObject::GetInternalFieldCount(*constructor_initial_map);
   12707       int pre_allocated = constructor_initial_map->GetInObjectProperties() -
   12708                           constructor_initial_map->unused_property_fields();
   12709       int instance_size;
   12710       int in_object_properties;
   12711       function->CalculateInstanceSizeForDerivedClass(
   12712           instance_type, internal_fields, &instance_size,
   12713           &in_object_properties);
   12714 
   12715       int unused_property_fields = in_object_properties - pre_allocated;
   12716       Handle<Map> map =
   12717           Map::CopyInitialMap(constructor_initial_map, instance_size,
   12718                               in_object_properties, unused_property_fields);
   12719       map->set_new_target_is_base(false);
   12720 
   12721       JSFunction::SetInitialMap(function, map, prototype);
   12722       map->SetConstructor(*constructor);
   12723       map->set_construction_counter(Map::kNoSlackTracking);
   12724       map->StartInobjectSlackTracking();
   12725       return map;
   12726     }
   12727   }
   12728 
   12729   // Slow path, new.target is either a proxy or can't cache the map.
   12730   // new.target.prototype is not guaranteed to be a JSReceiver, and may need to
   12731   // fall back to the intrinsicDefaultProto.
   12732   Handle<Object> prototype;
   12733   if (new_target->IsJSFunction()) {
   12734     Handle<JSFunction> function = Handle<JSFunction>::cast(new_target);
   12735     // Make sure the new.target.prototype is cached.
   12736     EnsureHasInitialMap(function);
   12737     prototype = handle(function->prototype(), isolate);
   12738   } else {
   12739     Handle<String> prototype_string = isolate->factory()->prototype_string();
   12740     ASSIGN_RETURN_ON_EXCEPTION(
   12741         isolate, prototype,
   12742         JSReceiver::GetProperty(new_target, prototype_string), Map);
   12743     // The above prototype lookup might change the constructor and its
   12744     // prototype, hence we have to reload the initial map.
   12745     EnsureHasInitialMap(constructor);
   12746     constructor_initial_map = handle(constructor->initial_map(), isolate);
   12747   }
   12748 
   12749   // If prototype is not a JSReceiver, fetch the intrinsicDefaultProto from the
   12750   // correct realm. Rather than directly fetching the .prototype, we fetch the
   12751   // constructor that points to the .prototype. This relies on
   12752   // constructor.prototype being FROZEN for those constructors.
   12753   if (!prototype->IsJSReceiver()) {
   12754     Handle<Context> context;
   12755     ASSIGN_RETURN_ON_EXCEPTION(isolate, context,
   12756                                JSReceiver::GetFunctionRealm(new_target), Map);
   12757     DCHECK(context->IsNativeContext());
   12758     Handle<Object> maybe_index = JSReceiver::GetDataProperty(
   12759         constructor, isolate->factory()->native_context_index_symbol());
   12760     int index = maybe_index->IsSmi() ? Smi::cast(*maybe_index)->value()
   12761                                      : Context::OBJECT_FUNCTION_INDEX;
   12762     Handle<JSFunction> realm_constructor(JSFunction::cast(context->get(index)));
   12763     prototype = handle(realm_constructor->prototype(), isolate);
   12764   }
   12765 
   12766   Handle<Map> map = Map::CopyInitialMap(constructor_initial_map);
   12767   map->set_new_target_is_base(false);
   12768   DCHECK(prototype->IsJSReceiver());
   12769   if (map->prototype() != *prototype) {
   12770     Map::SetPrototype(map, prototype, FAST_PROTOTYPE);
   12771   }
   12772   map->SetConstructor(*constructor);
   12773   return map;
   12774 }
   12775 
   12776 
   12777 void JSFunction::PrintName(FILE* out) {
   12778   std::unique_ptr<char[]> name = shared()->DebugName()->ToCString();
   12779   PrintF(out, "%s", name.get());
   12780 }
   12781 
   12782 
   12783 Handle<String> JSFunction::GetName(Handle<JSFunction> function) {
   12784   Isolate* isolate = function->GetIsolate();
   12785   Handle<Object> name =
   12786       JSReceiver::GetDataProperty(function, isolate->factory()->name_string());
   12787   if (name->IsString()) return Handle<String>::cast(name);
   12788   return handle(function->shared()->DebugName(), isolate);
   12789 }
   12790 
   12791 
   12792 Handle<String> JSFunction::GetDebugName(Handle<JSFunction> function) {
   12793   Isolate* isolate = function->GetIsolate();
   12794   Handle<Object> name = JSReceiver::GetDataProperty(
   12795       function, isolate->factory()->display_name_string());
   12796   if (name->IsString()) return Handle<String>::cast(name);
   12797   return JSFunction::GetName(function);
   12798 }
   12799 
   12800 void JSFunction::SetName(Handle<JSFunction> function, Handle<Name> name,
   12801                          Handle<String> prefix) {
   12802   Isolate* isolate = function->GetIsolate();
   12803   Handle<String> function_name = Name::ToFunctionName(name).ToHandleChecked();
   12804   if (prefix->length() > 0) {
   12805     IncrementalStringBuilder builder(isolate);
   12806     builder.AppendString(prefix);
   12807     builder.AppendCharacter(' ');
   12808     builder.AppendString(function_name);
   12809     function_name = builder.Finish().ToHandleChecked();
   12810   }
   12811   JSObject::DefinePropertyOrElementIgnoreAttributes(
   12812       function, isolate->factory()->name_string(), function_name,
   12813       static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY))
   12814       .ToHandleChecked();
   12815 }
   12816 
   12817 namespace {
   12818 
   12819 char const kNativeCodeSource[] = "function () { [native code] }";
   12820 
   12821 
   12822 Handle<String> NativeCodeFunctionSourceString(
   12823     Handle<SharedFunctionInfo> shared_info) {
   12824   Isolate* const isolate = shared_info->GetIsolate();
   12825   if (shared_info->name()->IsString()) {
   12826     IncrementalStringBuilder builder(isolate);
   12827     builder.AppendCString("function ");
   12828     builder.AppendString(handle(String::cast(shared_info->name()), isolate));
   12829     builder.AppendCString("() { [native code] }");
   12830     return builder.Finish().ToHandleChecked();
   12831   }
   12832   return isolate->factory()->NewStringFromAsciiChecked(kNativeCodeSource);
   12833 }
   12834 
   12835 }  // namespace
   12836 
   12837 
   12838 // static
   12839 Handle<String> JSBoundFunction::ToString(Handle<JSBoundFunction> function) {
   12840   Isolate* const isolate = function->GetIsolate();
   12841   return isolate->factory()->NewStringFromAsciiChecked(kNativeCodeSource);
   12842 }
   12843 
   12844 
   12845 // static
   12846 Handle<String> JSFunction::ToString(Handle<JSFunction> function) {
   12847   Isolate* const isolate = function->GetIsolate();
   12848   Handle<SharedFunctionInfo> shared_info(function->shared(), isolate);
   12849 
   12850   // Check if {function} should hide its source code.
   12851   if (!shared_info->IsUserJavaScript()) {
   12852     return NativeCodeFunctionSourceString(shared_info);
   12853   }
   12854 
   12855   // Check if we should print {function} as a class.
   12856   Handle<Object> class_start_position = JSReceiver::GetDataProperty(
   12857       function, isolate->factory()->class_start_position_symbol());
   12858   if (class_start_position->IsSmi()) {
   12859     Handle<Object> class_end_position = JSReceiver::GetDataProperty(
   12860         function, isolate->factory()->class_end_position_symbol());
   12861     Handle<String> script_source(
   12862         String::cast(Script::cast(shared_info->script())->source()), isolate);
   12863     return isolate->factory()->NewSubString(
   12864         script_source, Handle<Smi>::cast(class_start_position)->value(),
   12865         Handle<Smi>::cast(class_end_position)->value());
   12866   }
   12867 
   12868   // Check if we have source code for the {function}.
   12869   if (!shared_info->HasSourceCode()) {
   12870     return NativeCodeFunctionSourceString(shared_info);
   12871   }
   12872 
   12873   if (FLAG_harmony_function_tostring) {
   12874     return Handle<String>::cast(shared_info->GetSourceCodeHarmony());
   12875   }
   12876 
   12877   IncrementalStringBuilder builder(isolate);
   12878   FunctionKind kind = shared_info->kind();
   12879   if (!IsArrowFunction(kind)) {
   12880     if (IsConciseMethod(kind)) {
   12881       if (IsGeneratorFunction(kind)) {
   12882         builder.AppendCharacter('*');
   12883       } else if (IsAsyncFunction(kind)) {
   12884         builder.AppendCString("async ");
   12885       }
   12886     } else {
   12887       if (IsGeneratorFunction(kind)) {
   12888         builder.AppendCString("function* ");
   12889       } else if (IsAsyncFunction(kind)) {
   12890         builder.AppendCString("async function ");
   12891       } else {
   12892         builder.AppendCString("function ");
   12893       }
   12894     }
   12895     if (shared_info->name_should_print_as_anonymous()) {
   12896       builder.AppendCString("anonymous");
   12897     } else if (!shared_info->is_anonymous_expression()) {
   12898       builder.AppendString(handle(String::cast(shared_info->name()), isolate));
   12899     }
   12900   }
   12901   builder.AppendString(Handle<String>::cast(shared_info->GetSourceCode()));
   12902   return builder.Finish().ToHandleChecked();
   12903 }
   12904 
   12905 void Oddball::Initialize(Isolate* isolate, Handle<Oddball> oddball,
   12906                          const char* to_string, Handle<Object> to_number,
   12907                          const char* type_of, byte kind) {
   12908   Handle<String> internalized_to_string =
   12909       isolate->factory()->InternalizeUtf8String(to_string);
   12910   Handle<String> internalized_type_of =
   12911       isolate->factory()->InternalizeUtf8String(type_of);
   12912   oddball->set_to_number_raw(to_number->Number());
   12913   oddball->set_to_number(*to_number);
   12914   oddball->set_to_string(*internalized_to_string);
   12915   oddball->set_type_of(*internalized_type_of);
   12916   oddball->set_kind(kind);
   12917 }
   12918 
   12919 void Script::SetEvalOrigin(Handle<Script> script,
   12920                            Handle<SharedFunctionInfo> outer_info,
   12921                            int eval_position) {
   12922   if (eval_position == kNoSourcePosition) {
   12923     // If the position is missing, attempt to get the code offset from the
   12924     // current activation.  Do not translate the code offset into source
   12925     // position, but store it as negative value for lazy translation.
   12926     StackTraceFrameIterator it(script->GetIsolate());
   12927     if (!it.done() && it.is_javascript()) {
   12928       FrameSummary summary = FrameSummary::GetTop(it.javascript_frame());
   12929       script->set_eval_from_shared(summary.AsJavaScript().function()->shared());
   12930       script->set_eval_from_position(-summary.code_offset());
   12931       return;
   12932     }
   12933     eval_position = 0;
   12934   }
   12935   script->set_eval_from_shared(*outer_info);
   12936   script->set_eval_from_position(eval_position);
   12937 }
   12938 
   12939 int Script::GetEvalPosition() {
   12940   DisallowHeapAllocation no_gc;
   12941   DCHECK(compilation_type() == Script::COMPILATION_TYPE_EVAL);
   12942   int position = eval_from_position();
   12943   if (position < 0) {
   12944     // Due to laziness, the position may not have been translated from code
   12945     // offset yet, which would be encoded as negative integer. In that case,
   12946     // translate and set the position.
   12947     if (eval_from_shared()->IsUndefined(GetIsolate())) {
   12948       position = 0;
   12949     } else {
   12950       SharedFunctionInfo* shared = SharedFunctionInfo::cast(eval_from_shared());
   12951       position = shared->abstract_code()->SourcePosition(-position);
   12952     }
   12953     DCHECK(position >= 0);
   12954     set_eval_from_position(position);
   12955   }
   12956   return position;
   12957 }
   12958 
   12959 void Script::InitLineEnds(Handle<Script> script) {
   12960   Isolate* isolate = script->GetIsolate();
   12961   if (!script->line_ends()->IsUndefined(isolate)) return;
   12962   DCHECK_NE(Script::TYPE_WASM, script->type());
   12963 
   12964   Object* src_obj = script->source();
   12965   if (!src_obj->IsString()) {
   12966     DCHECK(src_obj->IsUndefined(isolate));
   12967     script->set_line_ends(isolate->heap()->empty_fixed_array());
   12968   } else {
   12969     DCHECK(src_obj->IsString());
   12970     Handle<String> src(String::cast(src_obj), isolate);
   12971     Handle<FixedArray> array = String::CalculateLineEnds(src, true);
   12972     script->set_line_ends(*array);
   12973   }
   12974 
   12975   DCHECK(script->line_ends()->IsFixedArray());
   12976 }
   12977 
   12978 bool Script::GetPositionInfo(Handle<Script> script, int position,
   12979                              PositionInfo* info, OffsetFlag offset_flag) {
   12980   // For wasm, we do not create an artificial line_ends array, but do the
   12981   // translation directly.
   12982   if (script->type() != Script::TYPE_WASM) InitLineEnds(script);
   12983   return script->GetPositionInfo(position, info, offset_flag);
   12984 }
   12985 
   12986 namespace {
   12987 bool GetPositionInfoSlow(const Script* script, int position,
   12988                          Script::PositionInfo* info) {
   12989   if (!script->source()->IsString()) return false;
   12990   if (position < 0) position = 0;
   12991 
   12992   String* source_string = String::cast(script->source());
   12993   int line = 0;
   12994   int line_start = 0;
   12995   int len = source_string->length();
   12996   for (int pos = 0; pos <= len; ++pos) {
   12997     if (pos == len || source_string->Get(pos) == '\n') {
   12998       if (position <= pos) {
   12999         info->line = line;
   13000         info->column = position - line_start;
   13001         info->line_start = line_start;
   13002         info->line_end = pos;
   13003         return true;
   13004       }
   13005       line++;
   13006       line_start = pos + 1;
   13007     }
   13008   }
   13009   return false;
   13010 }
   13011 }  // namespace
   13012 
   13013 #define SMI_VALUE(x) (Smi::cast(x)->value())
   13014 bool Script::GetPositionInfo(int position, PositionInfo* info,
   13015                              OffsetFlag offset_flag) const {
   13016   DisallowHeapAllocation no_allocation;
   13017 
   13018   // For wasm, we do not rely on the line_ends array, but do the translation
   13019   // directly.
   13020   if (type() == Script::TYPE_WASM) {
   13021     Handle<WasmCompiledModule> compiled_module(
   13022         WasmCompiledModule::cast(wasm_compiled_module()));
   13023     DCHECK_LE(0, position);
   13024     return compiled_module->GetPositionInfo(static_cast<uint32_t>(position),
   13025                                             info);
   13026   }
   13027 
   13028   if (line_ends()->IsUndefined(GetIsolate())) {
   13029     // Slow mode: we do not have line_ends. We have to iterate through source.
   13030     if (!GetPositionInfoSlow(this, position, info)) return false;
   13031   } else {
   13032     DCHECK(line_ends()->IsFixedArray());
   13033     FixedArray* ends = FixedArray::cast(line_ends());
   13034 
   13035     const int ends_len = ends->length();
   13036     if (ends_len == 0) return false;
   13037 
   13038     // Return early on invalid positions. Negative positions behave as if 0 was
   13039     // passed, and positions beyond the end of the script return as failure.
   13040     if (position < 0) {
   13041       position = 0;
   13042     } else if (position > SMI_VALUE(ends->get(ends_len - 1))) {
   13043       return false;
   13044     }
   13045 
   13046     // Determine line number by doing a binary search on the line ends array.
   13047     if (SMI_VALUE(ends->get(0)) >= position) {
   13048       info->line = 0;
   13049       info->line_start = 0;
   13050       info->column = position;
   13051     } else {
   13052       int left = 0;
   13053       int right = ends_len - 1;
   13054 
   13055       while (right > 0) {
   13056         DCHECK_LE(left, right);
   13057         const int mid = (left + right) / 2;
   13058         if (position > SMI_VALUE(ends->get(mid))) {
   13059           left = mid + 1;
   13060         } else if (position <= SMI_VALUE(ends->get(mid - 1))) {
   13061           right = mid - 1;
   13062         } else {
   13063           info->line = mid;
   13064           break;
   13065         }
   13066       }
   13067       DCHECK(SMI_VALUE(ends->get(info->line)) >= position &&
   13068              SMI_VALUE(ends->get(info->line - 1)) < position);
   13069       info->line_start = SMI_VALUE(ends->get(info->line - 1)) + 1;
   13070       info->column = position - info->line_start;
   13071     }
   13072 
   13073     // Line end is position of the linebreak character.
   13074     info->line_end = SMI_VALUE(ends->get(info->line));
   13075     if (info->line_end > 0) {
   13076       DCHECK(source()->IsString());
   13077       String* src = String::cast(source());
   13078       if (src->length() >= info->line_end &&
   13079           src->Get(info->line_end - 1) == '\r') {
   13080         info->line_end--;
   13081       }
   13082     }
   13083   }
   13084 
   13085   // Add offsets if requested.
   13086   if (offset_flag == WITH_OFFSET) {
   13087     if (info->line == 0) {
   13088       info->column += column_offset();
   13089     }
   13090     info->line += line_offset();
   13091   }
   13092 
   13093   return true;
   13094 }
   13095 #undef SMI_VALUE
   13096 
   13097 int Script::GetColumnNumber(Handle<Script> script, int code_pos) {
   13098   PositionInfo info;
   13099   GetPositionInfo(script, code_pos, &info, WITH_OFFSET);
   13100   return info.column;
   13101 }
   13102 
   13103 int Script::GetColumnNumber(int code_pos) const {
   13104   PositionInfo info;
   13105   GetPositionInfo(code_pos, &info, WITH_OFFSET);
   13106   return info.column;
   13107 }
   13108 
   13109 int Script::GetLineNumber(Handle<Script> script, int code_pos) {
   13110   PositionInfo info;
   13111   GetPositionInfo(script, code_pos, &info, WITH_OFFSET);
   13112   return info.line;
   13113 }
   13114 
   13115 int Script::GetLineNumber(int code_pos) const {
   13116   PositionInfo info;
   13117   GetPositionInfo(code_pos, &info, WITH_OFFSET);
   13118   return info.line;
   13119 }
   13120 
   13121 Object* Script::GetNameOrSourceURL() {
   13122   Isolate* isolate = GetIsolate();
   13123   // Keep in sync with ScriptNameOrSourceURL in messages.js.
   13124   if (!source_url()->IsUndefined(isolate)) return source_url();
   13125   return name();
   13126 }
   13127 
   13128 
   13129 Handle<JSObject> Script::GetWrapper(Handle<Script> script) {
   13130   Isolate* isolate = script->GetIsolate();
   13131   if (!script->wrapper()->IsUndefined(isolate)) {
   13132     DCHECK(script->wrapper()->IsWeakCell());
   13133     Handle<WeakCell> cell(WeakCell::cast(script->wrapper()));
   13134     if (!cell->cleared()) {
   13135       // Return a handle for the existing script wrapper from the cache.
   13136       return handle(JSObject::cast(cell->value()));
   13137     }
   13138     // If we found an empty WeakCell, that means the script wrapper was
   13139     // GCed.  We are not notified directly of that, so we decrement here
   13140     // so that we at least don't count double for any given script.
   13141     isolate->counters()->script_wrappers()->Decrement();
   13142   }
   13143   // Construct a new script wrapper.
   13144   isolate->counters()->script_wrappers()->Increment();
   13145   Handle<JSFunction> constructor = isolate->script_function();
   13146   Handle<JSValue> result =
   13147       Handle<JSValue>::cast(isolate->factory()->NewJSObject(constructor));
   13148   result->set_value(*script);
   13149   Handle<WeakCell> cell = isolate->factory()->NewWeakCell(result);
   13150   script->set_wrapper(*cell);
   13151   return result;
   13152 }
   13153 
   13154 MaybeHandle<SharedFunctionInfo> Script::FindSharedFunctionInfo(
   13155     Isolate* isolate, const FunctionLiteral* fun) {
   13156   DCHECK_NE(fun->function_literal_id(), FunctionLiteral::kIdTypeInvalid);
   13157   DCHECK_LT(fun->function_literal_id(), shared_function_infos()->length());
   13158   Object* shared = shared_function_infos()->get(fun->function_literal_id());
   13159   if (shared->IsUndefined(isolate) || WeakCell::cast(shared)->cleared()) {
   13160     return MaybeHandle<SharedFunctionInfo>();
   13161   }
   13162   return handle(SharedFunctionInfo::cast(WeakCell::cast(shared)->value()));
   13163 }
   13164 
   13165 Script::Iterator::Iterator(Isolate* isolate)
   13166     : iterator_(isolate->heap()->script_list()) {}
   13167 
   13168 
   13169 Script* Script::Iterator::Next() { return iterator_.Next<Script>(); }
   13170 
   13171 SharedFunctionInfo::ScriptIterator::ScriptIterator(Handle<Script> script)
   13172     : ScriptIterator(script->GetIsolate(),
   13173                      handle(script->shared_function_infos())) {}
   13174 
   13175 SharedFunctionInfo::ScriptIterator::ScriptIterator(
   13176     Isolate* isolate, Handle<FixedArray> shared_function_infos)
   13177     : isolate_(isolate),
   13178       shared_function_infos_(shared_function_infos),
   13179       index_(0) {}
   13180 
   13181 SharedFunctionInfo* SharedFunctionInfo::ScriptIterator::Next() {
   13182   while (index_ < shared_function_infos_->length()) {
   13183     Object* raw = shared_function_infos_->get(index_++);
   13184     if (raw->IsUndefined(isolate_) || WeakCell::cast(raw)->cleared()) continue;
   13185     return SharedFunctionInfo::cast(WeakCell::cast(raw)->value());
   13186   }
   13187   return nullptr;
   13188 }
   13189 
   13190 void SharedFunctionInfo::ScriptIterator::Reset(Handle<Script> script) {
   13191   shared_function_infos_ = handle(script->shared_function_infos());
   13192   index_ = 0;
   13193 }
   13194 
   13195 SharedFunctionInfo::GlobalIterator::GlobalIterator(Isolate* isolate)
   13196     : script_iterator_(isolate),
   13197       noscript_sfi_iterator_(isolate->heap()->noscript_shared_function_infos()),
   13198       sfi_iterator_(handle(script_iterator_.Next(), isolate)) {}
   13199 
   13200 SharedFunctionInfo* SharedFunctionInfo::GlobalIterator::Next() {
   13201   SharedFunctionInfo* next = noscript_sfi_iterator_.Next<SharedFunctionInfo>();
   13202   if (next != nullptr) return next;
   13203   for (;;) {
   13204     next = sfi_iterator_.Next();
   13205     if (next != nullptr) return next;
   13206     Script* next_script = script_iterator_.Next();
   13207     if (next_script == nullptr) return nullptr;
   13208     sfi_iterator_.Reset(handle(next_script));
   13209   }
   13210 }
   13211 
   13212 
   13213 void SharedFunctionInfo::SetScript(Handle<SharedFunctionInfo> shared,
   13214                                    Handle<Object> script_object) {
   13215   DCHECK_NE(shared->function_literal_id(), FunctionLiteral::kIdTypeInvalid);
   13216   if (shared->script() == *script_object) return;
   13217   Isolate* isolate = shared->GetIsolate();
   13218 
   13219   // Add shared function info to new script's list. If a collection occurs,
   13220   // the shared function info may be temporarily in two lists.
   13221   // This is okay because the gc-time processing of these lists can tolerate
   13222   // duplicates.
   13223   if (script_object->IsScript()) {
   13224     Handle<Script> script = Handle<Script>::cast(script_object);
   13225     Handle<FixedArray> list = handle(script->shared_function_infos(), isolate);
   13226 #ifdef DEBUG
   13227     DCHECK_LT(shared->function_literal_id(), list->length());
   13228     if (list->get(shared->function_literal_id())->IsWeakCell() &&
   13229         !WeakCell::cast(list->get(shared->function_literal_id()))->cleared()) {
   13230       DCHECK(
   13231           WeakCell::cast(list->get(shared->function_literal_id()))->value() ==
   13232           *shared);
   13233     }
   13234 #endif
   13235     Handle<WeakCell> cell = isolate->factory()->NewWeakCell(shared);
   13236     list->set(shared->function_literal_id(), *cell);
   13237   } else {
   13238     Handle<Object> list = isolate->factory()->noscript_shared_function_infos();
   13239 
   13240 #ifdef DEBUG
   13241     if (FLAG_enable_slow_asserts) {
   13242       WeakFixedArray::Iterator iterator(*list);
   13243       SharedFunctionInfo* next;
   13244       while ((next = iterator.Next<SharedFunctionInfo>())) {
   13245         DCHECK_NE(next, *shared);
   13246       }
   13247     }
   13248 #endif  // DEBUG
   13249 
   13250     list = WeakFixedArray::Add(list, shared);
   13251 
   13252     isolate->heap()->SetRootNoScriptSharedFunctionInfos(*list);
   13253   }
   13254 
   13255   if (shared->script()->IsScript()) {
   13256     // Remove shared function info from old script's list.
   13257     Script* old_script = Script::cast(shared->script());
   13258 
   13259     // Due to liveedit, it might happen that the old_script doesn't know
   13260     // about the SharedFunctionInfo, so we have to guard against that.
   13261     Handle<FixedArray> infos(old_script->shared_function_infos(), isolate);
   13262     if (shared->function_literal_id() < infos->length()) {
   13263       Object* raw = old_script->shared_function_infos()->get(
   13264           shared->function_literal_id());
   13265       if (!raw->IsWeakCell() || WeakCell::cast(raw)->value() == *shared) {
   13266         old_script->shared_function_infos()->set(
   13267             shared->function_literal_id(), isolate->heap()->undefined_value());
   13268       }
   13269     }
   13270   } else {
   13271     // Remove shared function info from root array.
   13272     Object* list = isolate->heap()->noscript_shared_function_infos();
   13273     CHECK(WeakFixedArray::cast(list)->Remove(shared));
   13274   }
   13275 
   13276   // Finally set new script.
   13277   shared->set_script(*script_object);
   13278 }
   13279 
   13280 
   13281 String* SharedFunctionInfo::DebugName() {
   13282   Object* n = name();
   13283   if (!n->IsString() || String::cast(n)->length() == 0) return inferred_name();
   13284   return String::cast(n);
   13285 }
   13286 
   13287 bool SharedFunctionInfo::HasNoSideEffect() {
   13288   if (!computed_has_no_side_effect()) {
   13289     DisallowHeapAllocation not_handlified;
   13290     Handle<SharedFunctionInfo> info(this);
   13291     set_has_no_side_effect(DebugEvaluate::FunctionHasNoSideEffect(info));
   13292     set_computed_has_no_side_effect(true);
   13293   }
   13294   return has_no_side_effect();
   13295 }
   13296 
   13297 // The filter is a pattern that matches function names in this way:
   13298 //   "*"      all; the default
   13299 //   "-"      all but the top-level function
   13300 //   "-name"  all but the function "name"
   13301 //   ""       only the top-level function
   13302 //   "name"   only the function "name"
   13303 //   "name*"  only functions starting with "name"
   13304 //   "~"      none; the tilde is not an identifier
   13305 bool SharedFunctionInfo::PassesFilter(const char* raw_filter) {
   13306   if (*raw_filter == '*') return true;
   13307   String* name = DebugName();
   13308   Vector<const char> filter = CStrVector(raw_filter);
   13309   if (filter.length() == 0) return name->length() == 0;
   13310   if (filter[0] == '-') {
   13311     // Negative filter.
   13312     if (filter.length() == 1) {
   13313       return (name->length() != 0);
   13314     } else if (name->IsUtf8EqualTo(filter.SubVector(1, filter.length()))) {
   13315       return false;
   13316     }
   13317     if (filter[filter.length() - 1] == '*' &&
   13318         name->IsUtf8EqualTo(filter.SubVector(1, filter.length() - 1), true)) {
   13319       return false;
   13320     }
   13321     return true;
   13322 
   13323   } else if (name->IsUtf8EqualTo(filter)) {
   13324     return true;
   13325   }
   13326   if (filter[filter.length() - 1] == '*' &&
   13327       name->IsUtf8EqualTo(filter.SubVector(0, filter.length() - 1), true)) {
   13328     return true;
   13329   }
   13330   return false;
   13331 }
   13332 
   13333 bool SharedFunctionInfo::HasSourceCode() const {
   13334   Isolate* isolate = GetIsolate();
   13335   return !script()->IsUndefined(isolate) &&
   13336          !reinterpret_cast<Script*>(script())->source()->IsUndefined(isolate);
   13337 }
   13338 
   13339 
   13340 Handle<Object> SharedFunctionInfo::GetSourceCode() {
   13341   if (!HasSourceCode()) return GetIsolate()->factory()->undefined_value();
   13342   Handle<String> source(String::cast(Script::cast(script())->source()));
   13343   return GetIsolate()->factory()->NewSubString(
   13344       source, start_position(), end_position());
   13345 }
   13346 
   13347 Handle<Object> SharedFunctionInfo::GetSourceCodeHarmony() {
   13348   Isolate* isolate = GetIsolate();
   13349   if (!HasSourceCode()) return isolate->factory()->undefined_value();
   13350   Handle<String> script_source(String::cast(Script::cast(script())->source()));
   13351   int start_pos = function_token_position();
   13352   if (start_pos == kNoSourcePosition) start_pos = start_position();
   13353   return isolate->factory()->NewSubString(script_source, start_pos,
   13354                                           end_position());
   13355 }
   13356 
   13357 bool SharedFunctionInfo::IsInlineable() {
   13358   // Check that the function has a script associated with it.
   13359   if (!script()->IsScript()) return false;
   13360   return !optimization_disabled();
   13361 }
   13362 
   13363 
   13364 int SharedFunctionInfo::SourceSize() {
   13365   return end_position() - start_position();
   13366 }
   13367 
   13368 void JSFunction::CalculateInstanceSizeHelper(InstanceType instance_type,
   13369                                              int requested_internal_fields,
   13370                                              int requested_in_object_properties,
   13371                                              int* instance_size,
   13372                                              int* in_object_properties) {
   13373   int header_size = JSObject::GetHeaderSize(instance_type);
   13374   DCHECK_LE(requested_internal_fields,
   13375             (JSObject::kMaxInstanceSize - header_size) >> kPointerSizeLog2);
   13376   *instance_size =
   13377       Min(header_size +
   13378               ((requested_internal_fields + requested_in_object_properties)
   13379                << kPointerSizeLog2),
   13380           JSObject::kMaxInstanceSize);
   13381   *in_object_properties = ((*instance_size - header_size) >> kPointerSizeLog2) -
   13382                           requested_internal_fields;
   13383 }
   13384 
   13385 
   13386 void JSFunction::CalculateInstanceSize(InstanceType instance_type,
   13387                                        int requested_internal_fields,
   13388                                        int* instance_size,
   13389                                        int* in_object_properties) {
   13390   CalculateInstanceSizeHelper(instance_type, requested_internal_fields,
   13391                               shared()->expected_nof_properties(),
   13392                               instance_size, in_object_properties);
   13393 }
   13394 
   13395 
   13396 void JSFunction::CalculateInstanceSizeForDerivedClass(
   13397     InstanceType instance_type, int requested_internal_fields,
   13398     int* instance_size, int* in_object_properties) {
   13399   Isolate* isolate = GetIsolate();
   13400   int expected_nof_properties = 0;
   13401   for (PrototypeIterator iter(isolate, this, kStartAtReceiver); !iter.IsAtEnd();
   13402        iter.Advance()) {
   13403     JSReceiver* current = iter.GetCurrent<JSReceiver>();
   13404     if (!current->IsJSFunction()) break;
   13405     JSFunction* func = JSFunction::cast(current);
   13406     SharedFunctionInfo* shared = func->shared();
   13407     expected_nof_properties += shared->expected_nof_properties();
   13408     if (!IsDerivedConstructor(shared->kind())) {
   13409       break;
   13410     }
   13411   }
   13412   CalculateInstanceSizeHelper(instance_type, requested_internal_fields,
   13413                               expected_nof_properties, instance_size,
   13414                               in_object_properties);
   13415 }
   13416 
   13417 
   13418 // Output the source code without any allocation in the heap.
   13419 std::ostream& operator<<(std::ostream& os, const SourceCodeOf& v) {
   13420   const SharedFunctionInfo* s = v.value;
   13421   // For some native functions there is no source.
   13422   if (!s->HasSourceCode()) return os << "<No Source>";
   13423 
   13424   // Get the source for the script which this function came from.
   13425   // Don't use String::cast because we don't want more assertion errors while
   13426   // we are already creating a stack dump.
   13427   String* script_source =
   13428       reinterpret_cast<String*>(Script::cast(s->script())->source());
   13429 
   13430   if (!script_source->LooksValid()) return os << "<Invalid Source>";
   13431 
   13432   if (!s->is_toplevel()) {
   13433     os << "function ";
   13434     Object* name = s->name();
   13435     if (name->IsString() && String::cast(name)->length() > 0) {
   13436       String::cast(name)->PrintUC16(os);
   13437     }
   13438   }
   13439 
   13440   int len = s->end_position() - s->start_position();
   13441   if (len <= v.max_length || v.max_length < 0) {
   13442     script_source->PrintUC16(os, s->start_position(), s->end_position());
   13443     return os;
   13444   } else {
   13445     script_source->PrintUC16(os, s->start_position(),
   13446                              s->start_position() + v.max_length);
   13447     return os << "...\n";
   13448   }
   13449 }
   13450 
   13451 
   13452 static bool IsCodeEquivalent(Code* code, Code* recompiled) {
   13453   if (code->instruction_size() != recompiled->instruction_size()) return false;
   13454   ByteArray* code_relocation = code->relocation_info();
   13455   ByteArray* recompiled_relocation = recompiled->relocation_info();
   13456   int length = code_relocation->length();
   13457   if (length != recompiled_relocation->length()) return false;
   13458   int compare = memcmp(code_relocation->GetDataStartAddress(),
   13459                        recompiled_relocation->GetDataStartAddress(),
   13460                        length);
   13461   return compare == 0;
   13462 }
   13463 
   13464 
   13465 void SharedFunctionInfo::EnableDeoptimizationSupport(Code* recompiled) {
   13466   DCHECK(!has_deoptimization_support());
   13467   DisallowHeapAllocation no_allocation;
   13468   Code* code = this->code();
   13469   if (IsCodeEquivalent(code, recompiled)) {
   13470     // Copy the deoptimization data from the recompiled code.
   13471     code->set_deoptimization_data(recompiled->deoptimization_data());
   13472     code->set_has_deoptimization_support(true);
   13473   } else {
   13474     // TODO(3025757): In case the recompiled isn't equivalent to the
   13475     // old code, we have to replace it. We should try to avoid this
   13476     // altogether because it flushes valuable type feedback by
   13477     // effectively resetting all IC state.
   13478     ReplaceCode(recompiled);
   13479   }
   13480   DCHECK(has_deoptimization_support());
   13481 }
   13482 
   13483 
   13484 void SharedFunctionInfo::DisableOptimization(BailoutReason reason) {
   13485   // Disable optimization for the shared function info and mark the
   13486   // code as non-optimizable. The marker on the shared function info
   13487   // is there because we flush non-optimized code thereby loosing the
   13488   // non-optimizable information for the code. When the code is
   13489   // regenerated and set on the shared function info it is marked as
   13490   // non-optimizable if optimization is disabled for the shared
   13491   // function info.
   13492   DCHECK(reason != kNoReason);
   13493   set_optimization_disabled(true);
   13494   set_disable_optimization_reason(reason);
   13495   // Code should be the lazy compilation stub or else unoptimized.
   13496   DCHECK(abstract_code()->kind() == AbstractCode::FUNCTION ||
   13497          abstract_code()->kind() == AbstractCode::INTERPRETED_FUNCTION ||
   13498          abstract_code()->kind() == AbstractCode::BUILTIN);
   13499   PROFILE(GetIsolate(), CodeDisableOptEvent(abstract_code(), this));
   13500   if (FLAG_trace_opt) {
   13501     PrintF("[disabled optimization for ");
   13502     ShortPrint();
   13503     PrintF(", reason: %s]\n", GetBailoutReason(reason));
   13504   }
   13505 }
   13506 
   13507 namespace {
   13508 
   13509 // Sets the expected number of properties based on estimate from parser.
   13510 void SetExpectedNofPropertiesFromEstimate(Handle<SharedFunctionInfo> shared,
   13511                                           FunctionLiteral* literal) {
   13512   int estimate = literal->expected_property_count();
   13513 
   13514   // If no properties are added in the constructor, they are more likely
   13515   // to be added later.
   13516   if (estimate == 0) estimate = 2;
   13517 
   13518   // TODO(yangguo): check whether those heuristics are still up-to-date.
   13519   // We do not shrink objects that go into a snapshot (yet), so we adjust
   13520   // the estimate conservatively.
   13521   if (shared->GetIsolate()->serializer_enabled()) {
   13522     estimate += 2;
   13523   } else {
   13524     // Inobject slack tracking will reclaim redundant inobject space later,
   13525     // so we can afford to adjust the estimate generously.
   13526     estimate += 8;
   13527   }
   13528 
   13529   shared->set_expected_nof_properties(estimate);
   13530 }
   13531 
   13532 }  // namespace
   13533 
   13534 void SharedFunctionInfo::InitFromFunctionLiteral(
   13535     Handle<SharedFunctionInfo> shared_info, FunctionLiteral* lit) {
   13536   // When adding fields here, make sure DeclarationScope::AnalyzePartially is
   13537   // updated accordingly.
   13538   shared_info->set_length(lit->function_length());
   13539   shared_info->set_internal_formal_parameter_count(lit->parameter_count());
   13540   shared_info->set_function_token_position(lit->function_token_position());
   13541   shared_info->set_start_position(lit->start_position());
   13542   shared_info->set_end_position(lit->end_position());
   13543   shared_info->set_is_declaration(lit->is_declaration());
   13544   shared_info->set_is_named_expression(lit->is_named_expression());
   13545   shared_info->set_is_anonymous_expression(lit->is_anonymous_expression());
   13546   shared_info->set_inferred_name(*lit->inferred_name());
   13547   shared_info->set_allows_lazy_compilation(lit->AllowsLazyCompilation());
   13548   shared_info->set_language_mode(lit->language_mode());
   13549   shared_info->set_uses_arguments(lit->scope()->arguments() != NULL);
   13550   shared_info->set_has_duplicate_parameters(lit->has_duplicate_parameters());
   13551   shared_info->set_kind(lit->kind());
   13552   if (!IsConstructable(lit->kind(), lit->language_mode())) {
   13553     shared_info->SetConstructStub(
   13554         *shared_info->GetIsolate()->builtins()->ConstructedNonConstructable());
   13555   }
   13556   shared_info->set_needs_home_object(lit->scope()->NeedsHomeObject());
   13557   shared_info->set_asm_function(lit->scope()->asm_function());
   13558   shared_info->set_function_literal_id(lit->function_literal_id());
   13559   SetExpectedNofPropertiesFromEstimate(shared_info, lit);
   13560 }
   13561 
   13562 
   13563 bool SharedFunctionInfo::VerifyBailoutId(BailoutId id) {
   13564   DCHECK(!id.IsNone());
   13565   Code* unoptimized = code();
   13566   DeoptimizationOutputData* data =
   13567       DeoptimizationOutputData::cast(unoptimized->deoptimization_data());
   13568   unsigned ignore = Deoptimizer::GetOutputInfo(data, id, this);
   13569   USE(ignore);
   13570   return true;  // Return true if there was no DCHECK.
   13571 }
   13572 
   13573 void SharedFunctionInfo::SetConstructStub(Code* code) {
   13574   if (code->kind() == Code::BUILTIN) code->set_is_construct_stub(true);
   13575   set_construct_stub(code);
   13576 }
   13577 
   13578 void Map::StartInobjectSlackTracking() {
   13579   DCHECK(!IsInobjectSlackTrackingInProgress());
   13580 
   13581   // No tracking during the snapshot construction phase.
   13582   Isolate* isolate = GetIsolate();
   13583   if (isolate->serializer_enabled()) return;
   13584 
   13585   if (unused_property_fields() == 0) return;
   13586 
   13587   set_construction_counter(Map::kSlackTrackingCounterStart);
   13588 }
   13589 
   13590 
   13591 void SharedFunctionInfo::ResetForNewContext(int new_ic_age) {
   13592   code()->ClearInlineCaches();
   13593   set_ic_age(new_ic_age);
   13594   if (code()->kind() == Code::FUNCTION) {
   13595     code()->set_profiler_ticks(0);
   13596     if (optimization_disabled() && opt_count() >= FLAG_max_opt_count) {
   13597       // Re-enable optimizations if they were disabled due to opt_count limit.
   13598       set_optimization_disabled(false);
   13599     }
   13600     set_opt_count(0);
   13601     set_deopt_count(0);
   13602   } else if (IsInterpreted()) {
   13603     set_profiler_ticks(0);
   13604     if (optimization_disabled() && opt_count() >= FLAG_max_opt_count) {
   13605       // Re-enable optimizations if they were disabled due to opt_count limit.
   13606       set_optimization_disabled(false);
   13607     }
   13608     set_opt_count(0);
   13609     set_deopt_count(0);
   13610   }
   13611 }
   13612 
   13613 int SharedFunctionInfo::SearchOptimizedCodeMapEntry(Context* native_context) {
   13614   DisallowHeapAllocation no_gc;
   13615   DCHECK(native_context->IsNativeContext());
   13616   if (!OptimizedCodeMapIsCleared()) {
   13617     FixedArray* optimized_code_map = this->optimized_code_map();
   13618     int length = optimized_code_map->length();
   13619     for (int i = kEntriesStart; i < length; i += kEntryLength) {
   13620       if (WeakCell::cast(optimized_code_map->get(i + kContextOffset))
   13621               ->value() == native_context) {
   13622         return i;
   13623       }
   13624     }
   13625   }
   13626   return -1;
   13627 }
   13628 
   13629 void SharedFunctionInfo::ClearCodeFromOptimizedCodeMap() {
   13630   if (!OptimizedCodeMapIsCleared()) {
   13631     FixedArray* optimized_code_map = this->optimized_code_map();
   13632     int length = optimized_code_map->length();
   13633     WeakCell* empty_weak_cell = GetHeap()->empty_weak_cell();
   13634     for (int i = kEntriesStart; i < length; i += kEntryLength) {
   13635       optimized_code_map->set(i + kCachedCodeOffset, empty_weak_cell,
   13636                               SKIP_WRITE_BARRIER);
   13637     }
   13638   }
   13639 }
   13640 
   13641 Code* SharedFunctionInfo::SearchOptimizedCodeMap(Context* native_context,
   13642                                                  BailoutId osr_ast_id) {
   13643   Code* result = nullptr;
   13644   if (!osr_ast_id.IsNone()) {
   13645     return native_context->SearchOptimizedCodeMap(this, osr_ast_id);
   13646   }
   13647 
   13648   DCHECK(osr_ast_id.IsNone());
   13649   int entry = SearchOptimizedCodeMapEntry(native_context);
   13650   if (entry != kNotFound) {
   13651     FixedArray* code_map = optimized_code_map();
   13652     DCHECK_LE(entry + kEntryLength, code_map->length());
   13653     WeakCell* cell = WeakCell::cast(code_map->get(entry + kCachedCodeOffset));
   13654     result = cell->cleared() ? nullptr : Code::cast(cell->value());
   13655   }
   13656   return result;
   13657 }
   13658 
   13659 
   13660 #define DECLARE_TAG(ignore1, name, ignore2) name,
   13661 const char* const VisitorSynchronization::kTags[
   13662     VisitorSynchronization::kNumberOfSyncTags] = {
   13663   VISITOR_SYNCHRONIZATION_TAGS_LIST(DECLARE_TAG)
   13664 };
   13665 #undef DECLARE_TAG
   13666 
   13667 
   13668 #define DECLARE_TAG(ignore1, ignore2, name) name,
   13669 const char* const VisitorSynchronization::kTagNames[
   13670     VisitorSynchronization::kNumberOfSyncTags] = {
   13671   VISITOR_SYNCHRONIZATION_TAGS_LIST(DECLARE_TAG)
   13672 };
   13673 #undef DECLARE_TAG
   13674 
   13675 
   13676 void ObjectVisitor::VisitCodeTarget(RelocInfo* rinfo) {
   13677   DCHECK(RelocInfo::IsCodeTarget(rinfo->rmode()));
   13678   Object* old_pointer = Code::GetCodeFromTargetAddress(rinfo->target_address());
   13679   Object* new_pointer = old_pointer;
   13680   VisitPointer(&new_pointer);
   13681   DCHECK_EQ(old_pointer, new_pointer);
   13682 }
   13683 
   13684 
   13685 void ObjectVisitor::VisitCodeAgeSequence(RelocInfo* rinfo) {
   13686   DCHECK(RelocInfo::IsCodeAgeSequence(rinfo->rmode()));
   13687   Object* old_pointer = rinfo->code_age_stub();
   13688   Object* new_pointer = old_pointer;
   13689   if (old_pointer != nullptr) {
   13690     VisitPointer(&new_pointer);
   13691     DCHECK_EQ(old_pointer, new_pointer);
   13692   }
   13693 }
   13694 
   13695 
   13696 void ObjectVisitor::VisitCodeEntry(Address entry_address) {
   13697   Object* old_pointer = Code::GetObjectFromEntryAddress(entry_address);
   13698   Object* new_pointer = old_pointer;
   13699   VisitPointer(&new_pointer);
   13700   DCHECK_EQ(old_pointer, new_pointer);
   13701 }
   13702 
   13703 
   13704 void ObjectVisitor::VisitCell(RelocInfo* rinfo) {
   13705   DCHECK(rinfo->rmode() == RelocInfo::CELL);
   13706   Object* old_pointer = rinfo->target_cell();
   13707   Object* new_pointer = old_pointer;
   13708   VisitPointer(&new_pointer);
   13709   DCHECK_EQ(old_pointer, new_pointer);
   13710 }
   13711 
   13712 
   13713 void ObjectVisitor::VisitDebugTarget(RelocInfo* rinfo) {
   13714   DCHECK(RelocInfo::IsDebugBreakSlot(rinfo->rmode()) &&
   13715          rinfo->IsPatchedDebugBreakSlotSequence());
   13716   Object* old_pointer =
   13717       Code::GetCodeFromTargetAddress(rinfo->debug_call_address());
   13718   Object* new_pointer = old_pointer;
   13719   VisitPointer(&new_pointer);
   13720   DCHECK_EQ(old_pointer, new_pointer);
   13721 }
   13722 
   13723 
   13724 void ObjectVisitor::VisitEmbeddedPointer(RelocInfo* rinfo) {
   13725   DCHECK(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT);
   13726   Object* old_pointer = rinfo->target_object();
   13727   Object* new_pointer = old_pointer;
   13728   VisitPointer(&new_pointer);
   13729   DCHECK_EQ(old_pointer, new_pointer);
   13730 }
   13731 
   13732 
   13733 void ObjectVisitor::VisitExternalReference(RelocInfo* rinfo) {
   13734   Address old_reference = rinfo->target_external_reference();
   13735   Address new_reference = old_reference;
   13736   VisitExternalReference(&new_reference);
   13737   DCHECK_EQ(old_reference, new_reference);
   13738 }
   13739 
   13740 
   13741 void Code::InvalidateRelocation() {
   13742   InvalidateEmbeddedObjects();
   13743   set_relocation_info(GetHeap()->empty_byte_array());
   13744 }
   13745 
   13746 
   13747 void Code::InvalidateEmbeddedObjects() {
   13748   Object* undefined = GetHeap()->undefined_value();
   13749   Cell* undefined_cell = GetHeap()->undefined_cell();
   13750   int mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
   13751                   RelocInfo::ModeMask(RelocInfo::CELL);
   13752   for (RelocIterator it(this, mode_mask); !it.done(); it.next()) {
   13753     RelocInfo::Mode mode = it.rinfo()->rmode();
   13754     if (mode == RelocInfo::EMBEDDED_OBJECT) {
   13755       it.rinfo()->set_target_object(undefined, SKIP_WRITE_BARRIER);
   13756     } else if (mode == RelocInfo::CELL) {
   13757       it.rinfo()->set_target_cell(undefined_cell, SKIP_WRITE_BARRIER);
   13758     }
   13759   }
   13760 }
   13761 
   13762 
   13763 void Code::Relocate(intptr_t delta) {
   13764   for (RelocIterator it(this, RelocInfo::kApplyMask); !it.done(); it.next()) {
   13765     it.rinfo()->apply(delta);
   13766   }
   13767   Assembler::FlushICache(GetIsolate(), instruction_start(), instruction_size());
   13768 }
   13769 
   13770 
   13771 void Code::CopyFrom(const CodeDesc& desc) {
   13772   // copy code
   13773   CopyBytes(instruction_start(), desc.buffer,
   13774             static_cast<size_t>(desc.instr_size));
   13775 
   13776   // copy unwinding info, if any
   13777   if (desc.unwinding_info) {
   13778     DCHECK_GT(desc.unwinding_info_size, 0);
   13779     set_unwinding_info_size(desc.unwinding_info_size);
   13780     CopyBytes(unwinding_info_start(), desc.unwinding_info,
   13781               static_cast<size_t>(desc.unwinding_info_size));
   13782   }
   13783 
   13784   // copy reloc info
   13785   CopyBytes(relocation_start(),
   13786             desc.buffer + desc.buffer_size - desc.reloc_size,
   13787             static_cast<size_t>(desc.reloc_size));
   13788 
   13789   // unbox handles and relocate
   13790   intptr_t delta = instruction_start() - desc.buffer;
   13791   int mode_mask = RelocInfo::kCodeTargetMask |
   13792                   RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
   13793                   RelocInfo::ModeMask(RelocInfo::CELL) |
   13794                   RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY) |
   13795                   RelocInfo::kApplyMask;
   13796   // Needed to find target_object and runtime_entry on X64
   13797   Assembler* origin = desc.origin;
   13798   AllowDeferredHandleDereference embedding_raw_address;
   13799   for (RelocIterator it(this, mode_mask); !it.done(); it.next()) {
   13800     RelocInfo::Mode mode = it.rinfo()->rmode();
   13801     if (mode == RelocInfo::EMBEDDED_OBJECT) {
   13802       Handle<Object> p = it.rinfo()->target_object_handle(origin);
   13803       it.rinfo()->set_target_object(*p, UPDATE_WRITE_BARRIER,
   13804                                     SKIP_ICACHE_FLUSH);
   13805     } else if (mode == RelocInfo::CELL) {
   13806       Handle<Cell> cell  = it.rinfo()->target_cell_handle();
   13807       it.rinfo()->set_target_cell(*cell, UPDATE_WRITE_BARRIER,
   13808                                   SKIP_ICACHE_FLUSH);
   13809     } else if (RelocInfo::IsCodeTarget(mode)) {
   13810       // rewrite code handles in inline cache targets to direct
   13811       // pointers to the first instruction in the code object
   13812       Handle<Object> p = it.rinfo()->target_object_handle(origin);
   13813       Code* code = Code::cast(*p);
   13814       it.rinfo()->set_target_address(code->instruction_start(),
   13815                                      UPDATE_WRITE_BARRIER, SKIP_ICACHE_FLUSH);
   13816     } else if (RelocInfo::IsRuntimeEntry(mode)) {
   13817       Address p = it.rinfo()->target_runtime_entry(origin);
   13818       it.rinfo()->set_target_runtime_entry(p, UPDATE_WRITE_BARRIER,
   13819                                            SKIP_ICACHE_FLUSH);
   13820     } else if (mode == RelocInfo::CODE_AGE_SEQUENCE) {
   13821       Handle<Object> p = it.rinfo()->code_age_stub_handle(origin);
   13822       Code* code = Code::cast(*p);
   13823       it.rinfo()->set_code_age_stub(code, SKIP_ICACHE_FLUSH);
   13824     } else {
   13825       it.rinfo()->apply(delta);
   13826     }
   13827   }
   13828   Assembler::FlushICache(GetIsolate(), instruction_start(), instruction_size());
   13829 }
   13830 
   13831 
   13832 SafepointEntry Code::GetSafepointEntry(Address pc) {
   13833   SafepointTable table(this);
   13834   return table.FindEntry(pc);
   13835 }
   13836 
   13837 
   13838 Object* Code::FindNthObject(int n, Map* match_map) {
   13839   DCHECK(is_inline_cache_stub());
   13840   DisallowHeapAllocation no_allocation;
   13841   int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
   13842   for (RelocIterator it(this, mask); !it.done(); it.next()) {
   13843     RelocInfo* info = it.rinfo();
   13844     Object* object = info->target_object();
   13845     if (object->IsWeakCell()) object = WeakCell::cast(object)->value();
   13846     if (object->IsHeapObject()) {
   13847       if (HeapObject::cast(object)->map() == match_map) {
   13848         if (--n == 0) return object;
   13849       }
   13850     }
   13851   }
   13852   return NULL;
   13853 }
   13854 
   13855 
   13856 AllocationSite* Code::FindFirstAllocationSite() {
   13857   Object* result = FindNthObject(1, GetHeap()->allocation_site_map());
   13858   return (result != NULL) ? AllocationSite::cast(result) : NULL;
   13859 }
   13860 
   13861 
   13862 Map* Code::FindFirstMap() {
   13863   Object* result = FindNthObject(1, GetHeap()->meta_map());
   13864   return (result != NULL) ? Map::cast(result) : NULL;
   13865 }
   13866 
   13867 
   13868 void Code::FindAndReplace(const FindAndReplacePattern& pattern) {
   13869   DCHECK(is_inline_cache_stub() || is_handler());
   13870   DisallowHeapAllocation no_allocation;
   13871   int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
   13872   STATIC_ASSERT(FindAndReplacePattern::kMaxCount < 32);
   13873   int current_pattern = 0;
   13874   for (RelocIterator it(this, mask); !it.done(); it.next()) {
   13875     RelocInfo* info = it.rinfo();
   13876     Object* object = info->target_object();
   13877     if (object->IsHeapObject()) {
   13878       if (object->IsWeakCell()) {
   13879         object = HeapObject::cast(WeakCell::cast(object)->value());
   13880       }
   13881       Map* map = HeapObject::cast(object)->map();
   13882       if (map == *pattern.find_[current_pattern]) {
   13883         info->set_target_object(*pattern.replace_[current_pattern]);
   13884         if (++current_pattern == pattern.count_) return;
   13885       }
   13886     }
   13887   }
   13888   UNREACHABLE();
   13889 }
   13890 
   13891 
   13892 void Code::ClearInlineCaches() {
   13893   int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
   13894              RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID);
   13895   for (RelocIterator it(this, mask); !it.done(); it.next()) {
   13896     RelocInfo* info = it.rinfo();
   13897     Code* target(Code::GetCodeFromTargetAddress(info->target_address()));
   13898     if (target->is_inline_cache_stub()) {
   13899       ICUtility::Clear(this->GetIsolate(), info->pc(),
   13900                        info->host()->constant_pool());
   13901     }
   13902   }
   13903 }
   13904 
   13905 int AbstractCode::SourcePosition(int offset) {
   13906   int position = 0;
   13907   // Subtract one because the current PC is one instruction after the call site.
   13908   if (IsCode()) offset--;
   13909   for (SourcePositionTableIterator iterator(source_position_table());
   13910        !iterator.done() && iterator.code_offset() <= offset;
   13911        iterator.Advance()) {
   13912     position = iterator.source_position().ScriptOffset();
   13913   }
   13914   return position;
   13915 }
   13916 
   13917 int AbstractCode::SourceStatementPosition(int offset) {
   13918   // First find the closest position.
   13919   int position = SourcePosition(offset);
   13920   // Now find the closest statement position before the position.
   13921   int statement_position = 0;
   13922   for (SourcePositionTableIterator it(source_position_table()); !it.done();
   13923        it.Advance()) {
   13924     if (it.is_statement()) {
   13925       int p = it.source_position().ScriptOffset();
   13926       if (statement_position < p && p <= position) {
   13927         statement_position = p;
   13928       }
   13929     }
   13930   }
   13931   return statement_position;
   13932 }
   13933 
   13934 void JSFunction::ClearTypeFeedbackInfo() {
   13935   if (feedback_vector_cell()->value()->IsFeedbackVector()) {
   13936     FeedbackVector* vector = feedback_vector();
   13937     vector->ClearSlots(this);
   13938   }
   13939 }
   13940 
   13941 BailoutId Code::TranslatePcOffsetToAstId(uint32_t pc_offset) {
   13942   DisallowHeapAllocation no_gc;
   13943   DCHECK(kind() == FUNCTION);
   13944   BackEdgeTable back_edges(this, &no_gc);
   13945   for (uint32_t i = 0; i < back_edges.length(); i++) {
   13946     if (back_edges.pc_offset(i) == pc_offset) return back_edges.ast_id(i);
   13947   }
   13948   return BailoutId::None();
   13949 }
   13950 
   13951 
   13952 uint32_t Code::TranslateAstIdToPcOffset(BailoutId ast_id) {
   13953   DisallowHeapAllocation no_gc;
   13954   DCHECK(kind() == FUNCTION);
   13955   BackEdgeTable back_edges(this, &no_gc);
   13956   for (uint32_t i = 0; i < back_edges.length(); i++) {
   13957     if (back_edges.ast_id(i) == ast_id) return back_edges.pc_offset(i);
   13958   }
   13959   UNREACHABLE();  // We expect to find the back edge.
   13960   return 0;
   13961 }
   13962 
   13963 void Code::MakeCodeAgeSequenceYoung(byte* sequence, Isolate* isolate) {
   13964   PatchPlatformCodeAge(isolate, sequence, kNoAgeCodeAge);
   13965 }
   13966 
   13967 
   13968 void Code::MarkCodeAsExecuted(byte* sequence, Isolate* isolate) {
   13969   PatchPlatformCodeAge(isolate, sequence, kExecutedOnceCodeAge);
   13970 }
   13971 
   13972 
   13973 // NextAge defines the Code::Age state transitions during a GC cycle.
   13974 static Code::Age NextAge(Code::Age age) {
   13975   switch (age) {
   13976     case Code::kNotExecutedCodeAge:  // Keep, until we've been executed.
   13977     case Code::kToBeExecutedOnceCodeAge:  // Keep, until we've been executed.
   13978     case Code::kLastCodeAge:  // Clamp at last Code::Age value.
   13979       return age;
   13980     case Code::kExecutedOnceCodeAge:
   13981       // Pre-age code that has only been executed once.
   13982       return static_cast<Code::Age>(Code::kPreAgedCodeAge + 1);
   13983     default:
   13984       return static_cast<Code::Age>(age + 1);  // Default case: Increase age.
   13985   }
   13986 }
   13987 
   13988 
   13989 // IsOldAge defines the collection criteria for a Code object.
   13990 static bool IsOldAge(Code::Age age) {
   13991   return age >= Code::kIsOldCodeAge || age == Code::kNotExecutedCodeAge;
   13992 }
   13993 
   13994 
   13995 void Code::MakeYoung(Isolate* isolate) {
   13996   byte* sequence = FindCodeAgeSequence();
   13997   if (sequence != NULL) MakeCodeAgeSequenceYoung(sequence, isolate);
   13998 }
   13999 
   14000 void Code::PreAge(Isolate* isolate) {
   14001   byte* sequence = FindCodeAgeSequence();
   14002   if (sequence != NULL) {
   14003     PatchPlatformCodeAge(isolate, sequence, kPreAgedCodeAge);
   14004   }
   14005 }
   14006 
   14007 void Code::MarkToBeExecutedOnce(Isolate* isolate) {
   14008   byte* sequence = FindCodeAgeSequence();
   14009   if (sequence != NULL) {
   14010     PatchPlatformCodeAge(isolate, sequence, kToBeExecutedOnceCodeAge);
   14011   }
   14012 }
   14013 
   14014 void Code::MakeOlder() {
   14015   byte* sequence = FindCodeAgeSequence();
   14016   if (sequence != NULL) {
   14017     Isolate* isolate = GetIsolate();
   14018     Age age = GetCodeAge(isolate, sequence);
   14019     Age next_age = NextAge(age);
   14020     if (age != next_age) {
   14021       PatchPlatformCodeAge(isolate, sequence, next_age);
   14022     }
   14023   }
   14024 }
   14025 
   14026 
   14027 bool Code::IsOld() {
   14028   return IsOldAge(GetAge());
   14029 }
   14030 
   14031 
   14032 byte* Code::FindCodeAgeSequence() {
   14033   return FLAG_age_code &&
   14034       prologue_offset() != Code::kPrologueOffsetNotSet &&
   14035       (kind() == OPTIMIZED_FUNCTION ||
   14036        (kind() == FUNCTION && !has_debug_break_slots()))
   14037       ? instruction_start() + prologue_offset()
   14038       : NULL;
   14039 }
   14040 
   14041 
   14042 Code::Age Code::GetAge() {
   14043   byte* sequence = FindCodeAgeSequence();
   14044   if (sequence == NULL) {
   14045     return kNoAgeCodeAge;
   14046   }
   14047   return GetCodeAge(GetIsolate(), sequence);
   14048 }
   14049 
   14050 Code::Age Code::GetAgeOfCodeAgeStub(Code* code) {
   14051   Isolate* isolate = code->GetIsolate();
   14052   Builtins* builtins = isolate->builtins();
   14053 #define HANDLE_CODE_AGE(AGE)                            \
   14054   if (code == *builtins->Make##AGE##CodeYoungAgain()) { \
   14055     return k##AGE##CodeAge;                             \
   14056   }
   14057   CODE_AGE_LIST(HANDLE_CODE_AGE)
   14058 #undef HANDLE_CODE_AGE
   14059   if (code == *builtins->MarkCodeAsExecutedOnce()) {
   14060     return kNotExecutedCodeAge;
   14061   }
   14062   if (code == *builtins->MarkCodeAsExecutedTwice()) {
   14063     return kExecutedOnceCodeAge;
   14064   }
   14065   if (code == *builtins->MarkCodeAsToBeExecutedOnce()) {
   14066     return kToBeExecutedOnceCodeAge;
   14067   }
   14068   UNREACHABLE();
   14069   return kNoAgeCodeAge;
   14070 }
   14071 
   14072 Code* Code::GetCodeAgeStub(Isolate* isolate, Age age) {
   14073   Builtins* builtins = isolate->builtins();
   14074   switch (age) {
   14075 #define HANDLE_CODE_AGE(AGE)                       \
   14076   case k##AGE##CodeAge: {                          \
   14077     return *builtins->Make##AGE##CodeYoungAgain(); \
   14078   }
   14079     CODE_AGE_LIST(HANDLE_CODE_AGE)
   14080 #undef HANDLE_CODE_AGE
   14081     case kNotExecutedCodeAge: {
   14082       return *builtins->MarkCodeAsExecutedOnce();
   14083     }
   14084     case kExecutedOnceCodeAge: {
   14085       return *builtins->MarkCodeAsExecutedTwice();
   14086     }
   14087     case kToBeExecutedOnceCodeAge: {
   14088       return *builtins->MarkCodeAsToBeExecutedOnce();
   14089     }
   14090     default:
   14091       UNREACHABLE();
   14092       break;
   14093   }
   14094   return NULL;
   14095 }
   14096 
   14097 
   14098 void Code::PrintDeoptLocation(FILE* out, Address pc) {
   14099   Deoptimizer::DeoptInfo info = Deoptimizer::GetDeoptInfo(this, pc);
   14100   class SourcePosition pos = info.position;
   14101   if (info.deopt_reason != DeoptimizeReason::kNoReason || pos.IsKnown()) {
   14102     if (FLAG_hydrogen_track_positions) {
   14103       PrintF(out, "            ;;; deoptimize at %d_%d: %s\n", pos.InliningId(),
   14104              pos.ScriptOffset(), DeoptimizeReasonToString(info.deopt_reason));
   14105     } else {
   14106       PrintF(out, "            ;;; deoptimize at ");
   14107       OFStream outstr(out);
   14108       pos.Print(outstr, this);
   14109       PrintF(out, ", %s\n", DeoptimizeReasonToString(info.deopt_reason));
   14110     }
   14111   }
   14112 }
   14113 
   14114 
   14115 bool Code::CanDeoptAt(Address pc) {
   14116   DeoptimizationInputData* deopt_data =
   14117       DeoptimizationInputData::cast(deoptimization_data());
   14118   Address code_start_address = instruction_start();
   14119   for (int i = 0; i < deopt_data->DeoptCount(); i++) {
   14120     if (deopt_data->Pc(i)->value() == -1) continue;
   14121     Address address = code_start_address + deopt_data->Pc(i)->value();
   14122     if (address == pc && deopt_data->AstId(i) != BailoutId::None()) {
   14123       return true;
   14124     }
   14125   }
   14126   return false;
   14127 }
   14128 
   14129 
   14130 // Identify kind of code.
   14131 const char* Code::Kind2String(Kind kind) {
   14132   switch (kind) {
   14133 #define CASE(name) case name: return #name;
   14134     CODE_KIND_LIST(CASE)
   14135 #undef CASE
   14136     case NUMBER_OF_KINDS: break;
   14137   }
   14138   UNREACHABLE();
   14139   return NULL;
   14140 }
   14141 
   14142 // Identify kind of code.
   14143 const char* AbstractCode::Kind2String(Kind kind) {
   14144   if (kind < AbstractCode::INTERPRETED_FUNCTION)
   14145     return Code::Kind2String((Code::Kind)kind);
   14146   if (kind == AbstractCode::INTERPRETED_FUNCTION) return "INTERPRETED_FUNCTION";
   14147   UNREACHABLE();
   14148   return NULL;
   14149 }
   14150 
   14151 Handle<WeakCell> Code::WeakCellFor(Handle<Code> code) {
   14152   DCHECK(code->kind() == OPTIMIZED_FUNCTION);
   14153   WeakCell* raw_cell = code->CachedWeakCell();
   14154   if (raw_cell != NULL) return Handle<WeakCell>(raw_cell);
   14155   Handle<WeakCell> cell = code->GetIsolate()->factory()->NewWeakCell(code);
   14156   DeoptimizationInputData::cast(code->deoptimization_data())
   14157       ->SetWeakCellCache(*cell);
   14158   return cell;
   14159 }
   14160 
   14161 
   14162 WeakCell* Code::CachedWeakCell() {
   14163   DCHECK(kind() == OPTIMIZED_FUNCTION);
   14164   Object* weak_cell_cache =
   14165       DeoptimizationInputData::cast(deoptimization_data())->WeakCellCache();
   14166   if (weak_cell_cache->IsWeakCell()) {
   14167     DCHECK(this == WeakCell::cast(weak_cell_cache)->value());
   14168     return WeakCell::cast(weak_cell_cache);
   14169   }
   14170   return NULL;
   14171 }
   14172 
   14173 #if defined(OBJECT_PRINT) || defined(ENABLE_DISASSEMBLER)
   14174 
   14175 const char* Code::ICState2String(InlineCacheState state) {
   14176   switch (state) {
   14177     case UNINITIALIZED:
   14178       return "UNINITIALIZED";
   14179     case PREMONOMORPHIC:
   14180       return "PREMONOMORPHIC";
   14181     case MONOMORPHIC:
   14182       return "MONOMORPHIC";
   14183     case RECOMPUTE_HANDLER:
   14184       return "RECOMPUTE_HANDLER";
   14185     case POLYMORPHIC:
   14186       return "POLYMORPHIC";
   14187     case MEGAMORPHIC:
   14188       return "MEGAMORPHIC";
   14189     case GENERIC:
   14190       return "GENERIC";
   14191   }
   14192   UNREACHABLE();
   14193   return NULL;
   14194 }
   14195 
   14196 void Code::PrintExtraICState(std::ostream& os,  // NOLINT
   14197                              Kind kind, ExtraICState extra) {
   14198   os << "extra_ic_state = ";
   14199   if ((kind == STORE_IC || kind == KEYED_STORE_IC) &&
   14200       is_strict(static_cast<LanguageMode>(extra))) {
   14201     os << "STRICT\n";
   14202   } else {
   14203     os << extra << "\n";
   14204   }
   14205 }
   14206 
   14207 #endif  // defined(OBJECT_PRINT) || defined(ENABLE_DISASSEMBLER)
   14208 
   14209 #ifdef ENABLE_DISASSEMBLER
   14210 
   14211 void DeoptimizationInputData::DeoptimizationInputDataPrint(
   14212     std::ostream& os) {  // NOLINT
   14213   disasm::NameConverter converter;
   14214   int const inlined_function_count = InlinedFunctionCount()->value();
   14215   os << "Inlined functions (count = " << inlined_function_count << ")\n";
   14216   for (int id = 0; id < inlined_function_count; ++id) {
   14217     Object* info = LiteralArray()->get(id);
   14218     os << " " << Brief(SharedFunctionInfo::cast(info)) << "\n";
   14219   }
   14220   os << "\n";
   14221   int deopt_count = DeoptCount();
   14222   os << "Deoptimization Input Data (deopt points = " << deopt_count << ")\n";
   14223   if (0 != deopt_count) {
   14224     os << " index  ast id    argc     pc";
   14225     if (FLAG_print_code_verbose) os << "  commands";
   14226     os << "\n";
   14227   }
   14228   for (int i = 0; i < deopt_count; i++) {
   14229     os << std::setw(6) << i << "  " << std::setw(6) << AstId(i).ToInt() << "  "
   14230        << std::setw(6) << ArgumentsStackHeight(i)->value() << " "
   14231        << std::setw(6) << Pc(i)->value();
   14232 
   14233     if (!FLAG_print_code_verbose) {
   14234       os << "\n";
   14235       continue;
   14236     }
   14237     // Print details of the frame translation.
   14238     int translation_index = TranslationIndex(i)->value();
   14239     TranslationIterator iterator(TranslationByteArray(), translation_index);
   14240     Translation::Opcode opcode =
   14241         static_cast<Translation::Opcode>(iterator.Next());
   14242     DCHECK(Translation::BEGIN == opcode);
   14243     int frame_count = iterator.Next();
   14244     int jsframe_count = iterator.Next();
   14245     os << "  " << Translation::StringFor(opcode)
   14246        << " {frame count=" << frame_count
   14247        << ", js frame count=" << jsframe_count << "}\n";
   14248 
   14249     while (iterator.HasNext() &&
   14250            Translation::BEGIN !=
   14251            (opcode = static_cast<Translation::Opcode>(iterator.Next()))) {
   14252       os << std::setw(31) << "    " << Translation::StringFor(opcode) << " ";
   14253 
   14254       switch (opcode) {
   14255         case Translation::BEGIN:
   14256           UNREACHABLE();
   14257           break;
   14258 
   14259         case Translation::JS_FRAME: {
   14260           int ast_id = iterator.Next();
   14261           int shared_info_id = iterator.Next();
   14262           unsigned height = iterator.Next();
   14263           Object* shared_info = LiteralArray()->get(shared_info_id);
   14264           os << "{ast_id=" << ast_id << ", function="
   14265              << Brief(SharedFunctionInfo::cast(shared_info)->DebugName())
   14266              << ", height=" << height << "}";
   14267           break;
   14268         }
   14269 
   14270         case Translation::INTERPRETED_FRAME: {
   14271           int bytecode_offset = iterator.Next();
   14272           int shared_info_id = iterator.Next();
   14273           unsigned height = iterator.Next();
   14274           Object* shared_info = LiteralArray()->get(shared_info_id);
   14275           os << "{bytecode_offset=" << bytecode_offset << ", function="
   14276              << Brief(SharedFunctionInfo::cast(shared_info)->DebugName())
   14277              << ", height=" << height << "}";
   14278           break;
   14279         }
   14280 
   14281         case Translation::CONSTRUCT_STUB_FRAME: {
   14282           int bailout_id = iterator.Next();
   14283           int shared_info_id = iterator.Next();
   14284           Object* shared_info = LiteralArray()->get(shared_info_id);
   14285           unsigned height = iterator.Next();
   14286           os << "{bailout_id=" << bailout_id << ", function="
   14287              << Brief(SharedFunctionInfo::cast(shared_info)->DebugName())
   14288              << ", height=" << height << "}";
   14289           break;
   14290         }
   14291 
   14292         case Translation::COMPILED_STUB_FRAME: {
   14293           Code::Kind stub_kind = static_cast<Code::Kind>(iterator.Next());
   14294           os << "{kind=" << stub_kind << "}";
   14295           break;
   14296         }
   14297 
   14298         case Translation::ARGUMENTS_ADAPTOR_FRAME: {
   14299           int shared_info_id = iterator.Next();
   14300           Object* shared_info = LiteralArray()->get(shared_info_id);
   14301           unsigned height = iterator.Next();
   14302           os << "{function="
   14303              << Brief(SharedFunctionInfo::cast(shared_info)->DebugName())
   14304              << ", height=" << height << "}";
   14305           break;
   14306         }
   14307 
   14308         case Translation::TAIL_CALLER_FRAME: {
   14309           int shared_info_id = iterator.Next();
   14310           Object* shared_info = LiteralArray()->get(shared_info_id);
   14311           os << "{function="
   14312              << Brief(SharedFunctionInfo::cast(shared_info)->DebugName())
   14313              << "}";
   14314           break;
   14315         }
   14316 
   14317         case Translation::GETTER_STUB_FRAME:
   14318         case Translation::SETTER_STUB_FRAME: {
   14319           int shared_info_id = iterator.Next();
   14320           Object* shared_info = LiteralArray()->get(shared_info_id);
   14321           os << "{function=" << Brief(SharedFunctionInfo::cast(shared_info)
   14322                                           ->DebugName()) << "}";
   14323           break;
   14324         }
   14325 
   14326         case Translation::REGISTER: {
   14327           int reg_code = iterator.Next();
   14328           os << "{input=" << converter.NameOfCPURegister(reg_code) << "}";
   14329           break;
   14330         }
   14331 
   14332         case Translation::INT32_REGISTER: {
   14333           int reg_code = iterator.Next();
   14334           os << "{input=" << converter.NameOfCPURegister(reg_code) << "}";
   14335           break;
   14336         }
   14337 
   14338         case Translation::UINT32_REGISTER: {
   14339           int reg_code = iterator.Next();
   14340           os << "{input=" << converter.NameOfCPURegister(reg_code)
   14341              << " (unsigned)}";
   14342           break;
   14343         }
   14344 
   14345         case Translation::BOOL_REGISTER: {
   14346           int reg_code = iterator.Next();
   14347           os << "{input=" << converter.NameOfCPURegister(reg_code)
   14348              << " (bool)}";
   14349           break;
   14350         }
   14351 
   14352         case Translation::FLOAT_REGISTER: {
   14353           int reg_code = iterator.Next();
   14354           os << "{input="
   14355              << RegisterConfiguration::Crankshaft()->GetFloatRegisterName(
   14356                     reg_code)
   14357              << "}";
   14358           break;
   14359         }
   14360 
   14361         case Translation::DOUBLE_REGISTER: {
   14362           int reg_code = iterator.Next();
   14363           os << "{input="
   14364              << RegisterConfiguration::Crankshaft()->GetDoubleRegisterName(
   14365                     reg_code)
   14366              << "}";
   14367           break;
   14368         }
   14369 
   14370         case Translation::STACK_SLOT: {
   14371           int input_slot_index = iterator.Next();
   14372           os << "{input=" << input_slot_index << "}";
   14373           break;
   14374         }
   14375 
   14376         case Translation::INT32_STACK_SLOT: {
   14377           int input_slot_index = iterator.Next();
   14378           os << "{input=" << input_slot_index << "}";
   14379           break;
   14380         }
   14381 
   14382         case Translation::UINT32_STACK_SLOT: {
   14383           int input_slot_index = iterator.Next();
   14384           os << "{input=" << input_slot_index << " (unsigned)}";
   14385           break;
   14386         }
   14387 
   14388         case Translation::BOOL_STACK_SLOT: {
   14389           int input_slot_index = iterator.Next();
   14390           os << "{input=" << input_slot_index << " (bool)}";
   14391           break;
   14392         }
   14393 
   14394         case Translation::FLOAT_STACK_SLOT:
   14395         case Translation::DOUBLE_STACK_SLOT: {
   14396           int input_slot_index = iterator.Next();
   14397           os << "{input=" << input_slot_index << "}";
   14398           break;
   14399         }
   14400 
   14401         case Translation::LITERAL: {
   14402           int literal_index = iterator.Next();
   14403           Object* literal_value = LiteralArray()->get(literal_index);
   14404           os << "{literal_id=" << literal_index << " (" << Brief(literal_value)
   14405              << ")}";
   14406           break;
   14407         }
   14408 
   14409         case Translation::DUPLICATED_OBJECT: {
   14410           int object_index = iterator.Next();
   14411           os << "{object_index=" << object_index << "}";
   14412           break;
   14413         }
   14414 
   14415         case Translation::ARGUMENTS_OBJECT:
   14416         case Translation::CAPTURED_OBJECT: {
   14417           int args_length = iterator.Next();
   14418           os << "{length=" << args_length << "}";
   14419           break;
   14420         }
   14421       }
   14422       os << "\n";
   14423     }
   14424   }
   14425 }
   14426 
   14427 
   14428 void DeoptimizationOutputData::DeoptimizationOutputDataPrint(
   14429     std::ostream& os) {  // NOLINT
   14430   os << "Deoptimization Output Data (deopt points = " << this->DeoptPoints()
   14431      << ")\n";
   14432   if (this->DeoptPoints() == 0) return;
   14433 
   14434   os << "ast id        pc  state\n";
   14435   for (int i = 0; i < this->DeoptPoints(); i++) {
   14436     int pc_and_state = this->PcAndState(i)->value();
   14437     os << std::setw(6) << this->AstId(i).ToInt() << "  " << std::setw(8)
   14438        << FullCodeGenerator::PcField::decode(pc_and_state) << "  "
   14439        << Deoptimizer::BailoutStateToString(
   14440               FullCodeGenerator::BailoutStateField::decode(pc_and_state))
   14441        << "\n";
   14442   }
   14443 }
   14444 
   14445 
   14446 void HandlerTable::HandlerTableRangePrint(std::ostream& os) {
   14447   os << "   from   to       hdlr\n";
   14448   for (int i = 0; i < length(); i += kRangeEntrySize) {
   14449     int pc_start = Smi::cast(get(i + kRangeStartIndex))->value();
   14450     int pc_end = Smi::cast(get(i + kRangeEndIndex))->value();
   14451     int handler_field = Smi::cast(get(i + kRangeHandlerIndex))->value();
   14452     int handler_offset = HandlerOffsetField::decode(handler_field);
   14453     CatchPrediction prediction = HandlerPredictionField::decode(handler_field);
   14454     int data = Smi::cast(get(i + kRangeDataIndex))->value();
   14455     os << "  (" << std::setw(4) << pc_start << "," << std::setw(4) << pc_end
   14456        << ")  ->  " << std::setw(4) << handler_offset
   14457        << " (prediction=" << prediction << ", data=" << data << ")\n";
   14458   }
   14459 }
   14460 
   14461 
   14462 void HandlerTable::HandlerTableReturnPrint(std::ostream& os) {
   14463   os << "   off      hdlr (c)\n";
   14464   for (int i = 0; i < length(); i += kReturnEntrySize) {
   14465     int pc_offset = Smi::cast(get(i + kReturnOffsetIndex))->value();
   14466     int handler_field = Smi::cast(get(i + kReturnHandlerIndex))->value();
   14467     int handler_offset = HandlerOffsetField::decode(handler_field);
   14468     CatchPrediction prediction = HandlerPredictionField::decode(handler_field);
   14469     os << "  " << std::setw(4) << pc_offset << "  ->  " << std::setw(4)
   14470        << handler_offset << " (prediction=" << prediction << ")\n";
   14471   }
   14472 }
   14473 
   14474 
   14475 void Code::Disassemble(const char* name, std::ostream& os) {  // NOLINT
   14476   os << "kind = " << Kind2String(kind()) << "\n";
   14477   if (IsCodeStubOrIC()) {
   14478     const char* n = CodeStub::MajorName(CodeStub::GetMajorKey(this));
   14479     os << "major_key = " << (n == NULL ? "null" : n) << "\n";
   14480   }
   14481   if (is_inline_cache_stub()) {
   14482     if (!IC::ICUseVector(kind())) {
   14483       InlineCacheState ic_state = IC::StateFromCode(this);
   14484       os << "ic_state = " << ICState2String(ic_state) << "\n";
   14485       PrintExtraICState(os, kind(), extra_ic_state());
   14486     }
   14487     if (is_compare_ic_stub()) {
   14488       DCHECK(CodeStub::GetMajorKey(this) == CodeStub::CompareIC);
   14489       CompareICStub stub(stub_key(), GetIsolate());
   14490       os << "compare_state = " << CompareICState::GetStateName(stub.left())
   14491          << "*" << CompareICState::GetStateName(stub.right()) << " -> "
   14492          << CompareICState::GetStateName(stub.state()) << "\n";
   14493       os << "compare_operation = " << Token::Name(stub.op()) << "\n";
   14494     }
   14495   }
   14496   if ((name != nullptr) && (name[0] != '\0')) {
   14497     os << "name = " << name << "\n";
   14498   } else if (kind() == BUILTIN) {
   14499     name = GetIsolate()->builtins()->Lookup(instruction_start());
   14500     if (name != nullptr) {
   14501       os << "name = " << name << "\n";
   14502     }
   14503   } else if (kind() == BYTECODE_HANDLER) {
   14504     name = GetIsolate()->interpreter()->LookupNameOfBytecodeHandler(this);
   14505     if (name != nullptr) {
   14506       os << "name = " << name << "\n";
   14507     }
   14508   }
   14509   if (kind() == OPTIMIZED_FUNCTION) {
   14510     os << "stack_slots = " << stack_slots() << "\n";
   14511   }
   14512   os << "compiler = " << (is_turbofanned()
   14513                               ? "turbofan"
   14514                               : is_crankshafted() ? "crankshaft"
   14515                                                   : kind() == Code::FUNCTION
   14516                                                         ? "full-codegen"
   14517                                                         : "unknown") << "\n";
   14518 
   14519   os << "Instructions (size = " << instruction_size() << ")\n";
   14520   {
   14521     Isolate* isolate = GetIsolate();
   14522     int size = instruction_size();
   14523     int safepoint_offset =
   14524         is_crankshafted() ? static_cast<int>(safepoint_table_offset()) : size;
   14525     int back_edge_offset = (kind() == Code::FUNCTION)
   14526                                ? static_cast<int>(back_edge_table_offset())
   14527                                : size;
   14528     int constant_pool_offset = FLAG_enable_embedded_constant_pool
   14529                                    ? this->constant_pool_offset()
   14530                                    : size;
   14531 
   14532     // Stop before reaching any embedded tables
   14533     int code_size = Min(safepoint_offset, back_edge_offset);
   14534     code_size = Min(code_size, constant_pool_offset);
   14535     byte* begin = instruction_start();
   14536     byte* end = begin + code_size;
   14537     Disassembler::Decode(isolate, &os, begin, end, this);
   14538 
   14539     if (constant_pool_offset < size) {
   14540       int constant_pool_size = size - constant_pool_offset;
   14541       DCHECK((constant_pool_size & kPointerAlignmentMask) == 0);
   14542       os << "\nConstant Pool (size = " << constant_pool_size << ")\n";
   14543       Vector<char> buf = Vector<char>::New(50);
   14544       intptr_t* ptr = reinterpret_cast<intptr_t*>(begin + constant_pool_offset);
   14545       for (int i = 0; i < constant_pool_size; i += kPointerSize, ptr++) {
   14546         SNPrintF(buf, "%4d %08" V8PRIxPTR, i, *ptr);
   14547         os << static_cast<const void*>(ptr) << "  " << buf.start() << "\n";
   14548       }
   14549     }
   14550   }
   14551   os << "\n";
   14552 
   14553   SourcePositionTableIterator it(source_position_table());
   14554   if (!it.done()) {
   14555     os << "Source positions:\n pc offset  position\n";
   14556     for (; !it.done(); it.Advance()) {
   14557       os << std::setw(10) << it.code_offset() << std::setw(10)
   14558          << it.source_position().ScriptOffset()
   14559          << (it.is_statement() ? "  statement" : "") << "\n";
   14560     }
   14561     os << "\n";
   14562   }
   14563 
   14564   if (kind() == FUNCTION) {
   14565     DeoptimizationOutputData* data =
   14566         DeoptimizationOutputData::cast(this->deoptimization_data());
   14567     data->DeoptimizationOutputDataPrint(os);
   14568   } else if (kind() == OPTIMIZED_FUNCTION) {
   14569     DeoptimizationInputData* data =
   14570         DeoptimizationInputData::cast(this->deoptimization_data());
   14571     data->DeoptimizationInputDataPrint(os);
   14572   }
   14573   os << "\n";
   14574 
   14575   if (is_crankshafted()) {
   14576     SafepointTable table(this);
   14577     os << "Safepoints (size = " << table.size() << ")\n";
   14578     for (unsigned i = 0; i < table.length(); i++) {
   14579       unsigned pc_offset = table.GetPcOffset(i);
   14580       os << static_cast<const void*>(instruction_start() + pc_offset) << "  ";
   14581       os << std::setw(4) << pc_offset << "  ";
   14582       table.PrintEntry(i, os);
   14583       os << " (sp -> fp)  ";
   14584       SafepointEntry entry = table.GetEntry(i);
   14585       if (entry.deoptimization_index() != Safepoint::kNoDeoptimizationIndex) {
   14586         os << std::setw(6) << entry.deoptimization_index();
   14587       } else {
   14588         os << "<none>";
   14589       }
   14590       if (entry.argument_count() > 0) {
   14591         os << " argc: " << entry.argument_count();
   14592       }
   14593       os << "\n";
   14594     }
   14595     os << "\n";
   14596   } else if (kind() == FUNCTION) {
   14597     unsigned offset = back_edge_table_offset();
   14598     // If there is no back edge table, the "table start" will be at or after
   14599     // (due to alignment) the end of the instruction stream.
   14600     if (static_cast<int>(offset) < instruction_size()) {
   14601       DisallowHeapAllocation no_gc;
   14602       BackEdgeTable back_edges(this, &no_gc);
   14603 
   14604       os << "Back edges (size = " << back_edges.length() << ")\n";
   14605       os << "ast_id  pc_offset  loop_depth\n";
   14606 
   14607       for (uint32_t i = 0; i < back_edges.length(); i++) {
   14608         os << std::setw(6) << back_edges.ast_id(i).ToInt() << "  "
   14609            << std::setw(9) << back_edges.pc_offset(i) << "  " << std::setw(10)
   14610            << back_edges.loop_depth(i) << "\n";
   14611       }
   14612 
   14613       os << "\n";
   14614     }
   14615 #ifdef OBJECT_PRINT
   14616     if (!type_feedback_info()->IsUndefined(GetIsolate())) {
   14617       TypeFeedbackInfo::cast(type_feedback_info())->TypeFeedbackInfoPrint(os);
   14618       os << "\n";
   14619     }
   14620 #endif
   14621   }
   14622 
   14623   if (handler_table()->length() > 0) {
   14624     os << "Handler Table (size = " << handler_table()->Size() << ")\n";
   14625     if (kind() == FUNCTION) {
   14626       HandlerTable::cast(handler_table())->HandlerTableRangePrint(os);
   14627     } else if (kind() == OPTIMIZED_FUNCTION) {
   14628       HandlerTable::cast(handler_table())->HandlerTableReturnPrint(os);
   14629     }
   14630     os << "\n";
   14631   }
   14632 
   14633   os << "RelocInfo (size = " << relocation_size() << ")\n";
   14634   for (RelocIterator it(this); !it.done(); it.next()) {
   14635     it.rinfo()->Print(GetIsolate(), os);
   14636   }
   14637   os << "\n";
   14638 
   14639   if (has_unwinding_info()) {
   14640     os << "UnwindingInfo (size = " << unwinding_info_size() << ")\n";
   14641     EhFrameDisassembler eh_frame_disassembler(unwinding_info_start(),
   14642                                               unwinding_info_end());
   14643     eh_frame_disassembler.DisassembleToStream(os);
   14644     os << "\n";
   14645   }
   14646 }
   14647 #endif  // ENABLE_DISASSEMBLER
   14648 
   14649 
   14650 void BytecodeArray::Disassemble(std::ostream& os) {
   14651   os << "Parameter count " << parameter_count() << "\n";
   14652   os << "Frame size " << frame_size() << "\n";
   14653 
   14654   const uint8_t* base_address = GetFirstBytecodeAddress();
   14655   SourcePositionTableIterator source_positions(source_position_table());
   14656 
   14657   interpreter::BytecodeArrayIterator iterator(handle(this));
   14658   while (!iterator.done()) {
   14659     if (!source_positions.done() &&
   14660         iterator.current_offset() == source_positions.code_offset()) {
   14661       os << std::setw(5) << source_positions.source_position().ScriptOffset();
   14662       os << (source_positions.is_statement() ? " S> " : " E> ");
   14663       source_positions.Advance();
   14664     } else {
   14665       os << "         ";
   14666     }
   14667     const uint8_t* current_address = base_address + iterator.current_offset();
   14668     os << reinterpret_cast<const void*>(current_address) << " @ "
   14669        << std::setw(4) << iterator.current_offset() << " : ";
   14670     interpreter::BytecodeDecoder::Decode(os, current_address,
   14671                                          parameter_count());
   14672     if (interpreter::Bytecodes::IsJump(iterator.current_bytecode())) {
   14673       const void* jump_target = base_address + iterator.GetJumpTargetOffset();
   14674       os << " (" << jump_target << " @ " << iterator.GetJumpTargetOffset()
   14675          << ")";
   14676     }
   14677     os << std::endl;
   14678     iterator.Advance();
   14679   }
   14680 
   14681   if (constant_pool()->length() > 0) {
   14682     os << "Constant pool (size = " << constant_pool()->length() << ")\n";
   14683     constant_pool()->Print();
   14684   }
   14685 
   14686 #ifdef ENABLE_DISASSEMBLER
   14687   if (handler_table()->length() > 0) {
   14688     os << "Handler Table (size = " << handler_table()->Size() << ")\n";
   14689     HandlerTable::cast(handler_table())->HandlerTableRangePrint(os);
   14690   }
   14691 #endif
   14692 }
   14693 
   14694 void BytecodeArray::CopyBytecodesTo(BytecodeArray* to) {
   14695   BytecodeArray* from = this;
   14696   DCHECK_EQ(from->length(), to->length());
   14697   CopyBytes(to->GetFirstBytecodeAddress(), from->GetFirstBytecodeAddress(),
   14698             from->length());
   14699 }
   14700 
   14701 void BytecodeArray::MakeOlder() {
   14702   Age age = bytecode_age();
   14703   if (age < kLastBytecodeAge) {
   14704     set_bytecode_age(static_cast<Age>(age + 1));
   14705   }
   14706   DCHECK_GE(bytecode_age(), kFirstBytecodeAge);
   14707   DCHECK_LE(bytecode_age(), kLastBytecodeAge);
   14708 }
   14709 
   14710 bool BytecodeArray::IsOld() const {
   14711   return bytecode_age() >= kIsOldBytecodeAge;
   14712 }
   14713 
   14714 // static
   14715 void JSArray::Initialize(Handle<JSArray> array, int capacity, int length) {
   14716   DCHECK(capacity >= 0);
   14717   array->GetIsolate()->factory()->NewJSArrayStorage(
   14718       array, length, capacity, INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE);
   14719 }
   14720 
   14721 void JSArray::SetLength(Handle<JSArray> array, uint32_t new_length) {
   14722   // We should never end in here with a pixel or external array.
   14723   DCHECK(array->AllowsSetLength());
   14724   if (array->SetLengthWouldNormalize(new_length)) {
   14725     JSObject::NormalizeElements(array);
   14726   }
   14727   array->GetElementsAccessor()->SetLength(array, new_length);
   14728 }
   14729 
   14730 
   14731 // static
   14732 void Map::AddDependentCode(Handle<Map> map,
   14733                            DependentCode::DependencyGroup group,
   14734                            Handle<Code> code) {
   14735   Handle<WeakCell> cell = Code::WeakCellFor(code);
   14736   Handle<DependentCode> codes = DependentCode::InsertWeakCode(
   14737       Handle<DependentCode>(map->dependent_code()), group, cell);
   14738   if (*codes != map->dependent_code()) map->set_dependent_code(*codes);
   14739 }
   14740 
   14741 
   14742 Handle<DependentCode> DependentCode::InsertCompilationDependencies(
   14743     Handle<DependentCode> entries, DependencyGroup group,
   14744     Handle<Foreign> info) {
   14745   return Insert(entries, group, info);
   14746 }
   14747 
   14748 
   14749 Handle<DependentCode> DependentCode::InsertWeakCode(
   14750     Handle<DependentCode> entries, DependencyGroup group,
   14751     Handle<WeakCell> code_cell) {
   14752   return Insert(entries, group, code_cell);
   14753 }
   14754 
   14755 
   14756 Handle<DependentCode> DependentCode::Insert(Handle<DependentCode> entries,
   14757                                             DependencyGroup group,
   14758                                             Handle<Object> object) {
   14759   if (entries->length() == 0 || entries->group() > group) {
   14760     // There is no such group.
   14761     return DependentCode::New(group, object, entries);
   14762   }
   14763   if (entries->group() < group) {
   14764     // The group comes later in the list.
   14765     Handle<DependentCode> old_next(entries->next_link());
   14766     Handle<DependentCode> new_next = Insert(old_next, group, object);
   14767     if (!old_next.is_identical_to(new_next)) {
   14768       entries->set_next_link(*new_next);
   14769     }
   14770     return entries;
   14771   }
   14772   DCHECK_EQ(group, entries->group());
   14773   int count = entries->count();
   14774   // Check for existing entry to avoid duplicates.
   14775   for (int i = 0; i < count; i++) {
   14776     if (entries->object_at(i) == *object) return entries;
   14777   }
   14778   if (entries->length() < kCodesStartIndex + count + 1) {
   14779     entries = EnsureSpace(entries);
   14780     // Count could have changed, reload it.
   14781     count = entries->count();
   14782   }
   14783   entries->set_object_at(count, *object);
   14784   entries->set_count(count + 1);
   14785   return entries;
   14786 }
   14787 
   14788 
   14789 Handle<DependentCode> DependentCode::New(DependencyGroup group,
   14790                                          Handle<Object> object,
   14791                                          Handle<DependentCode> next) {
   14792   Isolate* isolate = next->GetIsolate();
   14793   Handle<DependentCode> result = Handle<DependentCode>::cast(
   14794       isolate->factory()->NewFixedArray(kCodesStartIndex + 1, TENURED));
   14795   result->set_next_link(*next);
   14796   result->set_flags(GroupField::encode(group) | CountField::encode(1));
   14797   result->set_object_at(0, *object);
   14798   return result;
   14799 }
   14800 
   14801 
   14802 Handle<DependentCode> DependentCode::EnsureSpace(
   14803     Handle<DependentCode> entries) {
   14804   if (entries->Compact()) return entries;
   14805   Isolate* isolate = entries->GetIsolate();
   14806   int capacity = kCodesStartIndex + DependentCode::Grow(entries->count());
   14807   int grow_by = capacity - entries->length();
   14808   return Handle<DependentCode>::cast(
   14809       isolate->factory()->CopyFixedArrayAndGrow(entries, grow_by, TENURED));
   14810 }
   14811 
   14812 
   14813 bool DependentCode::Compact() {
   14814   int old_count = count();
   14815   int new_count = 0;
   14816   for (int i = 0; i < old_count; i++) {
   14817     Object* obj = object_at(i);
   14818     if (!obj->IsWeakCell() || !WeakCell::cast(obj)->cleared()) {
   14819       if (i != new_count) {
   14820         copy(i, new_count);
   14821       }
   14822       new_count++;
   14823     }
   14824   }
   14825   set_count(new_count);
   14826   for (int i = new_count; i < old_count; i++) {
   14827     clear_at(i);
   14828   }
   14829   return new_count < old_count;
   14830 }
   14831 
   14832 
   14833 void DependentCode::UpdateToFinishedCode(DependencyGroup group, Foreign* info,
   14834                                          WeakCell* code_cell) {
   14835   if (this->length() == 0 || this->group() > group) {
   14836     // There is no such group.
   14837     return;
   14838   }
   14839   if (this->group() < group) {
   14840     // The group comes later in the list.
   14841     next_link()->UpdateToFinishedCode(group, info, code_cell);
   14842     return;
   14843   }
   14844   DCHECK_EQ(group, this->group());
   14845   DisallowHeapAllocation no_gc;
   14846   int count = this->count();
   14847   for (int i = 0; i < count; i++) {
   14848     if (object_at(i) == info) {
   14849       set_object_at(i, code_cell);
   14850       break;
   14851     }
   14852   }
   14853 #ifdef DEBUG
   14854   for (int i = 0; i < count; i++) {
   14855     DCHECK(object_at(i) != info);
   14856   }
   14857 #endif
   14858 }
   14859 
   14860 
   14861 void DependentCode::RemoveCompilationDependencies(
   14862     DependentCode::DependencyGroup group, Foreign* info) {
   14863   if (this->length() == 0 || this->group() > group) {
   14864     // There is no such group.
   14865     return;
   14866   }
   14867   if (this->group() < group) {
   14868     // The group comes later in the list.
   14869     next_link()->RemoveCompilationDependencies(group, info);
   14870     return;
   14871   }
   14872   DCHECK_EQ(group, this->group());
   14873   DisallowHeapAllocation no_allocation;
   14874   int old_count = count();
   14875   // Find compilation info wrapper.
   14876   int info_pos = -1;
   14877   for (int i = 0; i < old_count; i++) {
   14878     if (object_at(i) == info) {
   14879       info_pos = i;
   14880       break;
   14881     }
   14882   }
   14883   if (info_pos == -1) return;  // Not found.
   14884   // Use the last code to fill the gap.
   14885   if (info_pos < old_count - 1) {
   14886     copy(old_count - 1, info_pos);
   14887   }
   14888   clear_at(old_count - 1);
   14889   set_count(old_count - 1);
   14890 
   14891 #ifdef DEBUG
   14892   for (int i = 0; i < old_count - 1; i++) {
   14893     DCHECK(object_at(i) != info);
   14894   }
   14895 #endif
   14896 }
   14897 
   14898 
   14899 bool DependentCode::Contains(DependencyGroup group, WeakCell* code_cell) {
   14900   if (this->length() == 0 || this->group() > group) {
   14901     // There is no such group.
   14902     return false;
   14903   }
   14904   if (this->group() < group) {
   14905     // The group comes later in the list.
   14906     return next_link()->Contains(group, code_cell);
   14907   }
   14908   DCHECK_EQ(group, this->group());
   14909   int count = this->count();
   14910   for (int i = 0; i < count; i++) {
   14911     if (object_at(i) == code_cell) return true;
   14912   }
   14913   return false;
   14914 }
   14915 
   14916 
   14917 bool DependentCode::IsEmpty(DependencyGroup group) {
   14918   if (this->length() == 0 || this->group() > group) {
   14919     // There is no such group.
   14920     return true;
   14921   }
   14922   if (this->group() < group) {
   14923     // The group comes later in the list.
   14924     return next_link()->IsEmpty(group);
   14925   }
   14926   DCHECK_EQ(group, this->group());
   14927   return count() == 0;
   14928 }
   14929 
   14930 
   14931 bool DependentCode::MarkCodeForDeoptimization(
   14932     Isolate* isolate,
   14933     DependentCode::DependencyGroup group) {
   14934   if (this->length() == 0 || this->group() > group) {
   14935     // There is no such group.
   14936     return false;
   14937   }
   14938   if (this->group() < group) {
   14939     // The group comes later in the list.
   14940     return next_link()->MarkCodeForDeoptimization(isolate, group);
   14941   }
   14942   DCHECK_EQ(group, this->group());
   14943   DisallowHeapAllocation no_allocation_scope;
   14944   // Mark all the code that needs to be deoptimized.
   14945   bool marked = false;
   14946   bool invalidate_embedded_objects = group == kWeakCodeGroup;
   14947   int count = this->count();
   14948   for (int i = 0; i < count; i++) {
   14949     Object* obj = object_at(i);
   14950     if (obj->IsWeakCell()) {
   14951       WeakCell* cell = WeakCell::cast(obj);
   14952       if (cell->cleared()) continue;
   14953       Code* code = Code::cast(cell->value());
   14954       if (!code->marked_for_deoptimization()) {
   14955         SetMarkedForDeoptimization(code, group);
   14956         if (invalidate_embedded_objects) {
   14957           code->InvalidateEmbeddedObjects();
   14958         }
   14959         marked = true;
   14960       }
   14961     } else {
   14962       DCHECK(obj->IsForeign());
   14963       CompilationDependencies* info =
   14964           reinterpret_cast<CompilationDependencies*>(
   14965               Foreign::cast(obj)->foreign_address());
   14966       info->Abort();
   14967     }
   14968   }
   14969   for (int i = 0; i < count; i++) {
   14970     clear_at(i);
   14971   }
   14972   set_count(0);
   14973   return marked;
   14974 }
   14975 
   14976 
   14977 void DependentCode::DeoptimizeDependentCodeGroup(
   14978     Isolate* isolate,
   14979     DependentCode::DependencyGroup group) {
   14980   DCHECK(AllowCodeDependencyChange::IsAllowed());
   14981   DisallowHeapAllocation no_allocation_scope;
   14982   bool marked = MarkCodeForDeoptimization(isolate, group);
   14983   if (marked) Deoptimizer::DeoptimizeMarkedCode(isolate);
   14984 }
   14985 
   14986 
   14987 void DependentCode::SetMarkedForDeoptimization(Code* code,
   14988                                                DependencyGroup group) {
   14989   code->set_marked_for_deoptimization(true);
   14990   if (FLAG_trace_deopt &&
   14991       (code->deoptimization_data() != code->GetHeap()->empty_fixed_array())) {
   14992     DeoptimizationInputData* deopt_data =
   14993         DeoptimizationInputData::cast(code->deoptimization_data());
   14994     CodeTracer::Scope scope(code->GetHeap()->isolate()->GetCodeTracer());
   14995     PrintF(scope.file(), "[marking dependent code 0x%08" V8PRIxPTR
   14996                          " (opt #%d) for deoptimization, reason: %s]\n",
   14997            reinterpret_cast<intptr_t>(code),
   14998            deopt_data->OptimizationId()->value(), DependencyGroupName(group));
   14999   }
   15000 }
   15001 
   15002 
   15003 const char* DependentCode::DependencyGroupName(DependencyGroup group) {
   15004   switch (group) {
   15005     case kWeakCodeGroup:
   15006       return "weak-code";
   15007     case kTransitionGroup:
   15008       return "transition";
   15009     case kPrototypeCheckGroup:
   15010       return "prototype-check";
   15011     case kPropertyCellChangedGroup:
   15012       return "property-cell-changed";
   15013     case kFieldOwnerGroup:
   15014       return "field-owner";
   15015     case kInitialMapChangedGroup:
   15016       return "initial-map-changed";
   15017     case kAllocationSiteTenuringChangedGroup:
   15018       return "allocation-site-tenuring-changed";
   15019     case kAllocationSiteTransitionChangedGroup:
   15020       return "allocation-site-transition-changed";
   15021   }
   15022   UNREACHABLE();
   15023   return "?";
   15024 }
   15025 
   15026 
   15027 Handle<Map> Map::TransitionToPrototype(Handle<Map> map,
   15028                                        Handle<Object> prototype,
   15029                                        PrototypeOptimizationMode mode) {
   15030   Handle<Map> new_map = TransitionArray::GetPrototypeTransition(map, prototype);
   15031   if (new_map.is_null()) {
   15032     new_map = Copy(map, "TransitionToPrototype");
   15033     TransitionArray::PutPrototypeTransition(map, prototype, new_map);
   15034     Map::SetPrototype(new_map, prototype, mode);
   15035   }
   15036   return new_map;
   15037 }
   15038 
   15039 
   15040 Maybe<bool> JSReceiver::SetPrototype(Handle<JSReceiver> object,
   15041                                      Handle<Object> value, bool from_javascript,
   15042                                      ShouldThrow should_throw) {
   15043   if (object->IsJSProxy()) {
   15044     return JSProxy::SetPrototype(Handle<JSProxy>::cast(object), value,
   15045                                  from_javascript, should_throw);
   15046   }
   15047   return JSObject::SetPrototype(Handle<JSObject>::cast(object), value,
   15048                                 from_javascript, should_throw);
   15049 }
   15050 
   15051 
   15052 // ES6: 9.5.2 [[SetPrototypeOf]] (V)
   15053 // static
   15054 Maybe<bool> JSProxy::SetPrototype(Handle<JSProxy> proxy, Handle<Object> value,
   15055                                   bool from_javascript,
   15056                                   ShouldThrow should_throw) {
   15057   Isolate* isolate = proxy->GetIsolate();
   15058   STACK_CHECK(isolate, Nothing<bool>());
   15059   Handle<Name> trap_name = isolate->factory()->setPrototypeOf_string();
   15060   // 1. Assert: Either Type(V) is Object or Type(V) is Null.
   15061   DCHECK(value->IsJSReceiver() || value->IsNull(isolate));
   15062   // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O.
   15063   Handle<Object> handler(proxy->handler(), isolate);
   15064   // 3. If handler is null, throw a TypeError exception.
   15065   // 4. Assert: Type(handler) is Object.
   15066   if (proxy->IsRevoked()) {
   15067     isolate->Throw(*isolate->factory()->NewTypeError(
   15068         MessageTemplate::kProxyRevoked, trap_name));
   15069     return Nothing<bool>();
   15070   }
   15071   // 5. Let target be the value of the [[ProxyTarget]] internal slot.
   15072   Handle<JSReceiver> target(proxy->target(), isolate);
   15073   // 6. Let trap be ? GetMethod(handler, "getPrototypeOf").
   15074   Handle<Object> trap;
   15075   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   15076       isolate, trap,
   15077       Object::GetMethod(Handle<JSReceiver>::cast(handler), trap_name),
   15078       Nothing<bool>());
   15079   // 7. If trap is undefined, then return target.[[SetPrototypeOf]]().
   15080   if (trap->IsUndefined(isolate)) {
   15081     return JSReceiver::SetPrototype(target, value, from_javascript,
   15082                                     should_throw);
   15083   }
   15084   // 8. Let booleanTrapResult be ToBoolean(? Call(trap, handler, target, V)).
   15085   Handle<Object> argv[] = {target, value};
   15086   Handle<Object> trap_result;
   15087   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   15088       isolate, trap_result,
   15089       Execution::Call(isolate, trap, handler, arraysize(argv), argv),
   15090       Nothing<bool>());
   15091   bool bool_trap_result = trap_result->BooleanValue();
   15092   // 9. If booleanTrapResult is false, return false.
   15093   if (!bool_trap_result) {
   15094     RETURN_FAILURE(
   15095         isolate, should_throw,
   15096         NewTypeError(MessageTemplate::kProxyTrapReturnedFalsish, trap_name));
   15097   }
   15098   // 10. Let extensibleTarget be ? IsExtensible(target).
   15099   Maybe<bool> is_extensible = JSReceiver::IsExtensible(target);
   15100   if (is_extensible.IsNothing()) return Nothing<bool>();
   15101   // 11. If extensibleTarget is true, return true.
   15102   if (is_extensible.FromJust()) {
   15103     if (bool_trap_result) return Just(true);
   15104     RETURN_FAILURE(
   15105         isolate, should_throw,
   15106         NewTypeError(MessageTemplate::kProxyTrapReturnedFalsish, trap_name));
   15107   }
   15108   // 12. Let targetProto be ? target.[[GetPrototypeOf]]().
   15109   Handle<Object> target_proto;
   15110   ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, target_proto,
   15111                                    JSReceiver::GetPrototype(isolate, target),
   15112                                    Nothing<bool>());
   15113   // 13. If SameValue(V, targetProto) is false, throw a TypeError exception.
   15114   if (bool_trap_result && !value->SameValue(*target_proto)) {
   15115     isolate->Throw(*isolate->factory()->NewTypeError(
   15116         MessageTemplate::kProxySetPrototypeOfNonExtensible));
   15117     return Nothing<bool>();
   15118   }
   15119   // 14. Return true.
   15120   return Just(true);
   15121 }
   15122 
   15123 
   15124 Maybe<bool> JSObject::SetPrototype(Handle<JSObject> object,
   15125                                    Handle<Object> value, bool from_javascript,
   15126                                    ShouldThrow should_throw) {
   15127   Isolate* isolate = object->GetIsolate();
   15128 
   15129 #ifdef DEBUG
   15130   int size = object->Size();
   15131 #endif
   15132 
   15133   if (from_javascript) {
   15134     if (object->IsAccessCheckNeeded() &&
   15135         !isolate->MayAccess(handle(isolate->context()), object)) {
   15136       isolate->ReportFailedAccessCheck(object);
   15137       RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
   15138       RETURN_FAILURE(isolate, should_throw,
   15139                      NewTypeError(MessageTemplate::kNoAccess));
   15140     }
   15141   } else {
   15142     DCHECK(!object->IsAccessCheckNeeded());
   15143   }
   15144 
   15145   Heap* heap = isolate->heap();
   15146   // Silently ignore the change if value is not a JSObject or null.
   15147   // SpiderMonkey behaves this way.
   15148   if (!value->IsJSReceiver() && !value->IsNull(isolate)) return Just(true);
   15149 
   15150   bool all_extensible = object->map()->is_extensible();
   15151   Handle<JSObject> real_receiver = object;
   15152   if (from_javascript) {
   15153     // Find the first object in the chain whose prototype object is not
   15154     // hidden.
   15155     PrototypeIterator iter(isolate, real_receiver, kStartAtPrototype,
   15156                            PrototypeIterator::END_AT_NON_HIDDEN);
   15157     while (!iter.IsAtEnd()) {
   15158       // Casting to JSObject is fine because hidden prototypes are never
   15159       // JSProxies.
   15160       real_receiver = PrototypeIterator::GetCurrent<JSObject>(iter);
   15161       iter.Advance();
   15162       all_extensible = all_extensible && real_receiver->map()->is_extensible();
   15163     }
   15164   }
   15165   Handle<Map> map(real_receiver->map());
   15166 
   15167   // Nothing to do if prototype is already set.
   15168   if (map->prototype() == *value) return Just(true);
   15169 
   15170   bool immutable_proto = map->is_immutable_proto();
   15171   if (immutable_proto) {
   15172     RETURN_FAILURE(
   15173         isolate, should_throw,
   15174         NewTypeError(MessageTemplate::kImmutablePrototypeSet, object));
   15175   }
   15176 
   15177   // From 8.6.2 Object Internal Methods
   15178   // ...
   15179   // In addition, if [[Extensible]] is false the value of the [[Class]] and
   15180   // [[Prototype]] internal properties of the object may not be modified.
   15181   // ...
   15182   // Implementation specific extensions that modify [[Class]], [[Prototype]]
   15183   // or [[Extensible]] must not violate the invariants defined in the preceding
   15184   // paragraph.
   15185   if (!all_extensible) {
   15186     RETURN_FAILURE(isolate, should_throw,
   15187                    NewTypeError(MessageTemplate::kNonExtensibleProto, object));
   15188   }
   15189 
   15190   // Before we can set the prototype we need to be sure prototype cycles are
   15191   // prevented.  It is sufficient to validate that the receiver is not in the
   15192   // new prototype chain.
   15193   if (value->IsJSReceiver()) {
   15194     for (PrototypeIterator iter(isolate, JSReceiver::cast(*value),
   15195                                 kStartAtReceiver);
   15196          !iter.IsAtEnd(); iter.Advance()) {
   15197       if (iter.GetCurrent<JSReceiver>() == *object) {
   15198         // Cycle detected.
   15199         RETURN_FAILURE(isolate, should_throw,
   15200                        NewTypeError(MessageTemplate::kCyclicProto));
   15201       }
   15202     }
   15203   }
   15204 
   15205   // Set the new prototype of the object.
   15206 
   15207   isolate->UpdateArrayProtectorOnSetPrototype(real_receiver);
   15208 
   15209   PrototypeOptimizationMode mode =
   15210       from_javascript ? REGULAR_PROTOTYPE : FAST_PROTOTYPE;
   15211   Handle<Map> new_map = Map::TransitionToPrototype(map, value, mode);
   15212   DCHECK(new_map->prototype() == *value);
   15213   JSObject::MigrateToMap(real_receiver, new_map);
   15214 
   15215   heap->ClearInstanceofCache();
   15216   DCHECK(size == object->Size());
   15217   return Just(true);
   15218 }
   15219 
   15220 // static
   15221 void JSObject::SetImmutableProto(Handle<JSObject> object) {
   15222   DCHECK(!object->IsAccessCheckNeeded());  // Never called from JS
   15223   Handle<Map> map(object->map());
   15224 
   15225   // Nothing to do if prototype is already set.
   15226   if (map->is_immutable_proto()) return;
   15227 
   15228   Handle<Map> new_map = Map::TransitionToImmutableProto(map);
   15229   object->set_map(*new_map);
   15230 }
   15231 
   15232 void JSObject::EnsureCanContainElements(Handle<JSObject> object,
   15233                                         Arguments* args,
   15234                                         uint32_t first_arg,
   15235                                         uint32_t arg_count,
   15236                                         EnsureElementsMode mode) {
   15237   // Elements in |Arguments| are ordered backwards (because they're on the
   15238   // stack), but the method that's called here iterates over them in forward
   15239   // direction.
   15240   return EnsureCanContainElements(
   15241       object, args->arguments() - first_arg - (arg_count - 1), arg_count, mode);
   15242 }
   15243 
   15244 
   15245 ElementsAccessor* JSObject::GetElementsAccessor() {
   15246   return ElementsAccessor::ForKind(GetElementsKind());
   15247 }
   15248 
   15249 
   15250 void JSObject::ValidateElements(Handle<JSObject> object) {
   15251 #ifdef ENABLE_SLOW_DCHECKS
   15252   if (FLAG_enable_slow_asserts) {
   15253     ElementsAccessor* accessor = object->GetElementsAccessor();
   15254     accessor->Validate(object);
   15255   }
   15256 #endif
   15257 }
   15258 
   15259 
   15260 static bool ShouldConvertToSlowElements(JSObject* object, uint32_t capacity,
   15261                                         uint32_t index,
   15262                                         uint32_t* new_capacity) {
   15263   STATIC_ASSERT(JSObject::kMaxUncheckedOldFastElementsLength <=
   15264                 JSObject::kMaxUncheckedFastElementsLength);
   15265   if (index < capacity) {
   15266     *new_capacity = capacity;
   15267     return false;
   15268   }
   15269   if (index - capacity >= JSObject::kMaxGap) return true;
   15270   *new_capacity = JSObject::NewElementsCapacity(index + 1);
   15271   DCHECK_LT(index, *new_capacity);
   15272   if (*new_capacity <= JSObject::kMaxUncheckedOldFastElementsLength ||
   15273       (*new_capacity <= JSObject::kMaxUncheckedFastElementsLength &&
   15274        object->GetHeap()->InNewSpace(object))) {
   15275     return false;
   15276   }
   15277   // If the fast-case backing storage takes up roughly three times as
   15278   // much space (in machine words) as a dictionary backing storage
   15279   // would, the object should have slow elements.
   15280   int used_elements = object->GetFastElementsUsage();
   15281   int dictionary_size = SeededNumberDictionary::ComputeCapacity(used_elements) *
   15282                         SeededNumberDictionary::kEntrySize;
   15283   return 3 * static_cast<uint32_t>(dictionary_size) <= *new_capacity;
   15284 }
   15285 
   15286 
   15287 bool JSObject::WouldConvertToSlowElements(uint32_t index) {
   15288   if (HasFastElements()) {
   15289     Handle<FixedArrayBase> backing_store(FixedArrayBase::cast(elements()));
   15290     uint32_t capacity = static_cast<uint32_t>(backing_store->length());
   15291     uint32_t new_capacity;
   15292     return ShouldConvertToSlowElements(this, capacity, index, &new_capacity);
   15293   }
   15294   return false;
   15295 }
   15296 
   15297 
   15298 static ElementsKind BestFittingFastElementsKind(JSObject* object) {
   15299   if (object->HasSloppyArgumentsElements()) {
   15300     return FAST_SLOPPY_ARGUMENTS_ELEMENTS;
   15301   }
   15302   if (object->HasStringWrapperElements()) {
   15303     return FAST_STRING_WRAPPER_ELEMENTS;
   15304   }
   15305   DCHECK(object->HasDictionaryElements());
   15306   SeededNumberDictionary* dictionary = object->element_dictionary();
   15307   ElementsKind kind = FAST_HOLEY_SMI_ELEMENTS;
   15308   for (int i = 0; i < dictionary->Capacity(); i++) {
   15309     Object* key = dictionary->KeyAt(i);
   15310     if (key->IsNumber()) {
   15311       Object* value = dictionary->ValueAt(i);
   15312       if (!value->IsNumber()) return FAST_HOLEY_ELEMENTS;
   15313       if (!value->IsSmi()) {
   15314         if (!FLAG_unbox_double_arrays) return FAST_HOLEY_ELEMENTS;
   15315         kind = FAST_HOLEY_DOUBLE_ELEMENTS;
   15316       }
   15317     }
   15318   }
   15319   return kind;
   15320 }
   15321 
   15322 
   15323 static bool ShouldConvertToFastElements(JSObject* object,
   15324                                         SeededNumberDictionary* dictionary,
   15325                                         uint32_t index,
   15326                                         uint32_t* new_capacity) {
   15327   // If properties with non-standard attributes or accessors were added, we
   15328   // cannot go back to fast elements.
   15329   if (dictionary->requires_slow_elements()) return false;
   15330 
   15331   // Adding a property with this index will require slow elements.
   15332   if (index >= static_cast<uint32_t>(Smi::kMaxValue)) return false;
   15333 
   15334   if (object->IsJSArray()) {
   15335     Object* length = JSArray::cast(object)->length();
   15336     if (!length->IsSmi()) return false;
   15337     *new_capacity = static_cast<uint32_t>(Smi::cast(length)->value());
   15338   } else {
   15339     *new_capacity = dictionary->max_number_key() + 1;
   15340   }
   15341   *new_capacity = Max(index + 1, *new_capacity);
   15342 
   15343   uint32_t dictionary_size = static_cast<uint32_t>(dictionary->Capacity()) *
   15344                              SeededNumberDictionary::kEntrySize;
   15345 
   15346   // Turn fast if the dictionary only saves 50% space.
   15347   return 2 * dictionary_size >= *new_capacity;
   15348 }
   15349 
   15350 
   15351 // static
   15352 MaybeHandle<Object> JSObject::AddDataElement(Handle<JSObject> object,
   15353                                              uint32_t index,
   15354                                              Handle<Object> value,
   15355                                              PropertyAttributes attributes) {
   15356   MAYBE_RETURN_NULL(
   15357       AddDataElement(object, index, value, attributes, THROW_ON_ERROR));
   15358   return value;
   15359 }
   15360 
   15361 
   15362 // static
   15363 Maybe<bool> JSObject::AddDataElement(Handle<JSObject> object, uint32_t index,
   15364                                      Handle<Object> value,
   15365                                      PropertyAttributes attributes,
   15366                                      ShouldThrow should_throw) {
   15367   DCHECK(object->map()->is_extensible());
   15368 
   15369   Isolate* isolate = object->GetIsolate();
   15370 
   15371   uint32_t old_length = 0;
   15372   uint32_t new_capacity = 0;
   15373 
   15374   if (object->IsJSArray()) {
   15375     CHECK(JSArray::cast(*object)->length()->ToArrayLength(&old_length));
   15376   }
   15377 
   15378   ElementsKind kind = object->GetElementsKind();
   15379   FixedArrayBase* elements = object->elements();
   15380   ElementsKind dictionary_kind = DICTIONARY_ELEMENTS;
   15381   if (IsSloppyArgumentsElements(kind)) {
   15382     elements = FixedArrayBase::cast(FixedArray::cast(elements)->get(1));
   15383     dictionary_kind = SLOW_SLOPPY_ARGUMENTS_ELEMENTS;
   15384   } else if (IsStringWrapperElementsKind(kind)) {
   15385     dictionary_kind = SLOW_STRING_WRAPPER_ELEMENTS;
   15386   }
   15387 
   15388   if (attributes != NONE) {
   15389     kind = dictionary_kind;
   15390   } else if (elements->IsSeededNumberDictionary()) {
   15391     kind = ShouldConvertToFastElements(*object,
   15392                                        SeededNumberDictionary::cast(elements),
   15393                                        index, &new_capacity)
   15394                ? BestFittingFastElementsKind(*object)
   15395                : dictionary_kind;  // Overwrite in case of arguments.
   15396   } else if (ShouldConvertToSlowElements(
   15397                  *object, static_cast<uint32_t>(elements->length()), index,
   15398                  &new_capacity)) {
   15399     kind = dictionary_kind;
   15400   }
   15401 
   15402   ElementsKind to = value->OptimalElementsKind();
   15403   if (IsHoleyElementsKind(kind) || !object->IsJSArray() || index > old_length) {
   15404     to = GetHoleyElementsKind(to);
   15405     kind = GetHoleyElementsKind(kind);
   15406   }
   15407   to = GetMoreGeneralElementsKind(kind, to);
   15408   ElementsAccessor* accessor = ElementsAccessor::ForKind(to);
   15409   accessor->Add(object, index, value, attributes, new_capacity);
   15410 
   15411   if (object->IsJSArray() && index >= old_length) {
   15412     Handle<Object> new_length =
   15413         isolate->factory()->NewNumberFromUint(index + 1);
   15414     JSArray::cast(*object)->set_length(*new_length);
   15415   }
   15416 
   15417   return Just(true);
   15418 }
   15419 
   15420 
   15421 bool JSArray::SetLengthWouldNormalize(uint32_t new_length) {
   15422   if (!HasFastElements()) return false;
   15423   uint32_t capacity = static_cast<uint32_t>(elements()->length());
   15424   uint32_t new_capacity;
   15425   return JSArray::SetLengthWouldNormalize(GetHeap(), new_length) &&
   15426          ShouldConvertToSlowElements(this, capacity, new_length - 1,
   15427                                      &new_capacity);
   15428 }
   15429 
   15430 
   15431 const double AllocationSite::kPretenureRatio = 0.85;
   15432 
   15433 
   15434 void AllocationSite::ResetPretenureDecision() {
   15435   set_pretenure_decision(kUndecided);
   15436   set_memento_found_count(0);
   15437   set_memento_create_count(0);
   15438 }
   15439 
   15440 
   15441 PretenureFlag AllocationSite::GetPretenureMode() {
   15442   PretenureDecision mode = pretenure_decision();
   15443   // Zombie objects "decide" to be untenured.
   15444   return mode == kTenure ? TENURED : NOT_TENURED;
   15445 }
   15446 
   15447 
   15448 bool AllocationSite::IsNestedSite() {
   15449   DCHECK(FLAG_trace_track_allocation_sites);
   15450   Object* current = GetHeap()->allocation_sites_list();
   15451   while (current->IsAllocationSite()) {
   15452     AllocationSite* current_site = AllocationSite::cast(current);
   15453     if (current_site->nested_site() == this) {
   15454       return true;
   15455     }
   15456     current = current_site->weak_next();
   15457   }
   15458   return false;
   15459 }
   15460 
   15461 template <AllocationSiteUpdateMode update_or_check>
   15462 bool AllocationSite::DigestTransitionFeedback(Handle<AllocationSite> site,
   15463                                               ElementsKind to_kind) {
   15464   Isolate* isolate = site->GetIsolate();
   15465   bool result = false;
   15466 
   15467   if (site->SitePointsToLiteral() && site->transition_info()->IsJSArray()) {
   15468     Handle<JSArray> transition_info =
   15469         handle(JSArray::cast(site->transition_info()));
   15470     ElementsKind kind = transition_info->GetElementsKind();
   15471     // if kind is holey ensure that to_kind is as well.
   15472     if (IsHoleyElementsKind(kind)) {
   15473       to_kind = GetHoleyElementsKind(to_kind);
   15474     }
   15475     if (IsMoreGeneralElementsKindTransition(kind, to_kind)) {
   15476       // If the array is huge, it's not likely to be defined in a local
   15477       // function, so we shouldn't make new instances of it very often.
   15478       uint32_t length = 0;
   15479       CHECK(transition_info->length()->ToArrayLength(&length));
   15480       if (length <= kMaximumArrayBytesToPretransition) {
   15481         if (update_or_check == AllocationSiteUpdateMode::kCheckOnly) {
   15482           return true;
   15483         }
   15484         if (FLAG_trace_track_allocation_sites) {
   15485           bool is_nested = site->IsNestedSite();
   15486           PrintF(
   15487               "AllocationSite: JSArray %p boilerplate %s updated %s->%s\n",
   15488               reinterpret_cast<void*>(*site),
   15489               is_nested ? "(nested)" : "",
   15490               ElementsKindToString(kind),
   15491               ElementsKindToString(to_kind));
   15492         }
   15493         JSObject::TransitionElementsKind(transition_info, to_kind);
   15494         site->dependent_code()->DeoptimizeDependentCodeGroup(
   15495             isolate, DependentCode::kAllocationSiteTransitionChangedGroup);
   15496         result = true;
   15497       }
   15498     }
   15499   } else {
   15500     ElementsKind kind = site->GetElementsKind();
   15501     // if kind is holey ensure that to_kind is as well.
   15502     if (IsHoleyElementsKind(kind)) {
   15503       to_kind = GetHoleyElementsKind(to_kind);
   15504     }
   15505     if (IsMoreGeneralElementsKindTransition(kind, to_kind)) {
   15506       if (update_or_check == AllocationSiteUpdateMode::kCheckOnly) return true;
   15507       if (FLAG_trace_track_allocation_sites) {
   15508         PrintF("AllocationSite: JSArray %p site updated %s->%s\n",
   15509                reinterpret_cast<void*>(*site),
   15510                ElementsKindToString(kind),
   15511                ElementsKindToString(to_kind));
   15512       }
   15513       site->SetElementsKind(to_kind);
   15514       site->dependent_code()->DeoptimizeDependentCodeGroup(
   15515           isolate, DependentCode::kAllocationSiteTransitionChangedGroup);
   15516       result = true;
   15517     }
   15518   }
   15519   return result;
   15520 }
   15521 
   15522 AllocationSiteMode AllocationSite::GetMode(ElementsKind from, ElementsKind to) {
   15523   if (IsFastSmiElementsKind(from) &&
   15524       IsMoreGeneralElementsKindTransition(from, to)) {
   15525     return TRACK_ALLOCATION_SITE;
   15526   }
   15527 
   15528   return DONT_TRACK_ALLOCATION_SITE;
   15529 }
   15530 
   15531 const char* AllocationSite::PretenureDecisionName(PretenureDecision decision) {
   15532   switch (decision) {
   15533     case kUndecided: return "undecided";
   15534     case kDontTenure: return "don't tenure";
   15535     case kMaybeTenure: return "maybe tenure";
   15536     case kTenure: return "tenure";
   15537     case kZombie: return "zombie";
   15538     default: UNREACHABLE();
   15539   }
   15540   return NULL;
   15541 }
   15542 
   15543 template <AllocationSiteUpdateMode update_or_check>
   15544 bool JSObject::UpdateAllocationSite(Handle<JSObject> object,
   15545                                     ElementsKind to_kind) {
   15546   if (!object->IsJSArray()) return false;
   15547 
   15548   Heap* heap = object->GetHeap();
   15549   if (!heap->InNewSpace(*object)) return false;
   15550 
   15551   Handle<AllocationSite> site;
   15552   {
   15553     DisallowHeapAllocation no_allocation;
   15554 
   15555     AllocationMemento* memento =
   15556         heap->FindAllocationMemento<Heap::kForRuntime>(*object);
   15557     if (memento == NULL) return false;
   15558 
   15559     // Walk through to the Allocation Site
   15560     site = handle(memento->GetAllocationSite());
   15561   }
   15562   return AllocationSite::DigestTransitionFeedback<update_or_check>(site,
   15563                                                                    to_kind);
   15564 }
   15565 
   15566 template bool
   15567 JSObject::UpdateAllocationSite<AllocationSiteUpdateMode::kCheckOnly>(
   15568     Handle<JSObject> object, ElementsKind to_kind);
   15569 
   15570 template bool JSObject::UpdateAllocationSite<AllocationSiteUpdateMode::kUpdate>(
   15571     Handle<JSObject> object, ElementsKind to_kind);
   15572 
   15573 void JSObject::TransitionElementsKind(Handle<JSObject> object,
   15574                                       ElementsKind to_kind) {
   15575   ElementsKind from_kind = object->GetElementsKind();
   15576 
   15577   if (IsFastHoleyElementsKind(from_kind)) {
   15578     to_kind = GetHoleyElementsKind(to_kind);
   15579   }
   15580 
   15581   if (from_kind == to_kind) return;
   15582 
   15583   // This method should never be called for any other case.
   15584   DCHECK(IsFastElementsKind(from_kind));
   15585   DCHECK(IsFastElementsKind(to_kind));
   15586   DCHECK_NE(TERMINAL_FAST_ELEMENTS_KIND, from_kind);
   15587 
   15588   UpdateAllocationSite(object, to_kind);
   15589   if (object->elements() == object->GetHeap()->empty_fixed_array() ||
   15590       IsFastDoubleElementsKind(from_kind) ==
   15591           IsFastDoubleElementsKind(to_kind)) {
   15592     // No change is needed to the elements() buffer, the transition
   15593     // only requires a map change.
   15594     Handle<Map> new_map = GetElementsTransitionMap(object, to_kind);
   15595     MigrateToMap(object, new_map);
   15596     if (FLAG_trace_elements_transitions) {
   15597       Handle<FixedArrayBase> elms(object->elements());
   15598       PrintElementsTransition(stdout, object, from_kind, elms, to_kind, elms);
   15599     }
   15600   } else {
   15601     DCHECK((IsFastSmiElementsKind(from_kind) &&
   15602             IsFastDoubleElementsKind(to_kind)) ||
   15603            (IsFastDoubleElementsKind(from_kind) &&
   15604             IsFastObjectElementsKind(to_kind)));
   15605     uint32_t c = static_cast<uint32_t>(object->elements()->length());
   15606     ElementsAccessor::ForKind(to_kind)->GrowCapacityAndConvert(object, c);
   15607   }
   15608 }
   15609 
   15610 
   15611 // static
   15612 bool Map::IsValidElementsTransition(ElementsKind from_kind,
   15613                                     ElementsKind to_kind) {
   15614   // Transitions can't go backwards.
   15615   if (!IsMoreGeneralElementsKindTransition(from_kind, to_kind)) {
   15616     return false;
   15617   }
   15618 
   15619   // Transitions from HOLEY -> PACKED are not allowed.
   15620   return !IsFastHoleyElementsKind(from_kind) ||
   15621       IsFastHoleyElementsKind(to_kind);
   15622 }
   15623 
   15624 
   15625 bool JSArray::HasReadOnlyLength(Handle<JSArray> array) {
   15626   Map* map = array->map();
   15627   // Fast path: "length" is the first fast property of arrays. Since it's not
   15628   // configurable, it's guaranteed to be the first in the descriptor array.
   15629   if (!map->is_dictionary_map()) {
   15630     DCHECK(map->instance_descriptors()->GetKey(0) ==
   15631            array->GetHeap()->length_string());
   15632     return map->instance_descriptors()->GetDetails(0).IsReadOnly();
   15633   }
   15634 
   15635   Isolate* isolate = array->GetIsolate();
   15636   LookupIterator it(array, isolate->factory()->length_string(), array,
   15637                     LookupIterator::OWN_SKIP_INTERCEPTOR);
   15638   CHECK_EQ(LookupIterator::ACCESSOR, it.state());
   15639   return it.IsReadOnly();
   15640 }
   15641 
   15642 
   15643 bool JSArray::WouldChangeReadOnlyLength(Handle<JSArray> array,
   15644                                         uint32_t index) {
   15645   uint32_t length = 0;
   15646   CHECK(array->length()->ToArrayLength(&length));
   15647   if (length <= index) return HasReadOnlyLength(array);
   15648   return false;
   15649 }
   15650 
   15651 
   15652 template <typename BackingStore>
   15653 static int FastHoleyElementsUsage(JSObject* object, BackingStore* store) {
   15654   Isolate* isolate = store->GetIsolate();
   15655   int limit = object->IsJSArray()
   15656                   ? Smi::cast(JSArray::cast(object)->length())->value()
   15657                   : store->length();
   15658   int used = 0;
   15659   for (int i = 0; i < limit; ++i) {
   15660     if (!store->is_the_hole(isolate, i)) ++used;
   15661   }
   15662   return used;
   15663 }
   15664 
   15665 
   15666 int JSObject::GetFastElementsUsage() {
   15667   FixedArrayBase* store = elements();
   15668   switch (GetElementsKind()) {
   15669     case FAST_SMI_ELEMENTS:
   15670     case FAST_DOUBLE_ELEMENTS:
   15671     case FAST_ELEMENTS:
   15672       return IsJSArray() ? Smi::cast(JSArray::cast(this)->length())->value()
   15673                          : store->length();
   15674     case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
   15675       store = FixedArray::cast(FixedArray::cast(store)->get(1));
   15676     // Fall through.
   15677     case FAST_HOLEY_SMI_ELEMENTS:
   15678     case FAST_HOLEY_ELEMENTS:
   15679     case FAST_STRING_WRAPPER_ELEMENTS:
   15680       return FastHoleyElementsUsage(this, FixedArray::cast(store));
   15681     case FAST_HOLEY_DOUBLE_ELEMENTS:
   15682       if (elements()->length() == 0) return 0;
   15683       return FastHoleyElementsUsage(this, FixedDoubleArray::cast(store));
   15684 
   15685     case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
   15686     case SLOW_STRING_WRAPPER_ELEMENTS:
   15687     case DICTIONARY_ELEMENTS:
   15688     case NO_ELEMENTS:
   15689 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                      \
   15690     case TYPE##_ELEMENTS:                                                    \
   15691 
   15692     TYPED_ARRAYS(TYPED_ARRAY_CASE)
   15693 #undef TYPED_ARRAY_CASE
   15694     UNREACHABLE();
   15695   }
   15696   return 0;
   15697 }
   15698 
   15699 
   15700 // Certain compilers request function template instantiation when they
   15701 // see the definition of the other template functions in the
   15702 // class. This requires us to have the template functions put
   15703 // together, so even though this function belongs in objects-debug.cc,
   15704 // we keep it here instead to satisfy certain compilers.
   15705 #ifdef OBJECT_PRINT
   15706 template <typename Derived, typename Shape, typename Key>
   15707 void Dictionary<Derived, Shape, Key>::Print(std::ostream& os) {  // NOLINT
   15708   Isolate* isolate = this->GetIsolate();
   15709   int capacity = this->Capacity();
   15710   for (int i = 0; i < capacity; i++) {
   15711     Object* k = this->KeyAt(i);
   15712     if (this->IsKey(isolate, k)) {
   15713       os << "\n   ";
   15714       if (k->IsString()) {
   15715         String::cast(k)->StringPrint(os);
   15716       } else {
   15717         os << Brief(k);
   15718       }
   15719       os << ": " << Brief(this->ValueAt(i)) << " ";
   15720       this->DetailsAt(i).PrintAsSlowTo(os);
   15721     }
   15722   }
   15723 }
   15724 template <typename Derived, typename Shape, typename Key>
   15725 void Dictionary<Derived, Shape, Key>::Print() {
   15726   OFStream os(stdout);
   15727   Print(os);
   15728 }
   15729 #endif
   15730 
   15731 
   15732 template<typename Derived, typename Shape, typename Key>
   15733 void Dictionary<Derived, Shape, Key>::CopyValuesTo(FixedArray* elements) {
   15734   Isolate* isolate = this->GetIsolate();
   15735   int pos = 0;
   15736   int capacity = this->Capacity();
   15737   DisallowHeapAllocation no_gc;
   15738   WriteBarrierMode mode = elements->GetWriteBarrierMode(no_gc);
   15739   for (int i = 0; i < capacity; i++) {
   15740     Object* k = this->KeyAt(i);
   15741     if (this->IsKey(isolate, k)) {
   15742       elements->set(pos++, this->ValueAt(i), mode);
   15743     }
   15744   }
   15745   DCHECK(pos == elements->length());
   15746 }
   15747 
   15748 
   15749 MaybeHandle<Object> JSObject::GetPropertyWithInterceptor(LookupIterator* it,
   15750                                                          bool* done) {
   15751   DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
   15752   return GetPropertyWithInterceptorInternal(it, it->GetInterceptor(), done);
   15753 }
   15754 
   15755 Maybe<bool> JSObject::HasRealNamedProperty(Handle<JSObject> object,
   15756                                            Handle<Name> name) {
   15757   LookupIterator it = LookupIterator::PropertyOrElement(
   15758       name->GetIsolate(), object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
   15759   return HasProperty(&it);
   15760 }
   15761 
   15762 
   15763 Maybe<bool> JSObject::HasRealElementProperty(Handle<JSObject> object,
   15764                                              uint32_t index) {
   15765   Isolate* isolate = object->GetIsolate();
   15766   LookupIterator it(isolate, object, index, object,
   15767                     LookupIterator::OWN_SKIP_INTERCEPTOR);
   15768   return HasProperty(&it);
   15769 }
   15770 
   15771 
   15772 Maybe<bool> JSObject::HasRealNamedCallbackProperty(Handle<JSObject> object,
   15773                                                    Handle<Name> name) {
   15774   LookupIterator it = LookupIterator::PropertyOrElement(
   15775       name->GetIsolate(), object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
   15776   Maybe<PropertyAttributes> maybe_result = GetPropertyAttributes(&it);
   15777   return maybe_result.IsJust() ? Just(it.state() == LookupIterator::ACCESSOR)
   15778                                : Nothing<bool>();
   15779 }
   15780 
   15781 int FixedArrayBase::GetMaxLengthForNewSpaceAllocation(ElementsKind kind) {
   15782   return ((kMaxRegularHeapObjectSize - FixedArrayBase::kHeaderSize) >>
   15783           ElementsKindToShiftSize(kind));
   15784 }
   15785 
   15786 bool JSObject::WasConstructedFromApiFunction() {
   15787   auto instance_type = map()->instance_type();
   15788   bool is_api_object = instance_type == JS_API_OBJECT_TYPE ||
   15789                        instance_type == JS_SPECIAL_API_OBJECT_TYPE;
   15790 #ifdef ENABLE_SLOW_DCHECKS
   15791   if (FLAG_enable_slow_asserts) {
   15792     Object* maybe_constructor = map()->GetConstructor();
   15793     if (!maybe_constructor->IsJSFunction()) return false;
   15794     JSFunction* constructor = JSFunction::cast(maybe_constructor);
   15795     if (constructor->shared()->IsApiFunction()) {
   15796       DCHECK(is_api_object);
   15797     } else {
   15798       DCHECK(!is_api_object);
   15799     }
   15800   }
   15801 #endif
   15802   return is_api_object;
   15803 }
   15804 
   15805 const char* Symbol::PrivateSymbolToName() const {
   15806   Heap* heap = GetIsolate()->heap();
   15807 #define SYMBOL_CHECK_AND_PRINT(name) \
   15808   if (this == heap->name()) return #name;
   15809   PRIVATE_SYMBOL_LIST(SYMBOL_CHECK_AND_PRINT)
   15810 #undef SYMBOL_CHECK_AND_PRINT
   15811   return "UNKNOWN";
   15812 }
   15813 
   15814 
   15815 void Symbol::SymbolShortPrint(std::ostream& os) {
   15816   os << "<Symbol:";
   15817   if (!name()->IsUndefined(GetIsolate())) {
   15818     os << " ";
   15819     HeapStringAllocator allocator;
   15820     StringStream accumulator(&allocator);
   15821     String::cast(name())->StringShortPrint(&accumulator, false);
   15822     os << accumulator.ToCString().get();
   15823   } else {
   15824     os << " (" << PrivateSymbolToName() << ")";
   15825   }
   15826   os << ">";
   15827 }
   15828 
   15829 
   15830 // StringSharedKeys are used as keys in the eval cache.
   15831 class StringSharedKey : public HashTableKey {
   15832  public:
   15833   // This tuple unambiguously identifies calls to eval() or
   15834   // CreateDynamicFunction() (such as through the Function() constructor).
   15835   // * source is the string passed into eval(). For dynamic functions, this is
   15836   //   the effective source for the function, some of which is implicitly
   15837   //   generated.
   15838   // * shared is the shared function info for the function containing the call
   15839   //   to eval(). for dynamic functions, shared is the native context closure.
   15840   // * When positive, position is the position in the source where eval is
   15841   //   called. When negative, position is the negation of the position in the
   15842   //   dynamic function's effective source where the ')' ends the parameters.
   15843   StringSharedKey(Handle<String> source, Handle<SharedFunctionInfo> shared,
   15844                   LanguageMode language_mode, int position)
   15845       : source_(source),
   15846         shared_(shared),
   15847         language_mode_(language_mode),
   15848         position_(position) {}
   15849 
   15850   bool IsMatch(Object* other) override {
   15851     DisallowHeapAllocation no_allocation;
   15852     if (!other->IsFixedArray()) {
   15853       if (!other->IsNumber()) return false;
   15854       uint32_t other_hash = static_cast<uint32_t>(other->Number());
   15855       return Hash() == other_hash;
   15856     }
   15857     FixedArray* other_array = FixedArray::cast(other);
   15858     SharedFunctionInfo* shared = SharedFunctionInfo::cast(other_array->get(0));
   15859     if (shared != *shared_) return false;
   15860     int language_unchecked = Smi::cast(other_array->get(2))->value();
   15861     DCHECK(is_valid_language_mode(language_unchecked));
   15862     LanguageMode language_mode = static_cast<LanguageMode>(language_unchecked);
   15863     if (language_mode != language_mode_) return false;
   15864     int position = Smi::cast(other_array->get(3))->value();
   15865     if (position != position_) return false;
   15866     String* source = String::cast(other_array->get(1));
   15867     return source->Equals(*source_);
   15868   }
   15869 
   15870   static uint32_t StringSharedHashHelper(String* source,
   15871                                          SharedFunctionInfo* shared,
   15872                                          LanguageMode language_mode,
   15873                                          int position) {
   15874     uint32_t hash = source->Hash();
   15875     if (shared->HasSourceCode()) {
   15876       // Instead of using the SharedFunctionInfo pointer in the hash
   15877       // code computation, we use a combination of the hash of the
   15878       // script source code and the start position of the calling scope.
   15879       // We do this to ensure that the cache entries can survive garbage
   15880       // collection.
   15881       Script* script(Script::cast(shared->script()));
   15882       hash ^= String::cast(script->source())->Hash();
   15883       STATIC_ASSERT(LANGUAGE_END == 2);
   15884       if (is_strict(language_mode)) hash ^= 0x8000;
   15885       hash += position;
   15886     }
   15887     return hash;
   15888   }
   15889 
   15890   uint32_t Hash() override {
   15891     return StringSharedHashHelper(*source_, *shared_, language_mode_,
   15892                                   position_);
   15893   }
   15894 
   15895   uint32_t HashForObject(Object* obj) override {
   15896     DisallowHeapAllocation no_allocation;
   15897     if (obj->IsNumber()) {
   15898       return static_cast<uint32_t>(obj->Number());
   15899     }
   15900     FixedArray* other_array = FixedArray::cast(obj);
   15901     SharedFunctionInfo* shared = SharedFunctionInfo::cast(other_array->get(0));
   15902     String* source = String::cast(other_array->get(1));
   15903     int language_unchecked = Smi::cast(other_array->get(2))->value();
   15904     DCHECK(is_valid_language_mode(language_unchecked));
   15905     LanguageMode language_mode = static_cast<LanguageMode>(language_unchecked);
   15906     int position = Smi::cast(other_array->get(3))->value();
   15907     return StringSharedHashHelper(source, shared, language_mode, position);
   15908   }
   15909 
   15910 
   15911   Handle<Object> AsHandle(Isolate* isolate) override {
   15912     Handle<FixedArray> array = isolate->factory()->NewFixedArray(4);
   15913     array->set(0, *shared_);
   15914     array->set(1, *source_);
   15915     array->set(2, Smi::FromInt(language_mode_));
   15916     array->set(3, Smi::FromInt(position_));
   15917     return array;
   15918   }
   15919 
   15920  private:
   15921   Handle<String> source_;
   15922   Handle<SharedFunctionInfo> shared_;
   15923   LanguageMode language_mode_;
   15924   int position_;
   15925 };
   15926 
   15927 // static
   15928 const char* JSPromise::Status(int status) {
   15929   switch (status) {
   15930     case v8::Promise::kFulfilled:
   15931       return "resolved";
   15932     case v8::Promise::kPending:
   15933       return "pending";
   15934     case v8::Promise::kRejected:
   15935       return "rejected";
   15936   }
   15937   UNREACHABLE();
   15938   return NULL;
   15939 }
   15940 
   15941 namespace {
   15942 
   15943 JSRegExp::Flags RegExpFlagsFromString(Handle<String> flags, bool* success) {
   15944   JSRegExp::Flags value = JSRegExp::kNone;
   15945   int length = flags->length();
   15946   // A longer flags string cannot be valid.
   15947   if (length > 5) return JSRegExp::Flags(0);
   15948   for (int i = 0; i < length; i++) {
   15949     JSRegExp::Flag flag = JSRegExp::kNone;
   15950     switch (flags->Get(i)) {
   15951       case 'g':
   15952         flag = JSRegExp::kGlobal;
   15953         break;
   15954       case 'i':
   15955         flag = JSRegExp::kIgnoreCase;
   15956         break;
   15957       case 'm':
   15958         flag = JSRegExp::kMultiline;
   15959         break;
   15960       case 'u':
   15961         flag = JSRegExp::kUnicode;
   15962         break;
   15963       case 'y':
   15964         flag = JSRegExp::kSticky;
   15965         break;
   15966       default:
   15967         return JSRegExp::Flags(0);
   15968     }
   15969     // Duplicate flag.
   15970     if (value & flag) return JSRegExp::Flags(0);
   15971     value |= flag;
   15972   }
   15973   *success = true;
   15974   return value;
   15975 }
   15976 
   15977 }  // namespace
   15978 
   15979 
   15980 // static
   15981 MaybeHandle<JSRegExp> JSRegExp::New(Handle<String> pattern, Flags flags) {
   15982   Isolate* isolate = pattern->GetIsolate();
   15983   Handle<JSFunction> constructor = isolate->regexp_function();
   15984   Handle<JSRegExp> regexp =
   15985       Handle<JSRegExp>::cast(isolate->factory()->NewJSObject(constructor));
   15986 
   15987   return JSRegExp::Initialize(regexp, pattern, flags);
   15988 }
   15989 
   15990 
   15991 // static
   15992 Handle<JSRegExp> JSRegExp::Copy(Handle<JSRegExp> regexp) {
   15993   Isolate* const isolate = regexp->GetIsolate();
   15994   return Handle<JSRegExp>::cast(isolate->factory()->CopyJSObject(regexp));
   15995 }
   15996 
   15997 
   15998 template <typename Char>
   15999 inline int CountRequiredEscapes(Handle<String> source) {
   16000   DisallowHeapAllocation no_gc;
   16001   int escapes = 0;
   16002   Vector<const Char> src = source->GetCharVector<Char>();
   16003   for (int i = 0; i < src.length(); i++) {
   16004     if (src[i] == '\\') {
   16005       // Escape. Skip next character;
   16006       i++;
   16007     } else if (src[i] == '/') {
   16008       // Not escaped forward-slash needs escape.
   16009       escapes++;
   16010     }
   16011   }
   16012   return escapes;
   16013 }
   16014 
   16015 
   16016 template <typename Char, typename StringType>
   16017 inline Handle<StringType> WriteEscapedRegExpSource(Handle<String> source,
   16018                                                    Handle<StringType> result) {
   16019   DisallowHeapAllocation no_gc;
   16020   Vector<const Char> src = source->GetCharVector<Char>();
   16021   Vector<Char> dst(result->GetChars(), result->length());
   16022   int s = 0;
   16023   int d = 0;
   16024   while (s < src.length()) {
   16025     if (src[s] == '\\') {
   16026       // Escape. Copy this and next character.
   16027       dst[d++] = src[s++];
   16028       if (s == src.length()) break;
   16029     } else if (src[s] == '/') {
   16030       // Not escaped forward-slash needs escape.
   16031       dst[d++] = '\\';
   16032     }
   16033     dst[d++] = src[s++];
   16034   }
   16035   DCHECK_EQ(result->length(), d);
   16036   return result;
   16037 }
   16038 
   16039 
   16040 MaybeHandle<String> EscapeRegExpSource(Isolate* isolate,
   16041                                        Handle<String> source) {
   16042   String::Flatten(source);
   16043   if (source->length() == 0) return isolate->factory()->query_colon_string();
   16044   bool one_byte = source->IsOneByteRepresentationUnderneath();
   16045   int escapes = one_byte ? CountRequiredEscapes<uint8_t>(source)
   16046                          : CountRequiredEscapes<uc16>(source);
   16047   if (escapes == 0) return source;
   16048   int length = source->length() + escapes;
   16049   if (one_byte) {
   16050     Handle<SeqOneByteString> result;
   16051     ASSIGN_RETURN_ON_EXCEPTION(isolate, result,
   16052                                isolate->factory()->NewRawOneByteString(length),
   16053                                String);
   16054     return WriteEscapedRegExpSource<uint8_t>(source, result);
   16055   } else {
   16056     Handle<SeqTwoByteString> result;
   16057     ASSIGN_RETURN_ON_EXCEPTION(isolate, result,
   16058                                isolate->factory()->NewRawTwoByteString(length),
   16059                                String);
   16060     return WriteEscapedRegExpSource<uc16>(source, result);
   16061   }
   16062 }
   16063 
   16064 
   16065 // static
   16066 MaybeHandle<JSRegExp> JSRegExp::Initialize(Handle<JSRegExp> regexp,
   16067                                            Handle<String> source,
   16068                                            Handle<String> flags_string) {
   16069   Isolate* isolate = source->GetIsolate();
   16070   bool success = false;
   16071   Flags flags = RegExpFlagsFromString(flags_string, &success);
   16072   if (!success) {
   16073     THROW_NEW_ERROR(
   16074         isolate,
   16075         NewSyntaxError(MessageTemplate::kInvalidRegExpFlags, flags_string),
   16076         JSRegExp);
   16077   }
   16078   return Initialize(regexp, source, flags);
   16079 }
   16080 
   16081 
   16082 // static
   16083 MaybeHandle<JSRegExp> JSRegExp::Initialize(Handle<JSRegExp> regexp,
   16084                                            Handle<String> source, Flags flags) {
   16085   Isolate* isolate = regexp->GetIsolate();
   16086   Factory* factory = isolate->factory();
   16087   // If source is the empty string we set it to "(?:)" instead as
   16088   // suggested by ECMA-262, 5th, section 15.10.4.1.
   16089   if (source->length() == 0) source = factory->query_colon_string();
   16090 
   16091   Handle<String> escaped_source;
   16092   ASSIGN_RETURN_ON_EXCEPTION(isolate, escaped_source,
   16093                              EscapeRegExpSource(isolate, source), JSRegExp);
   16094 
   16095   RETURN_ON_EXCEPTION(isolate, RegExpImpl::Compile(regexp, source, flags),
   16096                       JSRegExp);
   16097 
   16098   regexp->set_source(*escaped_source);
   16099   regexp->set_flags(Smi::FromInt(flags));
   16100 
   16101   Map* map = regexp->map();
   16102   Object* constructor = map->GetConstructor();
   16103   if (constructor->IsJSFunction() &&
   16104       JSFunction::cast(constructor)->initial_map() == map) {
   16105     // If we still have the original map, set in-object properties directly.
   16106     regexp->InObjectPropertyAtPut(JSRegExp::kLastIndexFieldIndex, Smi::kZero,
   16107                                   SKIP_WRITE_BARRIER);
   16108   } else {
   16109     // Map has changed, so use generic, but slower, method.
   16110     RETURN_ON_EXCEPTION(isolate, JSReceiver::SetProperty(
   16111                                      regexp, factory->lastIndex_string(),
   16112                                      Handle<Smi>(Smi::kZero, isolate), STRICT),
   16113                         JSRegExp);
   16114   }
   16115 
   16116   return regexp;
   16117 }
   16118 
   16119 
   16120 // RegExpKey carries the source and flags of a regular expression as key.
   16121 class RegExpKey : public HashTableKey {
   16122  public:
   16123   RegExpKey(Handle<String> string, JSRegExp::Flags flags)
   16124       : string_(string), flags_(Smi::FromInt(flags)) {}
   16125 
   16126   // Rather than storing the key in the hash table, a pointer to the
   16127   // stored value is stored where the key should be.  IsMatch then
   16128   // compares the search key to the found object, rather than comparing
   16129   // a key to a key.
   16130   bool IsMatch(Object* obj) override {
   16131     FixedArray* val = FixedArray::cast(obj);
   16132     return string_->Equals(String::cast(val->get(JSRegExp::kSourceIndex)))
   16133         && (flags_ == val->get(JSRegExp::kFlagsIndex));
   16134   }
   16135 
   16136   uint32_t Hash() override { return RegExpHash(*string_, flags_); }
   16137 
   16138   Handle<Object> AsHandle(Isolate* isolate) override {
   16139     // Plain hash maps, which is where regexp keys are used, don't
   16140     // use this function.
   16141     UNREACHABLE();
   16142     return MaybeHandle<Object>().ToHandleChecked();
   16143   }
   16144 
   16145   uint32_t HashForObject(Object* obj) override {
   16146     FixedArray* val = FixedArray::cast(obj);
   16147     return RegExpHash(String::cast(val->get(JSRegExp::kSourceIndex)),
   16148                       Smi::cast(val->get(JSRegExp::kFlagsIndex)));
   16149   }
   16150 
   16151   static uint32_t RegExpHash(String* string, Smi* flags) {
   16152     return string->Hash() + flags->value();
   16153   }
   16154 
   16155   Handle<String> string_;
   16156   Smi* flags_;
   16157 };
   16158 
   16159 
   16160 Handle<Object> OneByteStringKey::AsHandle(Isolate* isolate) {
   16161   if (hash_field_ == 0) Hash();
   16162   return isolate->factory()->NewOneByteInternalizedString(string_, hash_field_);
   16163 }
   16164 
   16165 
   16166 Handle<Object> TwoByteStringKey::AsHandle(Isolate* isolate) {
   16167   if (hash_field_ == 0) Hash();
   16168   return isolate->factory()->NewTwoByteInternalizedString(string_, hash_field_);
   16169 }
   16170 
   16171 
   16172 Handle<Object> SeqOneByteSubStringKey::AsHandle(Isolate* isolate) {
   16173   if (hash_field_ == 0) Hash();
   16174   return isolate->factory()->NewOneByteInternalizedSubString(
   16175       string_, from_, length_, hash_field_);
   16176 }
   16177 
   16178 
   16179 bool SeqOneByteSubStringKey::IsMatch(Object* string) {
   16180   Vector<const uint8_t> chars(string_->GetChars() + from_, length_);
   16181   return String::cast(string)->IsOneByteEqualTo(chars);
   16182 }
   16183 
   16184 
   16185 // InternalizedStringKey carries a string/internalized-string object as key.
   16186 class InternalizedStringKey : public HashTableKey {
   16187  public:
   16188   explicit InternalizedStringKey(Handle<String> string)
   16189       : string_(String::Flatten(string)) {}
   16190 
   16191   bool IsMatch(Object* string) override {
   16192     return String::cast(string)->Equals(*string_);
   16193   }
   16194 
   16195   uint32_t Hash() override { return string_->Hash(); }
   16196 
   16197   uint32_t HashForObject(Object* other) override {
   16198     return String::cast(other)->Hash();
   16199   }
   16200 
   16201   Handle<Object> AsHandle(Isolate* isolate) override {
   16202     // Internalize the string if possible.
   16203     MaybeHandle<Map> maybe_map =
   16204         isolate->factory()->InternalizedStringMapForString(string_);
   16205     Handle<Map> map;
   16206     if (maybe_map.ToHandle(&map)) {
   16207       string_->set_map_no_write_barrier(*map);
   16208       DCHECK(string_->IsInternalizedString());
   16209       return string_;
   16210     }
   16211     if (FLAG_thin_strings) {
   16212       // External strings get special treatment, to avoid copying their
   16213       // contents.
   16214       if (string_->IsExternalOneByteString()) {
   16215         return isolate->factory()
   16216             ->InternalizeExternalString<ExternalOneByteString>(string_);
   16217       } else if (string_->IsExternalTwoByteString()) {
   16218         return isolate->factory()
   16219             ->InternalizeExternalString<ExternalTwoByteString>(string_);
   16220       }
   16221     }
   16222     // Otherwise allocate a new internalized string.
   16223     return isolate->factory()->NewInternalizedStringImpl(
   16224         string_, string_->length(), string_->hash_field());
   16225   }
   16226 
   16227   static uint32_t StringHash(Object* obj) {
   16228     return String::cast(obj)->Hash();
   16229   }
   16230 
   16231  private:
   16232   Handle<String> string_;
   16233 };
   16234 
   16235 
   16236 template<typename Derived, typename Shape, typename Key>
   16237 void HashTable<Derived, Shape, Key>::IteratePrefix(ObjectVisitor* v) {
   16238   BodyDescriptorBase::IteratePointers(this, 0, kElementsStartOffset, v);
   16239 }
   16240 
   16241 
   16242 template<typename Derived, typename Shape, typename Key>
   16243 void HashTable<Derived, Shape, Key>::IterateElements(ObjectVisitor* v) {
   16244   BodyDescriptorBase::IteratePointers(this, kElementsStartOffset,
   16245                                       kHeaderSize + length() * kPointerSize, v);
   16246 }
   16247 
   16248 
   16249 template<typename Derived, typename Shape, typename Key>
   16250 Handle<Derived> HashTable<Derived, Shape, Key>::New(
   16251     Isolate* isolate,
   16252     int at_least_space_for,
   16253     MinimumCapacity capacity_option,
   16254     PretenureFlag pretenure) {
   16255   DCHECK(0 <= at_least_space_for);
   16256   DCHECK_IMPLIES(capacity_option == USE_CUSTOM_MINIMUM_CAPACITY,
   16257                  base::bits::IsPowerOfTwo32(at_least_space_for));
   16258 
   16259   int capacity = (capacity_option == USE_CUSTOM_MINIMUM_CAPACITY)
   16260                      ? at_least_space_for
   16261                      : ComputeCapacity(at_least_space_for);
   16262   if (capacity > HashTable::kMaxCapacity) {
   16263     v8::internal::Heap::FatalProcessOutOfMemory("invalid table size", true);
   16264   }
   16265   return New(isolate, capacity, pretenure);
   16266 }
   16267 
   16268 template <typename Derived, typename Shape, typename Key>
   16269 Handle<Derived> HashTable<Derived, Shape, Key>::New(Isolate* isolate,
   16270                                                     int capacity,
   16271                                                     PretenureFlag pretenure) {
   16272   Factory* factory = isolate->factory();
   16273   int length = EntryToIndex(capacity);
   16274   Handle<FixedArray> array = factory->NewFixedArray(length, pretenure);
   16275   array->set_map_no_write_barrier(Shape::GetMap(isolate));
   16276   Handle<Derived> table = Handle<Derived>::cast(array);
   16277 
   16278   table->SetNumberOfElements(0);
   16279   table->SetNumberOfDeletedElements(0);
   16280   table->SetCapacity(capacity);
   16281   return table;
   16282 }
   16283 
   16284 // Find entry for key otherwise return kNotFound.
   16285 template <typename Derived, typename Shape>
   16286 int NameDictionaryBase<Derived, Shape>::FindEntry(Handle<Name> key) {
   16287   if (!key->IsUniqueName()) {
   16288     return DerivedDictionary::FindEntry(key);
   16289   }
   16290 
   16291   // Optimized for unique names. Knowledge of the key type allows:
   16292   // 1. Move the check if the key is unique out of the loop.
   16293   // 2. Avoid comparing hash codes in unique-to-unique comparison.
   16294   // 3. Detect a case when a dictionary key is not unique but the key is.
   16295   //    In case of positive result the dictionary key may be replaced by the
   16296   //    internalized string with minimal performance penalty. It gives a chance
   16297   //    to perform further lookups in code stubs (and significant performance
   16298   //    boost a certain style of code).
   16299 
   16300   // EnsureCapacity will guarantee the hash table is never full.
   16301   uint32_t capacity = this->Capacity();
   16302   uint32_t entry = Derived::FirstProbe(key->Hash(), capacity);
   16303   uint32_t count = 1;
   16304   Isolate* isolate = this->GetIsolate();
   16305   while (true) {
   16306     Object* element = this->KeyAt(entry);
   16307     if (element->IsUndefined(isolate)) break;  // Empty entry.
   16308     if (*key == element) return entry;
   16309     DCHECK(element->IsTheHole(isolate) || element->IsUniqueName());
   16310     entry = Derived::NextProbe(entry, count++, capacity);
   16311   }
   16312   return Derived::kNotFound;
   16313 }
   16314 
   16315 
   16316 template<typename Derived, typename Shape, typename Key>
   16317 void HashTable<Derived, Shape, Key>::Rehash(
   16318     Handle<Derived> new_table,
   16319     Key key) {
   16320   DCHECK(NumberOfElements() < new_table->Capacity());
   16321 
   16322   DisallowHeapAllocation no_gc;
   16323   WriteBarrierMode mode = new_table->GetWriteBarrierMode(no_gc);
   16324 
   16325   // Copy prefix to new array.
   16326   for (int i = kPrefixStartIndex;
   16327        i < kPrefixStartIndex + Shape::kPrefixSize;
   16328        i++) {
   16329     new_table->set(i, get(i), mode);
   16330   }
   16331 
   16332   // Rehash the elements.
   16333   int capacity = this->Capacity();
   16334   Heap* heap = new_table->GetHeap();
   16335   Object* the_hole = heap->the_hole_value();
   16336   Object* undefined = heap->undefined_value();
   16337   for (int i = 0; i < capacity; i++) {
   16338     uint32_t from_index = EntryToIndex(i);
   16339     Object* k = this->get(from_index);
   16340     if (k != the_hole && k != undefined) {
   16341       uint32_t hash = this->HashForObject(key, k);
   16342       uint32_t insertion_index =
   16343           EntryToIndex(new_table->FindInsertionEntry(hash));
   16344       for (int j = 0; j < Shape::kEntrySize; j++) {
   16345         new_table->set(insertion_index + j, get(from_index + j), mode);
   16346       }
   16347     }
   16348   }
   16349   new_table->SetNumberOfElements(NumberOfElements());
   16350   new_table->SetNumberOfDeletedElements(0);
   16351 }
   16352 
   16353 
   16354 template<typename Derived, typename Shape, typename Key>
   16355 uint32_t HashTable<Derived, Shape, Key>::EntryForProbe(
   16356     Key key,
   16357     Object* k,
   16358     int probe,
   16359     uint32_t expected) {
   16360   uint32_t hash = this->HashForObject(key, k);
   16361   uint32_t capacity = this->Capacity();
   16362   uint32_t entry = FirstProbe(hash, capacity);
   16363   for (int i = 1; i < probe; i++) {
   16364     if (entry == expected) return expected;
   16365     entry = NextProbe(entry, i, capacity);
   16366   }
   16367   return entry;
   16368 }
   16369 
   16370 
   16371 template<typename Derived, typename Shape, typename Key>
   16372 void HashTable<Derived, Shape, Key>::Swap(uint32_t entry1,
   16373                                           uint32_t entry2,
   16374                                           WriteBarrierMode mode) {
   16375   int index1 = EntryToIndex(entry1);
   16376   int index2 = EntryToIndex(entry2);
   16377   Object* temp[Shape::kEntrySize];
   16378   for (int j = 0; j < Shape::kEntrySize; j++) {
   16379     temp[j] = get(index1 + j);
   16380   }
   16381   for (int j = 0; j < Shape::kEntrySize; j++) {
   16382     set(index1 + j, get(index2 + j), mode);
   16383   }
   16384   for (int j = 0; j < Shape::kEntrySize; j++) {
   16385     set(index2 + j, temp[j], mode);
   16386   }
   16387 }
   16388 
   16389 
   16390 template<typename Derived, typename Shape, typename Key>
   16391 void HashTable<Derived, Shape, Key>::Rehash(Key key) {
   16392   DisallowHeapAllocation no_gc;
   16393   WriteBarrierMode mode = GetWriteBarrierMode(no_gc);
   16394   Isolate* isolate = GetIsolate();
   16395   uint32_t capacity = Capacity();
   16396   bool done = false;
   16397   for (int probe = 1; !done; probe++) {
   16398     // All elements at entries given by one of the first _probe_ probes
   16399     // are placed correctly. Other elements might need to be moved.
   16400     done = true;
   16401     for (uint32_t current = 0; current < capacity; current++) {
   16402       Object* current_key = KeyAt(current);
   16403       if (IsKey(isolate, current_key)) {
   16404         uint32_t target = EntryForProbe(key, current_key, probe, current);
   16405         if (current == target) continue;
   16406         Object* target_key = KeyAt(target);
   16407         if (!IsKey(target_key) ||
   16408             EntryForProbe(key, target_key, probe, target) != target) {
   16409           // Put the current element into the correct position.
   16410           Swap(current, target, mode);
   16411           // The other element will be processed on the next iteration.
   16412           current--;
   16413         } else {
   16414           // The place for the current element is occupied. Leave the element
   16415           // for the next probe.
   16416           done = false;
   16417         }
   16418       }
   16419     }
   16420   }
   16421   // Wipe deleted entries.
   16422   Object* the_hole = isolate->heap()->the_hole_value();
   16423   Object* undefined = isolate->heap()->undefined_value();
   16424   for (uint32_t current = 0; current < capacity; current++) {
   16425     if (KeyAt(current) == the_hole) {
   16426       set(EntryToIndex(current) + Derived::kEntryKeyIndex, undefined);
   16427     }
   16428   }
   16429   SetNumberOfDeletedElements(0);
   16430 }
   16431 
   16432 
   16433 template<typename Derived, typename Shape, typename Key>
   16434 Handle<Derived> HashTable<Derived, Shape, Key>::EnsureCapacity(
   16435     Handle<Derived> table,
   16436     int n,
   16437     Key key,
   16438     PretenureFlag pretenure) {
   16439   Isolate* isolate = table->GetIsolate();
   16440   int capacity = table->Capacity();
   16441   int nof = table->NumberOfElements() + n;
   16442 
   16443   if (table->HasSufficientCapacityToAdd(n)) return table;
   16444 
   16445   const int kMinCapacityForPretenure = 256;
   16446   bool should_pretenure = pretenure == TENURED ||
   16447       ((capacity > kMinCapacityForPretenure) &&
   16448           !isolate->heap()->InNewSpace(*table));
   16449   Handle<Derived> new_table = HashTable::New(
   16450       isolate,
   16451       nof * 2,
   16452       USE_DEFAULT_MINIMUM_CAPACITY,
   16453       should_pretenure ? TENURED : NOT_TENURED);
   16454 
   16455   table->Rehash(new_table, key);
   16456   return new_table;
   16457 }
   16458 
   16459 template <typename Derived, typename Shape, typename Key>
   16460 bool HashTable<Derived, Shape, Key>::HasSufficientCapacityToAdd(
   16461     int number_of_additional_elements) {
   16462   int capacity = Capacity();
   16463   int nof = NumberOfElements() + number_of_additional_elements;
   16464   int nod = NumberOfDeletedElements();
   16465   // Return true if:
   16466   //   50% is still free after adding number_of_additional_elements elements and
   16467   //   at most 50% of the free elements are deleted elements.
   16468   if ((nof < capacity) && ((nod <= (capacity - nof) >> 1))) {
   16469     int needed_free = nof >> 1;
   16470     if (nof + needed_free <= capacity) return true;
   16471   }
   16472   return false;
   16473 }
   16474 
   16475 
   16476 template<typename Derived, typename Shape, typename Key>
   16477 Handle<Derived> HashTable<Derived, Shape, Key>::Shrink(Handle<Derived> table,
   16478                                                        Key key) {
   16479   int capacity = table->Capacity();
   16480   int nof = table->NumberOfElements();
   16481 
   16482   // Shrink to fit the number of elements if only a quarter of the
   16483   // capacity is filled with elements.
   16484   if (nof > (capacity >> 2)) return table;
   16485   // Allocate a new dictionary with room for at least the current
   16486   // number of elements. The allocation method will make sure that
   16487   // there is extra room in the dictionary for additions. Don't go
   16488   // lower than room for 16 elements.
   16489   int at_least_room_for = nof;
   16490   if (at_least_room_for < 16) return table;
   16491 
   16492   Isolate* isolate = table->GetIsolate();
   16493   const int kMinCapacityForPretenure = 256;
   16494   bool pretenure =
   16495       (at_least_room_for > kMinCapacityForPretenure) &&
   16496       !isolate->heap()->InNewSpace(*table);
   16497   Handle<Derived> new_table = HashTable::New(
   16498       isolate,
   16499       at_least_room_for,
   16500       USE_DEFAULT_MINIMUM_CAPACITY,
   16501       pretenure ? TENURED : NOT_TENURED);
   16502 
   16503   table->Rehash(new_table, key);
   16504   return new_table;
   16505 }
   16506 
   16507 
   16508 template<typename Derived, typename Shape, typename Key>
   16509 uint32_t HashTable<Derived, Shape, Key>::FindInsertionEntry(uint32_t hash) {
   16510   uint32_t capacity = Capacity();
   16511   uint32_t entry = FirstProbe(hash, capacity);
   16512   uint32_t count = 1;
   16513   // EnsureCapacity will guarantee the hash table is never full.
   16514   Isolate* isolate = GetIsolate();
   16515   while (true) {
   16516     Object* element = KeyAt(entry);
   16517     if (!IsKey(isolate, element)) break;
   16518     entry = NextProbe(entry, count++, capacity);
   16519   }
   16520   return entry;
   16521 }
   16522 
   16523 
   16524 // Force instantiation of template instances class.
   16525 // Please note this list is compiler dependent.
   16526 
   16527 template class HashTable<StringTable, StringTableShape, HashTableKey*>;
   16528 
   16529 template class HashTable<CompilationCacheTable,
   16530                          CompilationCacheShape,
   16531                          HashTableKey*>;
   16532 
   16533 template class HashTable<ObjectHashTable,
   16534                          ObjectHashTableShape,
   16535                          Handle<Object> >;
   16536 
   16537 template class HashTable<WeakHashTable, WeakHashTableShape<2>, Handle<Object> >;
   16538 
   16539 template class Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >;
   16540 
   16541 template class Dictionary<GlobalDictionary, GlobalDictionaryShape,
   16542                           Handle<Name> >;
   16543 
   16544 template class Dictionary<SeededNumberDictionary,
   16545                           SeededNumberDictionaryShape,
   16546                           uint32_t>;
   16547 
   16548 template class Dictionary<UnseededNumberDictionary,
   16549                           UnseededNumberDictionaryShape,
   16550                           uint32_t>;
   16551 
   16552 template Handle<SeededNumberDictionary>
   16553 Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::New(
   16554     Isolate*, int at_least_space_for, PretenureFlag pretenure,
   16555     MinimumCapacity capacity_option);
   16556 
   16557 template Handle<SeededNumberDictionary>
   16558 Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape,
   16559            uint32_t>::NewEmpty(Isolate*, PretenureFlag pretenure);
   16560 
   16561 template Handle<UnseededNumberDictionary>
   16562 Dictionary<UnseededNumberDictionary, UnseededNumberDictionaryShape,
   16563            uint32_t>::New(Isolate*, int at_least_space_for,
   16564                           PretenureFlag pretenure,
   16565                           MinimumCapacity capacity_option);
   16566 
   16567 template Handle<NameDictionary>
   16568 Dictionary<NameDictionary, NameDictionaryShape, Handle<Name>>::New(
   16569     Isolate*, int n, PretenureFlag pretenure, MinimumCapacity capacity_option);
   16570 
   16571 template Handle<NameDictionary>
   16572 Dictionary<NameDictionary, NameDictionaryShape, Handle<Name>>::NewEmpty(
   16573     Isolate*, PretenureFlag pretenure);
   16574 
   16575 template Handle<GlobalDictionary>
   16576 Dictionary<GlobalDictionary, GlobalDictionaryShape, Handle<Name>>::New(
   16577     Isolate*, int n, PretenureFlag pretenure, MinimumCapacity capacity_option);
   16578 
   16579 template Handle<SeededNumberDictionary>
   16580 Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
   16581     AtPut(Handle<SeededNumberDictionary>, uint32_t, Handle<Object>);
   16582 
   16583 template Handle<UnseededNumberDictionary>
   16584 Dictionary<UnseededNumberDictionary, UnseededNumberDictionaryShape, uint32_t>::
   16585     AtPut(Handle<UnseededNumberDictionary>, uint32_t, Handle<Object>);
   16586 
   16587 template Object*
   16588 Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
   16589     SlowReverseLookup(Object* value);
   16590 
   16591 template Object*
   16592 Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::
   16593     SlowReverseLookup(Object* value);
   16594 
   16595 template Handle<Object>
   16596 Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::DeleteProperty(
   16597     Handle<NameDictionary>, int);
   16598 
   16599 template Handle<Object>
   16600 Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape,
   16601            uint32_t>::DeleteProperty(Handle<SeededNumberDictionary>, int);
   16602 
   16603 template Handle<Object>
   16604 Dictionary<UnseededNumberDictionary, UnseededNumberDictionaryShape,
   16605            uint32_t>::DeleteProperty(Handle<UnseededNumberDictionary>, int);
   16606 
   16607 template Handle<NameDictionary>
   16608 HashTable<NameDictionary, NameDictionaryShape, Handle<Name> >::
   16609     New(Isolate*, int, MinimumCapacity, PretenureFlag);
   16610 
   16611 template Handle<ObjectHashSet> HashTable<ObjectHashSet, ObjectHashSetShape,
   16612                                          Handle<Object>>::New(Isolate*, int n,
   16613                                                               MinimumCapacity,
   16614                                                               PretenureFlag);
   16615 
   16616 template Handle<NameDictionary>
   16617 HashTable<NameDictionary, NameDictionaryShape, Handle<Name> >::
   16618     Shrink(Handle<NameDictionary>, Handle<Name>);
   16619 
   16620 template Handle<SeededNumberDictionary>
   16621 HashTable<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
   16622     Shrink(Handle<SeededNumberDictionary>, uint32_t);
   16623 
   16624 template Handle<UnseededNumberDictionary>
   16625     HashTable<UnseededNumberDictionary, UnseededNumberDictionaryShape,
   16626               uint32_t>::Shrink(Handle<UnseededNumberDictionary>, uint32_t);
   16627 
   16628 template Handle<NameDictionary>
   16629 Dictionary<NameDictionary, NameDictionaryShape, Handle<Name>>::Add(
   16630     Handle<NameDictionary>, Handle<Name>, Handle<Object>, PropertyDetails,
   16631     int*);
   16632 
   16633 template Handle<GlobalDictionary>
   16634 Dictionary<GlobalDictionary, GlobalDictionaryShape, Handle<Name>>::Add(
   16635     Handle<GlobalDictionary>, Handle<Name>, Handle<Object>, PropertyDetails,
   16636     int*);
   16637 
   16638 template Handle<FixedArray> Dictionary<
   16639     NameDictionary, NameDictionaryShape,
   16640     Handle<Name> >::GenerateNewEnumerationIndices(Handle<NameDictionary>);
   16641 
   16642 template Handle<SeededNumberDictionary>
   16643 Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::Add(
   16644     Handle<SeededNumberDictionary>, uint32_t, Handle<Object>, PropertyDetails,
   16645     int*);
   16646 
   16647 template Handle<UnseededNumberDictionary>
   16648 Dictionary<UnseededNumberDictionary, UnseededNumberDictionaryShape,
   16649            uint32_t>::Add(Handle<UnseededNumberDictionary>, uint32_t,
   16650                           Handle<Object>, PropertyDetails, int*);
   16651 
   16652 template Handle<SeededNumberDictionary>
   16653 Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
   16654     EnsureCapacity(Handle<SeededNumberDictionary>, int, uint32_t);
   16655 
   16656 template Handle<UnseededNumberDictionary>
   16657 Dictionary<UnseededNumberDictionary, UnseededNumberDictionaryShape, uint32_t>::
   16658     EnsureCapacity(Handle<UnseededNumberDictionary>, int, uint32_t);
   16659 
   16660 template void Dictionary<NameDictionary, NameDictionaryShape,
   16661                          Handle<Name> >::SetRequiresCopyOnCapacityChange();
   16662 
   16663 template Handle<NameDictionary>
   16664 Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::
   16665     EnsureCapacity(Handle<NameDictionary>, int, Handle<Name>);
   16666 
   16667 template int HashTable<SeededNumberDictionary, SeededNumberDictionaryShape,
   16668                        uint32_t>::FindEntry(uint32_t);
   16669 
   16670 template int NameDictionaryBase<NameDictionary, NameDictionaryShape>::FindEntry(
   16671     Handle<Name>);
   16672 
   16673 template int Dictionary<GlobalDictionary, GlobalDictionaryShape, Handle<Name>>::
   16674     NumberOfElementsFilterAttributes(PropertyFilter filter);
   16675 
   16676 template int Dictionary<NameDictionary, NameDictionaryShape, Handle<Name>>::
   16677     NumberOfElementsFilterAttributes(PropertyFilter filter);
   16678 
   16679 template void
   16680 Dictionary<GlobalDictionary, GlobalDictionaryShape, Handle<Name>>::
   16681     CopyEnumKeysTo(Handle<Dictionary<GlobalDictionary, GlobalDictionaryShape,
   16682                                      Handle<Name>>>
   16683                        dictionary,
   16684                    Handle<FixedArray> storage, KeyCollectionMode mode,
   16685                    KeyAccumulator* accumulator);
   16686 
   16687 template void
   16688 Dictionary<NameDictionary, NameDictionaryShape, Handle<Name>>::CopyEnumKeysTo(
   16689     Handle<Dictionary<NameDictionary, NameDictionaryShape, Handle<Name>>>
   16690         dictionary,
   16691     Handle<FixedArray> storage, KeyCollectionMode mode,
   16692     KeyAccumulator* accumulator);
   16693 
   16694 template Handle<FixedArray>
   16695 Dictionary<GlobalDictionary, GlobalDictionaryShape, Handle<Name>>::
   16696     IterationIndices(
   16697         Handle<
   16698             Dictionary<GlobalDictionary, GlobalDictionaryShape, Handle<Name>>>
   16699             dictionary);
   16700 template void
   16701 Dictionary<GlobalDictionary, GlobalDictionaryShape, Handle<Name>>::
   16702     CollectKeysTo(Handle<Dictionary<GlobalDictionary, GlobalDictionaryShape,
   16703                                     Handle<Name>>>
   16704                       dictionary,
   16705                   KeyAccumulator* keys);
   16706 
   16707 template Handle<FixedArray>
   16708 Dictionary<NameDictionary, NameDictionaryShape, Handle<Name>>::IterationIndices(
   16709     Handle<Dictionary<NameDictionary, NameDictionaryShape, Handle<Name>>>
   16710         dictionary);
   16711 template void
   16712 Dictionary<NameDictionary, NameDictionaryShape, Handle<Name>>::CollectKeysTo(
   16713     Handle<Dictionary<NameDictionary, NameDictionaryShape, Handle<Name>>>
   16714         dictionary,
   16715     KeyAccumulator* keys);
   16716 
   16717 Handle<Object> JSObject::PrepareSlowElementsForSort(
   16718     Handle<JSObject> object, uint32_t limit) {
   16719   DCHECK(object->HasDictionaryElements());
   16720   Isolate* isolate = object->GetIsolate();
   16721   // Must stay in dictionary mode, either because of requires_slow_elements,
   16722   // or because we are not going to sort (and therefore compact) all of the
   16723   // elements.
   16724   Handle<SeededNumberDictionary> dict(object->element_dictionary(), isolate);
   16725   Handle<SeededNumberDictionary> new_dict =
   16726       SeededNumberDictionary::New(isolate, dict->NumberOfElements());
   16727 
   16728   uint32_t pos = 0;
   16729   uint32_t undefs = 0;
   16730   int capacity = dict->Capacity();
   16731   Handle<Smi> bailout(Smi::FromInt(-1), isolate);
   16732   // Entry to the new dictionary does not cause it to grow, as we have
   16733   // allocated one that is large enough for all entries.
   16734   DisallowHeapAllocation no_gc;
   16735   for (int i = 0; i < capacity; i++) {
   16736     Object* k = dict->KeyAt(i);
   16737     if (!dict->IsKey(isolate, k)) continue;
   16738 
   16739     DCHECK(k->IsNumber());
   16740     DCHECK(!k->IsSmi() || Smi::cast(k)->value() >= 0);
   16741     DCHECK(!k->IsHeapNumber() || HeapNumber::cast(k)->value() >= 0);
   16742     DCHECK(!k->IsHeapNumber() || HeapNumber::cast(k)->value() <= kMaxUInt32);
   16743 
   16744     HandleScope scope(isolate);
   16745     Handle<Object> value(dict->ValueAt(i), isolate);
   16746     PropertyDetails details = dict->DetailsAt(i);
   16747     if (details.kind() == kAccessor || details.IsReadOnly()) {
   16748       // Bail out and do the sorting of undefineds and array holes in JS.
   16749       // Also bail out if the element is not supposed to be moved.
   16750       return bailout;
   16751     }
   16752 
   16753     uint32_t key = NumberToUint32(k);
   16754     if (key < limit) {
   16755       if (value->IsUndefined(isolate)) {
   16756         undefs++;
   16757       } else if (pos > static_cast<uint32_t>(Smi::kMaxValue)) {
   16758         // Adding an entry with the key beyond smi-range requires
   16759         // allocation. Bailout.
   16760         return bailout;
   16761       } else {
   16762         Handle<Object> result = SeededNumberDictionary::AddNumberEntry(
   16763             new_dict, pos, value, details, object);
   16764         DCHECK(result.is_identical_to(new_dict));
   16765         USE(result);
   16766         pos++;
   16767       }
   16768     } else if (key > static_cast<uint32_t>(Smi::kMaxValue)) {
   16769       // Adding an entry with the key beyond smi-range requires
   16770       // allocation. Bailout.
   16771       return bailout;
   16772     } else {
   16773       Handle<Object> result = SeededNumberDictionary::AddNumberEntry(
   16774           new_dict, key, value, details, object);
   16775       DCHECK(result.is_identical_to(new_dict));
   16776       USE(result);
   16777     }
   16778   }
   16779 
   16780   uint32_t result = pos;
   16781   PropertyDetails no_details = PropertyDetails::Empty();
   16782   while (undefs > 0) {
   16783     if (pos > static_cast<uint32_t>(Smi::kMaxValue)) {
   16784       // Adding an entry with the key beyond smi-range requires
   16785       // allocation. Bailout.
   16786       return bailout;
   16787     }
   16788     HandleScope scope(isolate);
   16789     Handle<Object> result = SeededNumberDictionary::AddNumberEntry(
   16790         new_dict, pos, isolate->factory()->undefined_value(), no_details,
   16791         object);
   16792     DCHECK(result.is_identical_to(new_dict));
   16793     USE(result);
   16794     pos++;
   16795     undefs--;
   16796   }
   16797 
   16798   object->set_elements(*new_dict);
   16799 
   16800   AllowHeapAllocation allocate_return_value;
   16801   return isolate->factory()->NewNumberFromUint(result);
   16802 }
   16803 
   16804 
   16805 // Collects all defined (non-hole) and non-undefined (array) elements at
   16806 // the start of the elements array.
   16807 // If the object is in dictionary mode, it is converted to fast elements
   16808 // mode.
   16809 Handle<Object> JSObject::PrepareElementsForSort(Handle<JSObject> object,
   16810                                                 uint32_t limit) {
   16811   Isolate* isolate = object->GetIsolate();
   16812   if (object->HasSloppyArgumentsElements() || !object->map()->is_extensible()) {
   16813     return handle(Smi::FromInt(-1), isolate);
   16814   }
   16815 
   16816   if (object->HasStringWrapperElements()) {
   16817     int len = String::cast(Handle<JSValue>::cast(object)->value())->length();
   16818     return handle(Smi::FromInt(len), isolate);
   16819   }
   16820 
   16821   if (object->HasDictionaryElements()) {
   16822     // Convert to fast elements containing only the existing properties.
   16823     // Ordering is irrelevant, since we are going to sort anyway.
   16824     Handle<SeededNumberDictionary> dict(object->element_dictionary());
   16825     if (object->IsJSArray() || dict->requires_slow_elements() ||
   16826         dict->max_number_key() >= limit) {
   16827       return JSObject::PrepareSlowElementsForSort(object, limit);
   16828     }
   16829     // Convert to fast elements.
   16830 
   16831     Handle<Map> new_map =
   16832         JSObject::GetElementsTransitionMap(object, FAST_HOLEY_ELEMENTS);
   16833 
   16834     PretenureFlag tenure = isolate->heap()->InNewSpace(*object) ?
   16835         NOT_TENURED: TENURED;
   16836     Handle<FixedArray> fast_elements =
   16837         isolate->factory()->NewFixedArray(dict->NumberOfElements(), tenure);
   16838     dict->CopyValuesTo(*fast_elements);
   16839     JSObject::ValidateElements(object);
   16840 
   16841     JSObject::SetMapAndElements(object, new_map, fast_elements);
   16842   } else if (object->HasFixedTypedArrayElements()) {
   16843     // Typed arrays cannot have holes or undefined elements.
   16844     return handle(Smi::FromInt(
   16845         FixedArrayBase::cast(object->elements())->length()), isolate);
   16846   } else if (!object->HasFastDoubleElements()) {
   16847     EnsureWritableFastElements(object);
   16848   }
   16849   DCHECK(object->HasFastSmiOrObjectElements() ||
   16850          object->HasFastDoubleElements());
   16851 
   16852   // Collect holes at the end, undefined before that and the rest at the
   16853   // start, and return the number of non-hole, non-undefined values.
   16854 
   16855   Handle<FixedArrayBase> elements_base(object->elements());
   16856   uint32_t elements_length = static_cast<uint32_t>(elements_base->length());
   16857   if (limit > elements_length) {
   16858     limit = elements_length;
   16859   }
   16860   if (limit == 0) {
   16861     return handle(Smi::kZero, isolate);
   16862   }
   16863 
   16864   uint32_t result = 0;
   16865   if (elements_base->map() == isolate->heap()->fixed_double_array_map()) {
   16866     FixedDoubleArray* elements = FixedDoubleArray::cast(*elements_base);
   16867     // Split elements into defined and the_hole, in that order.
   16868     unsigned int holes = limit;
   16869     // Assume most arrays contain no holes and undefined values, so minimize the
   16870     // number of stores of non-undefined, non-the-hole values.
   16871     for (unsigned int i = 0; i < holes; i++) {
   16872       if (elements->is_the_hole(i)) {
   16873         holes--;
   16874       } else {
   16875         continue;
   16876       }
   16877       // Position i needs to be filled.
   16878       while (holes > i) {
   16879         if (elements->is_the_hole(holes)) {
   16880           holes--;
   16881         } else {
   16882           elements->set(i, elements->get_scalar(holes));
   16883           break;
   16884         }
   16885       }
   16886     }
   16887     result = holes;
   16888     while (holes < limit) {
   16889       elements->set_the_hole(holes);
   16890       holes++;
   16891     }
   16892   } else {
   16893     FixedArray* elements = FixedArray::cast(*elements_base);
   16894     DisallowHeapAllocation no_gc;
   16895 
   16896     // Split elements into defined, undefined and the_hole, in that order.  Only
   16897     // count locations for undefined and the hole, and fill them afterwards.
   16898     WriteBarrierMode write_barrier = elements->GetWriteBarrierMode(no_gc);
   16899     unsigned int undefs = limit;
   16900     unsigned int holes = limit;
   16901     // Assume most arrays contain no holes and undefined values, so minimize the
   16902     // number of stores of non-undefined, non-the-hole values.
   16903     for (unsigned int i = 0; i < undefs; i++) {
   16904       Object* current = elements->get(i);
   16905       if (current->IsTheHole(isolate)) {
   16906         holes--;
   16907         undefs--;
   16908       } else if (current->IsUndefined(isolate)) {
   16909         undefs--;
   16910       } else {
   16911         continue;
   16912       }
   16913       // Position i needs to be filled.
   16914       while (undefs > i) {
   16915         current = elements->get(undefs);
   16916         if (current->IsTheHole(isolate)) {
   16917           holes--;
   16918           undefs--;
   16919         } else if (current->IsUndefined(isolate)) {
   16920           undefs--;
   16921         } else {
   16922           elements->set(i, current, write_barrier);
   16923           break;
   16924         }
   16925       }
   16926     }
   16927     result = undefs;
   16928     while (undefs < holes) {
   16929       elements->set_undefined(isolate, undefs);
   16930       undefs++;
   16931     }
   16932     while (holes < limit) {
   16933       elements->set_the_hole(isolate, holes);
   16934       holes++;
   16935     }
   16936   }
   16937 
   16938   return isolate->factory()->NewNumberFromUint(result);
   16939 }
   16940 
   16941 namespace {
   16942 
   16943 bool CanonicalNumericIndexString(Isolate* isolate, Handle<Object> s,
   16944                                  Handle<Object>* index) {
   16945   DCHECK(s->IsString() || s->IsSmi());
   16946 
   16947   Handle<Object> result;
   16948   if (s->IsSmi()) {
   16949     result = s;
   16950   } else {
   16951     result = String::ToNumber(Handle<String>::cast(s));
   16952     if (!result->IsMinusZero()) {
   16953       Handle<String> str = Object::ToString(isolate, result).ToHandleChecked();
   16954       // Avoid treating strings like "2E1" and "20" as the same key.
   16955       if (!str->SameValue(*s)) return false;
   16956     }
   16957   }
   16958   *index = result;
   16959   return true;
   16960 }
   16961 
   16962 }  // anonymous namespace
   16963 
   16964 // ES#sec-integer-indexed-exotic-objects-defineownproperty-p-desc
   16965 // static
   16966 Maybe<bool> JSTypedArray::DefineOwnProperty(Isolate* isolate,
   16967                                             Handle<JSTypedArray> o,
   16968                                             Handle<Object> key,
   16969                                             PropertyDescriptor* desc,
   16970                                             ShouldThrow should_throw) {
   16971   // 1. Assert: IsPropertyKey(P) is true.
   16972   DCHECK(key->IsName() || key->IsNumber());
   16973   // 2. Assert: O is an Object that has a [[ViewedArrayBuffer]] internal slot.
   16974   // 3. If Type(P) is String, then
   16975   if (key->IsString() || key->IsSmi()) {
   16976     // 3a. Let numericIndex be ! CanonicalNumericIndexString(P)
   16977     // 3b. If numericIndex is not undefined, then
   16978     Handle<Object> numeric_index;
   16979     if (CanonicalNumericIndexString(isolate, key, &numeric_index)) {
   16980       // 3b i. If IsInteger(numericIndex) is false, return false.
   16981       // 3b ii. If numericIndex = -0, return false.
   16982       // 3b iii. If numericIndex < 0, return false.
   16983       // FIXME: the standard allows up to 2^53 elements.
   16984       uint32_t index;
   16985       if (numeric_index->IsMinusZero() || !numeric_index->ToUint32(&index)) {
   16986         RETURN_FAILURE(isolate, should_throw,
   16987                        NewTypeError(MessageTemplate::kInvalidTypedArrayIndex));
   16988       }
   16989       // 3b iv. Let length be O.[[ArrayLength]].
   16990       uint32_t length = o->length()->Number();
   16991       // 3b v. If numericIndex  length, return false.
   16992       if (index >= length) {
   16993         RETURN_FAILURE(isolate, should_throw,
   16994                        NewTypeError(MessageTemplate::kInvalidTypedArrayIndex));
   16995       }
   16996       // 3b vi. If IsAccessorDescriptor(Desc) is true, return false.
   16997       if (PropertyDescriptor::IsAccessorDescriptor(desc)) {
   16998         RETURN_FAILURE(isolate, should_throw,
   16999                        NewTypeError(MessageTemplate::kRedefineDisallowed, key));
   17000       }
   17001       // 3b vii. If Desc has a [[Configurable]] field and if
   17002       //         Desc.[[Configurable]] is true, return false.
   17003       // 3b viii. If Desc has an [[Enumerable]] field and if Desc.[[Enumerable]]
   17004       //          is false, return false.
   17005       // 3b ix. If Desc has a [[Writable]] field and if Desc.[[Writable]] is
   17006       //        false, return false.
   17007       if ((desc->has_configurable() && desc->configurable()) ||
   17008           (desc->has_enumerable() && !desc->enumerable()) ||
   17009           (desc->has_writable() && !desc->writable())) {
   17010         RETURN_FAILURE(isolate, should_throw,
   17011                        NewTypeError(MessageTemplate::kRedefineDisallowed, key));
   17012       }
   17013       // 3b x. If Desc has a [[Value]] field, then
   17014       //   3b x 1. Let value be Desc.[[Value]].
   17015       //   3b x 2. Return ? IntegerIndexedElementSet(O, numericIndex, value).
   17016       if (desc->has_value()) {
   17017         if (!desc->has_configurable()) desc->set_configurable(false);
   17018         if (!desc->has_enumerable()) desc->set_enumerable(true);
   17019         if (!desc->has_writable()) desc->set_writable(true);
   17020         Handle<Object> value = desc->value();
   17021         RETURN_ON_EXCEPTION_VALUE(isolate,
   17022                                   SetOwnElementIgnoreAttributes(
   17023                                       o, index, value, desc->ToAttributes()),
   17024                                   Nothing<bool>());
   17025       }
   17026       // 3b xi. Return true.
   17027       return Just(true);
   17028     }
   17029   }
   17030   // 4. Return ! OrdinaryDefineOwnProperty(O, P, Desc).
   17031   return OrdinaryDefineOwnProperty(isolate, o, key, desc, should_throw);
   17032 }
   17033 
   17034 ExternalArrayType JSTypedArray::type() {
   17035   switch (elements()->map()->instance_type()) {
   17036 #define INSTANCE_TYPE_TO_ARRAY_TYPE(Type, type, TYPE, ctype, size)            \
   17037     case FIXED_##TYPE##_ARRAY_TYPE:                                           \
   17038       return kExternal##Type##Array;
   17039 
   17040     TYPED_ARRAYS(INSTANCE_TYPE_TO_ARRAY_TYPE)
   17041 #undef INSTANCE_TYPE_TO_ARRAY_TYPE
   17042 
   17043     default:
   17044       UNREACHABLE();
   17045       return static_cast<ExternalArrayType>(-1);
   17046   }
   17047 }
   17048 
   17049 
   17050 size_t JSTypedArray::element_size() {
   17051   switch (elements()->map()->instance_type()) {
   17052 #define INSTANCE_TYPE_TO_ELEMENT_SIZE(Type, type, TYPE, ctype, size) \
   17053   case FIXED_##TYPE##_ARRAY_TYPE:                                    \
   17054     return size;
   17055 
   17056     TYPED_ARRAYS(INSTANCE_TYPE_TO_ELEMENT_SIZE)
   17057 #undef INSTANCE_TYPE_TO_ELEMENT_SIZE
   17058 
   17059     default:
   17060       UNREACHABLE();
   17061       return 0;
   17062   }
   17063 }
   17064 
   17065 
   17066 void JSGlobalObject::InvalidatePropertyCell(Handle<JSGlobalObject> global,
   17067                                             Handle<Name> name) {
   17068   DCHECK(!global->HasFastProperties());
   17069   auto dictionary = handle(global->global_dictionary());
   17070   int entry = dictionary->FindEntry(name);
   17071   if (entry == GlobalDictionary::kNotFound) return;
   17072   PropertyCell::InvalidateEntry(dictionary, entry);
   17073 }
   17074 
   17075 Handle<PropertyCell> JSGlobalObject::EnsureEmptyPropertyCell(
   17076     Handle<JSGlobalObject> global, Handle<Name> name,
   17077     PropertyCellType cell_type, int* entry_out) {
   17078   Isolate* isolate = global->GetIsolate();
   17079   DCHECK(!global->HasFastProperties());
   17080   Handle<GlobalDictionary> dictionary(global->global_dictionary(), isolate);
   17081   int entry = dictionary->FindEntry(name);
   17082   Handle<PropertyCell> cell;
   17083   if (entry != GlobalDictionary::kNotFound) {
   17084     if (entry_out) *entry_out = entry;
   17085     // This call should be idempotent.
   17086     DCHECK(dictionary->ValueAt(entry)->IsPropertyCell());
   17087     cell = handle(PropertyCell::cast(dictionary->ValueAt(entry)));
   17088     PropertyCellType original_cell_type = cell->property_details().cell_type();
   17089     DCHECK(original_cell_type == PropertyCellType::kInvalidated ||
   17090            original_cell_type == PropertyCellType::kUninitialized);
   17091     DCHECK(cell->value()->IsTheHole(isolate));
   17092     if (original_cell_type == PropertyCellType::kInvalidated) {
   17093       cell = PropertyCell::InvalidateEntry(dictionary, entry);
   17094     }
   17095     PropertyDetails details(kData, NONE, 0, cell_type);
   17096     cell->set_property_details(details);
   17097     return cell;
   17098   }
   17099   cell = isolate->factory()->NewPropertyCell();
   17100   PropertyDetails details(kData, NONE, 0, cell_type);
   17101   dictionary =
   17102       GlobalDictionary::Add(dictionary, name, cell, details, entry_out);
   17103   // {*entry_out} is initialized inside GlobalDictionary::Add().
   17104   global->set_properties(*dictionary);
   17105   return cell;
   17106 }
   17107 
   17108 
   17109 // This class is used for looking up two character strings in the string table.
   17110 // If we don't have a hit we don't want to waste much time so we unroll the
   17111 // string hash calculation loop here for speed.  Doesn't work if the two
   17112 // characters form a decimal integer, since such strings have a different hash
   17113 // algorithm.
   17114 class TwoCharHashTableKey : public HashTableKey {
   17115  public:
   17116   TwoCharHashTableKey(uint16_t c1, uint16_t c2, uint32_t seed)
   17117     : c1_(c1), c2_(c2) {
   17118     // Char 1.
   17119     uint32_t hash = seed;
   17120     hash += c1;
   17121     hash += hash << 10;
   17122     hash ^= hash >> 6;
   17123     // Char 2.
   17124     hash += c2;
   17125     hash += hash << 10;
   17126     hash ^= hash >> 6;
   17127     // GetHash.
   17128     hash += hash << 3;
   17129     hash ^= hash >> 11;
   17130     hash += hash << 15;
   17131     if ((hash & String::kHashBitMask) == 0) hash = StringHasher::kZeroHash;
   17132     hash_ = hash;
   17133 #ifdef DEBUG
   17134     // If this assert fails then we failed to reproduce the two-character
   17135     // version of the string hashing algorithm above.  One reason could be
   17136     // that we were passed two digits as characters, since the hash
   17137     // algorithm is different in that case.
   17138     uint16_t chars[2] = {c1, c2};
   17139     uint32_t check_hash = StringHasher::HashSequentialString(chars, 2, seed);
   17140     hash = (hash << String::kHashShift) | String::kIsNotArrayIndexMask;
   17141     DCHECK_EQ(static_cast<int32_t>(hash), static_cast<int32_t>(check_hash));
   17142 #endif
   17143   }
   17144 
   17145   bool IsMatch(Object* o) override {
   17146     if (!o->IsString()) return false;
   17147     String* other = String::cast(o);
   17148     if (other->length() != 2) return false;
   17149     if (other->Get(0) != c1_) return false;
   17150     return other->Get(1) == c2_;
   17151   }
   17152 
   17153   uint32_t Hash() override { return hash_; }
   17154   uint32_t HashForObject(Object* key) override {
   17155     if (!key->IsString()) return 0;
   17156     return String::cast(key)->Hash();
   17157   }
   17158 
   17159   Handle<Object> AsHandle(Isolate* isolate) override {
   17160     // The TwoCharHashTableKey is only used for looking in the string
   17161     // table, not for adding to it.
   17162     UNREACHABLE();
   17163     return MaybeHandle<Object>().ToHandleChecked();
   17164   }
   17165 
   17166  private:
   17167   uint16_t c1_;
   17168   uint16_t c2_;
   17169   uint32_t hash_;
   17170 };
   17171 
   17172 
   17173 MaybeHandle<String> StringTable::InternalizeStringIfExists(
   17174     Isolate* isolate,
   17175     Handle<String> string) {
   17176   if (string->IsInternalizedString()) {
   17177     return string;
   17178   }
   17179   if (string->IsThinString()) {
   17180     return handle(Handle<ThinString>::cast(string)->actual(), isolate);
   17181   }
   17182   return LookupStringIfExists(isolate, string);
   17183 }
   17184 
   17185 
   17186 MaybeHandle<String> StringTable::LookupStringIfExists(
   17187     Isolate* isolate,
   17188     Handle<String> string) {
   17189   Handle<StringTable> string_table = isolate->factory()->string_table();
   17190   InternalizedStringKey key(string);
   17191   int entry = string_table->FindEntry(&key);
   17192   if (entry == kNotFound) {
   17193     return MaybeHandle<String>();
   17194   } else {
   17195     Handle<String> result(String::cast(string_table->KeyAt(entry)), isolate);
   17196     DCHECK(StringShape(*result).IsInternalized());
   17197     return result;
   17198   }
   17199 }
   17200 
   17201 
   17202 MaybeHandle<String> StringTable::LookupTwoCharsStringIfExists(
   17203     Isolate* isolate,
   17204     uint16_t c1,
   17205     uint16_t c2) {
   17206   Handle<StringTable> string_table = isolate->factory()->string_table();
   17207   TwoCharHashTableKey key(c1, c2, isolate->heap()->HashSeed());
   17208   int entry = string_table->FindEntry(&key);
   17209   if (entry == kNotFound) {
   17210     return MaybeHandle<String>();
   17211   } else {
   17212     Handle<String> result(String::cast(string_table->KeyAt(entry)), isolate);
   17213     DCHECK(StringShape(*result).IsInternalized());
   17214     return result;
   17215   }
   17216 }
   17217 
   17218 
   17219 void StringTable::EnsureCapacityForDeserialization(Isolate* isolate,
   17220                                                    int expected) {
   17221   Handle<StringTable> table = isolate->factory()->string_table();
   17222   // We need a key instance for the virtual hash function.
   17223   InternalizedStringKey dummy_key(isolate->factory()->empty_string());
   17224   table = StringTable::EnsureCapacity(table, expected, &dummy_key);
   17225   isolate->heap()->SetRootStringTable(*table);
   17226 }
   17227 
   17228 namespace {
   17229 
   17230 template <class StringClass>
   17231 void MigrateExternalStringResource(Isolate* isolate, Handle<String> from,
   17232                                    Handle<String> to) {
   17233   Handle<StringClass> cast_from = Handle<StringClass>::cast(from);
   17234   Handle<StringClass> cast_to = Handle<StringClass>::cast(to);
   17235   const typename StringClass::Resource* to_resource = cast_to->resource();
   17236   if (to_resource == nullptr) {
   17237     // |to| is a just-created internalized copy of |from|. Migrate the resource.
   17238     cast_to->set_resource(cast_from->resource());
   17239     // Zap |from|'s resource pointer to reflect the fact that |from| has
   17240     // relinquished ownership of its resource.
   17241     cast_from->set_resource(nullptr);
   17242   } else if (to_resource != cast_from->resource()) {
   17243     // |to| already existed and has its own resource. Finalize |from|.
   17244     isolate->heap()->FinalizeExternalString(*from);
   17245   }
   17246 }
   17247 
   17248 }  // namespace
   17249 
   17250 Handle<String> StringTable::LookupString(Isolate* isolate,
   17251                                          Handle<String> string) {
   17252   if (string->IsThinString()) {
   17253     DCHECK(Handle<ThinString>::cast(string)->actual()->IsInternalizedString());
   17254     return handle(Handle<ThinString>::cast(string)->actual(), isolate);
   17255   }
   17256   if (string->IsConsString() && string->IsFlat()) {
   17257     string = handle(Handle<ConsString>::cast(string)->first(), isolate);
   17258     if (string->IsInternalizedString()) return string;
   17259   }
   17260 
   17261   InternalizedStringKey key(string);
   17262   Handle<String> result = LookupKey(isolate, &key);
   17263 
   17264   if (FLAG_thin_strings) {
   17265     if (string->IsExternalString()) {
   17266       if (result->IsExternalOneByteString()) {
   17267         MigrateExternalStringResource<ExternalOneByteString>(isolate, string,
   17268                                                              result);
   17269       } else if (result->IsExternalTwoByteString()) {
   17270         MigrateExternalStringResource<ExternalTwoByteString>(isolate, string,
   17271                                                              result);
   17272       } else {
   17273         // If the external string is duped into an existing non-external
   17274         // internalized string, free its resource (it's about to be rewritten
   17275         // into a ThinString below).
   17276         isolate->heap()->FinalizeExternalString(*string);
   17277       }
   17278     }
   17279 
   17280     // The LookupKey() call above tries to internalize the string in-place.
   17281     // In cases where that wasn't possible (e.g. new-space strings), turn them
   17282     // into ThinStrings referring to their internalized versions now.
   17283     if (!string->IsInternalizedString()) {
   17284       DisallowHeapAllocation no_gc;
   17285       bool one_byte = result->IsOneByteRepresentation();
   17286       Handle<Map> map = one_byte
   17287                             ? isolate->factory()->thin_one_byte_string_map()
   17288                             : isolate->factory()->thin_string_map();
   17289       int old_size = string->Size();
   17290       DCHECK(old_size >= ThinString::kSize);
   17291       string->synchronized_set_map(*map);
   17292       Handle<ThinString> thin = Handle<ThinString>::cast(string);
   17293       thin->set_actual(*result);
   17294       Address thin_end = thin->address() + ThinString::kSize;
   17295       int size_delta = old_size - ThinString::kSize;
   17296       if (size_delta != 0) {
   17297         Heap* heap = isolate->heap();
   17298         heap->CreateFillerObjectAt(thin_end, size_delta,
   17299                                    ClearRecordedSlots::kNo);
   17300         heap->AdjustLiveBytes(*thin, -size_delta);
   17301       }
   17302     }
   17303   } else {  // !FLAG_thin_strings
   17304     if (string->IsConsString()) {
   17305       Handle<ConsString> cons = Handle<ConsString>::cast(string);
   17306       cons->set_first(*result);
   17307       cons->set_second(isolate->heap()->empty_string());
   17308     } else if (string->IsSlicedString()) {
   17309       STATIC_ASSERT(ConsString::kSize == SlicedString::kSize);
   17310       DisallowHeapAllocation no_gc;
   17311       bool one_byte = result->IsOneByteRepresentation();
   17312       Handle<Map> map = one_byte
   17313                             ? isolate->factory()->cons_one_byte_string_map()
   17314                             : isolate->factory()->cons_string_map();
   17315       string->set_map(*map);
   17316       Handle<ConsString> cons = Handle<ConsString>::cast(string);
   17317       cons->set_first(*result);
   17318       cons->set_second(isolate->heap()->empty_string());
   17319     }
   17320   }
   17321   return result;
   17322 }
   17323 
   17324 
   17325 Handle<String> StringTable::LookupKey(Isolate* isolate, HashTableKey* key) {
   17326   Handle<StringTable> table = isolate->factory()->string_table();
   17327   int entry = table->FindEntry(key);
   17328 
   17329   // String already in table.
   17330   if (entry != kNotFound) {
   17331     return handle(String::cast(table->KeyAt(entry)), isolate);
   17332   }
   17333 
   17334   // Adding new string. Grow table if needed.
   17335   table = StringTable::EnsureCapacity(table, 1, key);
   17336 
   17337   // Create string object.
   17338   Handle<Object> string = key->AsHandle(isolate);
   17339   // There must be no attempts to internalize strings that could throw
   17340   // InvalidStringLength error.
   17341   CHECK(!string.is_null());
   17342 
   17343   // Add the new string and return it along with the string table.
   17344   entry = table->FindInsertionEntry(key->Hash());
   17345   table->set(EntryToIndex(entry), *string);
   17346   table->ElementAdded();
   17347 
   17348   isolate->heap()->SetRootStringTable(*table);
   17349   return Handle<String>::cast(string);
   17350 }
   17351 
   17352 
   17353 String* StringTable::LookupKeyIfExists(Isolate* isolate, HashTableKey* key) {
   17354   Handle<StringTable> table = isolate->factory()->string_table();
   17355   int entry = table->FindEntry(key);
   17356   if (entry != kNotFound) return String::cast(table->KeyAt(entry));
   17357   return NULL;
   17358 }
   17359 
   17360 Handle<StringSet> StringSet::New(Isolate* isolate) {
   17361   return HashTable::New(isolate, 0);
   17362 }
   17363 
   17364 Handle<StringSet> StringSet::Add(Handle<StringSet> stringset,
   17365                                  Handle<String> name) {
   17366   if (!stringset->Has(name)) {
   17367     stringset = EnsureCapacity(stringset, 1, *name);
   17368     uint32_t hash = StringSetShape::Hash(*name);
   17369     int entry = stringset->FindInsertionEntry(hash);
   17370     stringset->set(EntryToIndex(entry), *name);
   17371     stringset->ElementAdded();
   17372   }
   17373   return stringset;
   17374 }
   17375 
   17376 bool StringSet::Has(Handle<String> name) {
   17377   return FindEntry(*name) != kNotFound;
   17378 }
   17379 
   17380 Handle<ObjectHashSet> ObjectHashSet::Add(Handle<ObjectHashSet> set,
   17381                                          Handle<Object> key) {
   17382   Isolate* isolate = set->GetIsolate();
   17383   int32_t hash = Object::GetOrCreateHash(isolate, key)->value();
   17384 
   17385   if (!set->Has(isolate, key, hash)) {
   17386     set = EnsureCapacity(set, 1, key);
   17387     int entry = set->FindInsertionEntry(hash);
   17388     set->set(EntryToIndex(entry), *key);
   17389     set->ElementAdded();
   17390   }
   17391   return set;
   17392 }
   17393 
   17394 Handle<Object> CompilationCacheTable::Lookup(Handle<String> src,
   17395                                              Handle<Context> context,
   17396                                              LanguageMode language_mode) {
   17397   Isolate* isolate = GetIsolate();
   17398   Handle<SharedFunctionInfo> shared(context->closure()->shared());
   17399   StringSharedKey key(src, shared, language_mode, kNoSourcePosition);
   17400   int entry = FindEntry(&key);
   17401   if (entry == kNotFound) return isolate->factory()->undefined_value();
   17402   int index = EntryToIndex(entry);
   17403   if (!get(index)->IsFixedArray()) return isolate->factory()->undefined_value();
   17404   return Handle<Object>(get(index + 1), isolate);
   17405 }
   17406 
   17407 namespace {
   17408 
   17409 const int kLiteralEntryLength = 2;
   17410 const int kLiteralInitialLength = 2;
   17411 const int kLiteralContextOffset = 0;
   17412 const int kLiteralLiteralsOffset = 1;
   17413 
   17414 int SearchLiteralsMapEntry(CompilationCacheTable* cache, int cache_entry,
   17415                            Context* native_context) {
   17416   DisallowHeapAllocation no_gc;
   17417   DCHECK(native_context->IsNativeContext());
   17418   Object* obj = cache->get(cache_entry);
   17419 
   17420   if (obj->IsFixedArray()) {
   17421     FixedArray* literals_map = FixedArray::cast(obj);
   17422     int length = literals_map->length();
   17423     for (int i = 0; i < length; i += kLiteralEntryLength) {
   17424       if (WeakCell::cast(literals_map->get(i + kLiteralContextOffset))
   17425               ->value() == native_context) {
   17426         return i;
   17427       }
   17428     }
   17429   }
   17430   return -1;
   17431 }
   17432 
   17433 void AddToLiteralsMap(Handle<CompilationCacheTable> cache, int cache_entry,
   17434                       Handle<Context> native_context, Handle<Cell> literals) {
   17435   Isolate* isolate = native_context->GetIsolate();
   17436   DCHECK(native_context->IsNativeContext());
   17437   STATIC_ASSERT(kLiteralEntryLength == 2);
   17438   Handle<FixedArray> new_literals_map;
   17439   int entry;
   17440 
   17441   Object* obj = cache->get(cache_entry);
   17442 
   17443   if (!obj->IsFixedArray() || FixedArray::cast(obj)->length() == 0) {
   17444     new_literals_map =
   17445         isolate->factory()->NewFixedArray(kLiteralInitialLength, TENURED);
   17446     entry = 0;
   17447   } else {
   17448     Handle<FixedArray> old_literals_map(FixedArray::cast(obj), isolate);
   17449     entry = SearchLiteralsMapEntry(*cache, cache_entry, *native_context);
   17450     if (entry >= 0) {
   17451       // Just set the code of the entry.
   17452       Handle<WeakCell> literals_cell =
   17453           isolate->factory()->NewWeakCell(literals);
   17454       old_literals_map->set(entry + kLiteralLiteralsOffset, *literals_cell);
   17455       return;
   17456     }
   17457 
   17458     // Can we reuse an entry?
   17459     DCHECK(entry < 0);
   17460     int length = old_literals_map->length();
   17461     for (int i = 0; i < length; i += kLiteralEntryLength) {
   17462       if (WeakCell::cast(old_literals_map->get(i + kLiteralContextOffset))
   17463               ->cleared()) {
   17464         new_literals_map = old_literals_map;
   17465         entry = i;
   17466         break;
   17467       }
   17468     }
   17469 
   17470     if (entry < 0) {
   17471       // Copy old optimized code map and append one new entry.
   17472       new_literals_map = isolate->factory()->CopyFixedArrayAndGrow(
   17473           old_literals_map, kLiteralEntryLength, TENURED);
   17474       entry = old_literals_map->length();
   17475     }
   17476   }
   17477 
   17478   Handle<WeakCell> literals_cell = isolate->factory()->NewWeakCell(literals);
   17479   WeakCell* context_cell = native_context->self_weak_cell();
   17480 
   17481   new_literals_map->set(entry + kLiteralContextOffset, context_cell);
   17482   new_literals_map->set(entry + kLiteralLiteralsOffset, *literals_cell);
   17483 
   17484 #ifdef DEBUG
   17485   for (int i = 0; i < new_literals_map->length(); i += kLiteralEntryLength) {
   17486     WeakCell* cell =
   17487         WeakCell::cast(new_literals_map->get(i + kLiteralContextOffset));
   17488     DCHECK(cell->cleared() || cell->value()->IsNativeContext());
   17489     cell = WeakCell::cast(new_literals_map->get(i + kLiteralLiteralsOffset));
   17490     DCHECK(cell->cleared() || (cell->value()->IsCell()));
   17491   }
   17492 #endif
   17493 
   17494   Object* old_literals_map = cache->get(cache_entry);
   17495   if (old_literals_map != *new_literals_map) {
   17496     cache->set(cache_entry, *new_literals_map);
   17497   }
   17498 }
   17499 
   17500 Cell* SearchLiteralsMap(CompilationCacheTable* cache, int cache_entry,
   17501                         Context* native_context) {
   17502   Cell* result = nullptr;
   17503   int entry = SearchLiteralsMapEntry(cache, cache_entry, native_context);
   17504   if (entry >= 0) {
   17505     FixedArray* literals_map = FixedArray::cast(cache->get(cache_entry));
   17506     DCHECK_LE(entry + kLiteralEntryLength, literals_map->length());
   17507     WeakCell* cell =
   17508         WeakCell::cast(literals_map->get(entry + kLiteralLiteralsOffset));
   17509 
   17510     result = cell->cleared() ? nullptr : Cell::cast(cell->value());
   17511   }
   17512   DCHECK(result == nullptr || result->IsCell());
   17513   return result;
   17514 }
   17515 
   17516 }  // namespace
   17517 
   17518 InfoVectorPair CompilationCacheTable::LookupScript(Handle<String> src,
   17519                                                    Handle<Context> context,
   17520                                                    LanguageMode language_mode) {
   17521   InfoVectorPair empty_result;
   17522   Handle<SharedFunctionInfo> shared(context->closure()->shared());
   17523   StringSharedKey key(src, shared, language_mode, kNoSourcePosition);
   17524   int entry = FindEntry(&key);
   17525   if (entry == kNotFound) return empty_result;
   17526   int index = EntryToIndex(entry);
   17527   if (!get(index)->IsFixedArray()) return empty_result;
   17528   Object* obj = get(index + 1);
   17529   if (obj->IsSharedFunctionInfo()) {
   17530     Cell* literals =
   17531         SearchLiteralsMap(this, index + 2, context->native_context());
   17532     return InfoVectorPair(SharedFunctionInfo::cast(obj), literals);
   17533   }
   17534   return empty_result;
   17535 }
   17536 
   17537 InfoVectorPair CompilationCacheTable::LookupEval(
   17538     Handle<String> src, Handle<SharedFunctionInfo> outer_info,
   17539     Handle<Context> native_context, LanguageMode language_mode, int position) {
   17540   InfoVectorPair empty_result;
   17541   StringSharedKey key(src, outer_info, language_mode, position);
   17542   int entry = FindEntry(&key);
   17543   if (entry == kNotFound) return empty_result;
   17544   int index = EntryToIndex(entry);
   17545   if (!get(index)->IsFixedArray()) return empty_result;
   17546   Object* obj = get(EntryToIndex(entry) + 1);
   17547   if (obj->IsSharedFunctionInfo()) {
   17548     Cell* literals =
   17549         SearchLiteralsMap(this, EntryToIndex(entry) + 2, *native_context);
   17550     return InfoVectorPair(SharedFunctionInfo::cast(obj), literals);
   17551   }
   17552   return empty_result;
   17553 }
   17554 
   17555 Handle<Object> CompilationCacheTable::LookupRegExp(Handle<String> src,
   17556                                                    JSRegExp::Flags flags) {
   17557   Isolate* isolate = GetIsolate();
   17558   DisallowHeapAllocation no_allocation;
   17559   RegExpKey key(src, flags);
   17560   int entry = FindEntry(&key);
   17561   if (entry == kNotFound) return isolate->factory()->undefined_value();
   17562   return Handle<Object>(get(EntryToIndex(entry) + 1), isolate);
   17563 }
   17564 
   17565 
   17566 Handle<CompilationCacheTable> CompilationCacheTable::Put(
   17567     Handle<CompilationCacheTable> cache, Handle<String> src,
   17568     Handle<Context> context, LanguageMode language_mode, Handle<Object> value) {
   17569   Isolate* isolate = cache->GetIsolate();
   17570   Handle<SharedFunctionInfo> shared(context->closure()->shared());
   17571   StringSharedKey key(src, shared, language_mode, kNoSourcePosition);
   17572   Handle<Object> k = key.AsHandle(isolate);
   17573   cache = EnsureCapacity(cache, 1, &key);
   17574   int entry = cache->FindInsertionEntry(key.Hash());
   17575   cache->set(EntryToIndex(entry), *k);
   17576   cache->set(EntryToIndex(entry) + 1, *value);
   17577   cache->ElementAdded();
   17578   return cache;
   17579 }
   17580 
   17581 Handle<CompilationCacheTable> CompilationCacheTable::PutScript(
   17582     Handle<CompilationCacheTable> cache, Handle<String> src,
   17583     Handle<Context> context, LanguageMode language_mode,
   17584     Handle<SharedFunctionInfo> value, Handle<Cell> literals) {
   17585   Isolate* isolate = cache->GetIsolate();
   17586   Handle<SharedFunctionInfo> shared(context->closure()->shared());
   17587   Handle<Context> native_context(context->native_context());
   17588   StringSharedKey key(src, shared, language_mode, kNoSourcePosition);
   17589   Handle<Object> k = key.AsHandle(isolate);
   17590   cache = EnsureCapacity(cache, 1, &key);
   17591   int entry = cache->FindInsertionEntry(key.Hash());
   17592   cache->set(EntryToIndex(entry), *k);
   17593   cache->set(EntryToIndex(entry) + 1, *value);
   17594   AddToLiteralsMap(cache, EntryToIndex(entry) + 2, native_context, literals);
   17595   cache->ElementAdded();
   17596   return cache;
   17597 }
   17598 
   17599 Handle<CompilationCacheTable> CompilationCacheTable::PutEval(
   17600     Handle<CompilationCacheTable> cache, Handle<String> src,
   17601     Handle<SharedFunctionInfo> outer_info, Handle<SharedFunctionInfo> value,
   17602     Handle<Context> native_context, Handle<Cell> literals, int position) {
   17603   Isolate* isolate = cache->GetIsolate();
   17604   StringSharedKey key(src, outer_info, value->language_mode(), position);
   17605   {
   17606     Handle<Object> k = key.AsHandle(isolate);
   17607     int entry = cache->FindEntry(&key);
   17608     if (entry != kNotFound) {
   17609       cache->set(EntryToIndex(entry), *k);
   17610       cache->set(EntryToIndex(entry) + 1, *value);
   17611       // AddToLiteralsMap may allocate a new sub-array to live in the entry,
   17612       // but it won't change the cache array. Therefore EntryToIndex and
   17613       // entry remains correct.
   17614       AddToLiteralsMap(cache, EntryToIndex(entry) + 2, native_context,
   17615                        literals);
   17616       return cache;
   17617     }
   17618   }
   17619 
   17620   cache = EnsureCapacity(cache, 1, &key);
   17621   int entry = cache->FindInsertionEntry(key.Hash());
   17622   Handle<Object> k =
   17623       isolate->factory()->NewNumber(static_cast<double>(key.Hash()));
   17624   cache->set(EntryToIndex(entry), *k);
   17625   cache->set(EntryToIndex(entry) + 1, Smi::FromInt(kHashGenerations));
   17626   cache->ElementAdded();
   17627   return cache;
   17628 }
   17629 
   17630 
   17631 Handle<CompilationCacheTable> CompilationCacheTable::PutRegExp(
   17632       Handle<CompilationCacheTable> cache, Handle<String> src,
   17633       JSRegExp::Flags flags, Handle<FixedArray> value) {
   17634   RegExpKey key(src, flags);
   17635   cache = EnsureCapacity(cache, 1, &key);
   17636   int entry = cache->FindInsertionEntry(key.Hash());
   17637   // We store the value in the key slot, and compare the search key
   17638   // to the stored value with a custon IsMatch function during lookups.
   17639   cache->set(EntryToIndex(entry), *value);
   17640   cache->set(EntryToIndex(entry) + 1, *value);
   17641   cache->ElementAdded();
   17642   return cache;
   17643 }
   17644 
   17645 
   17646 void CompilationCacheTable::Age() {
   17647   DisallowHeapAllocation no_allocation;
   17648   Object* the_hole_value = GetHeap()->the_hole_value();
   17649   for (int entry = 0, size = Capacity(); entry < size; entry++) {
   17650     int entry_index = EntryToIndex(entry);
   17651     int value_index = entry_index + 1;
   17652 
   17653     if (get(entry_index)->IsNumber()) {
   17654       Smi* count = Smi::cast(get(value_index));
   17655       count = Smi::FromInt(count->value() - 1);
   17656       if (count->value() == 0) {
   17657         NoWriteBarrierSet(this, entry_index, the_hole_value);
   17658         NoWriteBarrierSet(this, value_index, the_hole_value);
   17659         ElementRemoved();
   17660       } else {
   17661         NoWriteBarrierSet(this, value_index, count);
   17662       }
   17663     } else if (get(entry_index)->IsFixedArray()) {
   17664       SharedFunctionInfo* info = SharedFunctionInfo::cast(get(value_index));
   17665       bool is_old =
   17666           info->IsInterpreted()
   17667               ? info->bytecode_array()->IsOld()
   17668               : info->code()->kind() != Code::FUNCTION || info->code()->IsOld();
   17669       if (is_old) {
   17670         for (int i = 0; i < kEntrySize; i++) {
   17671           NoWriteBarrierSet(this, entry_index + i, the_hole_value);
   17672         }
   17673         ElementRemoved();
   17674       }
   17675     }
   17676   }
   17677 }
   17678 
   17679 
   17680 void CompilationCacheTable::Remove(Object* value) {
   17681   DisallowHeapAllocation no_allocation;
   17682   Object* the_hole_value = GetHeap()->the_hole_value();
   17683   for (int entry = 0, size = Capacity(); entry < size; entry++) {
   17684     int entry_index = EntryToIndex(entry);
   17685     int value_index = entry_index + 1;
   17686     if (get(value_index) == value) {
   17687       for (int i = 0; i < kEntrySize; i++) {
   17688         NoWriteBarrierSet(this, entry_index + i, the_hole_value);
   17689       }
   17690       ElementRemoved();
   17691     }
   17692   }
   17693   return;
   17694 }
   17695 
   17696 template <typename Derived, typename Shape, typename Key>
   17697 Handle<Derived> Dictionary<Derived, Shape, Key>::New(
   17698     Isolate* isolate, int at_least_space_for, PretenureFlag pretenure,
   17699     MinimumCapacity capacity_option) {
   17700   DCHECK(0 <= at_least_space_for);
   17701   Handle<Derived> dict = DerivedHashTable::New(isolate, at_least_space_for,
   17702                                                capacity_option, pretenure);
   17703 
   17704   // Initialize the next enumeration index.
   17705   dict->SetNextEnumerationIndex(PropertyDetails::kInitialIndex);
   17706   return dict;
   17707 }
   17708 
   17709 template <typename Derived, typename Shape, typename Key>
   17710 Handle<Derived> Dictionary<Derived, Shape, Key>::NewEmpty(
   17711     Isolate* isolate, PretenureFlag pretenure) {
   17712   Handle<Derived> dict = DerivedHashTable::New(isolate, 1, pretenure);
   17713   // Attempt to add one element to the empty dictionary must cause reallocation.
   17714   DCHECK(!dict->HasSufficientCapacityToAdd(1));
   17715   // Initialize the next enumeration index.
   17716   dict->SetNextEnumerationIndex(PropertyDetails::kInitialIndex);
   17717   return dict;
   17718 }
   17719 
   17720 template <typename Derived, typename Shape, typename Key>
   17721 Handle<FixedArray>
   17722 Dictionary<Derived, Shape, Key>::GenerateNewEnumerationIndices(
   17723     Handle<Derived> dictionary) {
   17724   int length = dictionary->NumberOfElements();
   17725 
   17726   Handle<FixedArray> iteration_order = IterationIndices(dictionary);
   17727   DCHECK(iteration_order->length() == length);
   17728 
   17729   // Iterate over the dictionary using the enumeration order and update
   17730   // the dictionary with new enumeration indices.
   17731   for (int i = 0; i < length; i++) {
   17732     int index = Smi::cast(iteration_order->get(i))->value();
   17733     DCHECK(dictionary->IsKey(dictionary->KeyAt(index)));
   17734 
   17735     int enum_index = PropertyDetails::kInitialIndex + i;
   17736 
   17737     PropertyDetails details = dictionary->DetailsAt(index);
   17738     PropertyDetails new_details = details.set_index(enum_index);
   17739     dictionary->DetailsAtPut(index, new_details);
   17740   }
   17741 
   17742   // Set the next enumeration index.
   17743   dictionary->SetNextEnumerationIndex(PropertyDetails::kInitialIndex+length);
   17744   return iteration_order;
   17745 }
   17746 
   17747 
   17748 template <typename Derived, typename Shape, typename Key>
   17749 void Dictionary<Derived, Shape, Key>::SetRequiresCopyOnCapacityChange() {
   17750   DCHECK_EQ(0, DerivedHashTable::NumberOfElements());
   17751   DCHECK_EQ(0, DerivedHashTable::NumberOfDeletedElements());
   17752   // Make sure that HashTable::EnsureCapacity will create a copy.
   17753   DerivedHashTable::SetNumberOfDeletedElements(DerivedHashTable::Capacity());
   17754   DCHECK(!DerivedHashTable::HasSufficientCapacityToAdd(1));
   17755 }
   17756 
   17757 
   17758 template <typename Derived, typename Shape, typename Key>
   17759 Handle<Derived> Dictionary<Derived, Shape, Key>::EnsureCapacity(
   17760     Handle<Derived> dictionary, int n, Key key) {
   17761   // Check whether there are enough enumeration indices to add n elements.
   17762   if (Shape::kIsEnumerable &&
   17763       !PropertyDetails::IsValidIndex(dictionary->NextEnumerationIndex() + n)) {
   17764     // If not, we generate new indices for the properties.
   17765     GenerateNewEnumerationIndices(dictionary);
   17766   }
   17767   return DerivedHashTable::EnsureCapacity(dictionary, n, key);
   17768 }
   17769 
   17770 
   17771 template <typename Derived, typename Shape, typename Key>
   17772 Handle<Object> Dictionary<Derived, Shape, Key>::DeleteProperty(
   17773     Handle<Derived> dictionary, int entry) {
   17774   Factory* factory = dictionary->GetIsolate()->factory();
   17775   PropertyDetails details = dictionary->DetailsAt(entry);
   17776   if (!details.IsConfigurable()) return factory->false_value();
   17777 
   17778   dictionary->SetEntry(
   17779       entry, factory->the_hole_value(), factory->the_hole_value());
   17780   dictionary->ElementRemoved();
   17781   return factory->true_value();
   17782 }
   17783 
   17784 
   17785 template<typename Derived, typename Shape, typename Key>
   17786 Handle<Derived> Dictionary<Derived, Shape, Key>::AtPut(
   17787     Handle<Derived> dictionary, Key key, Handle<Object> value) {
   17788   int entry = dictionary->FindEntry(key);
   17789 
   17790   // If the entry is present set the value;
   17791   if (entry != Dictionary::kNotFound) {
   17792     dictionary->ValueAtPut(entry, *value);
   17793     return dictionary;
   17794   }
   17795 
   17796   // Check whether the dictionary should be extended.
   17797   dictionary = EnsureCapacity(dictionary, 1, key);
   17798 #ifdef DEBUG
   17799   USE(Shape::AsHandle(dictionary->GetIsolate(), key));
   17800 #endif
   17801   PropertyDetails details = PropertyDetails::Empty();
   17802 
   17803   AddEntry(dictionary, key, value, details, dictionary->Hash(key));
   17804   return dictionary;
   17805 }
   17806 
   17807 template <typename Derived, typename Shape, typename Key>
   17808 Handle<Derived> Dictionary<Derived, Shape, Key>::Add(Handle<Derived> dictionary,
   17809                                                      Key key,
   17810                                                      Handle<Object> value,
   17811                                                      PropertyDetails details,
   17812                                                      int* entry_out) {
   17813   // Valdate key is absent.
   17814   SLOW_DCHECK((dictionary->FindEntry(key) == Dictionary::kNotFound));
   17815   // Check whether the dictionary should be extended.
   17816   dictionary = EnsureCapacity(dictionary, 1, key);
   17817 
   17818   int entry = AddEntry(dictionary, key, value, details, dictionary->Hash(key));
   17819   if (entry_out) *entry_out = entry;
   17820   return dictionary;
   17821 }
   17822 
   17823 // Add a key, value pair to the dictionary. Returns entry value.
   17824 template <typename Derived, typename Shape, typename Key>
   17825 int Dictionary<Derived, Shape, Key>::AddEntry(Handle<Derived> dictionary,
   17826                                               Key key, Handle<Object> value,
   17827                                               PropertyDetails details,
   17828                                               uint32_t hash) {
   17829   // Compute the key object.
   17830   Handle<Object> k = Shape::AsHandle(dictionary->GetIsolate(), key);
   17831 
   17832   uint32_t entry = dictionary->FindInsertionEntry(hash);
   17833   // Insert element at empty or deleted entry
   17834   if (details.dictionary_index() == 0 && Shape::kIsEnumerable) {
   17835     // Assign an enumeration index to the property and update
   17836     // SetNextEnumerationIndex.
   17837     int index = dictionary->NextEnumerationIndex();
   17838     details = details.set_index(index);
   17839     dictionary->SetNextEnumerationIndex(index + 1);
   17840   }
   17841   dictionary->SetEntry(entry, k, value, details);
   17842   DCHECK((dictionary->KeyAt(entry)->IsNumber() ||
   17843           dictionary->KeyAt(entry)->IsName()));
   17844   dictionary->ElementAdded();
   17845   return entry;
   17846 }
   17847 
   17848 bool SeededNumberDictionary::HasComplexElements() {
   17849   if (!requires_slow_elements()) return false;
   17850   Isolate* isolate = this->GetIsolate();
   17851   int capacity = this->Capacity();
   17852   for (int i = 0; i < capacity; i++) {
   17853     Object* k = this->KeyAt(i);
   17854     if (!this->IsKey(isolate, k)) continue;
   17855     DCHECK(!IsDeleted(i));
   17856     PropertyDetails details = this->DetailsAt(i);
   17857     if (details.kind() == kAccessor) return true;
   17858     PropertyAttributes attr = details.attributes();
   17859     if (attr & ALL_ATTRIBUTES_MASK) return true;
   17860   }
   17861   return false;
   17862 }
   17863 
   17864 void SeededNumberDictionary::UpdateMaxNumberKey(
   17865     uint32_t key, Handle<JSObject> dictionary_holder) {
   17866   DisallowHeapAllocation no_allocation;
   17867   // If the dictionary requires slow elements an element has already
   17868   // been added at a high index.
   17869   if (requires_slow_elements()) return;
   17870   // Check if this index is high enough that we should require slow
   17871   // elements.
   17872   if (key > kRequiresSlowElementsLimit) {
   17873     if (!dictionary_holder.is_null()) {
   17874       dictionary_holder->RequireSlowElements(this);
   17875     }
   17876     set_requires_slow_elements();
   17877     return;
   17878   }
   17879   // Update max key value.
   17880   Object* max_index_object = get(kMaxNumberKeyIndex);
   17881   if (!max_index_object->IsSmi() || max_number_key() < key) {
   17882     FixedArray::set(kMaxNumberKeyIndex,
   17883                     Smi::FromInt(key << kRequiresSlowElementsTagSize));
   17884   }
   17885 }
   17886 
   17887 Handle<SeededNumberDictionary> SeededNumberDictionary::AddNumberEntry(
   17888     Handle<SeededNumberDictionary> dictionary, uint32_t key,
   17889     Handle<Object> value, PropertyDetails details,
   17890     Handle<JSObject> dictionary_holder) {
   17891   dictionary->UpdateMaxNumberKey(key, dictionary_holder);
   17892   SLOW_DCHECK(dictionary->FindEntry(key) == kNotFound);
   17893   return Add(dictionary, key, value, details);
   17894 }
   17895 
   17896 
   17897 Handle<UnseededNumberDictionary> UnseededNumberDictionary::AddNumberEntry(
   17898     Handle<UnseededNumberDictionary> dictionary,
   17899     uint32_t key,
   17900     Handle<Object> value) {
   17901   SLOW_DCHECK(dictionary->FindEntry(key) == kNotFound);
   17902   return Add(dictionary, key, value, PropertyDetails::Empty());
   17903 }
   17904 
   17905 Handle<UnseededNumberDictionary> UnseededNumberDictionary::DeleteKey(
   17906     Handle<UnseededNumberDictionary> dictionary, uint32_t key) {
   17907   int entry = dictionary->FindEntry(key);
   17908   if (entry == kNotFound) return dictionary;
   17909 
   17910   Factory* factory = dictionary->GetIsolate()->factory();
   17911   dictionary->SetEntry(entry, factory->the_hole_value(),
   17912                        factory->the_hole_value());
   17913   dictionary->ElementRemoved();
   17914   return dictionary->Shrink(dictionary, key);
   17915 }
   17916 
   17917 Handle<SeededNumberDictionary> SeededNumberDictionary::AtNumberPut(
   17918     Handle<SeededNumberDictionary> dictionary, uint32_t key,
   17919     Handle<Object> value, Handle<JSObject> dictionary_holder) {
   17920   dictionary->UpdateMaxNumberKey(key, dictionary_holder);
   17921   return AtPut(dictionary, key, value);
   17922 }
   17923 
   17924 
   17925 Handle<UnseededNumberDictionary> UnseededNumberDictionary::AtNumberPut(
   17926     Handle<UnseededNumberDictionary> dictionary,
   17927     uint32_t key,
   17928     Handle<Object> value) {
   17929   return AtPut(dictionary, key, value);
   17930 }
   17931 
   17932 Handle<SeededNumberDictionary> SeededNumberDictionary::Set(
   17933     Handle<SeededNumberDictionary> dictionary, uint32_t key,
   17934     Handle<Object> value, PropertyDetails details,
   17935     Handle<JSObject> dictionary_holder) {
   17936   int entry = dictionary->FindEntry(key);
   17937   if (entry == kNotFound) {
   17938     return AddNumberEntry(dictionary, key, value, details, dictionary_holder);
   17939   }
   17940   // Preserve enumeration index.
   17941   details = details.set_index(dictionary->DetailsAt(entry).dictionary_index());
   17942   Handle<Object> object_key =
   17943       SeededNumberDictionaryShape::AsHandle(dictionary->GetIsolate(), key);
   17944   dictionary->SetEntry(entry, object_key, value, details);
   17945   return dictionary;
   17946 }
   17947 
   17948 
   17949 Handle<UnseededNumberDictionary> UnseededNumberDictionary::Set(
   17950     Handle<UnseededNumberDictionary> dictionary,
   17951     uint32_t key,
   17952     Handle<Object> value) {
   17953   int entry = dictionary->FindEntry(key);
   17954   if (entry == kNotFound) return AddNumberEntry(dictionary, key, value);
   17955   Handle<Object> object_key =
   17956       UnseededNumberDictionaryShape::AsHandle(dictionary->GetIsolate(), key);
   17957   dictionary->SetEntry(entry, object_key, value);
   17958   return dictionary;
   17959 }
   17960 
   17961 
   17962 template <typename Derived, typename Shape, typename Key>
   17963 int Dictionary<Derived, Shape, Key>::NumberOfElementsFilterAttributes(
   17964     PropertyFilter filter) {
   17965   Isolate* isolate = this->GetIsolate();
   17966   int capacity = this->Capacity();
   17967   int result = 0;
   17968   for (int i = 0; i < capacity; i++) {
   17969     Object* k = this->KeyAt(i);
   17970     if (this->IsKey(isolate, k) && !k->FilterKey(filter)) {
   17971       if (this->IsDeleted(i)) continue;
   17972       PropertyDetails details = this->DetailsAt(i);
   17973       PropertyAttributes attr = details.attributes();
   17974       if ((attr & filter) == 0) result++;
   17975     }
   17976   }
   17977   return result;
   17978 }
   17979 
   17980 
   17981 template <typename Dictionary>
   17982 struct EnumIndexComparator {
   17983   explicit EnumIndexComparator(Dictionary* dict) : dict(dict) {}
   17984   bool operator() (Smi* a, Smi* b) {
   17985     PropertyDetails da(dict->DetailsAt(a->value()));
   17986     PropertyDetails db(dict->DetailsAt(b->value()));
   17987     return da.dictionary_index() < db.dictionary_index();
   17988   }
   17989   Dictionary* dict;
   17990 };
   17991 
   17992 template <typename Derived, typename Shape, typename Key>
   17993 void Dictionary<Derived, Shape, Key>::CopyEnumKeysTo(
   17994     Handle<Dictionary<Derived, Shape, Key>> dictionary,
   17995     Handle<FixedArray> storage, KeyCollectionMode mode,
   17996     KeyAccumulator* accumulator) {
   17997   DCHECK_IMPLIES(mode != KeyCollectionMode::kOwnOnly, accumulator != nullptr);
   17998   Isolate* isolate = dictionary->GetIsolate();
   17999   int length = storage->length();
   18000   int capacity = dictionary->Capacity();
   18001   int properties = 0;
   18002   for (int i = 0; i < capacity; i++) {
   18003     Object* key = dictionary->KeyAt(i);
   18004     bool is_shadowing_key = false;
   18005     if (!dictionary->IsKey(isolate, key)) continue;
   18006     if (key->IsSymbol()) continue;
   18007     PropertyDetails details = dictionary->DetailsAt(i);
   18008     if (details.IsDontEnum()) {
   18009       if (mode == KeyCollectionMode::kIncludePrototypes) {
   18010         is_shadowing_key = true;
   18011       } else {
   18012         continue;
   18013       }
   18014     }
   18015     if (dictionary->IsDeleted(i)) continue;
   18016     if (is_shadowing_key) {
   18017       accumulator->AddShadowingKey(key);
   18018       continue;
   18019     } else {
   18020       storage->set(properties, Smi::FromInt(i));
   18021     }
   18022     properties++;
   18023     if (mode == KeyCollectionMode::kOwnOnly && properties == length) break;
   18024   }
   18025 
   18026   CHECK_EQ(length, properties);
   18027   DisallowHeapAllocation no_gc;
   18028   Dictionary<Derived, Shape, Key>* raw_dictionary = *dictionary;
   18029   FixedArray* raw_storage = *storage;
   18030   EnumIndexComparator<Derived> cmp(static_cast<Derived*>(*dictionary));
   18031   Smi** start = reinterpret_cast<Smi**>(storage->GetFirstElementAddress());
   18032   std::sort(start, start + length, cmp);
   18033   for (int i = 0; i < length; i++) {
   18034     int index = Smi::cast(raw_storage->get(i))->value();
   18035     raw_storage->set(i, raw_dictionary->KeyAt(index));
   18036   }
   18037 }
   18038 
   18039 template <typename Derived, typename Shape, typename Key>
   18040 Handle<FixedArray> Dictionary<Derived, Shape, Key>::IterationIndices(
   18041     Handle<Dictionary<Derived, Shape, Key>> dictionary) {
   18042   Isolate* isolate = dictionary->GetIsolate();
   18043   int capacity = dictionary->Capacity();
   18044   int length = dictionary->NumberOfElements();
   18045   Handle<FixedArray> array = isolate->factory()->NewFixedArray(length);
   18046   int array_size = 0;
   18047   {
   18048     DisallowHeapAllocation no_gc;
   18049     Dictionary<Derived, Shape, Key>* raw_dict = *dictionary;
   18050     for (int i = 0; i < capacity; i++) {
   18051       Object* k = raw_dict->KeyAt(i);
   18052       if (!raw_dict->IsKey(isolate, k)) continue;
   18053       if (raw_dict->IsDeleted(i)) continue;
   18054       array->set(array_size++, Smi::FromInt(i));
   18055     }
   18056 
   18057     DCHECK_EQ(array_size, length);
   18058 
   18059     EnumIndexComparator<Derived> cmp(static_cast<Derived*>(raw_dict));
   18060     Smi** start = reinterpret_cast<Smi**>(array->GetFirstElementAddress());
   18061     std::sort(start, start + array_size, cmp);
   18062   }
   18063   array->Shrink(array_size);
   18064   return array;
   18065 }
   18066 
   18067 template <typename Derived, typename Shape, typename Key>
   18068 void Dictionary<Derived, Shape, Key>::CollectKeysTo(
   18069     Handle<Dictionary<Derived, Shape, Key>> dictionary, KeyAccumulator* keys) {
   18070   Isolate* isolate = keys->isolate();
   18071   int capacity = dictionary->Capacity();
   18072   Handle<FixedArray> array =
   18073       isolate->factory()->NewFixedArray(dictionary->NumberOfElements());
   18074   int array_size = 0;
   18075   PropertyFilter filter = keys->filter();
   18076   {
   18077     DisallowHeapAllocation no_gc;
   18078     Dictionary<Derived, Shape, Key>* raw_dict = *dictionary;
   18079     for (int i = 0; i < capacity; i++) {
   18080       Object* k = raw_dict->KeyAt(i);
   18081       if (!raw_dict->IsKey(isolate, k) || k->FilterKey(filter)) continue;
   18082       if (raw_dict->IsDeleted(i)) continue;
   18083       PropertyDetails details = raw_dict->DetailsAt(i);
   18084       if ((details.attributes() & filter) != 0) {
   18085         keys->AddShadowingKey(k);
   18086         continue;
   18087       }
   18088       if (filter & ONLY_ALL_CAN_READ) {
   18089         if (details.kind() != kAccessor) continue;
   18090         Object* accessors = raw_dict->ValueAt(i);
   18091         if (accessors->IsPropertyCell()) {
   18092           accessors = PropertyCell::cast(accessors)->value();
   18093         }
   18094         if (!accessors->IsAccessorInfo()) continue;
   18095         if (!AccessorInfo::cast(accessors)->all_can_read()) continue;
   18096       }
   18097       array->set(array_size++, Smi::FromInt(i));
   18098     }
   18099 
   18100     EnumIndexComparator<Derived> cmp(static_cast<Derived*>(raw_dict));
   18101     Smi** start = reinterpret_cast<Smi**>(array->GetFirstElementAddress());
   18102     std::sort(start, start + array_size, cmp);
   18103   }
   18104 
   18105   bool has_seen_symbol = false;
   18106   for (int i = 0; i < array_size; i++) {
   18107     int index = Smi::cast(array->get(i))->value();
   18108     Object* key = dictionary->KeyAt(index);
   18109     if (key->IsSymbol()) {
   18110       has_seen_symbol = true;
   18111       continue;
   18112     }
   18113     keys->AddKey(key, DO_NOT_CONVERT);
   18114   }
   18115   if (has_seen_symbol) {
   18116     for (int i = 0; i < array_size; i++) {
   18117       int index = Smi::cast(array->get(i))->value();
   18118       Object* key = dictionary->KeyAt(index);
   18119       if (!key->IsSymbol()) continue;
   18120       keys->AddKey(key, DO_NOT_CONVERT);
   18121     }
   18122   }
   18123 }
   18124 
   18125 
   18126 // Backwards lookup (slow).
   18127 template<typename Derived, typename Shape, typename Key>
   18128 Object* Dictionary<Derived, Shape, Key>::SlowReverseLookup(Object* value) {
   18129   Isolate* isolate = this->GetIsolate();
   18130   int capacity = this->Capacity();
   18131   for (int i = 0; i < capacity; i++) {
   18132     Object* k = this->KeyAt(i);
   18133     if (!this->IsKey(isolate, k)) continue;
   18134     Object* e = this->ValueAt(i);
   18135     // TODO(dcarney): this should be templatized.
   18136     if (e->IsPropertyCell()) {
   18137       e = PropertyCell::cast(e)->value();
   18138     }
   18139     if (e == value) return k;
   18140   }
   18141   return isolate->heap()->undefined_value();
   18142 }
   18143 
   18144 
   18145 Object* ObjectHashTable::Lookup(Isolate* isolate, Handle<Object> key,
   18146                                 int32_t hash) {
   18147   DisallowHeapAllocation no_gc;
   18148   DCHECK(IsKey(isolate, *key));
   18149 
   18150   int entry = FindEntry(isolate, key, hash);
   18151   if (entry == kNotFound) return isolate->heap()->the_hole_value();
   18152   return get(EntryToIndex(entry) + 1);
   18153 }
   18154 
   18155 
   18156 Object* ObjectHashTable::Lookup(Handle<Object> key) {
   18157   DisallowHeapAllocation no_gc;
   18158 
   18159   Isolate* isolate = GetIsolate();
   18160   DCHECK(IsKey(isolate, *key));
   18161 
   18162   // If the object does not have an identity hash, it was never used as a key.
   18163   Object* hash = key->GetHash();
   18164   if (hash->IsUndefined(isolate)) {
   18165     return isolate->heap()->the_hole_value();
   18166   }
   18167   return Lookup(isolate, key, Smi::cast(hash)->value());
   18168 }
   18169 
   18170 Object* ObjectHashTable::ValueAt(int entry) {
   18171   return get(EntryToValueIndex(entry));
   18172 }
   18173 
   18174 Object* ObjectHashTable::Lookup(Handle<Object> key, int32_t hash) {
   18175   return Lookup(GetIsolate(), key, hash);
   18176 }
   18177 
   18178 
   18179 Handle<ObjectHashTable> ObjectHashTable::Put(Handle<ObjectHashTable> table,
   18180                                              Handle<Object> key,
   18181                                              Handle<Object> value) {
   18182   Isolate* isolate = table->GetIsolate();
   18183   DCHECK(table->IsKey(isolate, *key));
   18184   DCHECK(!value->IsTheHole(isolate));
   18185 
   18186   // Make sure the key object has an identity hash code.
   18187   int32_t hash = Object::GetOrCreateHash(isolate, key)->value();
   18188 
   18189   return Put(table, key, value, hash);
   18190 }
   18191 
   18192 
   18193 Handle<ObjectHashTable> ObjectHashTable::Put(Handle<ObjectHashTable> table,
   18194                                              Handle<Object> key,
   18195                                              Handle<Object> value,
   18196                                              int32_t hash) {
   18197   Isolate* isolate = table->GetIsolate();
   18198   DCHECK(table->IsKey(isolate, *key));
   18199   DCHECK(!value->IsTheHole(isolate));
   18200 
   18201   int entry = table->FindEntry(isolate, key, hash);
   18202 
   18203   // Key is already in table, just overwrite value.
   18204   if (entry != kNotFound) {
   18205     table->set(EntryToIndex(entry) + 1, *value);
   18206     return table;
   18207   }
   18208 
   18209   // Rehash if more than 33% of the entries are deleted entries.
   18210   // TODO(jochen): Consider to shrink the fixed array in place.
   18211   if ((table->NumberOfDeletedElements() << 1) > table->NumberOfElements()) {
   18212     table->Rehash(isolate->factory()->undefined_value());
   18213   }
   18214   // If we're out of luck, we didn't get a GC recently, and so rehashing
   18215   // isn't enough to avoid a crash.
   18216   if (!table->HasSufficientCapacityToAdd(1)) {
   18217     int nof = table->NumberOfElements() + 1;
   18218     int capacity = ObjectHashTable::ComputeCapacity(nof * 2);
   18219     if (capacity > ObjectHashTable::kMaxCapacity) {
   18220       for (size_t i = 0; i < 2; ++i) {
   18221         isolate->heap()->CollectAllGarbage(
   18222             Heap::kFinalizeIncrementalMarkingMask,
   18223             GarbageCollectionReason::kFullHashtable);
   18224       }
   18225       table->Rehash(isolate->factory()->undefined_value());
   18226     }
   18227   }
   18228 
   18229   // Check whether the hash table should be extended.
   18230   table = EnsureCapacity(table, 1, key);
   18231   table->AddEntry(table->FindInsertionEntry(hash), *key, *value);
   18232   return table;
   18233 }
   18234 
   18235 
   18236 Handle<ObjectHashTable> ObjectHashTable::Remove(Handle<ObjectHashTable> table,
   18237                                                 Handle<Object> key,
   18238                                                 bool* was_present) {
   18239   DCHECK(table->IsKey(table->GetIsolate(), *key));
   18240 
   18241   Object* hash = key->GetHash();
   18242   if (hash->IsUndefined(table->GetIsolate())) {
   18243     *was_present = false;
   18244     return table;
   18245   }
   18246 
   18247   return Remove(table, key, was_present, Smi::cast(hash)->value());
   18248 }
   18249 
   18250 
   18251 Handle<ObjectHashTable> ObjectHashTable::Remove(Handle<ObjectHashTable> table,
   18252                                                 Handle<Object> key,
   18253                                                 bool* was_present,
   18254                                                 int32_t hash) {
   18255   Isolate* isolate = table->GetIsolate();
   18256   DCHECK(table->IsKey(isolate, *key));
   18257 
   18258   int entry = table->FindEntry(isolate, key, hash);
   18259   if (entry == kNotFound) {
   18260     *was_present = false;
   18261     return table;
   18262   }
   18263 
   18264   *was_present = true;
   18265   table->RemoveEntry(entry);
   18266   return Shrink(table, key);
   18267 }
   18268 
   18269 
   18270 void ObjectHashTable::AddEntry(int entry, Object* key, Object* value) {
   18271   set(EntryToIndex(entry), key);
   18272   set(EntryToIndex(entry) + 1, value);
   18273   ElementAdded();
   18274 }
   18275 
   18276 
   18277 void ObjectHashTable::RemoveEntry(int entry) {
   18278   set_the_hole(EntryToIndex(entry));
   18279   set_the_hole(EntryToIndex(entry) + 1);
   18280   ElementRemoved();
   18281 }
   18282 
   18283 
   18284 Object* WeakHashTable::Lookup(Handle<HeapObject> key) {
   18285   DisallowHeapAllocation no_gc;
   18286   Isolate* isolate = GetIsolate();
   18287   DCHECK(IsKey(isolate, *key));
   18288   int entry = FindEntry(key);
   18289   if (entry == kNotFound) return isolate->heap()->the_hole_value();
   18290   return get(EntryToValueIndex(entry));
   18291 }
   18292 
   18293 
   18294 Handle<WeakHashTable> WeakHashTable::Put(Handle<WeakHashTable> table,
   18295                                          Handle<HeapObject> key,
   18296                                          Handle<HeapObject> value) {
   18297   Isolate* isolate = key->GetIsolate();
   18298   DCHECK(table->IsKey(isolate, *key));
   18299   int entry = table->FindEntry(key);
   18300   // Key is already in table, just overwrite value.
   18301   if (entry != kNotFound) {
   18302     table->set(EntryToValueIndex(entry), *value);
   18303     return table;
   18304   }
   18305 
   18306   Handle<WeakCell> key_cell = isolate->factory()->NewWeakCell(key);
   18307 
   18308   // Check whether the hash table should be extended.
   18309   table = EnsureCapacity(table, 1, key, TENURED);
   18310 
   18311   table->AddEntry(table->FindInsertionEntry(table->Hash(key)), key_cell, value);
   18312   return table;
   18313 }
   18314 
   18315 
   18316 void WeakHashTable::AddEntry(int entry, Handle<WeakCell> key_cell,
   18317                              Handle<HeapObject> value) {
   18318   DisallowHeapAllocation no_allocation;
   18319   set(EntryToIndex(entry), *key_cell);
   18320   set(EntryToValueIndex(entry), *value);
   18321   ElementAdded();
   18322 }
   18323 
   18324 
   18325 template<class Derived, class Iterator, int entrysize>
   18326 Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Allocate(
   18327     Isolate* isolate, int capacity, PretenureFlag pretenure) {
   18328   // Capacity must be a power of two, since we depend on being able
   18329   // to divide and multiple by 2 (kLoadFactor) to derive capacity
   18330   // from number of buckets. If we decide to change kLoadFactor
   18331   // to something other than 2, capacity should be stored as another
   18332   // field of this object.
   18333   capacity = base::bits::RoundUpToPowerOfTwo32(Max(kMinCapacity, capacity));
   18334   if (capacity > kMaxCapacity) {
   18335     v8::internal::Heap::FatalProcessOutOfMemory("invalid table size", true);
   18336   }
   18337   int num_buckets = capacity / kLoadFactor;
   18338   Handle<FixedArray> backing_store = isolate->factory()->NewFixedArray(
   18339       kHashTableStartIndex + num_buckets + (capacity * kEntrySize), pretenure);
   18340   backing_store->set_map_no_write_barrier(
   18341       isolate->heap()->ordered_hash_table_map());
   18342   Handle<Derived> table = Handle<Derived>::cast(backing_store);
   18343   for (int i = 0; i < num_buckets; ++i) {
   18344     table->set(kHashTableStartIndex + i, Smi::FromInt(kNotFound));
   18345   }
   18346   table->SetNumberOfBuckets(num_buckets);
   18347   table->SetNumberOfElements(0);
   18348   table->SetNumberOfDeletedElements(0);
   18349   return table;
   18350 }
   18351 
   18352 
   18353 template<class Derived, class Iterator, int entrysize>
   18354 Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::EnsureGrowable(
   18355     Handle<Derived> table) {
   18356   DCHECK(!table->IsObsolete());
   18357 
   18358   int nof = table->NumberOfElements();
   18359   int nod = table->NumberOfDeletedElements();
   18360   int capacity = table->Capacity();
   18361   if ((nof + nod) < capacity) return table;
   18362   // Don't need to grow if we can simply clear out deleted entries instead.
   18363   // Note that we can't compact in place, though, so we always allocate
   18364   // a new table.
   18365   return Rehash(table, (nod < (capacity >> 1)) ? capacity << 1 : capacity);
   18366 }
   18367 
   18368 
   18369 template<class Derived, class Iterator, int entrysize>
   18370 Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Shrink(
   18371     Handle<Derived> table) {
   18372   DCHECK(!table->IsObsolete());
   18373 
   18374   int nof = table->NumberOfElements();
   18375   int capacity = table->Capacity();
   18376   if (nof >= (capacity >> 2)) return table;
   18377   return Rehash(table, capacity / 2);
   18378 }
   18379 
   18380 
   18381 template<class Derived, class Iterator, int entrysize>
   18382 Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Clear(
   18383     Handle<Derived> table) {
   18384   DCHECK(!table->IsObsolete());
   18385 
   18386   Handle<Derived> new_table =
   18387       Allocate(table->GetIsolate(),
   18388                kMinCapacity,
   18389                table->GetHeap()->InNewSpace(*table) ? NOT_TENURED : TENURED);
   18390 
   18391   table->SetNextTable(*new_table);
   18392   table->SetNumberOfDeletedElements(kClearedTableSentinel);
   18393 
   18394   return new_table;
   18395 }
   18396 
   18397 template <class Derived, class Iterator, int entrysize>
   18398 bool OrderedHashTable<Derived, Iterator, entrysize>::HasKey(
   18399     Handle<Derived> table, Handle<Object> key) {
   18400   DisallowHeapAllocation no_gc;
   18401   Isolate* isolate = table->GetIsolate();
   18402   Object* raw_key = *key;
   18403   int entry = table->KeyToFirstEntry(isolate, raw_key);
   18404   // Walk the chain in the bucket to find the key.
   18405   while (entry != kNotFound) {
   18406     Object* candidate_key = table->KeyAt(entry);
   18407     if (candidate_key->SameValueZero(raw_key)) return true;
   18408     entry = table->NextChainEntry(entry);
   18409   }
   18410   return false;
   18411 }
   18412 
   18413 
   18414 Handle<OrderedHashSet> OrderedHashSet::Add(Handle<OrderedHashSet> table,
   18415                                            Handle<Object> key) {
   18416   int hash = Object::GetOrCreateHash(table->GetIsolate(), key)->value();
   18417   int entry = table->HashToEntry(hash);
   18418   // Walk the chain of the bucket and try finding the key.
   18419   while (entry != kNotFound) {
   18420     Object* candidate_key = table->KeyAt(entry);
   18421     // Do not add if we have the key already
   18422     if (candidate_key->SameValueZero(*key)) return table;
   18423     entry = table->NextChainEntry(entry);
   18424   }
   18425 
   18426   table = OrderedHashSet::EnsureGrowable(table);
   18427   // Read the existing bucket values.
   18428   int bucket = table->HashToBucket(hash);
   18429   int previous_entry = table->HashToEntry(hash);
   18430   int nof = table->NumberOfElements();
   18431   // Insert a new entry at the end,
   18432   int new_entry = nof + table->NumberOfDeletedElements();
   18433   int new_index = table->EntryToIndex(new_entry);
   18434   table->set(new_index, *key);
   18435   table->set(new_index + kChainOffset, Smi::FromInt(previous_entry));
   18436   // and point the bucket to the new entry.
   18437   table->set(kHashTableStartIndex + bucket, Smi::FromInt(new_entry));
   18438   table->SetNumberOfElements(nof + 1);
   18439   return table;
   18440 }
   18441 
   18442 Handle<FixedArray> OrderedHashSet::ConvertToKeysArray(
   18443     Handle<OrderedHashSet> table, GetKeysConversion convert) {
   18444   Isolate* isolate = table->GetIsolate();
   18445   int length = table->NumberOfElements();
   18446   int nof_buckets = table->NumberOfBuckets();
   18447   // Convert the dictionary to a linear list.
   18448   Handle<FixedArray> result = Handle<FixedArray>::cast(table);
   18449   // From this point on table is no longer a valid OrderedHashSet.
   18450   result->set_map(isolate->heap()->fixed_array_map());
   18451   for (int i = 0; i < length; i++) {
   18452     int index = kHashTableStartIndex + nof_buckets + (i * kEntrySize);
   18453     Object* key = table->get(index);
   18454     if (convert == GetKeysConversion::kConvertToString && key->IsNumber()) {
   18455       key = *isolate->factory()->NumberToString(handle(key, isolate));
   18456     }
   18457     result->set(i, key);
   18458   }
   18459   result->Shrink(length);
   18460   return result;
   18461 }
   18462 
   18463 template<class Derived, class Iterator, int entrysize>
   18464 Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Rehash(
   18465     Handle<Derived> table, int new_capacity) {
   18466   Isolate* isolate = table->GetIsolate();
   18467   DCHECK(!table->IsObsolete());
   18468 
   18469   Handle<Derived> new_table =
   18470       Allocate(isolate, new_capacity,
   18471                isolate->heap()->InNewSpace(*table) ? NOT_TENURED : TENURED);
   18472   int nof = table->NumberOfElements();
   18473   int nod = table->NumberOfDeletedElements();
   18474   int new_buckets = new_table->NumberOfBuckets();
   18475   int new_entry = 0;
   18476   int removed_holes_index = 0;
   18477 
   18478   DisallowHeapAllocation no_gc;
   18479   for (int old_entry = 0; old_entry < (nof + nod); ++old_entry) {
   18480     Object* key = table->KeyAt(old_entry);
   18481     if (key->IsTheHole(isolate)) {
   18482       table->SetRemovedIndexAt(removed_holes_index++, old_entry);
   18483       continue;
   18484     }
   18485 
   18486     Object* hash = key->GetHash();
   18487     int bucket = Smi::cast(hash)->value() & (new_buckets - 1);
   18488     Object* chain_entry = new_table->get(kHashTableStartIndex + bucket);
   18489     new_table->set(kHashTableStartIndex + bucket, Smi::FromInt(new_entry));
   18490     int new_index = new_table->EntryToIndex(new_entry);
   18491     int old_index = table->EntryToIndex(old_entry);
   18492     for (int i = 0; i < entrysize; ++i) {
   18493       Object* value = table->get(old_index + i);
   18494       new_table->set(new_index + i, value);
   18495     }
   18496     new_table->set(new_index + kChainOffset, chain_entry);
   18497     ++new_entry;
   18498   }
   18499 
   18500   DCHECK_EQ(nod, removed_holes_index);
   18501 
   18502   new_table->SetNumberOfElements(nof);
   18503   table->SetNextTable(*new_table);
   18504 
   18505   return new_table;
   18506 }
   18507 
   18508 
   18509 template Handle<OrderedHashSet>
   18510 OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::Allocate(
   18511     Isolate* isolate, int capacity, PretenureFlag pretenure);
   18512 
   18513 template Handle<OrderedHashSet>
   18514 OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::EnsureGrowable(
   18515     Handle<OrderedHashSet> table);
   18516 
   18517 template Handle<OrderedHashSet>
   18518 OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::Shrink(
   18519     Handle<OrderedHashSet> table);
   18520 
   18521 template Handle<OrderedHashSet>
   18522 OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::Clear(
   18523     Handle<OrderedHashSet> table);
   18524 
   18525 template bool OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::HasKey(
   18526     Handle<OrderedHashSet> table, Handle<Object> key);
   18527 
   18528 
   18529 template Handle<OrderedHashMap>
   18530 OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::Allocate(
   18531     Isolate* isolate, int capacity, PretenureFlag pretenure);
   18532 
   18533 template Handle<OrderedHashMap>
   18534 OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::EnsureGrowable(
   18535     Handle<OrderedHashMap> table);
   18536 
   18537 template Handle<OrderedHashMap>
   18538 OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::Shrink(
   18539     Handle<OrderedHashMap> table);
   18540 
   18541 template Handle<OrderedHashMap>
   18542 OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::Clear(
   18543     Handle<OrderedHashMap> table);
   18544 
   18545 template bool OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::HasKey(
   18546     Handle<OrderedHashMap> table, Handle<Object> key);
   18547 
   18548 
   18549 template<class Derived, class TableType>
   18550 void OrderedHashTableIterator<Derived, TableType>::Transition() {
   18551   DisallowHeapAllocation no_allocation;
   18552   TableType* table = TableType::cast(this->table());
   18553   if (!table->IsObsolete()) return;
   18554 
   18555   int index = Smi::cast(this->index())->value();
   18556   while (table->IsObsolete()) {
   18557     TableType* next_table = table->NextTable();
   18558 
   18559     if (index > 0) {
   18560       int nod = table->NumberOfDeletedElements();
   18561 
   18562       if (nod == TableType::kClearedTableSentinel) {
   18563         index = 0;
   18564       } else {
   18565         int old_index = index;
   18566         for (int i = 0; i < nod; ++i) {
   18567           int removed_index = table->RemovedIndexAt(i);
   18568           if (removed_index >= old_index) break;
   18569           --index;
   18570         }
   18571       }
   18572     }
   18573 
   18574     table = next_table;
   18575   }
   18576 
   18577   set_table(table);
   18578   set_index(Smi::FromInt(index));
   18579 }
   18580 
   18581 
   18582 template<class Derived, class TableType>
   18583 bool OrderedHashTableIterator<Derived, TableType>::HasMore() {
   18584   DisallowHeapAllocation no_allocation;
   18585   Isolate* isolate = this->GetIsolate();
   18586   if (this->table()->IsUndefined(isolate)) return false;
   18587 
   18588   Transition();
   18589 
   18590   TableType* table = TableType::cast(this->table());
   18591   int index = Smi::cast(this->index())->value();
   18592   int used_capacity = table->UsedCapacity();
   18593 
   18594   while (index < used_capacity && table->KeyAt(index)->IsTheHole(isolate)) {
   18595     index++;
   18596   }
   18597 
   18598   set_index(Smi::FromInt(index));
   18599 
   18600   if (index < used_capacity) return true;
   18601 
   18602   set_table(isolate->heap()->undefined_value());
   18603   return false;
   18604 }
   18605 
   18606 
   18607 template<class Derived, class TableType>
   18608 Smi* OrderedHashTableIterator<Derived, TableType>::Next(JSArray* value_array) {
   18609   DisallowHeapAllocation no_allocation;
   18610   if (HasMore()) {
   18611     FixedArray* array = FixedArray::cast(value_array->elements());
   18612     static_cast<Derived*>(this)->PopulateValueArray(array);
   18613     MoveNext();
   18614     return Smi::cast(kind());
   18615   }
   18616   return Smi::kZero;
   18617 }
   18618 
   18619 
   18620 template Smi*
   18621 OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::Next(
   18622     JSArray* value_array);
   18623 
   18624 template bool
   18625 OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::HasMore();
   18626 
   18627 template void
   18628 OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::MoveNext();
   18629 
   18630 template Object*
   18631 OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::CurrentKey();
   18632 
   18633 template void
   18634 OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::Transition();
   18635 
   18636 
   18637 template Smi*
   18638 OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::Next(
   18639     JSArray* value_array);
   18640 
   18641 template bool
   18642 OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::HasMore();
   18643 
   18644 template void
   18645 OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::MoveNext();
   18646 
   18647 template Object*
   18648 OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::CurrentKey();
   18649 
   18650 template void
   18651 OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::Transition();
   18652 
   18653 
   18654 void JSSet::Initialize(Handle<JSSet> set, Isolate* isolate) {
   18655   Handle<OrderedHashSet> table = isolate->factory()->NewOrderedHashSet();
   18656   set->set_table(*table);
   18657 }
   18658 
   18659 
   18660 void JSSet::Clear(Handle<JSSet> set) {
   18661   Handle<OrderedHashSet> table(OrderedHashSet::cast(set->table()));
   18662   table = OrderedHashSet::Clear(table);
   18663   set->set_table(*table);
   18664 }
   18665 
   18666 
   18667 void JSMap::Initialize(Handle<JSMap> map, Isolate* isolate) {
   18668   Handle<OrderedHashMap> table = isolate->factory()->NewOrderedHashMap();
   18669   map->set_table(*table);
   18670 }
   18671 
   18672 
   18673 void JSMap::Clear(Handle<JSMap> map) {
   18674   Handle<OrderedHashMap> table(OrderedHashMap::cast(map->table()));
   18675   table = OrderedHashMap::Clear(table);
   18676   map->set_table(*table);
   18677 }
   18678 
   18679 
   18680 void JSWeakCollection::Initialize(Handle<JSWeakCollection> weak_collection,
   18681                                   Isolate* isolate) {
   18682   Handle<ObjectHashTable> table = ObjectHashTable::New(isolate, 0);
   18683   weak_collection->set_table(*table);
   18684 }
   18685 
   18686 
   18687 void JSWeakCollection::Set(Handle<JSWeakCollection> weak_collection,
   18688                            Handle<Object> key, Handle<Object> value,
   18689                            int32_t hash) {
   18690   DCHECK(key->IsJSReceiver() || key->IsSymbol());
   18691   Handle<ObjectHashTable> table(
   18692       ObjectHashTable::cast(weak_collection->table()));
   18693   DCHECK(table->IsKey(*key));
   18694   Handle<ObjectHashTable> new_table =
   18695       ObjectHashTable::Put(table, key, value, hash);
   18696   weak_collection->set_table(*new_table);
   18697   if (*table != *new_table) {
   18698     // Zap the old table since we didn't record slots for its elements.
   18699     table->FillWithHoles(0, table->length());
   18700   }
   18701 }
   18702 
   18703 
   18704 bool JSWeakCollection::Delete(Handle<JSWeakCollection> weak_collection,
   18705                               Handle<Object> key, int32_t hash) {
   18706   DCHECK(key->IsJSReceiver() || key->IsSymbol());
   18707   Handle<ObjectHashTable> table(
   18708       ObjectHashTable::cast(weak_collection->table()));
   18709   DCHECK(table->IsKey(*key));
   18710   bool was_present = false;
   18711   Handle<ObjectHashTable> new_table =
   18712       ObjectHashTable::Remove(table, key, &was_present, hash);
   18713   weak_collection->set_table(*new_table);
   18714   if (*table != *new_table) {
   18715     // Zap the old table since we didn't record slots for its elements.
   18716     table->FillWithHoles(0, table->length());
   18717   }
   18718   return was_present;
   18719 }
   18720 
   18721 Handle<JSArray> JSWeakCollection::GetEntries(Handle<JSWeakCollection> holder,
   18722                                              int max_entries) {
   18723   Isolate* isolate = holder->GetIsolate();
   18724   Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
   18725   if (max_entries == 0 || max_entries > table->NumberOfElements()) {
   18726     max_entries = table->NumberOfElements();
   18727   }
   18728   int values_per_entry = holder->IsJSWeakMap() ? 2 : 1;
   18729   Handle<FixedArray> entries =
   18730       isolate->factory()->NewFixedArray(max_entries * values_per_entry);
   18731   // Recompute max_values because GC could have removed elements from the table.
   18732   if (max_entries > table->NumberOfElements()) {
   18733     max_entries = table->NumberOfElements();
   18734   }
   18735 
   18736   {
   18737     DisallowHeapAllocation no_gc;
   18738     int count = 0;
   18739     for (int i = 0;
   18740          count / values_per_entry < max_entries && i < table->Capacity(); i++) {
   18741       Handle<Object> key(table->KeyAt(i), isolate);
   18742       if (table->IsKey(isolate, *key)) {
   18743         entries->set(count++, *key);
   18744         if (values_per_entry > 1) {
   18745           Object* value = table->Lookup(key);
   18746           entries->set(count++, value);
   18747         }
   18748       }
   18749     }
   18750     DCHECK_EQ(max_entries * values_per_entry, count);
   18751   }
   18752   return isolate->factory()->NewJSArrayWithElements(entries);
   18753 }
   18754 
   18755 // Check if there is a break point at this source position.
   18756 bool DebugInfo::HasBreakPoint(int source_position) {
   18757   // Get the break point info object for this code offset.
   18758   Object* break_point_info = GetBreakPointInfo(source_position);
   18759 
   18760   // If there is no break point info object or no break points in the break
   18761   // point info object there is no break point at this code offset.
   18762   if (break_point_info->IsUndefined(GetIsolate())) return false;
   18763   return BreakPointInfo::cast(break_point_info)->GetBreakPointCount() > 0;
   18764 }
   18765 
   18766 // Get the break point info object for this source position.
   18767 Object* DebugInfo::GetBreakPointInfo(int source_position) {
   18768   Isolate* isolate = GetIsolate();
   18769   if (!break_points()->IsUndefined(isolate)) {
   18770     for (int i = 0; i < break_points()->length(); i++) {
   18771       if (!break_points()->get(i)->IsUndefined(isolate)) {
   18772         BreakPointInfo* break_point_info =
   18773             BreakPointInfo::cast(break_points()->get(i));
   18774         if (break_point_info->source_position() == source_position) {
   18775           return break_point_info;
   18776         }
   18777       }
   18778     }
   18779   }
   18780   return isolate->heap()->undefined_value();
   18781 }
   18782 
   18783 bool DebugInfo::ClearBreakPoint(Handle<DebugInfo> debug_info,
   18784                                 Handle<Object> break_point_object) {
   18785   Isolate* isolate = debug_info->GetIsolate();
   18786   if (debug_info->break_points()->IsUndefined(isolate)) return false;
   18787 
   18788   for (int i = 0; i < debug_info->break_points()->length(); i++) {
   18789     if (debug_info->break_points()->get(i)->IsUndefined(isolate)) continue;
   18790     Handle<BreakPointInfo> break_point_info = Handle<BreakPointInfo>(
   18791         BreakPointInfo::cast(debug_info->break_points()->get(i)), isolate);
   18792     if (BreakPointInfo::HasBreakPointObject(break_point_info,
   18793                                             break_point_object)) {
   18794       BreakPointInfo::ClearBreakPoint(break_point_info, break_point_object);
   18795       return true;
   18796     }
   18797   }
   18798   return false;
   18799 }
   18800 
   18801 void DebugInfo::SetBreakPoint(Handle<DebugInfo> debug_info, int source_position,
   18802                               Handle<Object> break_point_object) {
   18803   Isolate* isolate = debug_info->GetIsolate();
   18804   Handle<Object> break_point_info(
   18805       debug_info->GetBreakPointInfo(source_position), isolate);
   18806   if (!break_point_info->IsUndefined(isolate)) {
   18807     BreakPointInfo::SetBreakPoint(
   18808         Handle<BreakPointInfo>::cast(break_point_info),
   18809         break_point_object);
   18810     return;
   18811   }
   18812 
   18813   // Adding a new break point for a code offset which did not have any
   18814   // break points before. Try to find a free slot.
   18815   static const int kNoBreakPointInfo = -1;
   18816   int index = kNoBreakPointInfo;
   18817   for (int i = 0; i < debug_info->break_points()->length(); i++) {
   18818     if (debug_info->break_points()->get(i)->IsUndefined(isolate)) {
   18819       index = i;
   18820       break;
   18821     }
   18822   }
   18823   if (index == kNoBreakPointInfo) {
   18824     // No free slot - extend break point info array.
   18825     Handle<FixedArray> old_break_points = Handle<FixedArray>(
   18826         FixedArray::cast(debug_info->break_points()), isolate);
   18827     Handle<FixedArray> new_break_points =
   18828         isolate->factory()->NewFixedArray(
   18829             old_break_points->length() +
   18830             DebugInfo::kEstimatedNofBreakPointsInFunction);
   18831 
   18832     debug_info->set_break_points(*new_break_points);
   18833     for (int i = 0; i < old_break_points->length(); i++) {
   18834       new_break_points->set(i, old_break_points->get(i));
   18835     }
   18836     index = old_break_points->length();
   18837   }
   18838   DCHECK(index != kNoBreakPointInfo);
   18839 
   18840   // Allocate new BreakPointInfo object and set the break point.
   18841   Handle<BreakPointInfo> new_break_point_info =
   18842       isolate->factory()->NewBreakPointInfo(source_position);
   18843   BreakPointInfo::SetBreakPoint(new_break_point_info, break_point_object);
   18844   debug_info->break_points()->set(index, *new_break_point_info);
   18845 }
   18846 
   18847 // Get the break point objects for a source position.
   18848 Handle<Object> DebugInfo::GetBreakPointObjects(int source_position) {
   18849   Object* break_point_info = GetBreakPointInfo(source_position);
   18850   Isolate* isolate = GetIsolate();
   18851   if (break_point_info->IsUndefined(isolate)) {
   18852     return isolate->factory()->undefined_value();
   18853   }
   18854   return Handle<Object>(
   18855       BreakPointInfo::cast(break_point_info)->break_point_objects(), isolate);
   18856 }
   18857 
   18858 
   18859 // Get the total number of break points.
   18860 int DebugInfo::GetBreakPointCount() {
   18861   Isolate* isolate = GetIsolate();
   18862   if (break_points()->IsUndefined(isolate)) return 0;
   18863   int count = 0;
   18864   for (int i = 0; i < break_points()->length(); i++) {
   18865     if (!break_points()->get(i)->IsUndefined(isolate)) {
   18866       BreakPointInfo* break_point_info =
   18867           BreakPointInfo::cast(break_points()->get(i));
   18868       count += break_point_info->GetBreakPointCount();
   18869     }
   18870   }
   18871   return count;
   18872 }
   18873 
   18874 
   18875 Handle<Object> DebugInfo::FindBreakPointInfo(
   18876     Handle<DebugInfo> debug_info, Handle<Object> break_point_object) {
   18877   Isolate* isolate = debug_info->GetIsolate();
   18878   if (!debug_info->break_points()->IsUndefined(isolate)) {
   18879     for (int i = 0; i < debug_info->break_points()->length(); i++) {
   18880       if (!debug_info->break_points()->get(i)->IsUndefined(isolate)) {
   18881         Handle<BreakPointInfo> break_point_info = Handle<BreakPointInfo>(
   18882             BreakPointInfo::cast(debug_info->break_points()->get(i)), isolate);
   18883         if (BreakPointInfo::HasBreakPointObject(break_point_info,
   18884                                                 break_point_object)) {
   18885           return break_point_info;
   18886         }
   18887       }
   18888     }
   18889   }
   18890   return isolate->factory()->undefined_value();
   18891 }
   18892 
   18893 // Remove the specified break point object.
   18894 void BreakPointInfo::ClearBreakPoint(Handle<BreakPointInfo> break_point_info,
   18895                                      Handle<Object> break_point_object) {
   18896   Isolate* isolate = break_point_info->GetIsolate();
   18897   // If there are no break points just ignore.
   18898   if (break_point_info->break_point_objects()->IsUndefined(isolate)) return;
   18899   // If there is a single break point clear it if it is the same.
   18900   if (!break_point_info->break_point_objects()->IsFixedArray()) {
   18901     if (break_point_info->break_point_objects() == *break_point_object) {
   18902       break_point_info->set_break_point_objects(
   18903           isolate->heap()->undefined_value());
   18904     }
   18905     return;
   18906   }
   18907   // If there are multiple break points shrink the array
   18908   DCHECK(break_point_info->break_point_objects()->IsFixedArray());
   18909   Handle<FixedArray> old_array =
   18910       Handle<FixedArray>(
   18911           FixedArray::cast(break_point_info->break_point_objects()));
   18912   Handle<FixedArray> new_array =
   18913       isolate->factory()->NewFixedArray(old_array->length() - 1);
   18914   int found_count = 0;
   18915   for (int i = 0; i < old_array->length(); i++) {
   18916     if (old_array->get(i) == *break_point_object) {
   18917       DCHECK(found_count == 0);
   18918       found_count++;
   18919     } else {
   18920       new_array->set(i - found_count, old_array->get(i));
   18921     }
   18922   }
   18923   // If the break point was found in the list change it.
   18924   if (found_count > 0) break_point_info->set_break_point_objects(*new_array);
   18925 }
   18926 
   18927 
   18928 // Add the specified break point object.
   18929 void BreakPointInfo::SetBreakPoint(Handle<BreakPointInfo> break_point_info,
   18930                                    Handle<Object> break_point_object) {
   18931   Isolate* isolate = break_point_info->GetIsolate();
   18932 
   18933   // If there was no break point objects before just set it.
   18934   if (break_point_info->break_point_objects()->IsUndefined(isolate)) {
   18935     break_point_info->set_break_point_objects(*break_point_object);
   18936     return;
   18937   }
   18938   // If the break point object is the same as before just ignore.
   18939   if (break_point_info->break_point_objects() == *break_point_object) return;
   18940   // If there was one break point object before replace with array.
   18941   if (!break_point_info->break_point_objects()->IsFixedArray()) {
   18942     Handle<FixedArray> array = isolate->factory()->NewFixedArray(2);
   18943     array->set(0, break_point_info->break_point_objects());
   18944     array->set(1, *break_point_object);
   18945     break_point_info->set_break_point_objects(*array);
   18946     return;
   18947   }
   18948   // If there was more than one break point before extend array.
   18949   Handle<FixedArray> old_array =
   18950       Handle<FixedArray>(
   18951           FixedArray::cast(break_point_info->break_point_objects()));
   18952   Handle<FixedArray> new_array =
   18953       isolate->factory()->NewFixedArray(old_array->length() + 1);
   18954   for (int i = 0; i < old_array->length(); i++) {
   18955     // If the break point was there before just ignore.
   18956     if (old_array->get(i) == *break_point_object) return;
   18957     new_array->set(i, old_array->get(i));
   18958   }
   18959   // Add the new break point.
   18960   new_array->set(old_array->length(), *break_point_object);
   18961   break_point_info->set_break_point_objects(*new_array);
   18962 }
   18963 
   18964 
   18965 bool BreakPointInfo::HasBreakPointObject(
   18966     Handle<BreakPointInfo> break_point_info,
   18967     Handle<Object> break_point_object) {
   18968   // No break point.
   18969   Isolate* isolate = break_point_info->GetIsolate();
   18970   if (break_point_info->break_point_objects()->IsUndefined(isolate)) {
   18971     return false;
   18972   }
   18973   // Single break point.
   18974   if (!break_point_info->break_point_objects()->IsFixedArray()) {
   18975     return break_point_info->break_point_objects() == *break_point_object;
   18976   }
   18977   // Multiple break points.
   18978   FixedArray* array = FixedArray::cast(break_point_info->break_point_objects());
   18979   for (int i = 0; i < array->length(); i++) {
   18980     if (array->get(i) == *break_point_object) {
   18981       return true;
   18982     }
   18983   }
   18984   return false;
   18985 }
   18986 
   18987 
   18988 // Get the number of break points.
   18989 int BreakPointInfo::GetBreakPointCount() {
   18990   // No break point.
   18991   if (break_point_objects()->IsUndefined(GetIsolate())) return 0;
   18992   // Single break point.
   18993   if (!break_point_objects()->IsFixedArray()) return 1;
   18994   // Multiple break points.
   18995   return FixedArray::cast(break_point_objects())->length();
   18996 }
   18997 
   18998 
   18999 // static
   19000 MaybeHandle<JSDate> JSDate::New(Handle<JSFunction> constructor,
   19001                                 Handle<JSReceiver> new_target, double tv) {
   19002   Isolate* const isolate = constructor->GetIsolate();
   19003   Handle<JSObject> result;
   19004   ASSIGN_RETURN_ON_EXCEPTION(isolate, result,
   19005                              JSObject::New(constructor, new_target), JSDate);
   19006   if (-DateCache::kMaxTimeInMs <= tv && tv <= DateCache::kMaxTimeInMs) {
   19007     tv = DoubleToInteger(tv) + 0.0;
   19008   } else {
   19009     tv = std::numeric_limits<double>::quiet_NaN();
   19010   }
   19011   Handle<Object> value = isolate->factory()->NewNumber(tv);
   19012   Handle<JSDate>::cast(result)->SetValue(*value, std::isnan(tv));
   19013   return Handle<JSDate>::cast(result);
   19014 }
   19015 
   19016 
   19017 // static
   19018 double JSDate::CurrentTimeValue(Isolate* isolate) {
   19019   if (FLAG_log_timer_events || FLAG_prof_cpp) LOG(isolate, CurrentTimeEvent());
   19020 
   19021   // According to ECMA-262, section 15.9.1, page 117, the precision of
   19022   // the number in a Date object representing a particular instant in
   19023   // time is milliseconds. Therefore, we floor the result of getting
   19024   // the OS time.
   19025   return Floor(FLAG_verify_predictable
   19026                    ? isolate->heap()->MonotonicallyIncreasingTimeInMs()
   19027                    : base::OS::TimeCurrentMillis());
   19028 }
   19029 
   19030 
   19031 // static
   19032 Object* JSDate::GetField(Object* object, Smi* index) {
   19033   return JSDate::cast(object)->DoGetField(
   19034       static_cast<FieldIndex>(index->value()));
   19035 }
   19036 
   19037 
   19038 Object* JSDate::DoGetField(FieldIndex index) {
   19039   DCHECK(index != kDateValue);
   19040 
   19041   DateCache* date_cache = GetIsolate()->date_cache();
   19042 
   19043   if (index < kFirstUncachedField) {
   19044     Object* stamp = cache_stamp();
   19045     if (stamp != date_cache->stamp() && stamp->IsSmi()) {
   19046       // Since the stamp is not NaN, the value is also not NaN.
   19047       int64_t local_time_ms =
   19048           date_cache->ToLocal(static_cast<int64_t>(value()->Number()));
   19049       SetCachedFields(local_time_ms, date_cache);
   19050     }
   19051     switch (index) {
   19052       case kYear: return year();
   19053       case kMonth: return month();
   19054       case kDay: return day();
   19055       case kWeekday: return weekday();
   19056       case kHour: return hour();
   19057       case kMinute: return min();
   19058       case kSecond: return sec();
   19059       default: UNREACHABLE();
   19060     }
   19061   }
   19062 
   19063   if (index >= kFirstUTCField) {
   19064     return GetUTCField(index, value()->Number(), date_cache);
   19065   }
   19066 
   19067   double time = value()->Number();
   19068   if (std::isnan(time)) return GetIsolate()->heap()->nan_value();
   19069 
   19070   int64_t local_time_ms = date_cache->ToLocal(static_cast<int64_t>(time));
   19071   int days = DateCache::DaysFromTime(local_time_ms);
   19072 
   19073   if (index == kDays) return Smi::FromInt(days);
   19074 
   19075   int time_in_day_ms = DateCache::TimeInDay(local_time_ms, days);
   19076   if (index == kMillisecond) return Smi::FromInt(time_in_day_ms % 1000);
   19077   DCHECK(index == kTimeInDay);
   19078   return Smi::FromInt(time_in_day_ms);
   19079 }
   19080 
   19081 
   19082 Object* JSDate::GetUTCField(FieldIndex index,
   19083                             double value,
   19084                             DateCache* date_cache) {
   19085   DCHECK(index >= kFirstUTCField);
   19086 
   19087   if (std::isnan(value)) return GetIsolate()->heap()->nan_value();
   19088 
   19089   int64_t time_ms = static_cast<int64_t>(value);
   19090 
   19091   if (index == kTimezoneOffset) {
   19092     return Smi::FromInt(date_cache->TimezoneOffset(time_ms));
   19093   }
   19094 
   19095   int days = DateCache::DaysFromTime(time_ms);
   19096 
   19097   if (index == kWeekdayUTC) return Smi::FromInt(date_cache->Weekday(days));
   19098 
   19099   if (index <= kDayUTC) {
   19100     int year, month, day;
   19101     date_cache->YearMonthDayFromDays(days, &year, &month, &day);
   19102     if (index == kYearUTC) return Smi::FromInt(year);
   19103     if (index == kMonthUTC) return Smi::FromInt(month);
   19104     DCHECK(index == kDayUTC);
   19105     return Smi::FromInt(day);
   19106   }
   19107 
   19108   int time_in_day_ms = DateCache::TimeInDay(time_ms, days);
   19109   switch (index) {
   19110     case kHourUTC: return Smi::FromInt(time_in_day_ms / (60 * 60 * 1000));
   19111     case kMinuteUTC: return Smi::FromInt((time_in_day_ms / (60 * 1000)) % 60);
   19112     case kSecondUTC: return Smi::FromInt((time_in_day_ms / 1000) % 60);
   19113     case kMillisecondUTC: return Smi::FromInt(time_in_day_ms % 1000);
   19114     case kDaysUTC: return Smi::FromInt(days);
   19115     case kTimeInDayUTC: return Smi::FromInt(time_in_day_ms);
   19116     default: UNREACHABLE();
   19117   }
   19118 
   19119   UNREACHABLE();
   19120   return NULL;
   19121 }
   19122 
   19123 
   19124 // static
   19125 Handle<Object> JSDate::SetValue(Handle<JSDate> date, double v) {
   19126   Isolate* const isolate = date->GetIsolate();
   19127   Handle<Object> value = isolate->factory()->NewNumber(v);
   19128   bool value_is_nan = std::isnan(v);
   19129   date->SetValue(*value, value_is_nan);
   19130   return value;
   19131 }
   19132 
   19133 
   19134 void JSDate::SetValue(Object* value, bool is_value_nan) {
   19135   set_value(value);
   19136   if (is_value_nan) {
   19137     HeapNumber* nan = GetIsolate()->heap()->nan_value();
   19138     set_cache_stamp(nan, SKIP_WRITE_BARRIER);
   19139     set_year(nan, SKIP_WRITE_BARRIER);
   19140     set_month(nan, SKIP_WRITE_BARRIER);
   19141     set_day(nan, SKIP_WRITE_BARRIER);
   19142     set_hour(nan, SKIP_WRITE_BARRIER);
   19143     set_min(nan, SKIP_WRITE_BARRIER);
   19144     set_sec(nan, SKIP_WRITE_BARRIER);
   19145     set_weekday(nan, SKIP_WRITE_BARRIER);
   19146   } else {
   19147     set_cache_stamp(Smi::FromInt(DateCache::kInvalidStamp), SKIP_WRITE_BARRIER);
   19148   }
   19149 }
   19150 
   19151 
   19152 void JSDate::SetCachedFields(int64_t local_time_ms, DateCache* date_cache) {
   19153   int days = DateCache::DaysFromTime(local_time_ms);
   19154   int time_in_day_ms = DateCache::TimeInDay(local_time_ms, days);
   19155   int year, month, day;
   19156   date_cache->YearMonthDayFromDays(days, &year, &month, &day);
   19157   int weekday = date_cache->Weekday(days);
   19158   int hour = time_in_day_ms / (60 * 60 * 1000);
   19159   int min = (time_in_day_ms / (60 * 1000)) % 60;
   19160   int sec = (time_in_day_ms / 1000) % 60;
   19161   set_cache_stamp(date_cache->stamp());
   19162   set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER);
   19163   set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER);
   19164   set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER);
   19165   set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER);
   19166   set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER);
   19167   set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER);
   19168   set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER);
   19169 }
   19170 
   19171 namespace {
   19172 
   19173 Script* ScriptFromJSValue(Object* in) {
   19174   DCHECK(in->IsJSValue());
   19175   JSValue* jsvalue = JSValue::cast(in);
   19176   DCHECK(jsvalue->value()->IsScript());
   19177   return Script::cast(jsvalue->value());
   19178 }
   19179 
   19180 }  // namespace
   19181 
   19182 int JSMessageObject::GetLineNumber() const {
   19183   if (start_position() == -1) return Message::kNoLineNumberInfo;
   19184 
   19185   Handle<Script> the_script = handle(ScriptFromJSValue(script()));
   19186 
   19187   Script::PositionInfo info;
   19188   const Script::OffsetFlag offset_flag = Script::WITH_OFFSET;
   19189   if (!Script::GetPositionInfo(the_script, start_position(), &info,
   19190                                offset_flag)) {
   19191     return Message::kNoLineNumberInfo;
   19192   }
   19193 
   19194   return info.line + 1;
   19195 }
   19196 
   19197 int JSMessageObject::GetColumnNumber() const {
   19198   if (start_position() == -1) return -1;
   19199 
   19200   Handle<Script> the_script = handle(ScriptFromJSValue(script()));
   19201 
   19202   Script::PositionInfo info;
   19203   const Script::OffsetFlag offset_flag = Script::WITH_OFFSET;
   19204   if (!Script::GetPositionInfo(the_script, start_position(), &info,
   19205                                offset_flag)) {
   19206     return -1;
   19207   }
   19208 
   19209   return info.column;  // Note: No '+1' in contrast to GetLineNumber.
   19210 }
   19211 
   19212 Handle<String> JSMessageObject::GetSourceLine() const {
   19213   Handle<Script> the_script = handle(ScriptFromJSValue(script()));
   19214 
   19215   Isolate* isolate = the_script->GetIsolate();
   19216   if (the_script->type() == Script::TYPE_WASM) {
   19217     return isolate->factory()->empty_string();
   19218   }
   19219 
   19220   Script::PositionInfo info;
   19221   const Script::OffsetFlag offset_flag = Script::WITH_OFFSET;
   19222   if (!Script::GetPositionInfo(the_script, start_position(), &info,
   19223                                offset_flag)) {
   19224     return isolate->factory()->empty_string();
   19225   }
   19226 
   19227   Handle<String> src = handle(String::cast(the_script->source()), isolate);
   19228   return isolate->factory()->NewSubString(src, info.line_start, info.line_end);
   19229 }
   19230 
   19231 void JSArrayBuffer::Neuter() {
   19232   CHECK(is_neuterable());
   19233   CHECK(is_external());
   19234   set_backing_store(NULL);
   19235   set_byte_length(Smi::kZero);
   19236   set_was_neutered(true);
   19237   // Invalidate the neutering protector.
   19238   Isolate* const isolate = GetIsolate();
   19239   if (isolate->IsArrayBufferNeuteringIntact()) {
   19240     isolate->InvalidateArrayBufferNeuteringProtector();
   19241   }
   19242 }
   19243 
   19244 
   19245 void JSArrayBuffer::Setup(Handle<JSArrayBuffer> array_buffer, Isolate* isolate,
   19246                           bool is_external, void* data, size_t allocated_length,
   19247                           SharedFlag shared) {
   19248   DCHECK(array_buffer->GetInternalFieldCount() ==
   19249          v8::ArrayBuffer::kInternalFieldCount);
   19250   for (int i = 0; i < v8::ArrayBuffer::kInternalFieldCount; i++) {
   19251     array_buffer->SetInternalField(i, Smi::kZero);
   19252   }
   19253   array_buffer->set_bit_field(0);
   19254   array_buffer->set_is_external(is_external);
   19255   array_buffer->set_is_neuterable(shared == SharedFlag::kNotShared);
   19256   array_buffer->set_is_shared(shared == SharedFlag::kShared);
   19257 
   19258   Handle<Object> byte_length =
   19259       isolate->factory()->NewNumberFromSize(allocated_length);
   19260   CHECK(byte_length->IsSmi() || byte_length->IsHeapNumber());
   19261   array_buffer->set_byte_length(*byte_length);
   19262   // Initialize backing store at last to avoid handling of |JSArrayBuffers| that
   19263   // are currently being constructed in the |ArrayBufferTracker|. The
   19264   // registration method below handles the case of registering a buffer that has
   19265   // already been promoted.
   19266   array_buffer->set_backing_store(data);
   19267 
   19268   if (data && !is_external) {
   19269     isolate->heap()->RegisterNewArrayBuffer(*array_buffer);
   19270   }
   19271 }
   19272 
   19273 
   19274 bool JSArrayBuffer::SetupAllocatingData(Handle<JSArrayBuffer> array_buffer,
   19275                                         Isolate* isolate,
   19276                                         size_t allocated_length,
   19277                                         bool initialize, SharedFlag shared) {
   19278   void* data;
   19279   CHECK(isolate->array_buffer_allocator() != NULL);
   19280   // Prevent creating array buffers when serializing.
   19281   DCHECK(!isolate->serializer_enabled());
   19282   if (allocated_length != 0) {
   19283     if (initialize) {
   19284       data = isolate->array_buffer_allocator()->Allocate(allocated_length);
   19285     } else {
   19286       data = isolate->array_buffer_allocator()->AllocateUninitialized(
   19287           allocated_length);
   19288     }
   19289     if (data == NULL) return false;
   19290   } else {
   19291     data = NULL;
   19292   }
   19293 
   19294   JSArrayBuffer::Setup(array_buffer, isolate, false, data, allocated_length,
   19295                        shared);
   19296   return true;
   19297 }
   19298 
   19299 
   19300 Handle<JSArrayBuffer> JSTypedArray::MaterializeArrayBuffer(
   19301     Handle<JSTypedArray> typed_array) {
   19302 
   19303   Handle<Map> map(typed_array->map());
   19304   Isolate* isolate = typed_array->GetIsolate();
   19305 
   19306   DCHECK(IsFixedTypedArrayElementsKind(map->elements_kind()));
   19307 
   19308   Handle<FixedTypedArrayBase> fixed_typed_array(
   19309       FixedTypedArrayBase::cast(typed_array->elements()));
   19310 
   19311   Handle<JSArrayBuffer> buffer(JSArrayBuffer::cast(typed_array->buffer()),
   19312                                isolate);
   19313   void* backing_store =
   19314       isolate->array_buffer_allocator()->AllocateUninitialized(
   19315           fixed_typed_array->DataSize());
   19316   buffer->set_is_external(false);
   19317   DCHECK(buffer->byte_length()->IsSmi() ||
   19318          buffer->byte_length()->IsHeapNumber());
   19319   DCHECK(NumberToInt32(buffer->byte_length()) == fixed_typed_array->DataSize());
   19320   // Initialize backing store at last to avoid handling of |JSArrayBuffers| that
   19321   // are currently being constructed in the |ArrayBufferTracker|. The
   19322   // registration method below handles the case of registering a buffer that has
   19323   // already been promoted.
   19324   buffer->set_backing_store(backing_store);
   19325   isolate->heap()->RegisterNewArrayBuffer(*buffer);
   19326   memcpy(buffer->backing_store(),
   19327          fixed_typed_array->DataPtr(),
   19328          fixed_typed_array->DataSize());
   19329   Handle<FixedTypedArrayBase> new_elements =
   19330       isolate->factory()->NewFixedTypedArrayWithExternalPointer(
   19331           fixed_typed_array->length(), typed_array->type(),
   19332           static_cast<uint8_t*>(buffer->backing_store()));
   19333 
   19334   typed_array->set_elements(*new_elements);
   19335 
   19336   return buffer;
   19337 }
   19338 
   19339 
   19340 Handle<JSArrayBuffer> JSTypedArray::GetBuffer() {
   19341   Handle<JSArrayBuffer> array_buffer(JSArrayBuffer::cast(buffer()),
   19342                                      GetIsolate());
   19343   if (array_buffer->was_neutered() ||
   19344       array_buffer->backing_store() != nullptr) {
   19345     return array_buffer;
   19346   }
   19347   Handle<JSTypedArray> self(this);
   19348   return MaterializeArrayBuffer(self);
   19349 }
   19350 
   19351 Handle<PropertyCell> PropertyCell::InvalidateEntry(
   19352     Handle<GlobalDictionary> dictionary, int entry) {
   19353   Isolate* isolate = dictionary->GetIsolate();
   19354   // Swap with a copy.
   19355   DCHECK(dictionary->ValueAt(entry)->IsPropertyCell());
   19356   Handle<PropertyCell> cell(PropertyCell::cast(dictionary->ValueAt(entry)));
   19357   Handle<PropertyCell> new_cell = isolate->factory()->NewPropertyCell();
   19358   new_cell->set_value(cell->value());
   19359   dictionary->ValueAtPut(entry, *new_cell);
   19360   bool is_the_hole = cell->value()->IsTheHole(isolate);
   19361   // Cell is officially mutable henceforth.
   19362   PropertyDetails details = cell->property_details();
   19363   details = details.set_cell_type(is_the_hole ? PropertyCellType::kUninitialized
   19364                                               : PropertyCellType::kMutable);
   19365   new_cell->set_property_details(details);
   19366   // Old cell is ready for invalidation.
   19367   if (is_the_hole) {
   19368     cell->set_value(isolate->heap()->undefined_value());
   19369   } else {
   19370     cell->set_value(isolate->heap()->the_hole_value());
   19371   }
   19372   details = details.set_cell_type(PropertyCellType::kInvalidated);
   19373   cell->set_property_details(details);
   19374   cell->dependent_code()->DeoptimizeDependentCodeGroup(
   19375       isolate, DependentCode::kPropertyCellChangedGroup);
   19376   return new_cell;
   19377 }
   19378 
   19379 
   19380 PropertyCellConstantType PropertyCell::GetConstantType() {
   19381   if (value()->IsSmi()) return PropertyCellConstantType::kSmi;
   19382   return PropertyCellConstantType::kStableMap;
   19383 }
   19384 
   19385 
   19386 static bool RemainsConstantType(Handle<PropertyCell> cell,
   19387                                 Handle<Object> value) {
   19388   // TODO(dcarney): double->smi and smi->double transition from kConstant
   19389   if (cell->value()->IsSmi() && value->IsSmi()) {
   19390     return true;
   19391   } else if (cell->value()->IsHeapObject() && value->IsHeapObject()) {
   19392     return HeapObject::cast(cell->value())->map() ==
   19393                HeapObject::cast(*value)->map() &&
   19394            HeapObject::cast(*value)->map()->is_stable();
   19395   }
   19396   return false;
   19397 }
   19398 
   19399 
   19400 PropertyCellType PropertyCell::UpdatedType(Handle<PropertyCell> cell,
   19401                                            Handle<Object> value,
   19402                                            PropertyDetails details) {
   19403   PropertyCellType type = details.cell_type();
   19404   Isolate* isolate = cell->GetIsolate();
   19405   DCHECK(!value->IsTheHole(isolate));
   19406   if (cell->value()->IsTheHole(isolate)) {
   19407     switch (type) {
   19408       // Only allow a cell to transition once into constant state.
   19409       case PropertyCellType::kUninitialized:
   19410         if (value->IsUndefined(isolate)) return PropertyCellType::kUndefined;
   19411         return PropertyCellType::kConstant;
   19412       case PropertyCellType::kInvalidated:
   19413         return PropertyCellType::kMutable;
   19414       default:
   19415         UNREACHABLE();
   19416         return PropertyCellType::kMutable;
   19417     }
   19418   }
   19419   switch (type) {
   19420     case PropertyCellType::kUndefined:
   19421       return PropertyCellType::kConstant;
   19422     case PropertyCellType::kConstant:
   19423       if (*value == cell->value()) return PropertyCellType::kConstant;
   19424     // Fall through.
   19425     case PropertyCellType::kConstantType:
   19426       if (RemainsConstantType(cell, value)) {
   19427         return PropertyCellType::kConstantType;
   19428       }
   19429     // Fall through.
   19430     case PropertyCellType::kMutable:
   19431       return PropertyCellType::kMutable;
   19432   }
   19433   UNREACHABLE();
   19434   return PropertyCellType::kMutable;
   19435 }
   19436 
   19437 Handle<PropertyCell> PropertyCell::PrepareForValue(
   19438     Handle<GlobalDictionary> dictionary, int entry, Handle<Object> value,
   19439     PropertyDetails details) {
   19440   Isolate* isolate = dictionary->GetIsolate();
   19441   DCHECK(!value->IsTheHole(isolate));
   19442   DCHECK(dictionary->ValueAt(entry)->IsPropertyCell());
   19443   Handle<PropertyCell> cell(PropertyCell::cast(dictionary->ValueAt(entry)));
   19444   const PropertyDetails original_details = cell->property_details();
   19445   // Data accesses could be cached in ics or optimized code.
   19446   bool invalidate =
   19447       original_details.kind() == kData && details.kind() == kAccessor;
   19448   int index = original_details.dictionary_index();
   19449   PropertyCellType old_type = original_details.cell_type();
   19450   // Preserve the enumeration index unless the property was deleted or never
   19451   // initialized.
   19452   if (cell->value()->IsTheHole(isolate)) {
   19453     index = dictionary->NextEnumerationIndex();
   19454     dictionary->SetNextEnumerationIndex(index + 1);
   19455   }
   19456   DCHECK(index > 0);
   19457   details = details.set_index(index);
   19458 
   19459   PropertyCellType new_type = UpdatedType(cell, value, original_details);
   19460   if (invalidate) cell = PropertyCell::InvalidateEntry(dictionary, entry);
   19461 
   19462   // Install new property details.
   19463   details = details.set_cell_type(new_type);
   19464   cell->set_property_details(details);
   19465 
   19466   // Deopt when transitioning from a constant type.
   19467   if (!invalidate && (old_type != new_type ||
   19468                       original_details.IsReadOnly() != details.IsReadOnly())) {
   19469     cell->dependent_code()->DeoptimizeDependentCodeGroup(
   19470         isolate, DependentCode::kPropertyCellChangedGroup);
   19471   }
   19472   return cell;
   19473 }
   19474 
   19475 
   19476 // static
   19477 void PropertyCell::SetValueWithInvalidation(Handle<PropertyCell> cell,
   19478                                             Handle<Object> new_value) {
   19479   if (cell->value() != *new_value) {
   19480     cell->set_value(*new_value);
   19481     Isolate* isolate = cell->GetIsolate();
   19482     cell->dependent_code()->DeoptimizeDependentCodeGroup(
   19483         isolate, DependentCode::kPropertyCellChangedGroup);
   19484   }
   19485 }
   19486 
   19487 int JSGeneratorObject::source_position() const {
   19488   CHECK(is_suspended());
   19489   DCHECK(function()->shared()->HasBytecodeArray());
   19490   DCHECK(!function()->shared()->HasBaselineCode());
   19491   int code_offset = Smi::cast(input_or_debug_pos())->value();
   19492   // The stored bytecode offset is relative to a different base than what
   19493   // is used in the source position table, hence the subtraction.
   19494   code_offset -= BytecodeArray::kHeaderSize - kHeapObjectTag;
   19495   AbstractCode* code =
   19496       AbstractCode::cast(function()->shared()->bytecode_array());
   19497   return code->SourcePosition(code_offset);
   19498 }
   19499 
   19500 // static
   19501 AccessCheckInfo* AccessCheckInfo::Get(Isolate* isolate,
   19502                                       Handle<JSObject> receiver) {
   19503   DisallowHeapAllocation no_gc;
   19504   DCHECK(receiver->map()->is_access_check_needed());
   19505   Object* maybe_constructor = receiver->map()->GetConstructor();
   19506   // Might happen for a detached context.
   19507   if (!maybe_constructor->IsJSFunction()) return nullptr;
   19508   JSFunction* constructor = JSFunction::cast(maybe_constructor);
   19509   // Might happen for the debug context.
   19510   if (!constructor->shared()->IsApiFunction()) return nullptr;
   19511 
   19512   Object* data_obj =
   19513       constructor->shared()->get_api_func_data()->access_check_info();
   19514   if (data_obj->IsUndefined(isolate)) return nullptr;
   19515 
   19516   return AccessCheckInfo::cast(data_obj);
   19517 }
   19518 
   19519 bool JSReceiver::HasProxyInPrototype(Isolate* isolate) {
   19520   for (PrototypeIterator iter(isolate, this, kStartAtReceiver,
   19521                               PrototypeIterator::END_AT_NULL);
   19522        !iter.IsAtEnd(); iter.AdvanceIgnoringProxies()) {
   19523     if (iter.GetCurrent<Object>()->IsJSProxy()) return true;
   19524   }
   19525   return false;
   19526 }
   19527 
   19528 MaybeHandle<Object> JSModuleNamespace::GetExport(Handle<String> name) {
   19529   Isolate* isolate = name->GetIsolate();
   19530 
   19531   Handle<Object> object(module()->exports()->Lookup(name), isolate);
   19532   if (object->IsTheHole(isolate)) {
   19533     return isolate->factory()->undefined_value();
   19534   }
   19535 
   19536   Handle<Object> value(Handle<Cell>::cast(object)->value(), isolate);
   19537   if (value->IsTheHole(isolate)) {
   19538     THROW_NEW_ERROR(
   19539         isolate, NewReferenceError(MessageTemplate::kNotDefined, name), Object);
   19540   }
   19541 
   19542   return value;
   19543 }
   19544 
   19545 namespace {
   19546 
   19547 struct ModuleHandleHash {
   19548   V8_INLINE size_t operator()(Handle<Module> module) const {
   19549     return module->hash();
   19550   }
   19551 };
   19552 
   19553 struct ModuleHandleEqual {
   19554   V8_INLINE bool operator()(Handle<Module> lhs, Handle<Module> rhs) const {
   19555     return *lhs == *rhs;
   19556   }
   19557 };
   19558 
   19559 struct StringHandleHash {
   19560   V8_INLINE size_t operator()(Handle<String> string) const {
   19561     return string->Hash();
   19562   }
   19563 };
   19564 
   19565 struct StringHandleEqual {
   19566   V8_INLINE bool operator()(Handle<String> lhs, Handle<String> rhs) const {
   19567     return lhs->Equals(*rhs);
   19568   }
   19569 };
   19570 
   19571 class UnorderedStringSet
   19572     : public std::unordered_set<Handle<String>, StringHandleHash,
   19573                                 StringHandleEqual,
   19574                                 zone_allocator<Handle<String>>> {
   19575  public:
   19576   explicit UnorderedStringSet(Zone* zone)
   19577       : std::unordered_set<Handle<String>, StringHandleHash, StringHandleEqual,
   19578                            zone_allocator<Handle<String>>>(
   19579             2 /* bucket count */, StringHandleHash(), StringHandleEqual(),
   19580             zone_allocator<Handle<String>>(zone)) {}
   19581 };
   19582 
   19583 class UnorderedModuleSet
   19584     : public std::unordered_set<Handle<Module>, ModuleHandleHash,
   19585                                 ModuleHandleEqual,
   19586                                 zone_allocator<Handle<Module>>> {
   19587  public:
   19588   explicit UnorderedModuleSet(Zone* zone)
   19589       : std::unordered_set<Handle<Module>, ModuleHandleHash, ModuleHandleEqual,
   19590                            zone_allocator<Handle<Module>>>(
   19591             2 /* bucket count */, ModuleHandleHash(), ModuleHandleEqual(),
   19592             zone_allocator<Handle<Module>>(zone)) {}
   19593 };
   19594 
   19595 class UnorderedStringMap
   19596     : public std::unordered_map<
   19597           Handle<String>, Handle<Object>, StringHandleHash, StringHandleEqual,
   19598           zone_allocator<std::pair<const Handle<String>, Handle<Object>>>> {
   19599  public:
   19600   explicit UnorderedStringMap(Zone* zone)
   19601       : std::unordered_map<
   19602             Handle<String>, Handle<Object>, StringHandleHash, StringHandleEqual,
   19603             zone_allocator<std::pair<const Handle<String>, Handle<Object>>>>(
   19604             2 /* bucket count */, StringHandleHash(), StringHandleEqual(),
   19605             zone_allocator<std::pair<const Handle<String>, Handle<Object>>>(
   19606                 zone)) {}
   19607 };
   19608 
   19609 }  // anonymous namespace
   19610 
   19611 class Module::ResolveSet
   19612     : public std::unordered_map<
   19613           Handle<Module>, UnorderedStringSet*, ModuleHandleHash,
   19614           ModuleHandleEqual, zone_allocator<std::pair<const Handle<Module>,
   19615                                                       UnorderedStringSet*>>> {
   19616  public:
   19617   explicit ResolveSet(Zone* zone)
   19618       : std::unordered_map<Handle<Module>, UnorderedStringSet*,
   19619                            ModuleHandleHash, ModuleHandleEqual,
   19620                            zone_allocator<std::pair<const Handle<Module>,
   19621                                                     UnorderedStringSet*>>>(
   19622             2 /* bucket count */, ModuleHandleHash(), ModuleHandleEqual(),
   19623             zone_allocator<
   19624                 std::pair<const Handle<Module>, UnorderedStringSet*>>(zone)),
   19625         zone_(zone) {}
   19626 
   19627   Zone* zone() const { return zone_; }
   19628 
   19629  private:
   19630   Zone* zone_;
   19631 };
   19632 
   19633 namespace {
   19634 
   19635 int ExportIndex(int cell_index) {
   19636   DCHECK_EQ(ModuleDescriptor::GetCellIndexKind(cell_index),
   19637             ModuleDescriptor::kExport);
   19638   return cell_index - 1;
   19639 }
   19640 
   19641 int ImportIndex(int cell_index) {
   19642   DCHECK_EQ(ModuleDescriptor::GetCellIndexKind(cell_index),
   19643             ModuleDescriptor::kImport);
   19644   return -cell_index - 1;
   19645 }
   19646 
   19647 }  // anonymous namespace
   19648 
   19649 void Module::CreateIndirectExport(Handle<Module> module, Handle<String> name,
   19650                                   Handle<ModuleInfoEntry> entry) {
   19651   Isolate* isolate = module->GetIsolate();
   19652   Handle<ObjectHashTable> exports(module->exports(), isolate);
   19653   DCHECK(exports->Lookup(name)->IsTheHole(isolate));
   19654   exports = ObjectHashTable::Put(exports, name, entry);
   19655   module->set_exports(*exports);
   19656 }
   19657 
   19658 void Module::CreateExport(Handle<Module> module, int cell_index,
   19659                           Handle<FixedArray> names) {
   19660   DCHECK_LT(0, names->length());
   19661   Isolate* isolate = module->GetIsolate();
   19662 
   19663   Handle<Cell> cell =
   19664       isolate->factory()->NewCell(isolate->factory()->undefined_value());
   19665   module->regular_exports()->set(ExportIndex(cell_index), *cell);
   19666 
   19667   Handle<ObjectHashTable> exports(module->exports(), isolate);
   19668   for (int i = 0, n = names->length(); i < n; ++i) {
   19669     Handle<String> name(String::cast(names->get(i)), isolate);
   19670     DCHECK(exports->Lookup(name)->IsTheHole(isolate));
   19671     exports = ObjectHashTable::Put(exports, name, cell);
   19672   }
   19673   module->set_exports(*exports);
   19674 }
   19675 
   19676 Handle<Object> Module::LoadVariable(Handle<Module> module, int cell_index) {
   19677   Isolate* isolate = module->GetIsolate();
   19678   Handle<Object> object;
   19679   switch (ModuleDescriptor::GetCellIndexKind(cell_index)) {
   19680     case ModuleDescriptor::kImport:
   19681       object = handle(module->regular_imports()->get(ImportIndex(cell_index)),
   19682                       isolate);
   19683       break;
   19684     case ModuleDescriptor::kExport:
   19685       object = handle(module->regular_exports()->get(ExportIndex(cell_index)),
   19686                       isolate);
   19687       break;
   19688     case ModuleDescriptor::kInvalid:
   19689       UNREACHABLE();
   19690       break;
   19691   }
   19692   return handle(Handle<Cell>::cast(object)->value(), isolate);
   19693 }
   19694 
   19695 void Module::StoreVariable(Handle<Module> module, int cell_index,
   19696                            Handle<Object> value) {
   19697   Isolate* isolate = module->GetIsolate();
   19698   DCHECK_EQ(ModuleDescriptor::GetCellIndexKind(cell_index),
   19699             ModuleDescriptor::kExport);
   19700   Handle<Object> object(module->regular_exports()->get(ExportIndex(cell_index)),
   19701                         isolate);
   19702   Handle<Cell>::cast(object)->set_value(*value);
   19703 }
   19704 
   19705 MaybeHandle<Cell> Module::ResolveImport(Handle<Module> module,
   19706                                         Handle<String> name, int module_request,
   19707                                         MessageLocation loc, bool must_resolve,
   19708                                         Module::ResolveSet* resolve_set) {
   19709   Isolate* isolate = module->GetIsolate();
   19710   Handle<Module> requested_module(
   19711       Module::cast(module->requested_modules()->get(module_request)), isolate);
   19712   return Module::ResolveExport(requested_module, name, loc, must_resolve,
   19713                                resolve_set);
   19714 }
   19715 
   19716 MaybeHandle<Cell> Module::ResolveExport(Handle<Module> module,
   19717                                         Handle<String> name,
   19718                                         MessageLocation loc, bool must_resolve,
   19719                                         Module::ResolveSet* resolve_set) {
   19720   Isolate* isolate = module->GetIsolate();
   19721   Handle<Object> object(module->exports()->Lookup(name), isolate);
   19722   if (object->IsCell()) {
   19723     // Already resolved (e.g. because it's a local export).
   19724     return Handle<Cell>::cast(object);
   19725   }
   19726 
   19727   // Check for cycle before recursing.
   19728   {
   19729     // Attempt insertion with a null string set.
   19730     auto result = resolve_set->insert({module, nullptr});
   19731     UnorderedStringSet*& name_set = result.first->second;
   19732     if (result.second) {
   19733       // |module| wasn't in the map previously, so allocate a new name set.
   19734       Zone* zone = resolve_set->zone();
   19735       name_set =
   19736           new (zone->New(sizeof(UnorderedStringSet))) UnorderedStringSet(zone);
   19737     } else if (name_set->count(name)) {
   19738       // Cycle detected.
   19739       if (must_resolve) {
   19740         return isolate->Throw<Cell>(
   19741             isolate->factory()->NewSyntaxError(
   19742                 MessageTemplate::kCyclicModuleDependency, name),
   19743             &loc);
   19744       }
   19745       return MaybeHandle<Cell>();
   19746     }
   19747     name_set->insert(name);
   19748   }
   19749 
   19750   if (object->IsModuleInfoEntry()) {
   19751     // Not yet resolved indirect export.
   19752     Handle<ModuleInfoEntry> entry = Handle<ModuleInfoEntry>::cast(object);
   19753     Handle<String> import_name(String::cast(entry->import_name()), isolate);
   19754     Handle<Script> script(
   19755         Script::cast(JSFunction::cast(module->code())->shared()->script()),
   19756         isolate);
   19757     MessageLocation new_loc(script, entry->beg_pos(), entry->end_pos());
   19758 
   19759     Handle<Cell> cell;
   19760     if (!ResolveImport(module, import_name, entry->module_request(), new_loc,
   19761                        true, resolve_set)
   19762              .ToHandle(&cell)) {
   19763       DCHECK(isolate->has_pending_exception());
   19764       return MaybeHandle<Cell>();
   19765     }
   19766 
   19767     // The export table may have changed but the entry in question should be
   19768     // unchanged.
   19769     Handle<ObjectHashTable> exports(module->exports(), isolate);
   19770     DCHECK(exports->Lookup(name)->IsModuleInfoEntry());
   19771 
   19772     exports = ObjectHashTable::Put(exports, name, cell);
   19773     module->set_exports(*exports);
   19774     return cell;
   19775   }
   19776 
   19777   DCHECK(object->IsTheHole(isolate));
   19778   return Module::ResolveExportUsingStarExports(module, name, loc, must_resolve,
   19779                                                resolve_set);
   19780 }
   19781 
   19782 MaybeHandle<Cell> Module::ResolveExportUsingStarExports(
   19783     Handle<Module> module, Handle<String> name, MessageLocation loc,
   19784     bool must_resolve, Module::ResolveSet* resolve_set) {
   19785   Isolate* isolate = module->GetIsolate();
   19786   if (!name->Equals(isolate->heap()->default_string())) {
   19787     // Go through all star exports looking for the given name.  If multiple star
   19788     // exports provide the name, make sure they all map it to the same cell.
   19789     Handle<Cell> unique_cell;
   19790     Handle<FixedArray> special_exports(module->info()->special_exports(),
   19791                                        isolate);
   19792     for (int i = 0, n = special_exports->length(); i < n; ++i) {
   19793       i::Handle<i::ModuleInfoEntry> entry(
   19794           i::ModuleInfoEntry::cast(special_exports->get(i)), isolate);
   19795       if (!entry->export_name()->IsUndefined(isolate)) {
   19796         continue;  // Indirect export.
   19797       }
   19798 
   19799       Handle<Script> script(
   19800           Script::cast(JSFunction::cast(module->code())->shared()->script()),
   19801           isolate);
   19802       MessageLocation new_loc(script, entry->beg_pos(), entry->end_pos());
   19803 
   19804       Handle<Cell> cell;
   19805       if (ResolveImport(module, name, entry->module_request(), new_loc, false,
   19806                         resolve_set)
   19807               .ToHandle(&cell)) {
   19808         if (unique_cell.is_null()) unique_cell = cell;
   19809         if (*unique_cell != *cell) {
   19810           return isolate->Throw<Cell>(
   19811               isolate->factory()->NewSyntaxError(
   19812                   MessageTemplate::kAmbiguousExport, name),
   19813               &loc);
   19814         }
   19815       } else if (isolate->has_pending_exception()) {
   19816         return MaybeHandle<Cell>();
   19817       }
   19818     }
   19819 
   19820     if (!unique_cell.is_null()) {
   19821       // Found a unique star export for this name.
   19822       Handle<ObjectHashTable> exports(module->exports(), isolate);
   19823       DCHECK(exports->Lookup(name)->IsTheHole(isolate));
   19824       exports = ObjectHashTable::Put(exports, name, unique_cell);
   19825       module->set_exports(*exports);
   19826       return unique_cell;
   19827     }
   19828   }
   19829 
   19830   // Unresolvable.
   19831   if (must_resolve) {
   19832     return isolate->Throw<Cell>(isolate->factory()->NewSyntaxError(
   19833                                     MessageTemplate::kUnresolvableExport, name),
   19834                                 &loc);
   19835   }
   19836   return MaybeHandle<Cell>();
   19837 }
   19838 
   19839 bool Module::Instantiate(Handle<Module> module, v8::Local<v8::Context> context,
   19840                          v8::Module::ResolveCallback callback) {
   19841   if (module->instantiated()) return true;
   19842 
   19843   Isolate* isolate = module->GetIsolate();
   19844   Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(module->code()),
   19845                                     isolate);
   19846   Handle<JSFunction> function =
   19847       isolate->factory()->NewFunctionFromSharedFunctionInfo(
   19848           shared,
   19849           handle(Utils::OpenHandle(*context)->native_context(), isolate));
   19850   module->set_code(*function);
   19851   DCHECK(module->instantiated());
   19852 
   19853   Handle<ModuleInfo> module_info(shared->scope_info()->ModuleDescriptorInfo(),
   19854                                  isolate);
   19855 
   19856   // Set up local exports.
   19857   // TODO(neis): Create regular_exports array here instead of in factory method?
   19858   for (int i = 0, n = module_info->RegularExportCount(); i < n; ++i) {
   19859     int cell_index = module_info->RegularExportCellIndex(i);
   19860     Handle<FixedArray> export_names(module_info->RegularExportExportNames(i),
   19861                                     isolate);
   19862     CreateExport(module, cell_index, export_names);
   19863   }
   19864 
   19865   // Partially set up indirect exports.
   19866   // For each indirect export, we create the appropriate slot in the export
   19867   // table and store its ModuleInfoEntry there.  When we later find the correct
   19868   // Cell in the module that actually provides the value, we replace the
   19869   // ModuleInfoEntry by that Cell (see ResolveExport).
   19870   Handle<FixedArray> special_exports(module_info->special_exports(), isolate);
   19871   for (int i = 0, n = special_exports->length(); i < n; ++i) {
   19872     Handle<ModuleInfoEntry> entry(
   19873         ModuleInfoEntry::cast(special_exports->get(i)), isolate);
   19874     Handle<Object> export_name(entry->export_name(), isolate);
   19875     if (export_name->IsUndefined(isolate)) continue;  // Star export.
   19876     CreateIndirectExport(module, Handle<String>::cast(export_name), entry);
   19877   }
   19878 
   19879   Handle<FixedArray> module_requests(module_info->module_requests(), isolate);
   19880   for (int i = 0, length = module_requests->length(); i < length; ++i) {
   19881     Handle<String> specifier(String::cast(module_requests->get(i)), isolate);
   19882     v8::Local<v8::Module> api_requested_module;
   19883     // TODO(adamk): Revisit these failure cases once d8 knows how to
   19884     // persist a module_map across multiple top-level module loads, as
   19885     // the current module is left in a "half-instantiated" state.
   19886     if (!callback(context, v8::Utils::ToLocal(specifier),
   19887                   v8::Utils::ToLocal(module))
   19888              .ToLocal(&api_requested_module)) {
   19889       // TODO(adamk): Give this a better error message. But this is a
   19890       // misuse of the API anyway.
   19891       isolate->ThrowIllegalOperation();
   19892       return false;
   19893     }
   19894     Handle<Module> requested_module = Utils::OpenHandle(*api_requested_module);
   19895     module->requested_modules()->set(i, *requested_module);
   19896     if (!Instantiate(requested_module, context, callback)) {
   19897       return false;
   19898     }
   19899   }
   19900 
   19901   Zone zone(isolate->allocator(), ZONE_NAME);
   19902 
   19903   // Resolve imports.
   19904   Handle<FixedArray> regular_imports(module_info->regular_imports(), isolate);
   19905   for (int i = 0, n = regular_imports->length(); i < n; ++i) {
   19906     Handle<ModuleInfoEntry> entry(
   19907         ModuleInfoEntry::cast(regular_imports->get(i)), isolate);
   19908     Handle<String> name(String::cast(entry->import_name()), isolate);
   19909     Handle<Script> script(
   19910         Script::cast(JSFunction::cast(module->code())->shared()->script()),
   19911         isolate);
   19912     MessageLocation loc(script, entry->beg_pos(), entry->end_pos());
   19913     ResolveSet resolve_set(&zone);
   19914     Handle<Cell> cell;
   19915     if (!ResolveImport(module, name, entry->module_request(), loc, true,
   19916                        &resolve_set)
   19917              .ToHandle(&cell)) {
   19918       return false;
   19919     }
   19920     module->regular_imports()->set(ImportIndex(entry->cell_index()), *cell);
   19921   }
   19922 
   19923   // Resolve indirect exports.
   19924   for (int i = 0, n = special_exports->length(); i < n; ++i) {
   19925     Handle<ModuleInfoEntry> entry(
   19926         ModuleInfoEntry::cast(special_exports->get(i)), isolate);
   19927     Handle<Object> name(entry->export_name(), isolate);
   19928     if (name->IsUndefined(isolate)) continue;  // Star export.
   19929     Handle<Script> script(
   19930         Script::cast(JSFunction::cast(module->code())->shared()->script()),
   19931         isolate);
   19932     MessageLocation loc(script, entry->beg_pos(), entry->end_pos());
   19933     ResolveSet resolve_set(&zone);
   19934     if (ResolveExport(module, Handle<String>::cast(name), loc, true,
   19935                       &resolve_set)
   19936             .is_null()) {
   19937       return false;
   19938     }
   19939   }
   19940 
   19941   return true;
   19942 }
   19943 
   19944 MaybeHandle<Object> Module::Evaluate(Handle<Module> module) {
   19945   DCHECK(module->instantiated());
   19946 
   19947   // Each module can only be evaluated once.
   19948   Isolate* isolate = module->GetIsolate();
   19949   if (module->evaluated()) return isolate->factory()->undefined_value();
   19950   Handle<JSFunction> function(JSFunction::cast(module->code()), isolate);
   19951   module->set_evaluated();
   19952 
   19953   // Initialization.
   19954   DCHECK_EQ(MODULE_SCOPE, function->shared()->scope_info()->scope_type());
   19955   Handle<Object> receiver = isolate->factory()->undefined_value();
   19956   Handle<Object> argv[] = {module};
   19957   Handle<Object> generator;
   19958   ASSIGN_RETURN_ON_EXCEPTION(
   19959       isolate, generator,
   19960       Execution::Call(isolate, function, receiver, arraysize(argv), argv),
   19961       Object);
   19962 
   19963   // Recursion.
   19964   Handle<FixedArray> requested_modules(module->requested_modules(), isolate);
   19965   for (int i = 0, length = requested_modules->length(); i < length; ++i) {
   19966     Handle<Module> import(Module::cast(requested_modules->get(i)), isolate);
   19967     RETURN_ON_EXCEPTION(isolate, Evaluate(import), Object);
   19968   }
   19969 
   19970   // Evaluation of module body.
   19971   Handle<JSFunction> resume(
   19972       isolate->native_context()->generator_next_internal(), isolate);
   19973   return Execution::Call(isolate, resume, generator, 0, nullptr);
   19974 }
   19975 
   19976 namespace {
   19977 
   19978 void FetchStarExports(Handle<Module> module, Zone* zone,
   19979                       UnorderedModuleSet* visited) {
   19980   DCHECK(module->instantiated());
   19981 
   19982   bool cycle = !visited->insert(module).second;
   19983   if (cycle) return;
   19984 
   19985   Isolate* isolate = module->GetIsolate();
   19986   Handle<ObjectHashTable> exports(module->exports(), isolate);
   19987   UnorderedStringMap more_exports(zone);
   19988 
   19989   // TODO(neis): Only allocate more_exports if there are star exports.
   19990   // Maybe split special_exports into indirect_exports and star_exports.
   19991 
   19992   Handle<FixedArray> special_exports(module->info()->special_exports(),
   19993                                      isolate);
   19994   for (int i = 0, n = special_exports->length(); i < n; ++i) {
   19995     Handle<ModuleInfoEntry> entry(
   19996         ModuleInfoEntry::cast(special_exports->get(i)), isolate);
   19997     if (!entry->export_name()->IsUndefined(isolate)) {
   19998       continue;  // Indirect export.
   19999     }
   20000 
   20001     Handle<Module> requested_module(
   20002         Module::cast(module->requested_modules()->get(entry->module_request())),
   20003         isolate);
   20004 
   20005     // Recurse.
   20006     FetchStarExports(requested_module, zone, visited);
   20007 
   20008     // Collect all of [requested_module]'s exports that must be added to
   20009     // [module]'s exports (i.e. to [exports]).  We record these in
   20010     // [more_exports].  Ambiguities (conflicting exports) are marked by mapping
   20011     // the name to undefined instead of a Cell.
   20012     Handle<ObjectHashTable> requested_exports(requested_module->exports(),
   20013                                               isolate);
   20014     for (int i = 0, n = requested_exports->Capacity(); i < n; ++i) {
   20015       Handle<Object> key(requested_exports->KeyAt(i), isolate);
   20016       if (!requested_exports->IsKey(isolate, *key)) continue;
   20017       Handle<String> name = Handle<String>::cast(key);
   20018 
   20019       if (name->Equals(isolate->heap()->default_string())) continue;
   20020       if (!exports->Lookup(name)->IsTheHole(isolate)) continue;
   20021 
   20022       Handle<Cell> cell(Cell::cast(requested_exports->ValueAt(i)), isolate);
   20023       auto insert_result = more_exports.insert(std::make_pair(name, cell));
   20024       if (!insert_result.second) {
   20025         auto it = insert_result.first;
   20026         if (*it->second == *cell || it->second->IsUndefined(isolate)) {
   20027           // We already recorded this mapping before, or the name is already
   20028           // known to be ambiguous.  In either case, there's nothing to do.
   20029         } else {
   20030           DCHECK(it->second->IsCell());
   20031           // Different star exports provide different cells for this name, hence
   20032           // mark the name as ambiguous.
   20033           it->second = isolate->factory()->undefined_value();
   20034         }
   20035       }
   20036     }
   20037   }
   20038 
   20039   // Copy [more_exports] into [exports].
   20040   for (const auto& elem : more_exports) {
   20041     if (elem.second->IsUndefined(isolate)) continue;  // Ambiguous export.
   20042     DCHECK(!elem.first->Equals(isolate->heap()->default_string()));
   20043     DCHECK(elem.second->IsCell());
   20044     exports = ObjectHashTable::Put(exports, elem.first, elem.second);
   20045   }
   20046   module->set_exports(*exports);
   20047 }
   20048 
   20049 }  // anonymous namespace
   20050 
   20051 Handle<JSModuleNamespace> Module::GetModuleNamespace(Handle<Module> module,
   20052                                                      int module_request) {
   20053   Isolate* isolate = module->GetIsolate();
   20054   Handle<Module> requested_module(
   20055       Module::cast(module->requested_modules()->get(module_request)), isolate);
   20056   return Module::GetModuleNamespace(requested_module);
   20057 }
   20058 
   20059 Handle<JSModuleNamespace> Module::GetModuleNamespace(Handle<Module> module) {
   20060   Isolate* isolate = module->GetIsolate();
   20061 
   20062   Handle<HeapObject> object(module->module_namespace(), isolate);
   20063   if (!object->IsUndefined(isolate)) {
   20064     // Namespace object already exists.
   20065     return Handle<JSModuleNamespace>::cast(object);
   20066   }
   20067 
   20068   // Create the namespace object (initially empty).
   20069   Handle<JSModuleNamespace> ns = isolate->factory()->NewJSModuleNamespace();
   20070   ns->set_module(*module);
   20071   module->set_module_namespace(*ns);
   20072 
   20073   // Collect the export names.
   20074   Zone zone(isolate->allocator(), ZONE_NAME);
   20075   UnorderedModuleSet visited(&zone);
   20076   FetchStarExports(module, &zone, &visited);
   20077   Handle<ObjectHashTable> exports(module->exports(), isolate);
   20078   ZoneVector<Handle<String>> names(&zone);
   20079   names.reserve(exports->NumberOfElements());
   20080   for (int i = 0, n = exports->Capacity(); i < n; ++i) {
   20081     Handle<Object> key(exports->KeyAt(i), isolate);
   20082     if (!exports->IsKey(isolate, *key)) continue;
   20083     DCHECK(exports->ValueAt(i)->IsCell());
   20084     names.push_back(Handle<String>::cast(key));
   20085   }
   20086   DCHECK_EQ(static_cast<int>(names.size()), exports->NumberOfElements());
   20087 
   20088   // Sort them alphabetically.
   20089   struct {
   20090     bool operator()(Handle<String> a, Handle<String> b) {
   20091       return String::Compare(a, b) == ComparisonResult::kLessThan;
   20092     }
   20093   } StringLess;
   20094   std::sort(names.begin(), names.end(), StringLess);
   20095 
   20096   // Create the corresponding properties in the namespace object.
   20097   PropertyAttributes attr = DONT_DELETE;
   20098   for (const auto& name : names) {
   20099     JSObject::SetAccessor(
   20100         ns, Accessors::ModuleNamespaceEntryInfo(isolate, name, attr))
   20101         .Check();
   20102   }
   20103   JSObject::PreventExtensions(ns, THROW_ON_ERROR).ToChecked();
   20104 
   20105   return ns;
   20106 }
   20107 
   20108 MaybeHandle<Name> FunctionTemplateInfo::TryGetCachedPropertyName(
   20109     Isolate* isolate, Handle<Object> getter) {
   20110   if (getter->IsFunctionTemplateInfo()) {
   20111     Handle<FunctionTemplateInfo> fti =
   20112         Handle<FunctionTemplateInfo>::cast(getter);
   20113     // Check if the accessor uses a cached property.
   20114     if (!fti->cached_property_name()->IsTheHole(isolate)) {
   20115       return handle(Name::cast(fti->cached_property_name()));
   20116     }
   20117   }
   20118   return MaybeHandle<Name>();
   20119 }
   20120 
   20121 // static
   20122 ElementsKind JSArrayIterator::ElementsKindForInstanceType(InstanceType type) {
   20123   DCHECK_GE(type, FIRST_ARRAY_ITERATOR_TYPE);
   20124   DCHECK_LE(type, LAST_ARRAY_ITERATOR_TYPE);
   20125 
   20126   if (type <= LAST_ARRAY_KEY_ITERATOR_TYPE) {
   20127     // Should be ignored for key iterators.
   20128     return FAST_ELEMENTS;
   20129   } else {
   20130     ElementsKind kind;
   20131     if (type < FIRST_ARRAY_VALUE_ITERATOR_TYPE) {
   20132       // Convert `type` to a value iterator from an entries iterator
   20133       type = static_cast<InstanceType>(type +
   20134                                        (FIRST_ARRAY_VALUE_ITERATOR_TYPE -
   20135                                         FIRST_ARRAY_KEY_VALUE_ITERATOR_TYPE));
   20136       DCHECK_GE(type, FIRST_ARRAY_VALUE_ITERATOR_TYPE);
   20137       DCHECK_LE(type, LAST_ARRAY_ITERATOR_TYPE);
   20138     }
   20139 
   20140     if (type <= JS_UINT8_CLAMPED_ARRAY_VALUE_ITERATOR_TYPE) {
   20141       kind =
   20142           static_cast<ElementsKind>(FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND +
   20143                                     (type - FIRST_ARRAY_VALUE_ITERATOR_TYPE));
   20144       DCHECK_LE(kind, LAST_FIXED_TYPED_ARRAY_ELEMENTS_KIND);
   20145     } else if (type < JS_GENERIC_ARRAY_VALUE_ITERATOR_TYPE) {
   20146       kind = static_cast<ElementsKind>(
   20147           FIRST_FAST_ELEMENTS_KIND +
   20148           (type - JS_FAST_SMI_ARRAY_VALUE_ITERATOR_TYPE));
   20149       DCHECK_LE(kind, LAST_FAST_ELEMENTS_KIND);
   20150     } else {
   20151       // For any slow element cases, the actual elements kind is not known.
   20152       // Simply
   20153       // return a slow elements kind in this case. Users of this function must
   20154       // not
   20155       // depend on this.
   20156       return DICTIONARY_ELEMENTS;
   20157     }
   20158     DCHECK_LE(kind, LAST_ELEMENTS_KIND);
   20159     return kind;
   20160   }
   20161 }
   20162 
   20163 }  // namespace internal
   20164 }  // namespace v8
   20165