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/base/bits.h"
     22 #include "src/base/utils/random-number-generator.h"
     23 #include "src/bootstrapper.h"
     24 #include "src/code-stubs.h"
     25 #include "src/codegen.h"
     26 #include "src/compilation-dependencies.h"
     27 #include "src/compiler.h"
     28 #include "src/counters-inl.h"
     29 #include "src/counters.h"
     30 #include "src/date.h"
     31 #include "src/debug/debug.h"
     32 #include "src/deoptimizer.h"
     33 #include "src/elements.h"
     34 #include "src/execution.h"
     35 #include "src/field-index-inl.h"
     36 #include "src/field-index.h"
     37 #include "src/field-type.h"
     38 #include "src/frames-inl.h"
     39 #include "src/full-codegen/full-codegen.h"
     40 #include "src/globals.h"
     41 #include "src/ic/ic.h"
     42 #include "src/identity-map.h"
     43 #include "src/interpreter/bytecode-array-iterator.h"
     44 #include "src/interpreter/bytecode-decoder.h"
     45 #include "src/interpreter/interpreter.h"
     46 #include "src/isolate-inl.h"
     47 #include "src/keys.h"
     48 #include "src/list.h"
     49 #include "src/log.h"
     50 #include "src/lookup.h"
     51 #include "src/macro-assembler.h"
     52 #include "src/messages.h"
     53 #include "src/objects-body-descriptors-inl.h"
     54 #include "src/property-descriptor.h"
     55 #include "src/prototype.h"
     56 #include "src/regexp/jsregexp.h"
     57 #include "src/safepoint-table.h"
     58 #include "src/snapshot/code-serializer.h"
     59 #include "src/source-position-table.h"
     60 #include "src/string-builder.h"
     61 #include "src/string-search.h"
     62 #include "src/string-stream.h"
     63 #include "src/utils.h"
     64 #include "src/wasm/wasm-module.h"
     65 #include "src/wasm/wasm-objects.h"
     66 #include "src/zone/zone.h"
     67 
     68 #ifdef ENABLE_DISASSEMBLER
     69 #include "src/disasm.h"
     70 #include "src/disassembler.h"
     71 #include "src/eh-frame.h"
     72 #endif
     73 
     74 namespace v8 {
     75 namespace internal {
     76 
     77 std::ostream& operator<<(std::ostream& os, InstanceType instance_type) {
     78   switch (instance_type) {
     79 #define WRITE_TYPE(TYPE) \
     80   case TYPE:             \
     81     return os << #TYPE;
     82     INSTANCE_TYPE_LIST(WRITE_TYPE)
     83 #undef WRITE_TYPE
     84   }
     85   UNREACHABLE();
     86   return os << "UNKNOWN";  // Keep the compiler happy.
     87 }
     88 
     89 Handle<FieldType> Object::OptimalType(Isolate* isolate,
     90                                       Representation representation) {
     91   if (representation.IsNone()) return FieldType::None(isolate);
     92   if (FLAG_track_field_types) {
     93     if (representation.IsHeapObject() && IsHeapObject()) {
     94       // We can track only JavaScript objects with stable maps.
     95       Handle<Map> map(HeapObject::cast(this)->map(), isolate);
     96       if (map->is_stable() && map->IsJSReceiverMap()) {
     97         return FieldType::Class(map, isolate);
     98       }
     99     }
    100   }
    101   return FieldType::Any(isolate);
    102 }
    103 
    104 
    105 MaybeHandle<JSReceiver> Object::ToObject(Isolate* isolate,
    106                                          Handle<Object> object,
    107                                          Handle<Context> native_context) {
    108   if (object->IsJSReceiver()) return Handle<JSReceiver>::cast(object);
    109   Handle<JSFunction> constructor;
    110   if (object->IsSmi()) {
    111     constructor = handle(native_context->number_function(), isolate);
    112   } else {
    113     int constructor_function_index =
    114         Handle<HeapObject>::cast(object)->map()->GetConstructorFunctionIndex();
    115     if (constructor_function_index == Map::kNoConstructorFunctionIndex) {
    116       THROW_NEW_ERROR(isolate,
    117                       NewTypeError(MessageTemplate::kUndefinedOrNullToObject),
    118                       JSReceiver);
    119     }
    120     constructor = handle(
    121         JSFunction::cast(native_context->get(constructor_function_index)),
    122         isolate);
    123   }
    124   Handle<JSObject> result = isolate->factory()->NewJSObject(constructor);
    125   Handle<JSValue>::cast(result)->set_value(*object);
    126   return result;
    127 }
    128 
    129 // ES6 section 9.2.1.2, OrdinaryCallBindThis for sloppy callee.
    130 // static
    131 MaybeHandle<JSReceiver> Object::ConvertReceiver(Isolate* isolate,
    132                                                 Handle<Object> object) {
    133   if (object->IsJSReceiver()) return Handle<JSReceiver>::cast(object);
    134   if (*object == isolate->heap()->null_value() ||
    135       object->IsUndefined(isolate)) {
    136     return isolate->global_proxy();
    137   }
    138   return Object::ToObject(isolate, object);
    139 }
    140 
    141 // static
    142 MaybeHandle<Object> Object::ToNumber(Handle<Object> input) {
    143   while (true) {
    144     if (input->IsNumber()) {
    145       return input;
    146     }
    147     if (input->IsString()) {
    148       return String::ToNumber(Handle<String>::cast(input));
    149     }
    150     if (input->IsOddball()) {
    151       return Oddball::ToNumber(Handle<Oddball>::cast(input));
    152     }
    153     Isolate* const isolate = Handle<HeapObject>::cast(input)->GetIsolate();
    154     if (input->IsSymbol()) {
    155       THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kSymbolToNumber),
    156                       Object);
    157     }
    158     if (input->IsSimd128Value()) {
    159       THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kSimdToNumber),
    160                       Object);
    161     }
    162     ASSIGN_RETURN_ON_EXCEPTION(
    163         isolate, input, JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(input),
    164                                                 ToPrimitiveHint::kNumber),
    165         Object);
    166   }
    167 }
    168 
    169 
    170 // static
    171 MaybeHandle<Object> Object::ToInteger(Isolate* isolate, Handle<Object> input) {
    172   ASSIGN_RETURN_ON_EXCEPTION(isolate, input, ToNumber(input), Object);
    173   return isolate->factory()->NewNumber(DoubleToInteger(input->Number()));
    174 }
    175 
    176 
    177 // static
    178 MaybeHandle<Object> Object::ToInt32(Isolate* isolate, Handle<Object> input) {
    179   ASSIGN_RETURN_ON_EXCEPTION(isolate, input, ToNumber(input), Object);
    180   return isolate->factory()->NewNumberFromInt(DoubleToInt32(input->Number()));
    181 }
    182 
    183 
    184 // static
    185 MaybeHandle<Object> Object::ToUint32(Isolate* isolate, Handle<Object> input) {
    186   ASSIGN_RETURN_ON_EXCEPTION(isolate, input, ToNumber(input), Object);
    187   return isolate->factory()->NewNumberFromUint(DoubleToUint32(input->Number()));
    188 }
    189 
    190 
    191 // static
    192 MaybeHandle<Name> Object::ConvertToName(Isolate* isolate,
    193                                         Handle<Object> input) {
    194   ASSIGN_RETURN_ON_EXCEPTION(
    195       isolate, input, Object::ToPrimitive(input, ToPrimitiveHint::kString),
    196       Name);
    197   if (input->IsName()) return Handle<Name>::cast(input);
    198   return ToString(isolate, input);
    199 }
    200 
    201 // static
    202 MaybeHandle<String> Object::ToString(Isolate* isolate, Handle<Object> input) {
    203   while (true) {
    204     if (input->IsString()) {
    205       return Handle<String>::cast(input);
    206     }
    207     if (input->IsOddball()) {
    208       return handle(Handle<Oddball>::cast(input)->to_string(), isolate);
    209     }
    210     if (input->IsNumber()) {
    211       return isolate->factory()->NumberToString(input);
    212     }
    213     if (input->IsSymbol()) {
    214       THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kSymbolToString),
    215                       String);
    216     }
    217     if (input->IsSimd128Value()) {
    218       return Simd128Value::ToString(Handle<Simd128Value>::cast(input));
    219     }
    220     ASSIGN_RETURN_ON_EXCEPTION(
    221         isolate, input, JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(input),
    222                                                 ToPrimitiveHint::kString),
    223         String);
    224   }
    225 }
    226 
    227 namespace {
    228 
    229 bool IsErrorObject(Isolate* isolate, Handle<Object> object) {
    230   if (!object->IsJSReceiver()) return false;
    231   Handle<Symbol> symbol = isolate->factory()->stack_trace_symbol();
    232   return JSReceiver::HasOwnProperty(Handle<JSReceiver>::cast(object), symbol)
    233       .FromMaybe(false);
    234 }
    235 
    236 Handle<String> AsStringOrEmpty(Isolate* isolate, Handle<Object> object) {
    237   return object->IsString() ? Handle<String>::cast(object)
    238                             : isolate->factory()->empty_string();
    239 }
    240 
    241 Handle<String> NoSideEffectsErrorToString(Isolate* isolate,
    242                                           Handle<Object> input) {
    243   Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(input);
    244 
    245   Handle<Name> name_key = isolate->factory()->name_string();
    246   Handle<Object> name = JSReceiver::GetDataProperty(receiver, name_key);
    247   Handle<String> name_str = AsStringOrEmpty(isolate, name);
    248 
    249   Handle<Name> msg_key = isolate->factory()->message_string();
    250   Handle<Object> msg = JSReceiver::GetDataProperty(receiver, msg_key);
    251   Handle<String> msg_str = AsStringOrEmpty(isolate, msg);
    252 
    253   if (name_str->length() == 0) return msg_str;
    254   if (msg_str->length() == 0) return name_str;
    255 
    256   IncrementalStringBuilder builder(isolate);
    257   builder.AppendString(name_str);
    258   builder.AppendCString(": ");
    259   builder.AppendString(msg_str);
    260 
    261   return builder.Finish().ToHandleChecked();
    262 }
    263 
    264 }  // namespace
    265 
    266 // static
    267 Handle<String> Object::NoSideEffectsToString(Isolate* isolate,
    268                                              Handle<Object> input) {
    269   DisallowJavascriptExecution no_js(isolate);
    270 
    271   if (input->IsString() || input->IsNumber() || input->IsOddball() ||
    272       input->IsSimd128Value()) {
    273     return Object::ToString(isolate, input).ToHandleChecked();
    274   } else if (input->IsFunction()) {
    275     // -- F u n c t i o n
    276     Handle<String> fun_str;
    277     if (input->IsJSBoundFunction()) {
    278       fun_str = JSBoundFunction::ToString(Handle<JSBoundFunction>::cast(input));
    279     } else {
    280       DCHECK(input->IsJSFunction());
    281       fun_str = JSFunction::ToString(Handle<JSFunction>::cast(input));
    282     }
    283 
    284     if (fun_str->length() > 128) {
    285       IncrementalStringBuilder builder(isolate);
    286       builder.AppendString(isolate->factory()->NewSubString(fun_str, 0, 111));
    287       builder.AppendCString("...<omitted>...");
    288       builder.AppendString(isolate->factory()->NewSubString(
    289           fun_str, fun_str->length() - 2, fun_str->length()));
    290 
    291       return builder.Finish().ToHandleChecked();
    292     }
    293     return fun_str;
    294   } else if (input->IsSymbol()) {
    295     // -- S y m b o l
    296     Handle<Symbol> symbol = Handle<Symbol>::cast(input);
    297 
    298     IncrementalStringBuilder builder(isolate);
    299     builder.AppendCString("Symbol(");
    300     if (symbol->name()->IsString()) {
    301       builder.AppendString(handle(String::cast(symbol->name()), isolate));
    302     }
    303     builder.AppendCharacter(')');
    304 
    305     return builder.Finish().ToHandleChecked();
    306   } else if (input->IsJSReceiver()) {
    307     // -- J S R e c e i v e r
    308     Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(input);
    309     Handle<Object> to_string = JSReceiver::GetDataProperty(
    310         receiver, isolate->factory()->toString_string());
    311 
    312     if (IsErrorObject(isolate, input) ||
    313         *to_string == *isolate->error_to_string()) {
    314       // When internally formatting error objects, use a side-effects-free
    315       // version of Error.prototype.toString independent of the actually
    316       // installed toString method.
    317       return NoSideEffectsErrorToString(isolate, input);
    318     } else if (*to_string == *isolate->object_to_string()) {
    319       Handle<Object> ctor = JSReceiver::GetDataProperty(
    320           receiver, isolate->factory()->constructor_string());
    321       if (ctor->IsFunction()) {
    322         Handle<String> ctor_name;
    323         if (ctor->IsJSBoundFunction()) {
    324           ctor_name = JSBoundFunction::GetName(
    325                           isolate, Handle<JSBoundFunction>::cast(ctor))
    326                           .ToHandleChecked();
    327         } else if (ctor->IsJSFunction()) {
    328           Handle<Object> ctor_name_obj =
    329               JSFunction::GetName(isolate, Handle<JSFunction>::cast(ctor));
    330           ctor_name = AsStringOrEmpty(isolate, ctor_name_obj);
    331         }
    332 
    333         if (ctor_name->length() != 0) {
    334           IncrementalStringBuilder builder(isolate);
    335           builder.AppendCString("#<");
    336           builder.AppendString(ctor_name);
    337           builder.AppendCString(">");
    338 
    339           return builder.Finish().ToHandleChecked();
    340         }
    341       }
    342     }
    343   }
    344 
    345   // At this point, input is either none of the above or a JSReceiver.
    346 
    347   Handle<JSReceiver> receiver;
    348   if (input->IsJSReceiver()) {
    349     receiver = Handle<JSReceiver>::cast(input);
    350   } else {
    351     // This is the only case where Object::ToObject throws.
    352     DCHECK(!input->IsSmi());
    353     int constructor_function_index =
    354         Handle<HeapObject>::cast(input)->map()->GetConstructorFunctionIndex();
    355     if (constructor_function_index == Map::kNoConstructorFunctionIndex) {
    356       return isolate->factory()->NewStringFromAsciiChecked("[object Unknown]");
    357     }
    358 
    359     receiver = Object::ToObject(isolate, input, isolate->native_context())
    360                    .ToHandleChecked();
    361   }
    362 
    363   Handle<String> builtin_tag = handle(receiver->class_name(), isolate);
    364   Handle<Object> tag_obj = JSReceiver::GetDataProperty(
    365       receiver, isolate->factory()->to_string_tag_symbol());
    366   Handle<String> tag =
    367       tag_obj->IsString() ? Handle<String>::cast(tag_obj) : builtin_tag;
    368 
    369   IncrementalStringBuilder builder(isolate);
    370   builder.AppendCString("[object ");
    371   builder.AppendString(tag);
    372   builder.AppendCString("]");
    373 
    374   return builder.Finish().ToHandleChecked();
    375 }
    376 
    377 // static
    378 MaybeHandle<Object> Object::ToLength(Isolate* isolate, Handle<Object> input) {
    379   ASSIGN_RETURN_ON_EXCEPTION(isolate, input, ToNumber(input), Object);
    380   double len = DoubleToInteger(input->Number());
    381   if (len <= 0.0) {
    382     len = 0.0;
    383   } else if (len >= kMaxSafeInteger) {
    384     len = kMaxSafeInteger;
    385   }
    386   return isolate->factory()->NewNumber(len);
    387 }
    388 
    389 // static
    390 MaybeHandle<Object> Object::ToIndex(Isolate* isolate, Handle<Object> input,
    391                                     MessageTemplate::Template error_index) {
    392   if (input->IsUndefined(isolate)) return isolate->factory()->NewNumber(0.0);
    393   ASSIGN_RETURN_ON_EXCEPTION(isolate, input, ToNumber(input), Object);
    394   double len = DoubleToInteger(input->Number()) + 0.0;
    395   auto js_len = isolate->factory()->NewNumber(len);
    396   if (len < 0.0 || len > kMaxSafeInteger) {
    397     THROW_NEW_ERROR(isolate, NewRangeError(error_index, js_len), Object);
    398   }
    399   return js_len;
    400 }
    401 
    402 bool Object::BooleanValue() {
    403   if (IsSmi()) return Smi::cast(this)->value() != 0;
    404   DCHECK(IsHeapObject());
    405   Isolate* isolate = HeapObject::cast(this)->GetIsolate();
    406   if (IsBoolean()) return IsTrue(isolate);
    407   if (IsUndefined(isolate) || IsNull(isolate)) return false;
    408   if (IsUndetectable()) return false;  // Undetectable object is false.
    409   if (IsString()) return String::cast(this)->length() != 0;
    410   if (IsHeapNumber()) return HeapNumber::cast(this)->HeapNumberBooleanValue();
    411   return true;
    412 }
    413 
    414 
    415 namespace {
    416 
    417 // TODO(bmeurer): Maybe we should introduce a marker interface Number,
    418 // where we put all these methods at some point?
    419 ComparisonResult NumberCompare(double x, double y) {
    420   if (std::isnan(x) || std::isnan(y)) {
    421     return ComparisonResult::kUndefined;
    422   } else if (x < y) {
    423     return ComparisonResult::kLessThan;
    424   } else if (x > y) {
    425     return ComparisonResult::kGreaterThan;
    426   } else {
    427     return ComparisonResult::kEqual;
    428   }
    429 }
    430 
    431 
    432 bool NumberEquals(double x, double y) {
    433   // Must check explicitly for NaN's on Windows, but -0 works fine.
    434   if (std::isnan(x)) return false;
    435   if (std::isnan(y)) return false;
    436   return x == y;
    437 }
    438 
    439 
    440 bool NumberEquals(const Object* x, const Object* y) {
    441   return NumberEquals(x->Number(), y->Number());
    442 }
    443 
    444 
    445 bool NumberEquals(Handle<Object> x, Handle<Object> y) {
    446   return NumberEquals(*x, *y);
    447 }
    448 
    449 }  // namespace
    450 
    451 
    452 // static
    453 Maybe<ComparisonResult> Object::Compare(Handle<Object> x, Handle<Object> y) {
    454   // ES6 section 7.2.11 Abstract Relational Comparison step 3 and 4.
    455   if (!Object::ToPrimitive(x, ToPrimitiveHint::kNumber).ToHandle(&x) ||
    456       !Object::ToPrimitive(y, ToPrimitiveHint::kNumber).ToHandle(&y)) {
    457     return Nothing<ComparisonResult>();
    458   }
    459   if (x->IsString() && y->IsString()) {
    460     // ES6 section 7.2.11 Abstract Relational Comparison step 5.
    461     return Just(
    462         String::Compare(Handle<String>::cast(x), Handle<String>::cast(y)));
    463   }
    464   // ES6 section 7.2.11 Abstract Relational Comparison step 6.
    465   if (!Object::ToNumber(x).ToHandle(&x) || !Object::ToNumber(y).ToHandle(&y)) {
    466     return Nothing<ComparisonResult>();
    467   }
    468   return Just(NumberCompare(x->Number(), y->Number()));
    469 }
    470 
    471 
    472 // static
    473 Maybe<bool> Object::Equals(Handle<Object> x, Handle<Object> y) {
    474   // This is the generic version of Abstract Equality Comparison; a version in
    475   // JavaScript land is available in the EqualStub and NotEqualStub. Whenever
    476   // you change something functionality wise in here, remember to update the
    477   // TurboFan code stubs as well.
    478   while (true) {
    479     if (x->IsNumber()) {
    480       if (y->IsNumber()) {
    481         return Just(NumberEquals(x, y));
    482       } else if (y->IsBoolean()) {
    483         return Just(NumberEquals(*x, Handle<Oddball>::cast(y)->to_number()));
    484       } else if (y->IsString()) {
    485         return Just(NumberEquals(x, String::ToNumber(Handle<String>::cast(y))));
    486       } else if (y->IsJSReceiver()) {
    487         if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(y))
    488                  .ToHandle(&y)) {
    489           return Nothing<bool>();
    490         }
    491       } else {
    492         return Just(false);
    493       }
    494     } else if (x->IsString()) {
    495       if (y->IsString()) {
    496         return Just(
    497             String::Equals(Handle<String>::cast(x), Handle<String>::cast(y)));
    498       } else if (y->IsNumber()) {
    499         x = String::ToNumber(Handle<String>::cast(x));
    500         return Just(NumberEquals(x, y));
    501       } else if (y->IsBoolean()) {
    502         x = String::ToNumber(Handle<String>::cast(x));
    503         return Just(NumberEquals(*x, Handle<Oddball>::cast(y)->to_number()));
    504       } else if (y->IsJSReceiver()) {
    505         if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(y))
    506                  .ToHandle(&y)) {
    507           return Nothing<bool>();
    508         }
    509       } else {
    510         return Just(false);
    511       }
    512     } else if (x->IsBoolean()) {
    513       if (y->IsOddball()) {
    514         return Just(x.is_identical_to(y));
    515       } else if (y->IsNumber()) {
    516         return Just(NumberEquals(Handle<Oddball>::cast(x)->to_number(), *y));
    517       } else if (y->IsString()) {
    518         y = String::ToNumber(Handle<String>::cast(y));
    519         return Just(NumberEquals(Handle<Oddball>::cast(x)->to_number(), *y));
    520       } else if (y->IsJSReceiver()) {
    521         if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(y))
    522                  .ToHandle(&y)) {
    523           return Nothing<bool>();
    524         }
    525         x = Oddball::ToNumber(Handle<Oddball>::cast(x));
    526       } else {
    527         return Just(false);
    528       }
    529     } else if (x->IsSymbol()) {
    530       if (y->IsSymbol()) {
    531         return Just(x.is_identical_to(y));
    532       } else if (y->IsJSReceiver()) {
    533         if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(y))
    534                  .ToHandle(&y)) {
    535           return Nothing<bool>();
    536         }
    537       } else {
    538         return Just(false);
    539       }
    540     } else if (x->IsSimd128Value()) {
    541       if (y->IsSimd128Value()) {
    542         return Just(Simd128Value::Equals(Handle<Simd128Value>::cast(x),
    543                                          Handle<Simd128Value>::cast(y)));
    544       } else if (y->IsJSReceiver()) {
    545         if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(y))
    546                  .ToHandle(&y)) {
    547           return Nothing<bool>();
    548         }
    549       } else {
    550         return Just(false);
    551       }
    552     } else if (x->IsJSReceiver()) {
    553       if (y->IsJSReceiver()) {
    554         return Just(x.is_identical_to(y));
    555       } else if (y->IsUndetectable()) {
    556         return Just(x->IsUndetectable());
    557       } else if (y->IsBoolean()) {
    558         y = Oddball::ToNumber(Handle<Oddball>::cast(y));
    559       } else if (!JSReceiver::ToPrimitive(Handle<JSReceiver>::cast(x))
    560                       .ToHandle(&x)) {
    561         return Nothing<bool>();
    562       }
    563     } else {
    564       return Just(x->IsUndetectable() && y->IsUndetectable());
    565     }
    566   }
    567 }
    568 
    569 
    570 bool Object::StrictEquals(Object* that) {
    571   if (this->IsNumber()) {
    572     if (!that->IsNumber()) return false;
    573     return NumberEquals(this, that);
    574   } else if (this->IsString()) {
    575     if (!that->IsString()) return false;
    576     return String::cast(this)->Equals(String::cast(that));
    577   } else if (this->IsSimd128Value()) {
    578     if (!that->IsSimd128Value()) return false;
    579     return Simd128Value::cast(this)->Equals(Simd128Value::cast(that));
    580   }
    581   return this == that;
    582 }
    583 
    584 
    585 // static
    586 Handle<String> Object::TypeOf(Isolate* isolate, Handle<Object> object) {
    587   if (object->IsNumber()) return isolate->factory()->number_string();
    588   if (object->IsOddball()) return handle(Oddball::cast(*object)->type_of());
    589   if (object->IsUndetectable()) {
    590     return isolate->factory()->undefined_string();
    591   }
    592   if (object->IsString()) return isolate->factory()->string_string();
    593   if (object->IsSymbol()) return isolate->factory()->symbol_string();
    594   if (object->IsString()) return isolate->factory()->string_string();
    595 #define SIMD128_TYPE(TYPE, Type, type, lane_count, lane_type) \
    596   if (object->Is##Type()) return isolate->factory()->type##_string();
    597   SIMD128_TYPES(SIMD128_TYPE)
    598 #undef SIMD128_TYPE
    599   if (object->IsCallable()) return isolate->factory()->function_string();
    600   return isolate->factory()->object_string();
    601 }
    602 
    603 
    604 // static
    605 MaybeHandle<Object> Object::Multiply(Isolate* isolate, Handle<Object> lhs,
    606                                      Handle<Object> rhs) {
    607   if (!lhs->IsNumber() || !rhs->IsNumber()) {
    608     ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(lhs), Object);
    609     ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(rhs), Object);
    610   }
    611   return isolate->factory()->NewNumber(lhs->Number() * rhs->Number());
    612 }
    613 
    614 
    615 // static
    616 MaybeHandle<Object> Object::Divide(Isolate* isolate, Handle<Object> lhs,
    617                                    Handle<Object> rhs) {
    618   if (!lhs->IsNumber() || !rhs->IsNumber()) {
    619     ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(lhs), Object);
    620     ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(rhs), Object);
    621   }
    622   return isolate->factory()->NewNumber(lhs->Number() / rhs->Number());
    623 }
    624 
    625 
    626 // static
    627 MaybeHandle<Object> Object::Modulus(Isolate* isolate, Handle<Object> lhs,
    628                                     Handle<Object> rhs) {
    629   if (!lhs->IsNumber() || !rhs->IsNumber()) {
    630     ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(lhs), Object);
    631     ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(rhs), Object);
    632   }
    633   return isolate->factory()->NewNumber(modulo(lhs->Number(), rhs->Number()));
    634 }
    635 
    636 
    637 // static
    638 MaybeHandle<Object> Object::Add(Isolate* isolate, Handle<Object> lhs,
    639                                 Handle<Object> rhs) {
    640   if (lhs->IsNumber() && rhs->IsNumber()) {
    641     return isolate->factory()->NewNumber(lhs->Number() + rhs->Number());
    642   } else if (lhs->IsString() && rhs->IsString()) {
    643     return isolate->factory()->NewConsString(Handle<String>::cast(lhs),
    644                                              Handle<String>::cast(rhs));
    645   }
    646   ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToPrimitive(lhs), Object);
    647   ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToPrimitive(rhs), Object);
    648   if (lhs->IsString() || rhs->IsString()) {
    649     ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToString(isolate, rhs),
    650                                Object);
    651     ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToString(isolate, lhs),
    652                                Object);
    653     return isolate->factory()->NewConsString(Handle<String>::cast(lhs),
    654                                              Handle<String>::cast(rhs));
    655   }
    656   ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(rhs), Object);
    657   ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(lhs), Object);
    658   return isolate->factory()->NewNumber(lhs->Number() + rhs->Number());
    659 }
    660 
    661 
    662 // static
    663 MaybeHandle<Object> Object::Subtract(Isolate* isolate, Handle<Object> lhs,
    664                                      Handle<Object> rhs) {
    665   if (!lhs->IsNumber() || !rhs->IsNumber()) {
    666     ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(lhs), Object);
    667     ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(rhs), Object);
    668   }
    669   return isolate->factory()->NewNumber(lhs->Number() - rhs->Number());
    670 }
    671 
    672 
    673 // static
    674 MaybeHandle<Object> Object::ShiftLeft(Isolate* isolate, Handle<Object> lhs,
    675                                       Handle<Object> rhs) {
    676   if (!lhs->IsNumber() || !rhs->IsNumber()) {
    677     ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(lhs), Object);
    678     ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(rhs), Object);
    679   }
    680   return isolate->factory()->NewNumberFromInt(NumberToInt32(*lhs)
    681                                               << (NumberToUint32(*rhs) & 0x1F));
    682 }
    683 
    684 
    685 // static
    686 MaybeHandle<Object> Object::ShiftRight(Isolate* isolate, Handle<Object> lhs,
    687                                        Handle<Object> rhs) {
    688   if (!lhs->IsNumber() || !rhs->IsNumber()) {
    689     ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(lhs), Object);
    690     ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(rhs), Object);
    691   }
    692   return isolate->factory()->NewNumberFromInt(NumberToInt32(*lhs) >>
    693                                               (NumberToUint32(*rhs) & 0x1F));
    694 }
    695 
    696 
    697 // static
    698 MaybeHandle<Object> Object::ShiftRightLogical(Isolate* isolate,
    699                                               Handle<Object> lhs,
    700                                               Handle<Object> rhs) {
    701   if (!lhs->IsNumber() || !rhs->IsNumber()) {
    702     ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(lhs), Object);
    703     ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(rhs), Object);
    704   }
    705   return isolate->factory()->NewNumberFromUint(NumberToUint32(*lhs) >>
    706                                                (NumberToUint32(*rhs) & 0x1F));
    707 }
    708 
    709 
    710 // static
    711 MaybeHandle<Object> Object::BitwiseAnd(Isolate* isolate, Handle<Object> lhs,
    712                                        Handle<Object> rhs) {
    713   if (!lhs->IsNumber() || !rhs->IsNumber()) {
    714     ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(lhs), Object);
    715     ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(rhs), Object);
    716   }
    717   return isolate->factory()->NewNumberFromInt(NumberToInt32(*lhs) &
    718                                               NumberToInt32(*rhs));
    719 }
    720 
    721 
    722 // static
    723 MaybeHandle<Object> Object::BitwiseOr(Isolate* isolate, Handle<Object> lhs,
    724                                       Handle<Object> rhs) {
    725   if (!lhs->IsNumber() || !rhs->IsNumber()) {
    726     ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(lhs), Object);
    727     ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(rhs), Object);
    728   }
    729   return isolate->factory()->NewNumberFromInt(NumberToInt32(*lhs) |
    730                                               NumberToInt32(*rhs));
    731 }
    732 
    733 
    734 // static
    735 MaybeHandle<Object> Object::BitwiseXor(Isolate* isolate, Handle<Object> lhs,
    736                                        Handle<Object> rhs) {
    737   if (!lhs->IsNumber() || !rhs->IsNumber()) {
    738     ASSIGN_RETURN_ON_EXCEPTION(isolate, lhs, Object::ToNumber(lhs), Object);
    739     ASSIGN_RETURN_ON_EXCEPTION(isolate, rhs, Object::ToNumber(rhs), Object);
    740   }
    741   return isolate->factory()->NewNumberFromInt(NumberToInt32(*lhs) ^
    742                                               NumberToInt32(*rhs));
    743 }
    744 
    745 // static
    746 MaybeHandle<Object> Object::OrdinaryHasInstance(Isolate* isolate,
    747                                                 Handle<Object> callable,
    748                                                 Handle<Object> object) {
    749   // The {callable} must have a [[Call]] internal method.
    750   if (!callable->IsCallable()) return isolate->factory()->false_value();
    751 
    752   // Check if {callable} is a bound function, and if so retrieve its
    753   // [[BoundTargetFunction]] and use that instead of {callable}.
    754   if (callable->IsJSBoundFunction()) {
    755     Handle<Object> bound_callable(
    756         Handle<JSBoundFunction>::cast(callable)->bound_target_function(),
    757         isolate);
    758     return Object::InstanceOf(isolate, object, bound_callable);
    759   }
    760 
    761   // If {object} is not a receiver, return false.
    762   if (!object->IsJSReceiver()) return isolate->factory()->false_value();
    763 
    764   // Get the "prototype" of {callable}; raise an error if it's not a receiver.
    765   Handle<Object> prototype;
    766   ASSIGN_RETURN_ON_EXCEPTION(
    767       isolate, prototype,
    768       Object::GetProperty(callable, isolate->factory()->prototype_string()),
    769       Object);
    770   if (!prototype->IsJSReceiver()) {
    771     THROW_NEW_ERROR(
    772         isolate,
    773         NewTypeError(MessageTemplate::kInstanceofNonobjectProto, prototype),
    774         Object);
    775   }
    776 
    777   // Return whether or not {prototype} is in the prototype chain of {object}.
    778   Maybe<bool> result = JSReceiver::HasInPrototypeChain(
    779       isolate, Handle<JSReceiver>::cast(object), prototype);
    780   if (result.IsNothing()) return MaybeHandle<Object>();
    781   return isolate->factory()->ToBoolean(result.FromJust());
    782 }
    783 
    784 // static
    785 MaybeHandle<Object> Object::InstanceOf(Isolate* isolate, Handle<Object> object,
    786                                        Handle<Object> callable) {
    787   // The {callable} must be a receiver.
    788   if (!callable->IsJSReceiver()) {
    789     THROW_NEW_ERROR(isolate,
    790                     NewTypeError(MessageTemplate::kNonObjectInInstanceOfCheck),
    791                     Object);
    792   }
    793 
    794   // Lookup the @@hasInstance method on {callable}.
    795   Handle<Object> inst_of_handler;
    796   ASSIGN_RETURN_ON_EXCEPTION(
    797       isolate, inst_of_handler,
    798       JSReceiver::GetMethod(Handle<JSReceiver>::cast(callable),
    799                             isolate->factory()->has_instance_symbol()),
    800       Object);
    801   if (!inst_of_handler->IsUndefined(isolate)) {
    802     // Call the {inst_of_handler} on the {callable}.
    803     Handle<Object> result;
    804     ASSIGN_RETURN_ON_EXCEPTION(
    805         isolate, result,
    806         Execution::Call(isolate, inst_of_handler, callable, 1, &object),
    807         Object);
    808     return isolate->factory()->ToBoolean(result->BooleanValue());
    809   }
    810 
    811   // The {callable} must have a [[Call]] internal method.
    812   if (!callable->IsCallable()) {
    813     THROW_NEW_ERROR(
    814         isolate, NewTypeError(MessageTemplate::kNonCallableInInstanceOfCheck),
    815         Object);
    816   }
    817 
    818   // Fall back to OrdinaryHasInstance with {callable} and {object}.
    819   Handle<Object> result;
    820   ASSIGN_RETURN_ON_EXCEPTION(
    821       isolate, result,
    822       JSReceiver::OrdinaryHasInstance(isolate, callable, object), Object);
    823   return result;
    824 }
    825 
    826 Maybe<bool> Object::IsArray(Handle<Object> object) {
    827   if (object->IsJSArray()) return Just(true);
    828   if (object->IsJSProxy()) {
    829     Handle<JSProxy> proxy = Handle<JSProxy>::cast(object);
    830     Isolate* isolate = proxy->GetIsolate();
    831     if (proxy->IsRevoked()) {
    832       isolate->Throw(*isolate->factory()->NewTypeError(
    833           MessageTemplate::kProxyRevoked,
    834           isolate->factory()->NewStringFromAsciiChecked("IsArray")));
    835       return Nothing<bool>();
    836     }
    837     return Object::IsArray(handle(proxy->target(), isolate));
    838   }
    839   return Just(false);
    840 }
    841 
    842 
    843 // static
    844 MaybeHandle<Object> Object::GetMethod(Handle<JSReceiver> receiver,
    845                                       Handle<Name> name) {
    846   Handle<Object> func;
    847   Isolate* isolate = receiver->GetIsolate();
    848   ASSIGN_RETURN_ON_EXCEPTION(isolate, func,
    849                              JSReceiver::GetProperty(receiver, name), Object);
    850   if (func->IsNull(isolate) || func->IsUndefined(isolate)) {
    851     return isolate->factory()->undefined_value();
    852   }
    853   if (!func->IsCallable()) {
    854     THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kPropertyNotFunction,
    855                                           func, name, receiver),
    856                     Object);
    857   }
    858   return func;
    859 }
    860 
    861 
    862 // static
    863 MaybeHandle<FixedArray> Object::CreateListFromArrayLike(
    864     Isolate* isolate, Handle<Object> object, ElementTypes element_types) {
    865   // 1. ReturnIfAbrupt(object).
    866   // 2. (default elementTypes -- not applicable.)
    867   // 3. If Type(obj) is not Object, throw a TypeError exception.
    868   if (!object->IsJSReceiver()) {
    869     THROW_NEW_ERROR(isolate,
    870                     NewTypeError(MessageTemplate::kCalledOnNonObject,
    871                                  isolate->factory()->NewStringFromAsciiChecked(
    872                                      "CreateListFromArrayLike")),
    873                     FixedArray);
    874   }
    875   // 4. Let len be ? ToLength(? Get(obj, "length")).
    876   Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(object);
    877   Handle<Object> raw_length_number;
    878   ASSIGN_RETURN_ON_EXCEPTION(isolate, raw_length_number,
    879                              Object::GetLengthFromArrayLike(isolate, receiver),
    880                              FixedArray);
    881   uint32_t len;
    882   if (!raw_length_number->ToUint32(&len) ||
    883       len > static_cast<uint32_t>(FixedArray::kMaxLength)) {
    884     THROW_NEW_ERROR(isolate,
    885                     NewRangeError(MessageTemplate::kInvalidArrayLength),
    886                     FixedArray);
    887   }
    888   // 5. Let list be an empty List.
    889   Handle<FixedArray> list = isolate->factory()->NewFixedArray(len);
    890   // 6. Let index be 0.
    891   // 7. Repeat while index < len:
    892   for (uint32_t index = 0; index < len; ++index) {
    893     // 7a. Let indexName be ToString(index).
    894     // 7b. Let next be ? Get(obj, indexName).
    895     Handle<Object> next;
    896     ASSIGN_RETURN_ON_EXCEPTION(isolate, next,
    897                                JSReceiver::GetElement(isolate, receiver, index),
    898                                FixedArray);
    899     switch (element_types) {
    900       case ElementTypes::kAll:
    901         // Nothing to do.
    902         break;
    903       case ElementTypes::kStringAndSymbol: {
    904         // 7c. If Type(next) is not an element of elementTypes, throw a
    905         //     TypeError exception.
    906         if (!next->IsName()) {
    907           THROW_NEW_ERROR(isolate,
    908                           NewTypeError(MessageTemplate::kNotPropertyName, next),
    909                           FixedArray);
    910         }
    911         // 7d. Append next as the last element of list.
    912         // Internalize on the fly so we can use pointer identity later.
    913         next = isolate->factory()->InternalizeName(Handle<Name>::cast(next));
    914         break;
    915       }
    916     }
    917     list->set(index, *next);
    918     // 7e. Set index to index + 1. (See loop header.)
    919   }
    920   // 8. Return list.
    921   return list;
    922 }
    923 
    924 
    925 // static
    926 MaybeHandle<Object> Object::GetLengthFromArrayLike(Isolate* isolate,
    927                                                    Handle<Object> object) {
    928   Handle<Object> val;
    929   Handle<Object> key = isolate->factory()->length_string();
    930   ASSIGN_RETURN_ON_EXCEPTION(
    931       isolate, val, Runtime::GetObjectProperty(isolate, object, key), Object);
    932   return Object::ToLength(isolate, val);
    933 }
    934 
    935 // static
    936 Maybe<bool> JSReceiver::HasProperty(LookupIterator* it) {
    937   for (; it->IsFound(); it->Next()) {
    938     switch (it->state()) {
    939       case LookupIterator::NOT_FOUND:
    940       case LookupIterator::TRANSITION:
    941         UNREACHABLE();
    942       case LookupIterator::JSPROXY:
    943         return JSProxy::HasProperty(it->isolate(), it->GetHolder<JSProxy>(),
    944                                     it->GetName());
    945       case LookupIterator::INTERCEPTOR: {
    946         Maybe<PropertyAttributes> result =
    947             JSObject::GetPropertyAttributesWithInterceptor(it);
    948         if (result.IsNothing()) return Nothing<bool>();
    949         if (result.FromJust() != ABSENT) return Just(true);
    950         break;
    951       }
    952       case LookupIterator::ACCESS_CHECK: {
    953         if (it->HasAccess()) break;
    954         Maybe<PropertyAttributes> result =
    955             JSObject::GetPropertyAttributesWithFailedAccessCheck(it);
    956         if (result.IsNothing()) return Nothing<bool>();
    957         return Just(result.FromJust() != ABSENT);
    958       }
    959       case LookupIterator::INTEGER_INDEXED_EXOTIC:
    960         // TypedArray out-of-bounds access.
    961         return Just(false);
    962       case LookupIterator::ACCESSOR:
    963       case LookupIterator::DATA:
    964         return Just(true);
    965     }
    966   }
    967   return Just(false);
    968 }
    969 
    970 
    971 // static
    972 MaybeHandle<Object> Object::GetProperty(LookupIterator* it) {
    973   for (; it->IsFound(); it->Next()) {
    974     switch (it->state()) {
    975       case LookupIterator::NOT_FOUND:
    976       case LookupIterator::TRANSITION:
    977         UNREACHABLE();
    978       case LookupIterator::JSPROXY: {
    979         bool was_found;
    980         MaybeHandle<Object> result =
    981             JSProxy::GetProperty(it->isolate(), it->GetHolder<JSProxy>(),
    982                                  it->GetName(), it->GetReceiver(), &was_found);
    983         if (!was_found) it->NotFound();
    984         return result;
    985       }
    986       case LookupIterator::INTERCEPTOR: {
    987         bool done;
    988         Handle<Object> result;
    989         ASSIGN_RETURN_ON_EXCEPTION(
    990             it->isolate(), result,
    991             JSObject::GetPropertyWithInterceptor(it, &done), Object);
    992         if (done) return result;
    993         break;
    994       }
    995       case LookupIterator::ACCESS_CHECK:
    996         if (it->HasAccess()) break;
    997         return JSObject::GetPropertyWithFailedAccessCheck(it);
    998       case LookupIterator::ACCESSOR:
    999         return GetPropertyWithAccessor(it);
   1000       case LookupIterator::INTEGER_INDEXED_EXOTIC:
   1001         return it->isolate()->factory()->undefined_value();
   1002       case LookupIterator::DATA:
   1003         return it->GetDataValue();
   1004     }
   1005   }
   1006   return it->isolate()->factory()->undefined_value();
   1007 }
   1008 
   1009 
   1010 // static
   1011 MaybeHandle<Object> JSProxy::GetProperty(Isolate* isolate,
   1012                                          Handle<JSProxy> proxy,
   1013                                          Handle<Name> name,
   1014                                          Handle<Object> receiver,
   1015                                          bool* was_found) {
   1016   *was_found = true;
   1017   if (receiver->IsJSGlobalObject()) {
   1018     THROW_NEW_ERROR(
   1019         isolate,
   1020         NewTypeError(MessageTemplate::kReadGlobalReferenceThroughProxy, name),
   1021         Object);
   1022   }
   1023 
   1024   DCHECK(!name->IsPrivate());
   1025   STACK_CHECK(isolate, MaybeHandle<Object>());
   1026   Handle<Name> trap_name = isolate->factory()->get_string();
   1027   // 1. Assert: IsPropertyKey(P) is true.
   1028   // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O.
   1029   Handle<Object> handler(proxy->handler(), isolate);
   1030   // 3. If handler is null, throw a TypeError exception.
   1031   // 4. Assert: Type(handler) is Object.
   1032   if (proxy->IsRevoked()) {
   1033     THROW_NEW_ERROR(isolate,
   1034                     NewTypeError(MessageTemplate::kProxyRevoked, trap_name),
   1035                     Object);
   1036   }
   1037   // 5. Let target be the value of the [[ProxyTarget]] internal slot of O.
   1038   Handle<JSReceiver> target(proxy->target(), isolate);
   1039   // 6. Let trap be ? GetMethod(handler, "get").
   1040   Handle<Object> trap;
   1041   ASSIGN_RETURN_ON_EXCEPTION(
   1042       isolate, trap,
   1043       Object::GetMethod(Handle<JSReceiver>::cast(handler), trap_name), Object);
   1044   // 7. If trap is undefined, then
   1045   if (trap->IsUndefined(isolate)) {
   1046     // 7.a Return target.[[Get]](P, Receiver).
   1047     LookupIterator it =
   1048         LookupIterator::PropertyOrElement(isolate, receiver, name, target);
   1049     MaybeHandle<Object> result = Object::GetProperty(&it);
   1050     *was_found = it.IsFound();
   1051     return result;
   1052   }
   1053   // 8. Let trapResult be ? Call(trap, handler, target, P, Receiver).
   1054   Handle<Object> trap_result;
   1055   Handle<Object> args[] = {target, name, receiver};
   1056   ASSIGN_RETURN_ON_EXCEPTION(
   1057       isolate, trap_result,
   1058       Execution::Call(isolate, trap, handler, arraysize(args), args), Object);
   1059   // 9. Let targetDesc be ? target.[[GetOwnProperty]](P).
   1060   PropertyDescriptor target_desc;
   1061   Maybe<bool> target_found =
   1062       JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, &target_desc);
   1063   MAYBE_RETURN_NULL(target_found);
   1064   // 10. If targetDesc is not undefined, then
   1065   if (target_found.FromJust()) {
   1066     // 10.a. If IsDataDescriptor(targetDesc) and targetDesc.[[Configurable]] is
   1067     //       false and targetDesc.[[Writable]] is false, then
   1068     // 10.a.i. If SameValue(trapResult, targetDesc.[[Value]]) is false,
   1069     //        throw a TypeError exception.
   1070     bool inconsistent = PropertyDescriptor::IsDataDescriptor(&target_desc) &&
   1071                         !target_desc.configurable() &&
   1072                         !target_desc.writable() &&
   1073                         !trap_result->SameValue(*target_desc.value());
   1074     if (inconsistent) {
   1075       THROW_NEW_ERROR(
   1076           isolate, NewTypeError(MessageTemplate::kProxyGetNonConfigurableData,
   1077                                 name, target_desc.value(), trap_result),
   1078           Object);
   1079     }
   1080     // 10.b. If IsAccessorDescriptor(targetDesc) and targetDesc.[[Configurable]]
   1081     //       is false and targetDesc.[[Get]] is undefined, then
   1082     // 10.b.i. If trapResult is not undefined, throw a TypeError exception.
   1083     inconsistent = PropertyDescriptor::IsAccessorDescriptor(&target_desc) &&
   1084                    !target_desc.configurable() &&
   1085                    target_desc.get()->IsUndefined(isolate) &&
   1086                    !trap_result->IsUndefined(isolate);
   1087     if (inconsistent) {
   1088       THROW_NEW_ERROR(
   1089           isolate,
   1090           NewTypeError(MessageTemplate::kProxyGetNonConfigurableAccessor, name,
   1091                        trap_result),
   1092           Object);
   1093     }
   1094   }
   1095   // 11. Return trap_result
   1096   return trap_result;
   1097 }
   1098 
   1099 
   1100 Handle<Object> JSReceiver::GetDataProperty(LookupIterator* it) {
   1101   for (; it->IsFound(); it->Next()) {
   1102     switch (it->state()) {
   1103       case LookupIterator::INTERCEPTOR:
   1104       case LookupIterator::NOT_FOUND:
   1105       case LookupIterator::TRANSITION:
   1106         UNREACHABLE();
   1107       case LookupIterator::ACCESS_CHECK:
   1108         // Support calling this method without an active context, but refuse
   1109         // access to access-checked objects in that case.
   1110         if (it->isolate()->context() != nullptr && it->HasAccess()) continue;
   1111       // Fall through.
   1112       case LookupIterator::JSPROXY:
   1113         it->NotFound();
   1114         return it->isolate()->factory()->undefined_value();
   1115       case LookupIterator::ACCESSOR:
   1116         // TODO(verwaest): For now this doesn't call into AccessorInfo, since
   1117         // clients don't need it. Update once relevant.
   1118         it->NotFound();
   1119         return it->isolate()->factory()->undefined_value();
   1120       case LookupIterator::INTEGER_INDEXED_EXOTIC:
   1121         return it->isolate()->factory()->undefined_value();
   1122       case LookupIterator::DATA:
   1123         return it->GetDataValue();
   1124     }
   1125   }
   1126   return it->isolate()->factory()->undefined_value();
   1127 }
   1128 
   1129 
   1130 bool Object::ToInt32(int32_t* value) {
   1131   if (IsSmi()) {
   1132     *value = Smi::cast(this)->value();
   1133     return true;
   1134   }
   1135   if (IsHeapNumber()) {
   1136     double num = HeapNumber::cast(this)->value();
   1137     if (FastI2D(FastD2I(num)) == num) {
   1138       *value = FastD2I(num);
   1139       return true;
   1140     }
   1141   }
   1142   return false;
   1143 }
   1144 
   1145 Handle<SharedFunctionInfo> FunctionTemplateInfo::GetOrCreateSharedFunctionInfo(
   1146     Isolate* isolate, Handle<FunctionTemplateInfo> info) {
   1147   Object* current_info = info->shared_function_info();
   1148   if (current_info->IsSharedFunctionInfo()) {
   1149     return handle(SharedFunctionInfo::cast(current_info), isolate);
   1150   }
   1151 
   1152   Handle<Object> class_name(info->class_name(), isolate);
   1153   Handle<String> name = class_name->IsString()
   1154                             ? Handle<String>::cast(class_name)
   1155                             : isolate->factory()->empty_string();
   1156   Handle<Code> code;
   1157   if (info->call_code()->IsCallHandlerInfo() &&
   1158       CallHandlerInfo::cast(info->call_code())->fast_handler()->IsCode()) {
   1159     code = isolate->builtins()->HandleFastApiCall();
   1160   } else {
   1161     code = isolate->builtins()->HandleApiCall();
   1162   }
   1163   bool is_constructor = !info->remove_prototype();
   1164   Handle<SharedFunctionInfo> result =
   1165       isolate->factory()->NewSharedFunctionInfo(name, code, is_constructor);
   1166   if (is_constructor) {
   1167     result->SetConstructStub(*isolate->builtins()->JSConstructStubApi());
   1168   }
   1169 
   1170   result->set_length(info->length());
   1171   if (class_name->IsString()) result->set_instance_class_name(*class_name);
   1172   result->set_api_func_data(*info);
   1173   result->DontAdaptArguments();
   1174   DCHECK(result->IsApiFunction());
   1175 
   1176   info->set_shared_function_info(*result);
   1177   return result;
   1178 }
   1179 
   1180 bool FunctionTemplateInfo::IsTemplateFor(Map* map) {
   1181   // There is a constraint on the object; check.
   1182   if (!map->IsJSObjectMap()) return false;
   1183   // Fetch the constructor function of the object.
   1184   Object* cons_obj = map->GetConstructor();
   1185   if (!cons_obj->IsJSFunction()) return false;
   1186   JSFunction* fun = JSFunction::cast(cons_obj);
   1187   // Iterate through the chain of inheriting function templates to
   1188   // see if the required one occurs.
   1189   for (Object* type = fun->shared()->function_data();
   1190        type->IsFunctionTemplateInfo();
   1191        type = FunctionTemplateInfo::cast(type)->parent_template()) {
   1192     if (type == this) return true;
   1193   }
   1194   // Didn't find the required type in the inheritance chain.
   1195   return false;
   1196 }
   1197 
   1198 
   1199 // static
   1200 Handle<TemplateList> TemplateList::New(Isolate* isolate, int size) {
   1201   Handle<FixedArray> list =
   1202       isolate->factory()->NewFixedArray(kLengthIndex + size);
   1203   list->set(kLengthIndex, Smi::kZero);
   1204   return Handle<TemplateList>::cast(list);
   1205 }
   1206 
   1207 // static
   1208 Handle<TemplateList> TemplateList::Add(Isolate* isolate,
   1209                                        Handle<TemplateList> list,
   1210                                        Handle<i::Object> value) {
   1211   STATIC_ASSERT(kFirstElementIndex == 1);
   1212   int index = list->length() + 1;
   1213   Handle<i::FixedArray> fixed_array = Handle<FixedArray>::cast(list);
   1214   fixed_array = FixedArray::SetAndGrow(fixed_array, index, value);
   1215   fixed_array->set(kLengthIndex, Smi::FromInt(index));
   1216   return Handle<TemplateList>::cast(fixed_array);
   1217 }
   1218 
   1219 // static
   1220 MaybeHandle<JSObject> JSObject::New(Handle<JSFunction> constructor,
   1221                                     Handle<JSReceiver> new_target,
   1222                                     Handle<AllocationSite> site) {
   1223   // If called through new, new.target can be:
   1224   // - a subclass of constructor,
   1225   // - a proxy wrapper around constructor, or
   1226   // - the constructor itself.
   1227   // If called through Reflect.construct, it's guaranteed to be a constructor.
   1228   Isolate* const isolate = constructor->GetIsolate();
   1229   DCHECK(constructor->IsConstructor());
   1230   DCHECK(new_target->IsConstructor());
   1231   DCHECK(!constructor->has_initial_map() ||
   1232          constructor->initial_map()->instance_type() != JS_FUNCTION_TYPE);
   1233 
   1234   Handle<Map> initial_map;
   1235   ASSIGN_RETURN_ON_EXCEPTION(
   1236       isolate, initial_map,
   1237       JSFunction::GetDerivedMap(isolate, constructor, new_target), JSObject);
   1238   Handle<JSObject> result =
   1239       isolate->factory()->NewJSObjectFromMap(initial_map, NOT_TENURED, site);
   1240   isolate->counters()->constructed_objects()->Increment();
   1241   isolate->counters()->constructed_objects_runtime()->Increment();
   1242   return result;
   1243 }
   1244 
   1245 void JSObject::EnsureWritableFastElements(Handle<JSObject> object) {
   1246   DCHECK(object->HasFastSmiOrObjectElements() ||
   1247          object->HasFastStringWrapperElements());
   1248   FixedArray* raw_elems = FixedArray::cast(object->elements());
   1249   Heap* heap = object->GetHeap();
   1250   if (raw_elems->map() != heap->fixed_cow_array_map()) return;
   1251   Isolate* isolate = heap->isolate();
   1252   Handle<FixedArray> elems(raw_elems, isolate);
   1253   Handle<FixedArray> writable_elems = isolate->factory()->CopyFixedArrayWithMap(
   1254       elems, isolate->factory()->fixed_array_map());
   1255   object->set_elements(*writable_elems);
   1256   isolate->counters()->cow_arrays_converted()->Increment();
   1257 }
   1258 
   1259 
   1260 // ES6 9.5.1
   1261 // static
   1262 MaybeHandle<Object> JSProxy::GetPrototype(Handle<JSProxy> proxy) {
   1263   Isolate* isolate = proxy->GetIsolate();
   1264   Handle<String> trap_name = isolate->factory()->getPrototypeOf_string();
   1265 
   1266   STACK_CHECK(isolate, MaybeHandle<Object>());
   1267 
   1268   // 1. Let handler be the value of the [[ProxyHandler]] internal slot.
   1269   // 2. If handler is null, throw a TypeError exception.
   1270   // 3. Assert: Type(handler) is Object.
   1271   // 4. Let target be the value of the [[ProxyTarget]] internal slot.
   1272   if (proxy->IsRevoked()) {
   1273     THROW_NEW_ERROR(isolate,
   1274                     NewTypeError(MessageTemplate::kProxyRevoked, trap_name),
   1275                     Object);
   1276   }
   1277   Handle<JSReceiver> target(proxy->target(), isolate);
   1278   Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate);
   1279 
   1280   // 5. Let trap be ? GetMethod(handler, "getPrototypeOf").
   1281   Handle<Object> trap;
   1282   ASSIGN_RETURN_ON_EXCEPTION(isolate, trap, GetMethod(handler, trap_name),
   1283                              Object);
   1284   // 6. If trap is undefined, then return target.[[GetPrototypeOf]]().
   1285   if (trap->IsUndefined(isolate)) {
   1286     return JSReceiver::GetPrototype(isolate, target);
   1287   }
   1288   // 7. Let handlerProto be ? Call(trap, handler, target).
   1289   Handle<Object> argv[] = {target};
   1290   Handle<Object> handler_proto;
   1291   ASSIGN_RETURN_ON_EXCEPTION(
   1292       isolate, handler_proto,
   1293       Execution::Call(isolate, trap, handler, arraysize(argv), argv), Object);
   1294   // 8. If Type(handlerProto) is neither Object nor Null, throw a TypeError.
   1295   if (!(handler_proto->IsJSReceiver() || handler_proto->IsNull(isolate))) {
   1296     THROW_NEW_ERROR(isolate,
   1297                     NewTypeError(MessageTemplate::kProxyGetPrototypeOfInvalid),
   1298                     Object);
   1299   }
   1300   // 9. Let extensibleTarget be ? IsExtensible(target).
   1301   Maybe<bool> is_extensible = JSReceiver::IsExtensible(target);
   1302   MAYBE_RETURN_NULL(is_extensible);
   1303   // 10. If extensibleTarget is true, return handlerProto.
   1304   if (is_extensible.FromJust()) return handler_proto;
   1305   // 11. Let targetProto be ? target.[[GetPrototypeOf]]().
   1306   Handle<Object> target_proto;
   1307   ASSIGN_RETURN_ON_EXCEPTION(isolate, target_proto,
   1308                              JSReceiver::GetPrototype(isolate, target), Object);
   1309   // 12. If SameValue(handlerProto, targetProto) is false, throw a TypeError.
   1310   if (!handler_proto->SameValue(*target_proto)) {
   1311     THROW_NEW_ERROR(
   1312         isolate,
   1313         NewTypeError(MessageTemplate::kProxyGetPrototypeOfNonExtensible),
   1314         Object);
   1315   }
   1316   // 13. Return handlerProto.
   1317   return handler_proto;
   1318 }
   1319 
   1320 MaybeHandle<Object> Object::GetPropertyWithAccessor(LookupIterator* it) {
   1321   Isolate* isolate = it->isolate();
   1322   Handle<Object> structure = it->GetAccessors();
   1323   Handle<Object> receiver = it->GetReceiver();
   1324 
   1325   // We should never get here to initialize a const with the hole value since a
   1326   // const declaration would conflict with the getter.
   1327   DCHECK(!structure->IsForeign());
   1328 
   1329   // API style callbacks.
   1330   if (structure->IsAccessorInfo()) {
   1331     Handle<JSObject> holder = it->GetHolder<JSObject>();
   1332     Handle<Name> name = it->GetName();
   1333     Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(structure);
   1334     if (!info->IsCompatibleReceiver(*receiver)) {
   1335       THROW_NEW_ERROR(isolate,
   1336                       NewTypeError(MessageTemplate::kIncompatibleMethodReceiver,
   1337                                    name, receiver),
   1338                       Object);
   1339     }
   1340 
   1341     v8::AccessorNameGetterCallback call_fun =
   1342         v8::ToCData<v8::AccessorNameGetterCallback>(info->getter());
   1343     if (call_fun == nullptr) return isolate->factory()->undefined_value();
   1344 
   1345     if (info->is_sloppy() && !receiver->IsJSReceiver()) {
   1346       ASSIGN_RETURN_ON_EXCEPTION(isolate, receiver,
   1347                                  Object::ConvertReceiver(isolate, receiver),
   1348                                  Object);
   1349     }
   1350 
   1351     PropertyCallbackArguments args(isolate, info->data(), *receiver, *holder,
   1352                                    Object::DONT_THROW);
   1353     Handle<Object> result = args.Call(call_fun, name);
   1354     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
   1355     if (result.is_null()) return isolate->factory()->undefined_value();
   1356     Handle<Object> reboxed_result = handle(*result, isolate);
   1357     if (info->replace_on_access() && receiver->IsJSReceiver()) {
   1358       args.Call(reinterpret_cast<GenericNamedPropertySetterCallback>(
   1359                     &Accessors::ReconfigureToDataProperty),
   1360                 name, result);
   1361       RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
   1362     }
   1363     return reboxed_result;
   1364   }
   1365 
   1366   // AccessorPair with 'cached' private property.
   1367   if (it->TryLookupCachedProperty()) {
   1368     return Object::GetProperty(it);
   1369   }
   1370 
   1371   // Regular accessor.
   1372   Handle<Object> getter(AccessorPair::cast(*structure)->getter(), isolate);
   1373   if (getter->IsFunctionTemplateInfo()) {
   1374     return Builtins::InvokeApiFunction(
   1375         isolate, false, Handle<FunctionTemplateInfo>::cast(getter), receiver, 0,
   1376         nullptr, isolate->factory()->undefined_value());
   1377   } else if (getter->IsCallable()) {
   1378     // TODO(rossberg): nicer would be to cast to some JSCallable here...
   1379     return Object::GetPropertyWithDefinedGetter(
   1380         receiver, Handle<JSReceiver>::cast(getter));
   1381   }
   1382   // Getter is not a function.
   1383   return isolate->factory()->undefined_value();
   1384 }
   1385 
   1386 // static
   1387 Address AccessorInfo::redirect(Isolate* isolate, Address address,
   1388                                AccessorComponent component) {
   1389   ApiFunction fun(address);
   1390   DCHECK_EQ(ACCESSOR_GETTER, component);
   1391   ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL;
   1392   return ExternalReference(&fun, type, isolate).address();
   1393 }
   1394 
   1395 Address AccessorInfo::redirected_getter() const {
   1396   Address accessor = v8::ToCData<Address>(getter());
   1397   if (accessor == nullptr) return nullptr;
   1398   return redirect(GetIsolate(), accessor, ACCESSOR_GETTER);
   1399 }
   1400 
   1401 bool AccessorInfo::IsCompatibleReceiverMap(Isolate* isolate,
   1402                                            Handle<AccessorInfo> info,
   1403                                            Handle<Map> map) {
   1404   if (!info->HasExpectedReceiverType()) return true;
   1405   if (!map->IsJSObjectMap()) return false;
   1406   return FunctionTemplateInfo::cast(info->expected_receiver_type())
   1407       ->IsTemplateFor(*map);
   1408 }
   1409 
   1410 Maybe<bool> Object::SetPropertyWithAccessor(LookupIterator* it,
   1411                                             Handle<Object> value,
   1412                                             ShouldThrow should_throw) {
   1413   Isolate* isolate = it->isolate();
   1414   Handle<Object> structure = it->GetAccessors();
   1415   Handle<Object> receiver = it->GetReceiver();
   1416 
   1417   // We should never get here to initialize a const with the hole value since a
   1418   // const declaration would conflict with the setter.
   1419   DCHECK(!structure->IsForeign());
   1420 
   1421   // API style callbacks.
   1422   if (structure->IsAccessorInfo()) {
   1423     Handle<JSObject> holder = it->GetHolder<JSObject>();
   1424     Handle<Name> name = it->GetName();
   1425     Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(structure);
   1426     if (!info->IsCompatibleReceiver(*receiver)) {
   1427       isolate->Throw(*isolate->factory()->NewTypeError(
   1428           MessageTemplate::kIncompatibleMethodReceiver, name, receiver));
   1429       return Nothing<bool>();
   1430     }
   1431 
   1432     // The actual type of call_fun is either v8::AccessorNameSetterCallback or
   1433     // i::Accesors::AccessorNameBooleanSetterCallback, depending on whether the
   1434     // AccessorInfo was created by the API or internally (see accessors.cc).
   1435     // Here we handle both cases using GenericNamedPropertySetterCallback and
   1436     // its Call method.
   1437     GenericNamedPropertySetterCallback call_fun =
   1438         v8::ToCData<GenericNamedPropertySetterCallback>(info->setter());
   1439 
   1440     if (call_fun == nullptr) {
   1441       // TODO(verwaest): We should not get here anymore once all AccessorInfos
   1442       // are marked as special_data_property. They cannot both be writable and
   1443       // not have a setter.
   1444       return Just(true);
   1445     }
   1446 
   1447     if (info->is_sloppy() && !receiver->IsJSReceiver()) {
   1448       ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   1449           isolate, receiver, Object::ConvertReceiver(isolate, receiver),
   1450           Nothing<bool>());
   1451     }
   1452 
   1453     PropertyCallbackArguments args(isolate, info->data(), *receiver, *holder,
   1454                                    should_throw);
   1455     Handle<Object> result = args.Call(call_fun, name, value);
   1456     // In the case of AccessorNameSetterCallback, we know that the result value
   1457     // cannot have been set, so the result of Call will be null.  In the case of
   1458     // AccessorNameBooleanSetterCallback, the result will either be null
   1459     // (signalling an exception) or a boolean Oddball.
   1460     RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
   1461     if (result.is_null()) return Just(true);
   1462     DCHECK(result->BooleanValue() || should_throw == DONT_THROW);
   1463     return Just(result->BooleanValue());
   1464   }
   1465 
   1466   // Regular accessor.
   1467   Handle<Object> setter(AccessorPair::cast(*structure)->setter(), isolate);
   1468   if (setter->IsFunctionTemplateInfo()) {
   1469     Handle<Object> argv[] = {value};
   1470     RETURN_ON_EXCEPTION_VALUE(
   1471         isolate, Builtins::InvokeApiFunction(
   1472                      isolate, false, Handle<FunctionTemplateInfo>::cast(setter),
   1473                      receiver, arraysize(argv), argv,
   1474                      isolate->factory()->undefined_value()),
   1475         Nothing<bool>());
   1476     return Just(true);
   1477   } else if (setter->IsCallable()) {
   1478     // TODO(rossberg): nicer would be to cast to some JSCallable here...
   1479     return SetPropertyWithDefinedSetter(
   1480         receiver, Handle<JSReceiver>::cast(setter), value, should_throw);
   1481   }
   1482 
   1483   RETURN_FAILURE(isolate, should_throw,
   1484                  NewTypeError(MessageTemplate::kNoSetterInCallback,
   1485                               it->GetName(), it->GetHolder<JSObject>()));
   1486 }
   1487 
   1488 
   1489 MaybeHandle<Object> Object::GetPropertyWithDefinedGetter(
   1490     Handle<Object> receiver,
   1491     Handle<JSReceiver> getter) {
   1492   Isolate* isolate = getter->GetIsolate();
   1493 
   1494   // Platforms with simulators like arm/arm64 expose a funny issue. If the
   1495   // simulator has a separate JS stack pointer from the C++ stack pointer, it
   1496   // can miss C++ stack overflows in the stack guard at the start of JavaScript
   1497   // functions. It would be very expensive to check the C++ stack pointer at
   1498   // that location. The best solution seems to be to break the impasse by
   1499   // adding checks at possible recursion points. What's more, we don't put
   1500   // this stack check behind the USE_SIMULATOR define in order to keep
   1501   // behavior the same between hardware and simulators.
   1502   StackLimitCheck check(isolate);
   1503   if (check.JsHasOverflowed()) {
   1504     isolate->StackOverflow();
   1505     return MaybeHandle<Object>();
   1506   }
   1507 
   1508   return Execution::Call(isolate, getter, receiver, 0, NULL);
   1509 }
   1510 
   1511 
   1512 Maybe<bool> Object::SetPropertyWithDefinedSetter(Handle<Object> receiver,
   1513                                                  Handle<JSReceiver> setter,
   1514                                                  Handle<Object> value,
   1515                                                  ShouldThrow should_throw) {
   1516   Isolate* isolate = setter->GetIsolate();
   1517 
   1518   Handle<Object> argv[] = { value };
   1519   RETURN_ON_EXCEPTION_VALUE(isolate, Execution::Call(isolate, setter, receiver,
   1520                                                      arraysize(argv), argv),
   1521                             Nothing<bool>());
   1522   return Just(true);
   1523 }
   1524 
   1525 
   1526 // static
   1527 bool JSObject::AllCanRead(LookupIterator* it) {
   1528   // Skip current iteration, it's in state ACCESS_CHECK or INTERCEPTOR, both of
   1529   // which have already been checked.
   1530   DCHECK(it->state() == LookupIterator::ACCESS_CHECK ||
   1531          it->state() == LookupIterator::INTERCEPTOR);
   1532   for (it->Next(); it->IsFound(); it->Next()) {
   1533     if (it->state() == LookupIterator::ACCESSOR) {
   1534       auto accessors = it->GetAccessors();
   1535       if (accessors->IsAccessorInfo()) {
   1536         if (AccessorInfo::cast(*accessors)->all_can_read()) return true;
   1537       }
   1538     } else if (it->state() == LookupIterator::INTERCEPTOR) {
   1539       if (it->GetInterceptor()->all_can_read()) return true;
   1540     } else if (it->state() == LookupIterator::JSPROXY) {
   1541       // Stop lookupiterating. And no, AllCanNotRead.
   1542       return false;
   1543     }
   1544   }
   1545   return false;
   1546 }
   1547 
   1548 namespace {
   1549 
   1550 MaybeHandle<Object> GetPropertyWithInterceptorInternal(
   1551     LookupIterator* it, Handle<InterceptorInfo> interceptor, bool* done) {
   1552   *done = false;
   1553   Isolate* isolate = it->isolate();
   1554   // Make sure that the top context does not change when doing callbacks or
   1555   // interceptor calls.
   1556   AssertNoContextChange ncc(isolate);
   1557 
   1558   if (interceptor->getter()->IsUndefined(isolate)) {
   1559     return isolate->factory()->undefined_value();
   1560   }
   1561 
   1562   Handle<JSObject> holder = it->GetHolder<JSObject>();
   1563   Handle<Object> result;
   1564   Handle<Object> receiver = it->GetReceiver();
   1565   if (!receiver->IsJSReceiver()) {
   1566     ASSIGN_RETURN_ON_EXCEPTION(
   1567         isolate, receiver, Object::ConvertReceiver(isolate, receiver), Object);
   1568   }
   1569   PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
   1570                                  *holder, Object::DONT_THROW);
   1571 
   1572   if (it->IsElement()) {
   1573     uint32_t index = it->index();
   1574     v8::IndexedPropertyGetterCallback getter =
   1575         v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter());
   1576     result = args.Call(getter, index);
   1577   } else {
   1578     Handle<Name> name = it->name();
   1579     DCHECK(!name->IsPrivate());
   1580 
   1581     if (name->IsSymbol() && !interceptor->can_intercept_symbols()) {
   1582       return isolate->factory()->undefined_value();
   1583     }
   1584 
   1585     v8::GenericNamedPropertyGetterCallback getter =
   1586         v8::ToCData<v8::GenericNamedPropertyGetterCallback>(
   1587             interceptor->getter());
   1588     result = args.Call(getter, name);
   1589   }
   1590 
   1591   RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
   1592   if (result.is_null()) return isolate->factory()->undefined_value();
   1593   *done = true;
   1594   // Rebox handle before return
   1595   return handle(*result, isolate);
   1596 }
   1597 
   1598 Maybe<PropertyAttributes> GetPropertyAttributesWithInterceptorInternal(
   1599     LookupIterator* it, Handle<InterceptorInfo> interceptor) {
   1600   Isolate* isolate = it->isolate();
   1601   // Make sure that the top context does not change when doing
   1602   // callbacks or interceptor calls.
   1603   AssertNoContextChange ncc(isolate);
   1604   HandleScope scope(isolate);
   1605 
   1606   Handle<JSObject> holder = it->GetHolder<JSObject>();
   1607   if (!it->IsElement() && it->name()->IsSymbol() &&
   1608       !interceptor->can_intercept_symbols()) {
   1609     return Just(ABSENT);
   1610   }
   1611   Handle<Object> receiver = it->GetReceiver();
   1612   if (!receiver->IsJSReceiver()) {
   1613     ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, receiver,
   1614                                      Object::ConvertReceiver(isolate, receiver),
   1615                                      Nothing<PropertyAttributes>());
   1616   }
   1617   PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
   1618                                  *holder, Object::DONT_THROW);
   1619   if (!interceptor->query()->IsUndefined(isolate)) {
   1620     Handle<Object> result;
   1621     if (it->IsElement()) {
   1622       uint32_t index = it->index();
   1623       v8::IndexedPropertyQueryCallback query =
   1624           v8::ToCData<v8::IndexedPropertyQueryCallback>(interceptor->query());
   1625       result = args.Call(query, index);
   1626     } else {
   1627       Handle<Name> name = it->name();
   1628       DCHECK(!name->IsPrivate());
   1629       v8::GenericNamedPropertyQueryCallback query =
   1630           v8::ToCData<v8::GenericNamedPropertyQueryCallback>(
   1631               interceptor->query());
   1632       result = args.Call(query, name);
   1633     }
   1634     if (!result.is_null()) {
   1635       int32_t value;
   1636       CHECK(result->ToInt32(&value));
   1637       return Just(static_cast<PropertyAttributes>(value));
   1638     }
   1639   } else if (!interceptor->getter()->IsUndefined(isolate)) {
   1640     // TODO(verwaest): Use GetPropertyWithInterceptor?
   1641     Handle<Object> result;
   1642     if (it->IsElement()) {
   1643       uint32_t index = it->index();
   1644       v8::IndexedPropertyGetterCallback getter =
   1645           v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter());
   1646       result = args.Call(getter, index);
   1647     } else {
   1648       Handle<Name> name = it->name();
   1649       DCHECK(!name->IsPrivate());
   1650       v8::GenericNamedPropertyGetterCallback getter =
   1651           v8::ToCData<v8::GenericNamedPropertyGetterCallback>(
   1652               interceptor->getter());
   1653       result = args.Call(getter, name);
   1654     }
   1655     if (!result.is_null()) return Just(DONT_ENUM);
   1656   }
   1657 
   1658   RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<PropertyAttributes>());
   1659   return Just(ABSENT);
   1660 }
   1661 
   1662 Maybe<bool> SetPropertyWithInterceptorInternal(
   1663     LookupIterator* it, Handle<InterceptorInfo> interceptor,
   1664     Object::ShouldThrow should_throw, Handle<Object> value) {
   1665   Isolate* isolate = it->isolate();
   1666   // Make sure that the top context does not change when doing callbacks or
   1667   // interceptor calls.
   1668   AssertNoContextChange ncc(isolate);
   1669 
   1670   if (interceptor->setter()->IsUndefined(isolate)) return Just(false);
   1671 
   1672   Handle<JSObject> holder = it->GetHolder<JSObject>();
   1673   bool result;
   1674   Handle<Object> receiver = it->GetReceiver();
   1675   if (!receiver->IsJSReceiver()) {
   1676     ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, receiver,
   1677                                      Object::ConvertReceiver(isolate, receiver),
   1678                                      Nothing<bool>());
   1679   }
   1680   PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
   1681                                  *holder, should_throw);
   1682 
   1683   if (it->IsElement()) {
   1684     uint32_t index = it->index();
   1685     v8::IndexedPropertySetterCallback setter =
   1686         v8::ToCData<v8::IndexedPropertySetterCallback>(interceptor->setter());
   1687     // TODO(neis): In the future, we may want to actually return the
   1688     // interceptor's result, which then should be a boolean.
   1689     result = !args.Call(setter, index, value).is_null();
   1690   } else {
   1691     Handle<Name> name = it->name();
   1692     DCHECK(!name->IsPrivate());
   1693 
   1694     if (name->IsSymbol() && !interceptor->can_intercept_symbols()) {
   1695       return Just(false);
   1696     }
   1697 
   1698     v8::GenericNamedPropertySetterCallback setter =
   1699         v8::ToCData<v8::GenericNamedPropertySetterCallback>(
   1700             interceptor->setter());
   1701     result = !args.Call(setter, name, value).is_null();
   1702   }
   1703 
   1704   RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(), Nothing<bool>());
   1705   return Just(result);
   1706 }
   1707 
   1708 Maybe<bool> DefinePropertyWithInterceptorInternal(
   1709     LookupIterator* it, Handle<InterceptorInfo> interceptor,
   1710     Object::ShouldThrow should_throw, PropertyDescriptor& desc) {
   1711   Isolate* isolate = it->isolate();
   1712   // Make sure that the top context does not change when doing callbacks or
   1713   // interceptor calls.
   1714   AssertNoContextChange ncc(isolate);
   1715 
   1716   if (interceptor->definer()->IsUndefined(isolate)) return Just(false);
   1717 
   1718   Handle<JSObject> holder = it->GetHolder<JSObject>();
   1719   bool result;
   1720   Handle<Object> receiver = it->GetReceiver();
   1721   if (!receiver->IsJSReceiver()) {
   1722     ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, receiver,
   1723                                      Object::ConvertReceiver(isolate, receiver),
   1724                                      Nothing<bool>());
   1725   }
   1726   PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
   1727                                  *holder, should_throw);
   1728 
   1729   std::unique_ptr<v8::PropertyDescriptor> descriptor(
   1730       new v8::PropertyDescriptor());
   1731   if (PropertyDescriptor::IsAccessorDescriptor(&desc)) {
   1732     descriptor.reset(new v8::PropertyDescriptor(
   1733         v8::Utils::ToLocal(desc.get()), v8::Utils::ToLocal(desc.set())));
   1734   } else if (PropertyDescriptor::IsDataDescriptor(&desc)) {
   1735     if (desc.has_writable()) {
   1736       descriptor.reset(new v8::PropertyDescriptor(
   1737           v8::Utils::ToLocal(desc.value()), desc.writable()));
   1738     } else {
   1739       descriptor.reset(
   1740           new v8::PropertyDescriptor(v8::Utils::ToLocal(desc.value())));
   1741     }
   1742   }
   1743   if (desc.has_enumerable()) {
   1744     descriptor->set_enumerable(desc.enumerable());
   1745   }
   1746   if (desc.has_configurable()) {
   1747     descriptor->set_configurable(desc.configurable());
   1748   }
   1749 
   1750   if (it->IsElement()) {
   1751     uint32_t index = it->index();
   1752     v8::IndexedPropertyDefinerCallback definer =
   1753         v8::ToCData<v8::IndexedPropertyDefinerCallback>(interceptor->definer());
   1754     result = !args.Call(definer, index, *descriptor).is_null();
   1755   } else {
   1756     Handle<Name> name = it->name();
   1757     DCHECK(!name->IsPrivate());
   1758 
   1759     if (name->IsSymbol() && !interceptor->can_intercept_symbols()) {
   1760       return Just(false);
   1761     }
   1762 
   1763     v8::GenericNamedPropertyDefinerCallback definer =
   1764         v8::ToCData<v8::GenericNamedPropertyDefinerCallback>(
   1765             interceptor->definer());
   1766     result = !args.Call(definer, name, *descriptor).is_null();
   1767   }
   1768 
   1769   RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(), Nothing<bool>());
   1770   return Just(result);
   1771 }
   1772 
   1773 }  // namespace
   1774 
   1775 MaybeHandle<Object> JSObject::GetPropertyWithFailedAccessCheck(
   1776     LookupIterator* it) {
   1777   Isolate* isolate = it->isolate();
   1778   Handle<JSObject> checked = it->GetHolder<JSObject>();
   1779   Handle<InterceptorInfo> interceptor =
   1780       it->GetInterceptorForFailedAccessCheck();
   1781   if (interceptor.is_null()) {
   1782     while (AllCanRead(it)) {
   1783       if (it->state() == LookupIterator::ACCESSOR) {
   1784         return GetPropertyWithAccessor(it);
   1785       }
   1786       DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
   1787       bool done;
   1788       Handle<Object> result;
   1789       ASSIGN_RETURN_ON_EXCEPTION(isolate, result,
   1790                                  GetPropertyWithInterceptor(it, &done), Object);
   1791       if (done) return result;
   1792     }
   1793   } else {
   1794     MaybeHandle<Object> result;
   1795     bool done;
   1796     result = GetPropertyWithInterceptorInternal(it, interceptor, &done);
   1797     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
   1798     if (done) return result;
   1799   }
   1800 
   1801   // Cross-Origin [[Get]] of Well-Known Symbols does not throw, and returns
   1802   // undefined.
   1803   Handle<Name> name = it->GetName();
   1804   if (name->IsSymbol() && Symbol::cast(*name)->is_well_known_symbol()) {
   1805     return it->factory()->undefined_value();
   1806   }
   1807 
   1808   isolate->ReportFailedAccessCheck(checked);
   1809   RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
   1810   return it->factory()->undefined_value();
   1811 }
   1812 
   1813 
   1814 Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithFailedAccessCheck(
   1815     LookupIterator* it) {
   1816   Isolate* isolate = it->isolate();
   1817   Handle<JSObject> checked = it->GetHolder<JSObject>();
   1818   Handle<InterceptorInfo> interceptor =
   1819       it->GetInterceptorForFailedAccessCheck();
   1820   if (interceptor.is_null()) {
   1821     while (AllCanRead(it)) {
   1822       if (it->state() == LookupIterator::ACCESSOR) {
   1823         return Just(it->property_attributes());
   1824       }
   1825       DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
   1826       auto result = GetPropertyAttributesWithInterceptor(it);
   1827       if (isolate->has_scheduled_exception()) break;
   1828       if (result.IsJust() && result.FromJust() != ABSENT) return result;
   1829     }
   1830   } else {
   1831     Maybe<PropertyAttributes> result =
   1832         GetPropertyAttributesWithInterceptorInternal(it, interceptor);
   1833     RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<PropertyAttributes>());
   1834     if (result.FromMaybe(ABSENT) != ABSENT) return result;
   1835   }
   1836   isolate->ReportFailedAccessCheck(checked);
   1837   RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<PropertyAttributes>());
   1838   return Just(ABSENT);
   1839 }
   1840 
   1841 
   1842 // static
   1843 bool JSObject::AllCanWrite(LookupIterator* it) {
   1844   for (; it->IsFound() && it->state() != LookupIterator::JSPROXY; it->Next()) {
   1845     if (it->state() == LookupIterator::ACCESSOR) {
   1846       Handle<Object> accessors = it->GetAccessors();
   1847       if (accessors->IsAccessorInfo()) {
   1848         if (AccessorInfo::cast(*accessors)->all_can_write()) return true;
   1849       }
   1850     }
   1851   }
   1852   return false;
   1853 }
   1854 
   1855 
   1856 Maybe<bool> JSObject::SetPropertyWithFailedAccessCheck(
   1857     LookupIterator* it, Handle<Object> value, ShouldThrow should_throw) {
   1858   Isolate* isolate = it->isolate();
   1859   Handle<JSObject> checked = it->GetHolder<JSObject>();
   1860   Handle<InterceptorInfo> interceptor =
   1861       it->GetInterceptorForFailedAccessCheck();
   1862   if (interceptor.is_null()) {
   1863     if (AllCanWrite(it)) {
   1864       return SetPropertyWithAccessor(it, value, should_throw);
   1865     }
   1866   } else {
   1867     Maybe<bool> result = SetPropertyWithInterceptorInternal(
   1868         it, interceptor, should_throw, value);
   1869     RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
   1870     if (result.IsJust()) return result;
   1871   }
   1872 
   1873   isolate->ReportFailedAccessCheck(checked);
   1874   RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
   1875   return Just(true);
   1876 }
   1877 
   1878 
   1879 void JSObject::SetNormalizedProperty(Handle<JSObject> object,
   1880                                      Handle<Name> name,
   1881                                      Handle<Object> value,
   1882                                      PropertyDetails details) {
   1883   DCHECK(!object->HasFastProperties());
   1884   if (!name->IsUniqueName()) {
   1885     name = object->GetIsolate()->factory()->InternalizeString(
   1886         Handle<String>::cast(name));
   1887   }
   1888 
   1889   if (object->IsJSGlobalObject()) {
   1890     Handle<GlobalDictionary> dictionary(object->global_dictionary());
   1891 
   1892     int entry = dictionary->FindEntry(name);
   1893     if (entry == GlobalDictionary::kNotFound) {
   1894       Isolate* isolate = object->GetIsolate();
   1895       auto cell = isolate->factory()->NewPropertyCell();
   1896       cell->set_value(*value);
   1897       auto cell_type = value->IsUndefined(isolate)
   1898                            ? PropertyCellType::kUndefined
   1899                            : PropertyCellType::kConstant;
   1900       details = details.set_cell_type(cell_type);
   1901       value = cell;
   1902       dictionary = GlobalDictionary::Add(dictionary, name, value, details);
   1903       object->set_properties(*dictionary);
   1904     } else {
   1905       Handle<PropertyCell> cell =
   1906           PropertyCell::PrepareForValue(dictionary, entry, value, details);
   1907       cell->set_value(*value);
   1908     }
   1909   } else {
   1910     Handle<NameDictionary> dictionary(object->property_dictionary());
   1911 
   1912     int entry = dictionary->FindEntry(name);
   1913     if (entry == NameDictionary::kNotFound) {
   1914       dictionary = NameDictionary::Add(dictionary, name, value, details);
   1915       object->set_properties(*dictionary);
   1916     } else {
   1917       PropertyDetails original_details = dictionary->DetailsAt(entry);
   1918       int enumeration_index = original_details.dictionary_index();
   1919       DCHECK(enumeration_index > 0);
   1920       details = details.set_index(enumeration_index);
   1921       dictionary->SetEntry(entry, name, value, details);
   1922     }
   1923   }
   1924 }
   1925 
   1926 // static
   1927 Maybe<bool> JSReceiver::HasInPrototypeChain(Isolate* isolate,
   1928                                             Handle<JSReceiver> object,
   1929                                             Handle<Object> proto) {
   1930   PrototypeIterator iter(isolate, object, kStartAtReceiver);
   1931   while (true) {
   1932     if (!iter.AdvanceFollowingProxies()) return Nothing<bool>();
   1933     if (iter.IsAtEnd()) return Just(false);
   1934     if (PrototypeIterator::GetCurrent(iter).is_identical_to(proto)) {
   1935       return Just(true);
   1936     }
   1937   }
   1938 }
   1939 
   1940 Map* Object::GetPrototypeChainRootMap(Isolate* isolate) {
   1941   DisallowHeapAllocation no_alloc;
   1942   if (IsSmi()) {
   1943     Context* native_context = isolate->context()->native_context();
   1944     return native_context->number_function()->initial_map();
   1945   }
   1946 
   1947   // The object is either a number, a string, a symbol, a boolean, a SIMD value,
   1948   // a real JS object, or a Harmony proxy.
   1949   HeapObject* heap_object = HeapObject::cast(this);
   1950   return heap_object->map()->GetPrototypeChainRootMap(isolate);
   1951 }
   1952 
   1953 Map* Map::GetPrototypeChainRootMap(Isolate* isolate) {
   1954   DisallowHeapAllocation no_alloc;
   1955   if (IsJSReceiverMap()) {
   1956     return this;
   1957   }
   1958   int constructor_function_index = GetConstructorFunctionIndex();
   1959   if (constructor_function_index != Map::kNoConstructorFunctionIndex) {
   1960     Context* native_context = isolate->context()->native_context();
   1961     JSFunction* constructor_function =
   1962         JSFunction::cast(native_context->get(constructor_function_index));
   1963     return constructor_function->initial_map();
   1964   }
   1965   return isolate->heap()->null_value()->map();
   1966 }
   1967 
   1968 namespace {
   1969 
   1970 // Returns a non-SMI for JSObjects, but returns the hash code for simple
   1971 // objects.  This avoids a double lookup in the cases where we know we will
   1972 // add the hash to the JSObject if it does not already exist.
   1973 Object* GetSimpleHash(Object* object) {
   1974   // The object is either a Smi, a HeapNumber, a name, an odd-ball,
   1975   // a SIMD value type, a real JS object, or a Harmony proxy.
   1976   if (object->IsSmi()) {
   1977     uint32_t hash =
   1978         ComputeIntegerHash(Smi::cast(object)->value(), kZeroHashSeed);
   1979     return Smi::FromInt(hash & Smi::kMaxValue);
   1980   }
   1981   if (object->IsHeapNumber()) {
   1982     double num = HeapNumber::cast(object)->value();
   1983     if (std::isnan(num)) return Smi::FromInt(Smi::kMaxValue);
   1984     if (i::IsMinusZero(num)) num = 0;
   1985     if (IsSmiDouble(num)) {
   1986       return Smi::FromInt(FastD2I(num))->GetHash();
   1987     }
   1988     uint32_t hash = ComputeLongHash(double_to_uint64(num));
   1989     return Smi::FromInt(hash & Smi::kMaxValue);
   1990   }
   1991   if (object->IsName()) {
   1992     uint32_t hash = Name::cast(object)->Hash();
   1993     return Smi::FromInt(hash);
   1994   }
   1995   if (object->IsOddball()) {
   1996     uint32_t hash = Oddball::cast(object)->to_string()->Hash();
   1997     return Smi::FromInt(hash);
   1998   }
   1999   if (object->IsSimd128Value()) {
   2000     uint32_t hash = Simd128Value::cast(object)->Hash();
   2001     return Smi::FromInt(hash & Smi::kMaxValue);
   2002   }
   2003   DCHECK(object->IsJSReceiver());
   2004   // Simply return the receiver as it is guaranteed to not be a SMI.
   2005   return object;
   2006 }
   2007 
   2008 }  // namespace
   2009 
   2010 Object* Object::GetHash() {
   2011   Object* hash = GetSimpleHash(this);
   2012   if (hash->IsSmi()) return hash;
   2013 
   2014   DisallowHeapAllocation no_gc;
   2015   DCHECK(IsJSReceiver());
   2016   JSReceiver* receiver = JSReceiver::cast(this);
   2017   Isolate* isolate = receiver->GetIsolate();
   2018   return JSReceiver::GetIdentityHash(isolate, handle(receiver, isolate));
   2019 }
   2020 
   2021 Smi* Object::GetOrCreateHash(Isolate* isolate, Handle<Object> object) {
   2022   Object* hash = GetSimpleHash(*object);
   2023   if (hash->IsSmi()) return Smi::cast(hash);
   2024 
   2025   DCHECK(object->IsJSReceiver());
   2026   return JSReceiver::GetOrCreateIdentityHash(isolate,
   2027                                              Handle<JSReceiver>::cast(object));
   2028 }
   2029 
   2030 
   2031 bool Object::SameValue(Object* other) {
   2032   if (other == this) return true;
   2033 
   2034   // The object is either a number, a name, an odd-ball,
   2035   // a real JS object, or a Harmony proxy.
   2036   if (IsNumber() && other->IsNumber()) {
   2037     double this_value = Number();
   2038     double other_value = other->Number();
   2039     // SameValue(NaN, NaN) is true.
   2040     if (this_value != other_value) {
   2041       return std::isnan(this_value) && std::isnan(other_value);
   2042     }
   2043     // SameValue(0.0, -0.0) is false.
   2044     return (std::signbit(this_value) == std::signbit(other_value));
   2045   }
   2046   if (IsString() && other->IsString()) {
   2047     return String::cast(this)->Equals(String::cast(other));
   2048   }
   2049   if (IsFloat32x4() && other->IsFloat32x4()) {
   2050     Float32x4* a = Float32x4::cast(this);
   2051     Float32x4* b = Float32x4::cast(other);
   2052     for (int i = 0; i < 4; i++) {
   2053       float x = a->get_lane(i);
   2054       float y = b->get_lane(i);
   2055       // Implements the ES5 SameValue operation for floating point types.
   2056       // http://www.ecma-international.org/ecma-262/6.0/#sec-samevalue
   2057       if (x != y && !(std::isnan(x) && std::isnan(y))) return false;
   2058       if (std::signbit(x) != std::signbit(y)) return false;
   2059     }
   2060     return true;
   2061   } else if (IsSimd128Value() && other->IsSimd128Value()) {
   2062     Simd128Value* a = Simd128Value::cast(this);
   2063     Simd128Value* b = Simd128Value::cast(other);
   2064     return a->map() == b->map() && a->BitwiseEquals(b);
   2065   }
   2066   return false;
   2067 }
   2068 
   2069 
   2070 bool Object::SameValueZero(Object* other) {
   2071   if (other == this) return true;
   2072 
   2073   // The object is either a number, a name, an odd-ball,
   2074   // a real JS object, or a Harmony proxy.
   2075   if (IsNumber() && other->IsNumber()) {
   2076     double this_value = Number();
   2077     double other_value = other->Number();
   2078     // +0 == -0 is true
   2079     return this_value == other_value ||
   2080            (std::isnan(this_value) && std::isnan(other_value));
   2081   }
   2082   if (IsString() && other->IsString()) {
   2083     return String::cast(this)->Equals(String::cast(other));
   2084   }
   2085   if (IsFloat32x4() && other->IsFloat32x4()) {
   2086     Float32x4* a = Float32x4::cast(this);
   2087     Float32x4* b = Float32x4::cast(other);
   2088     for (int i = 0; i < 4; i++) {
   2089       float x = a->get_lane(i);
   2090       float y = b->get_lane(i);
   2091       // Implements the ES6 SameValueZero operation for floating point types.
   2092       // http://www.ecma-international.org/ecma-262/6.0/#sec-samevaluezero
   2093       if (x != y && !(std::isnan(x) && std::isnan(y))) return false;
   2094       // SameValueZero doesn't distinguish between 0 and -0.
   2095     }
   2096     return true;
   2097   } else if (IsSimd128Value() && other->IsSimd128Value()) {
   2098     Simd128Value* a = Simd128Value::cast(this);
   2099     Simd128Value* b = Simd128Value::cast(other);
   2100     return a->map() == b->map() && a->BitwiseEquals(b);
   2101   }
   2102   return false;
   2103 }
   2104 
   2105 
   2106 MaybeHandle<Object> Object::ArraySpeciesConstructor(
   2107     Isolate* isolate, Handle<Object> original_array) {
   2108   Handle<Object> default_species = isolate->array_function();
   2109   if (original_array->IsJSArray() &&
   2110       Handle<JSArray>::cast(original_array)->HasArrayPrototype(isolate) &&
   2111       isolate->IsArraySpeciesLookupChainIntact()) {
   2112     return default_species;
   2113   }
   2114   Handle<Object> constructor = isolate->factory()->undefined_value();
   2115   Maybe<bool> is_array = Object::IsArray(original_array);
   2116   MAYBE_RETURN_NULL(is_array);
   2117   if (is_array.FromJust()) {
   2118     ASSIGN_RETURN_ON_EXCEPTION(
   2119         isolate, constructor,
   2120         Object::GetProperty(original_array,
   2121                             isolate->factory()->constructor_string()),
   2122         Object);
   2123     if (constructor->IsConstructor()) {
   2124       Handle<Context> constructor_context;
   2125       ASSIGN_RETURN_ON_EXCEPTION(
   2126           isolate, constructor_context,
   2127           JSReceiver::GetFunctionRealm(Handle<JSReceiver>::cast(constructor)),
   2128           Object);
   2129       if (*constructor_context != *isolate->native_context() &&
   2130           *constructor == constructor_context->array_function()) {
   2131         constructor = isolate->factory()->undefined_value();
   2132       }
   2133     }
   2134     if (constructor->IsJSReceiver()) {
   2135       ASSIGN_RETURN_ON_EXCEPTION(
   2136           isolate, constructor,
   2137           JSReceiver::GetProperty(Handle<JSReceiver>::cast(constructor),
   2138                                   isolate->factory()->species_symbol()),
   2139           Object);
   2140       if (constructor->IsNull(isolate)) {
   2141         constructor = isolate->factory()->undefined_value();
   2142       }
   2143     }
   2144   }
   2145   if (constructor->IsUndefined(isolate)) {
   2146     return default_species;
   2147   } else {
   2148     if (!constructor->IsConstructor()) {
   2149       THROW_NEW_ERROR(isolate,
   2150           NewTypeError(MessageTemplate::kSpeciesNotConstructor),
   2151           Object);
   2152     }
   2153     return constructor;
   2154   }
   2155 }
   2156 
   2157 
   2158 void Object::ShortPrint(FILE* out) {
   2159   OFStream os(out);
   2160   os << Brief(this);
   2161 }
   2162 
   2163 
   2164 void Object::ShortPrint(StringStream* accumulator) {
   2165   std::ostringstream os;
   2166   os << Brief(this);
   2167   accumulator->Add(os.str().c_str());
   2168 }
   2169 
   2170 
   2171 void Object::ShortPrint(std::ostream& os) { os << Brief(this); }
   2172 
   2173 
   2174 std::ostream& operator<<(std::ostream& os, const Brief& v) {
   2175   if (v.value->IsSmi()) {
   2176     Smi::cast(v.value)->SmiPrint(os);
   2177   } else {
   2178     // TODO(svenpanne) Const-correct HeapObjectShortPrint!
   2179     HeapObject* obj = const_cast<HeapObject*>(HeapObject::cast(v.value));
   2180     obj->HeapObjectShortPrint(os);
   2181   }
   2182   return os;
   2183 }
   2184 
   2185 // Declaration of the static Smi::kZero constant.
   2186 Smi* const Smi::kZero(nullptr);
   2187 
   2188 void Smi::SmiPrint(std::ostream& os) const {  // NOLINT
   2189   os << value();
   2190 }
   2191 
   2192 
   2193 // Should a word be prefixed by 'a' or 'an' in order to read naturally in
   2194 // English?  Returns false for non-ASCII or words that don't start with
   2195 // a capital letter.  The a/an rule follows pronunciation in English.
   2196 // We don't use the BBC's overcorrect "an historic occasion" though if
   2197 // you speak a dialect you may well say "an 'istoric occasion".
   2198 static bool AnWord(String* str) {
   2199   if (str->length() == 0) return false;  // A nothing.
   2200   int c0 = str->Get(0);
   2201   int c1 = str->length() > 1 ? str->Get(1) : 0;
   2202   if (c0 == 'U') {
   2203     if (c1 > 'Z') {
   2204       return true;  // An Umpire, but a UTF8String, a U.
   2205     }
   2206   } else if (c0 == 'A' || c0 == 'E' || c0 == 'I' || c0 == 'O') {
   2207     return true;    // An Ape, an ABCBook.
   2208   } else if ((c1 == 0 || (c1 >= 'A' && c1 <= 'Z')) &&
   2209            (c0 == 'F' || c0 == 'H' || c0 == 'M' || c0 == 'N' || c0 == 'R' ||
   2210             c0 == 'S' || c0 == 'X')) {
   2211     return true;    // An MP3File, an M.
   2212   }
   2213   return false;
   2214 }
   2215 
   2216 
   2217 Handle<String> String::SlowFlatten(Handle<ConsString> cons,
   2218                                    PretenureFlag pretenure) {
   2219   DCHECK(cons->second()->length() != 0);
   2220 
   2221   // TurboFan can create cons strings with empty first parts.
   2222   if (cons->first()->length() == 0) return handle(cons->second());
   2223 
   2224   DCHECK(AllowHeapAllocation::IsAllowed());
   2225   Isolate* isolate = cons->GetIsolate();
   2226   int length = cons->length();
   2227   PretenureFlag tenure = isolate->heap()->InNewSpace(*cons) ? pretenure
   2228                                                             : TENURED;
   2229   Handle<SeqString> result;
   2230   if (cons->IsOneByteRepresentation()) {
   2231     Handle<SeqOneByteString> flat = isolate->factory()->NewRawOneByteString(
   2232         length, tenure).ToHandleChecked();
   2233     DisallowHeapAllocation no_gc;
   2234     WriteToFlat(*cons, flat->GetChars(), 0, length);
   2235     result = flat;
   2236   } else {
   2237     Handle<SeqTwoByteString> flat = isolate->factory()->NewRawTwoByteString(
   2238         length, tenure).ToHandleChecked();
   2239     DisallowHeapAllocation no_gc;
   2240     WriteToFlat(*cons, flat->GetChars(), 0, length);
   2241     result = flat;
   2242   }
   2243   cons->set_first(*result);
   2244   cons->set_second(isolate->heap()->empty_string());
   2245   DCHECK(result->IsFlat());
   2246   return result;
   2247 }
   2248 
   2249 
   2250 
   2251 bool String::MakeExternal(v8::String::ExternalStringResource* resource) {
   2252   // Externalizing twice leaks the external resource, so it's
   2253   // prohibited by the API.
   2254   DCHECK(!this->IsExternalString());
   2255   DCHECK(!resource->IsCompressible());
   2256 #ifdef ENABLE_SLOW_DCHECKS
   2257   if (FLAG_enable_slow_asserts) {
   2258     // Assert that the resource and the string are equivalent.
   2259     DCHECK(static_cast<size_t>(this->length()) == resource->length());
   2260     ScopedVector<uc16> smart_chars(this->length());
   2261     String::WriteToFlat(this, smart_chars.start(), 0, this->length());
   2262     DCHECK(memcmp(smart_chars.start(),
   2263                   resource->data(),
   2264                   resource->length() * sizeof(smart_chars[0])) == 0);
   2265   }
   2266 #endif  // DEBUG
   2267   int size = this->Size();  // Byte size of the original string.
   2268   // Abort if size does not allow in-place conversion.
   2269   if (size < ExternalString::kShortSize) return false;
   2270   Heap* heap = GetHeap();
   2271   bool is_one_byte = this->IsOneByteRepresentation();
   2272   bool is_internalized = this->IsInternalizedString();
   2273   bool has_pointers = this->IsConsString() || this->IsSlicedString();
   2274 
   2275   // Morph the string to an external string by replacing the map and
   2276   // reinitializing the fields.  This won't work if the space the existing
   2277   // string occupies is too small for a regular  external string.
   2278   // Instead, we resort to a short external string instead, omitting
   2279   // the field caching the address of the backing store.  When we encounter
   2280   // short external strings in generated code, we need to bailout to runtime.
   2281   Map* new_map;
   2282   if (size < ExternalString::kSize) {
   2283     new_map = is_internalized
   2284         ? (is_one_byte
   2285            ? heap->short_external_internalized_string_with_one_byte_data_map()
   2286            : heap->short_external_internalized_string_map())
   2287         : (is_one_byte ? heap->short_external_string_with_one_byte_data_map()
   2288                        : heap->short_external_string_map());
   2289   } else {
   2290     new_map = is_internalized
   2291         ? (is_one_byte
   2292            ? heap->external_internalized_string_with_one_byte_data_map()
   2293            : heap->external_internalized_string_map())
   2294         : (is_one_byte ? heap->external_string_with_one_byte_data_map()
   2295                        : heap->external_string_map());
   2296   }
   2297 
   2298   // Byte size of the external String object.
   2299   int new_size = this->SizeFromMap(new_map);
   2300   heap->CreateFillerObjectAt(this->address() + new_size, size - new_size,
   2301                              ClearRecordedSlots::kNo);
   2302   if (has_pointers) {
   2303     heap->ClearRecordedSlotRange(this->address(), this->address() + new_size);
   2304   }
   2305 
   2306   // We are storing the new map using release store after creating a filler for
   2307   // the left-over space to avoid races with the sweeper thread.
   2308   this->synchronized_set_map(new_map);
   2309 
   2310   ExternalTwoByteString* self = ExternalTwoByteString::cast(this);
   2311   self->set_resource(resource);
   2312   if (is_internalized) self->Hash();  // Force regeneration of the hash value.
   2313 
   2314   heap->AdjustLiveBytes(this, new_size - size, Heap::CONCURRENT_TO_SWEEPER);
   2315   return true;
   2316 }
   2317 
   2318 
   2319 bool String::MakeExternal(v8::String::ExternalOneByteStringResource* resource) {
   2320   // Externalizing twice leaks the external resource, so it's
   2321   // prohibited by the API.
   2322   DCHECK(!this->IsExternalString());
   2323   DCHECK(!resource->IsCompressible());
   2324 #ifdef ENABLE_SLOW_DCHECKS
   2325   if (FLAG_enable_slow_asserts) {
   2326     // Assert that the resource and the string are equivalent.
   2327     DCHECK(static_cast<size_t>(this->length()) == resource->length());
   2328     if (this->IsTwoByteRepresentation()) {
   2329       ScopedVector<uint16_t> smart_chars(this->length());
   2330       String::WriteToFlat(this, smart_chars.start(), 0, this->length());
   2331       DCHECK(String::IsOneByte(smart_chars.start(), this->length()));
   2332     }
   2333     ScopedVector<char> smart_chars(this->length());
   2334     String::WriteToFlat(this, smart_chars.start(), 0, this->length());
   2335     DCHECK(memcmp(smart_chars.start(),
   2336                   resource->data(),
   2337                   resource->length() * sizeof(smart_chars[0])) == 0);
   2338   }
   2339 #endif  // DEBUG
   2340   int size = this->Size();  // Byte size of the original string.
   2341   // Abort if size does not allow in-place conversion.
   2342   if (size < ExternalString::kShortSize) return false;
   2343   Heap* heap = GetHeap();
   2344   bool is_internalized = this->IsInternalizedString();
   2345   bool has_pointers = this->IsConsString() || this->IsSlicedString();
   2346 
   2347   // Morph the string to an external string by replacing the map and
   2348   // reinitializing the fields.  This won't work if the space the existing
   2349   // string occupies is too small for a regular  external string.
   2350   // Instead, we resort to a short external string instead, omitting
   2351   // the field caching the address of the backing store.  When we encounter
   2352   // short external strings in generated code, we need to bailout to runtime.
   2353   Map* new_map;
   2354   if (size < ExternalString::kSize) {
   2355     new_map = is_internalized
   2356                   ? heap->short_external_one_byte_internalized_string_map()
   2357                   : heap->short_external_one_byte_string_map();
   2358   } else {
   2359     new_map = is_internalized
   2360                   ? heap->external_one_byte_internalized_string_map()
   2361                   : heap->external_one_byte_string_map();
   2362   }
   2363 
   2364   // Byte size of the external String object.
   2365   int new_size = this->SizeFromMap(new_map);
   2366   heap->CreateFillerObjectAt(this->address() + new_size, size - new_size,
   2367                              ClearRecordedSlots::kNo);
   2368   if (has_pointers) {
   2369     heap->ClearRecordedSlotRange(this->address(), this->address() + new_size);
   2370   }
   2371 
   2372   // We are storing the new map using release store after creating a filler for
   2373   // the left-over space to avoid races with the sweeper thread.
   2374   this->synchronized_set_map(new_map);
   2375 
   2376   ExternalOneByteString* self = ExternalOneByteString::cast(this);
   2377   self->set_resource(resource);
   2378   if (is_internalized) self->Hash();  // Force regeneration of the hash value.
   2379 
   2380   heap->AdjustLiveBytes(this, new_size - size, Heap::CONCURRENT_TO_SWEEPER);
   2381   return true;
   2382 }
   2383 
   2384 void String::StringShortPrint(StringStream* accumulator, bool show_details) {
   2385   int len = length();
   2386   if (len > kMaxShortPrintLength) {
   2387     accumulator->Add("<Very long string[%u]>", len);
   2388     return;
   2389   }
   2390 
   2391   if (!LooksValid()) {
   2392     accumulator->Add("<Invalid String>");
   2393     return;
   2394   }
   2395 
   2396   StringCharacterStream stream(this);
   2397 
   2398   bool truncated = false;
   2399   if (len > kMaxShortPrintLength) {
   2400     len = kMaxShortPrintLength;
   2401     truncated = true;
   2402   }
   2403   bool one_byte = true;
   2404   for (int i = 0; i < len; i++) {
   2405     uint16_t c = stream.GetNext();
   2406 
   2407     if (c < 32 || c >= 127) {
   2408       one_byte = false;
   2409     }
   2410   }
   2411   stream.Reset(this);
   2412   if (one_byte) {
   2413     if (show_details) accumulator->Add("<String[%u]: ", length());
   2414     for (int i = 0; i < len; i++) {
   2415       accumulator->Put(static_cast<char>(stream.GetNext()));
   2416     }
   2417     if (show_details) accumulator->Put('>');
   2418   } else {
   2419     // Backslash indicates that the string contains control
   2420     // characters and that backslashes are therefore escaped.
   2421     if (show_details) accumulator->Add("<String[%u]\\: ", length());
   2422     for (int i = 0; i < len; i++) {
   2423       uint16_t c = stream.GetNext();
   2424       if (c == '\n') {
   2425         accumulator->Add("\\n");
   2426       } else if (c == '\r') {
   2427         accumulator->Add("\\r");
   2428       } else if (c == '\\') {
   2429         accumulator->Add("\\\\");
   2430       } else if (c < 32 || c > 126) {
   2431         accumulator->Add("\\x%02x", c);
   2432       } else {
   2433         accumulator->Put(static_cast<char>(c));
   2434       }
   2435     }
   2436     if (truncated) {
   2437       accumulator->Put('.');
   2438       accumulator->Put('.');
   2439       accumulator->Put('.');
   2440     }
   2441     if (show_details) accumulator->Put('>');
   2442   }
   2443   return;
   2444 }
   2445 
   2446 
   2447 void String::PrintUC16(std::ostream& os, int start, int end) {  // NOLINT
   2448   if (end < 0) end = length();
   2449   StringCharacterStream stream(this, start);
   2450   for (int i = start; i < end && stream.HasMore(); i++) {
   2451     os << AsUC16(stream.GetNext());
   2452   }
   2453 }
   2454 
   2455 
   2456 void JSObject::JSObjectShortPrint(StringStream* accumulator) {
   2457   switch (map()->instance_type()) {
   2458     case JS_ARRAY_TYPE: {
   2459       double length = JSArray::cast(this)->length()->IsUndefined(GetIsolate())
   2460                           ? 0
   2461                           : JSArray::cast(this)->length()->Number();
   2462       accumulator->Add("<JS Array[%u]>", static_cast<uint32_t>(length));
   2463       break;
   2464     }
   2465     case JS_BOUND_FUNCTION_TYPE: {
   2466       JSBoundFunction* bound_function = JSBoundFunction::cast(this);
   2467       accumulator->Add("<JS BoundFunction");
   2468       accumulator->Add(
   2469           " (BoundTargetFunction %p)>",
   2470           reinterpret_cast<void*>(bound_function->bound_target_function()));
   2471       break;
   2472     }
   2473     case JS_WEAK_MAP_TYPE: {
   2474       accumulator->Add("<JS WeakMap>");
   2475       break;
   2476     }
   2477     case JS_WEAK_SET_TYPE: {
   2478       accumulator->Add("<JS WeakSet>");
   2479       break;
   2480     }
   2481     case JS_REGEXP_TYPE: {
   2482       accumulator->Add("<JS RegExp>");
   2483       break;
   2484     }
   2485     case JS_FUNCTION_TYPE: {
   2486       JSFunction* function = JSFunction::cast(this);
   2487       Object* fun_name = function->shared()->DebugName();
   2488       bool printed = false;
   2489       if (fun_name->IsString()) {
   2490         String* str = String::cast(fun_name);
   2491         if (str->length() > 0) {
   2492           accumulator->Add("<JS Function ");
   2493           accumulator->Put(str);
   2494           printed = true;
   2495         }
   2496       }
   2497       if (!printed) {
   2498         accumulator->Add("<JS Function");
   2499       }
   2500       if (FLAG_trace_file_names) {
   2501         Object* source_name =
   2502             Script::cast(function->shared()->script())->name();
   2503         if (source_name->IsString()) {
   2504           String* str = String::cast(source_name);
   2505           if (str->length() > 0) {
   2506             accumulator->Add(" <");
   2507             accumulator->Put(str);
   2508             accumulator->Add(">");
   2509           }
   2510         }
   2511       }
   2512       accumulator->Add(" (SharedFunctionInfo %p)",
   2513                        reinterpret_cast<void*>(function->shared()));
   2514       accumulator->Put('>');
   2515       break;
   2516     }
   2517     case JS_GENERATOR_OBJECT_TYPE: {
   2518       accumulator->Add("<JS Generator>");
   2519       break;
   2520     }
   2521     // All other JSObjects are rather similar to each other (JSObject,
   2522     // JSGlobalProxy, JSGlobalObject, JSUndetectable, JSValue).
   2523     default: {
   2524       Map* map_of_this = map();
   2525       Heap* heap = GetHeap();
   2526       Object* constructor = map_of_this->GetConstructor();
   2527       bool printed = false;
   2528       if (constructor->IsHeapObject() &&
   2529           !heap->Contains(HeapObject::cast(constructor))) {
   2530         accumulator->Add("!!!INVALID CONSTRUCTOR!!!");
   2531       } else {
   2532         bool global_object = IsJSGlobalProxy();
   2533         if (constructor->IsJSFunction()) {
   2534           if (!heap->Contains(JSFunction::cast(constructor)->shared())) {
   2535             accumulator->Add("!!!INVALID SHARED ON CONSTRUCTOR!!!");
   2536           } else {
   2537             Object* constructor_name =
   2538                 JSFunction::cast(constructor)->shared()->name();
   2539             if (constructor_name->IsString()) {
   2540               String* str = String::cast(constructor_name);
   2541               if (str->length() > 0) {
   2542                 bool vowel = AnWord(str);
   2543                 accumulator->Add("<%sa%s ",
   2544                        global_object ? "Global Object: " : "",
   2545                        vowel ? "n" : "");
   2546                 accumulator->Put(str);
   2547                 accumulator->Add(" with %smap %p",
   2548                     map_of_this->is_deprecated() ? "deprecated " : "",
   2549                     map_of_this);
   2550                 printed = true;
   2551               }
   2552             }
   2553           }
   2554         }
   2555         if (!printed) {
   2556           accumulator->Add("<JS %sObject", global_object ? "Global " : "");
   2557         }
   2558       }
   2559       if (IsJSValue()) {
   2560         accumulator->Add(" value = ");
   2561         JSValue::cast(this)->value()->ShortPrint(accumulator);
   2562       }
   2563       accumulator->Put('>');
   2564       break;
   2565     }
   2566   }
   2567 }
   2568 
   2569 
   2570 void JSObject::PrintElementsTransition(
   2571     FILE* file, Handle<JSObject> object,
   2572     ElementsKind from_kind, Handle<FixedArrayBase> from_elements,
   2573     ElementsKind to_kind, Handle<FixedArrayBase> to_elements) {
   2574   if (from_kind != to_kind) {
   2575     OFStream os(file);
   2576     os << "elements transition [" << ElementsKindToString(from_kind) << " -> "
   2577        << ElementsKindToString(to_kind) << "] in ";
   2578     JavaScriptFrame::PrintTop(object->GetIsolate(), file, false, true);
   2579     PrintF(file, " for ");
   2580     object->ShortPrint(file);
   2581     PrintF(file, " from ");
   2582     from_elements->ShortPrint(file);
   2583     PrintF(file, " to ");
   2584     to_elements->ShortPrint(file);
   2585     PrintF(file, "\n");
   2586   }
   2587 }
   2588 
   2589 
   2590 // static
   2591 MaybeHandle<JSFunction> Map::GetConstructorFunction(
   2592     Handle<Map> map, Handle<Context> native_context) {
   2593   if (map->IsPrimitiveMap()) {
   2594     int const constructor_function_index = map->GetConstructorFunctionIndex();
   2595     if (constructor_function_index != kNoConstructorFunctionIndex) {
   2596       return handle(
   2597           JSFunction::cast(native_context->get(constructor_function_index)));
   2598     }
   2599   }
   2600   return MaybeHandle<JSFunction>();
   2601 }
   2602 
   2603 
   2604 void Map::PrintReconfiguration(FILE* file, int modify_index, PropertyKind kind,
   2605                                PropertyAttributes attributes) {
   2606   OFStream os(file);
   2607   os << "[reconfiguring]";
   2608   Name* name = instance_descriptors()->GetKey(modify_index);
   2609   if (name->IsString()) {
   2610     String::cast(name)->PrintOn(file);
   2611   } else {
   2612     os << "{symbol " << static_cast<void*>(name) << "}";
   2613   }
   2614   os << ": " << (kind == kData ? "kData" : "ACCESSORS") << ", attrs: ";
   2615   os << attributes << " [";
   2616   JavaScriptFrame::PrintTop(GetIsolate(), file, false, true);
   2617   os << "]\n";
   2618 }
   2619 
   2620 void Map::PrintGeneralization(
   2621     FILE* file, const char* reason, int modify_index, int split,
   2622     int descriptors, bool constant_to_field, Representation old_representation,
   2623     Representation new_representation, MaybeHandle<FieldType> old_field_type,
   2624     MaybeHandle<Object> old_value, MaybeHandle<FieldType> new_field_type,
   2625     MaybeHandle<Object> new_value) {
   2626   OFStream os(file);
   2627   os << "[generalizing]";
   2628   Name* name = instance_descriptors()->GetKey(modify_index);
   2629   if (name->IsString()) {
   2630     String::cast(name)->PrintOn(file);
   2631   } else {
   2632     os << "{symbol " << static_cast<void*>(name) << "}";
   2633   }
   2634   os << ":";
   2635   if (constant_to_field) {
   2636     os << "c";
   2637   } else {
   2638     os << old_representation.Mnemonic() << "{";
   2639     if (old_field_type.is_null()) {
   2640       os << Brief(*(old_value.ToHandleChecked()));
   2641     } else {
   2642       old_field_type.ToHandleChecked()->PrintTo(os);
   2643     }
   2644     os << "}";
   2645   }
   2646   os << "->" << new_representation.Mnemonic() << "{";
   2647   if (new_field_type.is_null()) {
   2648     os << Brief(*(new_value.ToHandleChecked()));
   2649   } else {
   2650     new_field_type.ToHandleChecked()->PrintTo(os);
   2651   }
   2652   os << "} (";
   2653   if (strlen(reason) > 0) {
   2654     os << reason;
   2655   } else {
   2656     os << "+" << (descriptors - split) << " maps";
   2657   }
   2658   os << ") [";
   2659   JavaScriptFrame::PrintTop(GetIsolate(), file, false, true);
   2660   os << "]\n";
   2661 }
   2662 
   2663 
   2664 void JSObject::PrintInstanceMigration(FILE* file,
   2665                                       Map* original_map,
   2666                                       Map* new_map) {
   2667   PrintF(file, "[migrating]");
   2668   DescriptorArray* o = original_map->instance_descriptors();
   2669   DescriptorArray* n = new_map->instance_descriptors();
   2670   for (int i = 0; i < original_map->NumberOfOwnDescriptors(); i++) {
   2671     Representation o_r = o->GetDetails(i).representation();
   2672     Representation n_r = n->GetDetails(i).representation();
   2673     if (!o_r.Equals(n_r)) {
   2674       String::cast(o->GetKey(i))->PrintOn(file);
   2675       PrintF(file, ":%s->%s ", o_r.Mnemonic(), n_r.Mnemonic());
   2676     } else if (o->GetDetails(i).type() == DATA_CONSTANT &&
   2677                n->GetDetails(i).type() == DATA) {
   2678       Name* name = o->GetKey(i);
   2679       if (name->IsString()) {
   2680         String::cast(name)->PrintOn(file);
   2681       } else {
   2682         PrintF(file, "{symbol %p}", static_cast<void*>(name));
   2683       }
   2684       PrintF(file, " ");
   2685     }
   2686   }
   2687   PrintF(file, "\n");
   2688 }
   2689 
   2690 
   2691 void HeapObject::HeapObjectShortPrint(std::ostream& os) {  // NOLINT
   2692   Heap* heap = GetHeap();
   2693   Isolate* isolate = heap->isolate();
   2694   if (!heap->Contains(this)) {
   2695     os << "!!!INVALID POINTER!!!";
   2696     return;
   2697   }
   2698   if (!heap->Contains(map())) {
   2699     os << "!!!INVALID MAP!!!";
   2700     return;
   2701   }
   2702 
   2703   os << this << " ";
   2704 
   2705   if (IsString()) {
   2706     HeapStringAllocator allocator;
   2707     StringStream accumulator(&allocator);
   2708     String::cast(this)->StringShortPrint(&accumulator);
   2709     os << accumulator.ToCString().get();
   2710     return;
   2711   }
   2712   if (IsJSObject()) {
   2713     HeapStringAllocator allocator;
   2714     StringStream accumulator(&allocator);
   2715     JSObject::cast(this)->JSObjectShortPrint(&accumulator);
   2716     os << accumulator.ToCString().get();
   2717     return;
   2718   }
   2719   switch (map()->instance_type()) {
   2720     case MAP_TYPE:
   2721       os << "<Map(" << ElementsKindToString(Map::cast(this)->elements_kind())
   2722          << ")>";
   2723       break;
   2724     case FIXED_ARRAY_TYPE:
   2725       os << "<FixedArray[" << FixedArray::cast(this)->length() << "]>";
   2726       break;
   2727     case FIXED_DOUBLE_ARRAY_TYPE:
   2728       os << "<FixedDoubleArray[" << FixedDoubleArray::cast(this)->length()
   2729          << "]>";
   2730       break;
   2731     case BYTE_ARRAY_TYPE:
   2732       os << "<ByteArray[" << ByteArray::cast(this)->length() << "]>";
   2733       break;
   2734     case BYTECODE_ARRAY_TYPE:
   2735       os << "<BytecodeArray[" << BytecodeArray::cast(this)->length() << "]>";
   2736       break;
   2737     case TRANSITION_ARRAY_TYPE:
   2738       os << "<TransitionArray[" << TransitionArray::cast(this)->length()
   2739          << "]>";
   2740       break;
   2741     case FREE_SPACE_TYPE:
   2742       os << "<FreeSpace[" << FreeSpace::cast(this)->size() << "]>";
   2743       break;
   2744 #define TYPED_ARRAY_SHORT_PRINT(Type, type, TYPE, ctype, size)                \
   2745   case FIXED_##TYPE##_ARRAY_TYPE:                                             \
   2746     os << "<Fixed" #Type "Array[" << Fixed##Type##Array::cast(this)->length() \
   2747        << "]>";                                                               \
   2748     break;
   2749 
   2750     TYPED_ARRAYS(TYPED_ARRAY_SHORT_PRINT)
   2751 #undef TYPED_ARRAY_SHORT_PRINT
   2752 
   2753     case SHARED_FUNCTION_INFO_TYPE: {
   2754       SharedFunctionInfo* shared = SharedFunctionInfo::cast(this);
   2755       std::unique_ptr<char[]> debug_name = shared->DebugName()->ToCString();
   2756       if (debug_name[0] != 0) {
   2757         os << "<SharedFunctionInfo " << debug_name.get() << ">";
   2758       } else {
   2759         os << "<SharedFunctionInfo>";
   2760       }
   2761       break;
   2762     }
   2763     case JS_MESSAGE_OBJECT_TYPE:
   2764       os << "<JSMessageObject>";
   2765       break;
   2766 #define MAKE_STRUCT_CASE(NAME, Name, name) \
   2767   case NAME##_TYPE:                        \
   2768     os << "<" #Name ">";                   \
   2769     break;
   2770   STRUCT_LIST(MAKE_STRUCT_CASE)
   2771 #undef MAKE_STRUCT_CASE
   2772     case CODE_TYPE: {
   2773       Code* code = Code::cast(this);
   2774       os << "<Code: " << Code::Kind2String(code->kind()) << ">";
   2775       break;
   2776     }
   2777     case ODDBALL_TYPE: {
   2778       if (IsUndefined(isolate)) {
   2779         os << "<undefined>";
   2780       } else if (IsTheHole(isolate)) {
   2781         os << "<the hole>";
   2782       } else if (IsNull(isolate)) {
   2783         os << "<null>";
   2784       } else if (IsTrue(isolate)) {
   2785         os << "<true>";
   2786       } else if (IsFalse(isolate)) {
   2787         os << "<false>";
   2788       } else {
   2789         os << "<Odd Oddball: ";
   2790         os << Oddball::cast(this)->to_string()->ToCString().get();
   2791         os << ">";
   2792       }
   2793       break;
   2794     }
   2795     case SYMBOL_TYPE: {
   2796       Symbol* symbol = Symbol::cast(this);
   2797       symbol->SymbolShortPrint(os);
   2798       break;
   2799     }
   2800     case HEAP_NUMBER_TYPE: {
   2801       os << "<Number: ";
   2802       HeapNumber::cast(this)->HeapNumberPrint(os);
   2803       os << ">";
   2804       break;
   2805     }
   2806     case MUTABLE_HEAP_NUMBER_TYPE: {
   2807       os << "<MutableNumber: ";
   2808       HeapNumber::cast(this)->HeapNumberPrint(os);
   2809       os << '>';
   2810       break;
   2811     }
   2812     case SIMD128_VALUE_TYPE: {
   2813 #define SIMD128_TYPE(TYPE, Type, type, lane_count, lane_type) \
   2814   if (Is##Type()) {                                           \
   2815     os << "<" #Type ">";                                      \
   2816     break;                                                    \
   2817   }
   2818       SIMD128_TYPES(SIMD128_TYPE)
   2819 #undef SIMD128_TYPE
   2820       UNREACHABLE();
   2821       break;
   2822     }
   2823     case JS_PROXY_TYPE:
   2824       os << "<JSProxy>";
   2825       break;
   2826     case FOREIGN_TYPE:
   2827       os << "<Foreign>";
   2828       break;
   2829     case CELL_TYPE: {
   2830       os << "Cell for ";
   2831       HeapStringAllocator allocator;
   2832       StringStream accumulator(&allocator);
   2833       Cell::cast(this)->value()->ShortPrint(&accumulator);
   2834       os << accumulator.ToCString().get();
   2835       break;
   2836     }
   2837     case PROPERTY_CELL_TYPE: {
   2838       os << "PropertyCell for ";
   2839       HeapStringAllocator allocator;
   2840       StringStream accumulator(&allocator);
   2841       PropertyCell* cell = PropertyCell::cast(this);
   2842       cell->value()->ShortPrint(&accumulator);
   2843       os << accumulator.ToCString().get();
   2844       break;
   2845     }
   2846     case WEAK_CELL_TYPE: {
   2847       os << "WeakCell for ";
   2848       HeapStringAllocator allocator;
   2849       StringStream accumulator(&allocator);
   2850       WeakCell::cast(this)->value()->ShortPrint(&accumulator);
   2851       os << accumulator.ToCString().get();
   2852       break;
   2853     }
   2854     default:
   2855       os << "<Other heap object (" << map()->instance_type() << ")>";
   2856       break;
   2857   }
   2858 }
   2859 
   2860 
   2861 void HeapObject::Iterate(ObjectVisitor* v) { IterateFast<ObjectVisitor>(v); }
   2862 
   2863 
   2864 void HeapObject::IterateBody(ObjectVisitor* v) {
   2865   Map* m = map();
   2866   IterateBodyFast<ObjectVisitor>(m->instance_type(), SizeFromMap(m), v);
   2867 }
   2868 
   2869 
   2870 void HeapObject::IterateBody(InstanceType type, int object_size,
   2871                              ObjectVisitor* v) {
   2872   IterateBodyFast<ObjectVisitor>(type, object_size, v);
   2873 }
   2874 
   2875 
   2876 struct CallIsValidSlot {
   2877   template <typename BodyDescriptor>
   2878   static bool apply(HeapObject* obj, int offset, int) {
   2879     return BodyDescriptor::IsValidSlot(obj, offset);
   2880   }
   2881 };
   2882 
   2883 
   2884 bool HeapObject::IsValidSlot(int offset) {
   2885   DCHECK_NE(0, offset);
   2886   return BodyDescriptorApply<CallIsValidSlot, bool>(map()->instance_type(),
   2887                                                     this, offset, 0);
   2888 }
   2889 
   2890 
   2891 bool HeapNumber::HeapNumberBooleanValue() {
   2892   return DoubleToBoolean(value());
   2893 }
   2894 
   2895 
   2896 void HeapNumber::HeapNumberPrint(std::ostream& os) {  // NOLINT
   2897   os << value();
   2898 }
   2899 
   2900 
   2901 #define FIELD_ADDR_CONST(p, offset) \
   2902   (reinterpret_cast<const byte*>(p) + offset - kHeapObjectTag)
   2903 
   2904 #define READ_INT32_FIELD(p, offset) \
   2905   (*reinterpret_cast<const int32_t*>(FIELD_ADDR_CONST(p, offset)))
   2906 
   2907 #define READ_INT64_FIELD(p, offset) \
   2908   (*reinterpret_cast<const int64_t*>(FIELD_ADDR_CONST(p, offset)))
   2909 
   2910 #define READ_BYTE_FIELD(p, offset) \
   2911   (*reinterpret_cast<const byte*>(FIELD_ADDR_CONST(p, offset)))
   2912 
   2913 
   2914 // static
   2915 Handle<String> Simd128Value::ToString(Handle<Simd128Value> input) {
   2916 #define SIMD128_TYPE(TYPE, Type, type, lane_count, lane_type) \
   2917   if (input->Is##Type()) return Type::ToString(Handle<Type>::cast(input));
   2918   SIMD128_TYPES(SIMD128_TYPE)
   2919 #undef SIMD128_TYPE
   2920   UNREACHABLE();
   2921   return Handle<String>::null();
   2922 }
   2923 
   2924 
   2925 // static
   2926 Handle<String> Float32x4::ToString(Handle<Float32x4> input) {
   2927   Isolate* const isolate = input->GetIsolate();
   2928   char arr[100];
   2929   Vector<char> buffer(arr, arraysize(arr));
   2930   std::ostringstream os;
   2931   os << "SIMD.Float32x4("
   2932      << std::string(DoubleToCString(input->get_lane(0), buffer)) << ", "
   2933      << std::string(DoubleToCString(input->get_lane(1), buffer)) << ", "
   2934      << std::string(DoubleToCString(input->get_lane(2), buffer)) << ", "
   2935      << std::string(DoubleToCString(input->get_lane(3), buffer)) << ")";
   2936   return isolate->factory()->NewStringFromAsciiChecked(os.str().c_str());
   2937 }
   2938 
   2939 
   2940 #define SIMD128_BOOL_TO_STRING(Type, lane_count)                            \
   2941   Handle<String> Type::ToString(Handle<Type> input) {                       \
   2942     Isolate* const isolate = input->GetIsolate();                           \
   2943     std::ostringstream os;                                                  \
   2944     os << "SIMD." #Type "(";                                                \
   2945     os << (input->get_lane(0) ? "true" : "false");                          \
   2946     for (int i = 1; i < lane_count; i++) {                                  \
   2947       os << ", " << (input->get_lane(i) ? "true" : "false");                \
   2948     }                                                                       \
   2949     os << ")";                                                              \
   2950     return isolate->factory()->NewStringFromAsciiChecked(os.str().c_str()); \
   2951   }
   2952 SIMD128_BOOL_TO_STRING(Bool32x4, 4)
   2953 SIMD128_BOOL_TO_STRING(Bool16x8, 8)
   2954 SIMD128_BOOL_TO_STRING(Bool8x16, 16)
   2955 #undef SIMD128_BOOL_TO_STRING
   2956 
   2957 
   2958 #define SIMD128_INT_TO_STRING(Type, lane_count)                             \
   2959   Handle<String> Type::ToString(Handle<Type> input) {                       \
   2960     Isolate* const isolate = input->GetIsolate();                           \
   2961     char arr[100];                                                          \
   2962     Vector<char> buffer(arr, arraysize(arr));                               \
   2963     std::ostringstream os;                                                  \
   2964     os << "SIMD." #Type "(";                                                \
   2965     os << IntToCString(input->get_lane(0), buffer);                         \
   2966     for (int i = 1; i < lane_count; i++) {                                  \
   2967       os << ", " << IntToCString(input->get_lane(i), buffer);               \
   2968     }                                                                       \
   2969     os << ")";                                                              \
   2970     return isolate->factory()->NewStringFromAsciiChecked(os.str().c_str()); \
   2971   }
   2972 SIMD128_INT_TO_STRING(Int32x4, 4)
   2973 SIMD128_INT_TO_STRING(Uint32x4, 4)
   2974 SIMD128_INT_TO_STRING(Int16x8, 8)
   2975 SIMD128_INT_TO_STRING(Uint16x8, 8)
   2976 SIMD128_INT_TO_STRING(Int8x16, 16)
   2977 SIMD128_INT_TO_STRING(Uint8x16, 16)
   2978 #undef SIMD128_INT_TO_STRING
   2979 
   2980 
   2981 bool Simd128Value::BitwiseEquals(const Simd128Value* other) const {
   2982   return READ_INT64_FIELD(this, kValueOffset) ==
   2983              READ_INT64_FIELD(other, kValueOffset) &&
   2984          READ_INT64_FIELD(this, kValueOffset + kInt64Size) ==
   2985              READ_INT64_FIELD(other, kValueOffset + kInt64Size);
   2986 }
   2987 
   2988 
   2989 uint32_t Simd128Value::Hash() const {
   2990   uint32_t seed = v8::internal::kZeroHashSeed;
   2991   uint32_t hash;
   2992   hash = ComputeIntegerHash(READ_INT32_FIELD(this, kValueOffset), seed);
   2993   hash = ComputeIntegerHash(
   2994       READ_INT32_FIELD(this, kValueOffset + 1 * kInt32Size), hash * 31);
   2995   hash = ComputeIntegerHash(
   2996       READ_INT32_FIELD(this, kValueOffset + 2 * kInt32Size), hash * 31);
   2997   hash = ComputeIntegerHash(
   2998       READ_INT32_FIELD(this, kValueOffset + 3 * kInt32Size), hash * 31);
   2999   return hash;
   3000 }
   3001 
   3002 
   3003 void Simd128Value::CopyBits(void* destination) const {
   3004   memcpy(destination, &READ_BYTE_FIELD(this, kValueOffset), kSimd128Size);
   3005 }
   3006 
   3007 
   3008 String* JSReceiver::class_name() {
   3009   if (IsFunction()) {
   3010     return GetHeap()->Function_string();
   3011   }
   3012   Object* maybe_constructor = map()->GetConstructor();
   3013   if (maybe_constructor->IsJSFunction()) {
   3014     JSFunction* constructor = JSFunction::cast(maybe_constructor);
   3015     return String::cast(constructor->shared()->instance_class_name());
   3016   }
   3017   // If the constructor is not present, return "Object".
   3018   return GetHeap()->Object_string();
   3019 }
   3020 
   3021 
   3022 // static
   3023 Handle<String> JSReceiver::GetConstructorName(Handle<JSReceiver> receiver) {
   3024   Isolate* isolate = receiver->GetIsolate();
   3025 
   3026   // If the object was instantiated simply with base == new.target, the
   3027   // constructor on the map provides the most accurate name.
   3028   // Don't provide the info for prototypes, since their constructors are
   3029   // reclaimed and replaced by Object in OptimizeAsPrototype.
   3030   if (!receiver->IsJSProxy() && receiver->map()->new_target_is_base() &&
   3031       !receiver->map()->is_prototype_map()) {
   3032     Object* maybe_constructor = receiver->map()->GetConstructor();
   3033     if (maybe_constructor->IsJSFunction()) {
   3034       JSFunction* constructor = JSFunction::cast(maybe_constructor);
   3035       String* name = String::cast(constructor->shared()->name());
   3036       if (name->length() == 0) name = constructor->shared()->inferred_name();
   3037       if (name->length() != 0 &&
   3038           !name->Equals(isolate->heap()->Object_string())) {
   3039         return handle(name, isolate);
   3040       }
   3041     }
   3042   }
   3043 
   3044   Handle<Object> maybe_tag = JSReceiver::GetDataProperty(
   3045       receiver, isolate->factory()->to_string_tag_symbol());
   3046   if (maybe_tag->IsString()) return Handle<String>::cast(maybe_tag);
   3047 
   3048   PrototypeIterator iter(isolate, receiver);
   3049   if (iter.IsAtEnd()) return handle(receiver->class_name());
   3050   Handle<JSReceiver> start = PrototypeIterator::GetCurrent<JSReceiver>(iter);
   3051   LookupIterator it(receiver, isolate->factory()->constructor_string(), start,
   3052                     LookupIterator::PROTOTYPE_CHAIN_SKIP_INTERCEPTOR);
   3053   Handle<Object> maybe_constructor = JSReceiver::GetDataProperty(&it);
   3054   Handle<String> result = isolate->factory()->Object_string();
   3055   if (maybe_constructor->IsJSFunction()) {
   3056     JSFunction* constructor = JSFunction::cast(*maybe_constructor);
   3057     String* name = String::cast(constructor->shared()->name());
   3058     if (name->length() == 0) name = constructor->shared()->inferred_name();
   3059     if (name->length() > 0) result = handle(name, isolate);
   3060   }
   3061 
   3062   return result.is_identical_to(isolate->factory()->Object_string())
   3063              ? handle(receiver->class_name())
   3064              : result;
   3065 }
   3066 
   3067 
   3068 Context* JSReceiver::GetCreationContext() {
   3069   JSReceiver* receiver = this;
   3070   while (receiver->IsJSBoundFunction()) {
   3071     receiver = JSBoundFunction::cast(receiver)->bound_target_function();
   3072   }
   3073   Object* constructor = receiver->map()->GetConstructor();
   3074   JSFunction* function;
   3075   if (constructor->IsJSFunction()) {
   3076     function = JSFunction::cast(constructor);
   3077   } else {
   3078     // Functions have null as a constructor,
   3079     // but any JSFunction knows its context immediately.
   3080     CHECK(receiver->IsJSFunction());
   3081     function = JSFunction::cast(receiver);
   3082   }
   3083 
   3084   return function->context()->native_context();
   3085 }
   3086 
   3087 static Handle<Object> WrapType(Handle<FieldType> type) {
   3088   if (type->IsClass()) return Map::WeakCellForMap(type->AsClass());
   3089   return type;
   3090 }
   3091 
   3092 MaybeHandle<Map> Map::CopyWithField(Handle<Map> map, Handle<Name> name,
   3093                                     Handle<FieldType> type,
   3094                                     PropertyAttributes attributes,
   3095                                     Representation representation,
   3096                                     TransitionFlag flag) {
   3097   DCHECK(DescriptorArray::kNotFound ==
   3098          map->instance_descriptors()->Search(
   3099              *name, map->NumberOfOwnDescriptors()));
   3100 
   3101   // Ensure the descriptor array does not get too big.
   3102   if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors) {
   3103     return MaybeHandle<Map>();
   3104   }
   3105 
   3106   Isolate* isolate = map->GetIsolate();
   3107 
   3108   // Compute the new index for new field.
   3109   int index = map->NextFreePropertyIndex();
   3110 
   3111   if (map->instance_type() == JS_CONTEXT_EXTENSION_OBJECT_TYPE) {
   3112     representation = Representation::Tagged();
   3113     type = FieldType::Any(isolate);
   3114   }
   3115 
   3116   Handle<Object> wrapped_type(WrapType(type));
   3117 
   3118   DataDescriptor new_field_desc(name, index, wrapped_type, attributes,
   3119                                 representation);
   3120   Handle<Map> new_map = Map::CopyAddDescriptor(map, &new_field_desc, flag);
   3121   int unused_property_fields = new_map->unused_property_fields() - 1;
   3122   if (unused_property_fields < 0) {
   3123     unused_property_fields += JSObject::kFieldsAdded;
   3124   }
   3125   new_map->set_unused_property_fields(unused_property_fields);
   3126   return new_map;
   3127 }
   3128 
   3129 
   3130 MaybeHandle<Map> Map::CopyWithConstant(Handle<Map> map,
   3131                                        Handle<Name> name,
   3132                                        Handle<Object> constant,
   3133                                        PropertyAttributes attributes,
   3134                                        TransitionFlag flag) {
   3135   // Ensure the descriptor array does not get too big.
   3136   if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors) {
   3137     return MaybeHandle<Map>();
   3138   }
   3139 
   3140   // Allocate new instance descriptors with (name, constant) added.
   3141   DataConstantDescriptor new_constant_desc(name, constant, attributes);
   3142   return Map::CopyAddDescriptor(map, &new_constant_desc, flag);
   3143 }
   3144 
   3145 const char* Representation::Mnemonic() const {
   3146   switch (kind_) {
   3147     case kNone: return "v";
   3148     case kTagged: return "t";
   3149     case kSmi: return "s";
   3150     case kDouble: return "d";
   3151     case kInteger32: return "i";
   3152     case kHeapObject: return "h";
   3153     case kExternal: return "x";
   3154     default:
   3155       UNREACHABLE();
   3156       return NULL;
   3157   }
   3158 }
   3159 
   3160 bool Map::InstancesNeedRewriting(Map* target) {
   3161   int target_number_of_fields = target->NumberOfFields();
   3162   int target_inobject = target->GetInObjectProperties();
   3163   int target_unused = target->unused_property_fields();
   3164   int old_number_of_fields;
   3165 
   3166   return InstancesNeedRewriting(target, target_number_of_fields,
   3167                                 target_inobject, target_unused,
   3168                                 &old_number_of_fields);
   3169 }
   3170 
   3171 bool Map::InstancesNeedRewriting(Map* target, int target_number_of_fields,
   3172                                  int target_inobject, int target_unused,
   3173                                  int* old_number_of_fields) {
   3174   // If fields were added (or removed), rewrite the instance.
   3175   *old_number_of_fields = NumberOfFields();
   3176   DCHECK(target_number_of_fields >= *old_number_of_fields);
   3177   if (target_number_of_fields != *old_number_of_fields) return true;
   3178 
   3179   // If smi descriptors were replaced by double descriptors, rewrite.
   3180   DescriptorArray* old_desc = instance_descriptors();
   3181   DescriptorArray* new_desc = target->instance_descriptors();
   3182   int limit = NumberOfOwnDescriptors();
   3183   for (int i = 0; i < limit; i++) {
   3184     if (new_desc->GetDetails(i).representation().IsDouble() !=
   3185         old_desc->GetDetails(i).representation().IsDouble()) {
   3186       return true;
   3187     }
   3188   }
   3189 
   3190   // If no fields were added, and no inobject properties were removed, setting
   3191   // the map is sufficient.
   3192   if (target_inobject == GetInObjectProperties()) return false;
   3193   // In-object slack tracking may have reduced the object size of the new map.
   3194   // In that case, succeed if all existing fields were inobject, and they still
   3195   // fit within the new inobject size.
   3196   DCHECK(target_inobject < GetInObjectProperties());
   3197   if (target_number_of_fields <= target_inobject) {
   3198     DCHECK(target_number_of_fields + target_unused == target_inobject);
   3199     return false;
   3200   }
   3201   // Otherwise, properties will need to be moved to the backing store.
   3202   return true;
   3203 }
   3204 
   3205 
   3206 // static
   3207 void JSObject::UpdatePrototypeUserRegistration(Handle<Map> old_map,
   3208                                                Handle<Map> new_map,
   3209                                                Isolate* isolate) {
   3210   DCHECK(old_map->is_prototype_map());
   3211   DCHECK(new_map->is_prototype_map());
   3212   bool was_registered = JSObject::UnregisterPrototypeUser(old_map, isolate);
   3213   new_map->set_prototype_info(old_map->prototype_info());
   3214   old_map->set_prototype_info(Smi::kZero);
   3215   if (FLAG_trace_prototype_users) {
   3216     PrintF("Moving prototype_info %p from map %p to map %p.\n",
   3217            reinterpret_cast<void*>(new_map->prototype_info()),
   3218            reinterpret_cast<void*>(*old_map),
   3219            reinterpret_cast<void*>(*new_map));
   3220   }
   3221   if (was_registered) {
   3222     if (new_map->prototype_info()->IsPrototypeInfo()) {
   3223       // The new map isn't registered with its prototype yet; reflect this fact
   3224       // in the PrototypeInfo it just inherited from the old map.
   3225       PrototypeInfo::cast(new_map->prototype_info())
   3226           ->set_registry_slot(PrototypeInfo::UNREGISTERED);
   3227     }
   3228     JSObject::LazyRegisterPrototypeUser(new_map, isolate);
   3229   }
   3230 }
   3231 
   3232 namespace {
   3233 // To migrate a fast instance to a fast map:
   3234 // - First check whether the instance needs to be rewritten. If not, simply
   3235 //   change the map.
   3236 // - Otherwise, allocate a fixed array large enough to hold all fields, in
   3237 //   addition to unused space.
   3238 // - Copy all existing properties in, in the following order: backing store
   3239 //   properties, unused fields, inobject properties.
   3240 // - If all allocation succeeded, commit the state atomically:
   3241 //   * Copy inobject properties from the backing store back into the object.
   3242 //   * Trim the difference in instance size of the object. This also cleanly
   3243 //     frees inobject properties that moved to the backing store.
   3244 //   * If there are properties left in the backing store, trim of the space used
   3245 //     to temporarily store the inobject properties.
   3246 //   * If there are properties left in the backing store, install the backing
   3247 //     store.
   3248 void MigrateFastToFast(Handle<JSObject> object, Handle<Map> new_map) {
   3249   Isolate* isolate = object->GetIsolate();
   3250   Handle<Map> old_map(object->map());
   3251   // In case of a regular transition.
   3252   if (new_map->GetBackPointer() == *old_map) {
   3253     // If the map does not add named properties, simply set the map.
   3254     if (old_map->NumberOfOwnDescriptors() ==
   3255         new_map->NumberOfOwnDescriptors()) {
   3256       object->synchronized_set_map(*new_map);
   3257       return;
   3258     }
   3259 
   3260     PropertyDetails details = new_map->GetLastDescriptorDetails();
   3261     // Either new_map adds an kDescriptor property, or a kField property for
   3262     // which there is still space, and which does not require a mutable double
   3263     // box (an out-of-object double).
   3264     if (details.location() == kDescriptor ||
   3265         (old_map->unused_property_fields() > 0 &&
   3266          ((FLAG_unbox_double_fields && object->properties()->length() == 0) ||
   3267           !details.representation().IsDouble()))) {
   3268       object->synchronized_set_map(*new_map);
   3269       return;
   3270     }
   3271 
   3272     // If there is still space in the object, we need to allocate a mutable
   3273     // double box.
   3274     if (old_map->unused_property_fields() > 0) {
   3275       FieldIndex index =
   3276           FieldIndex::ForDescriptor(*new_map, new_map->LastAdded());
   3277       DCHECK(details.representation().IsDouble());
   3278       DCHECK(!new_map->IsUnboxedDoubleField(index));
   3279       Handle<Object> value = isolate->factory()->NewHeapNumber(0, MUTABLE);
   3280       object->RawFastPropertyAtPut(index, *value);
   3281       object->synchronized_set_map(*new_map);
   3282       return;
   3283     }
   3284 
   3285     // This migration is a transition from a map that has run out of property
   3286     // space. Extend the backing store.
   3287     int grow_by = new_map->unused_property_fields() + 1;
   3288     Handle<FixedArray> old_storage = handle(object->properties(), isolate);
   3289     Handle<FixedArray> new_storage =
   3290         isolate->factory()->CopyFixedArrayAndGrow(old_storage, grow_by);
   3291 
   3292     // Properly initialize newly added property.
   3293     Handle<Object> value;
   3294     if (details.representation().IsDouble()) {
   3295       value = isolate->factory()->NewHeapNumber(0, MUTABLE);
   3296     } else {
   3297       value = isolate->factory()->uninitialized_value();
   3298     }
   3299     DCHECK_EQ(DATA, details.type());
   3300     int target_index = details.field_index() - new_map->GetInObjectProperties();
   3301     DCHECK(target_index >= 0);  // Must be a backing store index.
   3302     new_storage->set(target_index, *value);
   3303 
   3304     // From here on we cannot fail and we shouldn't GC anymore.
   3305     DisallowHeapAllocation no_allocation;
   3306 
   3307     // Set the new property value and do the map transition.
   3308     object->set_properties(*new_storage);
   3309     object->synchronized_set_map(*new_map);
   3310     return;
   3311   }
   3312 
   3313   int old_number_of_fields;
   3314   int number_of_fields = new_map->NumberOfFields();
   3315   int inobject = new_map->GetInObjectProperties();
   3316   int unused = new_map->unused_property_fields();
   3317 
   3318   // Nothing to do if no functions were converted to fields and no smis were
   3319   // converted to doubles.
   3320   if (!old_map->InstancesNeedRewriting(*new_map, number_of_fields, inobject,
   3321                                        unused, &old_number_of_fields)) {
   3322     object->synchronized_set_map(*new_map);
   3323     return;
   3324   }
   3325 
   3326   int total_size = number_of_fields + unused;
   3327   int external = total_size - inobject;
   3328 
   3329   Handle<FixedArray> array = isolate->factory()->NewFixedArray(total_size);
   3330 
   3331   Handle<DescriptorArray> old_descriptors(old_map->instance_descriptors());
   3332   Handle<DescriptorArray> new_descriptors(new_map->instance_descriptors());
   3333   int old_nof = old_map->NumberOfOwnDescriptors();
   3334   int new_nof = new_map->NumberOfOwnDescriptors();
   3335 
   3336   // This method only supports generalizing instances to at least the same
   3337   // number of properties.
   3338   DCHECK(old_nof <= new_nof);
   3339 
   3340   for (int i = 0; i < old_nof; i++) {
   3341     PropertyDetails details = new_descriptors->GetDetails(i);
   3342     if (details.type() != DATA) continue;
   3343     PropertyDetails old_details = old_descriptors->GetDetails(i);
   3344     Representation old_representation = old_details.representation();
   3345     Representation representation = details.representation();
   3346     Handle<Object> value;
   3347     if (old_details.type() == ACCESSOR_CONSTANT) {
   3348       // In case of kAccessor -> kData property reconfiguration, the property
   3349       // must already be prepared for data or certain type.
   3350       DCHECK(!details.representation().IsNone());
   3351       if (details.representation().IsDouble()) {
   3352         value = isolate->factory()->NewHeapNumber(0, MUTABLE);
   3353       } else {
   3354         value = isolate->factory()->uninitialized_value();
   3355       }
   3356     } else if (old_details.type() == DATA_CONSTANT) {
   3357       value = handle(old_descriptors->GetValue(i), isolate);
   3358       DCHECK(!old_representation.IsDouble() && !representation.IsDouble());
   3359     } else {
   3360       FieldIndex index = FieldIndex::ForDescriptor(*old_map, i);
   3361       if (object->IsUnboxedDoubleField(index)) {
   3362         double old = object->RawFastDoublePropertyAt(index);
   3363         value = isolate->factory()->NewHeapNumber(
   3364             old, representation.IsDouble() ? MUTABLE : IMMUTABLE);
   3365 
   3366       } else {
   3367         value = handle(object->RawFastPropertyAt(index), isolate);
   3368         if (!old_representation.IsDouble() && representation.IsDouble()) {
   3369           if (old_representation.IsNone()) {
   3370             value = handle(Smi::kZero, isolate);
   3371           }
   3372           value = Object::NewStorageFor(isolate, value, representation);
   3373         } else if (old_representation.IsDouble() &&
   3374                    !representation.IsDouble()) {
   3375           value = Object::WrapForRead(isolate, value, old_representation);
   3376         }
   3377       }
   3378     }
   3379     DCHECK(!(representation.IsDouble() && value->IsSmi()));
   3380     int target_index = new_descriptors->GetFieldIndex(i) - inobject;
   3381     if (target_index < 0) target_index += total_size;
   3382     array->set(target_index, *value);
   3383   }
   3384 
   3385   for (int i = old_nof; i < new_nof; i++) {
   3386     PropertyDetails details = new_descriptors->GetDetails(i);
   3387     if (details.type() != DATA) continue;
   3388     Handle<Object> value;
   3389     if (details.representation().IsDouble()) {
   3390       value = isolate->factory()->NewHeapNumber(0, MUTABLE);
   3391     } else {
   3392       value = isolate->factory()->uninitialized_value();
   3393     }
   3394     int target_index = new_descriptors->GetFieldIndex(i) - inobject;
   3395     if (target_index < 0) target_index += total_size;
   3396     array->set(target_index, *value);
   3397   }
   3398 
   3399   // From here on we cannot fail and we shouldn't GC anymore.
   3400   DisallowHeapAllocation no_allocation;
   3401 
   3402   Heap* heap = isolate->heap();
   3403 
   3404   // Copy (real) inobject properties. If necessary, stop at number_of_fields to
   3405   // avoid overwriting |one_pointer_filler_map|.
   3406   int limit = Min(inobject, number_of_fields);
   3407   for (int i = 0; i < limit; i++) {
   3408     FieldIndex index = FieldIndex::ForPropertyIndex(*new_map, i);
   3409     Object* value = array->get(external + i);
   3410     // Can't use JSObject::FastPropertyAtPut() because proper map was not set
   3411     // yet.
   3412     if (new_map->IsUnboxedDoubleField(index)) {
   3413       DCHECK(value->IsMutableHeapNumber());
   3414       object->RawFastDoublePropertyAtPut(index,
   3415                                          HeapNumber::cast(value)->value());
   3416       if (i < old_number_of_fields && !old_map->IsUnboxedDoubleField(index)) {
   3417         // Transition from tagged to untagged slot.
   3418         heap->ClearRecordedSlot(*object,
   3419                                 HeapObject::RawField(*object, index.offset()));
   3420       }
   3421     } else {
   3422       object->RawFastPropertyAtPut(index, value);
   3423     }
   3424   }
   3425 
   3426 
   3427   // If there are properties in the new backing store, trim it to the correct
   3428   // size and install the backing store into the object.
   3429   if (external > 0) {
   3430     heap->RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>(*array, inobject);
   3431     object->set_properties(*array);
   3432   }
   3433 
   3434   // Create filler object past the new instance size.
   3435   int new_instance_size = new_map->instance_size();
   3436   int instance_size_delta = old_map->instance_size() - new_instance_size;
   3437   DCHECK(instance_size_delta >= 0);
   3438 
   3439   if (instance_size_delta > 0) {
   3440     Address address = object->address();
   3441     heap->CreateFillerObjectAt(address + new_instance_size, instance_size_delta,
   3442                                ClearRecordedSlots::kYes);
   3443     heap->AdjustLiveBytes(*object, -instance_size_delta,
   3444                           Heap::CONCURRENT_TO_SWEEPER);
   3445   }
   3446 
   3447   // We are storing the new map using release store after creating a filler for
   3448   // the left-over space to avoid races with the sweeper thread.
   3449   object->synchronized_set_map(*new_map);
   3450 }
   3451 
   3452 void MigrateFastToSlow(Handle<JSObject> object, Handle<Map> new_map,
   3453                        int expected_additional_properties) {
   3454   // The global object is always normalized.
   3455   DCHECK(!object->IsJSGlobalObject());
   3456   // JSGlobalProxy must never be normalized
   3457   DCHECK(!object->IsJSGlobalProxy());
   3458 
   3459   Isolate* isolate = object->GetIsolate();
   3460   HandleScope scope(isolate);
   3461   Handle<Map> map(object->map());
   3462 
   3463   // Allocate new content.
   3464   int real_size = map->NumberOfOwnDescriptors();
   3465   int property_count = real_size;
   3466   if (expected_additional_properties > 0) {
   3467     property_count += expected_additional_properties;
   3468   } else {
   3469     // Make space for two more properties.
   3470     property_count += NameDictionary::kInitialCapacity;
   3471   }
   3472   Handle<NameDictionary> dictionary =
   3473       NameDictionary::New(isolate, property_count);
   3474 
   3475   Handle<DescriptorArray> descs(map->instance_descriptors());
   3476   for (int i = 0; i < real_size; i++) {
   3477     PropertyDetails details = descs->GetDetails(i);
   3478     Handle<Name> key(descs->GetKey(i));
   3479     switch (details.type()) {
   3480       case DATA_CONSTANT: {
   3481         Handle<Object> value(descs->GetConstant(i), isolate);
   3482         PropertyDetails d(details.attributes(), DATA, i + 1,
   3483                           PropertyCellType::kNoCell);
   3484         dictionary = NameDictionary::Add(dictionary, key, value, d);
   3485         break;
   3486       }
   3487       case DATA: {
   3488         FieldIndex index = FieldIndex::ForDescriptor(*map, i);
   3489         Handle<Object> value;
   3490         if (object->IsUnboxedDoubleField(index)) {
   3491           double old_value = object->RawFastDoublePropertyAt(index);
   3492           value = isolate->factory()->NewHeapNumber(old_value);
   3493         } else {
   3494           value = handle(object->RawFastPropertyAt(index), isolate);
   3495           if (details.representation().IsDouble()) {
   3496             DCHECK(value->IsMutableHeapNumber());
   3497             Handle<HeapNumber> old = Handle<HeapNumber>::cast(value);
   3498             value = isolate->factory()->NewHeapNumber(old->value());
   3499           }
   3500         }
   3501         PropertyDetails d(details.attributes(), DATA, i + 1,
   3502                           PropertyCellType::kNoCell);
   3503         dictionary = NameDictionary::Add(dictionary, key, value, d);
   3504         break;
   3505       }
   3506       case ACCESSOR: {
   3507         FieldIndex index = FieldIndex::ForDescriptor(*map, i);
   3508         Handle<Object> value(object->RawFastPropertyAt(index), isolate);
   3509         PropertyDetails d(details.attributes(), ACCESSOR_CONSTANT, i + 1,
   3510                           PropertyCellType::kNoCell);
   3511         dictionary = NameDictionary::Add(dictionary, key, value, d);
   3512         break;
   3513       }
   3514       case ACCESSOR_CONSTANT: {
   3515         Handle<Object> value(descs->GetCallbacksObject(i), isolate);
   3516         PropertyDetails d(details.attributes(), ACCESSOR_CONSTANT, i + 1,
   3517                           PropertyCellType::kNoCell);
   3518         dictionary = NameDictionary::Add(dictionary, key, value, d);
   3519         break;
   3520       }
   3521     }
   3522   }
   3523 
   3524   // Copy the next enumeration index from instance descriptor.
   3525   dictionary->SetNextEnumerationIndex(real_size + 1);
   3526 
   3527   // From here on we cannot fail and we shouldn't GC anymore.
   3528   DisallowHeapAllocation no_allocation;
   3529 
   3530   // Resize the object in the heap if necessary.
   3531   int new_instance_size = new_map->instance_size();
   3532   int instance_size_delta = map->instance_size() - new_instance_size;
   3533   DCHECK(instance_size_delta >= 0);
   3534 
   3535   if (instance_size_delta > 0) {
   3536     Heap* heap = isolate->heap();
   3537     heap->CreateFillerObjectAt(object->address() + new_instance_size,
   3538                                instance_size_delta, ClearRecordedSlots::kYes);
   3539     heap->AdjustLiveBytes(*object, -instance_size_delta,
   3540                           Heap::CONCURRENT_TO_SWEEPER);
   3541   }
   3542 
   3543   // We are storing the new map using release store after creating a filler for
   3544   // the left-over space to avoid races with the sweeper thread.
   3545   object->synchronized_set_map(*new_map);
   3546 
   3547   object->set_properties(*dictionary);
   3548 
   3549   // Ensure that in-object space of slow-mode object does not contain random
   3550   // garbage.
   3551   int inobject_properties = new_map->GetInObjectProperties();
   3552   if (inobject_properties) {
   3553     Heap* heap = isolate->heap();
   3554     heap->ClearRecordedSlotRange(
   3555         object->address() + map->GetInObjectPropertyOffset(0),
   3556         object->address() + new_instance_size);
   3557 
   3558     for (int i = 0; i < inobject_properties; i++) {
   3559       FieldIndex index = FieldIndex::ForPropertyIndex(*new_map, i);
   3560       object->RawFastPropertyAtPut(index, Smi::kZero);
   3561     }
   3562   }
   3563 
   3564   isolate->counters()->props_to_dictionary()->Increment();
   3565 
   3566 #ifdef DEBUG
   3567   if (FLAG_trace_normalization) {
   3568     OFStream os(stdout);
   3569     os << "Object properties have been normalized:\n";
   3570     object->Print(os);
   3571   }
   3572 #endif
   3573 }
   3574 
   3575 }  // namespace
   3576 
   3577 // static
   3578 void JSObject::NotifyMapChange(Handle<Map> old_map, Handle<Map> new_map,
   3579                                Isolate* isolate) {
   3580   if (!old_map->is_prototype_map()) return;
   3581 
   3582   InvalidatePrototypeChains(*old_map);
   3583 
   3584   // If the map was registered with its prototype before, ensure that it
   3585   // registers with its new prototype now. This preserves the invariant that
   3586   // when a map on a prototype chain is registered with its prototype, then
   3587   // all prototypes further up the chain are also registered with their
   3588   // respective prototypes.
   3589   UpdatePrototypeUserRegistration(old_map, new_map, isolate);
   3590 }
   3591 
   3592 void JSObject::MigrateToMap(Handle<JSObject> object, Handle<Map> new_map,
   3593                             int expected_additional_properties) {
   3594   if (object->map() == *new_map) return;
   3595   Handle<Map> old_map(object->map());
   3596   NotifyMapChange(old_map, new_map, new_map->GetIsolate());
   3597 
   3598   if (old_map->is_dictionary_map()) {
   3599     // For slow-to-fast migrations JSObject::MigrateSlowToFast()
   3600     // must be used instead.
   3601     CHECK(new_map->is_dictionary_map());
   3602 
   3603     // Slow-to-slow migration is trivial.
   3604     object->set_map(*new_map);
   3605   } else if (!new_map->is_dictionary_map()) {
   3606     MigrateFastToFast(object, new_map);
   3607     if (old_map->is_prototype_map()) {
   3608       DCHECK(!old_map->is_stable());
   3609       DCHECK(new_map->is_stable());
   3610       // Clear out the old descriptor array to avoid problems to sharing
   3611       // the descriptor array without using an explicit.
   3612       old_map->InitializeDescriptors(
   3613           old_map->GetHeap()->empty_descriptor_array(),
   3614           LayoutDescriptor::FastPointerLayout());
   3615       // Ensure that no transition was inserted for prototype migrations.
   3616       DCHECK_EQ(
   3617           0, TransitionArray::NumberOfTransitions(old_map->raw_transitions()));
   3618       DCHECK(new_map->GetBackPointer()->IsUndefined(new_map->GetIsolate()));
   3619     }
   3620   } else {
   3621     MigrateFastToSlow(object, new_map, expected_additional_properties);
   3622   }
   3623 
   3624   // Careful: Don't allocate here!
   3625   // For some callers of this method, |object| might be in an inconsistent
   3626   // state now: the new map might have a new elements_kind, but the object's
   3627   // elements pointer hasn't been updated yet. Callers will fix this, but in
   3628   // the meantime, (indirectly) calling JSObjectVerify() must be avoided.
   3629   // When adding code here, add a DisallowHeapAllocation too.
   3630 }
   3631 
   3632 void JSObject::ForceSetPrototype(Handle<JSObject> object,
   3633                                  Handle<Object> proto) {
   3634   // object.__proto__ = proto;
   3635   Handle<Map> old_map = Handle<Map>(object->map());
   3636   Handle<Map> new_map = Map::Copy(old_map, "ForceSetPrototype");
   3637   Map::SetPrototype(new_map, proto, FAST_PROTOTYPE);
   3638   JSObject::MigrateToMap(object, new_map);
   3639 }
   3640 
   3641 int Map::NumberOfFields() {
   3642   DescriptorArray* descriptors = instance_descriptors();
   3643   int result = 0;
   3644   for (int i = 0; i < NumberOfOwnDescriptors(); i++) {
   3645     if (descriptors->GetDetails(i).location() == kField) result++;
   3646   }
   3647   return result;
   3648 }
   3649 
   3650 Handle<Map> Map::CopyGeneralizeAllRepresentations(
   3651     Handle<Map> map, ElementsKind elements_kind, int modify_index,
   3652     StoreMode store_mode, PropertyKind kind, PropertyAttributes attributes,
   3653     const char* reason) {
   3654   Isolate* isolate = map->GetIsolate();
   3655   Handle<DescriptorArray> old_descriptors(map->instance_descriptors(), isolate);
   3656   int number_of_own_descriptors = map->NumberOfOwnDescriptors();
   3657   Handle<DescriptorArray> descriptors =
   3658       DescriptorArray::CopyUpTo(old_descriptors, number_of_own_descriptors);
   3659 
   3660   for (int i = 0; i < number_of_own_descriptors; i++) {
   3661     descriptors->SetRepresentation(i, Representation::Tagged());
   3662     if (descriptors->GetDetails(i).type() == DATA) {
   3663       descriptors->SetValue(i, FieldType::Any());
   3664     }
   3665   }
   3666 
   3667   Handle<LayoutDescriptor> new_layout_descriptor(
   3668       LayoutDescriptor::FastPointerLayout(), isolate);
   3669   Handle<Map> new_map = CopyReplaceDescriptors(
   3670       map, descriptors, new_layout_descriptor, OMIT_TRANSITION,
   3671       MaybeHandle<Name>(), reason, SPECIAL_TRANSITION);
   3672 
   3673   // Unless the instance is being migrated, ensure that modify_index is a field.
   3674   if (modify_index >= 0) {
   3675     PropertyDetails details = descriptors->GetDetails(modify_index);
   3676     if (store_mode == FORCE_FIELD &&
   3677         (details.type() != DATA || details.attributes() != attributes)) {
   3678       int field_index = details.type() == DATA ? details.field_index()
   3679                                                : new_map->NumberOfFields();
   3680       DataDescriptor d(handle(descriptors->GetKey(modify_index), isolate),
   3681                        field_index, attributes, Representation::Tagged());
   3682       descriptors->Replace(modify_index, &d);
   3683       if (details.type() != DATA) {
   3684         int unused_property_fields = new_map->unused_property_fields() - 1;
   3685         if (unused_property_fields < 0) {
   3686           unused_property_fields += JSObject::kFieldsAdded;
   3687         }
   3688         new_map->set_unused_property_fields(unused_property_fields);
   3689       }
   3690     } else {
   3691       DCHECK(details.attributes() == attributes);
   3692     }
   3693 
   3694     if (FLAG_trace_generalization) {
   3695       MaybeHandle<FieldType> field_type = FieldType::None(isolate);
   3696       if (details.type() == DATA) {
   3697         field_type = handle(
   3698             map->instance_descriptors()->GetFieldType(modify_index), isolate);
   3699       }
   3700       map->PrintGeneralization(
   3701           stdout, reason, modify_index, new_map->NumberOfOwnDescriptors(),
   3702           new_map->NumberOfOwnDescriptors(),
   3703           details.type() == DATA_CONSTANT && store_mode == FORCE_FIELD,
   3704           details.representation(), Representation::Tagged(), field_type,
   3705           MaybeHandle<Object>(), FieldType::Any(isolate),
   3706           MaybeHandle<Object>());
   3707     }
   3708   }
   3709   new_map->set_elements_kind(elements_kind);
   3710   return new_map;
   3711 }
   3712 
   3713 
   3714 void Map::DeprecateTransitionTree() {
   3715   if (is_deprecated()) return;
   3716   Object* transitions = raw_transitions();
   3717   int num_transitions = TransitionArray::NumberOfTransitions(transitions);
   3718   for (int i = 0; i < num_transitions; ++i) {
   3719     TransitionArray::GetTarget(transitions, i)->DeprecateTransitionTree();
   3720   }
   3721   deprecate();
   3722   dependent_code()->DeoptimizeDependentCodeGroup(
   3723       GetIsolate(), DependentCode::kTransitionGroup);
   3724   NotifyLeafMapLayoutChange();
   3725 }
   3726 
   3727 
   3728 static inline bool EqualImmutableValues(Object* obj1, Object* obj2) {
   3729   if (obj1 == obj2) return true;  // Valid for both kData and kAccessor kinds.
   3730   // TODO(ishell): compare AccessorPairs.
   3731   return false;
   3732 }
   3733 
   3734 
   3735 // Installs |new_descriptors| over the current instance_descriptors to ensure
   3736 // proper sharing of descriptor arrays.
   3737 void Map::ReplaceDescriptors(DescriptorArray* new_descriptors,
   3738                              LayoutDescriptor* new_layout_descriptor) {
   3739   Isolate* isolate = GetIsolate();
   3740   // Don't overwrite the empty descriptor array or initial map's descriptors.
   3741   if (NumberOfOwnDescriptors() == 0 || GetBackPointer()->IsUndefined(isolate)) {
   3742     return;
   3743   }
   3744 
   3745   DescriptorArray* to_replace = instance_descriptors();
   3746   isolate->heap()->incremental_marking()->IterateBlackObject(to_replace);
   3747   Map* current = this;
   3748   while (current->instance_descriptors() == to_replace) {
   3749     Object* next = current->GetBackPointer();
   3750     if (next->IsUndefined(isolate)) break;  // Stop overwriting at initial map.
   3751     current->SetEnumLength(kInvalidEnumCacheSentinel);
   3752     current->UpdateDescriptors(new_descriptors, new_layout_descriptor);
   3753     current = Map::cast(next);
   3754   }
   3755   set_owns_descriptors(false);
   3756 }
   3757 
   3758 
   3759 Map* Map::FindRootMap() {
   3760   Map* result = this;
   3761   Isolate* isolate = GetIsolate();
   3762   while (true) {
   3763     Object* back = result->GetBackPointer();
   3764     if (back->IsUndefined(isolate)) {
   3765       // Initial map always owns descriptors and doesn't have unused entries
   3766       // in the descriptor array.
   3767       DCHECK(result->owns_descriptors());
   3768       DCHECK_EQ(result->NumberOfOwnDescriptors(),
   3769                 result->instance_descriptors()->number_of_descriptors());
   3770       return result;
   3771     }
   3772     result = Map::cast(back);
   3773   }
   3774 }
   3775 
   3776 
   3777 Map* Map::FindLastMatchMap(int verbatim,
   3778                            int length,
   3779                            DescriptorArray* descriptors) {
   3780   DisallowHeapAllocation no_allocation;
   3781 
   3782   // This can only be called on roots of transition trees.
   3783   DCHECK_EQ(verbatim, NumberOfOwnDescriptors());
   3784 
   3785   Map* current = this;
   3786 
   3787   for (int i = verbatim; i < length; i++) {
   3788     Name* name = descriptors->GetKey(i);
   3789     PropertyDetails details = descriptors->GetDetails(i);
   3790     Map* next = TransitionArray::SearchTransition(current, details.kind(), name,
   3791                                                   details.attributes());
   3792     if (next == NULL) break;
   3793     DescriptorArray* next_descriptors = next->instance_descriptors();
   3794 
   3795     PropertyDetails next_details = next_descriptors->GetDetails(i);
   3796     DCHECK_EQ(details.kind(), next_details.kind());
   3797     DCHECK_EQ(details.attributes(), next_details.attributes());
   3798     if (details.location() != next_details.location()) break;
   3799     if (!details.representation().Equals(next_details.representation())) break;
   3800 
   3801     if (next_details.location() == kField) {
   3802       FieldType* next_field_type = next_descriptors->GetFieldType(i);
   3803       if (!descriptors->GetFieldType(i)->NowIs(next_field_type)) {
   3804         break;
   3805       }
   3806     } else {
   3807       if (!EqualImmutableValues(descriptors->GetValue(i),
   3808                                 next_descriptors->GetValue(i))) {
   3809         break;
   3810       }
   3811     }
   3812     current = next;
   3813   }
   3814   return current;
   3815 }
   3816 
   3817 
   3818 Map* Map::FindFieldOwner(int descriptor) {
   3819   DisallowHeapAllocation no_allocation;
   3820   DCHECK_EQ(DATA, instance_descriptors()->GetDetails(descriptor).type());
   3821   Map* result = this;
   3822   Isolate* isolate = GetIsolate();
   3823   while (true) {
   3824     Object* back = result->GetBackPointer();
   3825     if (back->IsUndefined(isolate)) break;
   3826     Map* parent = Map::cast(back);
   3827     if (parent->NumberOfOwnDescriptors() <= descriptor) break;
   3828     result = parent;
   3829   }
   3830   return result;
   3831 }
   3832 
   3833 
   3834 void Map::UpdateFieldType(int descriptor, Handle<Name> name,
   3835                           Representation new_representation,
   3836                           Handle<Object> new_wrapped_type) {
   3837   DCHECK(new_wrapped_type->IsSmi() || new_wrapped_type->IsWeakCell());
   3838   // We store raw pointers in the queue, so no allocations are allowed.
   3839   DisallowHeapAllocation no_allocation;
   3840   PropertyDetails details = instance_descriptors()->GetDetails(descriptor);
   3841   if (details.type() != DATA) return;
   3842 
   3843   Zone zone(GetIsolate()->allocator(), ZONE_NAME);
   3844   ZoneQueue<Map*> backlog(&zone);
   3845   backlog.push(this);
   3846 
   3847   while (!backlog.empty()) {
   3848     Map* current = backlog.front();
   3849     backlog.pop();
   3850 
   3851     Object* transitions = current->raw_transitions();
   3852     int num_transitions = TransitionArray::NumberOfTransitions(transitions);
   3853     for (int i = 0; i < num_transitions; ++i) {
   3854       Map* target = TransitionArray::GetTarget(transitions, i);
   3855       backlog.push(target);
   3856     }
   3857     DescriptorArray* descriptors = current->instance_descriptors();
   3858     PropertyDetails details = descriptors->GetDetails(descriptor);
   3859 
   3860     // It is allowed to change representation here only from None to something.
   3861     DCHECK(details.representation().Equals(new_representation) ||
   3862            details.representation().IsNone());
   3863 
   3864     // Skip if already updated the shared descriptor.
   3865     if (descriptors->GetValue(descriptor) != *new_wrapped_type) {
   3866       DataDescriptor d(name, descriptors->GetFieldIndex(descriptor),
   3867                        new_wrapped_type, details.attributes(),
   3868                        new_representation);
   3869       descriptors->Replace(descriptor, &d);
   3870     }
   3871   }
   3872 }
   3873 
   3874 bool FieldTypeIsCleared(Representation rep, FieldType* type) {
   3875   return type->IsNone() && rep.IsHeapObject();
   3876 }
   3877 
   3878 
   3879 // static
   3880 Handle<FieldType> Map::GeneralizeFieldType(Representation rep1,
   3881                                            Handle<FieldType> type1,
   3882                                            Representation rep2,
   3883                                            Handle<FieldType> type2,
   3884                                            Isolate* isolate) {
   3885   // Cleared field types need special treatment. They represent lost knowledge,
   3886   // so we must be conservative, so their generalization with any other type
   3887   // is "Any".
   3888   if (FieldTypeIsCleared(rep1, *type1) || FieldTypeIsCleared(rep2, *type2)) {
   3889     return FieldType::Any(isolate);
   3890   }
   3891   if (type1->NowIs(type2)) return type2;
   3892   if (type2->NowIs(type1)) return type1;
   3893   return FieldType::Any(isolate);
   3894 }
   3895 
   3896 
   3897 // static
   3898 void Map::GeneralizeFieldType(Handle<Map> map, int modify_index,
   3899                               Representation new_representation,
   3900                               Handle<FieldType> new_field_type) {
   3901   Isolate* isolate = map->GetIsolate();
   3902 
   3903   // Check if we actually need to generalize the field type at all.
   3904   Handle<DescriptorArray> old_descriptors(map->instance_descriptors(), isolate);
   3905   Representation old_representation =
   3906       old_descriptors->GetDetails(modify_index).representation();
   3907   Handle<FieldType> old_field_type(old_descriptors->GetFieldType(modify_index),
   3908                                    isolate);
   3909 
   3910   if (old_representation.Equals(new_representation) &&
   3911       !FieldTypeIsCleared(new_representation, *new_field_type) &&
   3912       // Checking old_field_type for being cleared is not necessary because
   3913       // the NowIs check below would fail anyway in that case.
   3914       new_field_type->NowIs(old_field_type)) {
   3915     DCHECK(Map::GeneralizeFieldType(old_representation, old_field_type,
   3916                                     new_representation, new_field_type, isolate)
   3917                ->NowIs(old_field_type));
   3918     return;
   3919   }
   3920 
   3921   // Determine the field owner.
   3922   Handle<Map> field_owner(map->FindFieldOwner(modify_index), isolate);
   3923   Handle<DescriptorArray> descriptors(
   3924       field_owner->instance_descriptors(), isolate);
   3925   DCHECK_EQ(*old_field_type, descriptors->GetFieldType(modify_index));
   3926 
   3927   new_field_type =
   3928       Map::GeneralizeFieldType(old_representation, old_field_type,
   3929                                new_representation, new_field_type, isolate);
   3930 
   3931   PropertyDetails details = descriptors->GetDetails(modify_index);
   3932   Handle<Name> name(descriptors->GetKey(modify_index));
   3933 
   3934   Handle<Object> wrapped_type(WrapType(new_field_type));
   3935   field_owner->UpdateFieldType(modify_index, name, new_representation,
   3936                                wrapped_type);
   3937   field_owner->dependent_code()->DeoptimizeDependentCodeGroup(
   3938       isolate, DependentCode::kFieldOwnerGroup);
   3939 
   3940   if (FLAG_trace_generalization) {
   3941     map->PrintGeneralization(
   3942         stdout, "field type generalization", modify_index,
   3943         map->NumberOfOwnDescriptors(), map->NumberOfOwnDescriptors(), false,
   3944         details.representation(), details.representation(), old_field_type,
   3945         MaybeHandle<Object>(), new_field_type, MaybeHandle<Object>());
   3946   }
   3947 }
   3948 
   3949 static inline Handle<FieldType> GetFieldType(
   3950     Isolate* isolate, Handle<DescriptorArray> descriptors, int descriptor,
   3951     PropertyLocation location, Representation representation) {
   3952 #ifdef DEBUG
   3953   PropertyDetails details = descriptors->GetDetails(descriptor);
   3954   DCHECK_EQ(kData, details.kind());
   3955   DCHECK_EQ(details.location(), location);
   3956 #endif
   3957   if (location == kField) {
   3958     return handle(descriptors->GetFieldType(descriptor), isolate);
   3959   } else {
   3960     return descriptors->GetValue(descriptor)
   3961         ->OptimalType(isolate, representation);
   3962   }
   3963 }
   3964 
   3965 // Reconfigures elements kind to |new_elements_kind| and/or property at
   3966 // |modify_index| with |new_kind|, |new_attributes|, |store_mode| and/or
   3967 // |new_representation|/|new_field_type|.
   3968 // If |modify_index| is negative then no properties are reconfigured but the
   3969 // map is migrated to the up-to-date non-deprecated state.
   3970 //
   3971 // This method rewrites or completes the transition tree to reflect the new
   3972 // change. To avoid high degrees over polymorphism, and to stabilize quickly,
   3973 // on every rewrite the new type is deduced by merging the current type with
   3974 // any potential new (partial) version of the type in the transition tree.
   3975 // To do this, on each rewrite:
   3976 // - Search the root of the transition tree using FindRootMap.
   3977 // - Find/create a |root_map| with requested |new_elements_kind|.
   3978 // - Find |target_map|, the newest matching version of this map using the
   3979 //   virtually "enhanced" |old_map|'s descriptor array (i.e. whose entry at
   3980 //   |modify_index| is considered to be of |new_kind| and having
   3981 //   |new_attributes|) to walk the transition tree.
   3982 // - Merge/generalize the "enhanced" descriptor array of the |old_map| and
   3983 //   descriptor array of the |target_map|.
   3984 // - Generalize the |modify_index| descriptor using |new_representation| and
   3985 //   |new_field_type|.
   3986 // - Walk the tree again starting from the root towards |target_map|. Stop at
   3987 //   |split_map|, the first map who's descriptor array does not match the merged
   3988 //   descriptor array.
   3989 // - If |target_map| == |split_map|, |target_map| is in the expected state.
   3990 //   Return it.
   3991 // - Otherwise, invalidate the outdated transition target from |target_map|, and
   3992 //   replace its transition tree with a new branch for the updated descriptors.
   3993 Handle<Map> Map::Reconfigure(Handle<Map> old_map,
   3994                              ElementsKind new_elements_kind, int modify_index,
   3995                              PropertyKind new_kind,
   3996                              PropertyAttributes new_attributes,
   3997                              Representation new_representation,
   3998                              Handle<FieldType> new_field_type,
   3999                              StoreMode store_mode) {
   4000   DCHECK_NE(kAccessor, new_kind);  // TODO(ishell): not supported yet.
   4001   DCHECK(store_mode != FORCE_FIELD || modify_index >= 0);
   4002   Isolate* isolate = old_map->GetIsolate();
   4003 
   4004   Handle<DescriptorArray> old_descriptors(
   4005       old_map->instance_descriptors(), isolate);
   4006   int old_nof = old_map->NumberOfOwnDescriptors();
   4007 
   4008   // If it's just a representation generalization case (i.e. property kind and
   4009   // attributes stays unchanged) it's fine to transition from None to anything
   4010   // but double without any modification to the object, because the default
   4011   // uninitialized value for representation None can be overwritten by both
   4012   // smi and tagged values. Doubles, however, would require a box allocation.
   4013   if (modify_index >= 0 && !new_representation.IsNone() &&
   4014       !new_representation.IsDouble() &&
   4015       old_map->elements_kind() == new_elements_kind) {
   4016     PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
   4017     Representation old_representation = old_details.representation();
   4018 
   4019     if (old_representation.IsNone()) {
   4020       DCHECK_EQ(new_kind, old_details.kind());
   4021       DCHECK_EQ(new_attributes, old_details.attributes());
   4022       DCHECK_EQ(DATA, old_details.type());
   4023       if (FLAG_trace_generalization) {
   4024         old_map->PrintGeneralization(
   4025             stdout, "uninitialized field", modify_index,
   4026             old_map->NumberOfOwnDescriptors(),
   4027             old_map->NumberOfOwnDescriptors(), false, old_representation,
   4028             new_representation,
   4029             handle(old_descriptors->GetFieldType(modify_index), isolate),
   4030             MaybeHandle<Object>(), new_field_type, MaybeHandle<Object>());
   4031       }
   4032       Handle<Map> field_owner(old_map->FindFieldOwner(modify_index), isolate);
   4033 
   4034       GeneralizeFieldType(field_owner, modify_index, new_representation,
   4035                           new_field_type);
   4036       DCHECK(old_descriptors->GetDetails(modify_index)
   4037                  .representation()
   4038                  .Equals(new_representation));
   4039       DCHECK(
   4040           old_descriptors->GetFieldType(modify_index)->NowIs(new_field_type));
   4041       return old_map;
   4042     }
   4043   }
   4044 
   4045   // Check the state of the root map.
   4046   Handle<Map> root_map(old_map->FindRootMap(), isolate);
   4047   if (!old_map->EquivalentToForTransition(*root_map)) {
   4048     return CopyGeneralizeAllRepresentations(
   4049         old_map, new_elements_kind, modify_index, store_mode, new_kind,
   4050         new_attributes, "GenAll_NotEquivalent");
   4051   }
   4052 
   4053   ElementsKind from_kind = root_map->elements_kind();
   4054   ElementsKind to_kind = new_elements_kind;
   4055   // TODO(ishell): Add a test for SLOW_SLOPPY_ARGUMENTS_ELEMENTS.
   4056   if (from_kind != to_kind && to_kind != DICTIONARY_ELEMENTS &&
   4057       to_kind != SLOW_STRING_WRAPPER_ELEMENTS &&
   4058       to_kind != SLOW_SLOPPY_ARGUMENTS_ELEMENTS &&
   4059       !(IsTransitionableFastElementsKind(from_kind) &&
   4060         IsMoreGeneralElementsKindTransition(from_kind, to_kind))) {
   4061     return CopyGeneralizeAllRepresentations(
   4062         old_map, to_kind, modify_index, store_mode, new_kind, new_attributes,
   4063         "GenAll_InvalidElementsTransition");
   4064   }
   4065   int root_nof = root_map->NumberOfOwnDescriptors();
   4066   if (modify_index >= 0 && modify_index < root_nof) {
   4067     PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
   4068     if (old_details.kind() != new_kind ||
   4069         old_details.attributes() != new_attributes) {
   4070       return CopyGeneralizeAllRepresentations(
   4071           old_map, to_kind, modify_index, store_mode, new_kind, new_attributes,
   4072           "GenAll_RootModification1");
   4073     }
   4074     if ((old_details.type() != DATA && store_mode == FORCE_FIELD) ||
   4075         (old_details.type() == DATA &&
   4076          (!new_field_type->NowIs(old_descriptors->GetFieldType(modify_index)) ||
   4077           !new_representation.fits_into(old_details.representation())))) {
   4078       return CopyGeneralizeAllRepresentations(
   4079           old_map, to_kind, modify_index, store_mode, new_kind, new_attributes,
   4080           "GenAll_RootModification2");
   4081     }
   4082   }
   4083 
   4084   // From here on, use the map with correct elements kind as root map.
   4085   if (from_kind != to_kind) {
   4086     root_map = Map::AsElementsKind(root_map, to_kind);
   4087   }
   4088 
   4089   Handle<Map> target_map = root_map;
   4090   for (int i = root_nof; i < old_nof; ++i) {
   4091     PropertyDetails old_details = old_descriptors->GetDetails(i);
   4092     PropertyKind next_kind;
   4093     PropertyLocation next_location;
   4094     PropertyAttributes next_attributes;
   4095     Representation next_representation;
   4096     bool property_kind_reconfiguration = false;
   4097 
   4098     if (modify_index == i) {
   4099       DCHECK_EQ(FORCE_FIELD, store_mode);
   4100       property_kind_reconfiguration = old_details.kind() != new_kind;
   4101 
   4102       next_kind = new_kind;
   4103       next_location = kField;
   4104       next_attributes = new_attributes;
   4105       // If property kind is not reconfigured merge the result with
   4106       // representation/field type from the old descriptor.
   4107       next_representation = new_representation;
   4108       if (!property_kind_reconfiguration) {
   4109         next_representation =
   4110             next_representation.generalize(old_details.representation());
   4111       }
   4112 
   4113     } else {
   4114       next_kind = old_details.kind();
   4115       next_location = old_details.location();
   4116       next_attributes = old_details.attributes();
   4117       next_representation = old_details.representation();
   4118     }
   4119     Map* transition = TransitionArray::SearchTransition(
   4120         *target_map, next_kind, old_descriptors->GetKey(i), next_attributes);
   4121     if (transition == NULL) break;
   4122     Handle<Map> tmp_map(transition, isolate);
   4123 
   4124     Handle<DescriptorArray> tmp_descriptors = handle(
   4125         tmp_map->instance_descriptors(), isolate);
   4126 
   4127     // Check if target map is incompatible.
   4128     PropertyDetails tmp_details = tmp_descriptors->GetDetails(i);
   4129     DCHECK_EQ(next_kind, tmp_details.kind());
   4130     DCHECK_EQ(next_attributes, tmp_details.attributes());
   4131     if (next_kind == kAccessor &&
   4132         !EqualImmutableValues(old_descriptors->GetValue(i),
   4133                               tmp_descriptors->GetValue(i))) {
   4134       return CopyGeneralizeAllRepresentations(
   4135           old_map, to_kind, modify_index, store_mode, new_kind, new_attributes,
   4136           "GenAll_Incompatible");
   4137     }
   4138     if (next_location == kField && tmp_details.location() == kDescriptor) break;
   4139 
   4140     Representation tmp_representation = tmp_details.representation();
   4141     if (!next_representation.fits_into(tmp_representation)) break;
   4142 
   4143     PropertyLocation old_location = old_details.location();
   4144     PropertyLocation tmp_location = tmp_details.location();
   4145     if (tmp_location == kField) {
   4146       if (next_kind == kData) {
   4147         Handle<FieldType> next_field_type;
   4148         if (modify_index == i) {
   4149           next_field_type = new_field_type;
   4150           if (!property_kind_reconfiguration) {
   4151             Handle<FieldType> old_field_type =
   4152                 GetFieldType(isolate, old_descriptors, i,
   4153                              old_details.location(), tmp_representation);
   4154             Representation old_representation = old_details.representation();
   4155             next_field_type = GeneralizeFieldType(
   4156                 old_representation, old_field_type, new_representation,
   4157                 next_field_type, isolate);
   4158           }
   4159         } else {
   4160           Handle<FieldType> old_field_type =
   4161               GetFieldType(isolate, old_descriptors, i, old_details.location(),
   4162                            tmp_representation);
   4163           next_field_type = old_field_type;
   4164         }
   4165         GeneralizeFieldType(tmp_map, i, tmp_representation, next_field_type);
   4166       }
   4167     } else if (old_location == kField ||
   4168                !EqualImmutableValues(old_descriptors->GetValue(i),
   4169                                      tmp_descriptors->GetValue(i))) {
   4170       break;
   4171     }
   4172     DCHECK(!tmp_map->is_deprecated());
   4173     target_map = tmp_map;
   4174   }
   4175 
   4176   // Directly change the map if the target map is more general.
   4177   Handle<DescriptorArray> target_descriptors(
   4178       target_map->instance_descriptors(), isolate);
   4179   int target_nof = target_map->NumberOfOwnDescriptors();
   4180   if (target_nof == old_nof &&
   4181       (store_mode != FORCE_FIELD ||
   4182        (modify_index >= 0 &&
   4183         target_descriptors->GetDetails(modify_index).location() == kField))) {
   4184 #ifdef DEBUG
   4185     if (modify_index >= 0) {
   4186       PropertyDetails details = target_descriptors->GetDetails(modify_index);
   4187       DCHECK_EQ(new_kind, details.kind());
   4188       DCHECK_EQ(new_attributes, details.attributes());
   4189       DCHECK(new_representation.fits_into(details.representation()));
   4190       DCHECK(details.location() != kField ||
   4191              new_field_type->NowIs(
   4192                  target_descriptors->GetFieldType(modify_index)));
   4193     }
   4194 #endif
   4195     if (*target_map != *old_map) {
   4196       old_map->NotifyLeafMapLayoutChange();
   4197     }
   4198     return target_map;
   4199   }
   4200 
   4201   // Find the last compatible target map in the transition tree.
   4202   for (int i = target_nof; i < old_nof; ++i) {
   4203     PropertyDetails old_details = old_descriptors->GetDetails(i);
   4204     PropertyKind next_kind;
   4205     PropertyAttributes next_attributes;
   4206     if (modify_index == i) {
   4207       next_kind = new_kind;
   4208       next_attributes = new_attributes;
   4209     } else {
   4210       next_kind = old_details.kind();
   4211       next_attributes = old_details.attributes();
   4212     }
   4213     Map* transition = TransitionArray::SearchTransition(
   4214         *target_map, next_kind, old_descriptors->GetKey(i), next_attributes);
   4215     if (transition == NULL) break;
   4216     Handle<Map> tmp_map(transition, isolate);
   4217     Handle<DescriptorArray> tmp_descriptors(
   4218         tmp_map->instance_descriptors(), isolate);
   4219 
   4220     // Check if target map is compatible.
   4221 #ifdef DEBUG
   4222     PropertyDetails tmp_details = tmp_descriptors->GetDetails(i);
   4223     DCHECK_EQ(next_kind, tmp_details.kind());
   4224     DCHECK_EQ(next_attributes, tmp_details.attributes());
   4225 #endif
   4226     if (next_kind == kAccessor &&
   4227         !EqualImmutableValues(old_descriptors->GetValue(i),
   4228                               tmp_descriptors->GetValue(i))) {
   4229       return CopyGeneralizeAllRepresentations(
   4230           old_map, to_kind, modify_index, store_mode, new_kind, new_attributes,
   4231           "GenAll_Incompatible");
   4232     }
   4233     DCHECK(!tmp_map->is_deprecated());
   4234     target_map = tmp_map;
   4235   }
   4236   target_nof = target_map->NumberOfOwnDescriptors();
   4237   target_descriptors = handle(target_map->instance_descriptors(), isolate);
   4238 
   4239   // Allocate a new descriptor array large enough to hold the required
   4240   // descriptors, with minimally the exact same size as the old descriptor
   4241   // array.
   4242   int new_slack = Max(
   4243       old_nof, old_descriptors->number_of_descriptors()) - old_nof;
   4244   Handle<DescriptorArray> new_descriptors = DescriptorArray::Allocate(
   4245       isolate, old_nof, new_slack);
   4246   DCHECK(new_descriptors->length() > target_descriptors->length() ||
   4247          new_descriptors->NumberOfSlackDescriptors() > 0 ||
   4248          new_descriptors->number_of_descriptors() ==
   4249          old_descriptors->number_of_descriptors());
   4250   DCHECK(new_descriptors->number_of_descriptors() == old_nof);
   4251 
   4252   // 0 -> |root_nof|
   4253   int current_offset = 0;
   4254   for (int i = 0; i < root_nof; ++i) {
   4255     PropertyDetails old_details = old_descriptors->GetDetails(i);
   4256     if (old_details.location() == kField) {
   4257       current_offset += old_details.field_width_in_words();
   4258     }
   4259     Descriptor d(handle(old_descriptors->GetKey(i), isolate),
   4260                  handle(old_descriptors->GetValue(i), isolate),
   4261                  old_details);
   4262     new_descriptors->Set(i, &d);
   4263   }
   4264 
   4265   // |root_nof| -> |target_nof|
   4266   for (int i = root_nof; i < target_nof; ++i) {
   4267     Handle<Name> target_key(target_descriptors->GetKey(i), isolate);
   4268     PropertyDetails old_details = old_descriptors->GetDetails(i);
   4269     PropertyDetails target_details = target_descriptors->GetDetails(i);
   4270 
   4271     PropertyKind next_kind;
   4272     PropertyAttributes next_attributes;
   4273     PropertyLocation next_location;
   4274     Representation next_representation;
   4275     bool property_kind_reconfiguration = false;
   4276 
   4277     if (modify_index == i) {
   4278       DCHECK_EQ(FORCE_FIELD, store_mode);
   4279       property_kind_reconfiguration = old_details.kind() != new_kind;
   4280 
   4281       next_kind = new_kind;
   4282       next_attributes = new_attributes;
   4283       next_location = kField;
   4284 
   4285       // Merge new representation/field type with ones from the target
   4286       // descriptor. If property kind is not reconfigured merge the result with
   4287       // representation/field type from the old descriptor.
   4288       next_representation =
   4289           new_representation.generalize(target_details.representation());
   4290       if (!property_kind_reconfiguration) {
   4291         next_representation =
   4292             next_representation.generalize(old_details.representation());
   4293       }
   4294     } else {
   4295       // Merge old_descriptor and target_descriptor entries.
   4296       DCHECK_EQ(target_details.kind(), old_details.kind());
   4297       next_kind = target_details.kind();
   4298       next_attributes = target_details.attributes();
   4299       next_location =
   4300           old_details.location() == kField ||
   4301                   target_details.location() == kField ||
   4302                   !EqualImmutableValues(target_descriptors->GetValue(i),
   4303                                         old_descriptors->GetValue(i))
   4304               ? kField
   4305               : kDescriptor;
   4306 
   4307       next_representation = old_details.representation().generalize(
   4308           target_details.representation());
   4309     }
   4310     DCHECK_EQ(next_kind, target_details.kind());
   4311     DCHECK_EQ(next_attributes, target_details.attributes());
   4312 
   4313     if (next_location == kField) {
   4314       if (next_kind == kData) {
   4315         Handle<FieldType> target_field_type =
   4316             GetFieldType(isolate, target_descriptors, i,
   4317                          target_details.location(), next_representation);
   4318 
   4319         Handle<FieldType> next_field_type;
   4320         if (modify_index == i) {
   4321           next_field_type = GeneralizeFieldType(
   4322               target_details.representation(), target_field_type,
   4323               new_representation, new_field_type, isolate);
   4324           if (!property_kind_reconfiguration) {
   4325             Handle<FieldType> old_field_type =
   4326                 GetFieldType(isolate, old_descriptors, i,
   4327                              old_details.location(), next_representation);
   4328             next_field_type = GeneralizeFieldType(
   4329                 old_details.representation(), old_field_type,
   4330                 next_representation, next_field_type, isolate);
   4331           }
   4332         } else {
   4333           Handle<FieldType> old_field_type =
   4334               GetFieldType(isolate, old_descriptors, i, old_details.location(),
   4335                            next_representation);
   4336           next_field_type = GeneralizeFieldType(
   4337               old_details.representation(), old_field_type, next_representation,
   4338               target_field_type, isolate);
   4339         }
   4340         Handle<Object> wrapped_type(WrapType(next_field_type));
   4341         DataDescriptor d(target_key, current_offset, wrapped_type,
   4342                          next_attributes, next_representation);
   4343         current_offset += d.GetDetails().field_width_in_words();
   4344         new_descriptors->Set(i, &d);
   4345       } else {
   4346         UNIMPLEMENTED();  // TODO(ishell): implement.
   4347       }
   4348     } else {
   4349       PropertyDetails details(next_attributes, next_kind, next_location,
   4350                               next_representation);
   4351       Descriptor d(target_key, handle(target_descriptors->GetValue(i), isolate),
   4352                    details);
   4353       new_descriptors->Set(i, &d);
   4354     }
   4355   }
   4356 
   4357   // |target_nof| -> |old_nof|
   4358   for (int i = target_nof; i < old_nof; ++i) {
   4359     PropertyDetails old_details = old_descriptors->GetDetails(i);
   4360     Handle<Name> old_key(old_descriptors->GetKey(i), isolate);
   4361 
   4362     // Merge old_descriptor entry and modified details together.
   4363     PropertyKind next_kind;
   4364     PropertyAttributes next_attributes;
   4365     PropertyLocation next_location;
   4366     Representation next_representation;
   4367     bool property_kind_reconfiguration = false;
   4368 
   4369     if (modify_index == i) {
   4370       DCHECK_EQ(FORCE_FIELD, store_mode);
   4371       // In case of property kind reconfiguration it is not necessary to
   4372       // take into account representation/field type of the old descriptor.
   4373       property_kind_reconfiguration = old_details.kind() != new_kind;
   4374 
   4375       next_kind = new_kind;
   4376       next_attributes = new_attributes;
   4377       next_location = kField;
   4378       next_representation = new_representation;
   4379       if (!property_kind_reconfiguration) {
   4380         next_representation =
   4381             next_representation.generalize(old_details.representation());
   4382       }
   4383     } else {
   4384       next_kind = old_details.kind();
   4385       next_attributes = old_details.attributes();
   4386       next_location = old_details.location();
   4387       next_representation = old_details.representation();
   4388     }
   4389 
   4390     if (next_location == kField) {
   4391       if (next_kind == kData) {
   4392         Handle<FieldType> next_field_type;
   4393         if (modify_index == i) {
   4394           next_field_type = new_field_type;
   4395           if (!property_kind_reconfiguration) {
   4396             Handle<FieldType> old_field_type =
   4397                 GetFieldType(isolate, old_descriptors, i,
   4398                              old_details.location(), next_representation);
   4399             next_field_type = GeneralizeFieldType(
   4400                 old_details.representation(), old_field_type,
   4401                 next_representation, next_field_type, isolate);
   4402           }
   4403         } else {
   4404           Handle<FieldType> old_field_type =
   4405               GetFieldType(isolate, old_descriptors, i, old_details.location(),
   4406                            next_representation);
   4407           next_field_type = old_field_type;
   4408         }
   4409 
   4410         Handle<Object> wrapped_type(WrapType(next_field_type));
   4411 
   4412         DataDescriptor d(old_key, current_offset, wrapped_type, next_attributes,
   4413                          next_representation);
   4414         current_offset += d.GetDetails().field_width_in_words();
   4415         new_descriptors->Set(i, &d);
   4416       } else {
   4417         UNIMPLEMENTED();  // TODO(ishell): implement.
   4418       }
   4419     } else {
   4420       PropertyDetails details(next_attributes, next_kind, next_location,
   4421                               next_representation);
   4422       Descriptor d(old_key, handle(old_descriptors->GetValue(i), isolate),
   4423                    details);
   4424       new_descriptors->Set(i, &d);
   4425     }
   4426   }
   4427 
   4428   new_descriptors->Sort();
   4429 
   4430   DCHECK(store_mode != FORCE_FIELD ||
   4431          new_descriptors->GetDetails(modify_index).location() == kField);
   4432 
   4433   Handle<Map> split_map(root_map->FindLastMatchMap(
   4434           root_nof, old_nof, *new_descriptors), isolate);
   4435   int split_nof = split_map->NumberOfOwnDescriptors();
   4436   DCHECK_NE(old_nof, split_nof);
   4437 
   4438   PropertyKind split_kind;
   4439   PropertyAttributes split_attributes;
   4440   if (modify_index == split_nof) {
   4441     split_kind = new_kind;
   4442     split_attributes = new_attributes;
   4443   } else {
   4444     PropertyDetails split_prop_details = old_descriptors->GetDetails(split_nof);
   4445     split_kind = split_prop_details.kind();
   4446     split_attributes = split_prop_details.attributes();
   4447   }
   4448 
   4449   // Invalidate a transition target at |key|.
   4450   Map* maybe_transition = TransitionArray::SearchTransition(
   4451       *split_map, split_kind, old_descriptors->GetKey(split_nof),
   4452       split_attributes);
   4453   if (maybe_transition != NULL) {
   4454     maybe_transition->DeprecateTransitionTree();
   4455   }
   4456 
   4457   // If |maybe_transition| is not NULL then the transition array already
   4458   // contains entry for given descriptor. This means that the transition
   4459   // could be inserted regardless of whether transitions array is full or not.
   4460   if (maybe_transition == NULL &&
   4461       !TransitionArray::CanHaveMoreTransitions(split_map)) {
   4462     return CopyGeneralizeAllRepresentations(
   4463         old_map, to_kind, modify_index, store_mode, new_kind, new_attributes,
   4464         "GenAll_CantHaveMoreTransitions");
   4465   }
   4466 
   4467   old_map->NotifyLeafMapLayoutChange();
   4468 
   4469   if (FLAG_trace_generalization && modify_index >= 0) {
   4470     PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
   4471     PropertyDetails new_details = new_descriptors->GetDetails(modify_index);
   4472     MaybeHandle<FieldType> old_field_type;
   4473     MaybeHandle<FieldType> new_field_type;
   4474     MaybeHandle<Object> old_value;
   4475     MaybeHandle<Object> new_value;
   4476     if (old_details.type() == DATA) {
   4477       old_field_type =
   4478           handle(old_descriptors->GetFieldType(modify_index), isolate);
   4479     } else {
   4480       old_value = handle(old_descriptors->GetValue(modify_index), isolate);
   4481     }
   4482     if (new_details.type() == DATA) {
   4483       new_field_type =
   4484           handle(new_descriptors->GetFieldType(modify_index), isolate);
   4485     } else {
   4486       new_value = handle(new_descriptors->GetValue(modify_index), isolate);
   4487     }
   4488 
   4489     old_map->PrintGeneralization(
   4490         stdout, "", modify_index, split_nof, old_nof,
   4491         old_details.location() == kDescriptor && store_mode == FORCE_FIELD,
   4492         old_details.representation(), new_details.representation(),
   4493         old_field_type, old_value, new_field_type, new_value);
   4494   }
   4495 
   4496   Handle<LayoutDescriptor> new_layout_descriptor =
   4497       LayoutDescriptor::New(split_map, new_descriptors, old_nof);
   4498 
   4499   Handle<Map> new_map =
   4500       AddMissingTransitions(split_map, new_descriptors, new_layout_descriptor);
   4501 
   4502   // Deprecated part of the transition tree is no longer reachable, so replace
   4503   // current instance descriptors in the "survived" part of the tree with
   4504   // the new descriptors to maintain descriptors sharing invariant.
   4505   split_map->ReplaceDescriptors(*new_descriptors, *new_layout_descriptor);
   4506   return new_map;
   4507 }
   4508 
   4509 
   4510 // Generalize the representation of all DATA descriptors.
   4511 Handle<Map> Map::GeneralizeAllFieldRepresentations(
   4512     Handle<Map> map) {
   4513   Handle<DescriptorArray> descriptors(map->instance_descriptors());
   4514   for (int i = 0; i < map->NumberOfOwnDescriptors(); ++i) {
   4515     PropertyDetails details = descriptors->GetDetails(i);
   4516     if (details.type() == DATA) {
   4517       map = ReconfigureProperty(map, i, kData, details.attributes(),
   4518                                 Representation::Tagged(),
   4519                                 FieldType::Any(map->GetIsolate()), FORCE_FIELD);
   4520     }
   4521   }
   4522   return map;
   4523 }
   4524 
   4525 
   4526 // static
   4527 MaybeHandle<Map> Map::TryUpdate(Handle<Map> old_map) {
   4528   DisallowHeapAllocation no_allocation;
   4529   DisallowDeoptimization no_deoptimization(old_map->GetIsolate());
   4530 
   4531   if (!old_map->is_deprecated()) return old_map;
   4532 
   4533   // Check the state of the root map.
   4534   Map* root_map = old_map->FindRootMap();
   4535   if (!old_map->EquivalentToForTransition(root_map)) return MaybeHandle<Map>();
   4536 
   4537   ElementsKind from_kind = root_map->elements_kind();
   4538   ElementsKind to_kind = old_map->elements_kind();
   4539   if (from_kind != to_kind) {
   4540     // Try to follow existing elements kind transitions.
   4541     root_map = root_map->LookupElementsTransitionMap(to_kind);
   4542     if (root_map == NULL) return MaybeHandle<Map>();
   4543     // From here on, use the map with correct elements kind as root map.
   4544   }
   4545   Map* new_map = root_map->TryReplayPropertyTransitions(*old_map);
   4546   if (new_map == nullptr) return MaybeHandle<Map>();
   4547   return handle(new_map);
   4548 }
   4549 
   4550 Map* Map::TryReplayPropertyTransitions(Map* old_map) {
   4551   DisallowHeapAllocation no_allocation;
   4552   DisallowDeoptimization no_deoptimization(GetIsolate());
   4553 
   4554   int root_nof = NumberOfOwnDescriptors();
   4555 
   4556   int old_nof = old_map->NumberOfOwnDescriptors();
   4557   DescriptorArray* old_descriptors = old_map->instance_descriptors();
   4558 
   4559   Map* new_map = this;
   4560   for (int i = root_nof; i < old_nof; ++i) {
   4561     PropertyDetails old_details = old_descriptors->GetDetails(i);
   4562     Map* transition = TransitionArray::SearchTransition(
   4563         new_map, old_details.kind(), old_descriptors->GetKey(i),
   4564         old_details.attributes());
   4565     if (transition == NULL) return nullptr;
   4566     new_map = transition;
   4567     DescriptorArray* new_descriptors = new_map->instance_descriptors();
   4568 
   4569     PropertyDetails new_details = new_descriptors->GetDetails(i);
   4570     DCHECK_EQ(old_details.kind(), new_details.kind());
   4571     DCHECK_EQ(old_details.attributes(), new_details.attributes());
   4572     if (!old_details.representation().fits_into(new_details.representation())) {
   4573       return nullptr;
   4574     }
   4575     switch (new_details.type()) {
   4576       case DATA: {
   4577         FieldType* new_type = new_descriptors->GetFieldType(i);
   4578         // Cleared field types need special treatment. They represent lost
   4579         // knowledge, so we must first generalize the new_type to "Any".
   4580         if (FieldTypeIsCleared(new_details.representation(), new_type)) {
   4581           return nullptr;
   4582         }
   4583         PropertyType old_property_type = old_details.type();
   4584         if (old_property_type == DATA) {
   4585           FieldType* old_type = old_descriptors->GetFieldType(i);
   4586           if (FieldTypeIsCleared(old_details.representation(), old_type) ||
   4587               !old_type->NowIs(new_type)) {
   4588             return nullptr;
   4589           }
   4590         } else {
   4591           DCHECK(old_property_type == DATA_CONSTANT);
   4592           Object* old_value = old_descriptors->GetValue(i);
   4593           if (!new_type->NowContains(old_value)) {
   4594             return nullptr;
   4595           }
   4596         }
   4597         break;
   4598       }
   4599       case ACCESSOR: {
   4600 #ifdef DEBUG
   4601         FieldType* new_type = new_descriptors->GetFieldType(i);
   4602         DCHECK(new_type->IsAny());
   4603 #endif
   4604         break;
   4605       }
   4606 
   4607       case DATA_CONSTANT:
   4608       case ACCESSOR_CONSTANT: {
   4609         Object* old_value = old_descriptors->GetValue(i);
   4610         Object* new_value = new_descriptors->GetValue(i);
   4611         if (old_details.location() == kField || old_value != new_value) {
   4612           return nullptr;
   4613         }
   4614         break;
   4615       }
   4616     }
   4617   }
   4618   if (new_map->NumberOfOwnDescriptors() != old_nof) return nullptr;
   4619   return new_map;
   4620 }
   4621 
   4622 
   4623 // static
   4624 Handle<Map> Map::Update(Handle<Map> map) {
   4625   if (!map->is_deprecated()) return map;
   4626   return ReconfigureProperty(map, -1, kData, NONE, Representation::None(),
   4627                              FieldType::None(map->GetIsolate()),
   4628                              ALLOW_IN_DESCRIPTOR);
   4629 }
   4630 
   4631 Maybe<bool> JSObject::SetPropertyWithInterceptor(LookupIterator* it,
   4632                                                  ShouldThrow should_throw,
   4633                                                  Handle<Object> value) {
   4634   DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
   4635   return SetPropertyWithInterceptorInternal(it, it->GetInterceptor(),
   4636                                             should_throw, value);
   4637 }
   4638 
   4639 MaybeHandle<Object> Object::SetProperty(Handle<Object> object,
   4640                                         Handle<Name> name, Handle<Object> value,
   4641                                         LanguageMode language_mode,
   4642                                         StoreFromKeyed store_mode) {
   4643   LookupIterator it(object, name);
   4644   MAYBE_RETURN_NULL(SetProperty(&it, value, language_mode, store_mode));
   4645   return value;
   4646 }
   4647 
   4648 
   4649 Maybe<bool> Object::SetPropertyInternal(LookupIterator* it,
   4650                                         Handle<Object> value,
   4651                                         LanguageMode language_mode,
   4652                                         StoreFromKeyed store_mode,
   4653                                         bool* found) {
   4654   it->UpdateProtector();
   4655   DCHECK(it->IsFound());
   4656   ShouldThrow should_throw =
   4657       is_sloppy(language_mode) ? DONT_THROW : THROW_ON_ERROR;
   4658 
   4659   // Make sure that the top context does not change when doing callbacks or
   4660   // interceptor calls.
   4661   AssertNoContextChange ncc(it->isolate());
   4662 
   4663   do {
   4664     switch (it->state()) {
   4665       case LookupIterator::NOT_FOUND:
   4666         UNREACHABLE();
   4667 
   4668       case LookupIterator::ACCESS_CHECK:
   4669         if (it->HasAccess()) break;
   4670         // Check whether it makes sense to reuse the lookup iterator. Here it
   4671         // might still call into setters up the prototype chain.
   4672         return JSObject::SetPropertyWithFailedAccessCheck(it, value,
   4673                                                           should_throw);
   4674 
   4675       case LookupIterator::JSPROXY:
   4676         return JSProxy::SetProperty(it->GetHolder<JSProxy>(), it->GetName(),
   4677                                     value, it->GetReceiver(), language_mode);
   4678 
   4679       case LookupIterator::INTERCEPTOR: {
   4680         if (it->HolderIsReceiverOrHiddenPrototype()) {
   4681           Maybe<bool> result =
   4682               JSObject::SetPropertyWithInterceptor(it, should_throw, value);
   4683           if (result.IsNothing() || result.FromJust()) return result;
   4684         } else {
   4685           Maybe<PropertyAttributes> maybe_attributes =
   4686               JSObject::GetPropertyAttributesWithInterceptor(it);
   4687           if (!maybe_attributes.IsJust()) return Nothing<bool>();
   4688           if ((maybe_attributes.FromJust() & READ_ONLY) != 0) {
   4689             return WriteToReadOnlyProperty(it, value, should_throw);
   4690           }
   4691           if (maybe_attributes.FromJust() == ABSENT) break;
   4692           *found = false;
   4693           return Nothing<bool>();
   4694         }
   4695         break;
   4696       }
   4697 
   4698       case LookupIterator::ACCESSOR: {
   4699         if (it->IsReadOnly()) {
   4700           return WriteToReadOnlyProperty(it, value, should_throw);
   4701         }
   4702         Handle<Object> accessors = it->GetAccessors();
   4703         if (accessors->IsAccessorInfo() &&
   4704             !it->HolderIsReceiverOrHiddenPrototype() &&
   4705             AccessorInfo::cast(*accessors)->is_special_data_property()) {
   4706           *found = false;
   4707           return Nothing<bool>();
   4708         }
   4709         return SetPropertyWithAccessor(it, value, should_throw);
   4710       }
   4711       case LookupIterator::INTEGER_INDEXED_EXOTIC:
   4712         // TODO(verwaest): We should throw an exception if holder is receiver.
   4713         return Just(true);
   4714 
   4715       case LookupIterator::DATA:
   4716         if (it->IsReadOnly()) {
   4717           return WriteToReadOnlyProperty(it, value, should_throw);
   4718         }
   4719         if (it->HolderIsReceiverOrHiddenPrototype()) {
   4720           return SetDataProperty(it, value);
   4721         }
   4722       // Fall through.
   4723       case LookupIterator::TRANSITION:
   4724         *found = false;
   4725         return Nothing<bool>();
   4726     }
   4727     it->Next();
   4728   } while (it->IsFound());
   4729 
   4730   *found = false;
   4731   return Nothing<bool>();
   4732 }
   4733 
   4734 
   4735 Maybe<bool> Object::SetProperty(LookupIterator* it, Handle<Object> value,
   4736                                 LanguageMode language_mode,
   4737                                 StoreFromKeyed store_mode) {
   4738   if (it->IsFound()) {
   4739     bool found = true;
   4740     Maybe<bool> result =
   4741         SetPropertyInternal(it, value, language_mode, store_mode, &found);
   4742     if (found) return result;
   4743   }
   4744 
   4745   // If the receiver is the JSGlobalObject, the store was contextual. In case
   4746   // the property did not exist yet on the global object itself, we have to
   4747   // throw a reference error in strict mode.  In sloppy mode, we continue.
   4748   if (is_strict(language_mode) && it->GetReceiver()->IsJSGlobalObject()) {
   4749     it->isolate()->Throw(*it->isolate()->factory()->NewReferenceError(
   4750         MessageTemplate::kNotDefined, it->name()));
   4751     return Nothing<bool>();
   4752   }
   4753 
   4754   ShouldThrow should_throw =
   4755       is_sloppy(language_mode) ? DONT_THROW : THROW_ON_ERROR;
   4756   return AddDataProperty(it, value, NONE, should_throw, store_mode);
   4757 }
   4758 
   4759 
   4760 Maybe<bool> Object::SetSuperProperty(LookupIterator* it, Handle<Object> value,
   4761                                      LanguageMode language_mode,
   4762                                      StoreFromKeyed store_mode) {
   4763   Isolate* isolate = it->isolate();
   4764 
   4765   if (it->IsFound()) {
   4766     bool found = true;
   4767     Maybe<bool> result =
   4768         SetPropertyInternal(it, value, language_mode, store_mode, &found);
   4769     if (found) return result;
   4770   }
   4771 
   4772   it->UpdateProtector();
   4773 
   4774   // The property either doesn't exist on the holder or exists there as a data
   4775   // property.
   4776 
   4777   ShouldThrow should_throw =
   4778       is_sloppy(language_mode) ? DONT_THROW : THROW_ON_ERROR;
   4779 
   4780   if (!it->GetReceiver()->IsJSReceiver()) {
   4781     return WriteToReadOnlyProperty(it, value, should_throw);
   4782   }
   4783   Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(it->GetReceiver());
   4784 
   4785   LookupIterator::Configuration c = LookupIterator::OWN;
   4786   LookupIterator own_lookup =
   4787       it->IsElement() ? LookupIterator(isolate, receiver, it->index(), c)
   4788                       : LookupIterator(receiver, it->name(), c);
   4789 
   4790   for (; own_lookup.IsFound(); own_lookup.Next()) {
   4791     switch (own_lookup.state()) {
   4792       case LookupIterator::ACCESS_CHECK:
   4793         if (!own_lookup.HasAccess()) {
   4794           return JSObject::SetPropertyWithFailedAccessCheck(&own_lookup, value,
   4795                                                             should_throw);
   4796         }
   4797         break;
   4798 
   4799       case LookupIterator::ACCESSOR:
   4800         if (own_lookup.GetAccessors()->IsAccessorInfo()) {
   4801           if (own_lookup.IsReadOnly()) {
   4802             return WriteToReadOnlyProperty(&own_lookup, value, should_throw);
   4803           }
   4804           return JSObject::SetPropertyWithAccessor(&own_lookup, value,
   4805                                                    should_throw);
   4806         }
   4807       // Fall through.
   4808       case LookupIterator::INTEGER_INDEXED_EXOTIC:
   4809         return RedefineIncompatibleProperty(isolate, it->GetName(), value,
   4810                                             should_throw);
   4811 
   4812       case LookupIterator::DATA: {
   4813         if (own_lookup.IsReadOnly()) {
   4814           return WriteToReadOnlyProperty(&own_lookup, value, should_throw);
   4815         }
   4816         return SetDataProperty(&own_lookup, value);
   4817       }
   4818 
   4819       case LookupIterator::INTERCEPTOR:
   4820       case LookupIterator::JSPROXY: {
   4821         PropertyDescriptor desc;
   4822         Maybe<bool> owned =
   4823             JSReceiver::GetOwnPropertyDescriptor(&own_lookup, &desc);
   4824         MAYBE_RETURN(owned, Nothing<bool>());
   4825         if (!owned.FromJust()) {
   4826           return JSReceiver::CreateDataProperty(&own_lookup, value,
   4827                                                 should_throw);
   4828         }
   4829         if (PropertyDescriptor::IsAccessorDescriptor(&desc) ||
   4830             !desc.writable()) {
   4831           return RedefineIncompatibleProperty(isolate, it->GetName(), value,
   4832                                               should_throw);
   4833         }
   4834 
   4835         PropertyDescriptor value_desc;
   4836         value_desc.set_value(value);
   4837         return JSReceiver::DefineOwnProperty(isolate, receiver, it->GetName(),
   4838                                              &value_desc, should_throw);
   4839       }
   4840 
   4841       case LookupIterator::NOT_FOUND:
   4842       case LookupIterator::TRANSITION:
   4843         UNREACHABLE();
   4844     }
   4845   }
   4846 
   4847   return AddDataProperty(&own_lookup, value, NONE, should_throw, store_mode);
   4848 }
   4849 
   4850 Maybe<bool> Object::CannotCreateProperty(Isolate* isolate,
   4851                                          Handle<Object> receiver,
   4852                                          Handle<Object> name,
   4853                                          Handle<Object> value,
   4854                                          ShouldThrow should_throw) {
   4855   RETURN_FAILURE(
   4856       isolate, should_throw,
   4857       NewTypeError(MessageTemplate::kStrictCannotCreateProperty, name,
   4858                    Object::TypeOf(isolate, receiver), receiver));
   4859 }
   4860 
   4861 
   4862 Maybe<bool> Object::WriteToReadOnlyProperty(LookupIterator* it,
   4863                                             Handle<Object> value,
   4864                                             ShouldThrow should_throw) {
   4865   return WriteToReadOnlyProperty(it->isolate(), it->GetReceiver(),
   4866                                  it->GetName(), value, should_throw);
   4867 }
   4868 
   4869 
   4870 Maybe<bool> Object::WriteToReadOnlyProperty(Isolate* isolate,
   4871                                             Handle<Object> receiver,
   4872                                             Handle<Object> name,
   4873                                             Handle<Object> value,
   4874                                             ShouldThrow should_throw) {
   4875   RETURN_FAILURE(isolate, should_throw,
   4876                  NewTypeError(MessageTemplate::kStrictReadOnlyProperty, name,
   4877                               Object::TypeOf(isolate, receiver), receiver));
   4878 }
   4879 
   4880 
   4881 Maybe<bool> Object::RedefineIncompatibleProperty(Isolate* isolate,
   4882                                                  Handle<Object> name,
   4883                                                  Handle<Object> value,
   4884                                                  ShouldThrow should_throw) {
   4885   RETURN_FAILURE(isolate, should_throw,
   4886                  NewTypeError(MessageTemplate::kRedefineDisallowed, name));
   4887 }
   4888 
   4889 
   4890 Maybe<bool> Object::SetDataProperty(LookupIterator* it, Handle<Object> value) {
   4891   // Proxies are handled elsewhere. Other non-JSObjects cannot have own
   4892   // properties.
   4893   Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver());
   4894 
   4895   // Store on the holder which may be hidden behind the receiver.
   4896   DCHECK(it->HolderIsReceiverOrHiddenPrototype());
   4897 
   4898   Handle<Object> to_assign = value;
   4899   // Convert the incoming value to a number for storing into typed arrays.
   4900   if (it->IsElement() && receiver->HasFixedTypedArrayElements()) {
   4901     if (!value->IsNumber() && !value->IsUndefined(it->isolate())) {
   4902       ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   4903           it->isolate(), to_assign, Object::ToNumber(value), Nothing<bool>());
   4904       // We have to recheck the length. However, it can only change if the
   4905       // underlying buffer was neutered, so just check that.
   4906       if (Handle<JSArrayBufferView>::cast(receiver)->WasNeutered()) {
   4907         return Just(true);
   4908         // TODO(neis): According to the spec, this should throw a TypeError.
   4909       }
   4910     }
   4911   }
   4912 
   4913   // Possibly migrate to the most up-to-date map that will be able to store
   4914   // |value| under it->name().
   4915   it->PrepareForDataProperty(to_assign);
   4916 
   4917   // Write the property value.
   4918   it->WriteDataValue(to_assign);
   4919 
   4920 #if VERIFY_HEAP
   4921   if (FLAG_verify_heap) {
   4922     receiver->JSObjectVerify();
   4923   }
   4924 #endif
   4925   return Just(true);
   4926 }
   4927 
   4928 
   4929 Maybe<bool> Object::AddDataProperty(LookupIterator* it, Handle<Object> value,
   4930                                     PropertyAttributes attributes,
   4931                                     ShouldThrow should_throw,
   4932                                     StoreFromKeyed store_mode) {
   4933   if (!it->GetReceiver()->IsJSObject()) {
   4934     if (it->GetReceiver()->IsJSProxy() && it->GetName()->IsPrivate()) {
   4935       RETURN_FAILURE(it->isolate(), should_throw,
   4936                      NewTypeError(MessageTemplate::kProxyPrivate));
   4937     }
   4938     return CannotCreateProperty(it->isolate(), it->GetReceiver(), it->GetName(),
   4939                                 value, should_throw);
   4940   }
   4941 
   4942   DCHECK_NE(LookupIterator::INTEGER_INDEXED_EXOTIC, it->state());
   4943 
   4944   Handle<JSObject> receiver = it->GetStoreTarget();
   4945 
   4946   // If the receiver is a JSGlobalProxy, store on the prototype (JSGlobalObject)
   4947   // instead. If the prototype is Null, the proxy is detached.
   4948   if (receiver->IsJSGlobalProxy()) return Just(true);
   4949 
   4950   Isolate* isolate = it->isolate();
   4951 
   4952   if (it->ExtendingNonExtensible(receiver)) {
   4953     RETURN_FAILURE(
   4954         isolate, should_throw,
   4955         NewTypeError(MessageTemplate::kObjectNotExtensible, it->GetName()));
   4956   }
   4957 
   4958   if (it->IsElement()) {
   4959     if (receiver->IsJSArray()) {
   4960       Handle<JSArray> array = Handle<JSArray>::cast(receiver);
   4961       if (JSArray::WouldChangeReadOnlyLength(array, it->index())) {
   4962         RETURN_FAILURE(array->GetIsolate(), should_throw,
   4963                        NewTypeError(MessageTemplate::kStrictReadOnlyProperty,
   4964                                     isolate->factory()->length_string(),
   4965                                     Object::TypeOf(isolate, array), array));
   4966       }
   4967 
   4968       if (FLAG_trace_external_array_abuse &&
   4969           array->HasFixedTypedArrayElements()) {
   4970         CheckArrayAbuse(array, "typed elements write", it->index(), true);
   4971       }
   4972 
   4973       if (FLAG_trace_js_array_abuse && !array->HasFixedTypedArrayElements()) {
   4974         CheckArrayAbuse(array, "elements write", it->index(), false);
   4975       }
   4976     }
   4977 
   4978     Maybe<bool> result = JSObject::AddDataElement(receiver, it->index(), value,
   4979                                                   attributes, should_throw);
   4980     JSObject::ValidateElements(receiver);
   4981     return result;
   4982   } else {
   4983     it->UpdateProtector();
   4984     // Migrate to the most up-to-date map that will be able to store |value|
   4985     // under it->name() with |attributes|.
   4986     it->PrepareTransitionToDataProperty(receiver, value, attributes,
   4987                                         store_mode);
   4988     DCHECK_EQ(LookupIterator::TRANSITION, it->state());
   4989     it->ApplyTransitionToDataProperty(receiver);
   4990 
   4991     // Write the property value.
   4992     it->WriteDataValue(value);
   4993 
   4994 #if VERIFY_HEAP
   4995     if (FLAG_verify_heap) {
   4996       receiver->JSObjectVerify();
   4997     }
   4998 #endif
   4999   }
   5000 
   5001   return Just(true);
   5002 }
   5003 
   5004 
   5005 void Map::EnsureDescriptorSlack(Handle<Map> map, int slack) {
   5006   // Only supports adding slack to owned descriptors.
   5007   DCHECK(map->owns_descriptors());
   5008 
   5009   Handle<DescriptorArray> descriptors(map->instance_descriptors());
   5010   int old_size = map->NumberOfOwnDescriptors();
   5011   if (slack <= descriptors->NumberOfSlackDescriptors()) return;
   5012 
   5013   Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo(
   5014       descriptors, old_size, slack);
   5015 
   5016   DisallowHeapAllocation no_allocation;
   5017   // The descriptors are still the same, so keep the layout descriptor.
   5018   LayoutDescriptor* layout_descriptor = map->GetLayoutDescriptor();
   5019 
   5020   if (old_size == 0) {
   5021     map->UpdateDescriptors(*new_descriptors, layout_descriptor);
   5022     return;
   5023   }
   5024 
   5025   // If the source descriptors had an enum cache we copy it. This ensures
   5026   // that the maps to which we push the new descriptor array back can rely
   5027   // on a cache always being available once it is set. If the map has more
   5028   // enumerated descriptors than available in the original cache, the cache
   5029   // will be lazily replaced by the extended cache when needed.
   5030   if (descriptors->HasEnumCache()) {
   5031     new_descriptors->CopyEnumCacheFrom(*descriptors);
   5032   }
   5033 
   5034   Isolate* isolate = map->GetIsolate();
   5035   // Replace descriptors by new_descriptors in all maps that share it.
   5036   isolate->heap()->incremental_marking()->IterateBlackObject(*descriptors);
   5037 
   5038   Map* current = *map;
   5039   while (current->instance_descriptors() == *descriptors) {
   5040     Object* next = current->GetBackPointer();
   5041     if (next->IsUndefined(isolate)) break;  // Stop overwriting at initial map.
   5042     current->UpdateDescriptors(*new_descriptors, layout_descriptor);
   5043     current = Map::cast(next);
   5044   }
   5045   map->UpdateDescriptors(*new_descriptors, layout_descriptor);
   5046 }
   5047 
   5048 template <class T>
   5049 static int AppendUniqueCallbacks(Handle<TemplateList> callbacks,
   5050                                  Handle<typename T::Array> array,
   5051                                  int valid_descriptors) {
   5052   int nof_callbacks = callbacks->length();
   5053 
   5054   Isolate* isolate = array->GetIsolate();
   5055   // Ensure the keys are unique names before writing them into the
   5056   // instance descriptor. Since it may cause a GC, it has to be done before we
   5057   // temporarily put the heap in an invalid state while appending descriptors.
   5058   for (int i = 0; i < nof_callbacks; ++i) {
   5059     Handle<AccessorInfo> entry(AccessorInfo::cast(callbacks->get(i)));
   5060     if (entry->name()->IsUniqueName()) continue;
   5061     Handle<String> key =
   5062         isolate->factory()->InternalizeString(
   5063             Handle<String>(String::cast(entry->name())));
   5064     entry->set_name(*key);
   5065   }
   5066 
   5067   // Fill in new callback descriptors.  Process the callbacks from
   5068   // back to front so that the last callback with a given name takes
   5069   // precedence over previously added callbacks with that name.
   5070   for (int i = nof_callbacks - 1; i >= 0; i--) {
   5071     Handle<AccessorInfo> entry(AccessorInfo::cast(callbacks->get(i)));
   5072     Handle<Name> key(Name::cast(entry->name()));
   5073     // Check if a descriptor with this name already exists before writing.
   5074     if (!T::Contains(key, entry, valid_descriptors, array)) {
   5075       T::Insert(key, entry, valid_descriptors, array);
   5076       valid_descriptors++;
   5077     }
   5078   }
   5079 
   5080   return valid_descriptors;
   5081 }
   5082 
   5083 struct DescriptorArrayAppender {
   5084   typedef DescriptorArray Array;
   5085   static bool Contains(Handle<Name> key,
   5086                        Handle<AccessorInfo> entry,
   5087                        int valid_descriptors,
   5088                        Handle<DescriptorArray> array) {
   5089     DisallowHeapAllocation no_gc;
   5090     return array->Search(*key, valid_descriptors) != DescriptorArray::kNotFound;
   5091   }
   5092   static void Insert(Handle<Name> key,
   5093                      Handle<AccessorInfo> entry,
   5094                      int valid_descriptors,
   5095                      Handle<DescriptorArray> array) {
   5096     DisallowHeapAllocation no_gc;
   5097     AccessorConstantDescriptor desc(key, entry, entry->property_attributes());
   5098     array->Append(&desc);
   5099   }
   5100 };
   5101 
   5102 
   5103 struct FixedArrayAppender {
   5104   typedef FixedArray Array;
   5105   static bool Contains(Handle<Name> key,
   5106                        Handle<AccessorInfo> entry,
   5107                        int valid_descriptors,
   5108                        Handle<FixedArray> array) {
   5109     for (int i = 0; i < valid_descriptors; i++) {
   5110       if (*key == AccessorInfo::cast(array->get(i))->name()) return true;
   5111     }
   5112     return false;
   5113   }
   5114   static void Insert(Handle<Name> key,
   5115                      Handle<AccessorInfo> entry,
   5116                      int valid_descriptors,
   5117                      Handle<FixedArray> array) {
   5118     DisallowHeapAllocation no_gc;
   5119     array->set(valid_descriptors, *entry);
   5120   }
   5121 };
   5122 
   5123 
   5124 void Map::AppendCallbackDescriptors(Handle<Map> map,
   5125                                     Handle<Object> descriptors) {
   5126   int nof = map->NumberOfOwnDescriptors();
   5127   Handle<DescriptorArray> array(map->instance_descriptors());
   5128   Handle<TemplateList> callbacks = Handle<TemplateList>::cast(descriptors);
   5129   DCHECK_GE(array->NumberOfSlackDescriptors(), callbacks->length());
   5130   nof = AppendUniqueCallbacks<DescriptorArrayAppender>(callbacks, array, nof);
   5131   map->SetNumberOfOwnDescriptors(nof);
   5132 }
   5133 
   5134 
   5135 int AccessorInfo::AppendUnique(Handle<Object> descriptors,
   5136                                Handle<FixedArray> array,
   5137                                int valid_descriptors) {
   5138   Handle<TemplateList> callbacks = Handle<TemplateList>::cast(descriptors);
   5139   DCHECK_GE(array->length(), callbacks->length() + valid_descriptors);
   5140   return AppendUniqueCallbacks<FixedArrayAppender>(callbacks, array,
   5141                                                    valid_descriptors);
   5142 }
   5143 
   5144 
   5145 static bool ContainsMap(MapHandleList* maps, Map* map) {
   5146   DCHECK_NOT_NULL(map);
   5147   for (int i = 0; i < maps->length(); ++i) {
   5148     if (!maps->at(i).is_null() && *maps->at(i) == map) return true;
   5149   }
   5150   return false;
   5151 }
   5152 
   5153 Map* Map::FindElementsKindTransitionedMap(MapHandleList* candidates) {
   5154   DisallowHeapAllocation no_allocation;
   5155   DisallowDeoptimization no_deoptimization(GetIsolate());
   5156 
   5157   ElementsKind kind = elements_kind();
   5158   bool packed = IsFastPackedElementsKind(kind);
   5159 
   5160   Map* transition = nullptr;
   5161   if (IsTransitionableFastElementsKind(kind)) {
   5162     // Check the state of the root map.
   5163     Map* root_map = FindRootMap();
   5164     if (!EquivalentToForTransition(root_map)) return nullptr;
   5165     root_map = root_map->LookupElementsTransitionMap(kind);
   5166     DCHECK_NOT_NULL(root_map);
   5167     // Starting from the next existing elements kind transition try to
   5168     // replay the property transitions that does not involve instance rewriting
   5169     // (ElementsTransitionAndStoreStub does not support that).
   5170     for (root_map = root_map->ElementsTransitionMap();
   5171          root_map != nullptr && root_map->has_fast_elements();
   5172          root_map = root_map->ElementsTransitionMap()) {
   5173       Map* current = root_map->TryReplayPropertyTransitions(this);
   5174       if (current == nullptr) continue;
   5175       if (InstancesNeedRewriting(current)) continue;
   5176 
   5177       if (ContainsMap(candidates, current) &&
   5178           (packed || !IsFastPackedElementsKind(current->elements_kind()))) {
   5179         transition = current;
   5180         packed = packed && IsFastPackedElementsKind(current->elements_kind());
   5181       }
   5182     }
   5183   }
   5184   return transition;
   5185 }
   5186 
   5187 
   5188 static Map* FindClosestElementsTransition(Map* map, ElementsKind to_kind) {
   5189   // Ensure we are requested to search elements kind transition "near the root".
   5190   DCHECK_EQ(map->FindRootMap()->NumberOfOwnDescriptors(),
   5191             map->NumberOfOwnDescriptors());
   5192   Map* current_map = map;
   5193 
   5194   ElementsKind kind = map->elements_kind();
   5195   while (kind != to_kind) {
   5196     Map* next_map = current_map->ElementsTransitionMap();
   5197     if (next_map == nullptr) return current_map;
   5198     kind = next_map->elements_kind();
   5199     current_map = next_map;
   5200   }
   5201 
   5202   DCHECK_EQ(to_kind, current_map->elements_kind());
   5203   return current_map;
   5204 }
   5205 
   5206 
   5207 Map* Map::LookupElementsTransitionMap(ElementsKind to_kind) {
   5208   Map* to_map = FindClosestElementsTransition(this, to_kind);
   5209   if (to_map->elements_kind() == to_kind) return to_map;
   5210   return nullptr;
   5211 }
   5212 
   5213 
   5214 bool Map::IsMapInArrayPrototypeChain() {
   5215   Isolate* isolate = GetIsolate();
   5216   if (isolate->initial_array_prototype()->map() == this) {
   5217     return true;
   5218   }
   5219 
   5220   if (isolate->initial_object_prototype()->map() == this) {
   5221     return true;
   5222   }
   5223 
   5224   return false;
   5225 }
   5226 
   5227 
   5228 Handle<WeakCell> Map::WeakCellForMap(Handle<Map> map) {
   5229   Isolate* isolate = map->GetIsolate();
   5230   if (map->weak_cell_cache()->IsWeakCell()) {
   5231     return Handle<WeakCell>(WeakCell::cast(map->weak_cell_cache()));
   5232   }
   5233   Handle<WeakCell> weak_cell = isolate->factory()->NewWeakCell(map);
   5234   map->set_weak_cell_cache(*weak_cell);
   5235   return weak_cell;
   5236 }
   5237 
   5238 
   5239 static Handle<Map> AddMissingElementsTransitions(Handle<Map> map,
   5240                                                  ElementsKind to_kind) {
   5241   DCHECK(IsTransitionElementsKind(map->elements_kind()));
   5242 
   5243   Handle<Map> current_map = map;
   5244 
   5245   ElementsKind kind = map->elements_kind();
   5246   TransitionFlag flag;
   5247   if (map->is_prototype_map()) {
   5248     flag = OMIT_TRANSITION;
   5249   } else {
   5250     flag = INSERT_TRANSITION;
   5251     if (IsFastElementsKind(kind)) {
   5252       while (kind != to_kind && !IsTerminalElementsKind(kind)) {
   5253         kind = GetNextTransitionElementsKind(kind);
   5254         current_map = Map::CopyAsElementsKind(current_map, kind, flag);
   5255       }
   5256     }
   5257   }
   5258 
   5259   // In case we are exiting the fast elements kind system, just add the map in
   5260   // the end.
   5261   if (kind != to_kind) {
   5262     current_map = Map::CopyAsElementsKind(current_map, to_kind, flag);
   5263   }
   5264 
   5265   DCHECK(current_map->elements_kind() == to_kind);
   5266   return current_map;
   5267 }
   5268 
   5269 
   5270 Handle<Map> Map::TransitionElementsTo(Handle<Map> map,
   5271                                       ElementsKind to_kind) {
   5272   ElementsKind from_kind = map->elements_kind();
   5273   if (from_kind == to_kind) return map;
   5274 
   5275   Isolate* isolate = map->GetIsolate();
   5276   Context* native_context = isolate->context()->native_context();
   5277   if (from_kind == FAST_SLOPPY_ARGUMENTS_ELEMENTS) {
   5278     if (*map == native_context->fast_aliased_arguments_map()) {
   5279       DCHECK_EQ(SLOW_SLOPPY_ARGUMENTS_ELEMENTS, to_kind);
   5280       return handle(native_context->slow_aliased_arguments_map());
   5281     }
   5282   } else if (from_kind == SLOW_SLOPPY_ARGUMENTS_ELEMENTS) {
   5283     if (*map == native_context->slow_aliased_arguments_map()) {
   5284       DCHECK_EQ(FAST_SLOPPY_ARGUMENTS_ELEMENTS, to_kind);
   5285       return handle(native_context->fast_aliased_arguments_map());
   5286     }
   5287   } else if (IsFastElementsKind(from_kind) && IsFastElementsKind(to_kind)) {
   5288     // Reuse map transitions for JSArrays.
   5289     DisallowHeapAllocation no_gc;
   5290     if (native_context->get(Context::ArrayMapIndex(from_kind)) == *map) {
   5291       Object* maybe_transitioned_map =
   5292           native_context->get(Context::ArrayMapIndex(to_kind));
   5293       if (maybe_transitioned_map->IsMap()) {
   5294         return handle(Map::cast(maybe_transitioned_map), isolate);
   5295       }
   5296     }
   5297   }
   5298 
   5299   DCHECK(!map->IsUndefined(isolate));
   5300   // Check if we can go back in the elements kind transition chain.
   5301   if (IsHoleyElementsKind(from_kind) &&
   5302       to_kind == GetPackedElementsKind(from_kind) &&
   5303       map->GetBackPointer()->IsMap() &&
   5304       Map::cast(map->GetBackPointer())->elements_kind() == to_kind) {
   5305     return handle(Map::cast(map->GetBackPointer()));
   5306   }
   5307 
   5308   bool allow_store_transition = IsTransitionElementsKind(from_kind);
   5309   // Only store fast element maps in ascending generality.
   5310   if (IsFastElementsKind(to_kind)) {
   5311     allow_store_transition =
   5312         allow_store_transition && IsTransitionableFastElementsKind(from_kind) &&
   5313         IsMoreGeneralElementsKindTransition(from_kind, to_kind);
   5314   }
   5315 
   5316   if (!allow_store_transition) {
   5317     return Map::CopyAsElementsKind(map, to_kind, OMIT_TRANSITION);
   5318   }
   5319 
   5320   return Map::ReconfigureElementsKind(map, to_kind);
   5321 }
   5322 
   5323 
   5324 // static
   5325 Handle<Map> Map::AsElementsKind(Handle<Map> map, ElementsKind kind) {
   5326   Handle<Map> closest_map(FindClosestElementsTransition(*map, kind));
   5327 
   5328   if (closest_map->elements_kind() == kind) {
   5329     return closest_map;
   5330   }
   5331 
   5332   return AddMissingElementsTransitions(closest_map, kind);
   5333 }
   5334 
   5335 
   5336 Handle<Map> JSObject::GetElementsTransitionMap(Handle<JSObject> object,
   5337                                                ElementsKind to_kind) {
   5338   Handle<Map> map(object->map());
   5339   return Map::TransitionElementsTo(map, to_kind);
   5340 }
   5341 
   5342 
   5343 void JSProxy::Revoke(Handle<JSProxy> proxy) {
   5344   Isolate* isolate = proxy->GetIsolate();
   5345   if (!proxy->IsRevoked()) proxy->set_handler(isolate->heap()->null_value());
   5346   DCHECK(proxy->IsRevoked());
   5347 }
   5348 
   5349 
   5350 Maybe<bool> JSProxy::HasProperty(Isolate* isolate, Handle<JSProxy> proxy,
   5351                                  Handle<Name> name) {
   5352   DCHECK(!name->IsPrivate());
   5353   STACK_CHECK(isolate, Nothing<bool>());
   5354   // 1. (Assert)
   5355   // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O.
   5356   Handle<Object> handler(proxy->handler(), isolate);
   5357   // 3. If handler is null, throw a TypeError exception.
   5358   // 4. Assert: Type(handler) is Object.
   5359   if (proxy->IsRevoked()) {
   5360     isolate->Throw(*isolate->factory()->NewTypeError(
   5361         MessageTemplate::kProxyRevoked, isolate->factory()->has_string()));
   5362     return Nothing<bool>();
   5363   }
   5364   // 5. Let target be the value of the [[ProxyTarget]] internal slot of O.
   5365   Handle<JSReceiver> target(proxy->target(), isolate);
   5366   // 6. Let trap be ? GetMethod(handler, "has").
   5367   Handle<Object> trap;
   5368   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   5369       isolate, trap, Object::GetMethod(Handle<JSReceiver>::cast(handler),
   5370                                        isolate->factory()->has_string()),
   5371       Nothing<bool>());
   5372   // 7. If trap is undefined, then
   5373   if (trap->IsUndefined(isolate)) {
   5374     // 7a. Return target.[[HasProperty]](P).
   5375     return JSReceiver::HasProperty(target, name);
   5376   }
   5377   // 8. Let booleanTrapResult be ToBoolean(? Call(trap, handler, target, P)).
   5378   Handle<Object> trap_result_obj;
   5379   Handle<Object> args[] = {target, name};
   5380   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   5381       isolate, trap_result_obj,
   5382       Execution::Call(isolate, trap, handler, arraysize(args), args),
   5383       Nothing<bool>());
   5384   bool boolean_trap_result = trap_result_obj->BooleanValue();
   5385   // 9. If booleanTrapResult is false, then:
   5386   if (!boolean_trap_result) {
   5387     // 9a. Let targetDesc be ? target.[[GetOwnProperty]](P).
   5388     PropertyDescriptor target_desc;
   5389     Maybe<bool> target_found = JSReceiver::GetOwnPropertyDescriptor(
   5390         isolate, target, name, &target_desc);
   5391     MAYBE_RETURN(target_found, Nothing<bool>());
   5392     // 9b. If targetDesc is not undefined, then:
   5393     if (target_found.FromJust()) {
   5394       // 9b i. If targetDesc.[[Configurable]] is false, throw a TypeError
   5395       //       exception.
   5396       if (!target_desc.configurable()) {
   5397         isolate->Throw(*isolate->factory()->NewTypeError(
   5398             MessageTemplate::kProxyHasNonConfigurable, name));
   5399         return Nothing<bool>();
   5400       }
   5401       // 9b ii. Let extensibleTarget be ? IsExtensible(target).
   5402       Maybe<bool> extensible_target = JSReceiver::IsExtensible(target);
   5403       MAYBE_RETURN(extensible_target, Nothing<bool>());
   5404       // 9b iii. If extensibleTarget is false, throw a TypeError exception.
   5405       if (!extensible_target.FromJust()) {
   5406         isolate->Throw(*isolate->factory()->NewTypeError(
   5407             MessageTemplate::kProxyHasNonExtensible, name));
   5408         return Nothing<bool>();
   5409       }
   5410     }
   5411   }
   5412   // 10. Return booleanTrapResult.
   5413   return Just(boolean_trap_result);
   5414 }
   5415 
   5416 
   5417 Maybe<bool> JSProxy::SetProperty(Handle<JSProxy> proxy, Handle<Name> name,
   5418                                  Handle<Object> value, Handle<Object> receiver,
   5419                                  LanguageMode language_mode) {
   5420   DCHECK(!name->IsPrivate());
   5421   Isolate* isolate = proxy->GetIsolate();
   5422   STACK_CHECK(isolate, Nothing<bool>());
   5423   Factory* factory = isolate->factory();
   5424   Handle<String> trap_name = factory->set_string();
   5425   ShouldThrow should_throw =
   5426       is_sloppy(language_mode) ? DONT_THROW : THROW_ON_ERROR;
   5427 
   5428   if (proxy->IsRevoked()) {
   5429     isolate->Throw(
   5430         *factory->NewTypeError(MessageTemplate::kProxyRevoked, trap_name));
   5431     return Nothing<bool>();
   5432   }
   5433   Handle<JSReceiver> target(proxy->target(), isolate);
   5434   Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate);
   5435 
   5436   Handle<Object> trap;
   5437   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   5438       isolate, trap, Object::GetMethod(handler, trap_name), Nothing<bool>());
   5439   if (trap->IsUndefined(isolate)) {
   5440     LookupIterator it =
   5441         LookupIterator::PropertyOrElement(isolate, receiver, name, target);
   5442     return Object::SetSuperProperty(&it, value, language_mode,
   5443                                     Object::MAY_BE_STORE_FROM_KEYED);
   5444   }
   5445 
   5446   Handle<Object> trap_result;
   5447   Handle<Object> args[] = {target, name, value, receiver};
   5448   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   5449       isolate, trap_result,
   5450       Execution::Call(isolate, trap, handler, arraysize(args), args),
   5451       Nothing<bool>());
   5452   if (!trap_result->BooleanValue()) {
   5453     RETURN_FAILURE(isolate, should_throw,
   5454                    NewTypeError(MessageTemplate::kProxyTrapReturnedFalsishFor,
   5455                                 trap_name, name));
   5456   }
   5457 
   5458   // Enforce the invariant.
   5459   PropertyDescriptor target_desc;
   5460   Maybe<bool> owned =
   5461       JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, &target_desc);
   5462   MAYBE_RETURN(owned, Nothing<bool>());
   5463   if (owned.FromJust()) {
   5464     bool inconsistent = PropertyDescriptor::IsDataDescriptor(&target_desc) &&
   5465                         !target_desc.configurable() &&
   5466                         !target_desc.writable() &&
   5467                         !value->SameValue(*target_desc.value());
   5468     if (inconsistent) {
   5469       isolate->Throw(*isolate->factory()->NewTypeError(
   5470           MessageTemplate::kProxySetFrozenData, name));
   5471       return Nothing<bool>();
   5472     }
   5473     inconsistent = PropertyDescriptor::IsAccessorDescriptor(&target_desc) &&
   5474                    !target_desc.configurable() &&
   5475                    target_desc.set()->IsUndefined(isolate);
   5476     if (inconsistent) {
   5477       isolate->Throw(*isolate->factory()->NewTypeError(
   5478           MessageTemplate::kProxySetFrozenAccessor, name));
   5479       return Nothing<bool>();
   5480     }
   5481   }
   5482   return Just(true);
   5483 }
   5484 
   5485 
   5486 Maybe<bool> JSProxy::DeletePropertyOrElement(Handle<JSProxy> proxy,
   5487                                              Handle<Name> name,
   5488                                              LanguageMode language_mode) {
   5489   DCHECK(!name->IsPrivate());
   5490   ShouldThrow should_throw =
   5491       is_sloppy(language_mode) ? DONT_THROW : THROW_ON_ERROR;
   5492   Isolate* isolate = proxy->GetIsolate();
   5493   STACK_CHECK(isolate, Nothing<bool>());
   5494   Factory* factory = isolate->factory();
   5495   Handle<String> trap_name = factory->deleteProperty_string();
   5496 
   5497   if (proxy->IsRevoked()) {
   5498     isolate->Throw(
   5499         *factory->NewTypeError(MessageTemplate::kProxyRevoked, trap_name));
   5500     return Nothing<bool>();
   5501   }
   5502   Handle<JSReceiver> target(proxy->target(), isolate);
   5503   Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate);
   5504 
   5505   Handle<Object> trap;
   5506   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   5507       isolate, trap, Object::GetMethod(handler, trap_name), Nothing<bool>());
   5508   if (trap->IsUndefined(isolate)) {
   5509     return JSReceiver::DeletePropertyOrElement(target, name, language_mode);
   5510   }
   5511 
   5512   Handle<Object> trap_result;
   5513   Handle<Object> args[] = {target, name};
   5514   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   5515       isolate, trap_result,
   5516       Execution::Call(isolate, trap, handler, arraysize(args), args),
   5517       Nothing<bool>());
   5518   if (!trap_result->BooleanValue()) {
   5519     RETURN_FAILURE(isolate, should_throw,
   5520                    NewTypeError(MessageTemplate::kProxyTrapReturnedFalsishFor,
   5521                                 trap_name, name));
   5522   }
   5523 
   5524   // Enforce the invariant.
   5525   PropertyDescriptor target_desc;
   5526   Maybe<bool> owned =
   5527       JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, &target_desc);
   5528   MAYBE_RETURN(owned, Nothing<bool>());
   5529   if (owned.FromJust() && !target_desc.configurable()) {
   5530     isolate->Throw(*factory->NewTypeError(
   5531         MessageTemplate::kProxyDeletePropertyNonConfigurable, name));
   5532     return Nothing<bool>();
   5533   }
   5534   return Just(true);
   5535 }
   5536 
   5537 
   5538 // static
   5539 MaybeHandle<JSProxy> JSProxy::New(Isolate* isolate, Handle<Object> target,
   5540                                   Handle<Object> handler) {
   5541   if (!target->IsJSReceiver()) {
   5542     THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kProxyNonObject),
   5543                     JSProxy);
   5544   }
   5545   if (target->IsJSProxy() && JSProxy::cast(*target)->IsRevoked()) {
   5546     THROW_NEW_ERROR(isolate,
   5547                     NewTypeError(MessageTemplate::kProxyHandlerOrTargetRevoked),
   5548                     JSProxy);
   5549   }
   5550   if (!handler->IsJSReceiver()) {
   5551     THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kProxyNonObject),
   5552                     JSProxy);
   5553   }
   5554   if (handler->IsJSProxy() && JSProxy::cast(*handler)->IsRevoked()) {
   5555     THROW_NEW_ERROR(isolate,
   5556                     NewTypeError(MessageTemplate::kProxyHandlerOrTargetRevoked),
   5557                     JSProxy);
   5558   }
   5559   return isolate->factory()->NewJSProxy(Handle<JSReceiver>::cast(target),
   5560                                         Handle<JSReceiver>::cast(handler));
   5561 }
   5562 
   5563 
   5564 // static
   5565 MaybeHandle<Context> JSProxy::GetFunctionRealm(Handle<JSProxy> proxy) {
   5566   DCHECK(proxy->map()->is_constructor());
   5567   if (proxy->IsRevoked()) {
   5568     THROW_NEW_ERROR(proxy->GetIsolate(),
   5569                     NewTypeError(MessageTemplate::kProxyRevoked), Context);
   5570   }
   5571   Handle<JSReceiver> target(JSReceiver::cast(proxy->target()));
   5572   return JSReceiver::GetFunctionRealm(target);
   5573 }
   5574 
   5575 
   5576 // static
   5577 MaybeHandle<Context> JSBoundFunction::GetFunctionRealm(
   5578     Handle<JSBoundFunction> function) {
   5579   DCHECK(function->map()->is_constructor());
   5580   return JSReceiver::GetFunctionRealm(
   5581       handle(function->bound_target_function()));
   5582 }
   5583 
   5584 // static
   5585 MaybeHandle<String> JSBoundFunction::GetName(Isolate* isolate,
   5586                                              Handle<JSBoundFunction> function) {
   5587   Handle<String> prefix = isolate->factory()->bound__string();
   5588   if (!function->bound_target_function()->IsJSFunction()) return prefix;
   5589   Handle<JSFunction> target(JSFunction::cast(function->bound_target_function()),
   5590                             isolate);
   5591   Handle<Object> target_name = JSFunction::GetName(isolate, target);
   5592   if (!target_name->IsString()) return prefix;
   5593   Factory* factory = isolate->factory();
   5594   return factory->NewConsString(prefix, Handle<String>::cast(target_name));
   5595 }
   5596 
   5597 // static
   5598 Handle<Object> JSFunction::GetName(Isolate* isolate,
   5599                                    Handle<JSFunction> function) {
   5600   if (function->shared()->name_should_print_as_anonymous()) {
   5601     return isolate->factory()->anonymous_string();
   5602   }
   5603   return handle(function->shared()->name(), isolate);
   5604 }
   5605 
   5606 // static
   5607 MaybeHandle<Smi> JSFunction::GetLength(Isolate* isolate,
   5608                                        Handle<JSFunction> function) {
   5609   int length = 0;
   5610   if (function->shared()->is_compiled()) {
   5611     length = function->shared()->length();
   5612   } else {
   5613     // If the function isn't compiled yet, the length is not computed
   5614     // correctly yet. Compile it now and return the right length.
   5615     if (Compiler::Compile(function, Compiler::KEEP_EXCEPTION)) {
   5616       length = function->shared()->length();
   5617     }
   5618     if (isolate->has_pending_exception()) return MaybeHandle<Smi>();
   5619   }
   5620   return handle(Smi::FromInt(length), isolate);
   5621 }
   5622 
   5623 // static
   5624 Handle<Context> JSFunction::GetFunctionRealm(Handle<JSFunction> function) {
   5625   DCHECK(function->map()->is_constructor());
   5626   return handle(function->context()->native_context());
   5627 }
   5628 
   5629 
   5630 // static
   5631 MaybeHandle<Context> JSObject::GetFunctionRealm(Handle<JSObject> object) {
   5632   DCHECK(object->map()->is_constructor());
   5633   DCHECK(!object->IsJSFunction());
   5634   return handle(object->GetCreationContext());
   5635 }
   5636 
   5637 
   5638 // static
   5639 MaybeHandle<Context> JSReceiver::GetFunctionRealm(Handle<JSReceiver> receiver) {
   5640   if (receiver->IsJSProxy()) {
   5641     return JSProxy::GetFunctionRealm(Handle<JSProxy>::cast(receiver));
   5642   }
   5643 
   5644   if (receiver->IsJSFunction()) {
   5645     return JSFunction::GetFunctionRealm(Handle<JSFunction>::cast(receiver));
   5646   }
   5647 
   5648   if (receiver->IsJSBoundFunction()) {
   5649     return JSBoundFunction::GetFunctionRealm(
   5650         Handle<JSBoundFunction>::cast(receiver));
   5651   }
   5652 
   5653   return JSObject::GetFunctionRealm(Handle<JSObject>::cast(receiver));
   5654 }
   5655 
   5656 
   5657 Maybe<PropertyAttributes> JSProxy::GetPropertyAttributes(LookupIterator* it) {
   5658   PropertyDescriptor desc;
   5659   Maybe<bool> found = JSProxy::GetOwnPropertyDescriptor(
   5660       it->isolate(), it->GetHolder<JSProxy>(), it->GetName(), &desc);
   5661   MAYBE_RETURN(found, Nothing<PropertyAttributes>());
   5662   if (!found.FromJust()) return Just(ABSENT);
   5663   return Just(desc.ToAttributes());
   5664 }
   5665 
   5666 
   5667 void JSObject::AllocateStorageForMap(Handle<JSObject> object, Handle<Map> map) {
   5668   DCHECK(object->map()->GetInObjectProperties() ==
   5669          map->GetInObjectProperties());
   5670   ElementsKind obj_kind = object->map()->elements_kind();
   5671   ElementsKind map_kind = map->elements_kind();
   5672   if (map_kind != obj_kind) {
   5673     ElementsKind to_kind = GetMoreGeneralElementsKind(map_kind, obj_kind);
   5674     if (IsDictionaryElementsKind(obj_kind)) {
   5675       to_kind = obj_kind;
   5676     }
   5677     if (IsDictionaryElementsKind(to_kind)) {
   5678       NormalizeElements(object);
   5679     } else {
   5680       TransitionElementsKind(object, to_kind);
   5681     }
   5682     map = Map::ReconfigureElementsKind(map, to_kind);
   5683   }
   5684   JSObject::MigrateToMap(object, map);
   5685 }
   5686 
   5687 
   5688 void JSObject::MigrateInstance(Handle<JSObject> object) {
   5689   Handle<Map> original_map(object->map());
   5690   Handle<Map> map = Map::Update(original_map);
   5691   map->set_migration_target(true);
   5692   MigrateToMap(object, map);
   5693   if (FLAG_trace_migration) {
   5694     object->PrintInstanceMigration(stdout, *original_map, *map);
   5695   }
   5696 #if VERIFY_HEAP
   5697   if (FLAG_verify_heap) {
   5698     object->JSObjectVerify();
   5699   }
   5700 #endif
   5701 }
   5702 
   5703 
   5704 // static
   5705 bool JSObject::TryMigrateInstance(Handle<JSObject> object) {
   5706   Isolate* isolate = object->GetIsolate();
   5707   DisallowDeoptimization no_deoptimization(isolate);
   5708   Handle<Map> original_map(object->map(), isolate);
   5709   Handle<Map> new_map;
   5710   if (!Map::TryUpdate(original_map).ToHandle(&new_map)) {
   5711     return false;
   5712   }
   5713   JSObject::MigrateToMap(object, new_map);
   5714   if (FLAG_trace_migration) {
   5715     object->PrintInstanceMigration(stdout, *original_map, object->map());
   5716   }
   5717 #if VERIFY_HEAP
   5718   if (FLAG_verify_heap) {
   5719     object->JSObjectVerify();
   5720   }
   5721 #endif
   5722   return true;
   5723 }
   5724 
   5725 
   5726 void JSObject::AddProperty(Handle<JSObject> object, Handle<Name> name,
   5727                            Handle<Object> value,
   5728                            PropertyAttributes attributes) {
   5729   LookupIterator it(object, name, object, LookupIterator::OWN_SKIP_INTERCEPTOR);
   5730   CHECK_NE(LookupIterator::ACCESS_CHECK, it.state());
   5731 #ifdef DEBUG
   5732   uint32_t index;
   5733   DCHECK(!object->IsJSProxy());
   5734   DCHECK(!name->AsArrayIndex(&index));
   5735   Maybe<PropertyAttributes> maybe = GetPropertyAttributes(&it);
   5736   DCHECK(maybe.IsJust());
   5737   DCHECK(!it.IsFound());
   5738   DCHECK(object->map()->is_extensible() || name->IsPrivate());
   5739 #endif
   5740   CHECK(AddDataProperty(&it, value, attributes, THROW_ON_ERROR,
   5741                         CERTAINLY_NOT_STORE_FROM_KEYED)
   5742             .IsJust());
   5743 }
   5744 
   5745 
   5746 // Reconfigures a property to a data property with attributes, even if it is not
   5747 // reconfigurable.
   5748 // Requires a LookupIterator that does not look at the prototype chain beyond
   5749 // hidden prototypes.
   5750 MaybeHandle<Object> JSObject::DefineOwnPropertyIgnoreAttributes(
   5751     LookupIterator* it, Handle<Object> value, PropertyAttributes attributes,
   5752     AccessorInfoHandling handling) {
   5753   MAYBE_RETURN_NULL(DefineOwnPropertyIgnoreAttributes(
   5754       it, value, attributes, THROW_ON_ERROR, handling));
   5755   return value;
   5756 }
   5757 
   5758 
   5759 Maybe<bool> JSObject::DefineOwnPropertyIgnoreAttributes(
   5760     LookupIterator* it, Handle<Object> value, PropertyAttributes attributes,
   5761     ShouldThrow should_throw, AccessorInfoHandling handling) {
   5762   it->UpdateProtector();
   5763   Handle<JSObject> object = Handle<JSObject>::cast(it->GetReceiver());
   5764 
   5765   for (; it->IsFound(); it->Next()) {
   5766     switch (it->state()) {
   5767       case LookupIterator::JSPROXY:
   5768       case LookupIterator::NOT_FOUND:
   5769       case LookupIterator::TRANSITION:
   5770         UNREACHABLE();
   5771 
   5772       case LookupIterator::ACCESS_CHECK:
   5773         if (!it->HasAccess()) {
   5774           it->isolate()->ReportFailedAccessCheck(it->GetHolder<JSObject>());
   5775           RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(), Nothing<bool>());
   5776           return Just(true);
   5777         }
   5778         break;
   5779 
   5780       // If there's an interceptor, try to store the property with the
   5781       // interceptor.
   5782       // In case of success, the attributes will have been reset to the default
   5783       // attributes of the interceptor, rather than the incoming attributes.
   5784       //
   5785       // TODO(verwaest): JSProxy afterwards verify the attributes that the
   5786       // JSProxy claims it has, and verifies that they are compatible. If not,
   5787       // they throw. Here we should do the same.
   5788       case LookupIterator::INTERCEPTOR:
   5789         if (handling == DONT_FORCE_FIELD) {
   5790           Maybe<bool> result =
   5791               JSObject::SetPropertyWithInterceptor(it, should_throw, value);
   5792           if (result.IsNothing() || result.FromJust()) return result;
   5793         }
   5794         break;
   5795 
   5796       case LookupIterator::ACCESSOR: {
   5797         Handle<Object> accessors = it->GetAccessors();
   5798 
   5799         // Special handling for AccessorInfo, which behaves like a data
   5800         // property.
   5801         if (accessors->IsAccessorInfo() && handling == DONT_FORCE_FIELD) {
   5802           PropertyAttributes current_attributes = it->property_attributes();
   5803           // Ensure the context isn't changed after calling into accessors.
   5804           AssertNoContextChange ncc(it->isolate());
   5805 
   5806           // Update the attributes before calling the setter. The setter may
   5807           // later change the shape of the property.
   5808           if (current_attributes != attributes) {
   5809             it->TransitionToAccessorPair(accessors, attributes);
   5810           }
   5811 
   5812           return JSObject::SetPropertyWithAccessor(it, value, should_throw);
   5813         }
   5814 
   5815         it->ReconfigureDataProperty(value, attributes);
   5816         return Just(true);
   5817       }
   5818       case LookupIterator::INTEGER_INDEXED_EXOTIC:
   5819         return RedefineIncompatibleProperty(it->isolate(), it->GetName(), value,
   5820                                             should_throw);
   5821 
   5822       case LookupIterator::DATA: {
   5823         // Regular property update if the attributes match.
   5824         if (it->property_attributes() == attributes) {
   5825           return SetDataProperty(it, value);
   5826         }
   5827 
   5828         // Special case: properties of typed arrays cannot be reconfigured to
   5829         // non-writable nor to non-enumerable.
   5830         if (it->IsElement() && object->HasFixedTypedArrayElements()) {
   5831           return RedefineIncompatibleProperty(it->isolate(), it->GetName(),
   5832                                               value, should_throw);
   5833         }
   5834 
   5835         // Reconfigure the data property if the attributes mismatch.
   5836         it->ReconfigureDataProperty(value, attributes);
   5837 
   5838         return Just(true);
   5839       }
   5840     }
   5841   }
   5842 
   5843   return AddDataProperty(it, value, attributes, should_throw,
   5844                          CERTAINLY_NOT_STORE_FROM_KEYED);
   5845 }
   5846 
   5847 MaybeHandle<Object> JSObject::SetOwnPropertyIgnoreAttributes(
   5848     Handle<JSObject> object, Handle<Name> name, Handle<Object> value,
   5849     PropertyAttributes attributes) {
   5850   DCHECK(!value->IsTheHole(object->GetIsolate()));
   5851   LookupIterator it(object, name, object, LookupIterator::OWN);
   5852   return DefineOwnPropertyIgnoreAttributes(&it, value, attributes);
   5853 }
   5854 
   5855 MaybeHandle<Object> JSObject::SetOwnElementIgnoreAttributes(
   5856     Handle<JSObject> object, uint32_t index, Handle<Object> value,
   5857     PropertyAttributes attributes) {
   5858   Isolate* isolate = object->GetIsolate();
   5859   LookupIterator it(isolate, object, index, object, LookupIterator::OWN);
   5860   return DefineOwnPropertyIgnoreAttributes(&it, value, attributes);
   5861 }
   5862 
   5863 MaybeHandle<Object> JSObject::DefinePropertyOrElementIgnoreAttributes(
   5864     Handle<JSObject> object, Handle<Name> name, Handle<Object> value,
   5865     PropertyAttributes attributes) {
   5866   Isolate* isolate = object->GetIsolate();
   5867   LookupIterator it = LookupIterator::PropertyOrElement(
   5868       isolate, object, name, object, LookupIterator::OWN);
   5869   return DefineOwnPropertyIgnoreAttributes(&it, value, attributes);
   5870 }
   5871 
   5872 Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithInterceptor(
   5873     LookupIterator* it) {
   5874   return GetPropertyAttributesWithInterceptorInternal(it, it->GetInterceptor());
   5875 }
   5876 
   5877 Maybe<PropertyAttributes> JSReceiver::GetPropertyAttributes(
   5878     LookupIterator* it) {
   5879   for (; it->IsFound(); it->Next()) {
   5880     switch (it->state()) {
   5881       case LookupIterator::NOT_FOUND:
   5882       case LookupIterator::TRANSITION:
   5883         UNREACHABLE();
   5884       case LookupIterator::JSPROXY:
   5885         return JSProxy::GetPropertyAttributes(it);
   5886       case LookupIterator::INTERCEPTOR: {
   5887         Maybe<PropertyAttributes> result =
   5888             JSObject::GetPropertyAttributesWithInterceptor(it);
   5889         if (!result.IsJust()) return result;
   5890         if (result.FromJust() != ABSENT) return result;
   5891         break;
   5892       }
   5893       case LookupIterator::ACCESS_CHECK:
   5894         if (it->HasAccess()) break;
   5895         return JSObject::GetPropertyAttributesWithFailedAccessCheck(it);
   5896       case LookupIterator::INTEGER_INDEXED_EXOTIC:
   5897         return Just(ABSENT);
   5898       case LookupIterator::ACCESSOR:
   5899       case LookupIterator::DATA:
   5900         return Just(it->property_attributes());
   5901     }
   5902   }
   5903   return Just(ABSENT);
   5904 }
   5905 
   5906 
   5907 Handle<NormalizedMapCache> NormalizedMapCache::New(Isolate* isolate) {
   5908   Handle<FixedArray> array(
   5909       isolate->factory()->NewFixedArray(kEntries, TENURED));
   5910   return Handle<NormalizedMapCache>::cast(array);
   5911 }
   5912 
   5913 
   5914 MaybeHandle<Map> NormalizedMapCache::Get(Handle<Map> fast_map,
   5915                                          PropertyNormalizationMode mode) {
   5916   DisallowHeapAllocation no_gc;
   5917   Object* value = FixedArray::get(GetIndex(fast_map));
   5918   if (!value->IsMap() ||
   5919       !Map::cast(value)->EquivalentToForNormalization(*fast_map, mode)) {
   5920     return MaybeHandle<Map>();
   5921   }
   5922   return handle(Map::cast(value));
   5923 }
   5924 
   5925 
   5926 void NormalizedMapCache::Set(Handle<Map> fast_map,
   5927                              Handle<Map> normalized_map) {
   5928   DisallowHeapAllocation no_gc;
   5929   DCHECK(normalized_map->is_dictionary_map());
   5930   FixedArray::set(GetIndex(fast_map), *normalized_map);
   5931 }
   5932 
   5933 
   5934 void NormalizedMapCache::Clear() {
   5935   int entries = length();
   5936   for (int i = 0; i != entries; i++) {
   5937     set_undefined(i);
   5938   }
   5939 }
   5940 
   5941 
   5942 void HeapObject::UpdateMapCodeCache(Handle<HeapObject> object,
   5943                                     Handle<Name> name,
   5944                                     Handle<Code> code) {
   5945   Handle<Map> map(object->map());
   5946   Map::UpdateCodeCache(map, name, code);
   5947 }
   5948 
   5949 
   5950 void JSObject::NormalizeProperties(Handle<JSObject> object,
   5951                                    PropertyNormalizationMode mode,
   5952                                    int expected_additional_properties,
   5953                                    const char* reason) {
   5954   if (!object->HasFastProperties()) return;
   5955 
   5956   Handle<Map> map(object->map());
   5957   Handle<Map> new_map = Map::Normalize(map, mode, reason);
   5958 
   5959   MigrateToMap(object, new_map, expected_additional_properties);
   5960 }
   5961 
   5962 
   5963 void JSObject::MigrateSlowToFast(Handle<JSObject> object,
   5964                                  int unused_property_fields,
   5965                                  const char* reason) {
   5966   if (object->HasFastProperties()) return;
   5967   DCHECK(!object->IsJSGlobalObject());
   5968   Isolate* isolate = object->GetIsolate();
   5969   Factory* factory = isolate->factory();
   5970   Handle<NameDictionary> dictionary(object->property_dictionary());
   5971 
   5972   // Make sure we preserve dictionary representation if there are too many
   5973   // descriptors.
   5974   int number_of_elements = dictionary->NumberOfElements();
   5975   if (number_of_elements > kMaxNumberOfDescriptors) return;
   5976 
   5977   Handle<FixedArray> iteration_order;
   5978   if (number_of_elements != dictionary->NextEnumerationIndex()) {
   5979     iteration_order =
   5980         NameDictionary::DoGenerateNewEnumerationIndices(dictionary);
   5981   } else {
   5982     iteration_order = NameDictionary::BuildIterationIndicesArray(dictionary);
   5983   }
   5984 
   5985   int instance_descriptor_length = iteration_order->length();
   5986   int number_of_fields = 0;
   5987 
   5988   // Compute the length of the instance descriptor.
   5989   for (int i = 0; i < instance_descriptor_length; i++) {
   5990     int index = Smi::cast(iteration_order->get(i))->value();
   5991     DCHECK(dictionary->IsKey(isolate, dictionary->KeyAt(index)));
   5992 
   5993     Object* value = dictionary->ValueAt(index);
   5994     PropertyType type = dictionary->DetailsAt(index).type();
   5995     if (type == DATA && !value->IsJSFunction()) {
   5996       number_of_fields += 1;
   5997     }
   5998   }
   5999 
   6000   Handle<Map> old_map(object->map(), isolate);
   6001 
   6002   int inobject_props = old_map->GetInObjectProperties();
   6003 
   6004   // Allocate new map.
   6005   Handle<Map> new_map = Map::CopyDropDescriptors(old_map);
   6006   new_map->set_dictionary_map(false);
   6007 
   6008   NotifyMapChange(old_map, new_map, isolate);
   6009 
   6010 #if TRACE_MAPS
   6011   if (FLAG_trace_maps) {
   6012     PrintF("[TraceMaps: SlowToFast from= %p to= %p reason= %s ]\n",
   6013            reinterpret_cast<void*>(*old_map), reinterpret_cast<void*>(*new_map),
   6014            reason);
   6015   }
   6016 #endif
   6017 
   6018   if (instance_descriptor_length == 0) {
   6019     DisallowHeapAllocation no_gc;
   6020     DCHECK_LE(unused_property_fields, inobject_props);
   6021     // Transform the object.
   6022     new_map->set_unused_property_fields(inobject_props);
   6023     object->synchronized_set_map(*new_map);
   6024     object->set_properties(isolate->heap()->empty_fixed_array());
   6025     // Check that it really works.
   6026     DCHECK(object->HasFastProperties());
   6027     return;
   6028   }
   6029 
   6030   // Allocate the instance descriptor.
   6031   Handle<DescriptorArray> descriptors = DescriptorArray::Allocate(
   6032       isolate, instance_descriptor_length, 0, TENURED);
   6033 
   6034   int number_of_allocated_fields =
   6035       number_of_fields + unused_property_fields - inobject_props;
   6036   if (number_of_allocated_fields < 0) {
   6037     // There is enough inobject space for all fields (including unused).
   6038     number_of_allocated_fields = 0;
   6039     unused_property_fields = inobject_props - number_of_fields;
   6040   }
   6041 
   6042   // Allocate the fixed array for the fields.
   6043   Handle<FixedArray> fields = factory->NewFixedArray(
   6044       number_of_allocated_fields);
   6045 
   6046   // Fill in the instance descriptor and the fields.
   6047   int current_offset = 0;
   6048   for (int i = 0; i < instance_descriptor_length; i++) {
   6049     int index = Smi::cast(iteration_order->get(i))->value();
   6050     Object* k = dictionary->KeyAt(index);
   6051     DCHECK(dictionary->IsKey(k));
   6052     // Dictionary keys are internalized upon insertion.
   6053     // TODO(jkummerow): Turn this into a DCHECK if it's not hit in the wild.
   6054     CHECK(k->IsUniqueName());
   6055     Handle<Name> key(Name::cast(k), isolate);
   6056 
   6057     Object* value = dictionary->ValueAt(index);
   6058 
   6059     PropertyDetails details = dictionary->DetailsAt(index);
   6060     int enumeration_index = details.dictionary_index();
   6061     PropertyType type = details.type();
   6062 
   6063     if (value->IsJSFunction()) {
   6064       DataConstantDescriptor d(key, handle(value, isolate),
   6065                                details.attributes());
   6066       descriptors->Set(enumeration_index - 1, &d);
   6067     } else if (type == DATA) {
   6068       if (current_offset < inobject_props) {
   6069         object->InObjectPropertyAtPut(current_offset, value,
   6070                                       UPDATE_WRITE_BARRIER);
   6071       } else {
   6072         int offset = current_offset - inobject_props;
   6073         fields->set(offset, value);
   6074       }
   6075       DataDescriptor d(key, current_offset, details.attributes(),
   6076                        // TODO(verwaest): value->OptimalRepresentation();
   6077                        Representation::Tagged());
   6078       current_offset += d.GetDetails().field_width_in_words();
   6079       descriptors->Set(enumeration_index - 1, &d);
   6080     } else if (type == ACCESSOR_CONSTANT) {
   6081       AccessorConstantDescriptor d(key, handle(value, isolate),
   6082                                    details.attributes());
   6083       descriptors->Set(enumeration_index - 1, &d);
   6084     } else {
   6085       UNREACHABLE();
   6086     }
   6087   }
   6088   DCHECK(current_offset == number_of_fields);
   6089 
   6090   descriptors->Sort();
   6091 
   6092   Handle<LayoutDescriptor> layout_descriptor = LayoutDescriptor::New(
   6093       new_map, descriptors, descriptors->number_of_descriptors());
   6094 
   6095   DisallowHeapAllocation no_gc;
   6096   new_map->InitializeDescriptors(*descriptors, *layout_descriptor);
   6097   new_map->set_unused_property_fields(unused_property_fields);
   6098 
   6099   // Transform the object.
   6100   object->synchronized_set_map(*new_map);
   6101 
   6102   object->set_properties(*fields);
   6103   DCHECK(object->IsJSObject());
   6104 
   6105   // Check that it really works.
   6106   DCHECK(object->HasFastProperties());
   6107 }
   6108 
   6109 
   6110 void JSObject::ResetElements(Handle<JSObject> object) {
   6111   Isolate* isolate = object->GetIsolate();
   6112   CHECK(object->map() != isolate->heap()->sloppy_arguments_elements_map());
   6113   if (object->map()->has_dictionary_elements()) {
   6114     Handle<SeededNumberDictionary> new_elements =
   6115         SeededNumberDictionary::New(isolate, 0);
   6116     object->set_elements(*new_elements);
   6117   } else {
   6118     object->set_elements(object->map()->GetInitialElements());
   6119   }
   6120 }
   6121 
   6122 
   6123 void JSObject::RequireSlowElements(SeededNumberDictionary* dictionary) {
   6124   if (dictionary->requires_slow_elements()) return;
   6125   dictionary->set_requires_slow_elements();
   6126   // TODO(verwaest): Remove this hack.
   6127   if (map()->is_prototype_map()) {
   6128     TypeFeedbackVector::ClearAllKeyedStoreICs(GetIsolate());
   6129   }
   6130 }
   6131 
   6132 
   6133 Handle<SeededNumberDictionary> JSObject::NormalizeElements(
   6134     Handle<JSObject> object) {
   6135   DCHECK(!object->HasFixedTypedArrayElements());
   6136   Isolate* isolate = object->GetIsolate();
   6137   bool is_arguments = object->HasSloppyArgumentsElements();
   6138   {
   6139     DisallowHeapAllocation no_gc;
   6140     FixedArrayBase* elements = object->elements();
   6141 
   6142     if (is_arguments) {
   6143       FixedArray* parameter_map = FixedArray::cast(elements);
   6144       elements = FixedArrayBase::cast(parameter_map->get(1));
   6145     }
   6146 
   6147     if (elements->IsDictionary()) {
   6148       return handle(SeededNumberDictionary::cast(elements), isolate);
   6149     }
   6150   }
   6151 
   6152   DCHECK(object->HasFastSmiOrObjectElements() ||
   6153          object->HasFastDoubleElements() ||
   6154          object->HasFastArgumentsElements() ||
   6155          object->HasFastStringWrapperElements());
   6156 
   6157   Handle<SeededNumberDictionary> dictionary =
   6158       object->GetElementsAccessor()->Normalize(object);
   6159 
   6160   // Switch to using the dictionary as the backing storage for elements.
   6161   ElementsKind target_kind = is_arguments
   6162                                  ? SLOW_SLOPPY_ARGUMENTS_ELEMENTS
   6163                                  : object->HasFastStringWrapperElements()
   6164                                        ? SLOW_STRING_WRAPPER_ELEMENTS
   6165                                        : DICTIONARY_ELEMENTS;
   6166   Handle<Map> new_map = JSObject::GetElementsTransitionMap(object, target_kind);
   6167   // Set the new map first to satify the elements type assert in set_elements().
   6168   JSObject::MigrateToMap(object, new_map);
   6169 
   6170   if (is_arguments) {
   6171     FixedArray::cast(object->elements())->set(1, *dictionary);
   6172   } else {
   6173     object->set_elements(*dictionary);
   6174   }
   6175 
   6176   isolate->counters()->elements_to_dictionary()->Increment();
   6177 
   6178 #ifdef DEBUG
   6179   if (FLAG_trace_normalization) {
   6180     OFStream os(stdout);
   6181     os << "Object elements have been normalized:\n";
   6182     object->Print(os);
   6183   }
   6184 #endif
   6185 
   6186   DCHECK(object->HasDictionaryElements() ||
   6187          object->HasSlowArgumentsElements() ||
   6188          object->HasSlowStringWrapperElements());
   6189   return dictionary;
   6190 }
   6191 
   6192 
   6193 template <typename ProxyType>
   6194 static Smi* GetOrCreateIdentityHashHelper(Isolate* isolate,
   6195                                           Handle<ProxyType> proxy) {
   6196   Object* maybe_hash = proxy->hash();
   6197   if (maybe_hash->IsSmi()) return Smi::cast(maybe_hash);
   6198 
   6199   Smi* hash = Smi::FromInt(isolate->GenerateIdentityHash(Smi::kMaxValue));
   6200   proxy->set_hash(hash);
   6201   return hash;
   6202 }
   6203 
   6204 // static
   6205 Object* JSObject::GetIdentityHash(Isolate* isolate, Handle<JSObject> object) {
   6206   if (object->IsJSGlobalProxy()) {
   6207     return JSGlobalProxy::cast(*object)->hash();
   6208   }
   6209   Handle<Name> hash_code_symbol = isolate->factory()->hash_code_symbol();
   6210   return *JSReceiver::GetDataProperty(object, hash_code_symbol);
   6211 }
   6212 
   6213 // static
   6214 Smi* JSObject::GetOrCreateIdentityHash(Isolate* isolate,
   6215                                        Handle<JSObject> object) {
   6216   if (object->IsJSGlobalProxy()) {
   6217     return GetOrCreateIdentityHashHelper(isolate,
   6218                                          Handle<JSGlobalProxy>::cast(object));
   6219   }
   6220 
   6221   Handle<Name> hash_code_symbol = isolate->factory()->hash_code_symbol();
   6222   LookupIterator it(object, hash_code_symbol, object, LookupIterator::OWN);
   6223   if (it.IsFound()) {
   6224     DCHECK_EQ(LookupIterator::DATA, it.state());
   6225     Object* maybe_hash = *it.GetDataValue();
   6226     if (maybe_hash->IsSmi()) return Smi::cast(maybe_hash);
   6227   }
   6228 
   6229   Smi* hash = Smi::FromInt(isolate->GenerateIdentityHash(Smi::kMaxValue));
   6230   CHECK(AddDataProperty(&it, handle(hash, isolate), NONE, THROW_ON_ERROR,
   6231                         CERTAINLY_NOT_STORE_FROM_KEYED)
   6232             .IsJust());
   6233   return hash;
   6234 }
   6235 
   6236 // static
   6237 Object* JSProxy::GetIdentityHash(Handle<JSProxy> proxy) {
   6238   return proxy->hash();
   6239 }
   6240 
   6241 Smi* JSProxy::GetOrCreateIdentityHash(Isolate* isolate, Handle<JSProxy> proxy) {
   6242   return GetOrCreateIdentityHashHelper(isolate, proxy);
   6243 }
   6244 
   6245 
   6246 Maybe<bool> JSObject::DeletePropertyWithInterceptor(LookupIterator* it,
   6247                                                     ShouldThrow should_throw) {
   6248   Isolate* isolate = it->isolate();
   6249   // Make sure that the top context does not change when doing callbacks or
   6250   // interceptor calls.
   6251   AssertNoContextChange ncc(isolate);
   6252 
   6253   DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
   6254   Handle<InterceptorInfo> interceptor(it->GetInterceptor());
   6255   if (interceptor->deleter()->IsUndefined(isolate)) return Nothing<bool>();
   6256 
   6257   Handle<JSObject> holder = it->GetHolder<JSObject>();
   6258   Handle<Object> receiver = it->GetReceiver();
   6259   if (!receiver->IsJSReceiver()) {
   6260     ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, receiver,
   6261                                      Object::ConvertReceiver(isolate, receiver),
   6262                                      Nothing<bool>());
   6263   }
   6264 
   6265   PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
   6266                                  *holder, should_throw);
   6267   Handle<Object> result;
   6268   if (it->IsElement()) {
   6269     uint32_t index = it->index();
   6270     v8::IndexedPropertyDeleterCallback deleter =
   6271         v8::ToCData<v8::IndexedPropertyDeleterCallback>(interceptor->deleter());
   6272     result = args.Call(deleter, index);
   6273   } else if (it->name()->IsSymbol() && !interceptor->can_intercept_symbols()) {
   6274     return Nothing<bool>();
   6275   } else {
   6276     Handle<Name> name = it->name();
   6277     DCHECK(!name->IsPrivate());
   6278     v8::GenericNamedPropertyDeleterCallback deleter =
   6279         v8::ToCData<v8::GenericNamedPropertyDeleterCallback>(
   6280             interceptor->deleter());
   6281     result = args.Call(deleter, name);
   6282   }
   6283 
   6284   RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
   6285   if (result.is_null()) return Nothing<bool>();
   6286 
   6287   DCHECK(result->IsBoolean());
   6288   // Rebox CustomArguments::kReturnValueOffset before returning.
   6289   return Just(result->IsTrue(isolate));
   6290 }
   6291 
   6292 
   6293 void JSReceiver::DeleteNormalizedProperty(Handle<JSReceiver> object,
   6294                                           Handle<Name> name, int entry) {
   6295   DCHECK(!object->HasFastProperties());
   6296   Isolate* isolate = object->GetIsolate();
   6297 
   6298   if (object->IsJSGlobalObject()) {
   6299     // If we have a global object, invalidate the cell and swap in a new one.
   6300     Handle<GlobalDictionary> dictionary(
   6301         JSObject::cast(*object)->global_dictionary());
   6302     DCHECK_NE(GlobalDictionary::kNotFound, entry);
   6303 
   6304     auto cell = PropertyCell::InvalidateEntry(dictionary, entry);
   6305     cell->set_value(isolate->heap()->the_hole_value());
   6306     cell->set_property_details(
   6307         PropertyDetails::Empty(PropertyCellType::kUninitialized));
   6308   } else {
   6309     Handle<NameDictionary> dictionary(object->property_dictionary());
   6310     DCHECK_NE(NameDictionary::kNotFound, entry);
   6311 
   6312     NameDictionary::DeleteProperty(dictionary, entry);
   6313     Handle<NameDictionary> new_properties =
   6314         NameDictionary::Shrink(dictionary, name);
   6315     object->set_properties(*new_properties);
   6316   }
   6317 }
   6318 
   6319 
   6320 Maybe<bool> JSReceiver::DeleteProperty(LookupIterator* it,
   6321                                        LanguageMode language_mode) {
   6322   it->UpdateProtector();
   6323 
   6324   Isolate* isolate = it->isolate();
   6325 
   6326   if (it->state() == LookupIterator::JSPROXY) {
   6327     return JSProxy::DeletePropertyOrElement(it->GetHolder<JSProxy>(),
   6328                                             it->GetName(), language_mode);
   6329   }
   6330 
   6331   if (it->GetReceiver()->IsJSProxy()) {
   6332     if (it->state() != LookupIterator::NOT_FOUND) {
   6333       DCHECK_EQ(LookupIterator::DATA, it->state());
   6334       DCHECK(it->name()->IsPrivate());
   6335       it->Delete();
   6336     }
   6337     return Just(true);
   6338   }
   6339   Handle<JSObject> receiver = Handle<JSObject>::cast(it->GetReceiver());
   6340 
   6341   for (; it->IsFound(); it->Next()) {
   6342     switch (it->state()) {
   6343       case LookupIterator::JSPROXY:
   6344       case LookupIterator::NOT_FOUND:
   6345       case LookupIterator::TRANSITION:
   6346         UNREACHABLE();
   6347       case LookupIterator::ACCESS_CHECK:
   6348         if (it->HasAccess()) break;
   6349         isolate->ReportFailedAccessCheck(it->GetHolder<JSObject>());
   6350         RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
   6351         return Just(false);
   6352       case LookupIterator::INTERCEPTOR: {
   6353         ShouldThrow should_throw =
   6354             is_sloppy(language_mode) ? DONT_THROW : THROW_ON_ERROR;
   6355         Maybe<bool> result =
   6356             JSObject::DeletePropertyWithInterceptor(it, should_throw);
   6357         // An exception was thrown in the interceptor. Propagate.
   6358         if (isolate->has_pending_exception()) return Nothing<bool>();
   6359         // Delete with interceptor succeeded. Return result.
   6360         // TODO(neis): In strict mode, we should probably throw if the
   6361         // interceptor returns false.
   6362         if (result.IsJust()) return result;
   6363         break;
   6364       }
   6365       case LookupIterator::INTEGER_INDEXED_EXOTIC:
   6366         return Just(true);
   6367       case LookupIterator::DATA:
   6368       case LookupIterator::ACCESSOR: {
   6369         if (!it->IsConfigurable()) {
   6370           // Fail if the property is not configurable.
   6371           if (is_strict(language_mode)) {
   6372             isolate->Throw(*isolate->factory()->NewTypeError(
   6373                 MessageTemplate::kStrictDeleteProperty, it->GetName(),
   6374                 receiver));
   6375             return Nothing<bool>();
   6376           }
   6377           return Just(false);
   6378         }
   6379 
   6380         it->Delete();
   6381 
   6382         return Just(true);
   6383       }
   6384     }
   6385   }
   6386 
   6387   return Just(true);
   6388 }
   6389 
   6390 
   6391 Maybe<bool> JSReceiver::DeleteElement(Handle<JSReceiver> object, uint32_t index,
   6392                                       LanguageMode language_mode) {
   6393   LookupIterator it(object->GetIsolate(), object, index, object,
   6394                     LookupIterator::OWN);
   6395   return DeleteProperty(&it, language_mode);
   6396 }
   6397 
   6398 
   6399 Maybe<bool> JSReceiver::DeleteProperty(Handle<JSReceiver> object,
   6400                                        Handle<Name> name,
   6401                                        LanguageMode language_mode) {
   6402   LookupIterator it(object, name, object, LookupIterator::OWN);
   6403   return DeleteProperty(&it, language_mode);
   6404 }
   6405 
   6406 
   6407 Maybe<bool> JSReceiver::DeletePropertyOrElement(Handle<JSReceiver> object,
   6408                                                 Handle<Name> name,
   6409                                                 LanguageMode language_mode) {
   6410   LookupIterator it = LookupIterator::PropertyOrElement(
   6411       name->GetIsolate(), object, name, object, LookupIterator::OWN);
   6412   return DeleteProperty(&it, language_mode);
   6413 }
   6414 
   6415 
   6416 // ES6 7.1.14
   6417 // static
   6418 MaybeHandle<Object> Object::ToPropertyKey(Isolate* isolate,
   6419                                           Handle<Object> value) {
   6420   // 1. Let key be ToPrimitive(argument, hint String).
   6421   MaybeHandle<Object> maybe_key =
   6422       Object::ToPrimitive(value, ToPrimitiveHint::kString);
   6423   // 2. ReturnIfAbrupt(key).
   6424   Handle<Object> key;
   6425   if (!maybe_key.ToHandle(&key)) return key;
   6426   // 3. If Type(key) is Symbol, then return key.
   6427   if (key->IsSymbol()) return key;
   6428   // 4. Return ToString(key).
   6429   // Extending spec'ed behavior, we'd be happy to return an element index.
   6430   if (key->IsSmi()) return key;
   6431   if (key->IsHeapNumber()) {
   6432     uint32_t uint_value;
   6433     if (value->ToArrayLength(&uint_value) &&
   6434         uint_value <= static_cast<uint32_t>(Smi::kMaxValue)) {
   6435       return handle(Smi::FromInt(static_cast<int>(uint_value)), isolate);
   6436     }
   6437   }
   6438   return Object::ToString(isolate, key);
   6439 }
   6440 
   6441 
   6442 // ES6 19.1.2.4
   6443 // static
   6444 Object* JSReceiver::DefineProperty(Isolate* isolate, Handle<Object> object,
   6445                                    Handle<Object> key,
   6446                                    Handle<Object> attributes) {
   6447   // 1. If Type(O) is not Object, throw a TypeError exception.
   6448   if (!object->IsJSReceiver()) {
   6449     Handle<String> fun_name =
   6450         isolate->factory()->InternalizeUtf8String("Object.defineProperty");
   6451     THROW_NEW_ERROR_RETURN_FAILURE(
   6452         isolate, NewTypeError(MessageTemplate::kCalledOnNonObject, fun_name));
   6453   }
   6454   // 2. Let key be ToPropertyKey(P).
   6455   // 3. ReturnIfAbrupt(key).
   6456   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, key, ToPropertyKey(isolate, key));
   6457   // 4. Let desc be ToPropertyDescriptor(Attributes).
   6458   // 5. ReturnIfAbrupt(desc).
   6459   PropertyDescriptor desc;
   6460   if (!PropertyDescriptor::ToPropertyDescriptor(isolate, attributes, &desc)) {
   6461     return isolate->heap()->exception();
   6462   }
   6463   // 6. Let success be DefinePropertyOrThrow(O,key, desc).
   6464   Maybe<bool> success = DefineOwnProperty(
   6465       isolate, Handle<JSReceiver>::cast(object), key, &desc, THROW_ON_ERROR);
   6466   // 7. ReturnIfAbrupt(success).
   6467   MAYBE_RETURN(success, isolate->heap()->exception());
   6468   CHECK(success.FromJust());
   6469   // 8. Return O.
   6470   return *object;
   6471 }
   6472 
   6473 
   6474 // ES6 19.1.2.3.1
   6475 // static
   6476 MaybeHandle<Object> JSReceiver::DefineProperties(Isolate* isolate,
   6477                                                  Handle<Object> object,
   6478                                                  Handle<Object> properties) {
   6479   // 1. If Type(O) is not Object, throw a TypeError exception.
   6480   if (!object->IsJSReceiver()) {
   6481     Handle<String> fun_name =
   6482         isolate->factory()->InternalizeUtf8String("Object.defineProperties");
   6483     THROW_NEW_ERROR(isolate,
   6484                     NewTypeError(MessageTemplate::kCalledOnNonObject, fun_name),
   6485                     Object);
   6486   }
   6487   // 2. Let props be ToObject(Properties).
   6488   // 3. ReturnIfAbrupt(props).
   6489   Handle<JSReceiver> props;
   6490   ASSIGN_RETURN_ON_EXCEPTION(isolate, props,
   6491                              Object::ToObject(isolate, properties), Object);
   6492 
   6493   // 4. Let keys be props.[[OwnPropertyKeys]]().
   6494   // 5. ReturnIfAbrupt(keys).
   6495   Handle<FixedArray> keys;
   6496   ASSIGN_RETURN_ON_EXCEPTION(
   6497       isolate, keys, KeyAccumulator::GetKeys(props, KeyCollectionMode::kOwnOnly,
   6498                                              ALL_PROPERTIES),
   6499       Object);
   6500   // 6. Let descriptors be an empty List.
   6501   int capacity = keys->length();
   6502   std::vector<PropertyDescriptor> descriptors(capacity);
   6503   size_t descriptors_index = 0;
   6504   // 7. Repeat for each element nextKey of keys in List order,
   6505   for (int i = 0; i < keys->length(); ++i) {
   6506     Handle<Object> next_key(keys->get(i), isolate);
   6507     // 7a. Let propDesc be props.[[GetOwnProperty]](nextKey).
   6508     // 7b. ReturnIfAbrupt(propDesc).
   6509     bool success = false;
   6510     LookupIterator it = LookupIterator::PropertyOrElement(
   6511         isolate, props, next_key, &success, LookupIterator::OWN);
   6512     DCHECK(success);
   6513     Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
   6514     if (!maybe.IsJust()) return MaybeHandle<Object>();
   6515     PropertyAttributes attrs = maybe.FromJust();
   6516     // 7c. If propDesc is not undefined and propDesc.[[Enumerable]] is true:
   6517     if (attrs == ABSENT) continue;
   6518     if (attrs & DONT_ENUM) continue;
   6519     // 7c i. Let descObj be Get(props, nextKey).
   6520     // 7c ii. ReturnIfAbrupt(descObj).
   6521     Handle<Object> desc_obj;
   6522     ASSIGN_RETURN_ON_EXCEPTION(isolate, desc_obj, Object::GetProperty(&it),
   6523                                Object);
   6524     // 7c iii. Let desc be ToPropertyDescriptor(descObj).
   6525     success = PropertyDescriptor::ToPropertyDescriptor(
   6526         isolate, desc_obj, &descriptors[descriptors_index]);
   6527     // 7c iv. ReturnIfAbrupt(desc).
   6528     if (!success) return MaybeHandle<Object>();
   6529     // 7c v. Append the pair (a two element List) consisting of nextKey and
   6530     //       desc to the end of descriptors.
   6531     descriptors[descriptors_index].set_name(next_key);
   6532     descriptors_index++;
   6533   }
   6534   // 8. For each pair from descriptors in list order,
   6535   for (size_t i = 0; i < descriptors_index; ++i) {
   6536     PropertyDescriptor* desc = &descriptors[i];
   6537     // 8a. Let P be the first element of pair.
   6538     // 8b. Let desc be the second element of pair.
   6539     // 8c. Let status be DefinePropertyOrThrow(O, P, desc).
   6540     Maybe<bool> status =
   6541         DefineOwnProperty(isolate, Handle<JSReceiver>::cast(object),
   6542                           desc->name(), desc, THROW_ON_ERROR);
   6543     // 8d. ReturnIfAbrupt(status).
   6544     if (!status.IsJust()) return MaybeHandle<Object>();
   6545     CHECK(status.FromJust());
   6546   }
   6547   // 9. Return o.
   6548   return object;
   6549 }
   6550 
   6551 
   6552 // static
   6553 Maybe<bool> JSReceiver::DefineOwnProperty(Isolate* isolate,
   6554                                           Handle<JSReceiver> object,
   6555                                           Handle<Object> key,
   6556                                           PropertyDescriptor* desc,
   6557                                           ShouldThrow should_throw) {
   6558   if (object->IsJSArray()) {
   6559     return JSArray::DefineOwnProperty(isolate, Handle<JSArray>::cast(object),
   6560                                       key, desc, should_throw);
   6561   }
   6562   if (object->IsJSProxy()) {
   6563     return JSProxy::DefineOwnProperty(isolate, Handle<JSProxy>::cast(object),
   6564                                       key, desc, should_throw);
   6565   }
   6566   // TODO(neis): Special case for JSModuleNamespace?
   6567 
   6568   // OrdinaryDefineOwnProperty, by virtue of calling
   6569   // DefineOwnPropertyIgnoreAttributes, can handle arguments (ES6 9.4.4.2)
   6570   // and IntegerIndexedExotics (ES6 9.4.5.3), with one exception:
   6571   // TODO(jkummerow): Setting an indexed accessor on a typed array should throw.
   6572   return OrdinaryDefineOwnProperty(isolate, Handle<JSObject>::cast(object), key,
   6573                                    desc, should_throw);
   6574 }
   6575 
   6576 
   6577 // static
   6578 Maybe<bool> JSReceiver::OrdinaryDefineOwnProperty(Isolate* isolate,
   6579                                                   Handle<JSObject> object,
   6580                                                   Handle<Object> key,
   6581                                                   PropertyDescriptor* desc,
   6582                                                   ShouldThrow should_throw) {
   6583   bool success = false;
   6584   DCHECK(key->IsName() || key->IsNumber());  // |key| is a PropertyKey...
   6585   LookupIterator it = LookupIterator::PropertyOrElement(
   6586       isolate, object, key, &success, LookupIterator::OWN);
   6587   DCHECK(success);  // ...so creating a LookupIterator can't fail.
   6588 
   6589   // Deal with access checks first.
   6590   if (it.state() == LookupIterator::ACCESS_CHECK) {
   6591     if (!it.HasAccess()) {
   6592       isolate->ReportFailedAccessCheck(it.GetHolder<JSObject>());
   6593       RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
   6594       return Just(true);
   6595     }
   6596     it.Next();
   6597   }
   6598 
   6599   // Handle interceptor
   6600   if (it.state() == LookupIterator::INTERCEPTOR) {
   6601     if (it.HolderIsReceiverOrHiddenPrototype()) {
   6602       Maybe<bool> result = DefinePropertyWithInterceptorInternal(
   6603           &it, it.GetInterceptor(), should_throw, *desc);
   6604       if (result.IsNothing() || result.FromJust()) {
   6605         return result;
   6606       }
   6607     }
   6608   }
   6609 
   6610   return OrdinaryDefineOwnProperty(&it, desc, should_throw);
   6611 }
   6612 
   6613 
   6614 // ES6 9.1.6.1
   6615 // static
   6616 Maybe<bool> JSReceiver::OrdinaryDefineOwnProperty(LookupIterator* it,
   6617                                                   PropertyDescriptor* desc,
   6618                                                   ShouldThrow should_throw) {
   6619   Isolate* isolate = it->isolate();
   6620   // 1. Let current be O.[[GetOwnProperty]](P).
   6621   // 2. ReturnIfAbrupt(current).
   6622   PropertyDescriptor current;
   6623   MAYBE_RETURN(GetOwnPropertyDescriptor(it, &current), Nothing<bool>());
   6624 
   6625   // TODO(jkummerow/verwaest): It would be nice if we didn't have to reset
   6626   // the iterator every time. Currently, the reasons why we need it are:
   6627   // - handle interceptors correctly
   6628   // - handle accessors correctly (which might change the holder's map)
   6629   it->Restart();
   6630   // 3. Let extensible be the value of the [[Extensible]] internal slot of O.
   6631   Handle<JSObject> object = Handle<JSObject>::cast(it->GetReceiver());
   6632   bool extensible = JSObject::IsExtensible(object);
   6633 
   6634   return ValidateAndApplyPropertyDescriptor(isolate, it, extensible, desc,
   6635                                             &current, should_throw);
   6636 }
   6637 
   6638 
   6639 // ES6 9.1.6.2
   6640 // static
   6641 Maybe<bool> JSReceiver::IsCompatiblePropertyDescriptor(
   6642     Isolate* isolate, bool extensible, PropertyDescriptor* desc,
   6643     PropertyDescriptor* current, Handle<Name> property_name,
   6644     ShouldThrow should_throw) {
   6645   // 1. Return ValidateAndApplyPropertyDescriptor(undefined, undefined,
   6646   //    Extensible, Desc, Current).
   6647   return ValidateAndApplyPropertyDescriptor(
   6648       isolate, NULL, extensible, desc, current, should_throw, property_name);
   6649 }
   6650 
   6651 
   6652 // ES6 9.1.6.3
   6653 // static
   6654 Maybe<bool> JSReceiver::ValidateAndApplyPropertyDescriptor(
   6655     Isolate* isolate, LookupIterator* it, bool extensible,
   6656     PropertyDescriptor* desc, PropertyDescriptor* current,
   6657     ShouldThrow should_throw, Handle<Name> property_name) {
   6658   // We either need a LookupIterator, or a property name.
   6659   DCHECK((it == NULL) != property_name.is_null());
   6660   Handle<JSObject> object;
   6661   if (it != NULL) object = Handle<JSObject>::cast(it->GetReceiver());
   6662   bool desc_is_data_descriptor = PropertyDescriptor::IsDataDescriptor(desc);
   6663   bool desc_is_accessor_descriptor =
   6664       PropertyDescriptor::IsAccessorDescriptor(desc);
   6665   bool desc_is_generic_descriptor =
   6666       PropertyDescriptor::IsGenericDescriptor(desc);
   6667   // 1. (Assert)
   6668   // 2. If current is undefined, then
   6669   if (current->is_empty()) {
   6670     // 2a. If extensible is false, return false.
   6671     if (!extensible) {
   6672       RETURN_FAILURE(isolate, should_throw,
   6673                      NewTypeError(MessageTemplate::kDefineDisallowed,
   6674                                   it != NULL ? it->GetName() : property_name));
   6675     }
   6676     // 2c. If IsGenericDescriptor(Desc) or IsDataDescriptor(Desc) is true, then:
   6677     // (This is equivalent to !IsAccessorDescriptor(desc).)
   6678     DCHECK((desc_is_generic_descriptor || desc_is_data_descriptor) ==
   6679            !desc_is_accessor_descriptor);
   6680     if (!desc_is_accessor_descriptor) {
   6681       // 2c i. If O is not undefined, create an own data property named P of
   6682       // object O whose [[Value]], [[Writable]], [[Enumerable]] and
   6683       // [[Configurable]] attribute values are described by Desc. If the value
   6684       // of an attribute field of Desc is absent, the attribute of the newly
   6685       // created property is set to its default value.
   6686       if (it != NULL) {
   6687         if (!desc->has_writable()) desc->set_writable(false);
   6688         if (!desc->has_enumerable()) desc->set_enumerable(false);
   6689         if (!desc->has_configurable()) desc->set_configurable(false);
   6690         Handle<Object> value(
   6691             desc->has_value()
   6692                 ? desc->value()
   6693                 : Handle<Object>::cast(isolate->factory()->undefined_value()));
   6694         MaybeHandle<Object> result =
   6695             JSObject::DefineOwnPropertyIgnoreAttributes(it, value,
   6696                                                         desc->ToAttributes());
   6697         if (result.is_null()) return Nothing<bool>();
   6698       }
   6699     } else {
   6700       // 2d. Else Desc must be an accessor Property Descriptor,
   6701       DCHECK(desc_is_accessor_descriptor);
   6702       // 2d i. If O is not undefined, create an own accessor property named P
   6703       // of object O whose [[Get]], [[Set]], [[Enumerable]] and
   6704       // [[Configurable]] attribute values are described by Desc. If the value
   6705       // of an attribute field of Desc is absent, the attribute of the newly
   6706       // created property is set to its default value.
   6707       if (it != NULL) {
   6708         if (!desc->has_enumerable()) desc->set_enumerable(false);
   6709         if (!desc->has_configurable()) desc->set_configurable(false);
   6710         Handle<Object> getter(
   6711             desc->has_get()
   6712                 ? desc->get()
   6713                 : Handle<Object>::cast(isolate->factory()->null_value()));
   6714         Handle<Object> setter(
   6715             desc->has_set()
   6716                 ? desc->set()
   6717                 : Handle<Object>::cast(isolate->factory()->null_value()));
   6718         MaybeHandle<Object> result =
   6719             JSObject::DefineAccessor(it, getter, setter, desc->ToAttributes());
   6720         if (result.is_null()) return Nothing<bool>();
   6721       }
   6722     }
   6723     // 2e. Return true.
   6724     return Just(true);
   6725   }
   6726   // 3. Return true, if every field in Desc is absent.
   6727   // 4. Return true, if every field in Desc also occurs in current and the
   6728   // value of every field in Desc is the same value as the corresponding field
   6729   // in current when compared using the SameValue algorithm.
   6730   if ((!desc->has_enumerable() ||
   6731        desc->enumerable() == current->enumerable()) &&
   6732       (!desc->has_configurable() ||
   6733        desc->configurable() == current->configurable()) &&
   6734       (!desc->has_value() ||
   6735        (current->has_value() && current->value()->SameValue(*desc->value()))) &&
   6736       (!desc->has_writable() ||
   6737        (current->has_writable() && current->writable() == desc->writable())) &&
   6738       (!desc->has_get() ||
   6739        (current->has_get() && current->get()->SameValue(*desc->get()))) &&
   6740       (!desc->has_set() ||
   6741        (current->has_set() && current->set()->SameValue(*desc->set())))) {
   6742     return Just(true);
   6743   }
   6744   // 5. If the [[Configurable]] field of current is false, then
   6745   if (!current->configurable()) {
   6746     // 5a. Return false, if the [[Configurable]] field of Desc is true.
   6747     if (desc->has_configurable() && desc->configurable()) {
   6748       RETURN_FAILURE(isolate, should_throw,
   6749                      NewTypeError(MessageTemplate::kRedefineDisallowed,
   6750                                   it != NULL ? it->GetName() : property_name));
   6751     }
   6752     // 5b. Return false, if the [[Enumerable]] field of Desc is present and the
   6753     // [[Enumerable]] fields of current and Desc are the Boolean negation of
   6754     // each other.
   6755     if (desc->has_enumerable() && desc->enumerable() != current->enumerable()) {
   6756       RETURN_FAILURE(isolate, should_throw,
   6757                      NewTypeError(MessageTemplate::kRedefineDisallowed,
   6758                                   it != NULL ? it->GetName() : property_name));
   6759     }
   6760   }
   6761 
   6762   bool current_is_data_descriptor =
   6763       PropertyDescriptor::IsDataDescriptor(current);
   6764   // 6. If IsGenericDescriptor(Desc) is true, no further validation is required.
   6765   if (desc_is_generic_descriptor) {
   6766     // Nothing to see here.
   6767 
   6768     // 7. Else if IsDataDescriptor(current) and IsDataDescriptor(Desc) have
   6769     // different results, then:
   6770   } else if (current_is_data_descriptor != desc_is_data_descriptor) {
   6771     // 7a. Return false, if the [[Configurable]] field of current is false.
   6772     if (!current->configurable()) {
   6773       RETURN_FAILURE(isolate, should_throw,
   6774                      NewTypeError(MessageTemplate::kRedefineDisallowed,
   6775                                   it != NULL ? it->GetName() : property_name));
   6776     }
   6777     // 7b. If IsDataDescriptor(current) is true, then:
   6778     if (current_is_data_descriptor) {
   6779       // 7b i. If O is not undefined, convert the property named P of object O
   6780       // from a data property to an accessor property. Preserve the existing
   6781       // values of the converted property's [[Configurable]] and [[Enumerable]]
   6782       // attributes and set the rest of the property's attributes to their
   6783       // default values.
   6784       // --> Folded into step 10.
   6785     } else {
   6786       // 7c i. If O is not undefined, convert the property named P of object O
   6787       // from an accessor property to a data property. Preserve the existing
   6788       // values of the converted propertys [[Configurable]] and [[Enumerable]]
   6789       // attributes and set the rest of the propertys attributes to their
   6790       // default values.
   6791       // --> Folded into step 10.
   6792     }
   6793 
   6794     // 8. Else if IsDataDescriptor(current) and IsDataDescriptor(Desc) are both
   6795     // true, then:
   6796   } else if (current_is_data_descriptor && desc_is_data_descriptor) {
   6797     // 8a. If the [[Configurable]] field of current is false, then:
   6798     if (!current->configurable()) {
   6799       // 8a i. Return false, if the [[Writable]] field of current is false and
   6800       // the [[Writable]] field of Desc is true.
   6801       if (!current->writable() && desc->has_writable() && desc->writable()) {
   6802         RETURN_FAILURE(
   6803             isolate, should_throw,
   6804             NewTypeError(MessageTemplate::kRedefineDisallowed,
   6805                          it != NULL ? it->GetName() : property_name));
   6806       }
   6807       // 8a ii. If the [[Writable]] field of current is false, then:
   6808       if (!current->writable()) {
   6809         // 8a ii 1. Return false, if the [[Value]] field of Desc is present and
   6810         // SameValue(Desc.[[Value]], current.[[Value]]) is false.
   6811         if (desc->has_value() && !desc->value()->SameValue(*current->value())) {
   6812           RETURN_FAILURE(
   6813               isolate, should_throw,
   6814               NewTypeError(MessageTemplate::kRedefineDisallowed,
   6815                            it != NULL ? it->GetName() : property_name));
   6816         }
   6817       }
   6818     }
   6819   } else {
   6820     // 9. Else IsAccessorDescriptor(current) and IsAccessorDescriptor(Desc)
   6821     // are both true,
   6822     DCHECK(PropertyDescriptor::IsAccessorDescriptor(current) &&
   6823            desc_is_accessor_descriptor);
   6824     // 9a. If the [[Configurable]] field of current is false, then:
   6825     if (!current->configurable()) {
   6826       // 9a i. Return false, if the [[Set]] field of Desc is present and
   6827       // SameValue(Desc.[[Set]], current.[[Set]]) is false.
   6828       if (desc->has_set() && !desc->set()->SameValue(*current->set())) {
   6829         RETURN_FAILURE(
   6830             isolate, should_throw,
   6831             NewTypeError(MessageTemplate::kRedefineDisallowed,
   6832                          it != NULL ? it->GetName() : property_name));
   6833       }
   6834       // 9a ii. Return false, if the [[Get]] field of Desc is present and
   6835       // SameValue(Desc.[[Get]], current.[[Get]]) is false.
   6836       if (desc->has_get() && !desc->get()->SameValue(*current->get())) {
   6837         RETURN_FAILURE(
   6838             isolate, should_throw,
   6839             NewTypeError(MessageTemplate::kRedefineDisallowed,
   6840                          it != NULL ? it->GetName() : property_name));
   6841       }
   6842     }
   6843   }
   6844 
   6845   // 10. If O is not undefined, then:
   6846   if (it != NULL) {
   6847     // 10a. For each field of Desc that is present, set the corresponding
   6848     // attribute of the property named P of object O to the value of the field.
   6849     PropertyAttributes attrs = NONE;
   6850 
   6851     if (desc->has_enumerable()) {
   6852       attrs = static_cast<PropertyAttributes>(
   6853           attrs | (desc->enumerable() ? NONE : DONT_ENUM));
   6854     } else {
   6855       attrs = static_cast<PropertyAttributes>(
   6856           attrs | (current->enumerable() ? NONE : DONT_ENUM));
   6857     }
   6858     if (desc->has_configurable()) {
   6859       attrs = static_cast<PropertyAttributes>(
   6860           attrs | (desc->configurable() ? NONE : DONT_DELETE));
   6861     } else {
   6862       attrs = static_cast<PropertyAttributes>(
   6863           attrs | (current->configurable() ? NONE : DONT_DELETE));
   6864     }
   6865     if (desc_is_data_descriptor ||
   6866         (desc_is_generic_descriptor && current_is_data_descriptor)) {
   6867       if (desc->has_writable()) {
   6868         attrs = static_cast<PropertyAttributes>(
   6869             attrs | (desc->writable() ? NONE : READ_ONLY));
   6870       } else {
   6871         attrs = static_cast<PropertyAttributes>(
   6872             attrs | (current->writable() ? NONE : READ_ONLY));
   6873       }
   6874       Handle<Object> value(
   6875           desc->has_value() ? desc->value()
   6876                             : current->has_value()
   6877                                   ? current->value()
   6878                                   : Handle<Object>::cast(
   6879                                         isolate->factory()->undefined_value()));
   6880       MaybeHandle<Object> result =
   6881           JSObject::DefineOwnPropertyIgnoreAttributes(it, value, attrs);
   6882       if (result.is_null()) return Nothing<bool>();
   6883     } else {
   6884       DCHECK(desc_is_accessor_descriptor ||
   6885              (desc_is_generic_descriptor &&
   6886               PropertyDescriptor::IsAccessorDescriptor(current)));
   6887       Handle<Object> getter(
   6888           desc->has_get()
   6889               ? desc->get()
   6890               : current->has_get()
   6891                     ? current->get()
   6892                     : Handle<Object>::cast(isolate->factory()->null_value()));
   6893       Handle<Object> setter(
   6894           desc->has_set()
   6895               ? desc->set()
   6896               : current->has_set()
   6897                     ? current->set()
   6898                     : Handle<Object>::cast(isolate->factory()->null_value()));
   6899       MaybeHandle<Object> result =
   6900           JSObject::DefineAccessor(it, getter, setter, attrs);
   6901       if (result.is_null()) return Nothing<bool>();
   6902     }
   6903   }
   6904 
   6905   // 11. Return true.
   6906   return Just(true);
   6907 }
   6908 
   6909 
   6910 // static
   6911 Maybe<bool> JSReceiver::CreateDataProperty(LookupIterator* it,
   6912                                            Handle<Object> value,
   6913                                            ShouldThrow should_throw) {
   6914   DCHECK(!it->check_prototype_chain());
   6915   Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(it->GetReceiver());
   6916   Isolate* isolate = receiver->GetIsolate();
   6917 
   6918   if (receiver->IsJSObject()) {
   6919     return JSObject::CreateDataProperty(it, value, should_throw);  // Shortcut.
   6920   }
   6921 
   6922   PropertyDescriptor new_desc;
   6923   new_desc.set_value(value);
   6924   new_desc.set_writable(true);
   6925   new_desc.set_enumerable(true);
   6926   new_desc.set_configurable(true);
   6927 
   6928   return JSReceiver::DefineOwnProperty(isolate, receiver, it->GetName(),
   6929                                        &new_desc, should_throw);
   6930 }
   6931 
   6932 Maybe<bool> JSObject::CreateDataProperty(LookupIterator* it,
   6933                                          Handle<Object> value,
   6934                                          ShouldThrow should_throw) {
   6935   DCHECK(it->GetReceiver()->IsJSObject());
   6936   MAYBE_RETURN(JSReceiver::GetPropertyAttributes(it), Nothing<bool>());
   6937   Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(it->GetReceiver());
   6938   Isolate* isolate = receiver->GetIsolate();
   6939 
   6940   if (it->IsFound()) {
   6941     Maybe<PropertyAttributes> attributes = GetPropertyAttributes(it);
   6942     MAYBE_RETURN(attributes, Nothing<bool>());
   6943     if ((attributes.FromJust() & DONT_DELETE) != 0) {
   6944       RETURN_FAILURE(
   6945           isolate, should_throw,
   6946           NewTypeError(MessageTemplate::kRedefineDisallowed, it->GetName()));
   6947     }
   6948   } else {
   6949     if (!JSObject::IsExtensible(Handle<JSObject>::cast(it->GetReceiver()))) {
   6950       RETURN_FAILURE(
   6951           isolate, should_throw,
   6952           NewTypeError(MessageTemplate::kDefineDisallowed, it->GetName()));
   6953     }
   6954   }
   6955 
   6956   RETURN_ON_EXCEPTION_VALUE(it->isolate(),
   6957                             DefineOwnPropertyIgnoreAttributes(it, value, NONE),
   6958                             Nothing<bool>());
   6959 
   6960   return Just(true);
   6961 }
   6962 
   6963 
   6964 // TODO(jkummerow): Consider unification with FastAsArrayLength() in
   6965 // accessors.cc.
   6966 bool PropertyKeyToArrayLength(Handle<Object> value, uint32_t* length) {
   6967   DCHECK(value->IsNumber() || value->IsName());
   6968   if (value->ToArrayLength(length)) return true;
   6969   if (value->IsString()) return String::cast(*value)->AsArrayIndex(length);
   6970   return false;
   6971 }
   6972 
   6973 
   6974 bool PropertyKeyToArrayIndex(Handle<Object> index_obj, uint32_t* output) {
   6975   return PropertyKeyToArrayLength(index_obj, output) && *output != kMaxUInt32;
   6976 }
   6977 
   6978 
   6979 // ES6 9.4.2.1
   6980 // static
   6981 Maybe<bool> JSArray::DefineOwnProperty(Isolate* isolate, Handle<JSArray> o,
   6982                                        Handle<Object> name,
   6983                                        PropertyDescriptor* desc,
   6984                                        ShouldThrow should_throw) {
   6985   // 1. Assert: IsPropertyKey(P) is true. ("P" is |name|.)
   6986   // 2. If P is "length", then:
   6987   // TODO(jkummerow): Check if we need slow string comparison.
   6988   if (*name == isolate->heap()->length_string()) {
   6989     // 2a. Return ArraySetLength(A, Desc).
   6990     return ArraySetLength(isolate, o, desc, should_throw);
   6991   }
   6992   // 3. Else if P is an array index, then:
   6993   uint32_t index = 0;
   6994   if (PropertyKeyToArrayIndex(name, &index)) {
   6995     // 3a. Let oldLenDesc be OrdinaryGetOwnProperty(A, "length").
   6996     PropertyDescriptor old_len_desc;
   6997     Maybe<bool> success = GetOwnPropertyDescriptor(
   6998         isolate, o, isolate->factory()->length_string(), &old_len_desc);
   6999     // 3b. (Assert)
   7000     DCHECK(success.FromJust());
   7001     USE(success);
   7002     // 3c. Let oldLen be oldLenDesc.[[Value]].
   7003     uint32_t old_len = 0;
   7004     CHECK(old_len_desc.value()->ToArrayLength(&old_len));
   7005     // 3d. Let index be ToUint32(P).
   7006     // (Already done above.)
   7007     // 3e. (Assert)
   7008     // 3f. If index >= oldLen and oldLenDesc.[[Writable]] is false,
   7009     //     return false.
   7010     if (index >= old_len && old_len_desc.has_writable() &&
   7011         !old_len_desc.writable()) {
   7012       RETURN_FAILURE(isolate, should_throw,
   7013                      NewTypeError(MessageTemplate::kDefineDisallowed, name));
   7014     }
   7015     // 3g. Let succeeded be OrdinaryDefineOwnProperty(A, P, Desc).
   7016     Maybe<bool> succeeded =
   7017         OrdinaryDefineOwnProperty(isolate, o, name, desc, should_throw);
   7018     // 3h. Assert: succeeded is not an abrupt completion.
   7019     //     In our case, if should_throw == THROW_ON_ERROR, it can be!
   7020     // 3i. If succeeded is false, return false.
   7021     if (succeeded.IsNothing() || !succeeded.FromJust()) return succeeded;
   7022     // 3j. If index >= oldLen, then:
   7023     if (index >= old_len) {
   7024       // 3j i. Set oldLenDesc.[[Value]] to index + 1.
   7025       old_len_desc.set_value(isolate->factory()->NewNumberFromUint(index + 1));
   7026       // 3j ii. Let succeeded be
   7027       //        OrdinaryDefineOwnProperty(A, "length", oldLenDesc).
   7028       succeeded = OrdinaryDefineOwnProperty(isolate, o,
   7029                                             isolate->factory()->length_string(),
   7030                                             &old_len_desc, should_throw);
   7031       // 3j iii. Assert: succeeded is true.
   7032       DCHECK(succeeded.FromJust());
   7033       USE(succeeded);
   7034     }
   7035     // 3k. Return true.
   7036     return Just(true);
   7037   }
   7038 
   7039   // 4. Return OrdinaryDefineOwnProperty(A, P, Desc).
   7040   return OrdinaryDefineOwnProperty(isolate, o, name, desc, should_throw);
   7041 }
   7042 
   7043 
   7044 // Part of ES6 9.4.2.4 ArraySetLength.
   7045 // static
   7046 bool JSArray::AnythingToArrayLength(Isolate* isolate,
   7047                                     Handle<Object> length_object,
   7048                                     uint32_t* output) {
   7049   // Fast path: check numbers and strings that can be converted directly
   7050   // and unobservably.
   7051   if (length_object->ToArrayLength(output)) return true;
   7052   if (length_object->IsString() &&
   7053       Handle<String>::cast(length_object)->AsArrayIndex(output)) {
   7054     return true;
   7055   }
   7056   // Slow path: follow steps in ES6 9.4.2.4 "ArraySetLength".
   7057   // 3. Let newLen be ToUint32(Desc.[[Value]]).
   7058   Handle<Object> uint32_v;
   7059   if (!Object::ToUint32(isolate, length_object).ToHandle(&uint32_v)) {
   7060     // 4. ReturnIfAbrupt(newLen).
   7061     return false;
   7062   }
   7063   // 5. Let numberLen be ToNumber(Desc.[[Value]]).
   7064   Handle<Object> number_v;
   7065   if (!Object::ToNumber(length_object).ToHandle(&number_v)) {
   7066     // 6. ReturnIfAbrupt(newLen).
   7067     return false;
   7068   }
   7069   // 7. If newLen != numberLen, throw a RangeError exception.
   7070   if (uint32_v->Number() != number_v->Number()) {
   7071     Handle<Object> exception =
   7072         isolate->factory()->NewRangeError(MessageTemplate::kInvalidArrayLength);
   7073     isolate->Throw(*exception);
   7074     return false;
   7075   }
   7076   CHECK(uint32_v->ToArrayLength(output));
   7077   return true;
   7078 }
   7079 
   7080 
   7081 // ES6 9.4.2.4
   7082 // static
   7083 Maybe<bool> JSArray::ArraySetLength(Isolate* isolate, Handle<JSArray> a,
   7084                                     PropertyDescriptor* desc,
   7085                                     ShouldThrow should_throw) {
   7086   // 1. If the [[Value]] field of Desc is absent, then
   7087   if (!desc->has_value()) {
   7088     // 1a. Return OrdinaryDefineOwnProperty(A, "length", Desc).
   7089     return OrdinaryDefineOwnProperty(
   7090         isolate, a, isolate->factory()->length_string(), desc, should_throw);
   7091   }
   7092   // 2. Let newLenDesc be a copy of Desc.
   7093   // (Actual copying is not necessary.)
   7094   PropertyDescriptor* new_len_desc = desc;
   7095   // 3. - 7. Convert Desc.[[Value]] to newLen.
   7096   uint32_t new_len = 0;
   7097   if (!AnythingToArrayLength(isolate, desc->value(), &new_len)) {
   7098     DCHECK(isolate->has_pending_exception());
   7099     return Nothing<bool>();
   7100   }
   7101   // 8. Set newLenDesc.[[Value]] to newLen.
   7102   // (Done below, if needed.)
   7103   // 9. Let oldLenDesc be OrdinaryGetOwnProperty(A, "length").
   7104   PropertyDescriptor old_len_desc;
   7105   Maybe<bool> success = GetOwnPropertyDescriptor(
   7106       isolate, a, isolate->factory()->length_string(), &old_len_desc);
   7107   // 10. (Assert)
   7108   DCHECK(success.FromJust());
   7109   USE(success);
   7110   // 11. Let oldLen be oldLenDesc.[[Value]].
   7111   uint32_t old_len = 0;
   7112   CHECK(old_len_desc.value()->ToArrayLength(&old_len));
   7113   // 12. If newLen >= oldLen, then
   7114   if (new_len >= old_len) {
   7115     // 8. Set newLenDesc.[[Value]] to newLen.
   7116     // 12a. Return OrdinaryDefineOwnProperty(A, "length", newLenDesc).
   7117     new_len_desc->set_value(isolate->factory()->NewNumberFromUint(new_len));
   7118     return OrdinaryDefineOwnProperty(isolate, a,
   7119                                      isolate->factory()->length_string(),
   7120                                      new_len_desc, should_throw);
   7121   }
   7122   // 13. If oldLenDesc.[[Writable]] is false, return false.
   7123   if (!old_len_desc.writable()) {
   7124     RETURN_FAILURE(isolate, should_throw,
   7125                    NewTypeError(MessageTemplate::kRedefineDisallowed,
   7126                                 isolate->factory()->length_string()));
   7127   }
   7128   // 14. If newLenDesc.[[Writable]] is absent or has the value true,
   7129   // let newWritable be true.
   7130   bool new_writable = false;
   7131   if (!new_len_desc->has_writable() || new_len_desc->writable()) {
   7132     new_writable = true;
   7133   } else {
   7134     // 15. Else,
   7135     // 15a. Need to defer setting the [[Writable]] attribute to false in case
   7136     //      any elements cannot be deleted.
   7137     // 15b. Let newWritable be false. (It's initialized as "false" anyway.)
   7138     // 15c. Set newLenDesc.[[Writable]] to true.
   7139     // (Not needed.)
   7140   }
   7141   // Most of steps 16 through 19 is implemented by JSArray::SetLength.
   7142   JSArray::SetLength(a, new_len);
   7143   // Steps 19d-ii, 20.
   7144   if (!new_writable) {
   7145     PropertyDescriptor readonly;
   7146     readonly.set_writable(false);
   7147     Maybe<bool> success = OrdinaryDefineOwnProperty(
   7148         isolate, a, isolate->factory()->length_string(), &readonly,
   7149         should_throw);
   7150     DCHECK(success.FromJust());
   7151     USE(success);
   7152   }
   7153   uint32_t actual_new_len = 0;
   7154   CHECK(a->length()->ToArrayLength(&actual_new_len));
   7155   // Steps 19d-v, 21. Return false if there were non-deletable elements.
   7156   bool result = actual_new_len == new_len;
   7157   if (!result) {
   7158     RETURN_FAILURE(
   7159         isolate, should_throw,
   7160         NewTypeError(MessageTemplate::kStrictDeleteProperty,
   7161                      isolate->factory()->NewNumberFromUint(actual_new_len - 1),
   7162                      a));
   7163   }
   7164   return Just(result);
   7165 }
   7166 
   7167 
   7168 // ES6 9.5.6
   7169 // static
   7170 Maybe<bool> JSProxy::DefineOwnProperty(Isolate* isolate, Handle<JSProxy> proxy,
   7171                                        Handle<Object> key,
   7172                                        PropertyDescriptor* desc,
   7173                                        ShouldThrow should_throw) {
   7174   STACK_CHECK(isolate, Nothing<bool>());
   7175   if (key->IsSymbol() && Handle<Symbol>::cast(key)->IsPrivate()) {
   7176     return SetPrivateProperty(isolate, proxy, Handle<Symbol>::cast(key), desc,
   7177                               should_throw);
   7178   }
   7179   Handle<String> trap_name = isolate->factory()->defineProperty_string();
   7180   // 1. Assert: IsPropertyKey(P) is true.
   7181   DCHECK(key->IsName() || key->IsNumber());
   7182   // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O.
   7183   Handle<Object> handler(proxy->handler(), isolate);
   7184   // 3. If handler is null, throw a TypeError exception.
   7185   // 4. Assert: Type(handler) is Object.
   7186   if (proxy->IsRevoked()) {
   7187     isolate->Throw(*isolate->factory()->NewTypeError(
   7188         MessageTemplate::kProxyRevoked, trap_name));
   7189     return Nothing<bool>();
   7190   }
   7191   // 5. Let target be the value of the [[ProxyTarget]] internal slot of O.
   7192   Handle<JSReceiver> target(proxy->target(), isolate);
   7193   // 6. Let trap be ? GetMethod(handler, "defineProperty").
   7194   Handle<Object> trap;
   7195   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   7196       isolate, trap,
   7197       Object::GetMethod(Handle<JSReceiver>::cast(handler), trap_name),
   7198       Nothing<bool>());
   7199   // 7. If trap is undefined, then:
   7200   if (trap->IsUndefined(isolate)) {
   7201     // 7a. Return target.[[DefineOwnProperty]](P, Desc).
   7202     return JSReceiver::DefineOwnProperty(isolate, target, key, desc,
   7203                                          should_throw);
   7204   }
   7205   // 8. Let descObj be FromPropertyDescriptor(Desc).
   7206   Handle<Object> desc_obj = desc->ToObject(isolate);
   7207   // 9. Let booleanTrapResult be
   7208   //    ToBoolean(? Call(trap, handler, target, P, descObj)).
   7209   Handle<Name> property_name =
   7210       key->IsName()
   7211           ? Handle<Name>::cast(key)
   7212           : Handle<Name>::cast(isolate->factory()->NumberToString(key));
   7213   // Do not leak private property names.
   7214   DCHECK(!property_name->IsPrivate());
   7215   Handle<Object> trap_result_obj;
   7216   Handle<Object> args[] = {target, property_name, desc_obj};
   7217   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   7218       isolate, trap_result_obj,
   7219       Execution::Call(isolate, trap, handler, arraysize(args), args),
   7220       Nothing<bool>());
   7221   // 10. If booleanTrapResult is false, return false.
   7222   if (!trap_result_obj->BooleanValue()) {
   7223     RETURN_FAILURE(isolate, should_throw,
   7224                    NewTypeError(MessageTemplate::kProxyTrapReturnedFalsishFor,
   7225                                 trap_name, property_name));
   7226   }
   7227   // 11. Let targetDesc be ? target.[[GetOwnProperty]](P).
   7228   PropertyDescriptor target_desc;
   7229   Maybe<bool> target_found =
   7230       JSReceiver::GetOwnPropertyDescriptor(isolate, target, key, &target_desc);
   7231   MAYBE_RETURN(target_found, Nothing<bool>());
   7232   // 12. Let extensibleTarget be ? IsExtensible(target).
   7233   Maybe<bool> maybe_extensible = JSReceiver::IsExtensible(target);
   7234   MAYBE_RETURN(maybe_extensible, Nothing<bool>());
   7235   bool extensible_target = maybe_extensible.FromJust();
   7236   // 13. If Desc has a [[Configurable]] field and if Desc.[[Configurable]]
   7237   //     is false, then:
   7238   // 13a. Let settingConfigFalse be true.
   7239   // 14. Else let settingConfigFalse be false.
   7240   bool setting_config_false = desc->has_configurable() && !desc->configurable();
   7241   // 15. If targetDesc is undefined, then
   7242   if (!target_found.FromJust()) {
   7243     // 15a. If extensibleTarget is false, throw a TypeError exception.
   7244     if (!extensible_target) {
   7245       isolate->Throw(*isolate->factory()->NewTypeError(
   7246           MessageTemplate::kProxyDefinePropertyNonExtensible, property_name));
   7247       return Nothing<bool>();
   7248     }
   7249     // 15b. If settingConfigFalse is true, throw a TypeError exception.
   7250     if (setting_config_false) {
   7251       isolate->Throw(*isolate->factory()->NewTypeError(
   7252           MessageTemplate::kProxyDefinePropertyNonConfigurable, property_name));
   7253       return Nothing<bool>();
   7254     }
   7255   } else {
   7256     // 16. Else targetDesc is not undefined,
   7257     // 16a. If IsCompatiblePropertyDescriptor(extensibleTarget, Desc,
   7258     //      targetDesc) is false, throw a TypeError exception.
   7259     Maybe<bool> valid =
   7260         IsCompatiblePropertyDescriptor(isolate, extensible_target, desc,
   7261                                        &target_desc, property_name, DONT_THROW);
   7262     MAYBE_RETURN(valid, Nothing<bool>());
   7263     if (!valid.FromJust()) {
   7264       isolate->Throw(*isolate->factory()->NewTypeError(
   7265           MessageTemplate::kProxyDefinePropertyIncompatible, property_name));
   7266       return Nothing<bool>();
   7267     }
   7268     // 16b. If settingConfigFalse is true and targetDesc.[[Configurable]] is
   7269     //      true, throw a TypeError exception.
   7270     if (setting_config_false && target_desc.configurable()) {
   7271       isolate->Throw(*isolate->factory()->NewTypeError(
   7272           MessageTemplate::kProxyDefinePropertyNonConfigurable, property_name));
   7273       return Nothing<bool>();
   7274     }
   7275   }
   7276   // 17. Return true.
   7277   return Just(true);
   7278 }
   7279 
   7280 
   7281 // static
   7282 Maybe<bool> JSProxy::SetPrivateProperty(Isolate* isolate, Handle<JSProxy> proxy,
   7283                                         Handle<Symbol> private_name,
   7284                                         PropertyDescriptor* desc,
   7285                                         ShouldThrow should_throw) {
   7286   // Despite the generic name, this can only add private data properties.
   7287   if (!PropertyDescriptor::IsDataDescriptor(desc) ||
   7288       desc->ToAttributes() != DONT_ENUM) {
   7289     RETURN_FAILURE(isolate, should_throw,
   7290                    NewTypeError(MessageTemplate::kProxyPrivate));
   7291   }
   7292   DCHECK(proxy->map()->is_dictionary_map());
   7293   Handle<Object> value =
   7294       desc->has_value()
   7295           ? desc->value()
   7296           : Handle<Object>::cast(isolate->factory()->undefined_value());
   7297 
   7298   LookupIterator it(proxy, private_name, proxy);
   7299 
   7300   if (it.IsFound()) {
   7301     DCHECK_EQ(LookupIterator::DATA, it.state());
   7302     DCHECK_EQ(DONT_ENUM, it.property_attributes());
   7303     it.WriteDataValue(value);
   7304     return Just(true);
   7305   }
   7306 
   7307   Handle<NameDictionary> dict(proxy->property_dictionary());
   7308   PropertyDetails details(DONT_ENUM, DATA, 0, PropertyCellType::kNoCell);
   7309   Handle<NameDictionary> result =
   7310       NameDictionary::Add(dict, private_name, value, details);
   7311   if (!dict.is_identical_to(result)) proxy->set_properties(*result);
   7312   return Just(true);
   7313 }
   7314 
   7315 
   7316 // static
   7317 Maybe<bool> JSReceiver::GetOwnPropertyDescriptor(Isolate* isolate,
   7318                                                  Handle<JSReceiver> object,
   7319                                                  Handle<Object> key,
   7320                                                  PropertyDescriptor* desc) {
   7321   bool success = false;
   7322   DCHECK(key->IsName() || key->IsNumber());  // |key| is a PropertyKey...
   7323   LookupIterator it = LookupIterator::PropertyOrElement(
   7324       isolate, object, key, &success, LookupIterator::OWN);
   7325   DCHECK(success);  // ...so creating a LookupIterator can't fail.
   7326   return GetOwnPropertyDescriptor(&it, desc);
   7327 }
   7328 
   7329 namespace {
   7330 
   7331 Maybe<bool> GetPropertyDescriptorWithInterceptor(LookupIterator* it,
   7332                                                  PropertyDescriptor* desc) {
   7333   if (it->state() == LookupIterator::INTERCEPTOR) {
   7334     Isolate* isolate = it->isolate();
   7335     Handle<InterceptorInfo> interceptor = it->GetInterceptor();
   7336     if (!interceptor->descriptor()->IsUndefined(isolate)) {
   7337       Handle<Object> result;
   7338       Handle<JSObject> holder = it->GetHolder<JSObject>();
   7339 
   7340       Handle<Object> receiver = it->GetReceiver();
   7341       if (!receiver->IsJSReceiver()) {
   7342         ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   7343             isolate, receiver, Object::ConvertReceiver(isolate, receiver),
   7344             Nothing<bool>());
   7345       }
   7346 
   7347       PropertyCallbackArguments args(isolate, interceptor->data(), *receiver,
   7348                                      *holder, Object::DONT_THROW);
   7349       if (it->IsElement()) {
   7350         uint32_t index = it->index();
   7351         v8::IndexedPropertyDescriptorCallback descriptorCallback =
   7352             v8::ToCData<v8::IndexedPropertyDescriptorCallback>(
   7353                 interceptor->descriptor());
   7354 
   7355         result = args.Call(descriptorCallback, index);
   7356       } else {
   7357         Handle<Name> name = it->name();
   7358         DCHECK(!name->IsPrivate());
   7359         v8::GenericNamedPropertyDescriptorCallback descriptorCallback =
   7360             v8::ToCData<v8::GenericNamedPropertyDescriptorCallback>(
   7361                 interceptor->descriptor());
   7362         result = args.Call(descriptorCallback, name);
   7363       }
   7364       if (!result.is_null()) {
   7365         // Request successfully intercepted, try to set the property
   7366         // descriptor.
   7367         Utils::ApiCheck(
   7368             PropertyDescriptor::ToPropertyDescriptor(isolate, result, desc),
   7369             it->IsElement() ? "v8::IndexedPropertyDescriptorCallback"
   7370                             : "v8::NamedPropertyDescriptorCallback",
   7371             "Invalid property descriptor.");
   7372 
   7373         return Just(true);
   7374       }
   7375     }
   7376   }
   7377   return Just(false);
   7378 }
   7379 }  // namespace
   7380 
   7381 // ES6 9.1.5.1
   7382 // Returns true on success, false if the property didn't exist, nothing if
   7383 // an exception was thrown.
   7384 // static
   7385 Maybe<bool> JSReceiver::GetOwnPropertyDescriptor(LookupIterator* it,
   7386                                                  PropertyDescriptor* desc) {
   7387   Isolate* isolate = it->isolate();
   7388   // "Virtual" dispatch.
   7389   if (it->IsFound() && it->GetHolder<JSReceiver>()->IsJSProxy()) {
   7390     return JSProxy::GetOwnPropertyDescriptor(isolate, it->GetHolder<JSProxy>(),
   7391                                              it->GetName(), desc);
   7392   }
   7393 
   7394   Maybe<bool> intercepted = GetPropertyDescriptorWithInterceptor(it, desc);
   7395   MAYBE_RETURN(intercepted, Nothing<bool>());
   7396   if (intercepted.FromJust()) {
   7397     return Just(true);
   7398   }
   7399 
   7400   // Request was not intercepted, continue as normal.
   7401   // 1. (Assert)
   7402   // 2. If O does not have an own property with key P, return undefined.
   7403   Maybe<PropertyAttributes> maybe = JSObject::GetPropertyAttributes(it);
   7404   MAYBE_RETURN(maybe, Nothing<bool>());
   7405   PropertyAttributes attrs = maybe.FromJust();
   7406   if (attrs == ABSENT) return Just(false);
   7407   DCHECK(!isolate->has_pending_exception());
   7408 
   7409   // 3. Let D be a newly created Property Descriptor with no fields.
   7410   DCHECK(desc->is_empty());
   7411   // 4. Let X be O's own property whose key is P.
   7412   // 5. If X is a data property, then
   7413   bool is_accessor_pair = it->state() == LookupIterator::ACCESSOR &&
   7414                           it->GetAccessors()->IsAccessorPair();
   7415   if (!is_accessor_pair) {
   7416     // 5a. Set D.[[Value]] to the value of X's [[Value]] attribute.
   7417     Handle<Object> value;
   7418     if (!Object::GetProperty(it).ToHandle(&value)) {
   7419       DCHECK(isolate->has_pending_exception());
   7420       return Nothing<bool>();
   7421     }
   7422     desc->set_value(value);
   7423     // 5b. Set D.[[Writable]] to the value of X's [[Writable]] attribute
   7424     desc->set_writable((attrs & READ_ONLY) == 0);
   7425   } else {
   7426     // 6. Else X is an accessor property, so
   7427     Handle<AccessorPair> accessors =
   7428         Handle<AccessorPair>::cast(it->GetAccessors());
   7429     // 6a. Set D.[[Get]] to the value of X's [[Get]] attribute.
   7430     desc->set_get(AccessorPair::GetComponent(accessors, ACCESSOR_GETTER));
   7431     // 6b. Set D.[[Set]] to the value of X's [[Set]] attribute.
   7432     desc->set_set(AccessorPair::GetComponent(accessors, ACCESSOR_SETTER));
   7433   }
   7434 
   7435   // 7. Set D.[[Enumerable]] to the value of X's [[Enumerable]] attribute.
   7436   desc->set_enumerable((attrs & DONT_ENUM) == 0);
   7437   // 8. Set D.[[Configurable]] to the value of X's [[Configurable]] attribute.
   7438   desc->set_configurable((attrs & DONT_DELETE) == 0);
   7439   // 9. Return D.
   7440   DCHECK(PropertyDescriptor::IsAccessorDescriptor(desc) !=
   7441          PropertyDescriptor::IsDataDescriptor(desc));
   7442   return Just(true);
   7443 }
   7444 
   7445 
   7446 // ES6 9.5.5
   7447 // static
   7448 Maybe<bool> JSProxy::GetOwnPropertyDescriptor(Isolate* isolate,
   7449                                               Handle<JSProxy> proxy,
   7450                                               Handle<Name> name,
   7451                                               PropertyDescriptor* desc) {
   7452   DCHECK(!name->IsPrivate());
   7453   STACK_CHECK(isolate, Nothing<bool>());
   7454 
   7455   Handle<String> trap_name =
   7456       isolate->factory()->getOwnPropertyDescriptor_string();
   7457   // 1. (Assert)
   7458   // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O.
   7459   Handle<Object> handler(proxy->handler(), isolate);
   7460   // 3. If handler is null, throw a TypeError exception.
   7461   // 4. Assert: Type(handler) is Object.
   7462   if (proxy->IsRevoked()) {
   7463     isolate->Throw(*isolate->factory()->NewTypeError(
   7464         MessageTemplate::kProxyRevoked, trap_name));
   7465     return Nothing<bool>();
   7466   }
   7467   // 5. Let target be the value of the [[ProxyTarget]] internal slot of O.
   7468   Handle<JSReceiver> target(proxy->target(), isolate);
   7469   // 6. Let trap be ? GetMethod(handler, "getOwnPropertyDescriptor").
   7470   Handle<Object> trap;
   7471   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   7472       isolate, trap,
   7473       Object::GetMethod(Handle<JSReceiver>::cast(handler), trap_name),
   7474       Nothing<bool>());
   7475   // 7. If trap is undefined, then
   7476   if (trap->IsUndefined(isolate)) {
   7477     // 7a. Return target.[[GetOwnProperty]](P).
   7478     return JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, desc);
   7479   }
   7480   // 8. Let trapResultObj be ? Call(trap, handler, target, P).
   7481   Handle<Object> trap_result_obj;
   7482   Handle<Object> args[] = {target, name};
   7483   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   7484       isolate, trap_result_obj,
   7485       Execution::Call(isolate, trap, handler, arraysize(args), args),
   7486       Nothing<bool>());
   7487   // 9. If Type(trapResultObj) is neither Object nor Undefined, throw a
   7488   //    TypeError exception.
   7489   if (!trap_result_obj->IsJSReceiver() &&
   7490       !trap_result_obj->IsUndefined(isolate)) {
   7491     isolate->Throw(*isolate->factory()->NewTypeError(
   7492         MessageTemplate::kProxyGetOwnPropertyDescriptorInvalid, name));
   7493     return Nothing<bool>();
   7494   }
   7495   // 10. Let targetDesc be ? target.[[GetOwnProperty]](P).
   7496   PropertyDescriptor target_desc;
   7497   Maybe<bool> found =
   7498       JSReceiver::GetOwnPropertyDescriptor(isolate, target, name, &target_desc);
   7499   MAYBE_RETURN(found, Nothing<bool>());
   7500   // 11. If trapResultObj is undefined, then
   7501   if (trap_result_obj->IsUndefined(isolate)) {
   7502     // 11a. If targetDesc is undefined, return undefined.
   7503     if (!found.FromJust()) return Just(false);
   7504     // 11b. If targetDesc.[[Configurable]] is false, throw a TypeError
   7505     //      exception.
   7506     if (!target_desc.configurable()) {
   7507       isolate->Throw(*isolate->factory()->NewTypeError(
   7508           MessageTemplate::kProxyGetOwnPropertyDescriptorUndefined, name));
   7509       return Nothing<bool>();
   7510     }
   7511     // 11c. Let extensibleTarget be ? IsExtensible(target).
   7512     Maybe<bool> extensible_target = JSReceiver::IsExtensible(target);
   7513     MAYBE_RETURN(extensible_target, Nothing<bool>());
   7514     // 11d. (Assert)
   7515     // 11e. If extensibleTarget is false, throw a TypeError exception.
   7516     if (!extensible_target.FromJust()) {
   7517       isolate->Throw(*isolate->factory()->NewTypeError(
   7518           MessageTemplate::kProxyGetOwnPropertyDescriptorNonExtensible, name));
   7519       return Nothing<bool>();
   7520     }
   7521     // 11f. Return undefined.
   7522     return Just(false);
   7523   }
   7524   // 12. Let extensibleTarget be ? IsExtensible(target).
   7525   Maybe<bool> extensible_target = JSReceiver::IsExtensible(target);
   7526   MAYBE_RETURN(extensible_target, Nothing<bool>());
   7527   // 13. Let resultDesc be ? ToPropertyDescriptor(trapResultObj).
   7528   if (!PropertyDescriptor::ToPropertyDescriptor(isolate, trap_result_obj,
   7529                                                 desc)) {
   7530     DCHECK(isolate->has_pending_exception());
   7531     return Nothing<bool>();
   7532   }
   7533   // 14. Call CompletePropertyDescriptor(resultDesc).
   7534   PropertyDescriptor::CompletePropertyDescriptor(isolate, desc);
   7535   // 15. Let valid be IsCompatiblePropertyDescriptor (extensibleTarget,
   7536   //     resultDesc, targetDesc).
   7537   Maybe<bool> valid =
   7538       IsCompatiblePropertyDescriptor(isolate, extensible_target.FromJust(),
   7539                                      desc, &target_desc, name, DONT_THROW);
   7540   MAYBE_RETURN(valid, Nothing<bool>());
   7541   // 16. If valid is false, throw a TypeError exception.
   7542   if (!valid.FromJust()) {
   7543     isolate->Throw(*isolate->factory()->NewTypeError(
   7544         MessageTemplate::kProxyGetOwnPropertyDescriptorIncompatible, name));
   7545     return Nothing<bool>();
   7546   }
   7547   // 17. If resultDesc.[[Configurable]] is false, then
   7548   if (!desc->configurable()) {
   7549     // 17a. If targetDesc is undefined or targetDesc.[[Configurable]] is true:
   7550     if (target_desc.is_empty() || target_desc.configurable()) {
   7551       // 17a i. Throw a TypeError exception.
   7552       isolate->Throw(*isolate->factory()->NewTypeError(
   7553           MessageTemplate::kProxyGetOwnPropertyDescriptorNonConfigurable,
   7554           name));
   7555       return Nothing<bool>();
   7556     }
   7557   }
   7558   // 18. Return resultDesc.
   7559   return Just(true);
   7560 }
   7561 
   7562 
   7563 bool JSObject::ReferencesObjectFromElements(FixedArray* elements,
   7564                                             ElementsKind kind,
   7565                                             Object* object) {
   7566   Isolate* isolate = elements->GetIsolate();
   7567   if (IsFastObjectElementsKind(kind) || kind == FAST_STRING_WRAPPER_ELEMENTS) {
   7568     int length = IsJSArray()
   7569         ? Smi::cast(JSArray::cast(this)->length())->value()
   7570         : elements->length();
   7571     for (int i = 0; i < length; ++i) {
   7572       Object* element = elements->get(i);
   7573       if (!element->IsTheHole(isolate) && element == object) return true;
   7574     }
   7575   } else {
   7576     DCHECK(kind == DICTIONARY_ELEMENTS || kind == SLOW_STRING_WRAPPER_ELEMENTS);
   7577     Object* key =
   7578         SeededNumberDictionary::cast(elements)->SlowReverseLookup(object);
   7579     if (!key->IsUndefined(isolate)) return true;
   7580   }
   7581   return false;
   7582 }
   7583 
   7584 
   7585 // Check whether this object references another object.
   7586 bool JSObject::ReferencesObject(Object* obj) {
   7587   Map* map_of_this = map();
   7588   Heap* heap = GetHeap();
   7589   DisallowHeapAllocation no_allocation;
   7590 
   7591   // Is the object the constructor for this object?
   7592   if (map_of_this->GetConstructor() == obj) {
   7593     return true;
   7594   }
   7595 
   7596   // Is the object the prototype for this object?
   7597   if (map_of_this->prototype() == obj) {
   7598     return true;
   7599   }
   7600 
   7601   // Check if the object is among the named properties.
   7602   Object* key = SlowReverseLookup(obj);
   7603   if (!key->IsUndefined(heap->isolate())) {
   7604     return true;
   7605   }
   7606 
   7607   // Check if the object is among the indexed properties.
   7608   ElementsKind kind = GetElementsKind();
   7609   switch (kind) {
   7610     // Raw pixels and external arrays do not reference other
   7611     // objects.
   7612 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                        \
   7613     case TYPE##_ELEMENTS:                                                      \
   7614       break;
   7615 
   7616     TYPED_ARRAYS(TYPED_ARRAY_CASE)
   7617 #undef TYPED_ARRAY_CASE
   7618 
   7619     case FAST_DOUBLE_ELEMENTS:
   7620     case FAST_HOLEY_DOUBLE_ELEMENTS:
   7621       break;
   7622     case FAST_SMI_ELEMENTS:
   7623     case FAST_HOLEY_SMI_ELEMENTS:
   7624       break;
   7625     case FAST_ELEMENTS:
   7626     case FAST_HOLEY_ELEMENTS:
   7627     case DICTIONARY_ELEMENTS:
   7628     case FAST_STRING_WRAPPER_ELEMENTS:
   7629     case SLOW_STRING_WRAPPER_ELEMENTS: {
   7630       FixedArray* elements = FixedArray::cast(this->elements());
   7631       if (ReferencesObjectFromElements(elements, kind, obj)) return true;
   7632       break;
   7633     }
   7634     case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
   7635     case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: {
   7636       FixedArray* parameter_map = FixedArray::cast(elements());
   7637       // Check the mapped parameters.
   7638       int length = parameter_map->length();
   7639       for (int i = 2; i < length; ++i) {
   7640         Object* value = parameter_map->get(i);
   7641         if (!value->IsTheHole(heap->isolate()) && value == obj) return true;
   7642       }
   7643       // Check the arguments.
   7644       FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
   7645       kind = arguments->IsDictionary() ? DICTIONARY_ELEMENTS :
   7646           FAST_HOLEY_ELEMENTS;
   7647       if (ReferencesObjectFromElements(arguments, kind, obj)) return true;
   7648       break;
   7649     }
   7650     case NO_ELEMENTS:
   7651       break;
   7652   }
   7653 
   7654   // For functions check the context.
   7655   if (IsJSFunction()) {
   7656     // Get the constructor function for arguments array.
   7657     Map* arguments_map =
   7658         heap->isolate()->context()->native_context()->sloppy_arguments_map();
   7659     JSFunction* arguments_function =
   7660         JSFunction::cast(arguments_map->GetConstructor());
   7661 
   7662     // Get the context and don't check if it is the native context.
   7663     JSFunction* f = JSFunction::cast(this);
   7664     Context* context = f->context();
   7665     if (context->IsNativeContext()) {
   7666       return false;
   7667     }
   7668 
   7669     // Check the non-special context slots.
   7670     for (int i = Context::MIN_CONTEXT_SLOTS; i < context->length(); i++) {
   7671       // Only check JS objects.
   7672       if (context->get(i)->IsJSObject()) {
   7673         JSObject* ctxobj = JSObject::cast(context->get(i));
   7674         // If it is an arguments array check the content.
   7675         if (ctxobj->map()->GetConstructor() == arguments_function) {
   7676           if (ctxobj->ReferencesObject(obj)) {
   7677             return true;
   7678           }
   7679         } else if (ctxobj == obj) {
   7680           return true;
   7681         }
   7682       }
   7683     }
   7684 
   7685     // Check the context extension (if any) if it can have references.
   7686     if (context->has_extension() && !context->IsCatchContext()) {
   7687       // With harmony scoping, a JSFunction may have a script context.
   7688       // TODO(mvstanton): walk into the ScopeInfo.
   7689       if (context->IsScriptContext()) {
   7690         return false;
   7691       }
   7692 
   7693       return context->extension_object()->ReferencesObject(obj);
   7694     }
   7695   }
   7696 
   7697   // No references to object.
   7698   return false;
   7699 }
   7700 
   7701 
   7702 Maybe<bool> JSReceiver::SetIntegrityLevel(Handle<JSReceiver> receiver,
   7703                                           IntegrityLevel level,
   7704                                           ShouldThrow should_throw) {
   7705   DCHECK(level == SEALED || level == FROZEN);
   7706 
   7707   if (receiver->IsJSObject()) {
   7708     Handle<JSObject> object = Handle<JSObject>::cast(receiver);
   7709     if (!object->HasSloppyArgumentsElements()) {  // Fast path.
   7710       if (level == SEALED) {
   7711         return JSObject::PreventExtensionsWithTransition<SEALED>(object,
   7712                                                                  should_throw);
   7713       } else {
   7714         return JSObject::PreventExtensionsWithTransition<FROZEN>(object,
   7715                                                                  should_throw);
   7716       }
   7717     }
   7718   }
   7719 
   7720   Isolate* isolate = receiver->GetIsolate();
   7721 
   7722   MAYBE_RETURN(JSReceiver::PreventExtensions(receiver, should_throw),
   7723                Nothing<bool>());
   7724 
   7725   Handle<FixedArray> keys;
   7726   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   7727       isolate, keys, JSReceiver::OwnPropertyKeys(receiver), Nothing<bool>());
   7728 
   7729   PropertyDescriptor no_conf;
   7730   no_conf.set_configurable(false);
   7731 
   7732   PropertyDescriptor no_conf_no_write;
   7733   no_conf_no_write.set_configurable(false);
   7734   no_conf_no_write.set_writable(false);
   7735 
   7736   if (level == SEALED) {
   7737     for (int i = 0; i < keys->length(); ++i) {
   7738       Handle<Object> key(keys->get(i), isolate);
   7739       MAYBE_RETURN(
   7740           DefineOwnProperty(isolate, receiver, key, &no_conf, THROW_ON_ERROR),
   7741           Nothing<bool>());
   7742     }
   7743     return Just(true);
   7744   }
   7745 
   7746   for (int i = 0; i < keys->length(); ++i) {
   7747     Handle<Object> key(keys->get(i), isolate);
   7748     PropertyDescriptor current_desc;
   7749     Maybe<bool> owned = JSReceiver::GetOwnPropertyDescriptor(
   7750         isolate, receiver, key, &current_desc);
   7751     MAYBE_RETURN(owned, Nothing<bool>());
   7752     if (owned.FromJust()) {
   7753       PropertyDescriptor desc =
   7754           PropertyDescriptor::IsAccessorDescriptor(&current_desc)
   7755               ? no_conf
   7756               : no_conf_no_write;
   7757       MAYBE_RETURN(
   7758           DefineOwnProperty(isolate, receiver, key, &desc, THROW_ON_ERROR),
   7759           Nothing<bool>());
   7760     }
   7761   }
   7762   return Just(true);
   7763 }
   7764 
   7765 
   7766 Maybe<bool> JSReceiver::TestIntegrityLevel(Handle<JSReceiver> object,
   7767                                            IntegrityLevel level) {
   7768   DCHECK(level == SEALED || level == FROZEN);
   7769   Isolate* isolate = object->GetIsolate();
   7770 
   7771   Maybe<bool> extensible = JSReceiver::IsExtensible(object);
   7772   MAYBE_RETURN(extensible, Nothing<bool>());
   7773   if (extensible.FromJust()) return Just(false);
   7774 
   7775   Handle<FixedArray> keys;
   7776   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   7777       isolate, keys, JSReceiver::OwnPropertyKeys(object), Nothing<bool>());
   7778 
   7779   for (int i = 0; i < keys->length(); ++i) {
   7780     Handle<Object> key(keys->get(i), isolate);
   7781     PropertyDescriptor current_desc;
   7782     Maybe<bool> owned = JSReceiver::GetOwnPropertyDescriptor(
   7783         isolate, object, key, &current_desc);
   7784     MAYBE_RETURN(owned, Nothing<bool>());
   7785     if (owned.FromJust()) {
   7786       if (current_desc.configurable()) return Just(false);
   7787       if (level == FROZEN &&
   7788           PropertyDescriptor::IsDataDescriptor(&current_desc) &&
   7789           current_desc.writable()) {
   7790         return Just(false);
   7791       }
   7792     }
   7793   }
   7794   return Just(true);
   7795 }
   7796 
   7797 
   7798 Maybe<bool> JSReceiver::PreventExtensions(Handle<JSReceiver> object,
   7799                                           ShouldThrow should_throw) {
   7800   if (object->IsJSProxy()) {
   7801     return JSProxy::PreventExtensions(Handle<JSProxy>::cast(object),
   7802                                       should_throw);
   7803   }
   7804   DCHECK(object->IsJSObject());
   7805   return JSObject::PreventExtensions(Handle<JSObject>::cast(object),
   7806                                      should_throw);
   7807 }
   7808 
   7809 
   7810 Maybe<bool> JSProxy::PreventExtensions(Handle<JSProxy> proxy,
   7811                                        ShouldThrow should_throw) {
   7812   Isolate* isolate = proxy->GetIsolate();
   7813   STACK_CHECK(isolate, Nothing<bool>());
   7814   Factory* factory = isolate->factory();
   7815   Handle<String> trap_name = factory->preventExtensions_string();
   7816 
   7817   if (proxy->IsRevoked()) {
   7818     isolate->Throw(
   7819         *factory->NewTypeError(MessageTemplate::kProxyRevoked, trap_name));
   7820     return Nothing<bool>();
   7821   }
   7822   Handle<JSReceiver> target(proxy->target(), isolate);
   7823   Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate);
   7824 
   7825   Handle<Object> trap;
   7826   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   7827       isolate, trap, Object::GetMethod(handler, trap_name), Nothing<bool>());
   7828   if (trap->IsUndefined(isolate)) {
   7829     return JSReceiver::PreventExtensions(target, should_throw);
   7830   }
   7831 
   7832   Handle<Object> trap_result;
   7833   Handle<Object> args[] = {target};
   7834   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   7835       isolate, trap_result,
   7836       Execution::Call(isolate, trap, handler, arraysize(args), args),
   7837       Nothing<bool>());
   7838   if (!trap_result->BooleanValue()) {
   7839     RETURN_FAILURE(
   7840         isolate, should_throw,
   7841         NewTypeError(MessageTemplate::kProxyTrapReturnedFalsish, trap_name));
   7842   }
   7843 
   7844   // Enforce the invariant.
   7845   Maybe<bool> target_result = JSReceiver::IsExtensible(target);
   7846   MAYBE_RETURN(target_result, Nothing<bool>());
   7847   if (target_result.FromJust()) {
   7848     isolate->Throw(*factory->NewTypeError(
   7849         MessageTemplate::kProxyPreventExtensionsExtensible));
   7850     return Nothing<bool>();
   7851   }
   7852   return Just(true);
   7853 }
   7854 
   7855 
   7856 Maybe<bool> JSObject::PreventExtensions(Handle<JSObject> object,
   7857                                         ShouldThrow should_throw) {
   7858   Isolate* isolate = object->GetIsolate();
   7859 
   7860   if (!object->HasSloppyArgumentsElements()) {
   7861     return PreventExtensionsWithTransition<NONE>(object, should_throw);
   7862   }
   7863 
   7864   if (object->IsAccessCheckNeeded() &&
   7865       !isolate->MayAccess(handle(isolate->context()), object)) {
   7866     isolate->ReportFailedAccessCheck(object);
   7867     RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
   7868     RETURN_FAILURE(isolate, should_throw,
   7869                    NewTypeError(MessageTemplate::kNoAccess));
   7870   }
   7871 
   7872   if (!object->map()->is_extensible()) return Just(true);
   7873 
   7874   if (object->IsJSGlobalProxy()) {
   7875     PrototypeIterator iter(isolate, object);
   7876     if (iter.IsAtEnd()) return Just(true);
   7877     DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
   7878     return PreventExtensions(PrototypeIterator::GetCurrent<JSObject>(iter),
   7879                              should_throw);
   7880   }
   7881 
   7882   if (!object->HasFixedTypedArrayElements()) {
   7883     // If there are fast elements we normalize.
   7884     Handle<SeededNumberDictionary> dictionary = NormalizeElements(object);
   7885     DCHECK(object->HasDictionaryElements() ||
   7886            object->HasSlowArgumentsElements());
   7887 
   7888     // Make sure that we never go back to fast case.
   7889     object->RequireSlowElements(*dictionary);
   7890   }
   7891 
   7892   // Do a map transition, other objects with this map may still
   7893   // be extensible.
   7894   // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps.
   7895   Handle<Map> new_map = Map::Copy(handle(object->map()), "PreventExtensions");
   7896 
   7897   new_map->set_is_extensible(false);
   7898   JSObject::MigrateToMap(object, new_map);
   7899   DCHECK(!object->map()->is_extensible());
   7900 
   7901   return Just(true);
   7902 }
   7903 
   7904 
   7905 Maybe<bool> JSReceiver::IsExtensible(Handle<JSReceiver> object) {
   7906   if (object->IsJSProxy()) {
   7907     return JSProxy::IsExtensible(Handle<JSProxy>::cast(object));
   7908   }
   7909   return Just(JSObject::IsExtensible(Handle<JSObject>::cast(object)));
   7910 }
   7911 
   7912 
   7913 Maybe<bool> JSProxy::IsExtensible(Handle<JSProxy> proxy) {
   7914   Isolate* isolate = proxy->GetIsolate();
   7915   STACK_CHECK(isolate, Nothing<bool>());
   7916   Factory* factory = isolate->factory();
   7917   Handle<String> trap_name = factory->isExtensible_string();
   7918 
   7919   if (proxy->IsRevoked()) {
   7920     isolate->Throw(
   7921         *factory->NewTypeError(MessageTemplate::kProxyRevoked, trap_name));
   7922     return Nothing<bool>();
   7923   }
   7924   Handle<JSReceiver> target(proxy->target(), isolate);
   7925   Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate);
   7926 
   7927   Handle<Object> trap;
   7928   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   7929       isolate, trap, Object::GetMethod(handler, trap_name), Nothing<bool>());
   7930   if (trap->IsUndefined(isolate)) {
   7931     return JSReceiver::IsExtensible(target);
   7932   }
   7933 
   7934   Handle<Object> trap_result;
   7935   Handle<Object> args[] = {target};
   7936   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   7937       isolate, trap_result,
   7938       Execution::Call(isolate, trap, handler, arraysize(args), args),
   7939       Nothing<bool>());
   7940 
   7941   // Enforce the invariant.
   7942   Maybe<bool> target_result = JSReceiver::IsExtensible(target);
   7943   MAYBE_RETURN(target_result, Nothing<bool>());
   7944   if (target_result.FromJust() != trap_result->BooleanValue()) {
   7945     isolate->Throw(
   7946         *factory->NewTypeError(MessageTemplate::kProxyIsExtensibleInconsistent,
   7947                                factory->ToBoolean(target_result.FromJust())));
   7948     return Nothing<bool>();
   7949   }
   7950   return target_result;
   7951 }
   7952 
   7953 
   7954 bool JSObject::IsExtensible(Handle<JSObject> object) {
   7955   Isolate* isolate = object->GetIsolate();
   7956   if (object->IsAccessCheckNeeded() &&
   7957       !isolate->MayAccess(handle(isolate->context()), object)) {
   7958     return true;
   7959   }
   7960   if (object->IsJSGlobalProxy()) {
   7961     PrototypeIterator iter(isolate, *object);
   7962     if (iter.IsAtEnd()) return false;
   7963     DCHECK(iter.GetCurrent()->IsJSGlobalObject());
   7964     return iter.GetCurrent<JSObject>()->map()->is_extensible();
   7965   }
   7966   return object->map()->is_extensible();
   7967 }
   7968 
   7969 namespace {
   7970 
   7971 template <typename Dictionary>
   7972 void DictionaryDetailsAtPut(Isolate* isolate, Handle<Dictionary> dictionary,
   7973                             int entry, PropertyDetails details) {
   7974   dictionary->DetailsAtPut(entry, details);
   7975 }
   7976 
   7977 template <>
   7978 void DictionaryDetailsAtPut<GlobalDictionary>(
   7979     Isolate* isolate, Handle<GlobalDictionary> dictionary, int entry,
   7980     PropertyDetails details) {
   7981   Object* value = dictionary->ValueAt(entry);
   7982   DCHECK(value->IsPropertyCell());
   7983   value = PropertyCell::cast(value)->value();
   7984   if (value->IsTheHole(isolate)) return;
   7985   PropertyCell::PrepareForValue(dictionary, entry, handle(value, isolate),
   7986                                 details);
   7987 }
   7988 
   7989 template <typename Dictionary>
   7990 void ApplyAttributesToDictionary(Isolate* isolate,
   7991                                  Handle<Dictionary> dictionary,
   7992                                  const PropertyAttributes attributes) {
   7993   int capacity = dictionary->Capacity();
   7994   for (int i = 0; i < capacity; i++) {
   7995     Object* k = dictionary->KeyAt(i);
   7996     if (dictionary->IsKey(isolate, k) &&
   7997         !(k->IsSymbol() && Symbol::cast(k)->is_private())) {
   7998       PropertyDetails details = dictionary->DetailsAt(i);
   7999       int attrs = attributes;
   8000       // READ_ONLY is an invalid attribute for JS setters/getters.
   8001       if ((attributes & READ_ONLY) && details.type() == ACCESSOR_CONSTANT) {
   8002         Object* v = dictionary->ValueAt(i);
   8003         if (v->IsPropertyCell()) v = PropertyCell::cast(v)->value();
   8004         if (v->IsAccessorPair()) attrs &= ~READ_ONLY;
   8005       }
   8006       details = details.CopyAddAttributes(
   8007           static_cast<PropertyAttributes>(attrs));
   8008       DictionaryDetailsAtPut<Dictionary>(isolate, dictionary, i, details);
   8009     }
   8010   }
   8011 }
   8012 
   8013 }  // namespace
   8014 
   8015 template <PropertyAttributes attrs>
   8016 Maybe<bool> JSObject::PreventExtensionsWithTransition(
   8017     Handle<JSObject> object, ShouldThrow should_throw) {
   8018   STATIC_ASSERT(attrs == NONE || attrs == SEALED || attrs == FROZEN);
   8019 
   8020   // Sealing/freezing sloppy arguments should be handled elsewhere.
   8021   DCHECK(!object->HasSloppyArgumentsElements());
   8022 
   8023   Isolate* isolate = object->GetIsolate();
   8024   if (object->IsAccessCheckNeeded() &&
   8025       !isolate->MayAccess(handle(isolate->context()), object)) {
   8026     isolate->ReportFailedAccessCheck(object);
   8027     RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
   8028     RETURN_FAILURE(isolate, should_throw,
   8029                    NewTypeError(MessageTemplate::kNoAccess));
   8030   }
   8031 
   8032   if (attrs == NONE && !object->map()->is_extensible()) return Just(true);
   8033 
   8034   if (object->IsJSGlobalProxy()) {
   8035     PrototypeIterator iter(isolate, object);
   8036     if (iter.IsAtEnd()) return Just(true);
   8037     DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject());
   8038     return PreventExtensionsWithTransition<attrs>(
   8039         PrototypeIterator::GetCurrent<JSObject>(iter), should_throw);
   8040   }
   8041 
   8042   Handle<SeededNumberDictionary> new_element_dictionary;
   8043   if (!object->HasFixedTypedArrayElements() &&
   8044       !object->HasDictionaryElements() &&
   8045       !object->HasSlowStringWrapperElements()) {
   8046     int length =
   8047         object->IsJSArray()
   8048             ? Smi::cast(Handle<JSArray>::cast(object)->length())->value()
   8049             : object->elements()->length();
   8050     new_element_dictionary =
   8051         length == 0 ? isolate->factory()->empty_slow_element_dictionary()
   8052                     : object->GetElementsAccessor()->Normalize(object);
   8053   }
   8054 
   8055   Handle<Symbol> transition_marker;
   8056   if (attrs == NONE) {
   8057     transition_marker = isolate->factory()->nonextensible_symbol();
   8058   } else if (attrs == SEALED) {
   8059     transition_marker = isolate->factory()->sealed_symbol();
   8060   } else {
   8061     DCHECK(attrs == FROZEN);
   8062     transition_marker = isolate->factory()->frozen_symbol();
   8063   }
   8064 
   8065   Handle<Map> old_map(object->map(), isolate);
   8066   Map* transition =
   8067       TransitionArray::SearchSpecial(*old_map, *transition_marker);
   8068   if (transition != NULL) {
   8069     Handle<Map> transition_map(transition, isolate);
   8070     DCHECK(transition_map->has_dictionary_elements() ||
   8071            transition_map->has_fixed_typed_array_elements() ||
   8072            transition_map->elements_kind() == SLOW_STRING_WRAPPER_ELEMENTS);
   8073     DCHECK(!transition_map->is_extensible());
   8074     JSObject::MigrateToMap(object, transition_map);
   8075   } else if (TransitionArray::CanHaveMoreTransitions(old_map)) {
   8076     // Create a new descriptor array with the appropriate property attributes
   8077     Handle<Map> new_map = Map::CopyForPreventExtensions(
   8078         old_map, attrs, transition_marker, "CopyForPreventExtensions");
   8079     JSObject::MigrateToMap(object, new_map);
   8080   } else {
   8081     DCHECK(old_map->is_dictionary_map() || !old_map->is_prototype_map());
   8082     // Slow path: need to normalize properties for safety
   8083     NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0,
   8084                         "SlowPreventExtensions");
   8085 
   8086     // Create a new map, since other objects with this map may be extensible.
   8087     // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps.
   8088     Handle<Map> new_map =
   8089         Map::Copy(handle(object->map()), "SlowCopyForPreventExtensions");
   8090     new_map->set_is_extensible(false);
   8091     if (!new_element_dictionary.is_null()) {
   8092       ElementsKind new_kind =
   8093           IsStringWrapperElementsKind(old_map->elements_kind())
   8094               ? SLOW_STRING_WRAPPER_ELEMENTS
   8095               : DICTIONARY_ELEMENTS;
   8096       new_map->set_elements_kind(new_kind);
   8097     }
   8098     JSObject::MigrateToMap(object, new_map);
   8099 
   8100     if (attrs != NONE) {
   8101       if (object->IsJSGlobalObject()) {
   8102         Handle<GlobalDictionary> dictionary(object->global_dictionary(),
   8103                                             isolate);
   8104         ApplyAttributesToDictionary(isolate, dictionary, attrs);
   8105       } else {
   8106         Handle<NameDictionary> dictionary(object->property_dictionary(),
   8107                                           isolate);
   8108         ApplyAttributesToDictionary(isolate, dictionary, attrs);
   8109       }
   8110     }
   8111   }
   8112 
   8113   // Both seal and preventExtensions always go through without modifications to
   8114   // typed array elements. Freeze works only if there are no actual elements.
   8115   if (object->HasFixedTypedArrayElements()) {
   8116     if (attrs == FROZEN &&
   8117         JSArrayBufferView::cast(*object)->byte_length()->Number() > 0) {
   8118       isolate->Throw(*isolate->factory()->NewTypeError(
   8119           MessageTemplate::kCannotFreezeArrayBufferView));
   8120       return Nothing<bool>();
   8121     }
   8122     return Just(true);
   8123   }
   8124 
   8125   DCHECK(object->map()->has_dictionary_elements() ||
   8126          object->map()->elements_kind() == SLOW_STRING_WRAPPER_ELEMENTS);
   8127   if (!new_element_dictionary.is_null()) {
   8128     object->set_elements(*new_element_dictionary);
   8129   }
   8130 
   8131   if (object->elements() != isolate->heap()->empty_slow_element_dictionary()) {
   8132     Handle<SeededNumberDictionary> dictionary(object->element_dictionary(),
   8133                                               isolate);
   8134     // Make sure we never go back to the fast case
   8135     object->RequireSlowElements(*dictionary);
   8136     if (attrs != NONE) {
   8137       ApplyAttributesToDictionary(isolate, dictionary, attrs);
   8138     }
   8139   }
   8140 
   8141   return Just(true);
   8142 }
   8143 
   8144 
   8145 Handle<Object> JSObject::FastPropertyAt(Handle<JSObject> object,
   8146                                         Representation representation,
   8147                                         FieldIndex index) {
   8148   Isolate* isolate = object->GetIsolate();
   8149   if (object->IsUnboxedDoubleField(index)) {
   8150     double value = object->RawFastDoublePropertyAt(index);
   8151     return isolate->factory()->NewHeapNumber(value);
   8152   }
   8153   Handle<Object> raw_value(object->RawFastPropertyAt(index), isolate);
   8154   return Object::WrapForRead(isolate, raw_value, representation);
   8155 }
   8156 
   8157 template <class ContextObject>
   8158 class JSObjectWalkVisitor {
   8159  public:
   8160   JSObjectWalkVisitor(ContextObject* site_context, bool copying,
   8161                       JSObject::DeepCopyHints hints)
   8162     : site_context_(site_context),
   8163       copying_(copying),
   8164       hints_(hints) {}
   8165 
   8166   MUST_USE_RESULT MaybeHandle<JSObject> StructureWalk(Handle<JSObject> object);
   8167 
   8168  protected:
   8169   MUST_USE_RESULT inline MaybeHandle<JSObject> VisitElementOrProperty(
   8170       Handle<JSObject> object,
   8171       Handle<JSObject> value) {
   8172     Handle<AllocationSite> current_site = site_context()->EnterNewScope();
   8173     MaybeHandle<JSObject> copy_of_value = StructureWalk(value);
   8174     site_context()->ExitScope(current_site, value);
   8175     return copy_of_value;
   8176   }
   8177 
   8178   inline ContextObject* site_context() { return site_context_; }
   8179   inline Isolate* isolate() { return site_context()->isolate(); }
   8180 
   8181   inline bool copying() const { return copying_; }
   8182 
   8183  private:
   8184   ContextObject* site_context_;
   8185   const bool copying_;
   8186   const JSObject::DeepCopyHints hints_;
   8187 };
   8188 
   8189 template <class ContextObject>
   8190 MaybeHandle<JSObject> JSObjectWalkVisitor<ContextObject>::StructureWalk(
   8191     Handle<JSObject> object) {
   8192   Isolate* isolate = this->isolate();
   8193   bool copying = this->copying();
   8194   bool shallow = hints_ == JSObject::kObjectIsShallow;
   8195 
   8196   if (!shallow) {
   8197     StackLimitCheck check(isolate);
   8198 
   8199     if (check.HasOverflowed()) {
   8200       isolate->StackOverflow();
   8201       return MaybeHandle<JSObject>();
   8202     }
   8203   }
   8204 
   8205   if (object->map()->is_deprecated()) {
   8206     JSObject::MigrateInstance(object);
   8207   }
   8208 
   8209   Handle<JSObject> copy;
   8210   if (copying) {
   8211     // JSFunction objects are not allowed to be in normal boilerplates at all.
   8212     DCHECK(!object->IsJSFunction());
   8213     Handle<AllocationSite> site_to_pass;
   8214     if (site_context()->ShouldCreateMemento(object)) {
   8215       site_to_pass = site_context()->current();
   8216     }
   8217     copy = isolate->factory()->CopyJSObjectWithAllocationSite(
   8218         object, site_to_pass);
   8219   } else {
   8220     copy = object;
   8221   }
   8222 
   8223   DCHECK(copying || copy.is_identical_to(object));
   8224 
   8225   ElementsKind kind = copy->GetElementsKind();
   8226   if (copying && IsFastSmiOrObjectElementsKind(kind) &&
   8227       FixedArray::cast(copy->elements())->map() ==
   8228         isolate->heap()->fixed_cow_array_map()) {
   8229     isolate->counters()->cow_arrays_created_runtime()->Increment();
   8230   }
   8231 
   8232   if (!shallow) {
   8233     HandleScope scope(isolate);
   8234 
   8235     // Deep copy own properties.
   8236     if (copy->HasFastProperties()) {
   8237       Handle<DescriptorArray> descriptors(copy->map()->instance_descriptors());
   8238       int limit = copy->map()->NumberOfOwnDescriptors();
   8239       for (int i = 0; i < limit; i++) {
   8240         PropertyDetails details = descriptors->GetDetails(i);
   8241         if (details.type() != DATA) continue;
   8242         FieldIndex index = FieldIndex::ForDescriptor(copy->map(), i);
   8243         if (object->IsUnboxedDoubleField(index)) {
   8244           if (copying) {
   8245             double value = object->RawFastDoublePropertyAt(index);
   8246             copy->RawFastDoublePropertyAtPut(index, value);
   8247           }
   8248         } else {
   8249           Handle<Object> value(object->RawFastPropertyAt(index), isolate);
   8250           if (value->IsJSObject()) {
   8251             ASSIGN_RETURN_ON_EXCEPTION(
   8252                 isolate, value,
   8253                 VisitElementOrProperty(copy, Handle<JSObject>::cast(value)),
   8254                 JSObject);
   8255             if (copying) {
   8256               copy->FastPropertyAtPut(index, *value);
   8257             }
   8258           } else {
   8259             if (copying) {
   8260               Representation representation = details.representation();
   8261               value = Object::NewStorageFor(isolate, value, representation);
   8262               copy->FastPropertyAtPut(index, *value);
   8263             }
   8264           }
   8265         }
   8266       }
   8267     } else {
   8268       // Only deep copy fields from the object literal expression.
   8269       // In particular, don't try to copy the length attribute of
   8270       // an array.
   8271       PropertyFilter filter = static_cast<PropertyFilter>(
   8272           ONLY_WRITABLE | ONLY_ENUMERABLE | ONLY_CONFIGURABLE);
   8273       KeyAccumulator accumulator(isolate, KeyCollectionMode::kOwnOnly, filter);
   8274       accumulator.CollectOwnPropertyNames(copy, copy);
   8275       Handle<FixedArray> names = accumulator.GetKeys();
   8276       for (int i = 0; i < names->length(); i++) {
   8277         DCHECK(names->get(i)->IsName());
   8278         Handle<Name> name(Name::cast(names->get(i)));
   8279         Handle<Object> value =
   8280             JSObject::GetProperty(copy, name).ToHandleChecked();
   8281         if (value->IsJSObject()) {
   8282           Handle<JSObject> result;
   8283           ASSIGN_RETURN_ON_EXCEPTION(
   8284               isolate, result,
   8285               VisitElementOrProperty(copy, Handle<JSObject>::cast(value)),
   8286               JSObject);
   8287           if (copying) {
   8288             // Creating object copy for literals. No strict mode needed.
   8289             JSObject::SetProperty(copy, name, result, SLOPPY).Assert();
   8290           }
   8291         }
   8292       }
   8293     }
   8294 
   8295     // Deep copy own elements.
   8296     switch (kind) {
   8297       case FAST_ELEMENTS:
   8298       case FAST_HOLEY_ELEMENTS: {
   8299         Handle<FixedArray> elements(FixedArray::cast(copy->elements()));
   8300         if (elements->map() == isolate->heap()->fixed_cow_array_map()) {
   8301 #ifdef DEBUG
   8302           for (int i = 0; i < elements->length(); i++) {
   8303             DCHECK(!elements->get(i)->IsJSObject());
   8304           }
   8305 #endif
   8306         } else {
   8307           for (int i = 0; i < elements->length(); i++) {
   8308             Handle<Object> value(elements->get(i), isolate);
   8309             if (value->IsJSObject()) {
   8310               Handle<JSObject> result;
   8311               ASSIGN_RETURN_ON_EXCEPTION(
   8312                   isolate, result,
   8313                   VisitElementOrProperty(copy, Handle<JSObject>::cast(value)),
   8314                   JSObject);
   8315               if (copying) {
   8316                 elements->set(i, *result);
   8317               }
   8318             }
   8319           }
   8320         }
   8321         break;
   8322       }
   8323       case DICTIONARY_ELEMENTS: {
   8324         Handle<SeededNumberDictionary> element_dictionary(
   8325             copy->element_dictionary());
   8326         int capacity = element_dictionary->Capacity();
   8327         for (int i = 0; i < capacity; i++) {
   8328           Object* k = element_dictionary->KeyAt(i);
   8329           if (element_dictionary->IsKey(isolate, k)) {
   8330             Handle<Object> value(element_dictionary->ValueAt(i), isolate);
   8331             if (value->IsJSObject()) {
   8332               Handle<JSObject> result;
   8333               ASSIGN_RETURN_ON_EXCEPTION(
   8334                   isolate, result,
   8335                   VisitElementOrProperty(copy, Handle<JSObject>::cast(value)),
   8336                   JSObject);
   8337               if (copying) {
   8338                 element_dictionary->ValueAtPut(i, *result);
   8339               }
   8340             }
   8341           }
   8342         }
   8343         break;
   8344       }
   8345       case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
   8346       case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
   8347         UNIMPLEMENTED();
   8348         break;
   8349       case FAST_STRING_WRAPPER_ELEMENTS:
   8350       case SLOW_STRING_WRAPPER_ELEMENTS:
   8351         UNREACHABLE();
   8352         break;
   8353 
   8354 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                        \
   8355       case TYPE##_ELEMENTS:                                                    \
   8356 
   8357       TYPED_ARRAYS(TYPED_ARRAY_CASE)
   8358 #undef TYPED_ARRAY_CASE
   8359       // Typed elements cannot be created using an object literal.
   8360       UNREACHABLE();
   8361       break;
   8362 
   8363       case FAST_SMI_ELEMENTS:
   8364       case FAST_HOLEY_SMI_ELEMENTS:
   8365       case FAST_DOUBLE_ELEMENTS:
   8366       case FAST_HOLEY_DOUBLE_ELEMENTS:
   8367       case NO_ELEMENTS:
   8368         // No contained objects, nothing to do.
   8369         break;
   8370     }
   8371   }
   8372 
   8373   return copy;
   8374 }
   8375 
   8376 
   8377 MaybeHandle<JSObject> JSObject::DeepWalk(
   8378     Handle<JSObject> object,
   8379     AllocationSiteCreationContext* site_context) {
   8380   JSObjectWalkVisitor<AllocationSiteCreationContext> v(site_context, false,
   8381                                                        kNoHints);
   8382   MaybeHandle<JSObject> result = v.StructureWalk(object);
   8383   Handle<JSObject> for_assert;
   8384   DCHECK(!result.ToHandle(&for_assert) || for_assert.is_identical_to(object));
   8385   return result;
   8386 }
   8387 
   8388 
   8389 MaybeHandle<JSObject> JSObject::DeepCopy(
   8390     Handle<JSObject> object,
   8391     AllocationSiteUsageContext* site_context,
   8392     DeepCopyHints hints) {
   8393   JSObjectWalkVisitor<AllocationSiteUsageContext> v(site_context, true, hints);
   8394   MaybeHandle<JSObject> copy = v.StructureWalk(object);
   8395   Handle<JSObject> for_assert;
   8396   DCHECK(!copy.ToHandle(&for_assert) || !for_assert.is_identical_to(object));
   8397   return copy;
   8398 }
   8399 
   8400 // static
   8401 MaybeHandle<Object> JSReceiver::ToPrimitive(Handle<JSReceiver> receiver,
   8402                                             ToPrimitiveHint hint) {
   8403   Isolate* const isolate = receiver->GetIsolate();
   8404   Handle<Object> exotic_to_prim;
   8405   ASSIGN_RETURN_ON_EXCEPTION(
   8406       isolate, exotic_to_prim,
   8407       GetMethod(receiver, isolate->factory()->to_primitive_symbol()), Object);
   8408   if (!exotic_to_prim->IsUndefined(isolate)) {
   8409     Handle<Object> hint_string =
   8410         isolate->factory()->ToPrimitiveHintString(hint);
   8411     Handle<Object> result;
   8412     ASSIGN_RETURN_ON_EXCEPTION(
   8413         isolate, result,
   8414         Execution::Call(isolate, exotic_to_prim, receiver, 1, &hint_string),
   8415         Object);
   8416     if (result->IsPrimitive()) return result;
   8417     THROW_NEW_ERROR(isolate,
   8418                     NewTypeError(MessageTemplate::kCannotConvertToPrimitive),
   8419                     Object);
   8420   }
   8421   return OrdinaryToPrimitive(receiver, (hint == ToPrimitiveHint::kString)
   8422                                            ? OrdinaryToPrimitiveHint::kString
   8423                                            : OrdinaryToPrimitiveHint::kNumber);
   8424 }
   8425 
   8426 
   8427 // static
   8428 MaybeHandle<Object> JSReceiver::OrdinaryToPrimitive(
   8429     Handle<JSReceiver> receiver, OrdinaryToPrimitiveHint hint) {
   8430   Isolate* const isolate = receiver->GetIsolate();
   8431   Handle<String> method_names[2];
   8432   switch (hint) {
   8433     case OrdinaryToPrimitiveHint::kNumber:
   8434       method_names[0] = isolate->factory()->valueOf_string();
   8435       method_names[1] = isolate->factory()->toString_string();
   8436       break;
   8437     case OrdinaryToPrimitiveHint::kString:
   8438       method_names[0] = isolate->factory()->toString_string();
   8439       method_names[1] = isolate->factory()->valueOf_string();
   8440       break;
   8441   }
   8442   for (Handle<String> name : method_names) {
   8443     Handle<Object> method;
   8444     ASSIGN_RETURN_ON_EXCEPTION(isolate, method,
   8445                                JSReceiver::GetProperty(receiver, name), Object);
   8446     if (method->IsCallable()) {
   8447       Handle<Object> result;
   8448       ASSIGN_RETURN_ON_EXCEPTION(
   8449           isolate, result, Execution::Call(isolate, method, receiver, 0, NULL),
   8450           Object);
   8451       if (result->IsPrimitive()) return result;
   8452     }
   8453   }
   8454   THROW_NEW_ERROR(isolate,
   8455                   NewTypeError(MessageTemplate::kCannotConvertToPrimitive),
   8456                   Object);
   8457 }
   8458 
   8459 
   8460 // TODO(cbruni/jkummerow): Consider moving this into elements.cc.
   8461 bool JSObject::HasEnumerableElements() {
   8462   // TODO(cbruni): cleanup
   8463   JSObject* object = this;
   8464   switch (object->GetElementsKind()) {
   8465     case FAST_SMI_ELEMENTS:
   8466     case FAST_ELEMENTS:
   8467     case FAST_DOUBLE_ELEMENTS: {
   8468       int length = object->IsJSArray()
   8469                        ? Smi::cast(JSArray::cast(object)->length())->value()
   8470                        : object->elements()->length();
   8471       return length > 0;
   8472     }
   8473     case FAST_HOLEY_SMI_ELEMENTS:
   8474     case FAST_HOLEY_ELEMENTS: {
   8475       FixedArray* elements = FixedArray::cast(object->elements());
   8476       int length = object->IsJSArray()
   8477                        ? Smi::cast(JSArray::cast(object)->length())->value()
   8478                        : elements->length();
   8479       Isolate* isolate = GetIsolate();
   8480       for (int i = 0; i < length; i++) {
   8481         if (!elements->is_the_hole(isolate, i)) return true;
   8482       }
   8483       return false;
   8484     }
   8485     case FAST_HOLEY_DOUBLE_ELEMENTS: {
   8486       int length = object->IsJSArray()
   8487                        ? Smi::cast(JSArray::cast(object)->length())->value()
   8488                        : object->elements()->length();
   8489       // Zero-length arrays would use the empty FixedArray...
   8490       if (length == 0) return false;
   8491       // ...so only cast to FixedDoubleArray otherwise.
   8492       FixedDoubleArray* elements = FixedDoubleArray::cast(object->elements());
   8493       for (int i = 0; i < length; i++) {
   8494         if (!elements->is_the_hole(i)) return true;
   8495       }
   8496       return false;
   8497     }
   8498 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
   8499     case TYPE##_ELEMENTS:
   8500 
   8501       TYPED_ARRAYS(TYPED_ARRAY_CASE)
   8502 #undef TYPED_ARRAY_CASE
   8503       {
   8504         int length = object->elements()->length();
   8505         return length > 0;
   8506       }
   8507     case DICTIONARY_ELEMENTS: {
   8508       SeededNumberDictionary* elements =
   8509           SeededNumberDictionary::cast(object->elements());
   8510       return elements->NumberOfElementsFilterAttributes(ONLY_ENUMERABLE) > 0;
   8511     }
   8512     case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
   8513     case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
   8514       // We're approximating non-empty arguments objects here.
   8515       return true;
   8516     case FAST_STRING_WRAPPER_ELEMENTS:
   8517     case SLOW_STRING_WRAPPER_ELEMENTS:
   8518       if (String::cast(JSValue::cast(object)->value())->length() > 0) {
   8519         return true;
   8520       }
   8521       return object->elements()->length() > 0;
   8522     case NO_ELEMENTS:
   8523       return false;
   8524   }
   8525   UNREACHABLE();
   8526   return true;
   8527 }
   8528 
   8529 
   8530 int Map::NumberOfDescribedProperties(DescriptorFlag which,
   8531                                      PropertyFilter filter) {
   8532   int result = 0;
   8533   DescriptorArray* descs = instance_descriptors();
   8534   int limit = which == ALL_DESCRIPTORS
   8535       ? descs->number_of_descriptors()
   8536       : NumberOfOwnDescriptors();
   8537   for (int i = 0; i < limit; i++) {
   8538     if ((descs->GetDetails(i).attributes() & filter) == 0 &&
   8539         !descs->GetKey(i)->FilterKey(filter)) {
   8540       result++;
   8541     }
   8542   }
   8543   return result;
   8544 }
   8545 
   8546 
   8547 int Map::NextFreePropertyIndex() {
   8548   int free_index = 0;
   8549   int number_of_own_descriptors = NumberOfOwnDescriptors();
   8550   DescriptorArray* descs = instance_descriptors();
   8551   for (int i = 0; i < number_of_own_descriptors; i++) {
   8552     PropertyDetails details = descs->GetDetails(i);
   8553     if (details.location() == kField) {
   8554       int candidate = details.field_index() + details.field_width_in_words();
   8555       if (candidate > free_index) free_index = candidate;
   8556     }
   8557   }
   8558   return free_index;
   8559 }
   8560 
   8561 
   8562 bool Map::OnlyHasSimpleProperties() {
   8563   // Wrapped string elements aren't explicitly stored in the elements backing
   8564   // store, but are loaded indirectly from the underlying string.
   8565   return !IsStringWrapperElementsKind(elements_kind()) &&
   8566          instance_type() > LAST_SPECIAL_RECEIVER_TYPE &&
   8567          !has_hidden_prototype() && !is_dictionary_map();
   8568 }
   8569 
   8570 MUST_USE_RESULT Maybe<bool> FastGetOwnValuesOrEntries(
   8571     Isolate* isolate, Handle<JSReceiver> receiver, bool get_entries,
   8572     Handle<FixedArray>* result) {
   8573   Handle<Map> map(JSReceiver::cast(*receiver)->map(), isolate);
   8574 
   8575   if (!map->IsJSObjectMap()) return Just(false);
   8576   if (!map->OnlyHasSimpleProperties()) return Just(false);
   8577 
   8578   Handle<JSObject> object(JSObject::cast(*receiver));
   8579 
   8580   Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate);
   8581   int number_of_own_descriptors = map->NumberOfOwnDescriptors();
   8582   int number_of_own_elements =
   8583       object->GetElementsAccessor()->GetCapacity(*object, object->elements());
   8584   Handle<FixedArray> values_or_entries = isolate->factory()->NewFixedArray(
   8585       number_of_own_descriptors + number_of_own_elements);
   8586   int count = 0;
   8587 
   8588   if (object->elements() != isolate->heap()->empty_fixed_array()) {
   8589     MAYBE_RETURN(object->GetElementsAccessor()->CollectValuesOrEntries(
   8590                      isolate, object, values_or_entries, get_entries, &count,
   8591                      ENUMERABLE_STRINGS),
   8592                  Nothing<bool>());
   8593   }
   8594 
   8595   bool stable = object->map() == *map;
   8596 
   8597   for (int index = 0; index < number_of_own_descriptors; index++) {
   8598     Handle<Name> next_key(descriptors->GetKey(index), isolate);
   8599     if (!next_key->IsString()) continue;
   8600     Handle<Object> prop_value;
   8601 
   8602     // Directly decode from the descriptor array if |from| did not change shape.
   8603     if (stable) {
   8604       PropertyDetails details = descriptors->GetDetails(index);
   8605       if (!details.IsEnumerable()) continue;
   8606       if (details.kind() == kData) {
   8607         if (details.location() == kDescriptor) {
   8608           prop_value = handle(descriptors->GetValue(index), isolate);
   8609         } else {
   8610           Representation representation = details.representation();
   8611           FieldIndex field_index = FieldIndex::ForDescriptor(*map, index);
   8612           prop_value =
   8613               JSObject::FastPropertyAt(object, representation, field_index);
   8614         }
   8615       } else {
   8616         ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   8617             isolate, prop_value, JSReceiver::GetProperty(object, next_key),
   8618             Nothing<bool>());
   8619         stable = object->map() == *map;
   8620       }
   8621     } else {
   8622       // If the map did change, do a slower lookup. We are still guaranteed that
   8623       // the object has a simple shape, and that the key is a name.
   8624       LookupIterator it(object, next_key, LookupIterator::OWN_SKIP_INTERCEPTOR);
   8625       if (!it.IsFound()) continue;
   8626       DCHECK(it.state() == LookupIterator::DATA ||
   8627              it.state() == LookupIterator::ACCESSOR);
   8628       if (!it.IsEnumerable()) continue;
   8629       ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   8630           isolate, prop_value, Object::GetProperty(&it), Nothing<bool>());
   8631     }
   8632 
   8633     if (get_entries) {
   8634       prop_value = MakeEntryPair(isolate, next_key, prop_value);
   8635     }
   8636 
   8637     values_or_entries->set(count, *prop_value);
   8638     count++;
   8639   }
   8640 
   8641   if (count < values_or_entries->length()) values_or_entries->Shrink(count);
   8642   *result = values_or_entries;
   8643   return Just(true);
   8644 }
   8645 
   8646 MaybeHandle<FixedArray> GetOwnValuesOrEntries(Isolate* isolate,
   8647                                               Handle<JSReceiver> object,
   8648                                               PropertyFilter filter,
   8649                                               bool get_entries) {
   8650   Handle<FixedArray> values_or_entries;
   8651   if (filter == ENUMERABLE_STRINGS) {
   8652     Maybe<bool> fast_values_or_entries = FastGetOwnValuesOrEntries(
   8653         isolate, object, get_entries, &values_or_entries);
   8654     if (fast_values_or_entries.IsNothing()) return MaybeHandle<FixedArray>();
   8655     if (fast_values_or_entries.FromJust()) return values_or_entries;
   8656   }
   8657 
   8658   PropertyFilter key_filter =
   8659       static_cast<PropertyFilter>(filter & ~ONLY_ENUMERABLE);
   8660 
   8661   Handle<FixedArray> keys;
   8662   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   8663       isolate, keys,
   8664       KeyAccumulator::GetKeys(object, KeyCollectionMode::kOwnOnly, key_filter,
   8665                               GetKeysConversion::kConvertToString),
   8666       MaybeHandle<FixedArray>());
   8667 
   8668   values_or_entries = isolate->factory()->NewFixedArray(keys->length());
   8669   int length = 0;
   8670 
   8671   for (int i = 0; i < keys->length(); ++i) {
   8672     Handle<Name> key = Handle<Name>::cast(handle(keys->get(i), isolate));
   8673 
   8674     if (filter & ONLY_ENUMERABLE) {
   8675       PropertyDescriptor descriptor;
   8676       Maybe<bool> did_get_descriptor = JSReceiver::GetOwnPropertyDescriptor(
   8677           isolate, object, key, &descriptor);
   8678       MAYBE_RETURN(did_get_descriptor, MaybeHandle<FixedArray>());
   8679       if (!did_get_descriptor.FromJust() || !descriptor.enumerable()) continue;
   8680     }
   8681 
   8682     Handle<Object> value;
   8683     ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   8684         isolate, value, JSReceiver::GetPropertyOrElement(object, key),
   8685         MaybeHandle<FixedArray>());
   8686 
   8687     if (get_entries) {
   8688       Handle<FixedArray> entry_storage =
   8689           isolate->factory()->NewUninitializedFixedArray(2);
   8690       entry_storage->set(0, *key);
   8691       entry_storage->set(1, *value);
   8692       value = isolate->factory()->NewJSArrayWithElements(entry_storage,
   8693                                                          FAST_ELEMENTS, 2);
   8694     }
   8695 
   8696     values_or_entries->set(length, *value);
   8697     length++;
   8698   }
   8699   if (length < values_or_entries->length()) values_or_entries->Shrink(length);
   8700   return values_or_entries;
   8701 }
   8702 
   8703 MaybeHandle<FixedArray> JSReceiver::GetOwnValues(Handle<JSReceiver> object,
   8704                                                  PropertyFilter filter) {
   8705   return GetOwnValuesOrEntries(object->GetIsolate(), object, filter, false);
   8706 }
   8707 
   8708 MaybeHandle<FixedArray> JSReceiver::GetOwnEntries(Handle<JSReceiver> object,
   8709                                                   PropertyFilter filter) {
   8710   return GetOwnValuesOrEntries(object->GetIsolate(), object, filter, true);
   8711 }
   8712 
   8713 bool Map::DictionaryElementsInPrototypeChainOnly() {
   8714   if (IsDictionaryElementsKind(elements_kind())) {
   8715     return false;
   8716   }
   8717 
   8718   for (PrototypeIterator iter(this); !iter.IsAtEnd(); iter.Advance()) {
   8719     // Be conservative, don't walk into proxies.
   8720     if (iter.GetCurrent()->IsJSProxy()) return true;
   8721     // String wrappers have non-configurable, non-writable elements.
   8722     if (iter.GetCurrent()->IsStringWrapper()) return true;
   8723     JSObject* current = iter.GetCurrent<JSObject>();
   8724 
   8725     if (current->HasDictionaryElements() &&
   8726         current->element_dictionary()->requires_slow_elements()) {
   8727       return true;
   8728     }
   8729 
   8730     if (current->HasSlowArgumentsElements()) {
   8731       FixedArray* parameter_map = FixedArray::cast(current->elements());
   8732       Object* arguments = parameter_map->get(1);
   8733       if (SeededNumberDictionary::cast(arguments)->requires_slow_elements()) {
   8734         return true;
   8735       }
   8736     }
   8737   }
   8738 
   8739   return false;
   8740 }
   8741 
   8742 
   8743 MaybeHandle<Object> JSObject::DefineAccessor(Handle<JSObject> object,
   8744                                              Handle<Name> name,
   8745                                              Handle<Object> getter,
   8746                                              Handle<Object> setter,
   8747                                              PropertyAttributes attributes) {
   8748   Isolate* isolate = object->GetIsolate();
   8749 
   8750   LookupIterator it = LookupIterator::PropertyOrElement(
   8751       isolate, object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
   8752   return DefineAccessor(&it, getter, setter, attributes);
   8753 }
   8754 
   8755 
   8756 MaybeHandle<Object> JSObject::DefineAccessor(LookupIterator* it,
   8757                                              Handle<Object> getter,
   8758                                              Handle<Object> setter,
   8759                                              PropertyAttributes attributes) {
   8760   Isolate* isolate = it->isolate();
   8761 
   8762   it->UpdateProtector();
   8763 
   8764   if (it->state() == LookupIterator::ACCESS_CHECK) {
   8765     if (!it->HasAccess()) {
   8766       isolate->ReportFailedAccessCheck(it->GetHolder<JSObject>());
   8767       RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
   8768       return isolate->factory()->undefined_value();
   8769     }
   8770     it->Next();
   8771   }
   8772 
   8773   Handle<JSObject> object = Handle<JSObject>::cast(it->GetReceiver());
   8774   // Ignore accessors on typed arrays.
   8775   if (it->IsElement() && object->HasFixedTypedArrayElements()) {
   8776     return it->factory()->undefined_value();
   8777   }
   8778 
   8779   DCHECK(getter->IsCallable() || getter->IsUndefined(isolate) ||
   8780          getter->IsNull(isolate) || getter->IsFunctionTemplateInfo());
   8781   DCHECK(setter->IsCallable() || setter->IsUndefined(isolate) ||
   8782          setter->IsNull(isolate) || setter->IsFunctionTemplateInfo());
   8783   it->TransitionToAccessorProperty(getter, setter, attributes);
   8784 
   8785   return isolate->factory()->undefined_value();
   8786 }
   8787 
   8788 
   8789 MaybeHandle<Object> JSObject::SetAccessor(Handle<JSObject> object,
   8790                                           Handle<AccessorInfo> info) {
   8791   Isolate* isolate = object->GetIsolate();
   8792   Handle<Name> name(Name::cast(info->name()), isolate);
   8793 
   8794   LookupIterator it = LookupIterator::PropertyOrElement(
   8795       isolate, object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
   8796 
   8797   // Duplicate ACCESS_CHECK outside of GetPropertyAttributes for the case that
   8798   // the FailedAccessCheckCallbackFunction doesn't throw an exception.
   8799   //
   8800   // TODO(verwaest): Force throw an exception if the callback doesn't, so we can
   8801   // remove reliance on default return values.
   8802   if (it.state() == LookupIterator::ACCESS_CHECK) {
   8803     if (!it.HasAccess()) {
   8804       isolate->ReportFailedAccessCheck(object);
   8805       RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
   8806       return it.factory()->undefined_value();
   8807     }
   8808     it.Next();
   8809   }
   8810 
   8811   // Ignore accessors on typed arrays.
   8812   if (it.IsElement() && object->HasFixedTypedArrayElements()) {
   8813     return it.factory()->undefined_value();
   8814   }
   8815 
   8816   CHECK(GetPropertyAttributes(&it).IsJust());
   8817 
   8818   // ES5 forbids turning a property into an accessor if it's not
   8819   // configurable. See 8.6.1 (Table 5).
   8820   if (it.IsFound() && !it.IsConfigurable()) {
   8821     return it.factory()->undefined_value();
   8822   }
   8823 
   8824   it.TransitionToAccessorPair(info, info->property_attributes());
   8825 
   8826   return object;
   8827 }
   8828 
   8829 Object* JSObject::SlowReverseLookup(Object* value) {
   8830   if (HasFastProperties()) {
   8831     int number_of_own_descriptors = map()->NumberOfOwnDescriptors();
   8832     DescriptorArray* descs = map()->instance_descriptors();
   8833     bool value_is_number = value->IsNumber();
   8834     for (int i = 0; i < number_of_own_descriptors; i++) {
   8835       if (descs->GetType(i) == DATA) {
   8836         FieldIndex field_index = FieldIndex::ForDescriptor(map(), i);
   8837         if (IsUnboxedDoubleField(field_index)) {
   8838           if (value_is_number) {
   8839             double property = RawFastDoublePropertyAt(field_index);
   8840             if (property == value->Number()) {
   8841               return descs->GetKey(i);
   8842             }
   8843           }
   8844         } else {
   8845           Object* property = RawFastPropertyAt(field_index);
   8846           if (field_index.is_double()) {
   8847             DCHECK(property->IsMutableHeapNumber());
   8848             if (value_is_number && property->Number() == value->Number()) {
   8849               return descs->GetKey(i);
   8850             }
   8851           } else if (property == value) {
   8852             return descs->GetKey(i);
   8853           }
   8854         }
   8855       } else if (descs->GetType(i) == DATA_CONSTANT) {
   8856         if (descs->GetConstant(i) == value) {
   8857           return descs->GetKey(i);
   8858         }
   8859       }
   8860     }
   8861     return GetHeap()->undefined_value();
   8862   } else if (IsJSGlobalObject()) {
   8863     return global_dictionary()->SlowReverseLookup(value);
   8864   } else {
   8865     return property_dictionary()->SlowReverseLookup(value);
   8866   }
   8867 }
   8868 
   8869 
   8870 Handle<Map> Map::RawCopy(Handle<Map> map, int instance_size) {
   8871   Isolate* isolate = map->GetIsolate();
   8872   Handle<Map> result =
   8873       isolate->factory()->NewMap(map->instance_type(), instance_size);
   8874   Handle<Object> prototype(map->prototype(), isolate);
   8875   Map::SetPrototype(result, prototype);
   8876   result->set_constructor_or_backpointer(map->GetConstructor());
   8877   result->set_bit_field(map->bit_field());
   8878   result->set_bit_field2(map->bit_field2());
   8879   int new_bit_field3 = map->bit_field3();
   8880   new_bit_field3 = OwnsDescriptors::update(new_bit_field3, true);
   8881   new_bit_field3 = NumberOfOwnDescriptorsBits::update(new_bit_field3, 0);
   8882   new_bit_field3 = EnumLengthBits::update(new_bit_field3,
   8883                                           kInvalidEnumCacheSentinel);
   8884   new_bit_field3 = Deprecated::update(new_bit_field3, false);
   8885   if (!map->is_dictionary_map()) {
   8886     new_bit_field3 = IsUnstable::update(new_bit_field3, false);
   8887   }
   8888   result->set_bit_field3(new_bit_field3);
   8889   return result;
   8890 }
   8891 
   8892 
   8893 Handle<Map> Map::Normalize(Handle<Map> fast_map, PropertyNormalizationMode mode,
   8894                            const char* reason) {
   8895   DCHECK(!fast_map->is_dictionary_map());
   8896 
   8897   Isolate* isolate = fast_map->GetIsolate();
   8898   Handle<Object> maybe_cache(isolate->native_context()->normalized_map_cache(),
   8899                              isolate);
   8900   bool use_cache =
   8901       !fast_map->is_prototype_map() && !maybe_cache->IsUndefined(isolate);
   8902   Handle<NormalizedMapCache> cache;
   8903   if (use_cache) cache = Handle<NormalizedMapCache>::cast(maybe_cache);
   8904 
   8905   Handle<Map> new_map;
   8906   if (use_cache && cache->Get(fast_map, mode).ToHandle(&new_map)) {
   8907 #ifdef VERIFY_HEAP
   8908     if (FLAG_verify_heap) new_map->DictionaryMapVerify();
   8909 #endif
   8910 #ifdef ENABLE_SLOW_DCHECKS
   8911     if (FLAG_enable_slow_asserts) {
   8912       // The cached map should match newly created normalized map bit-by-bit,
   8913       // except for the code cache, which can contain some ics which can be
   8914       // applied to the shared map, dependent code and weak cell cache.
   8915       Handle<Map> fresh = Map::CopyNormalized(fast_map, mode);
   8916 
   8917       if (new_map->is_prototype_map()) {
   8918         // For prototype maps, the PrototypeInfo is not copied.
   8919         DCHECK(memcmp(fresh->address(), new_map->address(),
   8920                       kTransitionsOrPrototypeInfoOffset) == 0);
   8921         DCHECK(fresh->raw_transitions() == Smi::kZero);
   8922         STATIC_ASSERT(kDescriptorsOffset ==
   8923                       kTransitionsOrPrototypeInfoOffset + kPointerSize);
   8924         DCHECK(memcmp(HeapObject::RawField(*fresh, kDescriptorsOffset),
   8925                       HeapObject::RawField(*new_map, kDescriptorsOffset),
   8926                       kCodeCacheOffset - kDescriptorsOffset) == 0);
   8927       } else {
   8928         DCHECK(memcmp(fresh->address(), new_map->address(),
   8929                       Map::kCodeCacheOffset) == 0);
   8930       }
   8931       STATIC_ASSERT(Map::kDependentCodeOffset ==
   8932                     Map::kCodeCacheOffset + kPointerSize);
   8933       STATIC_ASSERT(Map::kWeakCellCacheOffset ==
   8934                     Map::kDependentCodeOffset + kPointerSize);
   8935       int offset = Map::kWeakCellCacheOffset + kPointerSize;
   8936       DCHECK(memcmp(fresh->address() + offset,
   8937                     new_map->address() + offset,
   8938                     Map::kSize - offset) == 0);
   8939     }
   8940 #endif
   8941   } else {
   8942     new_map = Map::CopyNormalized(fast_map, mode);
   8943     if (use_cache) {
   8944       cache->Set(fast_map, new_map);
   8945       isolate->counters()->maps_normalized()->Increment();
   8946     }
   8947 #if TRACE_MAPS
   8948     if (FLAG_trace_maps) {
   8949       PrintF("[TraceMaps: Normalize from= %p to= %p reason= %s ]\n",
   8950              reinterpret_cast<void*>(*fast_map),
   8951              reinterpret_cast<void*>(*new_map), reason);
   8952     }
   8953 #endif
   8954   }
   8955   fast_map->NotifyLeafMapLayoutChange();
   8956   return new_map;
   8957 }
   8958 
   8959 
   8960 Handle<Map> Map::CopyNormalized(Handle<Map> map,
   8961                                 PropertyNormalizationMode mode) {
   8962   int new_instance_size = map->instance_size();
   8963   if (mode == CLEAR_INOBJECT_PROPERTIES) {
   8964     new_instance_size -= map->GetInObjectProperties() * kPointerSize;
   8965   }
   8966 
   8967   Handle<Map> result = RawCopy(map, new_instance_size);
   8968 
   8969   if (mode != CLEAR_INOBJECT_PROPERTIES) {
   8970     result->SetInObjectProperties(map->GetInObjectProperties());
   8971   }
   8972 
   8973   result->set_dictionary_map(true);
   8974   result->set_migration_target(false);
   8975   result->set_construction_counter(kNoSlackTracking);
   8976 
   8977 #ifdef VERIFY_HEAP
   8978   if (FLAG_verify_heap) result->DictionaryMapVerify();
   8979 #endif
   8980 
   8981   return result;
   8982 }
   8983 
   8984 // Return an immutable prototype exotic object version of the input map.
   8985 // Never even try to cache it in the transition tree, as it is intended
   8986 // for the global object and its prototype chain, and excluding it saves
   8987 // memory on the map transition tree.
   8988 
   8989 // static
   8990 Handle<Map> Map::TransitionToImmutableProto(Handle<Map> map) {
   8991   Handle<Map> new_map = Map::Copy(map, "ImmutablePrototype");
   8992   new_map->set_immutable_proto(true);
   8993   return new_map;
   8994 }
   8995 
   8996 Handle<Map> Map::CopyInitialMap(Handle<Map> map, int instance_size,
   8997                                 int in_object_properties,
   8998                                 int unused_property_fields) {
   8999 #ifdef DEBUG
   9000   Isolate* isolate = map->GetIsolate();
   9001   // Strict function maps have Function as a constructor but the
   9002   // Function's initial map is a sloppy function map. Same holds for
   9003   // GeneratorFunction and its initial map.
   9004   Object* constructor = map->GetConstructor();
   9005   DCHECK(constructor->IsJSFunction());
   9006   DCHECK(*map == JSFunction::cast(constructor)->initial_map() ||
   9007          *map == *isolate->strict_function_map() ||
   9008          *map == *isolate->strict_generator_function_map());
   9009 #endif
   9010   // Initial maps must always own their descriptors and it's descriptor array
   9011   // does not contain descriptors that do not belong to the map.
   9012   DCHECK(map->owns_descriptors());
   9013   DCHECK_EQ(map->NumberOfOwnDescriptors(),
   9014             map->instance_descriptors()->number_of_descriptors());
   9015 
   9016   Handle<Map> result = RawCopy(map, instance_size);
   9017 
   9018   // Please note instance_type and instance_size are set when allocated.
   9019   result->SetInObjectProperties(in_object_properties);
   9020   result->set_unused_property_fields(unused_property_fields);
   9021 
   9022   int number_of_own_descriptors = map->NumberOfOwnDescriptors();
   9023   if (number_of_own_descriptors > 0) {
   9024     // The copy will use the same descriptors array.
   9025     result->UpdateDescriptors(map->instance_descriptors(),
   9026                               map->GetLayoutDescriptor());
   9027     result->SetNumberOfOwnDescriptors(number_of_own_descriptors);
   9028 
   9029     DCHECK_EQ(result->NumberOfFields(),
   9030               in_object_properties - unused_property_fields);
   9031   }
   9032 
   9033   return result;
   9034 }
   9035 
   9036 
   9037 Handle<Map> Map::CopyDropDescriptors(Handle<Map> map) {
   9038   Handle<Map> result = RawCopy(map, map->instance_size());
   9039 
   9040   // Please note instance_type and instance_size are set when allocated.
   9041   if (map->IsJSObjectMap()) {
   9042     result->SetInObjectProperties(map->GetInObjectProperties());
   9043     result->set_unused_property_fields(map->unused_property_fields());
   9044   }
   9045   result->ClearCodeCache(map->GetHeap());
   9046   map->NotifyLeafMapLayoutChange();
   9047   return result;
   9048 }
   9049 
   9050 
   9051 Handle<Map> Map::ShareDescriptor(Handle<Map> map,
   9052                                  Handle<DescriptorArray> descriptors,
   9053                                  Descriptor* descriptor) {
   9054   // Sanity check. This path is only to be taken if the map owns its descriptor
   9055   // array, implying that its NumberOfOwnDescriptors equals the number of
   9056   // descriptors in the descriptor array.
   9057   DCHECK_EQ(map->NumberOfOwnDescriptors(),
   9058             map->instance_descriptors()->number_of_descriptors());
   9059 
   9060   Handle<Map> result = CopyDropDescriptors(map);
   9061   Handle<Name> name = descriptor->GetKey();
   9062 
   9063   // Ensure there's space for the new descriptor in the shared descriptor array.
   9064   if (descriptors->NumberOfSlackDescriptors() == 0) {
   9065     int old_size = descriptors->number_of_descriptors();
   9066     if (old_size == 0) {
   9067       descriptors = DescriptorArray::Allocate(map->GetIsolate(), 0, 1);
   9068     } else {
   9069       int slack = SlackForArraySize(old_size, kMaxNumberOfDescriptors);
   9070       EnsureDescriptorSlack(map, slack);
   9071       descriptors = handle(map->instance_descriptors());
   9072     }
   9073   }
   9074 
   9075   Handle<LayoutDescriptor> layout_descriptor =
   9076       FLAG_unbox_double_fields
   9077           ? LayoutDescriptor::ShareAppend(map, descriptor->GetDetails())
   9078           : handle(LayoutDescriptor::FastPointerLayout(), map->GetIsolate());
   9079 
   9080   {
   9081     DisallowHeapAllocation no_gc;
   9082     descriptors->Append(descriptor);
   9083     result->InitializeDescriptors(*descriptors, *layout_descriptor);
   9084   }
   9085 
   9086   DCHECK(result->NumberOfOwnDescriptors() == map->NumberOfOwnDescriptors() + 1);
   9087   ConnectTransition(map, result, name, SIMPLE_PROPERTY_TRANSITION);
   9088 
   9089   return result;
   9090 }
   9091 
   9092 
   9093 #if TRACE_MAPS
   9094 
   9095 // static
   9096 void Map::TraceTransition(const char* what, Map* from, Map* to, Name* name) {
   9097   if (FLAG_trace_maps) {
   9098     PrintF("[TraceMaps: %s from= %p to= %p name= ", what,
   9099            reinterpret_cast<void*>(from), reinterpret_cast<void*>(to));
   9100     name->NameShortPrint();
   9101     PrintF(" ]\n");
   9102   }
   9103 }
   9104 
   9105 
   9106 // static
   9107 void Map::TraceAllTransitions(Map* map) {
   9108   Object* transitions = map->raw_transitions();
   9109   int num_transitions = TransitionArray::NumberOfTransitions(transitions);
   9110   for (int i = -0; i < num_transitions; ++i) {
   9111     Map* target = TransitionArray::GetTarget(transitions, i);
   9112     Name* key = TransitionArray::GetKey(transitions, i);
   9113     Map::TraceTransition("Transition", map, target, key);
   9114     Map::TraceAllTransitions(target);
   9115   }
   9116 }
   9117 
   9118 #endif  // TRACE_MAPS
   9119 
   9120 
   9121 void Map::ConnectTransition(Handle<Map> parent, Handle<Map> child,
   9122                             Handle<Name> name, SimpleTransitionFlag flag) {
   9123   if (!parent->GetBackPointer()->IsUndefined(parent->GetIsolate())) {
   9124     parent->set_owns_descriptors(false);
   9125   } else {
   9126     // |parent| is initial map and it must keep the ownership, there must be no
   9127     // descriptors in the descriptors array that do not belong to the map.
   9128     DCHECK(parent->owns_descriptors());
   9129     DCHECK_EQ(parent->NumberOfOwnDescriptors(),
   9130               parent->instance_descriptors()->number_of_descriptors());
   9131   }
   9132   if (parent->is_prototype_map()) {
   9133     DCHECK(child->is_prototype_map());
   9134 #if TRACE_MAPS
   9135     Map::TraceTransition("NoTransition", *parent, *child, *name);
   9136 #endif
   9137   } else {
   9138     TransitionArray::Insert(parent, name, child, flag);
   9139 #if TRACE_MAPS
   9140     Map::TraceTransition("Transition", *parent, *child, *name);
   9141 #endif
   9142   }
   9143 }
   9144 
   9145 
   9146 Handle<Map> Map::CopyReplaceDescriptors(
   9147     Handle<Map> map, Handle<DescriptorArray> descriptors,
   9148     Handle<LayoutDescriptor> layout_descriptor, TransitionFlag flag,
   9149     MaybeHandle<Name> maybe_name, const char* reason,
   9150     SimpleTransitionFlag simple_flag) {
   9151   DCHECK(descriptors->IsSortedNoDuplicates());
   9152 
   9153   Handle<Map> result = CopyDropDescriptors(map);
   9154 
   9155   if (!map->is_prototype_map()) {
   9156     if (flag == INSERT_TRANSITION &&
   9157         TransitionArray::CanHaveMoreTransitions(map)) {
   9158       result->InitializeDescriptors(*descriptors, *layout_descriptor);
   9159 
   9160       Handle<Name> name;
   9161       CHECK(maybe_name.ToHandle(&name));
   9162       ConnectTransition(map, result, name, simple_flag);
   9163     } else {
   9164       int length = descriptors->number_of_descriptors();
   9165       for (int i = 0; i < length; i++) {
   9166         descriptors->SetRepresentation(i, Representation::Tagged());
   9167         if (descriptors->GetDetails(i).type() == DATA) {
   9168           descriptors->SetValue(i, FieldType::Any());
   9169         }
   9170       }
   9171       result->InitializeDescriptors(*descriptors,
   9172                                     LayoutDescriptor::FastPointerLayout());
   9173     }
   9174   } else {
   9175     result->InitializeDescriptors(*descriptors, *layout_descriptor);
   9176   }
   9177 #if TRACE_MAPS
   9178   if (FLAG_trace_maps &&
   9179       // Mirror conditions above that did not call ConnectTransition().
   9180       (map->is_prototype_map() ||
   9181        !(flag == INSERT_TRANSITION &&
   9182          TransitionArray::CanHaveMoreTransitions(map)))) {
   9183     PrintF("[TraceMaps: ReplaceDescriptors from= %p to= %p reason= %s ]\n",
   9184            reinterpret_cast<void*>(*map), reinterpret_cast<void*>(*result),
   9185            reason);
   9186   }
   9187 #endif
   9188 
   9189   return result;
   9190 }
   9191 
   9192 
   9193 // Creates transition tree starting from |split_map| and adding all descriptors
   9194 // starting from descriptor with index |split_map|.NumberOfOwnDescriptors().
   9195 // The way how it is done is tricky because of GC and special descriptors
   9196 // marking logic.
   9197 Handle<Map> Map::AddMissingTransitions(
   9198     Handle<Map> split_map, Handle<DescriptorArray> descriptors,
   9199     Handle<LayoutDescriptor> full_layout_descriptor) {
   9200   DCHECK(descriptors->IsSortedNoDuplicates());
   9201   int split_nof = split_map->NumberOfOwnDescriptors();
   9202   int nof_descriptors = descriptors->number_of_descriptors();
   9203   DCHECK_LT(split_nof, nof_descriptors);
   9204 
   9205   // Start with creating last map which will own full descriptors array.
   9206   // This is necessary to guarantee that GC will mark the whole descriptor
   9207   // array if any of the allocations happening below fail.
   9208   // Number of unused properties is temporarily incorrect and the layout
   9209   // descriptor could unnecessarily be in slow mode but we will fix after
   9210   // all the other intermediate maps are created.
   9211   Handle<Map> last_map = CopyDropDescriptors(split_map);
   9212   last_map->InitializeDescriptors(*descriptors, *full_layout_descriptor);
   9213   last_map->set_unused_property_fields(0);
   9214 
   9215   // During creation of intermediate maps we violate descriptors sharing
   9216   // invariant since the last map is not yet connected to the transition tree
   9217   // we create here. But it is safe because GC never trims map's descriptors
   9218   // if there are no dead transitions from that map and this is exactly the
   9219   // case for all the intermediate maps we create here.
   9220   Handle<Map> map = split_map;
   9221   for (int i = split_nof; i < nof_descriptors - 1; ++i) {
   9222     Handle<Map> new_map = CopyDropDescriptors(map);
   9223     InstallDescriptors(map, new_map, i, descriptors, full_layout_descriptor);
   9224     map = new_map;
   9225   }
   9226   map->NotifyLeafMapLayoutChange();
   9227   InstallDescriptors(map, last_map, nof_descriptors - 1, descriptors,
   9228                      full_layout_descriptor);
   9229   return last_map;
   9230 }
   9231 
   9232 
   9233 // Since this method is used to rewrite an existing transition tree, it can
   9234 // always insert transitions without checking.
   9235 void Map::InstallDescriptors(Handle<Map> parent, Handle<Map> child,
   9236                              int new_descriptor,
   9237                              Handle<DescriptorArray> descriptors,
   9238                              Handle<LayoutDescriptor> full_layout_descriptor) {
   9239   DCHECK(descriptors->IsSortedNoDuplicates());
   9240 
   9241   child->set_instance_descriptors(*descriptors);
   9242   child->SetNumberOfOwnDescriptors(new_descriptor + 1);
   9243 
   9244   int unused_property_fields = parent->unused_property_fields();
   9245   PropertyDetails details = descriptors->GetDetails(new_descriptor);
   9246   if (details.location() == kField) {
   9247     unused_property_fields = parent->unused_property_fields() - 1;
   9248     if (unused_property_fields < 0) {
   9249       unused_property_fields += JSObject::kFieldsAdded;
   9250     }
   9251   }
   9252   child->set_unused_property_fields(unused_property_fields);
   9253 
   9254   if (FLAG_unbox_double_fields) {
   9255     Handle<LayoutDescriptor> layout_descriptor =
   9256         LayoutDescriptor::AppendIfFastOrUseFull(parent, details,
   9257                                                 full_layout_descriptor);
   9258     child->set_layout_descriptor(*layout_descriptor);
   9259 #ifdef VERIFY_HEAP
   9260     // TODO(ishell): remove these checks from VERIFY_HEAP mode.
   9261     if (FLAG_verify_heap) {
   9262       CHECK(child->layout_descriptor()->IsConsistentWithMap(*child));
   9263     }
   9264 #else
   9265     SLOW_DCHECK(child->layout_descriptor()->IsConsistentWithMap(*child));
   9266 #endif
   9267     child->set_visitor_id(Heap::GetStaticVisitorIdForMap(*child));
   9268   }
   9269 
   9270   Handle<Name> name = handle(descriptors->GetKey(new_descriptor));
   9271   ConnectTransition(parent, child, name, SIMPLE_PROPERTY_TRANSITION);
   9272 }
   9273 
   9274 
   9275 Handle<Map> Map::CopyAsElementsKind(Handle<Map> map, ElementsKind kind,
   9276                                     TransitionFlag flag) {
   9277   Map* maybe_elements_transition_map = NULL;
   9278   if (flag == INSERT_TRANSITION) {
   9279     // Ensure we are requested to add elements kind transition "near the root".
   9280     DCHECK_EQ(map->FindRootMap()->NumberOfOwnDescriptors(),
   9281               map->NumberOfOwnDescriptors());
   9282 
   9283     maybe_elements_transition_map = map->ElementsTransitionMap();
   9284     DCHECK(maybe_elements_transition_map == NULL ||
   9285            (maybe_elements_transition_map->elements_kind() ==
   9286                 DICTIONARY_ELEMENTS &&
   9287             kind == DICTIONARY_ELEMENTS));
   9288     DCHECK(!IsFastElementsKind(kind) ||
   9289            IsMoreGeneralElementsKindTransition(map->elements_kind(), kind));
   9290     DCHECK(kind != map->elements_kind());
   9291   }
   9292 
   9293   bool insert_transition = flag == INSERT_TRANSITION &&
   9294                            TransitionArray::CanHaveMoreTransitions(map) &&
   9295                            maybe_elements_transition_map == NULL;
   9296 
   9297   if (insert_transition) {
   9298     Handle<Map> new_map = CopyForTransition(map, "CopyAsElementsKind");
   9299     new_map->set_elements_kind(kind);
   9300 
   9301     Isolate* isolate = map->GetIsolate();
   9302     Handle<Name> name = isolate->factory()->elements_transition_symbol();
   9303     ConnectTransition(map, new_map, name, SPECIAL_TRANSITION);
   9304     return new_map;
   9305   }
   9306 
   9307   // Create a new free-floating map only if we are not allowed to store it.
   9308   Handle<Map> new_map = Copy(map, "CopyAsElementsKind");
   9309   new_map->set_elements_kind(kind);
   9310   return new_map;
   9311 }
   9312 
   9313 
   9314 Handle<Map> Map::AsLanguageMode(Handle<Map> initial_map,
   9315                                 LanguageMode language_mode, FunctionKind kind) {
   9316   DCHECK_EQ(JS_FUNCTION_TYPE, initial_map->instance_type());
   9317   // Initial map for sloppy mode function is stored in the function
   9318   // constructor. Initial maps for strict mode are cached as special transitions
   9319   // using |strict_function_transition_symbol| as a key.
   9320   if (language_mode == SLOPPY) return initial_map;
   9321   Isolate* isolate = initial_map->GetIsolate();
   9322 
   9323   int map_index = Context::FunctionMapIndex(language_mode, kind);
   9324   Handle<Map> function_map(
   9325       Map::cast(isolate->native_context()->get(map_index)));
   9326 
   9327   STATIC_ASSERT(LANGUAGE_END == 2);
   9328   DCHECK_EQ(STRICT, language_mode);
   9329   Handle<Symbol> transition_symbol =
   9330       isolate->factory()->strict_function_transition_symbol();
   9331   Map* maybe_transition =
   9332       TransitionArray::SearchSpecial(*initial_map, *transition_symbol);
   9333   if (maybe_transition != NULL) {
   9334     return handle(maybe_transition, isolate);
   9335   }
   9336   initial_map->NotifyLeafMapLayoutChange();
   9337 
   9338   // Create new map taking descriptors from the |function_map| and all
   9339   // the other details from the |initial_map|.
   9340   Handle<Map> map =
   9341       Map::CopyInitialMap(function_map, initial_map->instance_size(),
   9342                           initial_map->GetInObjectProperties(),
   9343                           initial_map->unused_property_fields());
   9344   map->SetConstructor(initial_map->GetConstructor());
   9345   map->set_prototype(initial_map->prototype());
   9346 
   9347   if (TransitionArray::CanHaveMoreTransitions(initial_map)) {
   9348     Map::ConnectTransition(initial_map, map, transition_symbol,
   9349                            SPECIAL_TRANSITION);
   9350   }
   9351   return map;
   9352 }
   9353 
   9354 
   9355 Handle<Map> Map::CopyForTransition(Handle<Map> map, const char* reason) {
   9356   DCHECK(!map->is_prototype_map());
   9357   Handle<Map> new_map = CopyDropDescriptors(map);
   9358 
   9359   if (map->owns_descriptors()) {
   9360     // In case the map owned its own descriptors, share the descriptors and
   9361     // transfer ownership to the new map.
   9362     // The properties did not change, so reuse descriptors.
   9363     new_map->InitializeDescriptors(map->instance_descriptors(),
   9364                                    map->GetLayoutDescriptor());
   9365   } else {
   9366     // In case the map did not own its own descriptors, a split is forced by
   9367     // copying the map; creating a new descriptor array cell.
   9368     Handle<DescriptorArray> descriptors(map->instance_descriptors());
   9369     int number_of_own_descriptors = map->NumberOfOwnDescriptors();
   9370     Handle<DescriptorArray> new_descriptors =
   9371         DescriptorArray::CopyUpTo(descriptors, number_of_own_descriptors);
   9372     Handle<LayoutDescriptor> new_layout_descriptor(map->GetLayoutDescriptor(),
   9373                                                    map->GetIsolate());
   9374     new_map->InitializeDescriptors(*new_descriptors, *new_layout_descriptor);
   9375   }
   9376 
   9377 #if TRACE_MAPS
   9378   if (FLAG_trace_maps) {
   9379     PrintF("[TraceMaps: CopyForTransition from= %p to= %p reason= %s ]\n",
   9380            reinterpret_cast<void*>(*map), reinterpret_cast<void*>(*new_map),
   9381            reason);
   9382   }
   9383 #endif
   9384 
   9385   return new_map;
   9386 }
   9387 
   9388 
   9389 Handle<Map> Map::Copy(Handle<Map> map, const char* reason) {
   9390   Handle<DescriptorArray> descriptors(map->instance_descriptors());
   9391   int number_of_own_descriptors = map->NumberOfOwnDescriptors();
   9392   Handle<DescriptorArray> new_descriptors =
   9393       DescriptorArray::CopyUpTo(descriptors, number_of_own_descriptors);
   9394   Handle<LayoutDescriptor> new_layout_descriptor(map->GetLayoutDescriptor(),
   9395                                                  map->GetIsolate());
   9396   return CopyReplaceDescriptors(map, new_descriptors, new_layout_descriptor,
   9397                                 OMIT_TRANSITION, MaybeHandle<Name>(), reason,
   9398                                 SPECIAL_TRANSITION);
   9399 }
   9400 
   9401 
   9402 Handle<Map> Map::Create(Isolate* isolate, int inobject_properties) {
   9403   Handle<Map> copy =
   9404       Copy(handle(isolate->object_function()->initial_map()), "MapCreate");
   9405 
   9406   // Check that we do not overflow the instance size when adding the extra
   9407   // inobject properties. If the instance size overflows, we allocate as many
   9408   // properties as we can as inobject properties.
   9409   int max_extra_properties =
   9410       (JSObject::kMaxInstanceSize - JSObject::kHeaderSize) >> kPointerSizeLog2;
   9411 
   9412   if (inobject_properties > max_extra_properties) {
   9413     inobject_properties = max_extra_properties;
   9414   }
   9415 
   9416   int new_instance_size =
   9417       JSObject::kHeaderSize + kPointerSize * inobject_properties;
   9418 
   9419   // Adjust the map with the extra inobject properties.
   9420   copy->SetInObjectProperties(inobject_properties);
   9421   copy->set_unused_property_fields(inobject_properties);
   9422   copy->set_instance_size(new_instance_size);
   9423   copy->set_visitor_id(Heap::GetStaticVisitorIdForMap(*copy));
   9424   return copy;
   9425 }
   9426 
   9427 
   9428 Handle<Map> Map::CopyForPreventExtensions(Handle<Map> map,
   9429                                           PropertyAttributes attrs_to_add,
   9430                                           Handle<Symbol> transition_marker,
   9431                                           const char* reason) {
   9432   int num_descriptors = map->NumberOfOwnDescriptors();
   9433   Isolate* isolate = map->GetIsolate();
   9434   Handle<DescriptorArray> new_desc = DescriptorArray::CopyUpToAddAttributes(
   9435       handle(map->instance_descriptors(), isolate), num_descriptors,
   9436       attrs_to_add);
   9437   Handle<LayoutDescriptor> new_layout_descriptor(map->GetLayoutDescriptor(),
   9438                                                  isolate);
   9439   Handle<Map> new_map = CopyReplaceDescriptors(
   9440       map, new_desc, new_layout_descriptor, INSERT_TRANSITION,
   9441       transition_marker, reason, SPECIAL_TRANSITION);
   9442   new_map->set_is_extensible(false);
   9443   if (!IsFixedTypedArrayElementsKind(map->elements_kind())) {
   9444     ElementsKind new_kind = IsStringWrapperElementsKind(map->elements_kind())
   9445                                 ? SLOW_STRING_WRAPPER_ELEMENTS
   9446                                 : DICTIONARY_ELEMENTS;
   9447     new_map->set_elements_kind(new_kind);
   9448   }
   9449   return new_map;
   9450 }
   9451 
   9452 FieldType* DescriptorArray::GetFieldType(int descriptor_number) {
   9453   DCHECK(GetDetails(descriptor_number).location() == kField);
   9454   Object* value = GetValue(descriptor_number);
   9455   if (value->IsWeakCell()) {
   9456     if (WeakCell::cast(value)->cleared()) return FieldType::None();
   9457     value = WeakCell::cast(value)->value();
   9458   }
   9459   return FieldType::cast(value);
   9460 }
   9461 
   9462 namespace {
   9463 
   9464 bool CanHoldValue(DescriptorArray* descriptors, int descriptor, Object* value) {
   9465   PropertyDetails details = descriptors->GetDetails(descriptor);
   9466   switch (details.type()) {
   9467     case DATA:
   9468       return value->FitsRepresentation(details.representation()) &&
   9469              descriptors->GetFieldType(descriptor)->NowContains(value);
   9470 
   9471     case DATA_CONSTANT:
   9472       DCHECK(descriptors->GetConstant(descriptor) != value ||
   9473              value->FitsRepresentation(details.representation()));
   9474       return descriptors->GetConstant(descriptor) == value;
   9475 
   9476     case ACCESSOR:
   9477     case ACCESSOR_CONSTANT:
   9478       return false;
   9479   }
   9480 
   9481   UNREACHABLE();
   9482   return false;
   9483 }
   9484 
   9485 Handle<Map> UpdateDescriptorForValue(Handle<Map> map, int descriptor,
   9486                                      Handle<Object> value) {
   9487   if (CanHoldValue(map->instance_descriptors(), descriptor, *value)) return map;
   9488 
   9489   Isolate* isolate = map->GetIsolate();
   9490   PropertyAttributes attributes =
   9491       map->instance_descriptors()->GetDetails(descriptor).attributes();
   9492   Representation representation = value->OptimalRepresentation();
   9493   Handle<FieldType> type = value->OptimalType(isolate, representation);
   9494 
   9495   return Map::ReconfigureProperty(map, descriptor, kData, attributes,
   9496                                   representation, type, FORCE_FIELD);
   9497 }
   9498 
   9499 }  // namespace
   9500 
   9501 // static
   9502 Handle<Map> Map::PrepareForDataProperty(Handle<Map> map, int descriptor,
   9503                                         Handle<Object> value) {
   9504   // Dictionaries can store any property value.
   9505   DCHECK(!map->is_dictionary_map());
   9506   // Update to the newest map before storing the property.
   9507   return UpdateDescriptorForValue(Update(map), descriptor, value);
   9508 }
   9509 
   9510 
   9511 Handle<Map> Map::TransitionToDataProperty(Handle<Map> map, Handle<Name> name,
   9512                                           Handle<Object> value,
   9513                                           PropertyAttributes attributes,
   9514                                           StoreFromKeyed store_mode) {
   9515   RuntimeCallTimerScope stats_scope(
   9516       *map, map->is_prototype_map()
   9517                 ? &RuntimeCallStats::PrototypeMap_TransitionToDataProperty
   9518                 : &RuntimeCallStats::Map_TransitionToDataProperty);
   9519 
   9520   DCHECK(name->IsUniqueName());
   9521   DCHECK(!map->is_dictionary_map());
   9522 
   9523   // Migrate to the newest map before storing the property.
   9524   map = Update(map);
   9525 
   9526   Map* maybe_transition =
   9527       TransitionArray::SearchTransition(*map, kData, *name, attributes);
   9528   if (maybe_transition != NULL) {
   9529     Handle<Map> transition(maybe_transition);
   9530     int descriptor = transition->LastAdded();
   9531 
   9532     DCHECK_EQ(attributes, transition->instance_descriptors()
   9533                               ->GetDetails(descriptor)
   9534                               .attributes());
   9535 
   9536     return UpdateDescriptorForValue(transition, descriptor, value);
   9537   }
   9538 
   9539   TransitionFlag flag = INSERT_TRANSITION;
   9540   MaybeHandle<Map> maybe_map;
   9541   if (value->IsJSFunction()) {
   9542     maybe_map = Map::CopyWithConstant(map, name, value, attributes, flag);
   9543   } else if (!map->TooManyFastProperties(store_mode)) {
   9544     Isolate* isolate = name->GetIsolate();
   9545     Representation representation = value->OptimalRepresentation();
   9546     Handle<FieldType> type = value->OptimalType(isolate, representation);
   9547     maybe_map =
   9548         Map::CopyWithField(map, name, type, attributes, representation, flag);
   9549   }
   9550 
   9551   Handle<Map> result;
   9552   if (!maybe_map.ToHandle(&result)) {
   9553 #if TRACE_MAPS
   9554     if (FLAG_trace_maps) {
   9555       Vector<char> name_buffer = Vector<char>::New(100);
   9556       name->NameShortPrint(name_buffer);
   9557       Vector<char> buffer = Vector<char>::New(128);
   9558       SNPrintF(buffer, "TooManyFastProperties %s", name_buffer.start());
   9559       return Map::Normalize(map, CLEAR_INOBJECT_PROPERTIES, buffer.start());
   9560     }
   9561 #endif
   9562     return Map::Normalize(map, CLEAR_INOBJECT_PROPERTIES,
   9563                           "TooManyFastProperties");
   9564   }
   9565 
   9566   return result;
   9567 }
   9568 
   9569 
   9570 Handle<Map> Map::ReconfigureExistingProperty(Handle<Map> map, int descriptor,
   9571                                              PropertyKind kind,
   9572                                              PropertyAttributes attributes) {
   9573   // Dictionaries have to be reconfigured in-place.
   9574   DCHECK(!map->is_dictionary_map());
   9575 
   9576   if (!map->GetBackPointer()->IsMap()) {
   9577     // There is no benefit from reconstructing transition tree for maps without
   9578     // back pointers.
   9579     return CopyGeneralizeAllRepresentations(
   9580         map, map->elements_kind(), descriptor, FORCE_FIELD, kind, attributes,
   9581         "GenAll_AttributesMismatchProtoMap");
   9582   }
   9583 
   9584   if (FLAG_trace_generalization) {
   9585     map->PrintReconfiguration(stdout, descriptor, kind, attributes);
   9586   }
   9587 
   9588   Isolate* isolate = map->GetIsolate();
   9589   Handle<Map> new_map = ReconfigureProperty(
   9590       map, descriptor, kind, attributes, Representation::None(),
   9591       FieldType::None(isolate), FORCE_FIELD);
   9592   return new_map;
   9593 }
   9594 
   9595 Handle<Map> Map::TransitionToAccessorProperty(Isolate* isolate, Handle<Map> map,
   9596                                               Handle<Name> name, int descriptor,
   9597                                               Handle<Object> getter,
   9598                                               Handle<Object> setter,
   9599                                               PropertyAttributes attributes) {
   9600   RuntimeCallTimerScope stats_scope(
   9601       isolate,
   9602       map->is_prototype_map()
   9603           ? &RuntimeCallStats::PrototypeMap_TransitionToAccessorProperty
   9604           : &RuntimeCallStats::Map_TransitionToAccessorProperty);
   9605 
   9606   // At least one of the accessors needs to be a new value.
   9607   DCHECK(!getter->IsNull(isolate) || !setter->IsNull(isolate));
   9608   DCHECK(name->IsUniqueName());
   9609 
   9610   // Dictionary maps can always have additional data properties.
   9611   if (map->is_dictionary_map()) return map;
   9612 
   9613   // Migrate to the newest map before transitioning to the new property.
   9614   map = Update(map);
   9615 
   9616   PropertyNormalizationMode mode = map->is_prototype_map()
   9617                                        ? KEEP_INOBJECT_PROPERTIES
   9618                                        : CLEAR_INOBJECT_PROPERTIES;
   9619 
   9620   Map* maybe_transition =
   9621       TransitionArray::SearchTransition(*map, kAccessor, *name, attributes);
   9622   if (maybe_transition != NULL) {
   9623     Handle<Map> transition(maybe_transition, isolate);
   9624     DescriptorArray* descriptors = transition->instance_descriptors();
   9625     int descriptor = transition->LastAdded();
   9626     DCHECK(descriptors->GetKey(descriptor)->Equals(*name));
   9627 
   9628     DCHECK_EQ(kAccessor, descriptors->GetDetails(descriptor).kind());
   9629     DCHECK_EQ(attributes, descriptors->GetDetails(descriptor).attributes());
   9630 
   9631     Handle<Object> maybe_pair(descriptors->GetValue(descriptor), isolate);
   9632     if (!maybe_pair->IsAccessorPair()) {
   9633       return Map::Normalize(map, mode, "TransitionToAccessorFromNonPair");
   9634     }
   9635 
   9636     Handle<AccessorPair> pair = Handle<AccessorPair>::cast(maybe_pair);
   9637     if (!pair->Equals(*getter, *setter)) {
   9638       return Map::Normalize(map, mode, "TransitionToDifferentAccessor");
   9639     }
   9640 
   9641     return transition;
   9642   }
   9643 
   9644   Handle<AccessorPair> pair;
   9645   DescriptorArray* old_descriptors = map->instance_descriptors();
   9646   if (descriptor != DescriptorArray::kNotFound) {
   9647     if (descriptor != map->LastAdded()) {
   9648       return Map::Normalize(map, mode, "AccessorsOverwritingNonLast");
   9649     }
   9650     PropertyDetails old_details = old_descriptors->GetDetails(descriptor);
   9651     if (old_details.type() != ACCESSOR_CONSTANT) {
   9652       return Map::Normalize(map, mode, "AccessorsOverwritingNonAccessors");
   9653     }
   9654 
   9655     if (old_details.attributes() != attributes) {
   9656       return Map::Normalize(map, mode, "AccessorsWithAttributes");
   9657     }
   9658 
   9659     Handle<Object> maybe_pair(old_descriptors->GetValue(descriptor), isolate);
   9660     if (!maybe_pair->IsAccessorPair()) {
   9661       return Map::Normalize(map, mode, "AccessorsOverwritingNonPair");
   9662     }
   9663 
   9664     Handle<AccessorPair> current_pair = Handle<AccessorPair>::cast(maybe_pair);
   9665     if (current_pair->Equals(*getter, *setter)) return map;
   9666 
   9667     bool overwriting_accessor = false;
   9668     if (!getter->IsNull(isolate) &&
   9669         !current_pair->get(ACCESSOR_GETTER)->IsNull(isolate) &&
   9670         current_pair->get(ACCESSOR_GETTER) != *getter) {
   9671       overwriting_accessor = true;
   9672     }
   9673     if (!setter->IsNull(isolate) &&
   9674         !current_pair->get(ACCESSOR_SETTER)->IsNull(isolate) &&
   9675         current_pair->get(ACCESSOR_SETTER) != *setter) {
   9676       overwriting_accessor = true;
   9677     }
   9678     if (overwriting_accessor) {
   9679       return Map::Normalize(map, mode, "AccessorsOverwritingAccessors");
   9680     }
   9681 
   9682     pair = AccessorPair::Copy(Handle<AccessorPair>::cast(maybe_pair));
   9683   } else if (map->NumberOfOwnDescriptors() >= kMaxNumberOfDescriptors ||
   9684              map->TooManyFastProperties(CERTAINLY_NOT_STORE_FROM_KEYED)) {
   9685     return Map::Normalize(map, CLEAR_INOBJECT_PROPERTIES, "TooManyAccessors");
   9686   } else {
   9687     pair = isolate->factory()->NewAccessorPair();
   9688   }
   9689 
   9690   pair->SetComponents(*getter, *setter);
   9691 
   9692   TransitionFlag flag = INSERT_TRANSITION;
   9693   AccessorConstantDescriptor new_desc(name, pair, attributes);
   9694   return Map::CopyInsertDescriptor(map, &new_desc, flag);
   9695 }
   9696 
   9697 
   9698 Handle<Map> Map::CopyAddDescriptor(Handle<Map> map,
   9699                                    Descriptor* descriptor,
   9700                                    TransitionFlag flag) {
   9701   Handle<DescriptorArray> descriptors(map->instance_descriptors());
   9702 
   9703   // Share descriptors only if map owns descriptors and it not an initial map.
   9704   if (flag == INSERT_TRANSITION && map->owns_descriptors() &&
   9705       !map->GetBackPointer()->IsUndefined(map->GetIsolate()) &&
   9706       TransitionArray::CanHaveMoreTransitions(map)) {
   9707     return ShareDescriptor(map, descriptors, descriptor);
   9708   }
   9709 
   9710   int nof = map->NumberOfOwnDescriptors();
   9711   Handle<DescriptorArray> new_descriptors =
   9712       DescriptorArray::CopyUpTo(descriptors, nof, 1);
   9713   new_descriptors->Append(descriptor);
   9714 
   9715   Handle<LayoutDescriptor> new_layout_descriptor =
   9716       FLAG_unbox_double_fields
   9717           ? LayoutDescriptor::New(map, new_descriptors, nof + 1)
   9718           : handle(LayoutDescriptor::FastPointerLayout(), map->GetIsolate());
   9719 
   9720   return CopyReplaceDescriptors(map, new_descriptors, new_layout_descriptor,
   9721                                 flag, descriptor->GetKey(), "CopyAddDescriptor",
   9722                                 SIMPLE_PROPERTY_TRANSITION);
   9723 }
   9724 
   9725 
   9726 Handle<Map> Map::CopyInsertDescriptor(Handle<Map> map,
   9727                                       Descriptor* descriptor,
   9728                                       TransitionFlag flag) {
   9729   Handle<DescriptorArray> old_descriptors(map->instance_descriptors());
   9730 
   9731   // We replace the key if it is already present.
   9732   int index = old_descriptors->SearchWithCache(map->GetIsolate(),
   9733                                                *descriptor->GetKey(), *map);
   9734   if (index != DescriptorArray::kNotFound) {
   9735     return CopyReplaceDescriptor(map, old_descriptors, descriptor, index, flag);
   9736   }
   9737   return CopyAddDescriptor(map, descriptor, flag);
   9738 }
   9739 
   9740 
   9741 Handle<DescriptorArray> DescriptorArray::CopyUpTo(
   9742     Handle<DescriptorArray> desc,
   9743     int enumeration_index,
   9744     int slack) {
   9745   return DescriptorArray::CopyUpToAddAttributes(
   9746       desc, enumeration_index, NONE, slack);
   9747 }
   9748 
   9749 
   9750 Handle<DescriptorArray> DescriptorArray::CopyUpToAddAttributes(
   9751     Handle<DescriptorArray> desc,
   9752     int enumeration_index,
   9753     PropertyAttributes attributes,
   9754     int slack) {
   9755   if (enumeration_index + slack == 0) {
   9756     return desc->GetIsolate()->factory()->empty_descriptor_array();
   9757   }
   9758 
   9759   int size = enumeration_index;
   9760 
   9761   Handle<DescriptorArray> descriptors =
   9762       DescriptorArray::Allocate(desc->GetIsolate(), size, slack);
   9763 
   9764   if (attributes != NONE) {
   9765     for (int i = 0; i < size; ++i) {
   9766       Object* value = desc->GetValue(i);
   9767       Name* key = desc->GetKey(i);
   9768       PropertyDetails details = desc->GetDetails(i);
   9769       // Bulk attribute changes never affect private properties.
   9770       if (!key->IsPrivate()) {
   9771         int mask = DONT_DELETE | DONT_ENUM;
   9772         // READ_ONLY is an invalid attribute for JS setters/getters.
   9773         if (details.type() != ACCESSOR_CONSTANT || !value->IsAccessorPair()) {
   9774           mask |= READ_ONLY;
   9775         }
   9776         details = details.CopyAddAttributes(
   9777             static_cast<PropertyAttributes>(attributes & mask));
   9778       }
   9779       Descriptor inner_desc(
   9780           handle(key), handle(value, desc->GetIsolate()), details);
   9781       descriptors->SetDescriptor(i, &inner_desc);
   9782     }
   9783   } else {
   9784     for (int i = 0; i < size; ++i) {
   9785       descriptors->CopyFrom(i, *desc);
   9786     }
   9787   }
   9788 
   9789   if (desc->number_of_descriptors() != enumeration_index) descriptors->Sort();
   9790 
   9791   return descriptors;
   9792 }
   9793 
   9794 
   9795 bool DescriptorArray::IsEqualUpTo(DescriptorArray* desc, int nof_descriptors) {
   9796   for (int i = 0; i < nof_descriptors; i++) {
   9797     if (GetKey(i) != desc->GetKey(i) || GetValue(i) != desc->GetValue(i)) {
   9798       return false;
   9799     }
   9800     PropertyDetails details = GetDetails(i);
   9801     PropertyDetails other_details = desc->GetDetails(i);
   9802     if (details.type() != other_details.type() ||
   9803         !details.representation().Equals(other_details.representation())) {
   9804       return false;
   9805     }
   9806   }
   9807   return true;
   9808 }
   9809 
   9810 
   9811 Handle<Map> Map::CopyReplaceDescriptor(Handle<Map> map,
   9812                                        Handle<DescriptorArray> descriptors,
   9813                                        Descriptor* descriptor,
   9814                                        int insertion_index,
   9815                                        TransitionFlag flag) {
   9816   Handle<Name> key = descriptor->GetKey();
   9817   DCHECK(*key == descriptors->GetKey(insertion_index));
   9818 
   9819   Handle<DescriptorArray> new_descriptors = DescriptorArray::CopyUpTo(
   9820       descriptors, map->NumberOfOwnDescriptors());
   9821 
   9822   new_descriptors->Replace(insertion_index, descriptor);
   9823   Handle<LayoutDescriptor> new_layout_descriptor = LayoutDescriptor::New(
   9824       map, new_descriptors, new_descriptors->number_of_descriptors());
   9825 
   9826   SimpleTransitionFlag simple_flag =
   9827       (insertion_index == descriptors->number_of_descriptors() - 1)
   9828           ? SIMPLE_PROPERTY_TRANSITION
   9829           : PROPERTY_TRANSITION;
   9830   return CopyReplaceDescriptors(map, new_descriptors, new_layout_descriptor,
   9831                                 flag, key, "CopyReplaceDescriptor",
   9832                                 simple_flag);
   9833 }
   9834 
   9835 // Helper class to manage a Map's code cache. The layout depends on the number
   9836 // of entries; this is worthwhile because most code caches are very small,
   9837 // but some are huge (thousands of entries).
   9838 // For zero entries, the EmptyFixedArray is used.
   9839 // For one entry, we use a 2-element FixedArray containing [name, code].
   9840 // For 2..100 entries, we use a FixedArray with linear lookups, the layout is:
   9841 //   [0] - number of slots that are currently in use
   9842 //   [1] - first name
   9843 //   [2] - first code
   9844 //   [3] - second name
   9845 //   [4] - second code
   9846 //   etc.
   9847 // For more than 128 entries, we use a CodeCacheHashTable.
   9848 class CodeCache : public AllStatic {
   9849  public:
   9850   // Returns the new cache, to be stored on the map.
   9851   static Handle<FixedArray> Put(Isolate* isolate, Handle<FixedArray> cache,
   9852                                 Handle<Name> name, Handle<Code> code) {
   9853     int length = cache->length();
   9854     if (length == 0) return PutFirstElement(isolate, name, code);
   9855     if (length == kEntrySize) {
   9856       return PutSecondElement(isolate, cache, name, code);
   9857     }
   9858     if (length <= kLinearMaxSize) {
   9859       Handle<FixedArray> result = PutLinearElement(isolate, cache, name, code);
   9860       if (!result.is_null()) return result;
   9861       // Fall through if linear storage is getting too large.
   9862     }
   9863     return PutHashTableElement(isolate, cache, name, code);
   9864   }
   9865 
   9866   static Code* Lookup(FixedArray* cache, Name* name, Code::Flags flags) {
   9867     int length = cache->length();
   9868     if (length == 0) return nullptr;
   9869     if (length == kEntrySize) return OneElementLookup(cache, name, flags);
   9870     if (!cache->IsCodeCacheHashTable()) {
   9871       return LinearLookup(cache, name, flags);
   9872     } else {
   9873       return CodeCacheHashTable::cast(cache)->Lookup(name, flags);
   9874     }
   9875   }
   9876 
   9877  private:
   9878   static const int kNameIndex = 0;
   9879   static const int kCodeIndex = 1;
   9880   static const int kEntrySize = 2;
   9881 
   9882   static const int kLinearUsageIndex = 0;
   9883   static const int kLinearReservedSlots = 1;
   9884   static const int kLinearInitialCapacity = 2;
   9885   static const int kLinearMaxSize = 257;  // == LinearSizeFor(128);
   9886 
   9887   static const int kHashTableInitialCapacity = 200;  // Number of entries.
   9888 
   9889   static int LinearSizeFor(int entries) {
   9890     return kLinearReservedSlots + kEntrySize * entries;
   9891   }
   9892 
   9893   static int LinearNewSize(int old_size) {
   9894     int old_entries = (old_size - kLinearReservedSlots) / kEntrySize;
   9895     return LinearSizeFor(old_entries * 2);
   9896   }
   9897 
   9898   static Code* OneElementLookup(FixedArray* cache, Name* name,
   9899                                 Code::Flags flags) {
   9900     DCHECK_EQ(cache->length(), kEntrySize);
   9901     if (cache->get(kNameIndex) != name) return nullptr;
   9902     Code* maybe_code = Code::cast(cache->get(kCodeIndex));
   9903     if (maybe_code->flags() != flags) return nullptr;
   9904     return maybe_code;
   9905   }
   9906 
   9907   static Code* LinearLookup(FixedArray* cache, Name* name, Code::Flags flags) {
   9908     DCHECK_GE(cache->length(), kEntrySize);
   9909     DCHECK(!cache->IsCodeCacheHashTable());
   9910     int usage = GetLinearUsage(cache);
   9911     for (int i = kLinearReservedSlots; i < usage; i += kEntrySize) {
   9912       if (cache->get(i + kNameIndex) != name) continue;
   9913       Code* code = Code::cast(cache->get(i + kCodeIndex));
   9914       if (code->flags() == flags) return code;
   9915     }
   9916     return nullptr;
   9917   }
   9918 
   9919   static Handle<FixedArray> PutFirstElement(Isolate* isolate, Handle<Name> name,
   9920                                             Handle<Code> code) {
   9921     Handle<FixedArray> cache = isolate->factory()->NewFixedArray(kEntrySize);
   9922     cache->set(kNameIndex, *name);
   9923     cache->set(kCodeIndex, *code);
   9924     return cache;
   9925   }
   9926 
   9927   static Handle<FixedArray> PutSecondElement(Isolate* isolate,
   9928                                              Handle<FixedArray> cache,
   9929                                              Handle<Name> name,
   9930                                              Handle<Code> code) {
   9931     DCHECK_EQ(cache->length(), kEntrySize);
   9932     Handle<FixedArray> new_cache = isolate->factory()->NewFixedArray(
   9933         LinearSizeFor(kLinearInitialCapacity));
   9934     new_cache->set(kLinearReservedSlots + kNameIndex, cache->get(kNameIndex));
   9935     new_cache->set(kLinearReservedSlots + kCodeIndex, cache->get(kCodeIndex));
   9936     new_cache->set(LinearSizeFor(1) + kNameIndex, *name);
   9937     new_cache->set(LinearSizeFor(1) + kCodeIndex, *code);
   9938     new_cache->set(kLinearUsageIndex, Smi::FromInt(LinearSizeFor(2)));
   9939     return new_cache;
   9940   }
   9941 
   9942   static Handle<FixedArray> PutLinearElement(Isolate* isolate,
   9943                                              Handle<FixedArray> cache,
   9944                                              Handle<Name> name,
   9945                                              Handle<Code> code) {
   9946     int length = cache->length();
   9947     int usage = GetLinearUsage(*cache);
   9948     DCHECK_LE(usage, length);
   9949     // Check if we need to grow.
   9950     if (usage == length) {
   9951       int new_length = LinearNewSize(length);
   9952       if (new_length > kLinearMaxSize) return Handle<FixedArray>::null();
   9953       Handle<FixedArray> new_cache =
   9954           isolate->factory()->NewFixedArray(new_length);
   9955       for (int i = kLinearReservedSlots; i < length; i++) {
   9956         new_cache->set(i, cache->get(i));
   9957       }
   9958       cache = new_cache;
   9959     }
   9960     // Store new entry.
   9961     DCHECK_GE(cache->length(), usage + kEntrySize);
   9962     cache->set(usage + kNameIndex, *name);
   9963     cache->set(usage + kCodeIndex, *code);
   9964     cache->set(kLinearUsageIndex, Smi::FromInt(usage + kEntrySize));
   9965     return cache;
   9966   }
   9967 
   9968   static Handle<FixedArray> PutHashTableElement(Isolate* isolate,
   9969                                                 Handle<FixedArray> cache,
   9970                                                 Handle<Name> name,
   9971                                                 Handle<Code> code) {
   9972     // Check if we need to transition from linear to hash table storage.
   9973     if (!cache->IsCodeCacheHashTable()) {
   9974       // Check that the initial hash table capacity is large enough.
   9975       DCHECK_EQ(kLinearMaxSize, LinearSizeFor(128));
   9976       STATIC_ASSERT(kHashTableInitialCapacity > 128);
   9977 
   9978       int length = cache->length();
   9979       // Only migrate from linear storage when it's full.
   9980       DCHECK_EQ(length, GetLinearUsage(*cache));
   9981       DCHECK_EQ(length, kLinearMaxSize);
   9982       Handle<CodeCacheHashTable> table =
   9983           CodeCacheHashTable::New(isolate, kHashTableInitialCapacity);
   9984       HandleScope scope(isolate);
   9985       for (int i = kLinearReservedSlots; i < length; i += kEntrySize) {
   9986         Handle<Name> old_name(Name::cast(cache->get(i + kNameIndex)), isolate);
   9987         Handle<Code> old_code(Code::cast(cache->get(i + kCodeIndex)), isolate);
   9988         CodeCacheHashTable::Put(table, old_name, old_code);
   9989       }
   9990       cache = table;
   9991     }
   9992     // Store new entry.
   9993     DCHECK(cache->IsCodeCacheHashTable());
   9994     return CodeCacheHashTable::Put(Handle<CodeCacheHashTable>::cast(cache),
   9995                                    name, code);
   9996   }
   9997 
   9998   static inline int GetLinearUsage(FixedArray* linear_cache) {
   9999     DCHECK_GT(linear_cache->length(), kEntrySize);
   10000     return Smi::cast(linear_cache->get(kLinearUsageIndex))->value();
   10001   }
   10002 };
   10003 
   10004 void Map::UpdateCodeCache(Handle<Map> map,
   10005                           Handle<Name> name,
   10006                           Handle<Code> code) {
   10007   Isolate* isolate = map->GetIsolate();
   10008   Handle<FixedArray> cache(map->code_cache(), isolate);
   10009   Handle<FixedArray> new_cache = CodeCache::Put(isolate, cache, name, code);
   10010   map->set_code_cache(*new_cache);
   10011 }
   10012 
   10013 Code* Map::LookupInCodeCache(Name* name, Code::Flags flags) {
   10014   return CodeCache::Lookup(code_cache(), name, flags);
   10015 }
   10016 
   10017 
   10018 // The key in the code cache hash table consists of the property name and the
   10019 // code object. The actual match is on the name and the code flags. If a key
   10020 // is created using the flags and not a code object it can only be used for
   10021 // lookup not to create a new entry.
   10022 class CodeCacheHashTableKey : public HashTableKey {
   10023  public:
   10024   CodeCacheHashTableKey(Handle<Name> name, Code::Flags flags)
   10025       : name_(name), flags_(flags), code_() {
   10026     DCHECK(name_->IsUniqueName());
   10027   }
   10028 
   10029   CodeCacheHashTableKey(Handle<Name> name, Handle<Code> code)
   10030       : name_(name), flags_(code->flags()), code_(code) {
   10031     DCHECK(name_->IsUniqueName());
   10032   }
   10033 
   10034   bool IsMatch(Object* other) override {
   10035     DCHECK(other->IsFixedArray());
   10036     FixedArray* pair = FixedArray::cast(other);
   10037     Name* name = Name::cast(pair->get(0));
   10038     Code::Flags flags = Code::cast(pair->get(1))->flags();
   10039     if (flags != flags_) return false;
   10040     DCHECK(name->IsUniqueName());
   10041     return *name_ == name;
   10042   }
   10043 
   10044   static uint32_t NameFlagsHashHelper(Name* name, Code::Flags flags) {
   10045     return name->Hash() ^ flags;
   10046   }
   10047 
   10048   uint32_t Hash() override { return NameFlagsHashHelper(*name_, flags_); }
   10049 
   10050   uint32_t HashForObject(Object* obj) override {
   10051     FixedArray* pair = FixedArray::cast(obj);
   10052     Name* name = Name::cast(pair->get(0));
   10053     Code* code = Code::cast(pair->get(1));
   10054     return NameFlagsHashHelper(name, code->flags());
   10055   }
   10056 
   10057   MUST_USE_RESULT Handle<Object> AsHandle(Isolate* isolate) override {
   10058     Handle<Code> code = code_.ToHandleChecked();
   10059     Handle<FixedArray> pair = isolate->factory()->NewFixedArray(2);
   10060     pair->set(0, *name_);
   10061     pair->set(1, *code);
   10062     return pair;
   10063   }
   10064 
   10065  private:
   10066   Handle<Name> name_;
   10067   Code::Flags flags_;
   10068   // TODO(jkummerow): We should be able to get by without this.
   10069   MaybeHandle<Code> code_;
   10070 };
   10071 
   10072 
   10073 Handle<CodeCacheHashTable> CodeCacheHashTable::Put(
   10074     Handle<CodeCacheHashTable> cache, Handle<Name> name, Handle<Code> code) {
   10075   CodeCacheHashTableKey key(name, code);
   10076 
   10077   Handle<CodeCacheHashTable> new_cache = EnsureCapacity(cache, 1, &key);
   10078 
   10079   int entry = new_cache->FindInsertionEntry(key.Hash());
   10080   Handle<Object> k = key.AsHandle(cache->GetIsolate());
   10081 
   10082   new_cache->set(EntryToIndex(entry), *k);
   10083   new_cache->ElementAdded();
   10084   return new_cache;
   10085 }
   10086 
   10087 Code* CodeCacheHashTable::Lookup(Name* name, Code::Flags flags) {
   10088   DisallowHeapAllocation no_alloc;
   10089   CodeCacheHashTableKey key(handle(name), flags);
   10090   int entry = FindEntry(&key);
   10091   if (entry == kNotFound) return nullptr;
   10092   return Code::cast(FixedArray::cast(get(EntryToIndex(entry)))->get(1));
   10093 }
   10094 
   10095 Handle<FixedArray> FixedArray::SetAndGrow(Handle<FixedArray> array, int index,
   10096                                           Handle<Object> value) {
   10097   if (index < array->length()) {
   10098     array->set(index, *value);
   10099     return array;
   10100   }
   10101   int capacity = array->length();
   10102   do {
   10103     capacity = JSObject::NewElementsCapacity(capacity);
   10104   } while (capacity <= index);
   10105   Handle<FixedArray> new_array =
   10106       array->GetIsolate()->factory()->NewUninitializedFixedArray(capacity);
   10107   array->CopyTo(0, *new_array, 0, array->length());
   10108   new_array->FillWithHoles(array->length(), new_array->length());
   10109   new_array->set(index, *value);
   10110   return new_array;
   10111 }
   10112 
   10113 void FixedArray::Shrink(int new_length) {
   10114   DCHECK(0 <= new_length && new_length <= length());
   10115   if (new_length < length()) {
   10116     GetHeap()->RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>(
   10117         this, length() - new_length);
   10118   }
   10119 }
   10120 
   10121 
   10122 void FixedArray::CopyTo(int pos, FixedArray* dest, int dest_pos, int len) {
   10123   DisallowHeapAllocation no_gc;
   10124   WriteBarrierMode mode = dest->GetWriteBarrierMode(no_gc);
   10125   for (int index = 0; index < len; index++) {
   10126     dest->set(dest_pos+index, get(pos+index), mode);
   10127   }
   10128 }
   10129 
   10130 
   10131 #ifdef DEBUG
   10132 bool FixedArray::IsEqualTo(FixedArray* other) {
   10133   if (length() != other->length()) return false;
   10134   for (int i = 0 ; i < length(); ++i) {
   10135     if (get(i) != other->get(i)) return false;
   10136   }
   10137   return true;
   10138 }
   10139 #endif
   10140 
   10141 
   10142 // static
   10143 void WeakFixedArray::Set(Handle<WeakFixedArray> array, int index,
   10144                          Handle<HeapObject> value) {
   10145   DCHECK(array->IsEmptySlot(index));  // Don't overwrite anything.
   10146   Handle<WeakCell> cell =
   10147       value->IsMap() ? Map::WeakCellForMap(Handle<Map>::cast(value))
   10148                      : array->GetIsolate()->factory()->NewWeakCell(value);
   10149   Handle<FixedArray>::cast(array)->set(index + kFirstIndex, *cell);
   10150   if (FLAG_trace_weak_arrays) {
   10151     PrintF("[WeakFixedArray: storing at index %d ]\n", index);
   10152   }
   10153   array->set_last_used_index(index);
   10154 }
   10155 
   10156 
   10157 // static
   10158 Handle<WeakFixedArray> WeakFixedArray::Add(Handle<Object> maybe_array,
   10159                                            Handle<HeapObject> value,
   10160                                            int* assigned_index) {
   10161   Handle<WeakFixedArray> array =
   10162       (maybe_array.is_null() || !maybe_array->IsWeakFixedArray())
   10163           ? Allocate(value->GetIsolate(), 1, Handle<WeakFixedArray>::null())
   10164           : Handle<WeakFixedArray>::cast(maybe_array);
   10165   // Try to store the new entry if there's room. Optimize for consecutive
   10166   // accesses.
   10167   int first_index = array->last_used_index();
   10168   int length = array->Length();
   10169   if (length > 0) {
   10170     for (int i = first_index;;) {
   10171       if (array->IsEmptySlot((i))) {
   10172         WeakFixedArray::Set(array, i, value);
   10173         if (assigned_index != NULL) *assigned_index = i;
   10174         return array;
   10175       }
   10176       if (FLAG_trace_weak_arrays) {
   10177         PrintF("[WeakFixedArray: searching for free slot]\n");
   10178       }
   10179       i = (i + 1) % length;
   10180       if (i == first_index) break;
   10181     }
   10182   }
   10183 
   10184   // No usable slot found, grow the array.
   10185   int new_length = length == 0 ? 1 : length + (length >> 1) + 4;
   10186   Handle<WeakFixedArray> new_array =
   10187       Allocate(array->GetIsolate(), new_length, array);
   10188   if (FLAG_trace_weak_arrays) {
   10189     PrintF("[WeakFixedArray: growing to size %d ]\n", new_length);
   10190   }
   10191   WeakFixedArray::Set(new_array, length, value);
   10192   if (assigned_index != NULL) *assigned_index = length;
   10193   return new_array;
   10194 }
   10195 
   10196 
   10197 template <class CompactionCallback>
   10198 void WeakFixedArray::Compact() {
   10199   FixedArray* array = FixedArray::cast(this);
   10200   int new_length = kFirstIndex;
   10201   for (int i = kFirstIndex; i < array->length(); i++) {
   10202     Object* element = array->get(i);
   10203     if (element->IsSmi()) continue;
   10204     if (WeakCell::cast(element)->cleared()) continue;
   10205     Object* value = WeakCell::cast(element)->value();
   10206     CompactionCallback::Callback(value, i - kFirstIndex,
   10207                                  new_length - kFirstIndex);
   10208     array->set(new_length++, element);
   10209   }
   10210   array->Shrink(new_length);
   10211   set_last_used_index(0);
   10212 }
   10213 
   10214 
   10215 void WeakFixedArray::Iterator::Reset(Object* maybe_array) {
   10216   if (maybe_array->IsWeakFixedArray()) {
   10217     list_ = WeakFixedArray::cast(maybe_array);
   10218     index_ = 0;
   10219 #ifdef DEBUG
   10220     last_used_index_ = list_->last_used_index();
   10221 #endif  // DEBUG
   10222   }
   10223 }
   10224 
   10225 
   10226 void JSObject::PrototypeRegistryCompactionCallback::Callback(Object* value,
   10227                                                              int old_index,
   10228                                                              int new_index) {
   10229   DCHECK(value->IsMap() && Map::cast(value)->is_prototype_map());
   10230   Map* map = Map::cast(value);
   10231   DCHECK(map->prototype_info()->IsPrototypeInfo());
   10232   PrototypeInfo* proto_info = PrototypeInfo::cast(map->prototype_info());
   10233   DCHECK_EQ(old_index, proto_info->registry_slot());
   10234   proto_info->set_registry_slot(new_index);
   10235 }
   10236 
   10237 
   10238 template void WeakFixedArray::Compact<WeakFixedArray::NullCallback>();
   10239 template void
   10240 WeakFixedArray::Compact<JSObject::PrototypeRegistryCompactionCallback>();
   10241 
   10242 
   10243 bool WeakFixedArray::Remove(Handle<HeapObject> value) {
   10244   if (Length() == 0) return false;
   10245   // Optimize for the most recently added element to be removed again.
   10246   int first_index = last_used_index();
   10247   for (int i = first_index;;) {
   10248     if (Get(i) == *value) {
   10249       Clear(i);
   10250       // Users of WeakFixedArray should make sure that there are no duplicates.
   10251       return true;
   10252     }
   10253     i = (i + 1) % Length();
   10254     if (i == first_index) return false;
   10255   }
   10256   UNREACHABLE();
   10257 }
   10258 
   10259 
   10260 // static
   10261 Handle<WeakFixedArray> WeakFixedArray::Allocate(
   10262     Isolate* isolate, int size, Handle<WeakFixedArray> initialize_from) {
   10263   DCHECK(0 <= size);
   10264   Handle<FixedArray> result =
   10265       isolate->factory()->NewUninitializedFixedArray(size + kFirstIndex);
   10266   int index = 0;
   10267   if (!initialize_from.is_null()) {
   10268     DCHECK(initialize_from->Length() <= size);
   10269     Handle<FixedArray> raw_source = Handle<FixedArray>::cast(initialize_from);
   10270     // Copy the entries without compacting, since the PrototypeInfo relies on
   10271     // the index of the entries not to change.
   10272     while (index < raw_source->length()) {
   10273       result->set(index, raw_source->get(index));
   10274       index++;
   10275     }
   10276   }
   10277   while (index < result->length()) {
   10278     result->set(index, Smi::kZero);
   10279     index++;
   10280   }
   10281   return Handle<WeakFixedArray>::cast(result);
   10282 }
   10283 
   10284 
   10285 Handle<ArrayList> ArrayList::Add(Handle<ArrayList> array, Handle<Object> obj,
   10286                                  AddMode mode) {
   10287   int length = array->Length();
   10288   array = EnsureSpace(array, length + 1);
   10289   if (mode == kReloadLengthAfterAllocation) {
   10290     DCHECK(array->Length() <= length);
   10291     length = array->Length();
   10292   }
   10293   array->Set(length, *obj);
   10294   array->SetLength(length + 1);
   10295   return array;
   10296 }
   10297 
   10298 Handle<ArrayList> ArrayList::Add(Handle<ArrayList> array, Handle<Object> obj1,
   10299                                  Handle<Object> obj2, AddMode mode) {
   10300   int length = array->Length();
   10301   array = EnsureSpace(array, length + 2);
   10302   if (mode == kReloadLengthAfterAllocation) {
   10303     length = array->Length();
   10304   }
   10305   array->Set(length, *obj1);
   10306   array->Set(length + 1, *obj2);
   10307   array->SetLength(length + 2);
   10308   return array;
   10309 }
   10310 
   10311 
   10312 bool ArrayList::IsFull() {
   10313   int capacity = length();
   10314   return kFirstIndex + Length() == capacity;
   10315 }
   10316 
   10317 namespace {
   10318 
   10319 Handle<FixedArray> EnsureSpaceInFixedArray(Handle<FixedArray> array,
   10320                                            int length) {
   10321   int capacity = array->length();
   10322   if (capacity < length) {
   10323     Isolate* isolate = array->GetIsolate();
   10324     int new_capacity = length;
   10325     new_capacity = new_capacity + Max(new_capacity / 2, 2);
   10326     int grow_by = new_capacity - capacity;
   10327     array = Handle<ArrayList>::cast(
   10328         isolate->factory()->CopyFixedArrayAndGrow(array, grow_by));
   10329   }
   10330   return array;
   10331 }
   10332 
   10333 }  // namespace
   10334 
   10335 Handle<ArrayList> ArrayList::EnsureSpace(Handle<ArrayList> array, int length) {
   10336   const bool empty = (array->length() == 0);
   10337   auto ret = Handle<ArrayList>::cast(
   10338       EnsureSpaceInFixedArray(array, kFirstIndex + length));
   10339   if (empty) ret->SetLength(0);
   10340   return ret;
   10341 }
   10342 
   10343 Handle<RegExpMatchInfo> RegExpMatchInfo::ReserveCaptures(
   10344     Handle<RegExpMatchInfo> match_info, int capture_count) {
   10345   DCHECK_GE(match_info->length(), kLastMatchOverhead);
   10346   const int required_length = kFirstCaptureIndex + capture_count;
   10347   Handle<FixedArray> result =
   10348       EnsureSpaceInFixedArray(match_info, required_length);
   10349   return Handle<RegExpMatchInfo>::cast(result);
   10350 }
   10351 
   10352 // static
   10353 Handle<FrameArray> FrameArray::AppendJSFrame(Handle<FrameArray> in,
   10354                                              Handle<Object> receiver,
   10355                                              Handle<JSFunction> function,
   10356                                              Handle<AbstractCode> code,
   10357                                              int offset, int flags) {
   10358   const int frame_count = in->FrameCount();
   10359   const int new_length = LengthFor(frame_count + 1);
   10360   Handle<FrameArray> array = EnsureSpace(in, new_length);
   10361   array->SetReceiver(frame_count, *receiver);
   10362   array->SetFunction(frame_count, *function);
   10363   array->SetCode(frame_count, *code);
   10364   array->SetOffset(frame_count, Smi::FromInt(offset));
   10365   array->SetFlags(frame_count, Smi::FromInt(flags));
   10366   array->set(kFrameCountIndex, Smi::FromInt(frame_count + 1));
   10367   return array;
   10368 }
   10369 
   10370 // static
   10371 Handle<FrameArray> FrameArray::AppendWasmFrame(Handle<FrameArray> in,
   10372                                                Handle<Object> wasm_instance,
   10373                                                int wasm_function_index,
   10374                                                Handle<AbstractCode> code,
   10375                                                int offset, int flags) {
   10376   const int frame_count = in->FrameCount();
   10377   const int new_length = LengthFor(frame_count + 1);
   10378   Handle<FrameArray> array = EnsureSpace(in, new_length);
   10379   array->SetWasmInstance(frame_count, *wasm_instance);
   10380   array->SetWasmFunctionIndex(frame_count, Smi::FromInt(wasm_function_index));
   10381   array->SetCode(frame_count, *code);
   10382   array->SetOffset(frame_count, Smi::FromInt(offset));
   10383   array->SetFlags(frame_count, Smi::FromInt(flags));
   10384   array->set(kFrameCountIndex, Smi::FromInt(frame_count + 1));
   10385   return array;
   10386 }
   10387 
   10388 void FrameArray::ShrinkToFit() { Shrink(LengthFor(FrameCount())); }
   10389 
   10390 // static
   10391 Handle<FrameArray> FrameArray::EnsureSpace(Handle<FrameArray> array,
   10392                                            int length) {
   10393   return Handle<FrameArray>::cast(EnsureSpaceInFixedArray(array, length));
   10394 }
   10395 
   10396 Handle<DescriptorArray> DescriptorArray::Allocate(Isolate* isolate,
   10397                                                   int number_of_descriptors,
   10398                                                   int slack,
   10399                                                   PretenureFlag pretenure) {
   10400   DCHECK(0 <= number_of_descriptors);
   10401   Factory* factory = isolate->factory();
   10402   // Do not use DescriptorArray::cast on incomplete object.
   10403   int size = number_of_descriptors + slack;
   10404   if (size == 0) return factory->empty_descriptor_array();
   10405   // Allocate the array of keys.
   10406   Handle<FixedArray> result =
   10407       factory->NewFixedArray(LengthFor(size), pretenure);
   10408 
   10409   result->set(kDescriptorLengthIndex, Smi::FromInt(number_of_descriptors));
   10410   result->set(kEnumCacheIndex, Smi::kZero);
   10411   return Handle<DescriptorArray>::cast(result);
   10412 }
   10413 
   10414 void DescriptorArray::ClearEnumCache() { set(kEnumCacheIndex, Smi::kZero); }
   10415 
   10416 void DescriptorArray::Replace(int index, Descriptor* descriptor) {
   10417   descriptor->SetSortedKeyIndex(GetSortedKeyIndex(index));
   10418   Set(index, descriptor);
   10419 }
   10420 
   10421 
   10422 // static
   10423 void DescriptorArray::SetEnumCache(Handle<DescriptorArray> descriptors,
   10424                                    Isolate* isolate,
   10425                                    Handle<FixedArray> new_cache,
   10426                                    Handle<FixedArray> new_index_cache) {
   10427   DCHECK(!descriptors->IsEmpty());
   10428   FixedArray* bridge_storage;
   10429   bool needs_new_enum_cache = !descriptors->HasEnumCache();
   10430   if (needs_new_enum_cache) {
   10431     bridge_storage = *isolate->factory()->NewFixedArray(
   10432         DescriptorArray::kEnumCacheBridgeLength);
   10433   } else {
   10434     bridge_storage = FixedArray::cast(descriptors->get(kEnumCacheIndex));
   10435   }
   10436   bridge_storage->set(kEnumCacheBridgeCacheIndex, *new_cache);
   10437   bridge_storage->set(
   10438       kEnumCacheBridgeIndicesCacheIndex,
   10439       new_index_cache.is_null() ? Object::cast(Smi::kZero) : *new_index_cache);
   10440   if (needs_new_enum_cache) {
   10441     descriptors->set(kEnumCacheIndex, bridge_storage);
   10442   }
   10443 }
   10444 
   10445 
   10446 void DescriptorArray::CopyFrom(int index, DescriptorArray* src) {
   10447   Object* value = src->GetValue(index);
   10448   PropertyDetails details = src->GetDetails(index);
   10449   Descriptor desc(handle(src->GetKey(index)),
   10450                   handle(value, src->GetIsolate()),
   10451                   details);
   10452   SetDescriptor(index, &desc);
   10453 }
   10454 
   10455 
   10456 void DescriptorArray::Sort() {
   10457   // In-place heap sort.
   10458   int len = number_of_descriptors();
   10459   // Reset sorting since the descriptor array might contain invalid pointers.
   10460   for (int i = 0; i < len; ++i) SetSortedKey(i, i);
   10461   // Bottom-up max-heap construction.
   10462   // Index of the last node with children
   10463   const int max_parent_index = (len / 2) - 1;
   10464   for (int i = max_parent_index; i >= 0; --i) {
   10465     int parent_index = i;
   10466     const uint32_t parent_hash = GetSortedKey(i)->Hash();
   10467     while (parent_index <= max_parent_index) {
   10468       int child_index = 2 * parent_index + 1;
   10469       uint32_t child_hash = GetSortedKey(child_index)->Hash();
   10470       if (child_index + 1 < len) {
   10471         uint32_t right_child_hash = GetSortedKey(child_index + 1)->Hash();
   10472         if (right_child_hash > child_hash) {
   10473           child_index++;
   10474           child_hash = right_child_hash;
   10475         }
   10476       }
   10477       if (child_hash <= parent_hash) break;
   10478       SwapSortedKeys(parent_index, child_index);
   10479       // Now element at child_index could be < its children.
   10480       parent_index = child_index;  // parent_hash remains correct.
   10481     }
   10482   }
   10483 
   10484   // Extract elements and create sorted array.
   10485   for (int i = len - 1; i > 0; --i) {
   10486     // Put max element at the back of the array.
   10487     SwapSortedKeys(0, i);
   10488     // Shift down the new top element.
   10489     int parent_index = 0;
   10490     const uint32_t parent_hash = GetSortedKey(parent_index)->Hash();
   10491     const int max_parent_index = (i / 2) - 1;
   10492     while (parent_index <= max_parent_index) {
   10493       int child_index = parent_index * 2 + 1;
   10494       uint32_t child_hash = GetSortedKey(child_index)->Hash();
   10495       if (child_index + 1 < i) {
   10496         uint32_t right_child_hash = GetSortedKey(child_index + 1)->Hash();
   10497         if (right_child_hash > child_hash) {
   10498           child_index++;
   10499           child_hash = right_child_hash;
   10500         }
   10501       }
   10502       if (child_hash <= parent_hash) break;
   10503       SwapSortedKeys(parent_index, child_index);
   10504       parent_index = child_index;
   10505     }
   10506   }
   10507   DCHECK(IsSortedNoDuplicates());
   10508 }
   10509 
   10510 
   10511 Handle<AccessorPair> AccessorPair::Copy(Handle<AccessorPair> pair) {
   10512   Handle<AccessorPair> copy = pair->GetIsolate()->factory()->NewAccessorPair();
   10513   copy->set_getter(pair->getter());
   10514   copy->set_setter(pair->setter());
   10515   return copy;
   10516 }
   10517 
   10518 Handle<Object> AccessorPair::GetComponent(Handle<AccessorPair> accessor_pair,
   10519                                           AccessorComponent component) {
   10520   Object* accessor = accessor_pair->get(component);
   10521   if (accessor->IsFunctionTemplateInfo()) {
   10522     return ApiNatives::InstantiateFunction(
   10523                handle(FunctionTemplateInfo::cast(accessor)))
   10524         .ToHandleChecked();
   10525   }
   10526   Isolate* isolate = accessor_pair->GetIsolate();
   10527   if (accessor->IsNull(isolate)) {
   10528     return isolate->factory()->undefined_value();
   10529   }
   10530   return handle(accessor, isolate);
   10531 }
   10532 
   10533 Handle<DeoptimizationInputData> DeoptimizationInputData::New(
   10534     Isolate* isolate, int deopt_entry_count, PretenureFlag pretenure) {
   10535   return Handle<DeoptimizationInputData>::cast(
   10536       isolate->factory()->NewFixedArray(LengthFor(deopt_entry_count),
   10537                                         pretenure));
   10538 }
   10539 
   10540 
   10541 Handle<DeoptimizationOutputData> DeoptimizationOutputData::New(
   10542     Isolate* isolate,
   10543     int number_of_deopt_points,
   10544     PretenureFlag pretenure) {
   10545   Handle<FixedArray> result;
   10546   if (number_of_deopt_points == 0) {
   10547     result = isolate->factory()->empty_fixed_array();
   10548   } else {
   10549     result = isolate->factory()->NewFixedArray(
   10550         LengthOfFixedArray(number_of_deopt_points), pretenure);
   10551   }
   10552   return Handle<DeoptimizationOutputData>::cast(result);
   10553 }
   10554 
   10555 SharedFunctionInfo* DeoptimizationInputData::GetInlinedFunction(int index) {
   10556   if (index == -1) {
   10557     return SharedFunctionInfo::cast(this->SharedFunctionInfo());
   10558   } else {
   10559     return SharedFunctionInfo::cast(LiteralArray()->get(index));
   10560   }
   10561 }
   10562 
   10563 const int LiteralsArray::kFeedbackVectorOffset =
   10564     LiteralsArray::OffsetOfElementAt(LiteralsArray::kVectorIndex);
   10565 
   10566 const int LiteralsArray::kOffsetToFirstLiteral =
   10567     LiteralsArray::OffsetOfElementAt(LiteralsArray::kFirstLiteralIndex);
   10568 
   10569 // static
   10570 Handle<LiteralsArray> LiteralsArray::New(Isolate* isolate,
   10571                                          Handle<TypeFeedbackVector> vector,
   10572                                          int number_of_literals,
   10573                                          PretenureFlag pretenure) {
   10574   if (vector->is_empty() && number_of_literals == 0) {
   10575     return Handle<LiteralsArray>::cast(
   10576         isolate->factory()->empty_literals_array());
   10577   }
   10578   Handle<FixedArray> literals = isolate->factory()->NewFixedArray(
   10579       number_of_literals + kFirstLiteralIndex, pretenure);
   10580   Handle<LiteralsArray> casted_literals = Handle<LiteralsArray>::cast(literals);
   10581   casted_literals->set_feedback_vector(*vector);
   10582   return casted_literals;
   10583 }
   10584 
   10585 int HandlerTable::LookupRange(int pc_offset, int* data_out,
   10586                               CatchPrediction* prediction_out) {
   10587   int innermost_handler = -1;
   10588 #ifdef DEBUG
   10589   // Assuming that ranges are well nested, we don't need to track the innermost
   10590   // offsets. This is just to verify that the table is actually well nested.
   10591   int innermost_start = std::numeric_limits<int>::min();
   10592   int innermost_end = std::numeric_limits<int>::max();
   10593 #endif
   10594   for (int i = 0; i < length(); i += kRangeEntrySize) {
   10595     int start_offset = Smi::cast(get(i + kRangeStartIndex))->value();
   10596     int end_offset = Smi::cast(get(i + kRangeEndIndex))->value();
   10597     int handler_field = Smi::cast(get(i + kRangeHandlerIndex))->value();
   10598     int handler_offset = HandlerOffsetField::decode(handler_field);
   10599     CatchPrediction prediction = HandlerPredictionField::decode(handler_field);
   10600     int handler_data = Smi::cast(get(i + kRangeDataIndex))->value();
   10601     if (pc_offset > start_offset && pc_offset <= end_offset) {
   10602       DCHECK_GE(start_offset, innermost_start);
   10603       DCHECK_LT(end_offset, innermost_end);
   10604       innermost_handler = handler_offset;
   10605 #ifdef DEBUG
   10606       innermost_start = start_offset;
   10607       innermost_end = end_offset;
   10608 #endif
   10609       if (data_out) *data_out = handler_data;
   10610       if (prediction_out) *prediction_out = prediction;
   10611     }
   10612   }
   10613   return innermost_handler;
   10614 }
   10615 
   10616 
   10617 // TODO(turbofan): Make sure table is sorted and use binary search.
   10618 int HandlerTable::LookupReturn(int pc_offset) {
   10619   for (int i = 0; i < length(); i += kReturnEntrySize) {
   10620     int return_offset = Smi::cast(get(i + kReturnOffsetIndex))->value();
   10621     int handler_field = Smi::cast(get(i + kReturnHandlerIndex))->value();
   10622     if (pc_offset == return_offset) {
   10623       return HandlerOffsetField::decode(handler_field);
   10624     }
   10625   }
   10626   return -1;
   10627 }
   10628 
   10629 
   10630 #ifdef DEBUG
   10631 bool DescriptorArray::IsEqualTo(DescriptorArray* other) {
   10632   if (IsEmpty()) return other->IsEmpty();
   10633   if (other->IsEmpty()) return false;
   10634   if (length() != other->length()) return false;
   10635   for (int i = 0; i < length(); ++i) {
   10636     if (get(i) != other->get(i)) return false;
   10637   }
   10638   return true;
   10639 }
   10640 #endif
   10641 
   10642 // static
   10643 Handle<String> String::Trim(Handle<String> string, TrimMode mode) {
   10644   Isolate* const isolate = string->GetIsolate();
   10645   string = String::Flatten(string);
   10646   int const length = string->length();
   10647 
   10648   // Perform left trimming if requested.
   10649   int left = 0;
   10650   UnicodeCache* unicode_cache = isolate->unicode_cache();
   10651   if (mode == kTrim || mode == kTrimLeft) {
   10652     while (left < length &&
   10653            unicode_cache->IsWhiteSpaceOrLineTerminator(string->Get(left))) {
   10654       left++;
   10655     }
   10656   }
   10657 
   10658   // Perform right trimming if requested.
   10659   int right = length;
   10660   if (mode == kTrim || mode == kTrimRight) {
   10661     while (
   10662         right > left &&
   10663         unicode_cache->IsWhiteSpaceOrLineTerminator(string->Get(right - 1))) {
   10664       right--;
   10665     }
   10666   }
   10667 
   10668   return isolate->factory()->NewSubString(string, left, right);
   10669 }
   10670 
   10671 bool String::LooksValid() {
   10672   if (!GetIsolate()->heap()->Contains(this)) return false;
   10673   return true;
   10674 }
   10675 
   10676 
   10677 // static
   10678 MaybeHandle<String> Name::ToFunctionName(Handle<Name> name) {
   10679   if (name->IsString()) return Handle<String>::cast(name);
   10680   // ES6 section 9.2.11 SetFunctionName, step 4.
   10681   Isolate* const isolate = name->GetIsolate();
   10682   Handle<Object> description(Handle<Symbol>::cast(name)->name(), isolate);
   10683   if (description->IsUndefined(isolate)) {
   10684     return isolate->factory()->empty_string();
   10685   }
   10686   IncrementalStringBuilder builder(isolate);
   10687   builder.AppendCharacter('[');
   10688   builder.AppendString(Handle<String>::cast(description));
   10689   builder.AppendCharacter(']');
   10690   return builder.Finish();
   10691 }
   10692 
   10693 // static
   10694 MaybeHandle<String> Name::ToFunctionName(Handle<Name> name,
   10695                                          Handle<String> prefix) {
   10696   Handle<String> name_string;
   10697   Isolate* const isolate = name->GetIsolate();
   10698   ASSIGN_RETURN_ON_EXCEPTION(isolate, name_string, ToFunctionName(name),
   10699                              String);
   10700   IncrementalStringBuilder builder(isolate);
   10701   builder.AppendString(prefix);
   10702   builder.AppendCharacter(' ');
   10703   builder.AppendString(name_string);
   10704   return builder.Finish();
   10705 }
   10706 
   10707 namespace {
   10708 
   10709 bool AreDigits(const uint8_t* s, int from, int to) {
   10710   for (int i = from; i < to; i++) {
   10711     if (s[i] < '0' || s[i] > '9') return false;
   10712   }
   10713 
   10714   return true;
   10715 }
   10716 
   10717 
   10718 int ParseDecimalInteger(const uint8_t* s, int from, int to) {
   10719   DCHECK(to - from < 10);  // Overflow is not possible.
   10720   DCHECK(from < to);
   10721   int d = s[from] - '0';
   10722 
   10723   for (int i = from + 1; i < to; i++) {
   10724     d = 10 * d + (s[i] - '0');
   10725   }
   10726 
   10727   return d;
   10728 }
   10729 
   10730 }  // namespace
   10731 
   10732 
   10733 // static
   10734 Handle<Object> String::ToNumber(Handle<String> subject) {
   10735   Isolate* const isolate = subject->GetIsolate();
   10736 
   10737   // Flatten {subject} string first.
   10738   subject = String::Flatten(subject);
   10739 
   10740   // Fast array index case.
   10741   uint32_t index;
   10742   if (subject->AsArrayIndex(&index)) {
   10743     return isolate->factory()->NewNumberFromUint(index);
   10744   }
   10745 
   10746   // Fast case: short integer or some sorts of junk values.
   10747   if (subject->IsSeqOneByteString()) {
   10748     int len = subject->length();
   10749     if (len == 0) return handle(Smi::kZero, isolate);
   10750 
   10751     DisallowHeapAllocation no_gc;
   10752     uint8_t const* data = Handle<SeqOneByteString>::cast(subject)->GetChars();
   10753     bool minus = (data[0] == '-');
   10754     int start_pos = (minus ? 1 : 0);
   10755 
   10756     if (start_pos == len) {
   10757       return isolate->factory()->nan_value();
   10758     } else if (data[start_pos] > '9') {
   10759       // Fast check for a junk value. A valid string may start from a
   10760       // whitespace, a sign ('+' or '-'), the decimal point, a decimal digit
   10761       // or the 'I' character ('Infinity'). All of that have codes not greater
   10762       // than '9' except 'I' and &nbsp;.
   10763       if (data[start_pos] != 'I' && data[start_pos] != 0xa0) {
   10764         return isolate->factory()->nan_value();
   10765       }
   10766     } else if (len - start_pos < 10 && AreDigits(data, start_pos, len)) {
   10767       // The maximal/minimal smi has 10 digits. If the string has less digits
   10768       // we know it will fit into the smi-data type.
   10769       int d = ParseDecimalInteger(data, start_pos, len);
   10770       if (minus) {
   10771         if (d == 0) return isolate->factory()->minus_zero_value();
   10772         d = -d;
   10773       } else if (!subject->HasHashCode() && len <= String::kMaxArrayIndexSize &&
   10774                  (len == 1 || data[0] != '0')) {
   10775         // String hash is not calculated yet but all the data are present.
   10776         // Update the hash field to speed up sequential convertions.
   10777         uint32_t hash = StringHasher::MakeArrayIndexHash(d, len);
   10778 #ifdef DEBUG
   10779         subject->Hash();  // Force hash calculation.
   10780         DCHECK_EQ(static_cast<int>(subject->hash_field()),
   10781                   static_cast<int>(hash));
   10782 #endif
   10783         subject->set_hash_field(hash);
   10784       }
   10785       return handle(Smi::FromInt(d), isolate);
   10786     }
   10787   }
   10788 
   10789   // Slower case.
   10790   int flags = ALLOW_HEX | ALLOW_OCTAL | ALLOW_BINARY;
   10791   return isolate->factory()->NewNumber(
   10792       StringToDouble(isolate->unicode_cache(), subject, flags));
   10793 }
   10794 
   10795 
   10796 String::FlatContent String::GetFlatContent() {
   10797   DCHECK(!AllowHeapAllocation::IsAllowed());
   10798   int length = this->length();
   10799   StringShape shape(this);
   10800   String* string = this;
   10801   int offset = 0;
   10802   if (shape.representation_tag() == kConsStringTag) {
   10803     ConsString* cons = ConsString::cast(string);
   10804     if (cons->second()->length() != 0) {
   10805       return FlatContent();
   10806     }
   10807     string = cons->first();
   10808     shape = StringShape(string);
   10809   }
   10810   if (shape.representation_tag() == kSlicedStringTag) {
   10811     SlicedString* slice = SlicedString::cast(string);
   10812     offset = slice->offset();
   10813     string = slice->parent();
   10814     shape = StringShape(string);
   10815     DCHECK(shape.representation_tag() != kConsStringTag &&
   10816            shape.representation_tag() != kSlicedStringTag);
   10817   }
   10818   if (shape.encoding_tag() == kOneByteStringTag) {
   10819     const uint8_t* start;
   10820     if (shape.representation_tag() == kSeqStringTag) {
   10821       start = SeqOneByteString::cast(string)->GetChars();
   10822     } else {
   10823       start = ExternalOneByteString::cast(string)->GetChars();
   10824     }
   10825     return FlatContent(start + offset, length);
   10826   } else {
   10827     DCHECK(shape.encoding_tag() == kTwoByteStringTag);
   10828     const uc16* start;
   10829     if (shape.representation_tag() == kSeqStringTag) {
   10830       start = SeqTwoByteString::cast(string)->GetChars();
   10831     } else {
   10832       start = ExternalTwoByteString::cast(string)->GetChars();
   10833     }
   10834     return FlatContent(start + offset, length);
   10835   }
   10836 }
   10837 
   10838 std::unique_ptr<char[]> String::ToCString(AllowNullsFlag allow_nulls,
   10839                                           RobustnessFlag robust_flag,
   10840                                           int offset, int length,
   10841                                           int* length_return) {
   10842   if (robust_flag == ROBUST_STRING_TRAVERSAL && !LooksValid()) {
   10843     return std::unique_ptr<char[]>();
   10844   }
   10845   // Negative length means the to the end of the string.
   10846   if (length < 0) length = kMaxInt - offset;
   10847 
   10848   // Compute the size of the UTF-8 string. Start at the specified offset.
   10849   StringCharacterStream stream(this, offset);
   10850   int character_position = offset;
   10851   int utf8_bytes = 0;
   10852   int last = unibrow::Utf16::kNoPreviousCharacter;
   10853   while (stream.HasMore() && character_position++ < offset + length) {
   10854     uint16_t character = stream.GetNext();
   10855     utf8_bytes += unibrow::Utf8::Length(character, last);
   10856     last = character;
   10857   }
   10858 
   10859   if (length_return) {
   10860     *length_return = utf8_bytes;
   10861   }
   10862 
   10863   char* result = NewArray<char>(utf8_bytes + 1);
   10864 
   10865   // Convert the UTF-16 string to a UTF-8 buffer. Start at the specified offset.
   10866   stream.Reset(this, offset);
   10867   character_position = offset;
   10868   int utf8_byte_position = 0;
   10869   last = unibrow::Utf16::kNoPreviousCharacter;
   10870   while (stream.HasMore() && character_position++ < offset + length) {
   10871     uint16_t character = stream.GetNext();
   10872     if (allow_nulls == DISALLOW_NULLS && character == 0) {
   10873       character = ' ';
   10874     }
   10875     utf8_byte_position +=
   10876         unibrow::Utf8::Encode(result + utf8_byte_position, character, last);
   10877     last = character;
   10878   }
   10879   result[utf8_byte_position] = 0;
   10880   return std::unique_ptr<char[]>(result);
   10881 }
   10882 
   10883 std::unique_ptr<char[]> String::ToCString(AllowNullsFlag allow_nulls,
   10884                                           RobustnessFlag robust_flag,
   10885                                           int* length_return) {
   10886   return ToCString(allow_nulls, robust_flag, 0, -1, length_return);
   10887 }
   10888 
   10889 
   10890 const uc16* String::GetTwoByteData(unsigned start) {
   10891   DCHECK(!IsOneByteRepresentationUnderneath());
   10892   switch (StringShape(this).representation_tag()) {
   10893     case kSeqStringTag:
   10894       return SeqTwoByteString::cast(this)->SeqTwoByteStringGetData(start);
   10895     case kExternalStringTag:
   10896       return ExternalTwoByteString::cast(this)->
   10897         ExternalTwoByteStringGetData(start);
   10898     case kSlicedStringTag: {
   10899       SlicedString* slice = SlicedString::cast(this);
   10900       return slice->parent()->GetTwoByteData(start + slice->offset());
   10901     }
   10902     case kConsStringTag:
   10903       UNREACHABLE();
   10904       return NULL;
   10905   }
   10906   UNREACHABLE();
   10907   return NULL;
   10908 }
   10909 
   10910 
   10911 const uc16* SeqTwoByteString::SeqTwoByteStringGetData(unsigned start) {
   10912   return reinterpret_cast<uc16*>(
   10913       reinterpret_cast<char*>(this) - kHeapObjectTag + kHeaderSize) + start;
   10914 }
   10915 
   10916 
   10917 void Relocatable::PostGarbageCollectionProcessing(Isolate* isolate) {
   10918   Relocatable* current = isolate->relocatable_top();
   10919   while (current != NULL) {
   10920     current->PostGarbageCollection();
   10921     current = current->prev_;
   10922   }
   10923 }
   10924 
   10925 
   10926 // Reserve space for statics needing saving and restoring.
   10927 int Relocatable::ArchiveSpacePerThread() {
   10928   return sizeof(Relocatable*);  // NOLINT
   10929 }
   10930 
   10931 
   10932 // Archive statics that are thread-local.
   10933 char* Relocatable::ArchiveState(Isolate* isolate, char* to) {
   10934   *reinterpret_cast<Relocatable**>(to) = isolate->relocatable_top();
   10935   isolate->set_relocatable_top(NULL);
   10936   return to + ArchiveSpacePerThread();
   10937 }
   10938 
   10939 
   10940 // Restore statics that are thread-local.
   10941 char* Relocatable::RestoreState(Isolate* isolate, char* from) {
   10942   isolate->set_relocatable_top(*reinterpret_cast<Relocatable**>(from));
   10943   return from + ArchiveSpacePerThread();
   10944 }
   10945 
   10946 
   10947 char* Relocatable::Iterate(ObjectVisitor* v, char* thread_storage) {
   10948   Relocatable* top = *reinterpret_cast<Relocatable**>(thread_storage);
   10949   Iterate(v, top);
   10950   return thread_storage + ArchiveSpacePerThread();
   10951 }
   10952 
   10953 
   10954 void Relocatable::Iterate(Isolate* isolate, ObjectVisitor* v) {
   10955   Iterate(v, isolate->relocatable_top());
   10956 }
   10957 
   10958 
   10959 void Relocatable::Iterate(ObjectVisitor* v, Relocatable* top) {
   10960   Relocatable* current = top;
   10961   while (current != NULL) {
   10962     current->IterateInstance(v);
   10963     current = current->prev_;
   10964   }
   10965 }
   10966 
   10967 
   10968 FlatStringReader::FlatStringReader(Isolate* isolate, Handle<String> str)
   10969     : Relocatable(isolate),
   10970       str_(str.location()),
   10971       length_(str->length()) {
   10972   PostGarbageCollection();
   10973 }
   10974 
   10975 
   10976 FlatStringReader::FlatStringReader(Isolate* isolate, Vector<const char> input)
   10977     : Relocatable(isolate),
   10978       str_(0),
   10979       is_one_byte_(true),
   10980       length_(input.length()),
   10981       start_(input.start()) {}
   10982 
   10983 
   10984 void FlatStringReader::PostGarbageCollection() {
   10985   if (str_ == NULL) return;
   10986   Handle<String> str(str_);
   10987   DCHECK(str->IsFlat());
   10988   DisallowHeapAllocation no_gc;
   10989   // This does not actually prevent the vector from being relocated later.
   10990   String::FlatContent content = str->GetFlatContent();
   10991   DCHECK(content.IsFlat());
   10992   is_one_byte_ = content.IsOneByte();
   10993   if (is_one_byte_) {
   10994     start_ = content.ToOneByteVector().start();
   10995   } else {
   10996     start_ = content.ToUC16Vector().start();
   10997   }
   10998 }
   10999 
   11000 
   11001 void ConsStringIterator::Initialize(ConsString* cons_string, int offset) {
   11002   DCHECK(cons_string != NULL);
   11003   root_ = cons_string;
   11004   consumed_ = offset;
   11005   // Force stack blown condition to trigger restart.
   11006   depth_ = 1;
   11007   maximum_depth_ = kStackSize + depth_;
   11008   DCHECK(StackBlown());
   11009 }
   11010 
   11011 
   11012 String* ConsStringIterator::Continue(int* offset_out) {
   11013   DCHECK(depth_ != 0);
   11014   DCHECK_EQ(0, *offset_out);
   11015   bool blew_stack = StackBlown();
   11016   String* string = NULL;
   11017   // Get the next leaf if there is one.
   11018   if (!blew_stack) string = NextLeaf(&blew_stack);
   11019   // Restart search from root.
   11020   if (blew_stack) {
   11021     DCHECK(string == NULL);
   11022     string = Search(offset_out);
   11023   }
   11024   // Ensure future calls return null immediately.
   11025   if (string == NULL) Reset(NULL);
   11026   return string;
   11027 }
   11028 
   11029 
   11030 String* ConsStringIterator::Search(int* offset_out) {
   11031   ConsString* cons_string = root_;
   11032   // Reset the stack, pushing the root string.
   11033   depth_ = 1;
   11034   maximum_depth_ = 1;
   11035   frames_[0] = cons_string;
   11036   const int consumed = consumed_;
   11037   int offset = 0;
   11038   while (true) {
   11039     // Loop until the string is found which contains the target offset.
   11040     String* string = cons_string->first();
   11041     int length = string->length();
   11042     int32_t type;
   11043     if (consumed < offset + length) {
   11044       // Target offset is in the left branch.
   11045       // Keep going if we're still in a ConString.
   11046       type = string->map()->instance_type();
   11047       if ((type & kStringRepresentationMask) == kConsStringTag) {
   11048         cons_string = ConsString::cast(string);
   11049         PushLeft(cons_string);
   11050         continue;
   11051       }
   11052       // Tell the stack we're done descending.
   11053       AdjustMaximumDepth();
   11054     } else {
   11055       // Descend right.
   11056       // Update progress through the string.
   11057       offset += length;
   11058       // Keep going if we're still in a ConString.
   11059       string = cons_string->second();
   11060       type = string->map()->instance_type();
   11061       if ((type & kStringRepresentationMask) == kConsStringTag) {
   11062         cons_string = ConsString::cast(string);
   11063         PushRight(cons_string);
   11064         continue;
   11065       }
   11066       // Need this to be updated for the current string.
   11067       length = string->length();
   11068       // Account for the possibility of an empty right leaf.
   11069       // This happens only if we have asked for an offset outside the string.
   11070       if (length == 0) {
   11071         // Reset so future operations will return null immediately.
   11072         Reset(NULL);
   11073         return NULL;
   11074       }
   11075       // Tell the stack we're done descending.
   11076       AdjustMaximumDepth();
   11077       // Pop stack so next iteration is in correct place.
   11078       Pop();
   11079     }
   11080     DCHECK(length != 0);
   11081     // Adjust return values and exit.
   11082     consumed_ = offset + length;
   11083     *offset_out = consumed - offset;
   11084     return string;
   11085   }
   11086   UNREACHABLE();
   11087   return NULL;
   11088 }
   11089 
   11090 
   11091 String* ConsStringIterator::NextLeaf(bool* blew_stack) {
   11092   while (true) {
   11093     // Tree traversal complete.
   11094     if (depth_ == 0) {
   11095       *blew_stack = false;
   11096       return NULL;
   11097     }
   11098     // We've lost track of higher nodes.
   11099     if (StackBlown()) {
   11100       *blew_stack = true;
   11101       return NULL;
   11102     }
   11103     // Go right.
   11104     ConsString* cons_string = frames_[OffsetForDepth(depth_ - 1)];
   11105     String* string = cons_string->second();
   11106     int32_t type = string->map()->instance_type();
   11107     if ((type & kStringRepresentationMask) != kConsStringTag) {
   11108       // Pop stack so next iteration is in correct place.
   11109       Pop();
   11110       int length = string->length();
   11111       // Could be a flattened ConsString.
   11112       if (length == 0) continue;
   11113       consumed_ += length;
   11114       return string;
   11115     }
   11116     cons_string = ConsString::cast(string);
   11117     PushRight(cons_string);
   11118     // Need to traverse all the way left.
   11119     while (true) {
   11120       // Continue left.
   11121       string = cons_string->first();
   11122       type = string->map()->instance_type();
   11123       if ((type & kStringRepresentationMask) != kConsStringTag) {
   11124         AdjustMaximumDepth();
   11125         int length = string->length();
   11126         if (length == 0) break;  // Skip empty left-hand sides of ConsStrings.
   11127         consumed_ += length;
   11128         return string;
   11129       }
   11130       cons_string = ConsString::cast(string);
   11131       PushLeft(cons_string);
   11132     }
   11133   }
   11134   UNREACHABLE();
   11135   return NULL;
   11136 }
   11137 
   11138 
   11139 uint16_t ConsString::ConsStringGet(int index) {
   11140   DCHECK(index >= 0 && index < this->length());
   11141 
   11142   // Check for a flattened cons string
   11143   if (second()->length() == 0) {
   11144     String* left = first();
   11145     return left->Get(index);
   11146   }
   11147 
   11148   String* string = String::cast(this);
   11149 
   11150   while (true) {
   11151     if (StringShape(string).IsCons()) {
   11152       ConsString* cons_string = ConsString::cast(string);
   11153       String* left = cons_string->first();
   11154       if (left->length() > index) {
   11155         string = left;
   11156       } else {
   11157         index -= left->length();
   11158         string = cons_string->second();
   11159       }
   11160     } else {
   11161       return string->Get(index);
   11162     }
   11163   }
   11164 
   11165   UNREACHABLE();
   11166   return 0;
   11167 }
   11168 
   11169 
   11170 uint16_t SlicedString::SlicedStringGet(int index) {
   11171   return parent()->Get(offset() + index);
   11172 }
   11173 
   11174 
   11175 template <typename sinkchar>
   11176 void String::WriteToFlat(String* src,
   11177                          sinkchar* sink,
   11178                          int f,
   11179                          int t) {
   11180   String* source = src;
   11181   int from = f;
   11182   int to = t;
   11183   while (true) {
   11184     DCHECK(0 <= from && from <= to && to <= source->length());
   11185     switch (StringShape(source).full_representation_tag()) {
   11186       case kOneByteStringTag | kExternalStringTag: {
   11187         CopyChars(sink, ExternalOneByteString::cast(source)->GetChars() + from,
   11188                   to - from);
   11189         return;
   11190       }
   11191       case kTwoByteStringTag | kExternalStringTag: {
   11192         const uc16* data =
   11193             ExternalTwoByteString::cast(source)->GetChars();
   11194         CopyChars(sink,
   11195                   data + from,
   11196                   to - from);
   11197         return;
   11198       }
   11199       case kOneByteStringTag | kSeqStringTag: {
   11200         CopyChars(sink,
   11201                   SeqOneByteString::cast(source)->GetChars() + from,
   11202                   to - from);
   11203         return;
   11204       }
   11205       case kTwoByteStringTag | kSeqStringTag: {
   11206         CopyChars(sink,
   11207                   SeqTwoByteString::cast(source)->GetChars() + from,
   11208                   to - from);
   11209         return;
   11210       }
   11211       case kOneByteStringTag | kConsStringTag:
   11212       case kTwoByteStringTag | kConsStringTag: {
   11213         ConsString* cons_string = ConsString::cast(source);
   11214         String* first = cons_string->first();
   11215         int boundary = first->length();
   11216         if (to - boundary >= boundary - from) {
   11217           // Right hand side is longer.  Recurse over left.
   11218           if (from < boundary) {
   11219             WriteToFlat(first, sink, from, boundary);
   11220             if (from == 0 && cons_string->second() == first) {
   11221               CopyChars(sink + boundary, sink, boundary);
   11222               return;
   11223             }
   11224             sink += boundary - from;
   11225             from = 0;
   11226           } else {
   11227             from -= boundary;
   11228           }
   11229           to -= boundary;
   11230           source = cons_string->second();
   11231         } else {
   11232           // Left hand side is longer.  Recurse over right.
   11233           if (to > boundary) {
   11234             String* second = cons_string->second();
   11235             // When repeatedly appending to a string, we get a cons string that
   11236             // is unbalanced to the left, a list, essentially.  We inline the
   11237             // common case of sequential one-byte right child.
   11238             if (to - boundary == 1) {
   11239               sink[boundary - from] = static_cast<sinkchar>(second->Get(0));
   11240             } else if (second->IsSeqOneByteString()) {
   11241               CopyChars(sink + boundary - from,
   11242                         SeqOneByteString::cast(second)->GetChars(),
   11243                         to - boundary);
   11244             } else {
   11245               WriteToFlat(second,
   11246                           sink + boundary - from,
   11247                           0,
   11248                           to - boundary);
   11249             }
   11250             to = boundary;
   11251           }
   11252           source = first;
   11253         }
   11254         break;
   11255       }
   11256       case kOneByteStringTag | kSlicedStringTag:
   11257       case kTwoByteStringTag | kSlicedStringTag: {
   11258         SlicedString* slice = SlicedString::cast(source);
   11259         unsigned offset = slice->offset();
   11260         WriteToFlat(slice->parent(), sink, from + offset, to + offset);
   11261         return;
   11262       }
   11263     }
   11264   }
   11265 }
   11266 
   11267 
   11268 
   11269 template <typename SourceChar>
   11270 static void CalculateLineEndsImpl(Isolate* isolate,
   11271                                   List<int>* line_ends,
   11272                                   Vector<const SourceChar> src,
   11273                                   bool include_ending_line) {
   11274   const int src_len = src.length();
   11275   UnicodeCache* cache = isolate->unicode_cache();
   11276   for (int i = 0; i < src_len - 1; i++) {
   11277     SourceChar current = src[i];
   11278     SourceChar next = src[i + 1];
   11279     if (cache->IsLineTerminatorSequence(current, next)) line_ends->Add(i);
   11280   }
   11281 
   11282   if (src_len > 0 && cache->IsLineTerminatorSequence(src[src_len - 1], 0)) {
   11283     line_ends->Add(src_len - 1);
   11284   }
   11285   if (include_ending_line) {
   11286     // Include one character beyond the end of script. The rewriter uses that
   11287     // position for the implicit return statement.
   11288     line_ends->Add(src_len);
   11289   }
   11290 }
   11291 
   11292 
   11293 Handle<FixedArray> String::CalculateLineEnds(Handle<String> src,
   11294                                              bool include_ending_line) {
   11295   src = Flatten(src);
   11296   // Rough estimate of line count based on a roughly estimated average
   11297   // length of (unpacked) code.
   11298   int line_count_estimate = src->length() >> 4;
   11299   List<int> line_ends(line_count_estimate);
   11300   Isolate* isolate = src->GetIsolate();
   11301   { DisallowHeapAllocation no_allocation;  // ensure vectors stay valid.
   11302     // Dispatch on type of strings.
   11303     String::FlatContent content = src->GetFlatContent();
   11304     DCHECK(content.IsFlat());
   11305     if (content.IsOneByte()) {
   11306       CalculateLineEndsImpl(isolate,
   11307                             &line_ends,
   11308                             content.ToOneByteVector(),
   11309                             include_ending_line);
   11310     } else {
   11311       CalculateLineEndsImpl(isolate,
   11312                             &line_ends,
   11313                             content.ToUC16Vector(),
   11314                             include_ending_line);
   11315     }
   11316   }
   11317   int line_count = line_ends.length();
   11318   Handle<FixedArray> array = isolate->factory()->NewFixedArray(line_count);
   11319   for (int i = 0; i < line_count; i++) {
   11320     array->set(i, Smi::FromInt(line_ends[i]));
   11321   }
   11322   return array;
   11323 }
   11324 
   11325 
   11326 // Compares the contents of two strings by reading and comparing
   11327 // int-sized blocks of characters.
   11328 template <typename Char>
   11329 static inline bool CompareRawStringContents(const Char* const a,
   11330                                             const Char* const b,
   11331                                             int length) {
   11332   return CompareChars(a, b, length) == 0;
   11333 }
   11334 
   11335 
   11336 template<typename Chars1, typename Chars2>
   11337 class RawStringComparator : public AllStatic {
   11338  public:
   11339   static inline bool compare(const Chars1* a, const Chars2* b, int len) {
   11340     DCHECK(sizeof(Chars1) != sizeof(Chars2));
   11341     for (int i = 0; i < len; i++) {
   11342       if (a[i] != b[i]) {
   11343         return false;
   11344       }
   11345     }
   11346     return true;
   11347   }
   11348 };
   11349 
   11350 
   11351 template<>
   11352 class RawStringComparator<uint16_t, uint16_t> {
   11353  public:
   11354   static inline bool compare(const uint16_t* a, const uint16_t* b, int len) {
   11355     return CompareRawStringContents(a, b, len);
   11356   }
   11357 };
   11358 
   11359 
   11360 template<>
   11361 class RawStringComparator<uint8_t, uint8_t> {
   11362  public:
   11363   static inline bool compare(const uint8_t* a, const uint8_t* b, int len) {
   11364     return CompareRawStringContents(a, b, len);
   11365   }
   11366 };
   11367 
   11368 
   11369 class StringComparator {
   11370   class State {
   11371    public:
   11372     State() : is_one_byte_(true), length_(0), buffer8_(NULL) {}
   11373 
   11374     void Init(String* string) {
   11375       ConsString* cons_string = String::VisitFlat(this, string);
   11376       iter_.Reset(cons_string);
   11377       if (cons_string != NULL) {
   11378         int offset;
   11379         string = iter_.Next(&offset);
   11380         String::VisitFlat(this, string, offset);
   11381       }
   11382     }
   11383 
   11384     inline void VisitOneByteString(const uint8_t* chars, int length) {
   11385       is_one_byte_ = true;
   11386       buffer8_ = chars;
   11387       length_ = length;
   11388     }
   11389 
   11390     inline void VisitTwoByteString(const uint16_t* chars, int length) {
   11391       is_one_byte_ = false;
   11392       buffer16_ = chars;
   11393       length_ = length;
   11394     }
   11395 
   11396     void Advance(int consumed) {
   11397       DCHECK(consumed <= length_);
   11398       // Still in buffer.
   11399       if (length_ != consumed) {
   11400         if (is_one_byte_) {
   11401           buffer8_ += consumed;
   11402         } else {
   11403           buffer16_ += consumed;
   11404         }
   11405         length_ -= consumed;
   11406         return;
   11407       }
   11408       // Advance state.
   11409       int offset;
   11410       String* next = iter_.Next(&offset);
   11411       DCHECK_EQ(0, offset);
   11412       DCHECK(next != NULL);
   11413       String::VisitFlat(this, next);
   11414     }
   11415 
   11416     ConsStringIterator iter_;
   11417     bool is_one_byte_;
   11418     int length_;
   11419     union {
   11420       const uint8_t* buffer8_;
   11421       const uint16_t* buffer16_;
   11422     };
   11423 
   11424    private:
   11425     DISALLOW_COPY_AND_ASSIGN(State);
   11426   };
   11427 
   11428  public:
   11429   inline StringComparator() {}
   11430 
   11431   template<typename Chars1, typename Chars2>
   11432   static inline bool Equals(State* state_1, State* state_2, int to_check) {
   11433     const Chars1* a = reinterpret_cast<const Chars1*>(state_1->buffer8_);
   11434     const Chars2* b = reinterpret_cast<const Chars2*>(state_2->buffer8_);
   11435     return RawStringComparator<Chars1, Chars2>::compare(a, b, to_check);
   11436   }
   11437 
   11438   bool Equals(String* string_1, String* string_2) {
   11439     int length = string_1->length();
   11440     state_1_.Init(string_1);
   11441     state_2_.Init(string_2);
   11442     while (true) {
   11443       int to_check = Min(state_1_.length_, state_2_.length_);
   11444       DCHECK(to_check > 0 && to_check <= length);
   11445       bool is_equal;
   11446       if (state_1_.is_one_byte_) {
   11447         if (state_2_.is_one_byte_) {
   11448           is_equal = Equals<uint8_t, uint8_t>(&state_1_, &state_2_, to_check);
   11449         } else {
   11450           is_equal = Equals<uint8_t, uint16_t>(&state_1_, &state_2_, to_check);
   11451         }
   11452       } else {
   11453         if (state_2_.is_one_byte_) {
   11454           is_equal = Equals<uint16_t, uint8_t>(&state_1_, &state_2_, to_check);
   11455         } else {
   11456           is_equal = Equals<uint16_t, uint16_t>(&state_1_, &state_2_, to_check);
   11457         }
   11458       }
   11459       // Looping done.
   11460       if (!is_equal) return false;
   11461       length -= to_check;
   11462       // Exit condition. Strings are equal.
   11463       if (length == 0) return true;
   11464       state_1_.Advance(to_check);
   11465       state_2_.Advance(to_check);
   11466     }
   11467   }
   11468 
   11469  private:
   11470   State state_1_;
   11471   State state_2_;
   11472 
   11473   DISALLOW_COPY_AND_ASSIGN(StringComparator);
   11474 };
   11475 
   11476 
   11477 bool String::SlowEquals(String* other) {
   11478   DisallowHeapAllocation no_gc;
   11479   // Fast check: negative check with lengths.
   11480   int len = length();
   11481   if (len != other->length()) return false;
   11482   if (len == 0) return true;
   11483 
   11484   // Fast check: if hash code is computed for both strings
   11485   // a fast negative check can be performed.
   11486   if (HasHashCode() && other->HasHashCode()) {
   11487 #ifdef ENABLE_SLOW_DCHECKS
   11488     if (FLAG_enable_slow_asserts) {
   11489       if (Hash() != other->Hash()) {
   11490         bool found_difference = false;
   11491         for (int i = 0; i < len; i++) {
   11492           if (Get(i) != other->Get(i)) {
   11493             found_difference = true;
   11494             break;
   11495           }
   11496         }
   11497         DCHECK(found_difference);
   11498       }
   11499     }
   11500 #endif
   11501     if (Hash() != other->Hash()) return false;
   11502   }
   11503 
   11504   // We know the strings are both non-empty. Compare the first chars
   11505   // before we try to flatten the strings.
   11506   if (this->Get(0) != other->Get(0)) return false;
   11507 
   11508   if (IsSeqOneByteString() && other->IsSeqOneByteString()) {
   11509     const uint8_t* str1 = SeqOneByteString::cast(this)->GetChars();
   11510     const uint8_t* str2 = SeqOneByteString::cast(other)->GetChars();
   11511     return CompareRawStringContents(str1, str2, len);
   11512   }
   11513 
   11514   StringComparator comparator;
   11515   return comparator.Equals(this, other);
   11516 }
   11517 
   11518 
   11519 bool String::SlowEquals(Handle<String> one, Handle<String> two) {
   11520   // Fast check: negative check with lengths.
   11521   int one_length = one->length();
   11522   if (one_length != two->length()) return false;
   11523   if (one_length == 0) return true;
   11524 
   11525   // Fast check: if hash code is computed for both strings
   11526   // a fast negative check can be performed.
   11527   if (one->HasHashCode() && two->HasHashCode()) {
   11528 #ifdef ENABLE_SLOW_DCHECKS
   11529     if (FLAG_enable_slow_asserts) {
   11530       if (one->Hash() != two->Hash()) {
   11531         bool found_difference = false;
   11532         for (int i = 0; i < one_length; i++) {
   11533           if (one->Get(i) != two->Get(i)) {
   11534             found_difference = true;
   11535             break;
   11536           }
   11537         }
   11538         DCHECK(found_difference);
   11539       }
   11540     }
   11541 #endif
   11542     if (one->Hash() != two->Hash()) return false;
   11543   }
   11544 
   11545   // We know the strings are both non-empty. Compare the first chars
   11546   // before we try to flatten the strings.
   11547   if (one->Get(0) != two->Get(0)) return false;
   11548 
   11549   one = String::Flatten(one);
   11550   two = String::Flatten(two);
   11551 
   11552   DisallowHeapAllocation no_gc;
   11553   String::FlatContent flat1 = one->GetFlatContent();
   11554   String::FlatContent flat2 = two->GetFlatContent();
   11555 
   11556   if (flat1.IsOneByte() && flat2.IsOneByte()) {
   11557       return CompareRawStringContents(flat1.ToOneByteVector().start(),
   11558                                       flat2.ToOneByteVector().start(),
   11559                                       one_length);
   11560   } else {
   11561     for (int i = 0; i < one_length; i++) {
   11562       if (flat1.Get(i) != flat2.Get(i)) return false;
   11563     }
   11564     return true;
   11565   }
   11566 }
   11567 
   11568 
   11569 // static
   11570 ComparisonResult String::Compare(Handle<String> x, Handle<String> y) {
   11571   // A few fast case tests before we flatten.
   11572   if (x.is_identical_to(y)) {
   11573     return ComparisonResult::kEqual;
   11574   } else if (y->length() == 0) {
   11575     return x->length() == 0 ? ComparisonResult::kEqual
   11576                             : ComparisonResult::kGreaterThan;
   11577   } else if (x->length() == 0) {
   11578     return ComparisonResult::kLessThan;
   11579   }
   11580 
   11581   int const d = x->Get(0) - y->Get(0);
   11582   if (d < 0) {
   11583     return ComparisonResult::kLessThan;
   11584   } else if (d > 0) {
   11585     return ComparisonResult::kGreaterThan;
   11586   }
   11587 
   11588   // Slow case.
   11589   x = String::Flatten(x);
   11590   y = String::Flatten(y);
   11591 
   11592   DisallowHeapAllocation no_gc;
   11593   ComparisonResult result = ComparisonResult::kEqual;
   11594   int prefix_length = x->length();
   11595   if (y->length() < prefix_length) {
   11596     prefix_length = y->length();
   11597     result = ComparisonResult::kGreaterThan;
   11598   } else if (y->length() > prefix_length) {
   11599     result = ComparisonResult::kLessThan;
   11600   }
   11601   int r;
   11602   String::FlatContent x_content = x->GetFlatContent();
   11603   String::FlatContent y_content = y->GetFlatContent();
   11604   if (x_content.IsOneByte()) {
   11605     Vector<const uint8_t> x_chars = x_content.ToOneByteVector();
   11606     if (y_content.IsOneByte()) {
   11607       Vector<const uint8_t> y_chars = y_content.ToOneByteVector();
   11608       r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
   11609     } else {
   11610       Vector<const uc16> y_chars = y_content.ToUC16Vector();
   11611       r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
   11612     }
   11613   } else {
   11614     Vector<const uc16> x_chars = x_content.ToUC16Vector();
   11615     if (y_content.IsOneByte()) {
   11616       Vector<const uint8_t> y_chars = y_content.ToOneByteVector();
   11617       r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
   11618     } else {
   11619       Vector<const uc16> y_chars = y_content.ToUC16Vector();
   11620       r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
   11621     }
   11622   }
   11623   if (r < 0) {
   11624     result = ComparisonResult::kLessThan;
   11625   } else if (r > 0) {
   11626     result = ComparisonResult::kGreaterThan;
   11627   }
   11628   return result;
   11629 }
   11630 
   11631 Object* String::IndexOf(Isolate* isolate, Handle<Object> receiver,
   11632                         Handle<Object> search, Handle<Object> position) {
   11633   if (receiver->IsNull(isolate) || receiver->IsUndefined(isolate)) {
   11634     THROW_NEW_ERROR_RETURN_FAILURE(
   11635         isolate, NewTypeError(MessageTemplate::kCalledOnNullOrUndefined,
   11636                               isolate->factory()->NewStringFromAsciiChecked(
   11637                                   "String.prototype.indexOf")));
   11638   }
   11639   Handle<String> receiver_string;
   11640   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver_string,
   11641                                      Object::ToString(isolate, receiver));
   11642 
   11643   Handle<String> search_string;
   11644   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, search_string,
   11645                                      Object::ToString(isolate, search));
   11646 
   11647   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, position,
   11648                                      Object::ToInteger(isolate, position));
   11649 
   11650   double index = std::max(position->Number(), 0.0);
   11651   index = std::min(index, static_cast<double>(receiver_string->length()));
   11652 
   11653   return Smi::FromInt(String::IndexOf(isolate, receiver_string, search_string,
   11654                                       static_cast<uint32_t>(index)));
   11655 }
   11656 
   11657 namespace {
   11658 
   11659 template <typename T>
   11660 int SearchString(Isolate* isolate, String::FlatContent receiver_content,
   11661                  Vector<T> pat_vector, int start_index) {
   11662   if (receiver_content.IsOneByte()) {
   11663     return SearchString(isolate, receiver_content.ToOneByteVector(), pat_vector,
   11664                         start_index);
   11665   }
   11666   return SearchString(isolate, receiver_content.ToUC16Vector(), pat_vector,
   11667                       start_index);
   11668 }
   11669 
   11670 }  // namespace
   11671 
   11672 int String::IndexOf(Isolate* isolate, Handle<String> receiver,
   11673                     Handle<String> search, int start_index) {
   11674   DCHECK(0 <= start_index);
   11675   DCHECK(start_index <= receiver->length());
   11676 
   11677   uint32_t search_length = search->length();
   11678   if (search_length == 0) return start_index;
   11679 
   11680   uint32_t receiver_length = receiver->length();
   11681   if (start_index + search_length > receiver_length) return -1;
   11682 
   11683   receiver = String::Flatten(receiver);
   11684   search = String::Flatten(search);
   11685 
   11686   DisallowHeapAllocation no_gc;  // ensure vectors stay valid
   11687   // Extract flattened substrings of cons strings before getting encoding.
   11688   String::FlatContent receiver_content = receiver->GetFlatContent();
   11689   String::FlatContent search_content = search->GetFlatContent();
   11690 
   11691   // dispatch on type of strings
   11692   if (search_content.IsOneByte()) {
   11693     Vector<const uint8_t> pat_vector = search_content.ToOneByteVector();
   11694     return SearchString<const uint8_t>(isolate, receiver_content, pat_vector,
   11695                                        start_index);
   11696   }
   11697   Vector<const uc16> pat_vector = search_content.ToUC16Vector();
   11698   return SearchString<const uc16>(isolate, receiver_content, pat_vector,
   11699                                   start_index);
   11700 }
   11701 
   11702 MaybeHandle<String> String::GetSubstitution(Isolate* isolate, Match* match,
   11703                                             Handle<String> replacement) {
   11704   Factory* factory = isolate->factory();
   11705 
   11706   const int replacement_length = replacement->length();
   11707   const int captures_length = match->CaptureCount();
   11708 
   11709   replacement = String::Flatten(replacement);
   11710 
   11711   Handle<String> dollar_string =
   11712       factory->LookupSingleCharacterStringFromCode('$');
   11713   int next = String::IndexOf(isolate, replacement, dollar_string, 0);
   11714   if (next < 0) {
   11715     return replacement;
   11716   }
   11717 
   11718   IncrementalStringBuilder builder(isolate);
   11719 
   11720   if (next > 0) {
   11721     builder.AppendString(factory->NewSubString(replacement, 0, next));
   11722   }
   11723 
   11724   while (true) {
   11725     int pos = next + 1;
   11726     if (pos < replacement_length) {
   11727       const uint16_t peek = replacement->Get(pos);
   11728       if (peek == '$') {  // $$
   11729         pos++;
   11730         builder.AppendCharacter('$');
   11731       } else if (peek == '&') {  // $& - match
   11732         pos++;
   11733         builder.AppendString(match->GetMatch());
   11734       } else if (peek == '`') {  // $` - prefix
   11735         pos++;
   11736         builder.AppendString(match->GetPrefix());
   11737       } else if (peek == '\'') {  // $' - suffix
   11738         pos++;
   11739         builder.AppendString(match->GetSuffix());
   11740       } else if (peek >= '0' && peek <= '9') {
   11741         // Valid indices are $1 .. $9, $01 .. $09 and $10 .. $99
   11742         int scaled_index = (peek - '0');
   11743         int advance = 1;
   11744 
   11745         if (pos + 1 < replacement_length) {
   11746           const uint16_t next_peek = replacement->Get(pos + 1);
   11747           if (next_peek >= '0' && next_peek <= '9') {
   11748             const int new_scaled_index = scaled_index * 10 + (next_peek - '0');
   11749             if (new_scaled_index < captures_length) {
   11750               scaled_index = new_scaled_index;
   11751               advance = 2;
   11752             }
   11753           }
   11754         }
   11755 
   11756         if (scaled_index != 0 && scaled_index < captures_length) {
   11757           bool capture_exists;
   11758           Handle<String> capture;
   11759           ASSIGN_RETURN_ON_EXCEPTION(
   11760               isolate, capture,
   11761               match->GetCapture(scaled_index, &capture_exists), String);
   11762           if (capture_exists) builder.AppendString(capture);
   11763           pos += advance;
   11764         } else {
   11765           builder.AppendCharacter('$');
   11766         }
   11767       } else {
   11768         builder.AppendCharacter('$');
   11769       }
   11770     } else {
   11771       builder.AppendCharacter('$');
   11772     }
   11773 
   11774     // Go the the next $ in the replacement.
   11775     next = String::IndexOf(isolate, replacement, dollar_string, pos);
   11776 
   11777     // Return if there are no more $ characters in the replacement. If we
   11778     // haven't reached the end, we need to append the suffix.
   11779     if (next < 0) {
   11780       if (pos < replacement_length) {
   11781         builder.AppendString(
   11782             factory->NewSubString(replacement, pos, replacement_length));
   11783       }
   11784       return builder.Finish();
   11785     }
   11786 
   11787     // Append substring between the previous and the next $ character.
   11788     if (next > pos) {
   11789       builder.AppendString(factory->NewSubString(replacement, pos, next));
   11790     }
   11791   }
   11792 
   11793   UNREACHABLE();
   11794   return MaybeHandle<String>();
   11795 }
   11796 
   11797 namespace {  // for String.Prototype.lastIndexOf
   11798 
   11799 template <typename schar, typename pchar>
   11800 int StringMatchBackwards(Vector<const schar> subject,
   11801                          Vector<const pchar> pattern, int idx) {
   11802   int pattern_length = pattern.length();
   11803   DCHECK(pattern_length >= 1);
   11804   DCHECK(idx + pattern_length <= subject.length());
   11805 
   11806   if (sizeof(schar) == 1 && sizeof(pchar) > 1) {
   11807     for (int i = 0; i < pattern_length; i++) {
   11808       uc16 c = pattern[i];
   11809       if (c > String::kMaxOneByteCharCode) {
   11810         return -1;
   11811       }
   11812     }
   11813   }
   11814 
   11815   pchar pattern_first_char = pattern[0];
   11816   for (int i = idx; i >= 0; i--) {
   11817     if (subject[i] != pattern_first_char) continue;
   11818     int j = 1;
   11819     while (j < pattern_length) {
   11820       if (pattern[j] != subject[i + j]) {
   11821         break;
   11822       }
   11823       j++;
   11824     }
   11825     if (j == pattern_length) {
   11826       return i;
   11827     }
   11828   }
   11829   return -1;
   11830 }
   11831 
   11832 }  // namespace
   11833 
   11834 Object* String::LastIndexOf(Isolate* isolate, Handle<Object> receiver,
   11835                             Handle<Object> search, Handle<Object> position) {
   11836   if (receiver->IsNull(isolate) || receiver->IsUndefined(isolate)) {
   11837     THROW_NEW_ERROR_RETURN_FAILURE(
   11838         isolate, NewTypeError(MessageTemplate::kCalledOnNullOrUndefined,
   11839                               isolate->factory()->NewStringFromAsciiChecked(
   11840                                   "String.prototype.lastIndexOf")));
   11841   }
   11842   Handle<String> receiver_string;
   11843   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver_string,
   11844                                      Object::ToString(isolate, receiver));
   11845 
   11846   Handle<String> search_string;
   11847   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, search_string,
   11848                                      Object::ToString(isolate, search));
   11849 
   11850   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, position,
   11851                                      Object::ToNumber(position));
   11852 
   11853   uint32_t start_index;
   11854 
   11855   if (position->IsNaN()) {
   11856     start_index = receiver_string->length();
   11857   } else {
   11858     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, position,
   11859                                        Object::ToInteger(isolate, position));
   11860 
   11861     double position_number = std::max(position->Number(), 0.0);
   11862     position_number = std::min(position_number,
   11863                                static_cast<double>(receiver_string->length()));
   11864     start_index = static_cast<uint32_t>(position_number);
   11865   }
   11866 
   11867   uint32_t pattern_length = search_string->length();
   11868   uint32_t receiver_length = receiver_string->length();
   11869 
   11870   if (start_index + pattern_length > receiver_length) {
   11871     start_index = receiver_length - pattern_length;
   11872   }
   11873 
   11874   if (pattern_length == 0) {
   11875     return Smi::FromInt(start_index);
   11876   }
   11877 
   11878   receiver_string = String::Flatten(receiver_string);
   11879   search_string = String::Flatten(search_string);
   11880 
   11881   int last_index = -1;
   11882   DisallowHeapAllocation no_gc;  // ensure vectors stay valid
   11883 
   11884   String::FlatContent receiver_content = receiver_string->GetFlatContent();
   11885   String::FlatContent search_content = search_string->GetFlatContent();
   11886 
   11887   if (search_content.IsOneByte()) {
   11888     Vector<const uint8_t> pat_vector = search_content.ToOneByteVector();
   11889     if (receiver_content.IsOneByte()) {
   11890       last_index = StringMatchBackwards(receiver_content.ToOneByteVector(),
   11891                                         pat_vector, start_index);
   11892     } else {
   11893       last_index = StringMatchBackwards(receiver_content.ToUC16Vector(),
   11894                                         pat_vector, start_index);
   11895     }
   11896   } else {
   11897     Vector<const uc16> pat_vector = search_content.ToUC16Vector();
   11898     if (receiver_content.IsOneByte()) {
   11899       last_index = StringMatchBackwards(receiver_content.ToOneByteVector(),
   11900                                         pat_vector, start_index);
   11901     } else {
   11902       last_index = StringMatchBackwards(receiver_content.ToUC16Vector(),
   11903                                         pat_vector, start_index);
   11904     }
   11905   }
   11906   return Smi::FromInt(last_index);
   11907 }
   11908 
   11909 bool String::IsUtf8EqualTo(Vector<const char> str, bool allow_prefix_match) {
   11910   int slen = length();
   11911   // Can't check exact length equality, but we can check bounds.
   11912   int str_len = str.length();
   11913   if (!allow_prefix_match &&
   11914       (str_len < slen ||
   11915           str_len > slen*static_cast<int>(unibrow::Utf8::kMaxEncodedSize))) {
   11916     return false;
   11917   }
   11918   int i;
   11919   size_t remaining_in_str = static_cast<size_t>(str_len);
   11920   const uint8_t* utf8_data = reinterpret_cast<const uint8_t*>(str.start());
   11921   for (i = 0; i < slen && remaining_in_str > 0; i++) {
   11922     size_t cursor = 0;
   11923     uint32_t r = unibrow::Utf8::ValueOf(utf8_data, remaining_in_str, &cursor);
   11924     DCHECK(cursor > 0 && cursor <= remaining_in_str);
   11925     if (r > unibrow::Utf16::kMaxNonSurrogateCharCode) {
   11926       if (i > slen - 1) return false;
   11927       if (Get(i++) != unibrow::Utf16::LeadSurrogate(r)) return false;
   11928       if (Get(i) != unibrow::Utf16::TrailSurrogate(r)) return false;
   11929     } else {
   11930       if (Get(i) != r) return false;
   11931     }
   11932     utf8_data += cursor;
   11933     remaining_in_str -= cursor;
   11934   }
   11935   return (allow_prefix_match || i == slen) && remaining_in_str == 0;
   11936 }
   11937 
   11938 
   11939 bool String::IsOneByteEqualTo(Vector<const uint8_t> str) {
   11940   int slen = length();
   11941   if (str.length() != slen) return false;
   11942   DisallowHeapAllocation no_gc;
   11943   FlatContent content = GetFlatContent();
   11944   if (content.IsOneByte()) {
   11945     return CompareChars(content.ToOneByteVector().start(),
   11946                         str.start(), slen) == 0;
   11947   }
   11948   for (int i = 0; i < slen; i++) {
   11949     if (Get(i) != static_cast<uint16_t>(str[i])) return false;
   11950   }
   11951   return true;
   11952 }
   11953 
   11954 
   11955 bool String::IsTwoByteEqualTo(Vector<const uc16> str) {
   11956   int slen = length();
   11957   if (str.length() != slen) return false;
   11958   DisallowHeapAllocation no_gc;
   11959   FlatContent content = GetFlatContent();
   11960   if (content.IsTwoByte()) {
   11961     return CompareChars(content.ToUC16Vector().start(), str.start(), slen) == 0;
   11962   }
   11963   for (int i = 0; i < slen; i++) {
   11964     if (Get(i) != str[i]) return false;
   11965   }
   11966   return true;
   11967 }
   11968 
   11969 
   11970 uint32_t String::ComputeAndSetHash() {
   11971   // Should only be called if hash code has not yet been computed.
   11972   DCHECK(!HasHashCode());
   11973 
   11974   // Store the hash code in the object.
   11975   uint32_t field = IteratingStringHasher::Hash(this, GetHeap()->HashSeed());
   11976   set_hash_field(field);
   11977 
   11978   // Check the hash code is there.
   11979   DCHECK(HasHashCode());
   11980   uint32_t result = field >> kHashShift;
   11981   DCHECK(result != 0);  // Ensure that the hash value of 0 is never computed.
   11982   return result;
   11983 }
   11984 
   11985 
   11986 bool String::ComputeArrayIndex(uint32_t* index) {
   11987   int length = this->length();
   11988   if (length == 0 || length > kMaxArrayIndexSize) return false;
   11989   StringCharacterStream stream(this);
   11990   return StringToArrayIndex(&stream, index);
   11991 }
   11992 
   11993 
   11994 bool String::SlowAsArrayIndex(uint32_t* index) {
   11995   if (length() <= kMaxCachedArrayIndexLength) {
   11996     Hash();  // force computation of hash code
   11997     uint32_t field = hash_field();
   11998     if ((field & kIsNotArrayIndexMask) != 0) return false;
   11999     // Isolate the array index form the full hash field.
   12000     *index = ArrayIndexValueBits::decode(field);
   12001     return true;
   12002   } else {
   12003     return ComputeArrayIndex(index);
   12004   }
   12005 }
   12006 
   12007 
   12008 Handle<String> SeqString::Truncate(Handle<SeqString> string, int new_length) {
   12009   int new_size, old_size;
   12010   int old_length = string->length();
   12011   if (old_length <= new_length) return string;
   12012 
   12013   if (string->IsSeqOneByteString()) {
   12014     old_size = SeqOneByteString::SizeFor(old_length);
   12015     new_size = SeqOneByteString::SizeFor(new_length);
   12016   } else {
   12017     DCHECK(string->IsSeqTwoByteString());
   12018     old_size = SeqTwoByteString::SizeFor(old_length);
   12019     new_size = SeqTwoByteString::SizeFor(new_length);
   12020   }
   12021 
   12022   int delta = old_size - new_size;
   12023 
   12024   Address start_of_string = string->address();
   12025   DCHECK_OBJECT_ALIGNED(start_of_string);
   12026   DCHECK_OBJECT_ALIGNED(start_of_string + new_size);
   12027 
   12028   Heap* heap = string->GetHeap();
   12029   // Sizes are pointer size aligned, so that we can use filler objects
   12030   // that are a multiple of pointer size.
   12031   heap->CreateFillerObjectAt(start_of_string + new_size, delta,
   12032                              ClearRecordedSlots::kNo);
   12033   heap->AdjustLiveBytes(*string, -delta, Heap::CONCURRENT_TO_SWEEPER);
   12034 
   12035   // We are storing the new length using release store after creating a filler
   12036   // for the left-over space to avoid races with the sweeper thread.
   12037   string->synchronized_set_length(new_length);
   12038 
   12039   if (new_length == 0) return heap->isolate()->factory()->empty_string();
   12040   return string;
   12041 }
   12042 
   12043 
   12044 uint32_t StringHasher::MakeArrayIndexHash(uint32_t value, int length) {
   12045   // For array indexes mix the length into the hash as an array index could
   12046   // be zero.
   12047   DCHECK(length > 0);
   12048   DCHECK(length <= String::kMaxArrayIndexSize);
   12049   DCHECK(TenToThe(String::kMaxCachedArrayIndexLength) <
   12050          (1 << String::kArrayIndexValueBits));
   12051 
   12052   value <<= String::ArrayIndexValueBits::kShift;
   12053   value |= length << String::ArrayIndexLengthBits::kShift;
   12054 
   12055   DCHECK((value & String::kIsNotArrayIndexMask) == 0);
   12056   DCHECK_EQ(length <= String::kMaxCachedArrayIndexLength,
   12057             (value & String::kContainsCachedArrayIndexMask) == 0);
   12058   return value;
   12059 }
   12060 
   12061 
   12062 uint32_t StringHasher::GetHashField() {
   12063   if (length_ <= String::kMaxHashCalcLength) {
   12064     if (is_array_index_) {
   12065       return MakeArrayIndexHash(array_index_, length_);
   12066     }
   12067     return (GetHashCore(raw_running_hash_) << String::kHashShift) |
   12068            String::kIsNotArrayIndexMask;
   12069   } else {
   12070     return (length_ << String::kHashShift) | String::kIsNotArrayIndexMask;
   12071   }
   12072 }
   12073 
   12074 
   12075 uint32_t StringHasher::ComputeUtf8Hash(Vector<const char> chars,
   12076                                        uint32_t seed,
   12077                                        int* utf16_length_out) {
   12078   int vector_length = chars.length();
   12079   // Handle some edge cases
   12080   if (vector_length <= 1) {
   12081     DCHECK(vector_length == 0 ||
   12082            static_cast<uint8_t>(chars.start()[0]) <=
   12083                unibrow::Utf8::kMaxOneByteChar);
   12084     *utf16_length_out = vector_length;
   12085     return HashSequentialString(chars.start(), vector_length, seed);
   12086   }
   12087   // Start with a fake length which won't affect computation.
   12088   // It will be updated later.
   12089   StringHasher hasher(String::kMaxArrayIndexSize, seed);
   12090   size_t remaining = static_cast<size_t>(vector_length);
   12091   const uint8_t* stream = reinterpret_cast<const uint8_t*>(chars.start());
   12092   int utf16_length = 0;
   12093   bool is_index = true;
   12094   DCHECK(hasher.is_array_index_);
   12095   while (remaining > 0) {
   12096     size_t consumed = 0;
   12097     uint32_t c = unibrow::Utf8::ValueOf(stream, remaining, &consumed);
   12098     DCHECK(consumed > 0 && consumed <= remaining);
   12099     stream += consumed;
   12100     remaining -= consumed;
   12101     bool is_two_characters = c > unibrow::Utf16::kMaxNonSurrogateCharCode;
   12102     utf16_length += is_two_characters ? 2 : 1;
   12103     // No need to keep hashing. But we do need to calculate utf16_length.
   12104     if (utf16_length > String::kMaxHashCalcLength) continue;
   12105     if (is_two_characters) {
   12106       uint16_t c1 = unibrow::Utf16::LeadSurrogate(c);
   12107       uint16_t c2 = unibrow::Utf16::TrailSurrogate(c);
   12108       hasher.AddCharacter(c1);
   12109       hasher.AddCharacter(c2);
   12110       if (is_index) is_index = hasher.UpdateIndex(c1);
   12111       if (is_index) is_index = hasher.UpdateIndex(c2);
   12112     } else {
   12113       hasher.AddCharacter(c);
   12114       if (is_index) is_index = hasher.UpdateIndex(c);
   12115     }
   12116   }
   12117   *utf16_length_out = static_cast<int>(utf16_length);
   12118   // Must set length here so that hash computation is correct.
   12119   hasher.length_ = utf16_length;
   12120   return hasher.GetHashField();
   12121 }
   12122 
   12123 
   12124 void IteratingStringHasher::VisitConsString(ConsString* cons_string) {
   12125   // Run small ConsStrings through ConsStringIterator.
   12126   if (cons_string->length() < 64) {
   12127     ConsStringIterator iter(cons_string);
   12128     int offset;
   12129     String* string;
   12130     while (nullptr != (string = iter.Next(&offset))) {
   12131       DCHECK_EQ(0, offset);
   12132       String::VisitFlat(this, string, 0);
   12133     }
   12134     return;
   12135   }
   12136   // Slow case.
   12137   const int max_length = String::kMaxHashCalcLength;
   12138   int length = std::min(cons_string->length(), max_length);
   12139   if (cons_string->HasOnlyOneByteChars()) {
   12140     uint8_t* buffer = new uint8_t[length];
   12141     String::WriteToFlat(cons_string, buffer, 0, length);
   12142     AddCharacters(buffer, length);
   12143     delete[] buffer;
   12144   } else {
   12145     uint16_t* buffer = new uint16_t[length];
   12146     String::WriteToFlat(cons_string, buffer, 0, length);
   12147     AddCharacters(buffer, length);
   12148     delete[] buffer;
   12149   }
   12150 }
   12151 
   12152 
   12153 void String::PrintOn(FILE* file) {
   12154   int length = this->length();
   12155   for (int i = 0; i < length; i++) {
   12156     PrintF(file, "%c", Get(i));
   12157   }
   12158 }
   12159 
   12160 
   12161 int Map::Hash() {
   12162   // For performance reasons we only hash the 3 most variable fields of a map:
   12163   // constructor, prototype and bit_field2. For predictability reasons we
   12164   // use objects' offsets in respective pages for hashing instead of raw
   12165   // addresses.
   12166 
   12167   // Shift away the tag.
   12168   int hash = ObjectAddressForHashing(GetConstructor()) >> 2;
   12169 
   12170   // XOR-ing the prototype and constructor directly yields too many zero bits
   12171   // when the two pointers are close (which is fairly common).
   12172   // To avoid this we shift the prototype bits relatively to the constructor.
   12173   hash ^= ObjectAddressForHashing(prototype()) << (32 - kPageSizeBits);
   12174 
   12175   return hash ^ (hash >> 16) ^ bit_field2();
   12176 }
   12177 
   12178 
   12179 namespace {
   12180 
   12181 bool CheckEquivalent(Map* first, Map* second) {
   12182   return first->GetConstructor() == second->GetConstructor() &&
   12183          first->prototype() == second->prototype() &&
   12184          first->instance_type() == second->instance_type() &&
   12185          first->bit_field() == second->bit_field() &&
   12186          first->is_extensible() == second->is_extensible() &&
   12187          first->new_target_is_base() == second->new_target_is_base() &&
   12188          first->has_hidden_prototype() == second->has_hidden_prototype();
   12189 }
   12190 
   12191 }  // namespace
   12192 
   12193 
   12194 bool Map::EquivalentToForTransition(Map* other) {
   12195   if (!CheckEquivalent(this, other)) return false;
   12196   if (instance_type() == JS_FUNCTION_TYPE) {
   12197     // JSFunctions require more checks to ensure that sloppy function is
   12198     // not equvalent to strict function.
   12199     int nof = Min(NumberOfOwnDescriptors(), other->NumberOfOwnDescriptors());
   12200     return instance_descriptors()->IsEqualUpTo(other->instance_descriptors(),
   12201                                                nof);
   12202   }
   12203   return true;
   12204 }
   12205 
   12206 
   12207 bool Map::EquivalentToForNormalization(Map* other,
   12208                                        PropertyNormalizationMode mode) {
   12209   int properties =
   12210       mode == CLEAR_INOBJECT_PROPERTIES ? 0 : other->GetInObjectProperties();
   12211   return CheckEquivalent(this, other) && bit_field2() == other->bit_field2() &&
   12212          GetInObjectProperties() == properties;
   12213 }
   12214 
   12215 
   12216 bool JSFunction::Inlines(SharedFunctionInfo* candidate) {
   12217   DisallowHeapAllocation no_gc;
   12218   if (shared() == candidate) return true;
   12219   if (code()->kind() != Code::OPTIMIZED_FUNCTION) return false;
   12220   DeoptimizationInputData* const data =
   12221       DeoptimizationInputData::cast(code()->deoptimization_data());
   12222   if (data->length() == 0) return false;
   12223   FixedArray* const literals = data->LiteralArray();
   12224   int const inlined_count = data->InlinedFunctionCount()->value();
   12225   for (int i = 0; i < inlined_count; ++i) {
   12226     if (SharedFunctionInfo::cast(literals->get(i)) == candidate) {
   12227       return true;
   12228     }
   12229   }
   12230   return false;
   12231 }
   12232 
   12233 void JSFunction::MarkForBaseline() {
   12234   Isolate* isolate = GetIsolate();
   12235   set_code_no_write_barrier(
   12236       isolate->builtins()->builtin(Builtins::kCompileBaseline));
   12237   // No write barrier required, since the builtin is part of the root set.
   12238   if (FLAG_mark_shared_functions_for_tier_up) {
   12239     shared()->set_marked_for_tier_up(true);
   12240   }
   12241 }
   12242 
   12243 void JSFunction::MarkForOptimization() {
   12244   Isolate* isolate = GetIsolate();
   12245   DCHECK(!IsOptimized());
   12246   DCHECK(shared()->allows_lazy_compilation() ||
   12247          !shared()->optimization_disabled());
   12248   set_code_no_write_barrier(
   12249       isolate->builtins()->builtin(Builtins::kCompileOptimized));
   12250   // No write barrier required, since the builtin is part of the root set.
   12251   if (FLAG_mark_shared_functions_for_tier_up) {
   12252     shared()->set_marked_for_tier_up(true);
   12253   }
   12254 }
   12255 
   12256 
   12257 void JSFunction::AttemptConcurrentOptimization() {
   12258   Isolate* isolate = GetIsolate();
   12259   if (!isolate->concurrent_recompilation_enabled() ||
   12260       isolate->bootstrapper()->IsActive()) {
   12261     MarkForOptimization();
   12262     return;
   12263   }
   12264   DCHECK(!IsInOptimizationQueue());
   12265   DCHECK(!IsOptimized());
   12266   DCHECK(shared()->allows_lazy_compilation() ||
   12267          !shared()->optimization_disabled());
   12268   DCHECK(isolate->concurrent_recompilation_enabled());
   12269   if (FLAG_trace_concurrent_recompilation) {
   12270     PrintF("  ** Marking ");
   12271     ShortPrint();
   12272     PrintF(" for concurrent recompilation.\n");
   12273   }
   12274 
   12275   set_code_no_write_barrier(
   12276       isolate->builtins()->builtin(Builtins::kCompileOptimizedConcurrent));
   12277   // No write barrier required, since the builtin is part of the root set.
   12278   if (FLAG_mark_shared_functions_for_tier_up) {
   12279     // TODO(leszeks): The compilation isn't concurrent if we trigger it using
   12280     // this bit.
   12281     shared()->set_marked_for_tier_up(true);
   12282   }
   12283 }
   12284 
   12285 // static
   12286 Handle<LiteralsArray> SharedFunctionInfo::FindOrCreateLiterals(
   12287     Handle<SharedFunctionInfo> shared, Handle<Context> native_context) {
   12288   Isolate* isolate = shared->GetIsolate();
   12289   CodeAndLiterals result =
   12290       shared->SearchOptimizedCodeMap(*native_context, BailoutId::None());
   12291   if (result.literals != nullptr) {
   12292     DCHECK(shared->feedback_metadata()->is_empty() ||
   12293            !result.literals->feedback_vector()->is_empty());
   12294     return handle(result.literals, isolate);
   12295   }
   12296 
   12297   Handle<TypeFeedbackVector> feedback_vector =
   12298       TypeFeedbackVector::New(isolate, handle(shared->feedback_metadata()));
   12299   Handle<LiteralsArray> literals =
   12300       LiteralsArray::New(isolate, feedback_vector, shared->num_literals());
   12301   Handle<Code> code;
   12302   if (result.code != nullptr) {
   12303     code = Handle<Code>(result.code, isolate);
   12304   }
   12305   AddToOptimizedCodeMap(shared, native_context, code, literals,
   12306                         BailoutId::None());
   12307   return literals;
   12308 }
   12309 
   12310 // static
   12311 void SharedFunctionInfo::AddToOptimizedCodeMap(
   12312     Handle<SharedFunctionInfo> shared, Handle<Context> native_context,
   12313     MaybeHandle<Code> code, Handle<LiteralsArray> literals,
   12314     BailoutId osr_ast_id) {
   12315   Isolate* isolate = shared->GetIsolate();
   12316   if (isolate->serializer_enabled()) return;
   12317   DCHECK(code.is_null() ||
   12318          code.ToHandleChecked()->kind() == Code::OPTIMIZED_FUNCTION);
   12319   DCHECK(native_context->IsNativeContext());
   12320   STATIC_ASSERT(kEntryLength == 4);
   12321   Handle<FixedArray> new_code_map;
   12322   int entry;
   12323 
   12324   if (shared->OptimizedCodeMapIsCleared()) {
   12325     new_code_map = isolate->factory()->NewFixedArray(kInitialLength, TENURED);
   12326     entry = kEntriesStart;
   12327   } else {
   12328     Handle<FixedArray> old_code_map(shared->optimized_code_map(), isolate);
   12329     entry = shared->SearchOptimizedCodeMapEntry(*native_context, osr_ast_id);
   12330     if (entry >= kEntriesStart) {
   12331       // Just set the code and literals of the entry.
   12332       if (!code.is_null()) {
   12333         Handle<WeakCell> code_cell =
   12334             isolate->factory()->NewWeakCell(code.ToHandleChecked());
   12335         old_code_map->set(entry + kCachedCodeOffset, *code_cell);
   12336       }
   12337       Handle<WeakCell> literals_cell =
   12338           isolate->factory()->NewWeakCell(literals);
   12339       old_code_map->set(entry + kLiteralsOffset, *literals_cell);
   12340       return;
   12341     }
   12342 
   12343     // Can we reuse an entry?
   12344     DCHECK(entry < kEntriesStart);
   12345     int length = old_code_map->length();
   12346     for (int i = kEntriesStart; i < length; i += kEntryLength) {
   12347       if (WeakCell::cast(old_code_map->get(i + kContextOffset))->cleared()) {
   12348         new_code_map = old_code_map;
   12349         entry = i;
   12350         break;
   12351       }
   12352     }
   12353 
   12354     if (entry < kEntriesStart) {
   12355       // Copy old optimized code map and append one new entry.
   12356       new_code_map = isolate->factory()->CopyFixedArrayAndGrow(
   12357           old_code_map, kEntryLength, TENURED);
   12358       // TODO(mstarzinger): Temporary workaround. The allocation above might
   12359       // have flushed the optimized code map and the copy we created is full of
   12360       // holes. For now we just give up on adding the entry and pretend it got
   12361       // flushed.
   12362       if (shared->OptimizedCodeMapIsCleared()) return;
   12363       entry = old_code_map->length();
   12364     }
   12365   }
   12366 
   12367   Handle<WeakCell> code_cell =
   12368       code.is_null() ? isolate->factory()->empty_weak_cell()
   12369                      : isolate->factory()->NewWeakCell(code.ToHandleChecked());
   12370   Handle<WeakCell> literals_cell = isolate->factory()->NewWeakCell(literals);
   12371   WeakCell* context_cell = native_context->self_weak_cell();
   12372 
   12373   new_code_map->set(entry + kContextOffset, context_cell);
   12374   new_code_map->set(entry + kCachedCodeOffset, *code_cell);
   12375   new_code_map->set(entry + kLiteralsOffset, *literals_cell);
   12376   new_code_map->set(entry + kOsrAstIdOffset, Smi::FromInt(osr_ast_id.ToInt()));
   12377 
   12378 #ifdef DEBUG
   12379   for (int i = kEntriesStart; i < new_code_map->length(); i += kEntryLength) {
   12380     WeakCell* cell = WeakCell::cast(new_code_map->get(i + kContextOffset));
   12381     DCHECK(cell->cleared() || cell->value()->IsNativeContext());
   12382     cell = WeakCell::cast(new_code_map->get(i + kCachedCodeOffset));
   12383     DCHECK(cell->cleared() ||
   12384            (cell->value()->IsCode() &&
   12385             Code::cast(cell->value())->kind() == Code::OPTIMIZED_FUNCTION));
   12386     cell = WeakCell::cast(new_code_map->get(i + kLiteralsOffset));
   12387     DCHECK(cell->cleared() || cell->value()->IsFixedArray());
   12388     DCHECK(new_code_map->get(i + kOsrAstIdOffset)->IsSmi());
   12389   }
   12390 #endif
   12391 
   12392   FixedArray* old_code_map = shared->optimized_code_map();
   12393   if (old_code_map != *new_code_map) {
   12394     shared->set_optimized_code_map(*new_code_map);
   12395   }
   12396 }
   12397 
   12398 
   12399 void SharedFunctionInfo::ClearOptimizedCodeMap() {
   12400   FixedArray* empty_fixed_array = GetHeap()->empty_fixed_array();
   12401   set_optimized_code_map(empty_fixed_array, SKIP_WRITE_BARRIER);
   12402 }
   12403 
   12404 
   12405 void SharedFunctionInfo::EvictFromOptimizedCodeMap(Code* optimized_code,
   12406                                                    const char* reason) {
   12407   DisallowHeapAllocation no_gc;
   12408   if (OptimizedCodeMapIsCleared()) return;
   12409 
   12410   Heap* heap = GetHeap();
   12411   FixedArray* code_map = optimized_code_map();
   12412   int dst = kEntriesStart;
   12413   int length = code_map->length();
   12414   for (int src = kEntriesStart; src < length; src += kEntryLength) {
   12415     DCHECK(WeakCell::cast(code_map->get(src))->cleared() ||
   12416            WeakCell::cast(code_map->get(src))->value()->IsNativeContext());
   12417     if (WeakCell::cast(code_map->get(src + kCachedCodeOffset))->value() ==
   12418         optimized_code) {
   12419       BailoutId osr(Smi::cast(code_map->get(src + kOsrAstIdOffset))->value());
   12420       if (FLAG_trace_opt) {
   12421         PrintF("[evicting entry from optimizing code map (%s) for ", reason);
   12422         ShortPrint();
   12423         if (osr.IsNone()) {
   12424           PrintF("]\n");
   12425         } else {
   12426           PrintF(" (osr ast id %d)]\n", osr.ToInt());
   12427         }
   12428       }
   12429       if (!osr.IsNone()) {
   12430         // Evict the src entry by not copying it to the dst entry.
   12431         continue;
   12432       }
   12433       // In case of non-OSR entry just clear the code in order to proceed
   12434       // sharing literals.
   12435       code_map->set(src + kCachedCodeOffset, heap->empty_weak_cell(),
   12436                     SKIP_WRITE_BARRIER);
   12437     }
   12438 
   12439     // Keep the src entry by copying it to the dst entry.
   12440     if (dst != src) {
   12441       code_map->set(dst + kContextOffset, code_map->get(src + kContextOffset));
   12442       code_map->set(dst + kCachedCodeOffset,
   12443                     code_map->get(src + kCachedCodeOffset));
   12444       code_map->set(dst + kLiteralsOffset,
   12445                     code_map->get(src + kLiteralsOffset));
   12446       code_map->set(dst + kOsrAstIdOffset,
   12447                     code_map->get(src + kOsrAstIdOffset));
   12448     }
   12449     dst += kEntryLength;
   12450   }
   12451   if (dst != length) {
   12452     // Always trim even when array is cleared because of heap verifier.
   12453     heap->RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>(code_map,
   12454                                                            length - dst);
   12455     if (code_map->length() == kEntriesStart) {
   12456       ClearOptimizedCodeMap();
   12457     }
   12458   }
   12459 }
   12460 
   12461 
   12462 void SharedFunctionInfo::TrimOptimizedCodeMap(int shrink_by) {
   12463   FixedArray* code_map = optimized_code_map();
   12464   DCHECK(shrink_by % kEntryLength == 0);
   12465   DCHECK(shrink_by <= code_map->length() - kEntriesStart);
   12466   // Always trim even when array is cleared because of heap verifier.
   12467   GetHeap()->RightTrimFixedArray<Heap::SEQUENTIAL_TO_SWEEPER>(code_map,
   12468                                                               shrink_by);
   12469   if (code_map->length() == kEntriesStart) {
   12470     ClearOptimizedCodeMap();
   12471   }
   12472 }
   12473 
   12474 // static
   12475 void JSFunction::EnsureLiterals(Handle<JSFunction> function) {
   12476   Handle<SharedFunctionInfo> shared(function->shared());
   12477   Handle<Context> native_context(function->context()->native_context());
   12478   if (function->literals() ==
   12479       function->GetIsolate()->heap()->empty_literals_array()) {
   12480     Handle<LiteralsArray> literals =
   12481         SharedFunctionInfo::FindOrCreateLiterals(shared, native_context);
   12482     function->set_literals(*literals);
   12483   }
   12484 }
   12485 
   12486 static void GetMinInobjectSlack(Map* map, void* data) {
   12487   int slack = map->unused_property_fields();
   12488   if (*reinterpret_cast<int*>(data) > slack) {
   12489     *reinterpret_cast<int*>(data) = slack;
   12490   }
   12491 }
   12492 
   12493 
   12494 static void ShrinkInstanceSize(Map* map, void* data) {
   12495   int slack = *reinterpret_cast<int*>(data);
   12496   map->SetInObjectProperties(map->GetInObjectProperties() - slack);
   12497   map->set_unused_property_fields(map->unused_property_fields() - slack);
   12498   map->set_instance_size(map->instance_size() - slack * kPointerSize);
   12499   map->set_construction_counter(Map::kNoSlackTracking);
   12500 
   12501   // Visitor id might depend on the instance size, recalculate it.
   12502   map->set_visitor_id(Heap::GetStaticVisitorIdForMap(map));
   12503 }
   12504 
   12505 static void StopSlackTracking(Map* map, void* data) {
   12506   map->set_construction_counter(Map::kNoSlackTracking);
   12507 }
   12508 
   12509 void Map::CompleteInobjectSlackTracking() {
   12510   // Has to be an initial map.
   12511   DCHECK(GetBackPointer()->IsUndefined(GetIsolate()));
   12512 
   12513   int slack = unused_property_fields();
   12514   TransitionArray::TraverseTransitionTree(this, &GetMinInobjectSlack, &slack);
   12515   if (slack != 0) {
   12516     // Resize the initial map and all maps in its transition tree.
   12517     TransitionArray::TraverseTransitionTree(this, &ShrinkInstanceSize, &slack);
   12518   } else {
   12519     TransitionArray::TraverseTransitionTree(this, &StopSlackTracking, nullptr);
   12520   }
   12521 }
   12522 
   12523 
   12524 static bool PrototypeBenefitsFromNormalization(Handle<JSObject> object) {
   12525   DisallowHeapAllocation no_gc;
   12526   if (!object->HasFastProperties()) return false;
   12527   Map* map = object->map();
   12528   if (map->is_prototype_map()) return false;
   12529   DescriptorArray* descriptors = map->instance_descriptors();
   12530   for (int i = 0; i < map->NumberOfOwnDescriptors(); i++) {
   12531     PropertyDetails details = descriptors->GetDetails(i);
   12532     if (details.location() == kDescriptor) continue;
   12533     if (details.representation().IsHeapObject() ||
   12534         details.representation().IsTagged()) {
   12535       FieldIndex index = FieldIndex::ForDescriptor(map, i);
   12536       if (object->RawFastPropertyAt(index)->IsJSFunction()) return true;
   12537     }
   12538   }
   12539   return false;
   12540 }
   12541 
   12542 // static
   12543 void JSObject::MakePrototypesFast(Handle<Object> receiver,
   12544                                   WhereToStart where_to_start,
   12545                                   Isolate* isolate) {
   12546   if (!receiver->IsJSReceiver()) return;
   12547   for (PrototypeIterator iter(isolate, Handle<JSReceiver>::cast(receiver),
   12548                               where_to_start);
   12549        !iter.IsAtEnd(); iter.Advance()) {
   12550     Handle<Object> current = PrototypeIterator::GetCurrent(iter);
   12551     if (!current->IsJSObject()) return;
   12552     Handle<JSObject> current_obj = Handle<JSObject>::cast(current);
   12553     Map* current_map = current_obj->map();
   12554     if (current_map->is_prototype_map() &&
   12555         !current_map->should_be_fast_prototype_map()) {
   12556       Handle<Map> map(current_map);
   12557       Map::SetShouldBeFastPrototypeMap(map, true, isolate);
   12558       JSObject::OptimizeAsPrototype(current_obj, FAST_PROTOTYPE);
   12559     }
   12560   }
   12561 }
   12562 
   12563 // static
   12564 void JSObject::OptimizeAsPrototype(Handle<JSObject> object,
   12565                                    PrototypeOptimizationMode mode) {
   12566   if (object->IsJSGlobalObject()) return;
   12567   if (mode == FAST_PROTOTYPE && PrototypeBenefitsFromNormalization(object)) {
   12568     // First normalize to ensure all JSFunctions are DATA_CONSTANT.
   12569     JSObject::NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, 0,
   12570                                   "NormalizeAsPrototype");
   12571   }
   12572   Handle<Map> previous_map(object->map());
   12573   if (object->map()->is_prototype_map()) {
   12574     if (object->map()->should_be_fast_prototype_map() &&
   12575         !object->HasFastProperties()) {
   12576       JSObject::MigrateSlowToFast(object, 0, "OptimizeAsPrototype");
   12577     }
   12578   } else {
   12579     if (object->map() == *previous_map) {
   12580       Handle<Map> new_map = Map::Copy(handle(object->map()), "CopyAsPrototype");
   12581       JSObject::MigrateToMap(object, new_map);
   12582     }
   12583     object->map()->set_is_prototype_map(true);
   12584 
   12585     // Replace the pointer to the exact constructor with the Object function
   12586     // from the same context if undetectable from JS. This is to avoid keeping
   12587     // memory alive unnecessarily.
   12588     Object* maybe_constructor = object->map()->GetConstructor();
   12589     if (maybe_constructor->IsJSFunction()) {
   12590       JSFunction* constructor = JSFunction::cast(maybe_constructor);
   12591       Isolate* isolate = object->GetIsolate();
   12592       if (!constructor->shared()->IsApiFunction() &&
   12593           object->class_name() == isolate->heap()->Object_string()) {
   12594         Context* context = constructor->context()->native_context();
   12595         JSFunction* object_function = context->object_function();
   12596         object->map()->SetConstructor(object_function);
   12597       }
   12598     }
   12599   }
   12600 }
   12601 
   12602 
   12603 // static
   12604 void JSObject::ReoptimizeIfPrototype(Handle<JSObject> object) {
   12605   if (!object->map()->is_prototype_map()) return;
   12606   if (!object->map()->should_be_fast_prototype_map()) return;
   12607   OptimizeAsPrototype(object, FAST_PROTOTYPE);
   12608 }
   12609 
   12610 
   12611 // static
   12612 void JSObject::LazyRegisterPrototypeUser(Handle<Map> user, Isolate* isolate) {
   12613   // Contract: In line with InvalidatePrototypeChains()'s requirements,
   12614   // leaf maps don't need to register as users, only prototypes do.
   12615   DCHECK(user->is_prototype_map());
   12616 
   12617   Handle<Map> current_user = user;
   12618   Handle<PrototypeInfo> current_user_info =
   12619       Map::GetOrCreatePrototypeInfo(user, isolate);
   12620   for (PrototypeIterator iter(user); !iter.IsAtEnd(); iter.Advance()) {
   12621     // Walk up the prototype chain as far as links haven't been registered yet.
   12622     if (current_user_info->registry_slot() != PrototypeInfo::UNREGISTERED) {
   12623       break;
   12624     }
   12625     Handle<Object> maybe_proto = PrototypeIterator::GetCurrent(iter);
   12626     // Proxies on the prototype chain are not supported. They make it
   12627     // impossible to make any assumptions about the prototype chain anyway.
   12628     if (maybe_proto->IsJSProxy()) return;
   12629     Handle<JSObject> proto = Handle<JSObject>::cast(maybe_proto);
   12630     Handle<PrototypeInfo> proto_info =
   12631         Map::GetOrCreatePrototypeInfo(proto, isolate);
   12632     Handle<Object> maybe_registry(proto_info->prototype_users(), isolate);
   12633     int slot = 0;
   12634     Handle<WeakFixedArray> new_array =
   12635         WeakFixedArray::Add(maybe_registry, current_user, &slot);
   12636     current_user_info->set_registry_slot(slot);
   12637     if (!maybe_registry.is_identical_to(new_array)) {
   12638       proto_info->set_prototype_users(*new_array);
   12639     }
   12640     if (FLAG_trace_prototype_users) {
   12641       PrintF("Registering %p as a user of prototype %p (map=%p).\n",
   12642              reinterpret_cast<void*>(*current_user),
   12643              reinterpret_cast<void*>(*proto),
   12644              reinterpret_cast<void*>(proto->map()));
   12645     }
   12646 
   12647     current_user = handle(proto->map(), isolate);
   12648     current_user_info = proto_info;
   12649   }
   12650 }
   12651 
   12652 
   12653 // Can be called regardless of whether |user| was actually registered with
   12654 // |prototype|. Returns true when there was a registration.
   12655 // static
   12656 bool JSObject::UnregisterPrototypeUser(Handle<Map> user, Isolate* isolate) {
   12657   DCHECK(user->is_prototype_map());
   12658   // If it doesn't have a PrototypeInfo, it was never registered.
   12659   if (!user->prototype_info()->IsPrototypeInfo()) return false;
   12660   // If it had no prototype before, see if it had users that might expect
   12661   // registration.
   12662   if (!user->prototype()->IsJSObject()) {
   12663     Object* users =
   12664         PrototypeInfo::cast(user->prototype_info())->prototype_users();
   12665     return users->IsWeakFixedArray();
   12666   }
   12667   Handle<JSObject> prototype(JSObject::cast(user->prototype()), isolate);
   12668   Handle<PrototypeInfo> user_info =
   12669       Map::GetOrCreatePrototypeInfo(user, isolate);
   12670   int slot = user_info->registry_slot();
   12671   if (slot == PrototypeInfo::UNREGISTERED) return false;
   12672   DCHECK(prototype->map()->is_prototype_map());
   12673   Object* maybe_proto_info = prototype->map()->prototype_info();
   12674   // User knows its registry slot, prototype info and user registry must exist.
   12675   DCHECK(maybe_proto_info->IsPrototypeInfo());
   12676   Handle<PrototypeInfo> proto_info(PrototypeInfo::cast(maybe_proto_info),
   12677                                    isolate);
   12678   Object* maybe_registry = proto_info->prototype_users();
   12679   DCHECK(maybe_registry->IsWeakFixedArray());
   12680   DCHECK(WeakFixedArray::cast(maybe_registry)->Get(slot) == *user);
   12681   WeakFixedArray::cast(maybe_registry)->Clear(slot);
   12682   if (FLAG_trace_prototype_users) {
   12683     PrintF("Unregistering %p as a user of prototype %p.\n",
   12684            reinterpret_cast<void*>(*user), reinterpret_cast<void*>(*prototype));
   12685   }
   12686   return true;
   12687 }
   12688 
   12689 
   12690 static void InvalidatePrototypeChainsInternal(Map* map) {
   12691   DCHECK(map->is_prototype_map());
   12692   if (FLAG_trace_prototype_users) {
   12693     PrintF("Invalidating prototype map %p 's cell\n",
   12694            reinterpret_cast<void*>(map));
   12695   }
   12696   Object* maybe_proto_info = map->prototype_info();
   12697   if (!maybe_proto_info->IsPrototypeInfo()) return;
   12698   PrototypeInfo* proto_info = PrototypeInfo::cast(maybe_proto_info);
   12699   Object* maybe_cell = proto_info->validity_cell();
   12700   if (maybe_cell->IsCell()) {
   12701     // Just set the value; the cell will be replaced lazily.
   12702     Cell* cell = Cell::cast(maybe_cell);
   12703     cell->set_value(Smi::FromInt(Map::kPrototypeChainInvalid));
   12704   }
   12705 
   12706   WeakFixedArray::Iterator iterator(proto_info->prototype_users());
   12707   // For now, only maps register themselves as users.
   12708   Map* user;
   12709   while ((user = iterator.Next<Map>())) {
   12710     // Walk the prototype chain (backwards, towards leaf objects) if necessary.
   12711     InvalidatePrototypeChainsInternal(user);
   12712   }
   12713 }
   12714 
   12715 
   12716 // static
   12717 void JSObject::InvalidatePrototypeChains(Map* map) {
   12718   DisallowHeapAllocation no_gc;
   12719   InvalidatePrototypeChainsInternal(map);
   12720 }
   12721 
   12722 
   12723 // static
   12724 Handle<PrototypeInfo> Map::GetOrCreatePrototypeInfo(Handle<JSObject> prototype,
   12725                                                     Isolate* isolate) {
   12726   Object* maybe_proto_info = prototype->map()->prototype_info();
   12727   if (maybe_proto_info->IsPrototypeInfo()) {
   12728     return handle(PrototypeInfo::cast(maybe_proto_info), isolate);
   12729   }
   12730   Handle<PrototypeInfo> proto_info = isolate->factory()->NewPrototypeInfo();
   12731   prototype->map()->set_prototype_info(*proto_info);
   12732   return proto_info;
   12733 }
   12734 
   12735 
   12736 // static
   12737 Handle<PrototypeInfo> Map::GetOrCreatePrototypeInfo(Handle<Map> prototype_map,
   12738                                                     Isolate* isolate) {
   12739   Object* maybe_proto_info = prototype_map->prototype_info();
   12740   if (maybe_proto_info->IsPrototypeInfo()) {
   12741     return handle(PrototypeInfo::cast(maybe_proto_info), isolate);
   12742   }
   12743   Handle<PrototypeInfo> proto_info = isolate->factory()->NewPrototypeInfo();
   12744   prototype_map->set_prototype_info(*proto_info);
   12745   return proto_info;
   12746 }
   12747 
   12748 // static
   12749 void Map::SetShouldBeFastPrototypeMap(Handle<Map> map, bool value,
   12750                                       Isolate* isolate) {
   12751   if (value == false && !map->prototype_info()->IsPrototypeInfo()) {
   12752     // "False" is the implicit default value, so there's nothing to do.
   12753     return;
   12754   }
   12755   GetOrCreatePrototypeInfo(map, isolate)->set_should_be_fast_map(value);
   12756 }
   12757 
   12758 // static
   12759 Handle<Cell> Map::GetOrCreatePrototypeChainValidityCell(Handle<Map> map,
   12760                                                         Isolate* isolate) {
   12761   Handle<Object> maybe_prototype(
   12762       map->GetPrototypeChainRootMap(isolate)->prototype(), isolate);
   12763   if (!maybe_prototype->IsJSObject()) return Handle<Cell>::null();
   12764   Handle<JSObject> prototype = Handle<JSObject>::cast(maybe_prototype);
   12765   // Ensure the prototype is registered with its own prototypes so its cell
   12766   // will be invalidated when necessary.
   12767   JSObject::LazyRegisterPrototypeUser(handle(prototype->map(), isolate),
   12768                                       isolate);
   12769   Handle<PrototypeInfo> proto_info =
   12770       GetOrCreatePrototypeInfo(prototype, isolate);
   12771   Object* maybe_cell = proto_info->validity_cell();
   12772   // Return existing cell if it's still valid.
   12773   if (maybe_cell->IsCell()) {
   12774     Handle<Cell> cell(Cell::cast(maybe_cell), isolate);
   12775     if (cell->value() == Smi::FromInt(Map::kPrototypeChainValid)) {
   12776       return cell;
   12777     }
   12778   }
   12779   // Otherwise create a new cell.
   12780   Handle<Cell> cell = isolate->factory()->NewCell(
   12781       handle(Smi::FromInt(Map::kPrototypeChainValid), isolate));
   12782   proto_info->set_validity_cell(*cell);
   12783   return cell;
   12784 }
   12785 
   12786 // static
   12787 Handle<WeakCell> Map::GetOrCreatePrototypeWeakCell(Handle<JSObject> prototype,
   12788                                                    Isolate* isolate) {
   12789   DCHECK(!prototype.is_null());
   12790   Handle<PrototypeInfo> proto_info =
   12791       GetOrCreatePrototypeInfo(prototype, isolate);
   12792   Object* maybe_cell = proto_info->weak_cell();
   12793   // Return existing cell if it's already created.
   12794   if (maybe_cell->IsWeakCell()) {
   12795     Handle<WeakCell> cell(WeakCell::cast(maybe_cell), isolate);
   12796     DCHECK(!cell->cleared());
   12797     return cell;
   12798   }
   12799   // Otherwise create a new cell.
   12800   Handle<WeakCell> cell = isolate->factory()->NewWeakCell(prototype);
   12801   proto_info->set_weak_cell(*cell);
   12802   return cell;
   12803 }
   12804 
   12805 // static
   12806 void Map::SetPrototype(Handle<Map> map, Handle<Object> prototype,
   12807                        PrototypeOptimizationMode proto_mode) {
   12808   RuntimeCallTimerScope stats_scope(*map, &RuntimeCallStats::Map_SetPrototype);
   12809 
   12810   bool is_hidden = false;
   12811   if (prototype->IsJSObject()) {
   12812     Handle<JSObject> prototype_jsobj = Handle<JSObject>::cast(prototype);
   12813     JSObject::OptimizeAsPrototype(prototype_jsobj, proto_mode);
   12814 
   12815     Object* maybe_constructor = prototype_jsobj->map()->GetConstructor();
   12816     if (maybe_constructor->IsJSFunction()) {
   12817       JSFunction* constructor = JSFunction::cast(maybe_constructor);
   12818       Object* data = constructor->shared()->function_data();
   12819       is_hidden = (data->IsFunctionTemplateInfo() &&
   12820                    FunctionTemplateInfo::cast(data)->hidden_prototype()) ||
   12821                   prototype->IsJSGlobalObject();
   12822     }
   12823   }
   12824   map->set_has_hidden_prototype(is_hidden);
   12825 
   12826   WriteBarrierMode wb_mode = prototype->IsNull(map->GetIsolate())
   12827                                  ? SKIP_WRITE_BARRIER
   12828                                  : UPDATE_WRITE_BARRIER;
   12829   map->set_prototype(*prototype, wb_mode);
   12830 }
   12831 
   12832 
   12833 Handle<Object> CacheInitialJSArrayMaps(
   12834     Handle<Context> native_context, Handle<Map> initial_map) {
   12835   // Replace all of the cached initial array maps in the native context with
   12836   // the appropriate transitioned elements kind maps.
   12837   Handle<Map> current_map = initial_map;
   12838   ElementsKind kind = current_map->elements_kind();
   12839   DCHECK_EQ(GetInitialFastElementsKind(), kind);
   12840   native_context->set(Context::ArrayMapIndex(kind), *current_map);
   12841   for (int i = GetSequenceIndexFromFastElementsKind(kind) + 1;
   12842        i < kFastElementsKindCount; ++i) {
   12843     Handle<Map> new_map;
   12844     ElementsKind next_kind = GetFastElementsKindFromSequenceIndex(i);
   12845     if (Map* maybe_elements_transition = current_map->ElementsTransitionMap()) {
   12846       new_map = handle(maybe_elements_transition);
   12847     } else {
   12848       new_map = Map::CopyAsElementsKind(
   12849           current_map, next_kind, INSERT_TRANSITION);
   12850     }
   12851     DCHECK_EQ(next_kind, new_map->elements_kind());
   12852     native_context->set(Context::ArrayMapIndex(next_kind), *new_map);
   12853     current_map = new_map;
   12854   }
   12855   return initial_map;
   12856 }
   12857 
   12858 
   12859 void JSFunction::SetInstancePrototype(Handle<JSFunction> function,
   12860                                       Handle<Object> value) {
   12861   Isolate* isolate = function->GetIsolate();
   12862 
   12863   DCHECK(value->IsJSReceiver());
   12864 
   12865   // Now some logic for the maps of the objects that are created by using this
   12866   // function as a constructor.
   12867   if (function->has_initial_map()) {
   12868     // If the function has allocated the initial map replace it with a
   12869     // copy containing the new prototype.  Also complete any in-object
   12870     // slack tracking that is in progress at this point because it is
   12871     // still tracking the old copy.
   12872     function->CompleteInobjectSlackTrackingIfActive();
   12873 
   12874     Handle<Map> initial_map(function->initial_map(), isolate);
   12875 
   12876     if (!initial_map->GetIsolate()->bootstrapper()->IsActive() &&
   12877         initial_map->instance_type() == JS_OBJECT_TYPE) {
   12878       // Put the value in the initial map field until an initial map is needed.
   12879       // At that point, a new initial map is created and the prototype is put
   12880       // into the initial map where it belongs.
   12881       function->set_prototype_or_initial_map(*value);
   12882     } else {
   12883       Handle<Map> new_map = Map::Copy(initial_map, "SetInstancePrototype");
   12884       JSFunction::SetInitialMap(function, new_map, value);
   12885 
   12886       // If the function is used as the global Array function, cache the
   12887       // updated initial maps (and transitioned versions) in the native context.
   12888       Handle<Context> native_context(function->context()->native_context(),
   12889                                      isolate);
   12890       Handle<Object> array_function(
   12891           native_context->get(Context::ARRAY_FUNCTION_INDEX), isolate);
   12892       if (array_function->IsJSFunction() &&
   12893           *function == JSFunction::cast(*array_function)) {
   12894         CacheInitialJSArrayMaps(native_context, new_map);
   12895       }
   12896     }
   12897 
   12898     // Deoptimize all code that embeds the previous initial map.
   12899     initial_map->dependent_code()->DeoptimizeDependentCodeGroup(
   12900         isolate, DependentCode::kInitialMapChangedGroup);
   12901   } else {
   12902     // Put the value in the initial map field until an initial map is
   12903     // needed.  At that point, a new initial map is created and the
   12904     // prototype is put into the initial map where it belongs.
   12905     function->set_prototype_or_initial_map(*value);
   12906     if (value->IsJSObject()) {
   12907       // Optimize as prototype to detach it from its transition tree.
   12908       JSObject::OptimizeAsPrototype(Handle<JSObject>::cast(value),
   12909                                     FAST_PROTOTYPE);
   12910     }
   12911   }
   12912   isolate->heap()->ClearInstanceofCache();
   12913 }
   12914 
   12915 
   12916 void JSFunction::SetPrototype(Handle<JSFunction> function,
   12917                               Handle<Object> value) {
   12918   DCHECK(function->IsConstructor() ||
   12919          IsGeneratorFunction(function->shared()->kind()));
   12920   Handle<Object> construct_prototype = value;
   12921 
   12922   // If the value is not a JSReceiver, store the value in the map's
   12923   // constructor field so it can be accessed.  Also, set the prototype
   12924   // used for constructing objects to the original object prototype.
   12925   // See ECMA-262 13.2.2.
   12926   if (!value->IsJSReceiver()) {
   12927     // Copy the map so this does not affect unrelated functions.
   12928     // Remove map transitions because they point to maps with a
   12929     // different prototype.
   12930     Handle<Map> new_map = Map::Copy(handle(function->map()), "SetPrototype");
   12931 
   12932     JSObject::MigrateToMap(function, new_map);
   12933     new_map->SetConstructor(*value);
   12934     new_map->set_non_instance_prototype(true);
   12935     Isolate* isolate = new_map->GetIsolate();
   12936 
   12937     construct_prototype = handle(
   12938         IsGeneratorFunction(function->shared()->kind())
   12939             ? function->context()
   12940                   ->native_context()
   12941                   ->initial_generator_prototype()
   12942             : function->context()->native_context()->initial_object_prototype(),
   12943         isolate);
   12944   } else {
   12945     function->map()->set_non_instance_prototype(false);
   12946   }
   12947 
   12948   return SetInstancePrototype(function, construct_prototype);
   12949 }
   12950 
   12951 
   12952 bool JSFunction::RemovePrototype() {
   12953   Context* native_context = context()->native_context();
   12954   Map* no_prototype_map =
   12955       is_strict(shared()->language_mode())
   12956           ? native_context->strict_function_without_prototype_map()
   12957           : native_context->sloppy_function_without_prototype_map();
   12958 
   12959   if (map() == no_prototype_map) return true;
   12960 
   12961 #ifdef DEBUG
   12962   if (map() != (is_strict(shared()->language_mode())
   12963                     ? native_context->strict_function_map()
   12964                     : native_context->sloppy_function_map())) {
   12965     return false;
   12966   }
   12967 #endif
   12968 
   12969   set_map(no_prototype_map);
   12970   set_prototype_or_initial_map(no_prototype_map->GetHeap()->the_hole_value());
   12971   return true;
   12972 }
   12973 
   12974 
   12975 void JSFunction::SetInitialMap(Handle<JSFunction> function, Handle<Map> map,
   12976                                Handle<Object> prototype) {
   12977   if (map->prototype() != *prototype) {
   12978     Map::SetPrototype(map, prototype, FAST_PROTOTYPE);
   12979   }
   12980   function->set_prototype_or_initial_map(*map);
   12981   map->SetConstructor(*function);
   12982 #if TRACE_MAPS
   12983   if (FLAG_trace_maps) {
   12984     PrintF("[TraceMaps: InitialMap map= %p SFI= %d_%s ]\n",
   12985            reinterpret_cast<void*>(*map), function->shared()->unique_id(),
   12986            function->shared()->DebugName()->ToCString().get());
   12987   }
   12988 #endif
   12989 }
   12990 
   12991 
   12992 #ifdef DEBUG
   12993 namespace {
   12994 
   12995 bool CanSubclassHaveInobjectProperties(InstanceType instance_type) {
   12996   switch (instance_type) {
   12997     case JS_API_OBJECT_TYPE:
   12998     case JS_ARRAY_BUFFER_TYPE:
   12999     case JS_ARRAY_TYPE:
   13000     case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
   13001     case JS_DATA_VIEW_TYPE:
   13002     case JS_DATE_TYPE:
   13003     case JS_FUNCTION_TYPE:
   13004     case JS_GENERATOR_OBJECT_TYPE:
   13005     case JS_MAP_ITERATOR_TYPE:
   13006     case JS_MAP_TYPE:
   13007     case JS_MESSAGE_OBJECT_TYPE:
   13008     case JS_OBJECT_TYPE:
   13009     case JS_ERROR_TYPE:
   13010     case JS_ARGUMENTS_TYPE:
   13011     case JS_PROMISE_TYPE:
   13012     case JS_REGEXP_TYPE:
   13013     case JS_SET_ITERATOR_TYPE:
   13014     case JS_SET_TYPE:
   13015     case JS_SPECIAL_API_OBJECT_TYPE:
   13016     case JS_TYPED_ARRAY_TYPE:
   13017     case JS_VALUE_TYPE:
   13018     case JS_WEAK_MAP_TYPE:
   13019     case JS_WEAK_SET_TYPE:
   13020       return true;
   13021 
   13022     case BYTECODE_ARRAY_TYPE:
   13023     case BYTE_ARRAY_TYPE:
   13024     case CELL_TYPE:
   13025     case CODE_TYPE:
   13026     case FILLER_TYPE:
   13027     case FIXED_ARRAY_TYPE:
   13028     case FIXED_DOUBLE_ARRAY_TYPE:
   13029     case FOREIGN_TYPE:
   13030     case FREE_SPACE_TYPE:
   13031     case HEAP_NUMBER_TYPE:
   13032     case JS_BOUND_FUNCTION_TYPE:
   13033     case JS_GLOBAL_OBJECT_TYPE:
   13034     case JS_GLOBAL_PROXY_TYPE:
   13035     case JS_PROXY_TYPE:
   13036     case MAP_TYPE:
   13037     case MUTABLE_HEAP_NUMBER_TYPE:
   13038     case ODDBALL_TYPE:
   13039     case PROPERTY_CELL_TYPE:
   13040     case SHARED_FUNCTION_INFO_TYPE:
   13041     case SIMD128_VALUE_TYPE:
   13042     case SYMBOL_TYPE:
   13043     case WEAK_CELL_TYPE:
   13044 
   13045 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
   13046   case FIXED_##TYPE##_ARRAY_TYPE:
   13047 #undef TYPED_ARRAY_CASE
   13048 
   13049 #define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE:
   13050       STRUCT_LIST(MAKE_STRUCT_CASE)
   13051 #undef MAKE_STRUCT_CASE
   13052       // We must not end up here for these instance types at all.
   13053       UNREACHABLE();
   13054     // Fall through.
   13055     default:
   13056       return false;
   13057   }
   13058 }
   13059 
   13060 }  // namespace
   13061 #endif
   13062 
   13063 
   13064 void JSFunction::EnsureHasInitialMap(Handle<JSFunction> function) {
   13065   DCHECK(function->IsConstructor() ||
   13066          IsResumableFunction(function->shared()->kind()));
   13067   if (function->has_initial_map()) return;
   13068   Isolate* isolate = function->GetIsolate();
   13069 
   13070   // The constructor should be compiled for the optimization hints to be
   13071   // available.
   13072   Compiler::Compile(function, Compiler::CLEAR_EXCEPTION);
   13073 
   13074   // First create a new map with the size and number of in-object properties
   13075   // suggested by the function.
   13076   InstanceType instance_type;
   13077   if (IsResumableFunction(function->shared()->kind())) {
   13078     instance_type = JS_GENERATOR_OBJECT_TYPE;
   13079   } else {
   13080     instance_type = JS_OBJECT_TYPE;
   13081   }
   13082   int instance_size;
   13083   int in_object_properties;
   13084   function->CalculateInstanceSize(instance_type, 0, &instance_size,
   13085                                   &in_object_properties);
   13086 
   13087   Handle<Map> map = isolate->factory()->NewMap(instance_type, instance_size);
   13088 
   13089   // Fetch or allocate prototype.
   13090   Handle<Object> prototype;
   13091   if (function->has_instance_prototype()) {
   13092     prototype = handle(function->instance_prototype(), isolate);
   13093   } else {
   13094     prototype = isolate->factory()->NewFunctionPrototype(function);
   13095   }
   13096   map->SetInObjectProperties(in_object_properties);
   13097   map->set_unused_property_fields(in_object_properties);
   13098   DCHECK(map->has_fast_object_elements());
   13099 
   13100   // Finally link initial map and constructor function.
   13101   DCHECK(prototype->IsJSReceiver());
   13102   JSFunction::SetInitialMap(function, map, prototype);
   13103   map->StartInobjectSlackTracking();
   13104 }
   13105 
   13106 
   13107 // static
   13108 MaybeHandle<Map> JSFunction::GetDerivedMap(Isolate* isolate,
   13109                                            Handle<JSFunction> constructor,
   13110                                            Handle<JSReceiver> new_target) {
   13111   EnsureHasInitialMap(constructor);
   13112 
   13113   Handle<Map> constructor_initial_map(constructor->initial_map(), isolate);
   13114   if (*new_target == *constructor) return constructor_initial_map;
   13115 
   13116   // Fast case, new.target is a subclass of constructor. The map is cacheable
   13117   // (and may already have been cached). new.target.prototype is guaranteed to
   13118   // be a JSReceiver.
   13119   if (new_target->IsJSFunction()) {
   13120     Handle<JSFunction> function = Handle<JSFunction>::cast(new_target);
   13121 
   13122     // Check that |function|'s initial map still in sync with the |constructor|,
   13123     // otherwise we must create a new initial map for |function|.
   13124     if (function->has_initial_map() &&
   13125         function->initial_map()->GetConstructor() == *constructor) {
   13126       return handle(function->initial_map(), isolate);
   13127     }
   13128 
   13129     // Create a new map with the size and number of in-object properties
   13130     // suggested by |function|.
   13131 
   13132     // Link initial map and constructor function if the new.target is actually a
   13133     // subclass constructor.
   13134     if (IsSubclassConstructor(function->shared()->kind())) {
   13135       Handle<Object> prototype(function->instance_prototype(), isolate);
   13136       InstanceType instance_type = constructor_initial_map->instance_type();
   13137       DCHECK(CanSubclassHaveInobjectProperties(instance_type));
   13138       int internal_fields =
   13139           JSObject::GetInternalFieldCount(*constructor_initial_map);
   13140       int pre_allocated = constructor_initial_map->GetInObjectProperties() -
   13141                           constructor_initial_map->unused_property_fields();
   13142       int instance_size;
   13143       int in_object_properties;
   13144       function->CalculateInstanceSizeForDerivedClass(
   13145           instance_type, internal_fields, &instance_size,
   13146           &in_object_properties);
   13147 
   13148       int unused_property_fields = in_object_properties - pre_allocated;
   13149       Handle<Map> map =
   13150           Map::CopyInitialMap(constructor_initial_map, instance_size,
   13151                               in_object_properties, unused_property_fields);
   13152       map->set_new_target_is_base(false);
   13153 
   13154       JSFunction::SetInitialMap(function, map, prototype);
   13155       map->SetConstructor(*constructor);
   13156       map->set_construction_counter(Map::kNoSlackTracking);
   13157       map->StartInobjectSlackTracking();
   13158       return map;
   13159     }
   13160   }
   13161 
   13162   // Slow path, new.target is either a proxy or can't cache the map.
   13163   // new.target.prototype is not guaranteed to be a JSReceiver, and may need to
   13164   // fall back to the intrinsicDefaultProto.
   13165   Handle<Object> prototype;
   13166   if (new_target->IsJSFunction()) {
   13167     Handle<JSFunction> function = Handle<JSFunction>::cast(new_target);
   13168     // Make sure the new.target.prototype is cached.
   13169     EnsureHasInitialMap(function);
   13170     prototype = handle(function->prototype(), isolate);
   13171   } else {
   13172     Handle<String> prototype_string = isolate->factory()->prototype_string();
   13173     ASSIGN_RETURN_ON_EXCEPTION(
   13174         isolate, prototype,
   13175         JSReceiver::GetProperty(new_target, prototype_string), Map);
   13176     // The above prototype lookup might change the constructor and its
   13177     // prototype, hence we have to reload the initial map.
   13178     EnsureHasInitialMap(constructor);
   13179     constructor_initial_map = handle(constructor->initial_map(), isolate);
   13180   }
   13181 
   13182   // If prototype is not a JSReceiver, fetch the intrinsicDefaultProto from the
   13183   // correct realm. Rather than directly fetching the .prototype, we fetch the
   13184   // constructor that points to the .prototype. This relies on
   13185   // constructor.prototype being FROZEN for those constructors.
   13186   if (!prototype->IsJSReceiver()) {
   13187     Handle<Context> context;
   13188     ASSIGN_RETURN_ON_EXCEPTION(isolate, context,
   13189                                JSReceiver::GetFunctionRealm(new_target), Map);
   13190     DCHECK(context->IsNativeContext());
   13191     Handle<Object> maybe_index = JSReceiver::GetDataProperty(
   13192         constructor, isolate->factory()->native_context_index_symbol());
   13193     int index = maybe_index->IsSmi() ? Smi::cast(*maybe_index)->value()
   13194                                      : Context::OBJECT_FUNCTION_INDEX;
   13195     Handle<JSFunction> realm_constructor(JSFunction::cast(context->get(index)));
   13196     prototype = handle(realm_constructor->prototype(), isolate);
   13197   }
   13198 
   13199   Handle<Map> map = Map::CopyInitialMap(constructor_initial_map);
   13200   map->set_new_target_is_base(false);
   13201   DCHECK(prototype->IsJSReceiver());
   13202   if (map->prototype() != *prototype) {
   13203     Map::SetPrototype(map, prototype, FAST_PROTOTYPE);
   13204   }
   13205   map->SetConstructor(*constructor);
   13206   return map;
   13207 }
   13208 
   13209 
   13210 void JSFunction::PrintName(FILE* out) {
   13211   std::unique_ptr<char[]> name = shared()->DebugName()->ToCString();
   13212   PrintF(out, "%s", name.get());
   13213 }
   13214 
   13215 
   13216 Handle<String> JSFunction::GetName(Handle<JSFunction> function) {
   13217   Isolate* isolate = function->GetIsolate();
   13218   Handle<Object> name =
   13219       JSReceiver::GetDataProperty(function, isolate->factory()->name_string());
   13220   if (name->IsString()) return Handle<String>::cast(name);
   13221   return handle(function->shared()->DebugName(), isolate);
   13222 }
   13223 
   13224 
   13225 Handle<String> JSFunction::GetDebugName(Handle<JSFunction> function) {
   13226   Isolate* isolate = function->GetIsolate();
   13227   Handle<Object> name = JSReceiver::GetDataProperty(
   13228       function, isolate->factory()->display_name_string());
   13229   if (name->IsString()) return Handle<String>::cast(name);
   13230   return JSFunction::GetName(function);
   13231 }
   13232 
   13233 void JSFunction::SetName(Handle<JSFunction> function, Handle<Name> name,
   13234                          Handle<String> prefix) {
   13235   Isolate* isolate = function->GetIsolate();
   13236   Handle<String> function_name = Name::ToFunctionName(name).ToHandleChecked();
   13237   if (prefix->length() > 0) {
   13238     IncrementalStringBuilder builder(isolate);
   13239     builder.AppendString(prefix);
   13240     builder.AppendCharacter(' ');
   13241     builder.AppendString(function_name);
   13242     function_name = builder.Finish().ToHandleChecked();
   13243   }
   13244   JSObject::DefinePropertyOrElementIgnoreAttributes(
   13245       function, isolate->factory()->name_string(), function_name,
   13246       static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY))
   13247       .ToHandleChecked();
   13248 }
   13249 
   13250 namespace {
   13251 
   13252 char const kNativeCodeSource[] = "function () { [native code] }";
   13253 
   13254 
   13255 Handle<String> NativeCodeFunctionSourceString(
   13256     Handle<SharedFunctionInfo> shared_info) {
   13257   Isolate* const isolate = shared_info->GetIsolate();
   13258   if (shared_info->name()->IsString()) {
   13259     IncrementalStringBuilder builder(isolate);
   13260     builder.AppendCString("function ");
   13261     builder.AppendString(handle(String::cast(shared_info->name()), isolate));
   13262     builder.AppendCString("() { [native code] }");
   13263     return builder.Finish().ToHandleChecked();
   13264   }
   13265   return isolate->factory()->NewStringFromAsciiChecked(kNativeCodeSource);
   13266 }
   13267 
   13268 }  // namespace
   13269 
   13270 
   13271 // static
   13272 Handle<String> JSBoundFunction::ToString(Handle<JSBoundFunction> function) {
   13273   Isolate* const isolate = function->GetIsolate();
   13274   return isolate->factory()->NewStringFromAsciiChecked(kNativeCodeSource);
   13275 }
   13276 
   13277 
   13278 // static
   13279 Handle<String> JSFunction::ToString(Handle<JSFunction> function) {
   13280   Isolate* const isolate = function->GetIsolate();
   13281   Handle<SharedFunctionInfo> shared_info(function->shared(), isolate);
   13282 
   13283   // Check if {function} should hide its source code.
   13284   if (!shared_info->script()->IsScript() ||
   13285       Script::cast(shared_info->script())->hide_source()) {
   13286     return NativeCodeFunctionSourceString(shared_info);
   13287   }
   13288 
   13289   // Check if we should print {function} as a class.
   13290   Handle<Object> class_start_position = JSReceiver::GetDataProperty(
   13291       function, isolate->factory()->class_start_position_symbol());
   13292   if (class_start_position->IsSmi()) {
   13293     Handle<Object> class_end_position = JSReceiver::GetDataProperty(
   13294         function, isolate->factory()->class_end_position_symbol());
   13295     Handle<String> script_source(
   13296         String::cast(Script::cast(shared_info->script())->source()), isolate);
   13297     return isolate->factory()->NewSubString(
   13298         script_source, Handle<Smi>::cast(class_start_position)->value(),
   13299         Handle<Smi>::cast(class_end_position)->value());
   13300   }
   13301 
   13302   // Check if we have source code for the {function}.
   13303   if (!shared_info->HasSourceCode()) {
   13304     return NativeCodeFunctionSourceString(shared_info);
   13305   }
   13306 
   13307   IncrementalStringBuilder builder(isolate);
   13308   FunctionKind kind = shared_info->kind();
   13309   if (!IsArrowFunction(kind)) {
   13310     if (IsConciseMethod(kind)) {
   13311       if (IsGeneratorFunction(kind)) {
   13312         builder.AppendCharacter('*');
   13313       } else if (IsAsyncFunction(kind)) {
   13314         builder.AppendCString("async ");
   13315       }
   13316     } else {
   13317       if (IsGeneratorFunction(kind)) {
   13318         builder.AppendCString("function* ");
   13319       } else if (IsAsyncFunction(kind)) {
   13320         builder.AppendCString("async function ");
   13321       } else {
   13322         builder.AppendCString("function ");
   13323       }
   13324     }
   13325     if (shared_info->name_should_print_as_anonymous()) {
   13326       builder.AppendCString("anonymous");
   13327     } else if (!shared_info->is_anonymous_expression()) {
   13328       builder.AppendString(handle(String::cast(shared_info->name()), isolate));
   13329     }
   13330   }
   13331   builder.AppendString(Handle<String>::cast(shared_info->GetSourceCode()));
   13332   return builder.Finish().ToHandleChecked();
   13333 }
   13334 
   13335 void Oddball::Initialize(Isolate* isolate, Handle<Oddball> oddball,
   13336                          const char* to_string, Handle<Object> to_number,
   13337                          const char* type_of, byte kind) {
   13338   Handle<String> internalized_to_string =
   13339       isolate->factory()->InternalizeUtf8String(to_string);
   13340   Handle<String> internalized_type_of =
   13341       isolate->factory()->InternalizeUtf8String(type_of);
   13342   oddball->set_to_number_raw(to_number->Number());
   13343   oddball->set_to_number(*to_number);
   13344   oddball->set_to_string(*internalized_to_string);
   13345   oddball->set_type_of(*internalized_type_of);
   13346   oddball->set_kind(kind);
   13347 }
   13348 
   13349 void Script::SetEvalOrigin(Handle<Script> script,
   13350                            Handle<SharedFunctionInfo> outer_info,
   13351                            int eval_position) {
   13352   if (eval_position == kNoSourcePosition) {
   13353     // If the position is missing, attempt to get the code offset from the
   13354     // current activation.  Do not translate the code offset into source
   13355     // position, but store it as negative value for lazy translation.
   13356     StackTraceFrameIterator it(script->GetIsolate());
   13357     if (!it.done() && it.is_javascript()) {
   13358       FrameSummary summary = FrameSummary::GetFirst(it.javascript_frame());
   13359       script->set_eval_from_shared(summary.function()->shared());
   13360       script->set_eval_from_position(-summary.code_offset());
   13361       return;
   13362     }
   13363     eval_position = 0;
   13364   }
   13365   script->set_eval_from_shared(*outer_info);
   13366   script->set_eval_from_position(eval_position);
   13367 }
   13368 
   13369 int Script::GetEvalPosition() {
   13370   DisallowHeapAllocation no_gc;
   13371   DCHECK(compilation_type() == Script::COMPILATION_TYPE_EVAL);
   13372   int position = eval_from_position();
   13373   if (position < 0) {
   13374     // Due to laziness, the position may not have been translated from code
   13375     // offset yet, which would be encoded as negative integer. In that case,
   13376     // translate and set the position.
   13377     if (eval_from_shared()->IsUndefined(GetIsolate())) {
   13378       position = 0;
   13379     } else {
   13380       SharedFunctionInfo* shared = SharedFunctionInfo::cast(eval_from_shared());
   13381       position = shared->abstract_code()->SourcePosition(-position);
   13382     }
   13383     DCHECK(position >= 0);
   13384     set_eval_from_position(position);
   13385   }
   13386   return position;
   13387 }
   13388 
   13389 void Script::InitLineEnds(Handle<Script> script) {
   13390   Isolate* isolate = script->GetIsolate();
   13391   if (!script->line_ends()->IsUndefined(isolate)) return;
   13392   DCHECK_NE(Script::TYPE_WASM, script->type());
   13393 
   13394   Object* src_obj = script->source();
   13395   if (!src_obj->IsString()) {
   13396     DCHECK(src_obj->IsUndefined(isolate));
   13397     script->set_line_ends(isolate->heap()->empty_fixed_array());
   13398   } else {
   13399     DCHECK(src_obj->IsString());
   13400     Handle<String> src(String::cast(src_obj), isolate);
   13401     Handle<FixedArray> array = String::CalculateLineEnds(src, true);
   13402     script->set_line_ends(*array);
   13403   }
   13404 
   13405   DCHECK(script->line_ends()->IsFixedArray());
   13406 }
   13407 
   13408 bool Script::GetPositionInfo(Handle<Script> script, int position,
   13409                              PositionInfo* info, OffsetFlag offset_flag) {
   13410   // For wasm, we do not create an artificial line_ends array, but do the
   13411   // translation directly.
   13412   if (script->type() == Script::TYPE_WASM) {
   13413     Handle<WasmCompiledModule> compiled_module(
   13414         WasmCompiledModule::cast(script->wasm_compiled_module()));
   13415     DCHECK_LE(0, position);
   13416     return wasm::GetPositionInfo(compiled_module,
   13417                                  static_cast<uint32_t>(position), info);
   13418   }
   13419 
   13420   InitLineEnds(script);
   13421   return script->GetPositionInfo(position, info, offset_flag);
   13422 }
   13423 
   13424 namespace {
   13425 bool GetPositionInfoSlow(const Script* script, int position,
   13426                          Script::PositionInfo* info) {
   13427   if (!script->source()->IsString()) return false;
   13428   if (position < 0) position = 0;
   13429 
   13430   String* source_string = String::cast(script->source());
   13431   int line = 0;
   13432   int line_start = 0;
   13433   int len = source_string->length();
   13434   for (int pos = 0; pos <= len; ++pos) {
   13435     if (pos == len || source_string->Get(pos) == '\n') {
   13436       if (position <= pos) {
   13437         info->line = line;
   13438         info->column = position - line_start;
   13439         info->line_start = line_start;
   13440         info->line_end = pos;
   13441         return true;
   13442       }
   13443       line++;
   13444       line_start = pos + 1;
   13445     }
   13446   }
   13447   return false;
   13448 }
   13449 }  // namespace
   13450 
   13451 #define SMI_VALUE(x) (Smi::cast(x)->value())
   13452 bool Script::GetPositionInfo(int position, PositionInfo* info,
   13453                              OffsetFlag offset_flag) const {
   13454   DisallowHeapAllocation no_allocation;
   13455 
   13456   if (line_ends()->IsUndefined(GetIsolate())) {
   13457     // Slow mode: we do not have line_ends. We have to iterate through source.
   13458     if (!GetPositionInfoSlow(this, position, info)) return false;
   13459   } else {
   13460     DCHECK(line_ends()->IsFixedArray());
   13461     FixedArray* ends = FixedArray::cast(line_ends());
   13462 
   13463     const int ends_len = ends->length();
   13464     if (ends_len == 0) return false;
   13465 
   13466     // Return early on invalid positions. Negative positions behave as if 0 was
   13467     // passed, and positions beyond the end of the script return as failure.
   13468     if (position < 0) {
   13469       position = 0;
   13470     } else if (position > SMI_VALUE(ends->get(ends_len - 1))) {
   13471       return false;
   13472     }
   13473 
   13474     // Determine line number by doing a binary search on the line ends array.
   13475     if (SMI_VALUE(ends->get(0)) >= position) {
   13476       info->line = 0;
   13477       info->line_start = 0;
   13478       info->column = position;
   13479     } else {
   13480       int left = 0;
   13481       int right = ends_len - 1;
   13482 
   13483       while (right > 0) {
   13484         DCHECK_LE(left, right);
   13485         const int mid = (left + right) / 2;
   13486         if (position > SMI_VALUE(ends->get(mid))) {
   13487           left = mid + 1;
   13488         } else if (position <= SMI_VALUE(ends->get(mid - 1))) {
   13489           right = mid - 1;
   13490         } else {
   13491           info->line = mid;
   13492           break;
   13493         }
   13494       }
   13495       DCHECK(SMI_VALUE(ends->get(info->line)) >= position &&
   13496              SMI_VALUE(ends->get(info->line - 1)) < position);
   13497       info->line_start = SMI_VALUE(ends->get(info->line - 1)) + 1;
   13498       info->column = position - info->line_start;
   13499     }
   13500 
   13501     // Line end is position of the linebreak character.
   13502     info->line_end = SMI_VALUE(ends->get(info->line));
   13503     if (info->line_end > 0) {
   13504       DCHECK(source()->IsString());
   13505       String* src = String::cast(source());
   13506       if (src->length() >= info->line_end &&
   13507           src->Get(info->line_end - 1) == '\r') {
   13508         info->line_end--;
   13509       }
   13510     }
   13511   }
   13512 
   13513   // Add offsets if requested.
   13514   if (offset_flag == WITH_OFFSET) {
   13515     if (info->line == 0) {
   13516       info->column += column_offset();
   13517     }
   13518     info->line += line_offset();
   13519   }
   13520 
   13521   return true;
   13522 }
   13523 #undef SMI_VALUE
   13524 
   13525 int Script::GetColumnNumber(Handle<Script> script, int code_pos) {
   13526   PositionInfo info;
   13527   GetPositionInfo(script, code_pos, &info, WITH_OFFSET);
   13528   return info.column;
   13529 }
   13530 
   13531 int Script::GetColumnNumber(int code_pos) const {
   13532   PositionInfo info;
   13533   GetPositionInfo(code_pos, &info, WITH_OFFSET);
   13534   return info.column;
   13535 }
   13536 
   13537 int Script::GetLineNumber(Handle<Script> script, int code_pos) {
   13538   PositionInfo info;
   13539   GetPositionInfo(script, code_pos, &info, WITH_OFFSET);
   13540   return info.line;
   13541 }
   13542 
   13543 int Script::GetLineNumber(int code_pos) const {
   13544   PositionInfo info;
   13545   GetPositionInfo(code_pos, &info, WITH_OFFSET);
   13546   return info.line;
   13547 }
   13548 
   13549 Handle<Object> Script::GetNameOrSourceURL(Handle<Script> script) {
   13550   Isolate* isolate = script->GetIsolate();
   13551 
   13552   // Keep in sync with ScriptNameOrSourceURL in messages.js.
   13553 
   13554   if (!script->source_url()->IsUndefined(isolate)) {
   13555     return handle(script->source_url(), isolate);
   13556   }
   13557   return handle(script->name(), isolate);
   13558 }
   13559 
   13560 
   13561 Handle<JSObject> Script::GetWrapper(Handle<Script> script) {
   13562   Isolate* isolate = script->GetIsolate();
   13563   if (!script->wrapper()->IsUndefined(isolate)) {
   13564     DCHECK(script->wrapper()->IsWeakCell());
   13565     Handle<WeakCell> cell(WeakCell::cast(script->wrapper()));
   13566     if (!cell->cleared()) {
   13567       // Return a handle for the existing script wrapper from the cache.
   13568       return handle(JSObject::cast(cell->value()));
   13569     }
   13570     // If we found an empty WeakCell, that means the script wrapper was
   13571     // GCed.  We are not notified directly of that, so we decrement here
   13572     // so that we at least don't count double for any given script.
   13573     isolate->counters()->script_wrappers()->Decrement();
   13574   }
   13575   // Construct a new script wrapper.
   13576   isolate->counters()->script_wrappers()->Increment();
   13577   Handle<JSFunction> constructor = isolate->script_function();
   13578   Handle<JSValue> result =
   13579       Handle<JSValue>::cast(isolate->factory()->NewJSObject(constructor));
   13580   result->set_value(*script);
   13581   Handle<WeakCell> cell = isolate->factory()->NewWeakCell(result);
   13582   script->set_wrapper(*cell);
   13583   return result;
   13584 }
   13585 
   13586 
   13587 MaybeHandle<SharedFunctionInfo> Script::FindSharedFunctionInfo(
   13588     FunctionLiteral* fun) {
   13589   WeakFixedArray::Iterator iterator(shared_function_infos());
   13590   SharedFunctionInfo* shared;
   13591   while ((shared = iterator.Next<SharedFunctionInfo>())) {
   13592     if (fun->function_token_position() == shared->function_token_position() &&
   13593         fun->start_position() == shared->start_position() &&
   13594         fun->end_position() == shared->end_position()) {
   13595       return Handle<SharedFunctionInfo>(shared);
   13596     }
   13597   }
   13598   return MaybeHandle<SharedFunctionInfo>();
   13599 }
   13600 
   13601 
   13602 Script::Iterator::Iterator(Isolate* isolate)
   13603     : iterator_(isolate->heap()->script_list()) {}
   13604 
   13605 
   13606 Script* Script::Iterator::Next() { return iterator_.Next<Script>(); }
   13607 
   13608 
   13609 SharedFunctionInfo::Iterator::Iterator(Isolate* isolate)
   13610     : script_iterator_(isolate),
   13611       sfi_iterator_(isolate->heap()->noscript_shared_function_infos()) {}
   13612 
   13613 
   13614 bool SharedFunctionInfo::Iterator::NextScript() {
   13615   Script* script = script_iterator_.Next();
   13616   if (script == NULL) return false;
   13617   sfi_iterator_.Reset(script->shared_function_infos());
   13618   return true;
   13619 }
   13620 
   13621 
   13622 SharedFunctionInfo* SharedFunctionInfo::Iterator::Next() {
   13623   do {
   13624     SharedFunctionInfo* next = sfi_iterator_.Next<SharedFunctionInfo>();
   13625     if (next != NULL) return next;
   13626   } while (NextScript());
   13627   return NULL;
   13628 }
   13629 
   13630 
   13631 void SharedFunctionInfo::SetScript(Handle<SharedFunctionInfo> shared,
   13632                                    Handle<Object> script_object) {
   13633   if (shared->script() == *script_object) return;
   13634   Isolate* isolate = shared->GetIsolate();
   13635 
   13636   // Add shared function info to new script's list. If a collection occurs,
   13637   // the shared function info may be temporarily in two lists.
   13638   // This is okay because the gc-time processing of these lists can tolerate
   13639   // duplicates.
   13640   Handle<Object> list;
   13641   if (script_object->IsScript()) {
   13642     Handle<Script> script = Handle<Script>::cast(script_object);
   13643     list = handle(script->shared_function_infos(), isolate);
   13644   } else {
   13645     list = isolate->factory()->noscript_shared_function_infos();
   13646   }
   13647 
   13648 #ifdef DEBUG
   13649   if (FLAG_enable_slow_asserts) {
   13650     WeakFixedArray::Iterator iterator(*list);
   13651     SharedFunctionInfo* next;
   13652     while ((next = iterator.Next<SharedFunctionInfo>())) {
   13653       DCHECK_NE(next, *shared);
   13654     }
   13655   }
   13656 #endif  // DEBUG
   13657   list = WeakFixedArray::Add(list, shared);
   13658 
   13659   if (script_object->IsScript()) {
   13660     Handle<Script> script = Handle<Script>::cast(script_object);
   13661     script->set_shared_function_infos(*list);
   13662   } else {
   13663     isolate->heap()->SetRootNoScriptSharedFunctionInfos(*list);
   13664   }
   13665 
   13666   // Remove shared function info from old script's list.
   13667   if (shared->script()->IsScript()) {
   13668     Script* old_script = Script::cast(shared->script());
   13669     if (old_script->shared_function_infos()->IsWeakFixedArray()) {
   13670       WeakFixedArray* list =
   13671           WeakFixedArray::cast(old_script->shared_function_infos());
   13672       list->Remove(shared);
   13673     }
   13674   } else {
   13675     // Remove shared function info from root array.
   13676     Object* list = isolate->heap()->noscript_shared_function_infos();
   13677     CHECK(WeakFixedArray::cast(list)->Remove(shared));
   13678   }
   13679 
   13680   // Finally set new script.
   13681   shared->set_script(*script_object);
   13682 }
   13683 
   13684 
   13685 String* SharedFunctionInfo::DebugName() {
   13686   Object* n = name();
   13687   if (!n->IsString() || String::cast(n)->length() == 0) return inferred_name();
   13688   return String::cast(n);
   13689 }
   13690 
   13691 // The filter is a pattern that matches function names in this way:
   13692 //   "*"      all; the default
   13693 //   "-"      all but the top-level function
   13694 //   "-name"  all but the function "name"
   13695 //   ""       only the top-level function
   13696 //   "name"   only the function "name"
   13697 //   "name*"  only functions starting with "name"
   13698 //   "~"      none; the tilde is not an identifier
   13699 bool SharedFunctionInfo::PassesFilter(const char* raw_filter) {
   13700   if (*raw_filter == '*') return true;
   13701   String* name = DebugName();
   13702   Vector<const char> filter = CStrVector(raw_filter);
   13703   if (filter.length() == 0) return name->length() == 0;
   13704   if (filter[0] == '-') {
   13705     // Negative filter.
   13706     if (filter.length() == 1) {
   13707       return (name->length() != 0);
   13708     } else if (name->IsUtf8EqualTo(filter.SubVector(1, filter.length()))) {
   13709       return false;
   13710     }
   13711     if (filter[filter.length() - 1] == '*' &&
   13712         name->IsUtf8EqualTo(filter.SubVector(1, filter.length() - 1), true)) {
   13713       return false;
   13714     }
   13715     return true;
   13716 
   13717   } else if (name->IsUtf8EqualTo(filter)) {
   13718     return true;
   13719   }
   13720   if (filter[filter.length() - 1] == '*' &&
   13721       name->IsUtf8EqualTo(filter.SubVector(0, filter.length() - 1), true)) {
   13722     return true;
   13723   }
   13724   return false;
   13725 }
   13726 
   13727 bool SharedFunctionInfo::HasSourceCode() const {
   13728   Isolate* isolate = GetIsolate();
   13729   return !script()->IsUndefined(isolate) &&
   13730          !reinterpret_cast<Script*>(script())->source()->IsUndefined(isolate);
   13731 }
   13732 
   13733 
   13734 Handle<Object> SharedFunctionInfo::GetSourceCode() {
   13735   if (!HasSourceCode()) return GetIsolate()->factory()->undefined_value();
   13736   Handle<String> source(String::cast(Script::cast(script())->source()));
   13737   return GetIsolate()->factory()->NewSubString(
   13738       source, start_position(), end_position());
   13739 }
   13740 
   13741 
   13742 bool SharedFunctionInfo::IsInlineable() {
   13743   // Check that the function has a script associated with it.
   13744   if (!script()->IsScript()) return false;
   13745   return !optimization_disabled();
   13746 }
   13747 
   13748 
   13749 int SharedFunctionInfo::SourceSize() {
   13750   return end_position() - start_position();
   13751 }
   13752 
   13753 void JSFunction::CalculateInstanceSizeHelper(InstanceType instance_type,
   13754                                              int requested_internal_fields,
   13755                                              int requested_in_object_properties,
   13756                                              int* instance_size,
   13757                                              int* in_object_properties) {
   13758   int header_size = JSObject::GetHeaderSize(instance_type);
   13759   DCHECK_LE(requested_internal_fields,
   13760             (JSObject::kMaxInstanceSize - header_size) >> kPointerSizeLog2);
   13761   *instance_size =
   13762       Min(header_size +
   13763               ((requested_internal_fields + requested_in_object_properties)
   13764                << kPointerSizeLog2),
   13765           JSObject::kMaxInstanceSize);
   13766   *in_object_properties = ((*instance_size - header_size) >> kPointerSizeLog2) -
   13767                           requested_internal_fields;
   13768 }
   13769 
   13770 
   13771 void JSFunction::CalculateInstanceSize(InstanceType instance_type,
   13772                                        int requested_internal_fields,
   13773                                        int* instance_size,
   13774                                        int* in_object_properties) {
   13775   CalculateInstanceSizeHelper(instance_type, requested_internal_fields,
   13776                               shared()->expected_nof_properties(),
   13777                               instance_size, in_object_properties);
   13778 }
   13779 
   13780 
   13781 void JSFunction::CalculateInstanceSizeForDerivedClass(
   13782     InstanceType instance_type, int requested_internal_fields,
   13783     int* instance_size, int* in_object_properties) {
   13784   Isolate* isolate = GetIsolate();
   13785   int expected_nof_properties = 0;
   13786   for (PrototypeIterator iter(isolate, this, kStartAtReceiver); !iter.IsAtEnd();
   13787        iter.Advance()) {
   13788     JSReceiver* current = iter.GetCurrent<JSReceiver>();
   13789     if (!current->IsJSFunction()) break;
   13790     JSFunction* func = JSFunction::cast(current);
   13791     SharedFunctionInfo* shared = func->shared();
   13792     expected_nof_properties += shared->expected_nof_properties();
   13793     if (!IsSubclassConstructor(shared->kind())) {
   13794       break;
   13795     }
   13796   }
   13797   CalculateInstanceSizeHelper(instance_type, requested_internal_fields,
   13798                               expected_nof_properties, instance_size,
   13799                               in_object_properties);
   13800 }
   13801 
   13802 
   13803 // Output the source code without any allocation in the heap.
   13804 std::ostream& operator<<(std::ostream& os, const SourceCodeOf& v) {
   13805   const SharedFunctionInfo* s = v.value;
   13806   // For some native functions there is no source.
   13807   if (!s->HasSourceCode()) return os << "<No Source>";
   13808 
   13809   // Get the source for the script which this function came from.
   13810   // Don't use String::cast because we don't want more assertion errors while
   13811   // we are already creating a stack dump.
   13812   String* script_source =
   13813       reinterpret_cast<String*>(Script::cast(s->script())->source());
   13814 
   13815   if (!script_source->LooksValid()) return os << "<Invalid Source>";
   13816 
   13817   if (!s->is_toplevel()) {
   13818     os << "function ";
   13819     Object* name = s->name();
   13820     if (name->IsString() && String::cast(name)->length() > 0) {
   13821       String::cast(name)->PrintUC16(os);
   13822     }
   13823   }
   13824 
   13825   int len = s->end_position() - s->start_position();
   13826   if (len <= v.max_length || v.max_length < 0) {
   13827     script_source->PrintUC16(os, s->start_position(), s->end_position());
   13828     return os;
   13829   } else {
   13830     script_source->PrintUC16(os, s->start_position(),
   13831                              s->start_position() + v.max_length);
   13832     return os << "...\n";
   13833   }
   13834 }
   13835 
   13836 
   13837 static bool IsCodeEquivalent(Code* code, Code* recompiled) {
   13838   if (code->instruction_size() != recompiled->instruction_size()) return false;
   13839   ByteArray* code_relocation = code->relocation_info();
   13840   ByteArray* recompiled_relocation = recompiled->relocation_info();
   13841   int length = code_relocation->length();
   13842   if (length != recompiled_relocation->length()) return false;
   13843   int compare = memcmp(code_relocation->GetDataStartAddress(),
   13844                        recompiled_relocation->GetDataStartAddress(),
   13845                        length);
   13846   return compare == 0;
   13847 }
   13848 
   13849 
   13850 void SharedFunctionInfo::EnableDeoptimizationSupport(Code* recompiled) {
   13851   DCHECK(!has_deoptimization_support());
   13852   DisallowHeapAllocation no_allocation;
   13853   Code* code = this->code();
   13854   if (IsCodeEquivalent(code, recompiled)) {
   13855     // Copy the deoptimization data from the recompiled code.
   13856     code->set_deoptimization_data(recompiled->deoptimization_data());
   13857     code->set_has_deoptimization_support(true);
   13858   } else {
   13859     // TODO(3025757): In case the recompiled isn't equivalent to the
   13860     // old code, we have to replace it. We should try to avoid this
   13861     // altogether because it flushes valuable type feedback by
   13862     // effectively resetting all IC state.
   13863     ReplaceCode(recompiled);
   13864   }
   13865   DCHECK(has_deoptimization_support());
   13866 }
   13867 
   13868 
   13869 void SharedFunctionInfo::DisableOptimization(BailoutReason reason) {
   13870   // Disable optimization for the shared function info and mark the
   13871   // code as non-optimizable. The marker on the shared function info
   13872   // is there because we flush non-optimized code thereby loosing the
   13873   // non-optimizable information for the code. When the code is
   13874   // regenerated and set on the shared function info it is marked as
   13875   // non-optimizable if optimization is disabled for the shared
   13876   // function info.
   13877   DCHECK(reason != kNoReason);
   13878   set_optimization_disabled(true);
   13879   set_disable_optimization_reason(reason);
   13880   // Code should be the lazy compilation stub or else unoptimized.
   13881   DCHECK(abstract_code()->kind() == AbstractCode::FUNCTION ||
   13882          abstract_code()->kind() == AbstractCode::INTERPRETED_FUNCTION ||
   13883          abstract_code()->kind() == AbstractCode::BUILTIN);
   13884   PROFILE(GetIsolate(), CodeDisableOptEvent(abstract_code(), this));
   13885   if (FLAG_trace_opt) {
   13886     PrintF("[disabled optimization for ");
   13887     ShortPrint();
   13888     PrintF(", reason: %s]\n", GetBailoutReason(reason));
   13889   }
   13890 }
   13891 
   13892 namespace {
   13893 
   13894 // Sets the expected number of properties based on estimate from parser.
   13895 void SetExpectedNofPropertiesFromEstimate(Handle<SharedFunctionInfo> shared,
   13896                                           FunctionLiteral* literal) {
   13897   int estimate = literal->expected_property_count();
   13898 
   13899   // If no properties are added in the constructor, they are more likely
   13900   // to be added later.
   13901   if (estimate == 0) estimate = 2;
   13902 
   13903   // TODO(yangguo): check whether those heuristics are still up-to-date.
   13904   // We do not shrink objects that go into a snapshot (yet), so we adjust
   13905   // the estimate conservatively.
   13906   if (shared->GetIsolate()->serializer_enabled()) {
   13907     estimate += 2;
   13908   } else {
   13909     // Inobject slack tracking will reclaim redundant inobject space later,
   13910     // so we can afford to adjust the estimate generously.
   13911     estimate += 8;
   13912   }
   13913 
   13914   shared->set_expected_nof_properties(estimate);
   13915 }
   13916 
   13917 }  // namespace
   13918 
   13919 void SharedFunctionInfo::InitFromFunctionLiteral(
   13920     Handle<SharedFunctionInfo> shared_info, FunctionLiteral* lit) {
   13921   // When adding fields here, make sure DeclarationScope::AnalyzePartially is
   13922   // updated accordingly.
   13923   shared_info->set_length(lit->function_length());
   13924   shared_info->set_internal_formal_parameter_count(lit->parameter_count());
   13925   shared_info->set_function_token_position(lit->function_token_position());
   13926   shared_info->set_start_position(lit->start_position());
   13927   shared_info->set_end_position(lit->end_position());
   13928   shared_info->set_is_declaration(lit->is_declaration());
   13929   shared_info->set_is_named_expression(lit->is_named_expression());
   13930   shared_info->set_is_anonymous_expression(lit->is_anonymous_expression());
   13931   shared_info->set_inferred_name(*lit->inferred_name());
   13932   shared_info->set_allows_lazy_compilation(lit->AllowsLazyCompilation());
   13933   shared_info->set_language_mode(lit->language_mode());
   13934   shared_info->set_uses_arguments(lit->scope()->arguments() != NULL);
   13935   shared_info->set_has_duplicate_parameters(lit->has_duplicate_parameters());
   13936   shared_info->set_is_function(lit->is_function());
   13937   shared_info->set_never_compiled(true);
   13938   shared_info->set_kind(lit->kind());
   13939   if (!IsConstructable(lit->kind(), lit->language_mode())) {
   13940     shared_info->SetConstructStub(
   13941         *shared_info->GetIsolate()->builtins()->ConstructedNonConstructable());
   13942   }
   13943   shared_info->set_needs_home_object(lit->scope()->NeedsHomeObject());
   13944   shared_info->set_asm_function(lit->scope()->asm_function());
   13945   shared_info->set_requires_class_field_init(lit->requires_class_field_init());
   13946   shared_info->set_is_class_field_initializer(
   13947       lit->is_class_field_initializer());
   13948   SetExpectedNofPropertiesFromEstimate(shared_info, lit);
   13949 }
   13950 
   13951 
   13952 bool SharedFunctionInfo::VerifyBailoutId(BailoutId id) {
   13953   DCHECK(!id.IsNone());
   13954   Code* unoptimized = code();
   13955   DeoptimizationOutputData* data =
   13956       DeoptimizationOutputData::cast(unoptimized->deoptimization_data());
   13957   unsigned ignore = Deoptimizer::GetOutputInfo(data, id, this);
   13958   USE(ignore);
   13959   return true;  // Return true if there was no DCHECK.
   13960 }
   13961 
   13962 void SharedFunctionInfo::SetConstructStub(Code* code) {
   13963   if (code->kind() == Code::BUILTIN) code->set_is_construct_stub(true);
   13964   set_construct_stub(code);
   13965 }
   13966 
   13967 void Map::StartInobjectSlackTracking() {
   13968   DCHECK(!IsInobjectSlackTrackingInProgress());
   13969 
   13970   // No tracking during the snapshot construction phase.
   13971   Isolate* isolate = GetIsolate();
   13972   if (isolate->serializer_enabled()) return;
   13973 
   13974   if (unused_property_fields() == 0) return;
   13975 
   13976   set_construction_counter(Map::kSlackTrackingCounterStart);
   13977 }
   13978 
   13979 
   13980 void SharedFunctionInfo::ResetForNewContext(int new_ic_age) {
   13981   code()->ClearInlineCaches();
   13982   set_ic_age(new_ic_age);
   13983   if (code()->kind() == Code::FUNCTION) {
   13984     code()->set_profiler_ticks(0);
   13985     if (optimization_disabled() && opt_count() >= FLAG_max_opt_count) {
   13986       // Re-enable optimizations if they were disabled due to opt_count limit.
   13987       set_optimization_disabled(false);
   13988     }
   13989     set_opt_count(0);
   13990     set_deopt_count(0);
   13991   } else if (IsInterpreted()) {
   13992     set_profiler_ticks(0);
   13993     if (optimization_disabled() && opt_count() >= FLAG_max_opt_count) {
   13994       // Re-enable optimizations if they were disabled due to opt_count limit.
   13995       set_optimization_disabled(false);
   13996     }
   13997     set_opt_count(0);
   13998     set_deopt_count(0);
   13999   }
   14000 }
   14001 
   14002 
   14003 int SharedFunctionInfo::SearchOptimizedCodeMapEntry(Context* native_context,
   14004                                                     BailoutId osr_ast_id) {
   14005   DisallowHeapAllocation no_gc;
   14006   DCHECK(native_context->IsNativeContext());
   14007   if (!OptimizedCodeMapIsCleared()) {
   14008     FixedArray* optimized_code_map = this->optimized_code_map();
   14009     int length = optimized_code_map->length();
   14010     Smi* osr_ast_id_smi = Smi::FromInt(osr_ast_id.ToInt());
   14011     for (int i = kEntriesStart; i < length; i += kEntryLength) {
   14012       if (WeakCell::cast(optimized_code_map->get(i + kContextOffset))
   14013                   ->value() == native_context &&
   14014           optimized_code_map->get(i + kOsrAstIdOffset) == osr_ast_id_smi) {
   14015         return i;
   14016       }
   14017     }
   14018   }
   14019   return -1;
   14020 }
   14021 
   14022 void SharedFunctionInfo::ClearCodeFromOptimizedCodeMap() {
   14023   if (!OptimizedCodeMapIsCleared()) {
   14024     FixedArray* optimized_code_map = this->optimized_code_map();
   14025     int length = optimized_code_map->length();
   14026     WeakCell* empty_weak_cell = GetHeap()->empty_weak_cell();
   14027     for (int i = kEntriesStart; i < length; i += kEntryLength) {
   14028       optimized_code_map->set(i + kCachedCodeOffset, empty_weak_cell,
   14029                               SKIP_WRITE_BARRIER);
   14030     }
   14031   }
   14032 }
   14033 
   14034 CodeAndLiterals SharedFunctionInfo::SearchOptimizedCodeMap(
   14035     Context* native_context, BailoutId osr_ast_id) {
   14036   CodeAndLiterals result = {nullptr, nullptr};
   14037   int entry = SearchOptimizedCodeMapEntry(native_context, osr_ast_id);
   14038   if (entry != kNotFound) {
   14039     FixedArray* code_map = optimized_code_map();
   14040     DCHECK_LE(entry + kEntryLength, code_map->length());
   14041     WeakCell* cell = WeakCell::cast(code_map->get(entry + kCachedCodeOffset));
   14042     WeakCell* literals_cell =
   14043         WeakCell::cast(code_map->get(entry + kLiteralsOffset));
   14044 
   14045     result = {cell->cleared() ? nullptr : Code::cast(cell->value()),
   14046               literals_cell->cleared() ? nullptr : LiteralsArray::cast(
   14047                                                        literals_cell->value())};
   14048   }
   14049   return result;
   14050 }
   14051 
   14052 
   14053 #define DECLARE_TAG(ignore1, name, ignore2) name,
   14054 const char* const VisitorSynchronization::kTags[
   14055     VisitorSynchronization::kNumberOfSyncTags] = {
   14056   VISITOR_SYNCHRONIZATION_TAGS_LIST(DECLARE_TAG)
   14057 };
   14058 #undef DECLARE_TAG
   14059 
   14060 
   14061 #define DECLARE_TAG(ignore1, ignore2, name) name,
   14062 const char* const VisitorSynchronization::kTagNames[
   14063     VisitorSynchronization::kNumberOfSyncTags] = {
   14064   VISITOR_SYNCHRONIZATION_TAGS_LIST(DECLARE_TAG)
   14065 };
   14066 #undef DECLARE_TAG
   14067 
   14068 
   14069 void ObjectVisitor::VisitCodeTarget(RelocInfo* rinfo) {
   14070   DCHECK(RelocInfo::IsCodeTarget(rinfo->rmode()));
   14071   Object* old_pointer = Code::GetCodeFromTargetAddress(rinfo->target_address());
   14072   Object* new_pointer = old_pointer;
   14073   VisitPointer(&new_pointer);
   14074   DCHECK_EQ(old_pointer, new_pointer);
   14075 }
   14076 
   14077 
   14078 void ObjectVisitor::VisitCodeAgeSequence(RelocInfo* rinfo) {
   14079   DCHECK(RelocInfo::IsCodeAgeSequence(rinfo->rmode()));
   14080   Object* old_pointer = rinfo->code_age_stub();
   14081   Object* new_pointer = old_pointer;
   14082   if (old_pointer != nullptr) {
   14083     VisitPointer(&new_pointer);
   14084     DCHECK_EQ(old_pointer, new_pointer);
   14085   }
   14086 }
   14087 
   14088 
   14089 void ObjectVisitor::VisitCodeEntry(Address entry_address) {
   14090   Object* old_pointer = Code::GetObjectFromEntryAddress(entry_address);
   14091   Object* new_pointer = old_pointer;
   14092   VisitPointer(&new_pointer);
   14093   DCHECK_EQ(old_pointer, new_pointer);
   14094 }
   14095 
   14096 
   14097 void ObjectVisitor::VisitCell(RelocInfo* rinfo) {
   14098   DCHECK(rinfo->rmode() == RelocInfo::CELL);
   14099   Object* old_pointer = rinfo->target_cell();
   14100   Object* new_pointer = old_pointer;
   14101   VisitPointer(&new_pointer);
   14102   DCHECK_EQ(old_pointer, new_pointer);
   14103 }
   14104 
   14105 
   14106 void ObjectVisitor::VisitDebugTarget(RelocInfo* rinfo) {
   14107   DCHECK(RelocInfo::IsDebugBreakSlot(rinfo->rmode()) &&
   14108          rinfo->IsPatchedDebugBreakSlotSequence());
   14109   Object* old_pointer =
   14110       Code::GetCodeFromTargetAddress(rinfo->debug_call_address());
   14111   Object* new_pointer = old_pointer;
   14112   VisitPointer(&new_pointer);
   14113   DCHECK_EQ(old_pointer, new_pointer);
   14114 }
   14115 
   14116 
   14117 void ObjectVisitor::VisitEmbeddedPointer(RelocInfo* rinfo) {
   14118   DCHECK(rinfo->rmode() == RelocInfo::EMBEDDED_OBJECT);
   14119   Object* old_pointer = rinfo->target_object();
   14120   Object* new_pointer = old_pointer;
   14121   VisitPointer(&new_pointer);
   14122   DCHECK_EQ(old_pointer, new_pointer);
   14123 }
   14124 
   14125 
   14126 void ObjectVisitor::VisitExternalReference(RelocInfo* rinfo) {
   14127   Address old_reference = rinfo->target_external_reference();
   14128   Address new_reference = old_reference;
   14129   VisitExternalReference(&new_reference);
   14130   DCHECK_EQ(old_reference, new_reference);
   14131 }
   14132 
   14133 
   14134 void Code::InvalidateRelocation() {
   14135   InvalidateEmbeddedObjects();
   14136   set_relocation_info(GetHeap()->empty_byte_array());
   14137 }
   14138 
   14139 
   14140 void Code::InvalidateEmbeddedObjects() {
   14141   Object* undefined = GetHeap()->undefined_value();
   14142   Cell* undefined_cell = GetHeap()->undefined_cell();
   14143   int mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
   14144                   RelocInfo::ModeMask(RelocInfo::CELL);
   14145   for (RelocIterator it(this, mode_mask); !it.done(); it.next()) {
   14146     RelocInfo::Mode mode = it.rinfo()->rmode();
   14147     if (mode == RelocInfo::EMBEDDED_OBJECT) {
   14148       it.rinfo()->set_target_object(undefined, SKIP_WRITE_BARRIER);
   14149     } else if (mode == RelocInfo::CELL) {
   14150       it.rinfo()->set_target_cell(undefined_cell, SKIP_WRITE_BARRIER);
   14151     }
   14152   }
   14153 }
   14154 
   14155 
   14156 void Code::Relocate(intptr_t delta) {
   14157   for (RelocIterator it(this, RelocInfo::kApplyMask); !it.done(); it.next()) {
   14158     it.rinfo()->apply(delta);
   14159   }
   14160   Assembler::FlushICache(GetIsolate(), instruction_start(), instruction_size());
   14161 }
   14162 
   14163 
   14164 void Code::CopyFrom(const CodeDesc& desc) {
   14165   // copy code
   14166   CopyBytes(instruction_start(), desc.buffer,
   14167             static_cast<size_t>(desc.instr_size));
   14168 
   14169   // copy unwinding info, if any
   14170   if (desc.unwinding_info) {
   14171     DCHECK_GT(desc.unwinding_info_size, 0);
   14172     set_unwinding_info_size(desc.unwinding_info_size);
   14173     CopyBytes(unwinding_info_start(), desc.unwinding_info,
   14174               static_cast<size_t>(desc.unwinding_info_size));
   14175   }
   14176 
   14177   // copy reloc info
   14178   CopyBytes(relocation_start(),
   14179             desc.buffer + desc.buffer_size - desc.reloc_size,
   14180             static_cast<size_t>(desc.reloc_size));
   14181 
   14182   // unbox handles and relocate
   14183   intptr_t delta = instruction_start() - desc.buffer;
   14184   int mode_mask = RelocInfo::kCodeTargetMask |
   14185                   RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
   14186                   RelocInfo::ModeMask(RelocInfo::CELL) |
   14187                   RelocInfo::ModeMask(RelocInfo::RUNTIME_ENTRY) |
   14188                   RelocInfo::kApplyMask;
   14189   // Needed to find target_object and runtime_entry on X64
   14190   Assembler* origin = desc.origin;
   14191   AllowDeferredHandleDereference embedding_raw_address;
   14192   for (RelocIterator it(this, mode_mask); !it.done(); it.next()) {
   14193     RelocInfo::Mode mode = it.rinfo()->rmode();
   14194     if (mode == RelocInfo::EMBEDDED_OBJECT) {
   14195       Handle<Object> p = it.rinfo()->target_object_handle(origin);
   14196       it.rinfo()->set_target_object(*p, UPDATE_WRITE_BARRIER,
   14197                                     SKIP_ICACHE_FLUSH);
   14198     } else if (mode == RelocInfo::CELL) {
   14199       Handle<Cell> cell  = it.rinfo()->target_cell_handle();
   14200       it.rinfo()->set_target_cell(*cell, UPDATE_WRITE_BARRIER,
   14201                                   SKIP_ICACHE_FLUSH);
   14202     } else if (RelocInfo::IsCodeTarget(mode)) {
   14203       // rewrite code handles in inline cache targets to direct
   14204       // pointers to the first instruction in the code object
   14205       Handle<Object> p = it.rinfo()->target_object_handle(origin);
   14206       Code* code = Code::cast(*p);
   14207       it.rinfo()->set_target_address(code->instruction_start(),
   14208                                      UPDATE_WRITE_BARRIER, SKIP_ICACHE_FLUSH);
   14209     } else if (RelocInfo::IsRuntimeEntry(mode)) {
   14210       Address p = it.rinfo()->target_runtime_entry(origin);
   14211       it.rinfo()->set_target_runtime_entry(p, UPDATE_WRITE_BARRIER,
   14212                                            SKIP_ICACHE_FLUSH);
   14213     } else if (mode == RelocInfo::CODE_AGE_SEQUENCE) {
   14214       Handle<Object> p = it.rinfo()->code_age_stub_handle(origin);
   14215       Code* code = Code::cast(*p);
   14216       it.rinfo()->set_code_age_stub(code, SKIP_ICACHE_FLUSH);
   14217     } else {
   14218       it.rinfo()->apply(delta);
   14219     }
   14220   }
   14221   Assembler::FlushICache(GetIsolate(), instruction_start(), instruction_size());
   14222 }
   14223 
   14224 
   14225 SafepointEntry Code::GetSafepointEntry(Address pc) {
   14226   SafepointTable table(this);
   14227   return table.FindEntry(pc);
   14228 }
   14229 
   14230 
   14231 Object* Code::FindNthObject(int n, Map* match_map) {
   14232   DCHECK(is_inline_cache_stub());
   14233   DisallowHeapAllocation no_allocation;
   14234   int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
   14235   for (RelocIterator it(this, mask); !it.done(); it.next()) {
   14236     RelocInfo* info = it.rinfo();
   14237     Object* object = info->target_object();
   14238     if (object->IsWeakCell()) object = WeakCell::cast(object)->value();
   14239     if (object->IsHeapObject()) {
   14240       if (HeapObject::cast(object)->map() == match_map) {
   14241         if (--n == 0) return object;
   14242       }
   14243     }
   14244   }
   14245   return NULL;
   14246 }
   14247 
   14248 
   14249 AllocationSite* Code::FindFirstAllocationSite() {
   14250   Object* result = FindNthObject(1, GetHeap()->allocation_site_map());
   14251   return (result != NULL) ? AllocationSite::cast(result) : NULL;
   14252 }
   14253 
   14254 
   14255 Map* Code::FindFirstMap() {
   14256   Object* result = FindNthObject(1, GetHeap()->meta_map());
   14257   return (result != NULL) ? Map::cast(result) : NULL;
   14258 }
   14259 
   14260 
   14261 void Code::FindAndReplace(const FindAndReplacePattern& pattern) {
   14262   DCHECK(is_inline_cache_stub() || is_handler());
   14263   DisallowHeapAllocation no_allocation;
   14264   int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
   14265   STATIC_ASSERT(FindAndReplacePattern::kMaxCount < 32);
   14266   int current_pattern = 0;
   14267   for (RelocIterator it(this, mask); !it.done(); it.next()) {
   14268     RelocInfo* info = it.rinfo();
   14269     Object* object = info->target_object();
   14270     if (object->IsHeapObject()) {
   14271       if (object->IsWeakCell()) {
   14272         object = HeapObject::cast(WeakCell::cast(object)->value());
   14273       }
   14274       Map* map = HeapObject::cast(object)->map();
   14275       if (map == *pattern.find_[current_pattern]) {
   14276         info->set_target_object(*pattern.replace_[current_pattern]);
   14277         if (++current_pattern == pattern.count_) return;
   14278       }
   14279     }
   14280   }
   14281   UNREACHABLE();
   14282 }
   14283 
   14284 
   14285 void Code::ClearInlineCaches() {
   14286   int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) |
   14287              RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID);
   14288   for (RelocIterator it(this, mask); !it.done(); it.next()) {
   14289     RelocInfo* info = it.rinfo();
   14290     Code* target(Code::GetCodeFromTargetAddress(info->target_address()));
   14291     if (target->is_inline_cache_stub()) {
   14292       IC::Clear(this->GetIsolate(), info->pc(), info->host()->constant_pool());
   14293     }
   14294   }
   14295 }
   14296 
   14297 int AbstractCode::SourcePosition(int offset) {
   14298   int position = 0;
   14299   // Subtract one because the current PC is one instruction after the call site.
   14300   if (IsCode()) offset--;
   14301   for (SourcePositionTableIterator iterator(source_position_table());
   14302        !iterator.done() && iterator.code_offset() <= offset;
   14303        iterator.Advance()) {
   14304     position = iterator.source_position().ScriptOffset();
   14305   }
   14306   return position;
   14307 }
   14308 
   14309 int AbstractCode::SourceStatementPosition(int offset) {
   14310   // First find the closest position.
   14311   int position = SourcePosition(offset);
   14312   // Now find the closest statement position before the position.
   14313   int statement_position = 0;
   14314   for (SourcePositionTableIterator it(source_position_table()); !it.done();
   14315        it.Advance()) {
   14316     if (it.is_statement()) {
   14317       int p = it.source_position().ScriptOffset();
   14318       if (statement_position < p && p <= position) {
   14319         statement_position = p;
   14320       }
   14321     }
   14322   }
   14323   return statement_position;
   14324 }
   14325 
   14326 void JSFunction::ClearTypeFeedbackInfo() {
   14327   feedback_vector()->ClearSlots(shared());
   14328 }
   14329 
   14330 void JSFunction::ClearTypeFeedbackInfoAtGCTime() {
   14331   feedback_vector()->ClearSlotsAtGCTime(shared());
   14332 }
   14333 
   14334 BailoutId Code::TranslatePcOffsetToAstId(uint32_t pc_offset) {
   14335   DisallowHeapAllocation no_gc;
   14336   DCHECK(kind() == FUNCTION);
   14337   BackEdgeTable back_edges(this, &no_gc);
   14338   for (uint32_t i = 0; i < back_edges.length(); i++) {
   14339     if (back_edges.pc_offset(i) == pc_offset) return back_edges.ast_id(i);
   14340   }
   14341   return BailoutId::None();
   14342 }
   14343 
   14344 
   14345 uint32_t Code::TranslateAstIdToPcOffset(BailoutId ast_id) {
   14346   DisallowHeapAllocation no_gc;
   14347   DCHECK(kind() == FUNCTION);
   14348   BackEdgeTable back_edges(this, &no_gc);
   14349   for (uint32_t i = 0; i < back_edges.length(); i++) {
   14350     if (back_edges.ast_id(i) == ast_id) return back_edges.pc_offset(i);
   14351   }
   14352   UNREACHABLE();  // We expect to find the back edge.
   14353   return 0;
   14354 }
   14355 
   14356 int Code::LookupRangeInHandlerTable(int code_offset, int* data,
   14357                                     HandlerTable::CatchPrediction* prediction) {
   14358   DCHECK(!is_optimized_code());
   14359   HandlerTable* table = HandlerTable::cast(handler_table());
   14360   return table->LookupRange(code_offset, data, prediction);
   14361 }
   14362 
   14363 void Code::MakeCodeAgeSequenceYoung(byte* sequence, Isolate* isolate) {
   14364   PatchPlatformCodeAge(isolate, sequence, kNoAgeCodeAge, NO_MARKING_PARITY);
   14365 }
   14366 
   14367 
   14368 void Code::MarkCodeAsExecuted(byte* sequence, Isolate* isolate) {
   14369   PatchPlatformCodeAge(isolate, sequence, kExecutedOnceCodeAge,
   14370       NO_MARKING_PARITY);
   14371 }
   14372 
   14373 
   14374 // NextAge defines the Code::Age state transitions during a GC cycle.
   14375 static Code::Age NextAge(Code::Age age) {
   14376   switch (age) {
   14377     case Code::kNotExecutedCodeAge:  // Keep, until we've been executed.
   14378     case Code::kToBeExecutedOnceCodeAge:  // Keep, until we've been executed.
   14379     case Code::kLastCodeAge:  // Clamp at last Code::Age value.
   14380       return age;
   14381     case Code::kExecutedOnceCodeAge:
   14382       // Pre-age code that has only been executed once.
   14383       return static_cast<Code::Age>(Code::kPreAgedCodeAge + 1);
   14384     default:
   14385       return static_cast<Code::Age>(age + 1);  // Default case: Increase age.
   14386   }
   14387 }
   14388 
   14389 
   14390 // IsOldAge defines the collection criteria for a Code object.
   14391 static bool IsOldAge(Code::Age age) {
   14392   return age >= Code::kIsOldCodeAge || age == Code::kNotExecutedCodeAge;
   14393 }
   14394 
   14395 
   14396 void Code::MakeYoung(Isolate* isolate) {
   14397   byte* sequence = FindCodeAgeSequence();
   14398   if (sequence != NULL) MakeCodeAgeSequenceYoung(sequence, isolate);
   14399 }
   14400 
   14401 void Code::PreAge(Isolate* isolate) {
   14402   byte* sequence = FindCodeAgeSequence();
   14403   if (sequence != NULL) {
   14404     PatchPlatformCodeAge(isolate, sequence, kPreAgedCodeAge, NO_MARKING_PARITY);
   14405   }
   14406 }
   14407 
   14408 void Code::MarkToBeExecutedOnce(Isolate* isolate) {
   14409   byte* sequence = FindCodeAgeSequence();
   14410   if (sequence != NULL) {
   14411     PatchPlatformCodeAge(isolate, sequence, kToBeExecutedOnceCodeAge,
   14412                          NO_MARKING_PARITY);
   14413   }
   14414 }
   14415 
   14416 void Code::MakeOlder(MarkingParity current_parity) {
   14417   byte* sequence = FindCodeAgeSequence();
   14418   if (sequence != NULL) {
   14419     Age age;
   14420     MarkingParity code_parity;
   14421     Isolate* isolate = GetIsolate();
   14422     GetCodeAgeAndParity(isolate, sequence, &age, &code_parity);
   14423     Age next_age = NextAge(age);
   14424     if (age != next_age && code_parity != current_parity) {
   14425       PatchPlatformCodeAge(isolate, sequence, next_age, current_parity);
   14426     }
   14427   }
   14428 }
   14429 
   14430 
   14431 bool Code::IsOld() {
   14432   return IsOldAge(GetAge());
   14433 }
   14434 
   14435 
   14436 byte* Code::FindCodeAgeSequence() {
   14437   return FLAG_age_code &&
   14438       prologue_offset() != Code::kPrologueOffsetNotSet &&
   14439       (kind() == OPTIMIZED_FUNCTION ||
   14440        (kind() == FUNCTION && !has_debug_break_slots()))
   14441       ? instruction_start() + prologue_offset()
   14442       : NULL;
   14443 }
   14444 
   14445 
   14446 Code::Age Code::GetAge() {
   14447   byte* sequence = FindCodeAgeSequence();
   14448   if (sequence == NULL) {
   14449     return kNoAgeCodeAge;
   14450   }
   14451   Age age;
   14452   MarkingParity parity;
   14453   GetCodeAgeAndParity(GetIsolate(), sequence, &age, &parity);
   14454   return age;
   14455 }
   14456 
   14457 
   14458 void Code::GetCodeAgeAndParity(Code* code, Age* age,
   14459                                MarkingParity* parity) {
   14460   Isolate* isolate = code->GetIsolate();
   14461   Builtins* builtins = isolate->builtins();
   14462   Code* stub = NULL;
   14463 #define HANDLE_CODE_AGE(AGE)                                            \
   14464   stub = *builtins->Make##AGE##CodeYoungAgainEvenMarking();             \
   14465   if (code == stub) {                                                   \
   14466     *age = k##AGE##CodeAge;                                             \
   14467     *parity = EVEN_MARKING_PARITY;                                      \
   14468     return;                                                             \
   14469   }                                                                     \
   14470   stub = *builtins->Make##AGE##CodeYoungAgainOddMarking();              \
   14471   if (code == stub) {                                                   \
   14472     *age = k##AGE##CodeAge;                                             \
   14473     *parity = ODD_MARKING_PARITY;                                       \
   14474     return;                                                             \
   14475   }
   14476   CODE_AGE_LIST(HANDLE_CODE_AGE)
   14477 #undef HANDLE_CODE_AGE
   14478   stub = *builtins->MarkCodeAsExecutedOnce();
   14479   if (code == stub) {
   14480     *age = kNotExecutedCodeAge;
   14481     *parity = NO_MARKING_PARITY;
   14482     return;
   14483   }
   14484   stub = *builtins->MarkCodeAsExecutedTwice();
   14485   if (code == stub) {
   14486     *age = kExecutedOnceCodeAge;
   14487     *parity = NO_MARKING_PARITY;
   14488     return;
   14489   }
   14490   stub = *builtins->MarkCodeAsToBeExecutedOnce();
   14491   if (code == stub) {
   14492     *age = kToBeExecutedOnceCodeAge;
   14493     *parity = NO_MARKING_PARITY;
   14494     return;
   14495   }
   14496   UNREACHABLE();
   14497 }
   14498 
   14499 
   14500 Code* Code::GetCodeAgeStub(Isolate* isolate, Age age, MarkingParity parity) {
   14501   Builtins* builtins = isolate->builtins();
   14502   switch (age) {
   14503 #define HANDLE_CODE_AGE(AGE)                                            \
   14504     case k##AGE##CodeAge: {                                             \
   14505       Code* stub = parity == EVEN_MARKING_PARITY                        \
   14506           ? *builtins->Make##AGE##CodeYoungAgainEvenMarking()           \
   14507           : *builtins->Make##AGE##CodeYoungAgainOddMarking();           \
   14508       return stub;                                                      \
   14509     }
   14510     CODE_AGE_LIST(HANDLE_CODE_AGE)
   14511 #undef HANDLE_CODE_AGE
   14512     case kNotExecutedCodeAge: {
   14513       DCHECK(parity == NO_MARKING_PARITY);
   14514       return *builtins->MarkCodeAsExecutedOnce();
   14515     }
   14516     case kExecutedOnceCodeAge: {
   14517       DCHECK(parity == NO_MARKING_PARITY);
   14518       return *builtins->MarkCodeAsExecutedTwice();
   14519     }
   14520     case kToBeExecutedOnceCodeAge: {
   14521       DCHECK(parity == NO_MARKING_PARITY);
   14522       return *builtins->MarkCodeAsToBeExecutedOnce();
   14523     }
   14524     default:
   14525       UNREACHABLE();
   14526       break;
   14527   }
   14528   return NULL;
   14529 }
   14530 
   14531 
   14532 void Code::PrintDeoptLocation(FILE* out, Address pc) {
   14533   Deoptimizer::DeoptInfo info = Deoptimizer::GetDeoptInfo(this, pc);
   14534   class SourcePosition pos = info.position;
   14535   if (info.deopt_reason != DeoptimizeReason::kNoReason || pos.IsKnown()) {
   14536     if (FLAG_hydrogen_track_positions) {
   14537       PrintF(out, "            ;;; deoptimize at %d_%d: %s\n", pos.InliningId(),
   14538              pos.ScriptOffset(), DeoptimizeReasonToString(info.deopt_reason));
   14539     } else {
   14540       PrintF(out, "            ;;; deoptimize at ");
   14541       OFStream outstr(out);
   14542       pos.Print(outstr, this);
   14543       PrintF(out, ", %s\n", DeoptimizeReasonToString(info.deopt_reason));
   14544     }
   14545   }
   14546 }
   14547 
   14548 
   14549 bool Code::CanDeoptAt(Address pc) {
   14550   DeoptimizationInputData* deopt_data =
   14551       DeoptimizationInputData::cast(deoptimization_data());
   14552   Address code_start_address = instruction_start();
   14553   for (int i = 0; i < deopt_data->DeoptCount(); i++) {
   14554     if (deopt_data->Pc(i)->value() == -1) continue;
   14555     Address address = code_start_address + deopt_data->Pc(i)->value();
   14556     if (address == pc && deopt_data->AstId(i) != BailoutId::None()) {
   14557       return true;
   14558     }
   14559   }
   14560   return false;
   14561 }
   14562 
   14563 
   14564 // Identify kind of code.
   14565 const char* Code::Kind2String(Kind kind) {
   14566   switch (kind) {
   14567 #define CASE(name) case name: return #name;
   14568     CODE_KIND_LIST(CASE)
   14569 #undef CASE
   14570     case NUMBER_OF_KINDS: break;
   14571   }
   14572   UNREACHABLE();
   14573   return NULL;
   14574 }
   14575 
   14576 // Identify kind of code.
   14577 const char* AbstractCode::Kind2String(Kind kind) {
   14578   if (kind < AbstractCode::INTERPRETED_FUNCTION)
   14579     return Code::Kind2String((Code::Kind)kind);
   14580   if (kind == AbstractCode::INTERPRETED_FUNCTION) return "INTERPRETED_FUNCTION";
   14581   UNREACHABLE();
   14582   return NULL;
   14583 }
   14584 
   14585 Handle<WeakCell> Code::WeakCellFor(Handle<Code> code) {
   14586   DCHECK(code->kind() == OPTIMIZED_FUNCTION);
   14587   WeakCell* raw_cell = code->CachedWeakCell();
   14588   if (raw_cell != NULL) return Handle<WeakCell>(raw_cell);
   14589   Handle<WeakCell> cell = code->GetIsolate()->factory()->NewWeakCell(code);
   14590   DeoptimizationInputData::cast(code->deoptimization_data())
   14591       ->SetWeakCellCache(*cell);
   14592   return cell;
   14593 }
   14594 
   14595 
   14596 WeakCell* Code::CachedWeakCell() {
   14597   DCHECK(kind() == OPTIMIZED_FUNCTION);
   14598   Object* weak_cell_cache =
   14599       DeoptimizationInputData::cast(deoptimization_data())->WeakCellCache();
   14600   if (weak_cell_cache->IsWeakCell()) {
   14601     DCHECK(this == WeakCell::cast(weak_cell_cache)->value());
   14602     return WeakCell::cast(weak_cell_cache);
   14603   }
   14604   return NULL;
   14605 }
   14606 
   14607 #if defined(OBJECT_PRINT) || defined(ENABLE_DISASSEMBLER)
   14608 
   14609 const char* Code::ICState2String(InlineCacheState state) {
   14610   switch (state) {
   14611     case UNINITIALIZED:
   14612       return "UNINITIALIZED";
   14613     case PREMONOMORPHIC:
   14614       return "PREMONOMORPHIC";
   14615     case MONOMORPHIC:
   14616       return "MONOMORPHIC";
   14617     case RECOMPUTE_HANDLER:
   14618       return "RECOMPUTE_HANDLER";
   14619     case POLYMORPHIC:
   14620       return "POLYMORPHIC";
   14621     case MEGAMORPHIC:
   14622       return "MEGAMORPHIC";
   14623     case GENERIC:
   14624       return "GENERIC";
   14625   }
   14626   UNREACHABLE();
   14627   return NULL;
   14628 }
   14629 
   14630 void Code::PrintExtraICState(std::ostream& os,  // NOLINT
   14631                              Kind kind, ExtraICState extra) {
   14632   os << "extra_ic_state = ";
   14633   if ((kind == STORE_IC || kind == KEYED_STORE_IC) &&
   14634       is_strict(static_cast<LanguageMode>(extra))) {
   14635     os << "STRICT\n";
   14636   } else {
   14637     os << extra << "\n";
   14638   }
   14639 }
   14640 
   14641 #endif  // defined(OBJECT_PRINT) || defined(ENABLE_DISASSEMBLER)
   14642 
   14643 #ifdef ENABLE_DISASSEMBLER
   14644 
   14645 void DeoptimizationInputData::DeoptimizationInputDataPrint(
   14646     std::ostream& os) {  // NOLINT
   14647   disasm::NameConverter converter;
   14648   int const inlined_function_count = InlinedFunctionCount()->value();
   14649   os << "Inlined functions (count = " << inlined_function_count << ")\n";
   14650   for (int id = 0; id < inlined_function_count; ++id) {
   14651     Object* info = LiteralArray()->get(id);
   14652     os << " " << Brief(SharedFunctionInfo::cast(info)) << "\n";
   14653   }
   14654   os << "\n";
   14655   int deopt_count = DeoptCount();
   14656   os << "Deoptimization Input Data (deopt points = " << deopt_count << ")\n";
   14657   if (0 != deopt_count) {
   14658     os << " index  ast id    argc     pc";
   14659     if (FLAG_print_code_verbose) os << "  commands";
   14660     os << "\n";
   14661   }
   14662   for (int i = 0; i < deopt_count; i++) {
   14663     os << std::setw(6) << i << "  " << std::setw(6) << AstId(i).ToInt() << "  "
   14664        << std::setw(6) << ArgumentsStackHeight(i)->value() << " "
   14665        << std::setw(6) << Pc(i)->value();
   14666 
   14667     if (!FLAG_print_code_verbose) {
   14668       os << "\n";
   14669       continue;
   14670     }
   14671     // Print details of the frame translation.
   14672     int translation_index = TranslationIndex(i)->value();
   14673     TranslationIterator iterator(TranslationByteArray(), translation_index);
   14674     Translation::Opcode opcode =
   14675         static_cast<Translation::Opcode>(iterator.Next());
   14676     DCHECK(Translation::BEGIN == opcode);
   14677     int frame_count = iterator.Next();
   14678     int jsframe_count = iterator.Next();
   14679     os << "  " << Translation::StringFor(opcode)
   14680        << " {frame count=" << frame_count
   14681        << ", js frame count=" << jsframe_count << "}\n";
   14682 
   14683     while (iterator.HasNext() &&
   14684            Translation::BEGIN !=
   14685            (opcode = static_cast<Translation::Opcode>(iterator.Next()))) {
   14686       os << std::setw(31) << "    " << Translation::StringFor(opcode) << " ";
   14687 
   14688       switch (opcode) {
   14689         case Translation::BEGIN:
   14690           UNREACHABLE();
   14691           break;
   14692 
   14693         case Translation::JS_FRAME: {
   14694           int ast_id = iterator.Next();
   14695           int shared_info_id = iterator.Next();
   14696           unsigned height = iterator.Next();
   14697           Object* shared_info = LiteralArray()->get(shared_info_id);
   14698           os << "{ast_id=" << ast_id << ", function="
   14699              << Brief(SharedFunctionInfo::cast(shared_info)->DebugName())
   14700              << ", height=" << height << "}";
   14701           break;
   14702         }
   14703 
   14704         case Translation::INTERPRETED_FRAME: {
   14705           int bytecode_offset = iterator.Next();
   14706           int shared_info_id = iterator.Next();
   14707           unsigned height = iterator.Next();
   14708           Object* shared_info = LiteralArray()->get(shared_info_id);
   14709           os << "{bytecode_offset=" << bytecode_offset << ", function="
   14710              << Brief(SharedFunctionInfo::cast(shared_info)->DebugName())
   14711              << ", height=" << height << "}";
   14712           break;
   14713         }
   14714 
   14715         case Translation::COMPILED_STUB_FRAME: {
   14716           Code::Kind stub_kind = static_cast<Code::Kind>(iterator.Next());
   14717           os << "{kind=" << stub_kind << "}";
   14718           break;
   14719         }
   14720 
   14721         case Translation::ARGUMENTS_ADAPTOR_FRAME:
   14722         case Translation::CONSTRUCT_STUB_FRAME: {
   14723           int shared_info_id = iterator.Next();
   14724           Object* shared_info = LiteralArray()->get(shared_info_id);
   14725           unsigned height = iterator.Next();
   14726           os << "{function="
   14727              << Brief(SharedFunctionInfo::cast(shared_info)->DebugName())
   14728              << ", height=" << height << "}";
   14729           break;
   14730         }
   14731 
   14732         case Translation::TAIL_CALLER_FRAME: {
   14733           int shared_info_id = iterator.Next();
   14734           Object* shared_info = LiteralArray()->get(shared_info_id);
   14735           os << "{function="
   14736              << Brief(SharedFunctionInfo::cast(shared_info)->DebugName())
   14737              << "}";
   14738           break;
   14739         }
   14740 
   14741         case Translation::GETTER_STUB_FRAME:
   14742         case Translation::SETTER_STUB_FRAME: {
   14743           int shared_info_id = iterator.Next();
   14744           Object* shared_info = LiteralArray()->get(shared_info_id);
   14745           os << "{function=" << Brief(SharedFunctionInfo::cast(shared_info)
   14746                                           ->DebugName()) << "}";
   14747           break;
   14748         }
   14749 
   14750         case Translation::REGISTER: {
   14751           int reg_code = iterator.Next();
   14752           os << "{input=" << converter.NameOfCPURegister(reg_code) << "}";
   14753           break;
   14754         }
   14755 
   14756         case Translation::INT32_REGISTER: {
   14757           int reg_code = iterator.Next();
   14758           os << "{input=" << converter.NameOfCPURegister(reg_code) << "}";
   14759           break;
   14760         }
   14761 
   14762         case Translation::UINT32_REGISTER: {
   14763           int reg_code = iterator.Next();
   14764           os << "{input=" << converter.NameOfCPURegister(reg_code)
   14765              << " (unsigned)}";
   14766           break;
   14767         }
   14768 
   14769         case Translation::BOOL_REGISTER: {
   14770           int reg_code = iterator.Next();
   14771           os << "{input=" << converter.NameOfCPURegister(reg_code)
   14772              << " (bool)}";
   14773           break;
   14774         }
   14775 
   14776         case Translation::FLOAT_REGISTER: {
   14777           int reg_code = iterator.Next();
   14778           os << "{input="
   14779              << RegisterConfiguration::Crankshaft()->GetFloatRegisterName(
   14780                     reg_code)
   14781              << "}";
   14782           break;
   14783         }
   14784 
   14785         case Translation::DOUBLE_REGISTER: {
   14786           int reg_code = iterator.Next();
   14787           os << "{input="
   14788              << RegisterConfiguration::Crankshaft()->GetDoubleRegisterName(
   14789                     reg_code)
   14790              << "}";
   14791           break;
   14792         }
   14793 
   14794         case Translation::STACK_SLOT: {
   14795           int input_slot_index = iterator.Next();
   14796           os << "{input=" << input_slot_index << "}";
   14797           break;
   14798         }
   14799 
   14800         case Translation::INT32_STACK_SLOT: {
   14801           int input_slot_index = iterator.Next();
   14802           os << "{input=" << input_slot_index << "}";
   14803           break;
   14804         }
   14805 
   14806         case Translation::UINT32_STACK_SLOT: {
   14807           int input_slot_index = iterator.Next();
   14808           os << "{input=" << input_slot_index << " (unsigned)}";
   14809           break;
   14810         }
   14811 
   14812         case Translation::BOOL_STACK_SLOT: {
   14813           int input_slot_index = iterator.Next();
   14814           os << "{input=" << input_slot_index << " (bool)}";
   14815           break;
   14816         }
   14817 
   14818         case Translation::FLOAT_STACK_SLOT:
   14819         case Translation::DOUBLE_STACK_SLOT: {
   14820           int input_slot_index = iterator.Next();
   14821           os << "{input=" << input_slot_index << "}";
   14822           break;
   14823         }
   14824 
   14825         case Translation::LITERAL: {
   14826           int literal_index = iterator.Next();
   14827           Object* literal_value = LiteralArray()->get(literal_index);
   14828           os << "{literal_id=" << literal_index << " (" << Brief(literal_value)
   14829              << ")}";
   14830           break;
   14831         }
   14832 
   14833         case Translation::DUPLICATED_OBJECT: {
   14834           int object_index = iterator.Next();
   14835           os << "{object_index=" << object_index << "}";
   14836           break;
   14837         }
   14838 
   14839         case Translation::ARGUMENTS_OBJECT:
   14840         case Translation::CAPTURED_OBJECT: {
   14841           int args_length = iterator.Next();
   14842           os << "{length=" << args_length << "}";
   14843           break;
   14844         }
   14845       }
   14846       os << "\n";
   14847     }
   14848   }
   14849 }
   14850 
   14851 
   14852 void DeoptimizationOutputData::DeoptimizationOutputDataPrint(
   14853     std::ostream& os) {  // NOLINT
   14854   os << "Deoptimization Output Data (deopt points = " << this->DeoptPoints()
   14855      << ")\n";
   14856   if (this->DeoptPoints() == 0) return;
   14857 
   14858   os << "ast id        pc  state\n";
   14859   for (int i = 0; i < this->DeoptPoints(); i++) {
   14860     int pc_and_state = this->PcAndState(i)->value();
   14861     os << std::setw(6) << this->AstId(i).ToInt() << "  " << std::setw(8)
   14862        << FullCodeGenerator::PcField::decode(pc_and_state) << "  "
   14863        << Deoptimizer::BailoutStateToString(
   14864               FullCodeGenerator::BailoutStateField::decode(pc_and_state))
   14865        << "\n";
   14866   }
   14867 }
   14868 
   14869 
   14870 void HandlerTable::HandlerTableRangePrint(std::ostream& os) {
   14871   os << "   from   to       hdlr\n";
   14872   for (int i = 0; i < length(); i += kRangeEntrySize) {
   14873     int pc_start = Smi::cast(get(i + kRangeStartIndex))->value();
   14874     int pc_end = Smi::cast(get(i + kRangeEndIndex))->value();
   14875     int handler_field = Smi::cast(get(i + kRangeHandlerIndex))->value();
   14876     int handler_offset = HandlerOffsetField::decode(handler_field);
   14877     CatchPrediction prediction = HandlerPredictionField::decode(handler_field);
   14878     int data = Smi::cast(get(i + kRangeDataIndex))->value();
   14879     os << "  (" << std::setw(4) << pc_start << "," << std::setw(4) << pc_end
   14880        << ")  ->  " << std::setw(4) << handler_offset
   14881        << " (prediction=" << prediction << ", data=" << data << ")\n";
   14882   }
   14883 }
   14884 
   14885 
   14886 void HandlerTable::HandlerTableReturnPrint(std::ostream& os) {
   14887   os << "   off      hdlr (c)\n";
   14888   for (int i = 0; i < length(); i += kReturnEntrySize) {
   14889     int pc_offset = Smi::cast(get(i + kReturnOffsetIndex))->value();
   14890     int handler_field = Smi::cast(get(i + kReturnHandlerIndex))->value();
   14891     int handler_offset = HandlerOffsetField::decode(handler_field);
   14892     CatchPrediction prediction = HandlerPredictionField::decode(handler_field);
   14893     os << "  " << std::setw(4) << pc_offset << "  ->  " << std::setw(4)
   14894        << handler_offset << " (prediction=" << prediction << ")\n";
   14895   }
   14896 }
   14897 
   14898 
   14899 void Code::Disassemble(const char* name, std::ostream& os) {  // NOLINT
   14900   os << "kind = " << Kind2String(kind()) << "\n";
   14901   if (IsCodeStubOrIC()) {
   14902     const char* n = CodeStub::MajorName(CodeStub::GetMajorKey(this));
   14903     os << "major_key = " << (n == NULL ? "null" : n) << "\n";
   14904   }
   14905   if (is_inline_cache_stub()) {
   14906     if (!IC::ICUseVector(kind())) {
   14907       InlineCacheState ic_state = IC::StateFromCode(this);
   14908       os << "ic_state = " << ICState2String(ic_state) << "\n";
   14909     }
   14910     PrintExtraICState(os, kind(), extra_ic_state());
   14911     if (is_compare_ic_stub()) {
   14912       DCHECK(CodeStub::GetMajorKey(this) == CodeStub::CompareIC);
   14913       CompareICStub stub(stub_key(), GetIsolate());
   14914       os << "compare_state = " << CompareICState::GetStateName(stub.left())
   14915          << "*" << CompareICState::GetStateName(stub.right()) << " -> "
   14916          << CompareICState::GetStateName(stub.state()) << "\n";
   14917       os << "compare_operation = " << Token::Name(stub.op()) << "\n";
   14918     }
   14919   }
   14920   if ((name != nullptr) && (name[0] != '\0')) {
   14921     os << "name = " << name << "\n";
   14922   } else if (kind() == BUILTIN) {
   14923     name = GetIsolate()->builtins()->Lookup(instruction_start());
   14924     if (name != nullptr) {
   14925       os << "name = " << name << "\n";
   14926     }
   14927   } else if (kind() == BYTECODE_HANDLER) {
   14928     name = GetIsolate()->interpreter()->LookupNameOfBytecodeHandler(this);
   14929     if (name != nullptr) {
   14930       os << "name = " << name << "\n";
   14931     }
   14932   }
   14933   if (kind() == OPTIMIZED_FUNCTION) {
   14934     os << "stack_slots = " << stack_slots() << "\n";
   14935   }
   14936   os << "compiler = " << (is_turbofanned()
   14937                               ? "turbofan"
   14938                               : is_crankshafted() ? "crankshaft"
   14939                                                   : kind() == Code::FUNCTION
   14940                                                         ? "full-codegen"
   14941                                                         : "unknown") << "\n";
   14942 
   14943   os << "Instructions (size = " << instruction_size() << ")\n";
   14944   {
   14945     Isolate* isolate = GetIsolate();
   14946     int size = instruction_size();
   14947     int safepoint_offset =
   14948         is_crankshafted() ? static_cast<int>(safepoint_table_offset()) : size;
   14949     int back_edge_offset = (kind() == Code::FUNCTION)
   14950                                ? static_cast<int>(back_edge_table_offset())
   14951                                : size;
   14952     int constant_pool_offset = FLAG_enable_embedded_constant_pool
   14953                                    ? this->constant_pool_offset()
   14954                                    : size;
   14955 
   14956     // Stop before reaching any embedded tables
   14957     int code_size = Min(safepoint_offset, back_edge_offset);
   14958     code_size = Min(code_size, constant_pool_offset);
   14959     byte* begin = instruction_start();
   14960     byte* end = begin + code_size;
   14961     Disassembler::Decode(isolate, &os, begin, end, this);
   14962 
   14963     if (constant_pool_offset < size) {
   14964       int constant_pool_size = size - constant_pool_offset;
   14965       DCHECK((constant_pool_size & kPointerAlignmentMask) == 0);
   14966       os << "\nConstant Pool (size = " << constant_pool_size << ")\n";
   14967       Vector<char> buf = Vector<char>::New(50);
   14968       intptr_t* ptr = reinterpret_cast<intptr_t*>(begin + constant_pool_offset);
   14969       for (int i = 0; i < constant_pool_size; i += kPointerSize, ptr++) {
   14970         SNPrintF(buf, "%4d %08" V8PRIxPTR, i, *ptr);
   14971         os << static_cast<const void*>(ptr) << "  " << buf.start() << "\n";
   14972       }
   14973     }
   14974   }
   14975   os << "\n";
   14976 
   14977   SourcePositionTableIterator it(source_position_table());
   14978   if (!it.done()) {
   14979     os << "Source positions:\n pc offset  position\n";
   14980     for (; !it.done(); it.Advance()) {
   14981       os << std::setw(10) << it.code_offset() << std::setw(10)
   14982          << it.source_position().ScriptOffset()
   14983          << (it.is_statement() ? "  statement" : "") << "\n";
   14984     }
   14985     os << "\n";
   14986   }
   14987 
   14988   if (kind() == FUNCTION) {
   14989     DeoptimizationOutputData* data =
   14990         DeoptimizationOutputData::cast(this->deoptimization_data());
   14991     data->DeoptimizationOutputDataPrint(os);
   14992   } else if (kind() == OPTIMIZED_FUNCTION) {
   14993     DeoptimizationInputData* data =
   14994         DeoptimizationInputData::cast(this->deoptimization_data());
   14995     data->DeoptimizationInputDataPrint(os);
   14996   }
   14997   os << "\n";
   14998 
   14999   if (is_crankshafted()) {
   15000     SafepointTable table(this);
   15001     os << "Safepoints (size = " << table.size() << ")\n";
   15002     for (unsigned i = 0; i < table.length(); i++) {
   15003       unsigned pc_offset = table.GetPcOffset(i);
   15004       os << static_cast<const void*>(instruction_start() + pc_offset) << "  ";
   15005       os << std::setw(4) << pc_offset << "  ";
   15006       table.PrintEntry(i, os);
   15007       os << " (sp -> fp)  ";
   15008       SafepointEntry entry = table.GetEntry(i);
   15009       if (entry.deoptimization_index() != Safepoint::kNoDeoptimizationIndex) {
   15010         os << std::setw(6) << entry.deoptimization_index();
   15011       } else {
   15012         os << "<none>";
   15013       }
   15014       if (entry.argument_count() > 0) {
   15015         os << " argc: " << entry.argument_count();
   15016       }
   15017       os << "\n";
   15018     }
   15019     os << "\n";
   15020   } else if (kind() == FUNCTION) {
   15021     unsigned offset = back_edge_table_offset();
   15022     // If there is no back edge table, the "table start" will be at or after
   15023     // (due to alignment) the end of the instruction stream.
   15024     if (static_cast<int>(offset) < instruction_size()) {
   15025       DisallowHeapAllocation no_gc;
   15026       BackEdgeTable back_edges(this, &no_gc);
   15027 
   15028       os << "Back edges (size = " << back_edges.length() << ")\n";
   15029       os << "ast_id  pc_offset  loop_depth\n";
   15030 
   15031       for (uint32_t i = 0; i < back_edges.length(); i++) {
   15032         os << std::setw(6) << back_edges.ast_id(i).ToInt() << "  "
   15033            << std::setw(9) << back_edges.pc_offset(i) << "  " << std::setw(10)
   15034            << back_edges.loop_depth(i) << "\n";
   15035       }
   15036 
   15037       os << "\n";
   15038     }
   15039 #ifdef OBJECT_PRINT
   15040     if (!type_feedback_info()->IsUndefined(GetIsolate())) {
   15041       TypeFeedbackInfo::cast(type_feedback_info())->TypeFeedbackInfoPrint(os);
   15042       os << "\n";
   15043     }
   15044 #endif
   15045   }
   15046 
   15047   if (handler_table()->length() > 0) {
   15048     os << "Handler Table (size = " << handler_table()->Size() << ")\n";
   15049     if (kind() == FUNCTION) {
   15050       HandlerTable::cast(handler_table())->HandlerTableRangePrint(os);
   15051     } else if (kind() == OPTIMIZED_FUNCTION) {
   15052       HandlerTable::cast(handler_table())->HandlerTableReturnPrint(os);
   15053     }
   15054     os << "\n";
   15055   }
   15056 
   15057   os << "RelocInfo (size = " << relocation_size() << ")\n";
   15058   for (RelocIterator it(this); !it.done(); it.next()) {
   15059     it.rinfo()->Print(GetIsolate(), os);
   15060   }
   15061   os << "\n";
   15062 
   15063   if (has_unwinding_info()) {
   15064     os << "UnwindingInfo (size = " << unwinding_info_size() << ")\n";
   15065     EhFrameDisassembler eh_frame_disassembler(unwinding_info_start(),
   15066                                               unwinding_info_end());
   15067     eh_frame_disassembler.DisassembleToStream(os);
   15068     os << "\n";
   15069   }
   15070 }
   15071 #endif  // ENABLE_DISASSEMBLER
   15072 
   15073 
   15074 void BytecodeArray::Disassemble(std::ostream& os) {
   15075   os << "Parameter count " << parameter_count() << "\n";
   15076   os << "Frame size " << frame_size() << "\n";
   15077 
   15078   const uint8_t* base_address = GetFirstBytecodeAddress();
   15079   SourcePositionTableIterator source_positions(source_position_table());
   15080 
   15081   interpreter::BytecodeArrayIterator iterator(handle(this));
   15082   while (!iterator.done()) {
   15083     if (!source_positions.done() &&
   15084         iterator.current_offset() == source_positions.code_offset()) {
   15085       os << std::setw(5) << source_positions.source_position().ScriptOffset();
   15086       os << (source_positions.is_statement() ? " S> " : " E> ");
   15087       source_positions.Advance();
   15088     } else {
   15089       os << "         ";
   15090     }
   15091     const uint8_t* current_address = base_address + iterator.current_offset();
   15092     os << reinterpret_cast<const void*>(current_address) << " @ "
   15093        << std::setw(4) << iterator.current_offset() << " : ";
   15094     interpreter::BytecodeDecoder::Decode(os, current_address,
   15095                                          parameter_count());
   15096     if (interpreter::Bytecodes::IsJump(iterator.current_bytecode())) {
   15097       const void* jump_target = base_address + iterator.GetJumpTargetOffset();
   15098       os << " (" << jump_target << " @ " << iterator.GetJumpTargetOffset()
   15099          << ")";
   15100     }
   15101     os << std::endl;
   15102     iterator.Advance();
   15103   }
   15104 
   15105   if (constant_pool()->length() > 0) {
   15106     os << "Constant pool (size = " << constant_pool()->length() << ")\n";
   15107     constant_pool()->Print();
   15108   }
   15109 
   15110 #ifdef ENABLE_DISASSEMBLER
   15111   if (handler_table()->length() > 0) {
   15112     os << "Handler Table (size = " << handler_table()->Size() << ")\n";
   15113     HandlerTable::cast(handler_table())->HandlerTableRangePrint(os);
   15114   }
   15115 #endif
   15116 }
   15117 
   15118 void BytecodeArray::CopyBytecodesTo(BytecodeArray* to) {
   15119   BytecodeArray* from = this;
   15120   DCHECK_EQ(from->length(), to->length());
   15121   CopyBytes(to->GetFirstBytecodeAddress(), from->GetFirstBytecodeAddress(),
   15122             from->length());
   15123 }
   15124 
   15125 int BytecodeArray::LookupRangeInHandlerTable(
   15126     int code_offset, int* data, HandlerTable::CatchPrediction* prediction) {
   15127   HandlerTable* table = HandlerTable::cast(handler_table());
   15128   code_offset++;  // Point after current bytecode.
   15129   return table->LookupRange(code_offset, data, prediction);
   15130 }
   15131 
   15132 // static
   15133 void JSArray::Initialize(Handle<JSArray> array, int capacity, int length) {
   15134   DCHECK(capacity >= 0);
   15135   array->GetIsolate()->factory()->NewJSArrayStorage(
   15136       array, length, capacity, INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE);
   15137 }
   15138 
   15139 void JSArray::SetLength(Handle<JSArray> array, uint32_t new_length) {
   15140   // We should never end in here with a pixel or external array.
   15141   DCHECK(array->AllowsSetLength());
   15142   if (array->SetLengthWouldNormalize(new_length)) {
   15143     JSObject::NormalizeElements(array);
   15144   }
   15145   array->GetElementsAccessor()->SetLength(array, new_length);
   15146 }
   15147 
   15148 
   15149 // static
   15150 void Map::AddDependentCode(Handle<Map> map,
   15151                            DependentCode::DependencyGroup group,
   15152                            Handle<Code> code) {
   15153   Handle<WeakCell> cell = Code::WeakCellFor(code);
   15154   Handle<DependentCode> codes = DependentCode::InsertWeakCode(
   15155       Handle<DependentCode>(map->dependent_code()), group, cell);
   15156   if (*codes != map->dependent_code()) map->set_dependent_code(*codes);
   15157 }
   15158 
   15159 
   15160 Handle<DependentCode> DependentCode::InsertCompilationDependencies(
   15161     Handle<DependentCode> entries, DependencyGroup group,
   15162     Handle<Foreign> info) {
   15163   return Insert(entries, group, info);
   15164 }
   15165 
   15166 
   15167 Handle<DependentCode> DependentCode::InsertWeakCode(
   15168     Handle<DependentCode> entries, DependencyGroup group,
   15169     Handle<WeakCell> code_cell) {
   15170   return Insert(entries, group, code_cell);
   15171 }
   15172 
   15173 
   15174 Handle<DependentCode> DependentCode::Insert(Handle<DependentCode> entries,
   15175                                             DependencyGroup group,
   15176                                             Handle<Object> object) {
   15177   if (entries->length() == 0 || entries->group() > group) {
   15178     // There is no such group.
   15179     return DependentCode::New(group, object, entries);
   15180   }
   15181   if (entries->group() < group) {
   15182     // The group comes later in the list.
   15183     Handle<DependentCode> old_next(entries->next_link());
   15184     Handle<DependentCode> new_next = Insert(old_next, group, object);
   15185     if (!old_next.is_identical_to(new_next)) {
   15186       entries->set_next_link(*new_next);
   15187     }
   15188     return entries;
   15189   }
   15190   DCHECK_EQ(group, entries->group());
   15191   int count = entries->count();
   15192   // Check for existing entry to avoid duplicates.
   15193   for (int i = 0; i < count; i++) {
   15194     if (entries->object_at(i) == *object) return entries;
   15195   }
   15196   if (entries->length() < kCodesStartIndex + count + 1) {
   15197     entries = EnsureSpace(entries);
   15198     // Count could have changed, reload it.
   15199     count = entries->count();
   15200   }
   15201   entries->set_object_at(count, *object);
   15202   entries->set_count(count + 1);
   15203   return entries;
   15204 }
   15205 
   15206 
   15207 Handle<DependentCode> DependentCode::New(DependencyGroup group,
   15208                                          Handle<Object> object,
   15209                                          Handle<DependentCode> next) {
   15210   Isolate* isolate = next->GetIsolate();
   15211   Handle<DependentCode> result = Handle<DependentCode>::cast(
   15212       isolate->factory()->NewFixedArray(kCodesStartIndex + 1, TENURED));
   15213   result->set_next_link(*next);
   15214   result->set_flags(GroupField::encode(group) | CountField::encode(1));
   15215   result->set_object_at(0, *object);
   15216   return result;
   15217 }
   15218 
   15219 
   15220 Handle<DependentCode> DependentCode::EnsureSpace(
   15221     Handle<DependentCode> entries) {
   15222   if (entries->Compact()) return entries;
   15223   Isolate* isolate = entries->GetIsolate();
   15224   int capacity = kCodesStartIndex + DependentCode::Grow(entries->count());
   15225   int grow_by = capacity - entries->length();
   15226   return Handle<DependentCode>::cast(
   15227       isolate->factory()->CopyFixedArrayAndGrow(entries, grow_by, TENURED));
   15228 }
   15229 
   15230 
   15231 bool DependentCode::Compact() {
   15232   int old_count = count();
   15233   int new_count = 0;
   15234   for (int i = 0; i < old_count; i++) {
   15235     Object* obj = object_at(i);
   15236     if (!obj->IsWeakCell() || !WeakCell::cast(obj)->cleared()) {
   15237       if (i != new_count) {
   15238         copy(i, new_count);
   15239       }
   15240       new_count++;
   15241     }
   15242   }
   15243   set_count(new_count);
   15244   for (int i = new_count; i < old_count; i++) {
   15245     clear_at(i);
   15246   }
   15247   return new_count < old_count;
   15248 }
   15249 
   15250 
   15251 void DependentCode::UpdateToFinishedCode(DependencyGroup group, Foreign* info,
   15252                                          WeakCell* code_cell) {
   15253   if (this->length() == 0 || this->group() > group) {
   15254     // There is no such group.
   15255     return;
   15256   }
   15257   if (this->group() < group) {
   15258     // The group comes later in the list.
   15259     next_link()->UpdateToFinishedCode(group, info, code_cell);
   15260     return;
   15261   }
   15262   DCHECK_EQ(group, this->group());
   15263   DisallowHeapAllocation no_gc;
   15264   int count = this->count();
   15265   for (int i = 0; i < count; i++) {
   15266     if (object_at(i) == info) {
   15267       set_object_at(i, code_cell);
   15268       break;
   15269     }
   15270   }
   15271 #ifdef DEBUG
   15272   for (int i = 0; i < count; i++) {
   15273     DCHECK(object_at(i) != info);
   15274   }
   15275 #endif
   15276 }
   15277 
   15278 
   15279 void DependentCode::RemoveCompilationDependencies(
   15280     DependentCode::DependencyGroup group, Foreign* info) {
   15281   if (this->length() == 0 || this->group() > group) {
   15282     // There is no such group.
   15283     return;
   15284   }
   15285   if (this->group() < group) {
   15286     // The group comes later in the list.
   15287     next_link()->RemoveCompilationDependencies(group, info);
   15288     return;
   15289   }
   15290   DCHECK_EQ(group, this->group());
   15291   DisallowHeapAllocation no_allocation;
   15292   int old_count = count();
   15293   // Find compilation info wrapper.
   15294   int info_pos = -1;
   15295   for (int i = 0; i < old_count; i++) {
   15296     if (object_at(i) == info) {
   15297       info_pos = i;
   15298       break;
   15299     }
   15300   }
   15301   if (info_pos == -1) return;  // Not found.
   15302   // Use the last code to fill the gap.
   15303   if (info_pos < old_count - 1) {
   15304     copy(old_count - 1, info_pos);
   15305   }
   15306   clear_at(old_count - 1);
   15307   set_count(old_count - 1);
   15308 
   15309 #ifdef DEBUG
   15310   for (int i = 0; i < old_count - 1; i++) {
   15311     DCHECK(object_at(i) != info);
   15312   }
   15313 #endif
   15314 }
   15315 
   15316 
   15317 bool DependentCode::Contains(DependencyGroup group, WeakCell* code_cell) {
   15318   if (this->length() == 0 || this->group() > group) {
   15319     // There is no such group.
   15320     return false;
   15321   }
   15322   if (this->group() < group) {
   15323     // The group comes later in the list.
   15324     return next_link()->Contains(group, code_cell);
   15325   }
   15326   DCHECK_EQ(group, this->group());
   15327   int count = this->count();
   15328   for (int i = 0; i < count; i++) {
   15329     if (object_at(i) == code_cell) return true;
   15330   }
   15331   return false;
   15332 }
   15333 
   15334 
   15335 bool DependentCode::IsEmpty(DependencyGroup group) {
   15336   if (this->length() == 0 || this->group() > group) {
   15337     // There is no such group.
   15338     return true;
   15339   }
   15340   if (this->group() < group) {
   15341     // The group comes later in the list.
   15342     return next_link()->IsEmpty(group);
   15343   }
   15344   DCHECK_EQ(group, this->group());
   15345   return count() == 0;
   15346 }
   15347 
   15348 
   15349 bool DependentCode::MarkCodeForDeoptimization(
   15350     Isolate* isolate,
   15351     DependentCode::DependencyGroup group) {
   15352   if (this->length() == 0 || this->group() > group) {
   15353     // There is no such group.
   15354     return false;
   15355   }
   15356   if (this->group() < group) {
   15357     // The group comes later in the list.
   15358     return next_link()->MarkCodeForDeoptimization(isolate, group);
   15359   }
   15360   DCHECK_EQ(group, this->group());
   15361   DisallowHeapAllocation no_allocation_scope;
   15362   // Mark all the code that needs to be deoptimized.
   15363   bool marked = false;
   15364   bool invalidate_embedded_objects = group == kWeakCodeGroup;
   15365   int count = this->count();
   15366   for (int i = 0; i < count; i++) {
   15367     Object* obj = object_at(i);
   15368     if (obj->IsWeakCell()) {
   15369       WeakCell* cell = WeakCell::cast(obj);
   15370       if (cell->cleared()) continue;
   15371       Code* code = Code::cast(cell->value());
   15372       if (!code->marked_for_deoptimization()) {
   15373         SetMarkedForDeoptimization(code, group);
   15374         if (invalidate_embedded_objects) {
   15375           code->InvalidateEmbeddedObjects();
   15376         }
   15377         marked = true;
   15378       }
   15379     } else {
   15380       DCHECK(obj->IsForeign());
   15381       CompilationDependencies* info =
   15382           reinterpret_cast<CompilationDependencies*>(
   15383               Foreign::cast(obj)->foreign_address());
   15384       info->Abort();
   15385     }
   15386   }
   15387   for (int i = 0; i < count; i++) {
   15388     clear_at(i);
   15389   }
   15390   set_count(0);
   15391   return marked;
   15392 }
   15393 
   15394 
   15395 void DependentCode::DeoptimizeDependentCodeGroup(
   15396     Isolate* isolate,
   15397     DependentCode::DependencyGroup group) {
   15398   DCHECK(AllowCodeDependencyChange::IsAllowed());
   15399   DisallowHeapAllocation no_allocation_scope;
   15400   bool marked = MarkCodeForDeoptimization(isolate, group);
   15401   if (marked) Deoptimizer::DeoptimizeMarkedCode(isolate);
   15402 }
   15403 
   15404 
   15405 void DependentCode::SetMarkedForDeoptimization(Code* code,
   15406                                                DependencyGroup group) {
   15407   code->set_marked_for_deoptimization(true);
   15408   if (FLAG_trace_deopt &&
   15409       (code->deoptimization_data() != code->GetHeap()->empty_fixed_array())) {
   15410     DeoptimizationInputData* deopt_data =
   15411         DeoptimizationInputData::cast(code->deoptimization_data());
   15412     CodeTracer::Scope scope(code->GetHeap()->isolate()->GetCodeTracer());
   15413     PrintF(scope.file(), "[marking dependent code 0x%08" V8PRIxPTR
   15414                          " (opt #%d) for deoptimization, reason: %s]\n",
   15415            reinterpret_cast<intptr_t>(code),
   15416            deopt_data->OptimizationId()->value(), DependencyGroupName(group));
   15417   }
   15418 }
   15419 
   15420 
   15421 const char* DependentCode::DependencyGroupName(DependencyGroup group) {
   15422   switch (group) {
   15423     case kWeakCodeGroup:
   15424       return "weak-code";
   15425     case kTransitionGroup:
   15426       return "transition";
   15427     case kPrototypeCheckGroup:
   15428       return "prototype-check";
   15429     case kPropertyCellChangedGroup:
   15430       return "property-cell-changed";
   15431     case kFieldOwnerGroup:
   15432       return "field-owner";
   15433     case kInitialMapChangedGroup:
   15434       return "initial-map-changed";
   15435     case kAllocationSiteTenuringChangedGroup:
   15436       return "allocation-site-tenuring-changed";
   15437     case kAllocationSiteTransitionChangedGroup:
   15438       return "allocation-site-transition-changed";
   15439   }
   15440   UNREACHABLE();
   15441   return "?";
   15442 }
   15443 
   15444 
   15445 Handle<Map> Map::TransitionToPrototype(Handle<Map> map,
   15446                                        Handle<Object> prototype,
   15447                                        PrototypeOptimizationMode mode) {
   15448   Handle<Map> new_map = TransitionArray::GetPrototypeTransition(map, prototype);
   15449   if (new_map.is_null()) {
   15450     new_map = Copy(map, "TransitionToPrototype");
   15451     TransitionArray::PutPrototypeTransition(map, prototype, new_map);
   15452     Map::SetPrototype(new_map, prototype, mode);
   15453   }
   15454   return new_map;
   15455 }
   15456 
   15457 
   15458 Maybe<bool> JSReceiver::SetPrototype(Handle<JSReceiver> object,
   15459                                      Handle<Object> value, bool from_javascript,
   15460                                      ShouldThrow should_throw) {
   15461   if (object->IsJSProxy()) {
   15462     return JSProxy::SetPrototype(Handle<JSProxy>::cast(object), value,
   15463                                  from_javascript, should_throw);
   15464   }
   15465   return JSObject::SetPrototype(Handle<JSObject>::cast(object), value,
   15466                                 from_javascript, should_throw);
   15467 }
   15468 
   15469 
   15470 // ES6: 9.5.2 [[SetPrototypeOf]] (V)
   15471 // static
   15472 Maybe<bool> JSProxy::SetPrototype(Handle<JSProxy> proxy, Handle<Object> value,
   15473                                   bool from_javascript,
   15474                                   ShouldThrow should_throw) {
   15475   Isolate* isolate = proxy->GetIsolate();
   15476   STACK_CHECK(isolate, Nothing<bool>());
   15477   Handle<Name> trap_name = isolate->factory()->setPrototypeOf_string();
   15478   // 1. Assert: Either Type(V) is Object or Type(V) is Null.
   15479   DCHECK(value->IsJSReceiver() || value->IsNull(isolate));
   15480   // 2. Let handler be the value of the [[ProxyHandler]] internal slot of O.
   15481   Handle<Object> handler(proxy->handler(), isolate);
   15482   // 3. If handler is null, throw a TypeError exception.
   15483   // 4. Assert: Type(handler) is Object.
   15484   if (proxy->IsRevoked()) {
   15485     isolate->Throw(*isolate->factory()->NewTypeError(
   15486         MessageTemplate::kProxyRevoked, trap_name));
   15487     return Nothing<bool>();
   15488   }
   15489   // 5. Let target be the value of the [[ProxyTarget]] internal slot.
   15490   Handle<JSReceiver> target(proxy->target(), isolate);
   15491   // 6. Let trap be ? GetMethod(handler, "getPrototypeOf").
   15492   Handle<Object> trap;
   15493   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   15494       isolate, trap,
   15495       Object::GetMethod(Handle<JSReceiver>::cast(handler), trap_name),
   15496       Nothing<bool>());
   15497   // 7. If trap is undefined, then return target.[[SetPrototypeOf]]().
   15498   if (trap->IsUndefined(isolate)) {
   15499     return JSReceiver::SetPrototype(target, value, from_javascript,
   15500                                     should_throw);
   15501   }
   15502   // 8. Let booleanTrapResult be ToBoolean(? Call(trap, handler, target, V)).
   15503   Handle<Object> argv[] = {target, value};
   15504   Handle<Object> trap_result;
   15505   ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   15506       isolate, trap_result,
   15507       Execution::Call(isolate, trap, handler, arraysize(argv), argv),
   15508       Nothing<bool>());
   15509   bool bool_trap_result = trap_result->BooleanValue();
   15510   // 9. If booleanTrapResult is false, return false.
   15511   if (!bool_trap_result) {
   15512     RETURN_FAILURE(
   15513         isolate, should_throw,
   15514         NewTypeError(MessageTemplate::kProxyTrapReturnedFalsish, trap_name));
   15515   }
   15516   // 10. Let extensibleTarget be ? IsExtensible(target).
   15517   Maybe<bool> is_extensible = JSReceiver::IsExtensible(target);
   15518   if (is_extensible.IsNothing()) return Nothing<bool>();
   15519   // 11. If extensibleTarget is true, return true.
   15520   if (is_extensible.FromJust()) {
   15521     if (bool_trap_result) return Just(true);
   15522     RETURN_FAILURE(
   15523         isolate, should_throw,
   15524         NewTypeError(MessageTemplate::kProxyTrapReturnedFalsish, trap_name));
   15525   }
   15526   // 12. Let targetProto be ? target.[[GetPrototypeOf]]().
   15527   Handle<Object> target_proto;
   15528   ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, target_proto,
   15529                                    JSReceiver::GetPrototype(isolate, target),
   15530                                    Nothing<bool>());
   15531   // 13. If SameValue(V, targetProto) is false, throw a TypeError exception.
   15532   if (bool_trap_result && !value->SameValue(*target_proto)) {
   15533     isolate->Throw(*isolate->factory()->NewTypeError(
   15534         MessageTemplate::kProxySetPrototypeOfNonExtensible));
   15535     return Nothing<bool>();
   15536   }
   15537   // 14. Return true.
   15538   return Just(true);
   15539 }
   15540 
   15541 
   15542 Maybe<bool> JSObject::SetPrototype(Handle<JSObject> object,
   15543                                    Handle<Object> value, bool from_javascript,
   15544                                    ShouldThrow should_throw) {
   15545   Isolate* isolate = object->GetIsolate();
   15546 
   15547 #ifdef DEBUG
   15548   int size = object->Size();
   15549 #endif
   15550 
   15551   if (from_javascript) {
   15552     if (object->IsAccessCheckNeeded() &&
   15553         !isolate->MayAccess(handle(isolate->context()), object)) {
   15554       isolate->ReportFailedAccessCheck(object);
   15555       RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
   15556       RETURN_FAILURE(isolate, should_throw,
   15557                      NewTypeError(MessageTemplate::kNoAccess));
   15558     }
   15559   } else {
   15560     DCHECK(!object->IsAccessCheckNeeded());
   15561   }
   15562 
   15563   Heap* heap = isolate->heap();
   15564   // Silently ignore the change if value is not a JSObject or null.
   15565   // SpiderMonkey behaves this way.
   15566   if (!value->IsJSReceiver() && !value->IsNull(isolate)) return Just(true);
   15567 
   15568   bool dictionary_elements_in_chain =
   15569       object->map()->DictionaryElementsInPrototypeChainOnly();
   15570 
   15571   bool all_extensible = object->map()->is_extensible();
   15572   Handle<JSObject> real_receiver = object;
   15573   if (from_javascript) {
   15574     // Find the first object in the chain whose prototype object is not
   15575     // hidden.
   15576     PrototypeIterator iter(isolate, real_receiver, kStartAtPrototype,
   15577                            PrototypeIterator::END_AT_NON_HIDDEN);
   15578     while (!iter.IsAtEnd()) {
   15579       // Casting to JSObject is fine because hidden prototypes are never
   15580       // JSProxies.
   15581       real_receiver = PrototypeIterator::GetCurrent<JSObject>(iter);
   15582       iter.Advance();
   15583       all_extensible = all_extensible && real_receiver->map()->is_extensible();
   15584     }
   15585   }
   15586   Handle<Map> map(real_receiver->map());
   15587 
   15588   // Nothing to do if prototype is already set.
   15589   if (map->prototype() == *value) return Just(true);
   15590 
   15591   bool immutable_proto = map->is_immutable_proto();
   15592   if (immutable_proto) {
   15593     RETURN_FAILURE(
   15594         isolate, should_throw,
   15595         NewTypeError(MessageTemplate::kImmutablePrototypeSet, object));
   15596   }
   15597 
   15598   // From 8.6.2 Object Internal Methods
   15599   // ...
   15600   // In addition, if [[Extensible]] is false the value of the [[Class]] and
   15601   // [[Prototype]] internal properties of the object may not be modified.
   15602   // ...
   15603   // Implementation specific extensions that modify [[Class]], [[Prototype]]
   15604   // or [[Extensible]] must not violate the invariants defined in the preceding
   15605   // paragraph.
   15606   if (!all_extensible) {
   15607     RETURN_FAILURE(isolate, should_throw,
   15608                    NewTypeError(MessageTemplate::kNonExtensibleProto, object));
   15609   }
   15610 
   15611   // Before we can set the prototype we need to be sure prototype cycles are
   15612   // prevented.  It is sufficient to validate that the receiver is not in the
   15613   // new prototype chain.
   15614   if (value->IsJSReceiver()) {
   15615     for (PrototypeIterator iter(isolate, JSReceiver::cast(*value),
   15616                                 kStartAtReceiver);
   15617          !iter.IsAtEnd(); iter.Advance()) {
   15618       if (iter.GetCurrent<JSReceiver>() == *object) {
   15619         // Cycle detected.
   15620         RETURN_FAILURE(isolate, should_throw,
   15621                        NewTypeError(MessageTemplate::kCyclicProto));
   15622       }
   15623     }
   15624   }
   15625 
   15626   // Set the new prototype of the object.
   15627 
   15628   isolate->UpdateArrayProtectorOnSetPrototype(real_receiver);
   15629 
   15630   PrototypeOptimizationMode mode =
   15631       from_javascript ? REGULAR_PROTOTYPE : FAST_PROTOTYPE;
   15632   Handle<Map> new_map = Map::TransitionToPrototype(map, value, mode);
   15633   DCHECK(new_map->prototype() == *value);
   15634   JSObject::MigrateToMap(real_receiver, new_map);
   15635 
   15636   if (from_javascript && !dictionary_elements_in_chain &&
   15637       new_map->DictionaryElementsInPrototypeChainOnly()) {
   15638     // If the prototype chain didn't previously have element callbacks, then
   15639     // KeyedStoreICs need to be cleared to ensure any that involve this
   15640     // map go generic.
   15641     TypeFeedbackVector::ClearAllKeyedStoreICs(isolate);
   15642   }
   15643 
   15644   heap->ClearInstanceofCache();
   15645   DCHECK(size == object->Size());
   15646   return Just(true);
   15647 }
   15648 
   15649 // static
   15650 void JSObject::SetImmutableProto(Handle<JSObject> object) {
   15651   DCHECK(!object->IsAccessCheckNeeded());  // Never called from JS
   15652   Handle<Map> map(object->map());
   15653 
   15654   // Nothing to do if prototype is already set.
   15655   if (map->is_immutable_proto()) return;
   15656 
   15657   Handle<Map> new_map = Map::TransitionToImmutableProto(map);
   15658   object->set_map(*new_map);
   15659 }
   15660 
   15661 void JSObject::EnsureCanContainElements(Handle<JSObject> object,
   15662                                         Arguments* args,
   15663                                         uint32_t first_arg,
   15664                                         uint32_t arg_count,
   15665                                         EnsureElementsMode mode) {
   15666   // Elements in |Arguments| are ordered backwards (because they're on the
   15667   // stack), but the method that's called here iterates over them in forward
   15668   // direction.
   15669   return EnsureCanContainElements(
   15670       object, args->arguments() - first_arg - (arg_count - 1), arg_count, mode);
   15671 }
   15672 
   15673 
   15674 ElementsAccessor* JSObject::GetElementsAccessor() {
   15675   return ElementsAccessor::ForKind(GetElementsKind());
   15676 }
   15677 
   15678 
   15679 void JSObject::ValidateElements(Handle<JSObject> object) {
   15680 #ifdef ENABLE_SLOW_DCHECKS
   15681   if (FLAG_enable_slow_asserts) {
   15682     ElementsAccessor* accessor = object->GetElementsAccessor();
   15683     accessor->Validate(object);
   15684   }
   15685 #endif
   15686 }
   15687 
   15688 
   15689 static bool ShouldConvertToSlowElements(JSObject* object, uint32_t capacity,
   15690                                         uint32_t index,
   15691                                         uint32_t* new_capacity) {
   15692   STATIC_ASSERT(JSObject::kMaxUncheckedOldFastElementsLength <=
   15693                 JSObject::kMaxUncheckedFastElementsLength);
   15694   if (index < capacity) {
   15695     *new_capacity = capacity;
   15696     return false;
   15697   }
   15698   if (index - capacity >= JSObject::kMaxGap) return true;
   15699   *new_capacity = JSObject::NewElementsCapacity(index + 1);
   15700   DCHECK_LT(index, *new_capacity);
   15701   if (*new_capacity <= JSObject::kMaxUncheckedOldFastElementsLength ||
   15702       (*new_capacity <= JSObject::kMaxUncheckedFastElementsLength &&
   15703        object->GetHeap()->InNewSpace(object))) {
   15704     return false;
   15705   }
   15706   // If the fast-case backing storage takes up roughly three times as
   15707   // much space (in machine words) as a dictionary backing storage
   15708   // would, the object should have slow elements.
   15709   int used_elements = object->GetFastElementsUsage();
   15710   int dictionary_size = SeededNumberDictionary::ComputeCapacity(used_elements) *
   15711                         SeededNumberDictionary::kEntrySize;
   15712   return 3 * static_cast<uint32_t>(dictionary_size) <= *new_capacity;
   15713 }
   15714 
   15715 
   15716 bool JSObject::WouldConvertToSlowElements(uint32_t index) {
   15717   if (HasFastElements()) {
   15718     Handle<FixedArrayBase> backing_store(FixedArrayBase::cast(elements()));
   15719     uint32_t capacity = static_cast<uint32_t>(backing_store->length());
   15720     uint32_t new_capacity;
   15721     return ShouldConvertToSlowElements(this, capacity, index, &new_capacity);
   15722   }
   15723   return false;
   15724 }
   15725 
   15726 
   15727 static ElementsKind BestFittingFastElementsKind(JSObject* object) {
   15728   if (object->HasSloppyArgumentsElements()) {
   15729     return FAST_SLOPPY_ARGUMENTS_ELEMENTS;
   15730   }
   15731   if (object->HasStringWrapperElements()) {
   15732     return FAST_STRING_WRAPPER_ELEMENTS;
   15733   }
   15734   DCHECK(object->HasDictionaryElements());
   15735   SeededNumberDictionary* dictionary = object->element_dictionary();
   15736   ElementsKind kind = FAST_HOLEY_SMI_ELEMENTS;
   15737   for (int i = 0; i < dictionary->Capacity(); i++) {
   15738     Object* key = dictionary->KeyAt(i);
   15739     if (key->IsNumber()) {
   15740       Object* value = dictionary->ValueAt(i);
   15741       if (!value->IsNumber()) return FAST_HOLEY_ELEMENTS;
   15742       if (!value->IsSmi()) {
   15743         if (!FLAG_unbox_double_arrays) return FAST_HOLEY_ELEMENTS;
   15744         kind = FAST_HOLEY_DOUBLE_ELEMENTS;
   15745       }
   15746     }
   15747   }
   15748   return kind;
   15749 }
   15750 
   15751 
   15752 static bool ShouldConvertToFastElements(JSObject* object,
   15753                                         SeededNumberDictionary* dictionary,
   15754                                         uint32_t index,
   15755                                         uint32_t* new_capacity) {
   15756   // If properties with non-standard attributes or accessors were added, we
   15757   // cannot go back to fast elements.
   15758   if (dictionary->requires_slow_elements()) return false;
   15759 
   15760   // Adding a property with this index will require slow elements.
   15761   if (index >= static_cast<uint32_t>(Smi::kMaxValue)) return false;
   15762 
   15763   if (object->IsJSArray()) {
   15764     Object* length = JSArray::cast(object)->length();
   15765     if (!length->IsSmi()) return false;
   15766     *new_capacity = static_cast<uint32_t>(Smi::cast(length)->value());
   15767   } else {
   15768     *new_capacity = dictionary->max_number_key() + 1;
   15769   }
   15770   *new_capacity = Max(index + 1, *new_capacity);
   15771 
   15772   uint32_t dictionary_size = static_cast<uint32_t>(dictionary->Capacity()) *
   15773                              SeededNumberDictionary::kEntrySize;
   15774 
   15775   // Turn fast if the dictionary only saves 50% space.
   15776   return 2 * dictionary_size >= *new_capacity;
   15777 }
   15778 
   15779 
   15780 // static
   15781 MaybeHandle<Object> JSObject::AddDataElement(Handle<JSObject> object,
   15782                                              uint32_t index,
   15783                                              Handle<Object> value,
   15784                                              PropertyAttributes attributes) {
   15785   MAYBE_RETURN_NULL(
   15786       AddDataElement(object, index, value, attributes, THROW_ON_ERROR));
   15787   return value;
   15788 }
   15789 
   15790 
   15791 // static
   15792 Maybe<bool> JSObject::AddDataElement(Handle<JSObject> object, uint32_t index,
   15793                                      Handle<Object> value,
   15794                                      PropertyAttributes attributes,
   15795                                      ShouldThrow should_throw) {
   15796   DCHECK(object->map()->is_extensible());
   15797 
   15798   Isolate* isolate = object->GetIsolate();
   15799 
   15800   uint32_t old_length = 0;
   15801   uint32_t new_capacity = 0;
   15802 
   15803   if (object->IsJSArray()) {
   15804     CHECK(JSArray::cast(*object)->length()->ToArrayLength(&old_length));
   15805   }
   15806 
   15807   ElementsKind kind = object->GetElementsKind();
   15808   FixedArrayBase* elements = object->elements();
   15809   ElementsKind dictionary_kind = DICTIONARY_ELEMENTS;
   15810   if (IsSloppyArgumentsElements(kind)) {
   15811     elements = FixedArrayBase::cast(FixedArray::cast(elements)->get(1));
   15812     dictionary_kind = SLOW_SLOPPY_ARGUMENTS_ELEMENTS;
   15813   } else if (IsStringWrapperElementsKind(kind)) {
   15814     dictionary_kind = SLOW_STRING_WRAPPER_ELEMENTS;
   15815   }
   15816 
   15817   if (attributes != NONE) {
   15818     kind = dictionary_kind;
   15819   } else if (elements->IsSeededNumberDictionary()) {
   15820     kind = ShouldConvertToFastElements(*object,
   15821                                        SeededNumberDictionary::cast(elements),
   15822                                        index, &new_capacity)
   15823                ? BestFittingFastElementsKind(*object)
   15824                : dictionary_kind;  // Overwrite in case of arguments.
   15825   } else if (ShouldConvertToSlowElements(
   15826                  *object, static_cast<uint32_t>(elements->length()), index,
   15827                  &new_capacity)) {
   15828     kind = dictionary_kind;
   15829   }
   15830 
   15831   ElementsKind to = value->OptimalElementsKind();
   15832   if (IsHoleyElementsKind(kind) || !object->IsJSArray() || index > old_length) {
   15833     to = GetHoleyElementsKind(to);
   15834     kind = GetHoleyElementsKind(kind);
   15835   }
   15836   to = GetMoreGeneralElementsKind(kind, to);
   15837   ElementsAccessor* accessor = ElementsAccessor::ForKind(to);
   15838   accessor->Add(object, index, value, attributes, new_capacity);
   15839 
   15840   uint32_t new_length = old_length;
   15841   Handle<Object> new_length_handle;
   15842   if (object->IsJSArray() && index >= old_length) {
   15843     new_length = index + 1;
   15844     new_length_handle = isolate->factory()->NewNumberFromUint(new_length);
   15845     JSArray::cast(*object)->set_length(*new_length_handle);
   15846   }
   15847 
   15848   return Just(true);
   15849 }
   15850 
   15851 
   15852 bool JSArray::SetLengthWouldNormalize(uint32_t new_length) {
   15853   if (!HasFastElements()) return false;
   15854   uint32_t capacity = static_cast<uint32_t>(elements()->length());
   15855   uint32_t new_capacity;
   15856   return JSArray::SetLengthWouldNormalize(GetHeap(), new_length) &&
   15857          ShouldConvertToSlowElements(this, capacity, new_length - 1,
   15858                                      &new_capacity);
   15859 }
   15860 
   15861 
   15862 const double AllocationSite::kPretenureRatio = 0.85;
   15863 
   15864 
   15865 void AllocationSite::ResetPretenureDecision() {
   15866   set_pretenure_decision(kUndecided);
   15867   set_memento_found_count(0);
   15868   set_memento_create_count(0);
   15869 }
   15870 
   15871 
   15872 PretenureFlag AllocationSite::GetPretenureMode() {
   15873   PretenureDecision mode = pretenure_decision();
   15874   // Zombie objects "decide" to be untenured.
   15875   return mode == kTenure ? TENURED : NOT_TENURED;
   15876 }
   15877 
   15878 
   15879 bool AllocationSite::IsNestedSite() {
   15880   DCHECK(FLAG_trace_track_allocation_sites);
   15881   Object* current = GetHeap()->allocation_sites_list();
   15882   while (current->IsAllocationSite()) {
   15883     AllocationSite* current_site = AllocationSite::cast(current);
   15884     if (current_site->nested_site() == this) {
   15885       return true;
   15886     }
   15887     current = current_site->weak_next();
   15888   }
   15889   return false;
   15890 }
   15891 
   15892 template <AllocationSiteUpdateMode update_or_check>
   15893 bool AllocationSite::DigestTransitionFeedback(Handle<AllocationSite> site,
   15894                                               ElementsKind to_kind) {
   15895   Isolate* isolate = site->GetIsolate();
   15896   bool result = false;
   15897 
   15898   if (site->SitePointsToLiteral() && site->transition_info()->IsJSArray()) {
   15899     Handle<JSArray> transition_info =
   15900         handle(JSArray::cast(site->transition_info()));
   15901     ElementsKind kind = transition_info->GetElementsKind();
   15902     // if kind is holey ensure that to_kind is as well.
   15903     if (IsHoleyElementsKind(kind)) {
   15904       to_kind = GetHoleyElementsKind(to_kind);
   15905     }
   15906     if (IsMoreGeneralElementsKindTransition(kind, to_kind)) {
   15907       // If the array is huge, it's not likely to be defined in a local
   15908       // function, so we shouldn't make new instances of it very often.
   15909       uint32_t length = 0;
   15910       CHECK(transition_info->length()->ToArrayLength(&length));
   15911       if (length <= kMaximumArrayBytesToPretransition) {
   15912         if (update_or_check == AllocationSiteUpdateMode::kCheckOnly) {
   15913           return true;
   15914         }
   15915         if (FLAG_trace_track_allocation_sites) {
   15916           bool is_nested = site->IsNestedSite();
   15917           PrintF(
   15918               "AllocationSite: JSArray %p boilerplate %s updated %s->%s\n",
   15919               reinterpret_cast<void*>(*site),
   15920               is_nested ? "(nested)" : "",
   15921               ElementsKindToString(kind),
   15922               ElementsKindToString(to_kind));
   15923         }
   15924         JSObject::TransitionElementsKind(transition_info, to_kind);
   15925         site->dependent_code()->DeoptimizeDependentCodeGroup(
   15926             isolate, DependentCode::kAllocationSiteTransitionChangedGroup);
   15927         result = true;
   15928       }
   15929     }
   15930   } else {
   15931     ElementsKind kind = site->GetElementsKind();
   15932     // if kind is holey ensure that to_kind is as well.
   15933     if (IsHoleyElementsKind(kind)) {
   15934       to_kind = GetHoleyElementsKind(to_kind);
   15935     }
   15936     if (IsMoreGeneralElementsKindTransition(kind, to_kind)) {
   15937       if (update_or_check == AllocationSiteUpdateMode::kCheckOnly) return true;
   15938       if (FLAG_trace_track_allocation_sites) {
   15939         PrintF("AllocationSite: JSArray %p site updated %s->%s\n",
   15940                reinterpret_cast<void*>(*site),
   15941                ElementsKindToString(kind),
   15942                ElementsKindToString(to_kind));
   15943       }
   15944       site->SetElementsKind(to_kind);
   15945       site->dependent_code()->DeoptimizeDependentCodeGroup(
   15946           isolate, DependentCode::kAllocationSiteTransitionChangedGroup);
   15947       result = true;
   15948     }
   15949   }
   15950   return result;
   15951 }
   15952 
   15953 AllocationSiteMode AllocationSite::GetMode(ElementsKind from, ElementsKind to) {
   15954   if (IsFastSmiElementsKind(from) &&
   15955       IsMoreGeneralElementsKindTransition(from, to)) {
   15956     return TRACK_ALLOCATION_SITE;
   15957   }
   15958 
   15959   return DONT_TRACK_ALLOCATION_SITE;
   15960 }
   15961 
   15962 const char* AllocationSite::PretenureDecisionName(PretenureDecision decision) {
   15963   switch (decision) {
   15964     case kUndecided: return "undecided";
   15965     case kDontTenure: return "don't tenure";
   15966     case kMaybeTenure: return "maybe tenure";
   15967     case kTenure: return "tenure";
   15968     case kZombie: return "zombie";
   15969     default: UNREACHABLE();
   15970   }
   15971   return NULL;
   15972 }
   15973 
   15974 template <AllocationSiteUpdateMode update_or_check>
   15975 bool JSObject::UpdateAllocationSite(Handle<JSObject> object,
   15976                                     ElementsKind to_kind) {
   15977   if (!object->IsJSArray()) return false;
   15978 
   15979   Heap* heap = object->GetHeap();
   15980   if (!heap->InNewSpace(*object)) return false;
   15981 
   15982   Handle<AllocationSite> site;
   15983   {
   15984     DisallowHeapAllocation no_allocation;
   15985 
   15986     AllocationMemento* memento =
   15987         heap->FindAllocationMemento<Heap::kForRuntime>(*object);
   15988     if (memento == NULL) return false;
   15989 
   15990     // Walk through to the Allocation Site
   15991     site = handle(memento->GetAllocationSite());
   15992   }
   15993   return AllocationSite::DigestTransitionFeedback<update_or_check>(site,
   15994                                                                    to_kind);
   15995 }
   15996 
   15997 template bool
   15998 JSObject::UpdateAllocationSite<AllocationSiteUpdateMode::kCheckOnly>(
   15999     Handle<JSObject> object, ElementsKind to_kind);
   16000 
   16001 template bool JSObject::UpdateAllocationSite<AllocationSiteUpdateMode::kUpdate>(
   16002     Handle<JSObject> object, ElementsKind to_kind);
   16003 
   16004 void JSObject::TransitionElementsKind(Handle<JSObject> object,
   16005                                       ElementsKind to_kind) {
   16006   ElementsKind from_kind = object->GetElementsKind();
   16007 
   16008   if (IsFastHoleyElementsKind(from_kind)) {
   16009     to_kind = GetHoleyElementsKind(to_kind);
   16010   }
   16011 
   16012   if (from_kind == to_kind) return;
   16013 
   16014   // This method should never be called for any other case.
   16015   DCHECK(IsFastElementsKind(from_kind));
   16016   DCHECK(IsFastElementsKind(to_kind));
   16017   DCHECK_NE(TERMINAL_FAST_ELEMENTS_KIND, from_kind);
   16018 
   16019   UpdateAllocationSite(object, to_kind);
   16020   if (object->elements() == object->GetHeap()->empty_fixed_array() ||
   16021       IsFastDoubleElementsKind(from_kind) ==
   16022           IsFastDoubleElementsKind(to_kind)) {
   16023     // No change is needed to the elements() buffer, the transition
   16024     // only requires a map change.
   16025     Handle<Map> new_map = GetElementsTransitionMap(object, to_kind);
   16026     MigrateToMap(object, new_map);
   16027     if (FLAG_trace_elements_transitions) {
   16028       Handle<FixedArrayBase> elms(object->elements());
   16029       PrintElementsTransition(stdout, object, from_kind, elms, to_kind, elms);
   16030     }
   16031   } else {
   16032     DCHECK((IsFastSmiElementsKind(from_kind) &&
   16033             IsFastDoubleElementsKind(to_kind)) ||
   16034            (IsFastDoubleElementsKind(from_kind) &&
   16035             IsFastObjectElementsKind(to_kind)));
   16036     uint32_t c = static_cast<uint32_t>(object->elements()->length());
   16037     ElementsAccessor::ForKind(to_kind)->GrowCapacityAndConvert(object, c);
   16038   }
   16039 }
   16040 
   16041 
   16042 // static
   16043 bool Map::IsValidElementsTransition(ElementsKind from_kind,
   16044                                     ElementsKind to_kind) {
   16045   // Transitions can't go backwards.
   16046   if (!IsMoreGeneralElementsKindTransition(from_kind, to_kind)) {
   16047     return false;
   16048   }
   16049 
   16050   // Transitions from HOLEY -> PACKED are not allowed.
   16051   return !IsFastHoleyElementsKind(from_kind) ||
   16052       IsFastHoleyElementsKind(to_kind);
   16053 }
   16054 
   16055 
   16056 bool JSArray::HasReadOnlyLength(Handle<JSArray> array) {
   16057   Map* map = array->map();
   16058   // Fast path: "length" is the first fast property of arrays. Since it's not
   16059   // configurable, it's guaranteed to be the first in the descriptor array.
   16060   if (!map->is_dictionary_map()) {
   16061     DCHECK(map->instance_descriptors()->GetKey(0) ==
   16062            array->GetHeap()->length_string());
   16063     return map->instance_descriptors()->GetDetails(0).IsReadOnly();
   16064   }
   16065 
   16066   Isolate* isolate = array->GetIsolate();
   16067   LookupIterator it(array, isolate->factory()->length_string(), array,
   16068                     LookupIterator::OWN_SKIP_INTERCEPTOR);
   16069   CHECK_EQ(LookupIterator::ACCESSOR, it.state());
   16070   return it.IsReadOnly();
   16071 }
   16072 
   16073 
   16074 bool JSArray::WouldChangeReadOnlyLength(Handle<JSArray> array,
   16075                                         uint32_t index) {
   16076   uint32_t length = 0;
   16077   CHECK(array->length()->ToArrayLength(&length));
   16078   if (length <= index) return HasReadOnlyLength(array);
   16079   return false;
   16080 }
   16081 
   16082 
   16083 template <typename BackingStore>
   16084 static int FastHoleyElementsUsage(JSObject* object, BackingStore* store) {
   16085   Isolate* isolate = store->GetIsolate();
   16086   int limit = object->IsJSArray()
   16087                   ? Smi::cast(JSArray::cast(object)->length())->value()
   16088                   : store->length();
   16089   int used = 0;
   16090   for (int i = 0; i < limit; ++i) {
   16091     if (!store->is_the_hole(isolate, i)) ++used;
   16092   }
   16093   return used;
   16094 }
   16095 
   16096 
   16097 int JSObject::GetFastElementsUsage() {
   16098   FixedArrayBase* store = elements();
   16099   switch (GetElementsKind()) {
   16100     case FAST_SMI_ELEMENTS:
   16101     case FAST_DOUBLE_ELEMENTS:
   16102     case FAST_ELEMENTS:
   16103       return IsJSArray() ? Smi::cast(JSArray::cast(this)->length())->value()
   16104                          : store->length();
   16105     case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
   16106       store = FixedArray::cast(FixedArray::cast(store)->get(1));
   16107     // Fall through.
   16108     case FAST_HOLEY_SMI_ELEMENTS:
   16109     case FAST_HOLEY_ELEMENTS:
   16110     case FAST_STRING_WRAPPER_ELEMENTS:
   16111       return FastHoleyElementsUsage(this, FixedArray::cast(store));
   16112     case FAST_HOLEY_DOUBLE_ELEMENTS:
   16113       if (elements()->length() == 0) return 0;
   16114       return FastHoleyElementsUsage(this, FixedDoubleArray::cast(store));
   16115 
   16116     case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
   16117     case SLOW_STRING_WRAPPER_ELEMENTS:
   16118     case DICTIONARY_ELEMENTS:
   16119     case NO_ELEMENTS:
   16120 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                      \
   16121     case TYPE##_ELEMENTS:                                                    \
   16122 
   16123     TYPED_ARRAYS(TYPED_ARRAY_CASE)
   16124 #undef TYPED_ARRAY_CASE
   16125     UNREACHABLE();
   16126   }
   16127   return 0;
   16128 }
   16129 
   16130 
   16131 // Certain compilers request function template instantiation when they
   16132 // see the definition of the other template functions in the
   16133 // class. This requires us to have the template functions put
   16134 // together, so even though this function belongs in objects-debug.cc,
   16135 // we keep it here instead to satisfy certain compilers.
   16136 #ifdef OBJECT_PRINT
   16137 template <typename Derived, typename Shape, typename Key>
   16138 void Dictionary<Derived, Shape, Key>::Print(std::ostream& os) {  // NOLINT
   16139   Isolate* isolate = this->GetIsolate();
   16140   int capacity = this->Capacity();
   16141   for (int i = 0; i < capacity; i++) {
   16142     Object* k = this->KeyAt(i);
   16143     if (this->IsKey(isolate, k)) {
   16144       os << "\n   ";
   16145       if (k->IsString()) {
   16146         String::cast(k)->StringPrint(os);
   16147       } else {
   16148         os << Brief(k);
   16149       }
   16150       os << ": " << Brief(this->ValueAt(i)) << " " << this->DetailsAt(i);
   16151     }
   16152   }
   16153 }
   16154 template <typename Derived, typename Shape, typename Key>
   16155 void Dictionary<Derived, Shape, Key>::Print() {
   16156   OFStream os(stdout);
   16157   Print(os);
   16158 }
   16159 #endif
   16160 
   16161 
   16162 template<typename Derived, typename Shape, typename Key>
   16163 void Dictionary<Derived, Shape, Key>::CopyValuesTo(FixedArray* elements) {
   16164   Isolate* isolate = this->GetIsolate();
   16165   int pos = 0;
   16166   int capacity = this->Capacity();
   16167   DisallowHeapAllocation no_gc;
   16168   WriteBarrierMode mode = elements->GetWriteBarrierMode(no_gc);
   16169   for (int i = 0; i < capacity; i++) {
   16170     Object* k = this->KeyAt(i);
   16171     if (this->IsKey(isolate, k)) {
   16172       elements->set(pos++, this->ValueAt(i), mode);
   16173     }
   16174   }
   16175   DCHECK(pos == elements->length());
   16176 }
   16177 
   16178 
   16179 MaybeHandle<Object> JSObject::GetPropertyWithInterceptor(LookupIterator* it,
   16180                                                          bool* done) {
   16181   DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state());
   16182   return GetPropertyWithInterceptorInternal(it, it->GetInterceptor(), done);
   16183 }
   16184 
   16185 Maybe<bool> JSObject::HasRealNamedProperty(Handle<JSObject> object,
   16186                                            Handle<Name> name) {
   16187   LookupIterator it = LookupIterator::PropertyOrElement(
   16188       name->GetIsolate(), object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
   16189   return HasProperty(&it);
   16190 }
   16191 
   16192 
   16193 Maybe<bool> JSObject::HasRealElementProperty(Handle<JSObject> object,
   16194                                              uint32_t index) {
   16195   Isolate* isolate = object->GetIsolate();
   16196   LookupIterator it(isolate, object, index, object,
   16197                     LookupIterator::OWN_SKIP_INTERCEPTOR);
   16198   return HasProperty(&it);
   16199 }
   16200 
   16201 
   16202 Maybe<bool> JSObject::HasRealNamedCallbackProperty(Handle<JSObject> object,
   16203                                                    Handle<Name> name) {
   16204   LookupIterator it = LookupIterator::PropertyOrElement(
   16205       name->GetIsolate(), object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
   16206   Maybe<PropertyAttributes> maybe_result = GetPropertyAttributes(&it);
   16207   return maybe_result.IsJust() ? Just(it.state() == LookupIterator::ACCESSOR)
   16208                                : Nothing<bool>();
   16209 }
   16210 
   16211 int FixedArrayBase::GetMaxLengthForNewSpaceAllocation(ElementsKind kind) {
   16212   return ((kMaxRegularHeapObjectSize - FixedArrayBase::kHeaderSize) >>
   16213           ElementsKindToShiftSize(kind));
   16214 }
   16215 
   16216 void FixedArray::SwapPairs(FixedArray* numbers, int i, int j) {
   16217   Object* temp = get(i);
   16218   set(i, get(j));
   16219   set(j, temp);
   16220   if (this != numbers) {
   16221     temp = numbers->get(i);
   16222     numbers->set(i, Smi::cast(numbers->get(j)));
   16223     numbers->set(j, Smi::cast(temp));
   16224   }
   16225 }
   16226 
   16227 
   16228 static void InsertionSortPairs(FixedArray* content,
   16229                                FixedArray* numbers,
   16230                                int len) {
   16231   for (int i = 1; i < len; i++) {
   16232     int j = i;
   16233     while (j > 0 &&
   16234            (NumberToUint32(numbers->get(j - 1)) >
   16235             NumberToUint32(numbers->get(j)))) {
   16236       content->SwapPairs(numbers, j - 1, j);
   16237       j--;
   16238     }
   16239   }
   16240 }
   16241 
   16242 
   16243 void HeapSortPairs(FixedArray* content, FixedArray* numbers, int len) {
   16244   // In-place heap sort.
   16245   DCHECK(content->length() == numbers->length());
   16246 
   16247   // Bottom-up max-heap construction.
   16248   for (int i = 1; i < len; ++i) {
   16249     int child_index = i;
   16250     while (child_index > 0) {
   16251       int parent_index = ((child_index + 1) >> 1) - 1;
   16252       uint32_t parent_value = NumberToUint32(numbers->get(parent_index));
   16253       uint32_t child_value = NumberToUint32(numbers->get(child_index));
   16254       if (parent_value < child_value) {
   16255         content->SwapPairs(numbers, parent_index, child_index);
   16256       } else {
   16257         break;
   16258       }
   16259       child_index = parent_index;
   16260     }
   16261   }
   16262 
   16263   // Extract elements and create sorted array.
   16264   for (int i = len - 1; i > 0; --i) {
   16265     // Put max element at the back of the array.
   16266     content->SwapPairs(numbers, 0, i);
   16267     // Sift down the new top element.
   16268     int parent_index = 0;
   16269     while (true) {
   16270       int child_index = ((parent_index + 1) << 1) - 1;
   16271       if (child_index >= i) break;
   16272       uint32_t child1_value = NumberToUint32(numbers->get(child_index));
   16273       uint32_t child2_value = NumberToUint32(numbers->get(child_index + 1));
   16274       uint32_t parent_value = NumberToUint32(numbers->get(parent_index));
   16275       if (child_index + 1 >= i || child1_value > child2_value) {
   16276         if (parent_value > child1_value) break;
   16277         content->SwapPairs(numbers, parent_index, child_index);
   16278         parent_index = child_index;
   16279       } else {
   16280         if (parent_value > child2_value) break;
   16281         content->SwapPairs(numbers, parent_index, child_index + 1);
   16282         parent_index = child_index + 1;
   16283       }
   16284     }
   16285   }
   16286 }
   16287 
   16288 
   16289 // Sort this array and the numbers as pairs wrt. the (distinct) numbers.
   16290 void FixedArray::SortPairs(FixedArray* numbers, uint32_t len) {
   16291   DCHECK(this->length() == numbers->length());
   16292   // For small arrays, simply use insertion sort.
   16293   if (len <= 10) {
   16294     InsertionSortPairs(this, numbers, len);
   16295     return;
   16296   }
   16297   // Check the range of indices.
   16298   uint32_t min_index = NumberToUint32(numbers->get(0));
   16299   uint32_t max_index = min_index;
   16300   uint32_t i;
   16301   for (i = 1; i < len; i++) {
   16302     if (NumberToUint32(numbers->get(i)) < min_index) {
   16303       min_index = NumberToUint32(numbers->get(i));
   16304     } else if (NumberToUint32(numbers->get(i)) > max_index) {
   16305       max_index = NumberToUint32(numbers->get(i));
   16306     }
   16307   }
   16308   if (max_index - min_index + 1 == len) {
   16309     // Indices form a contiguous range, unless there are duplicates.
   16310     // Do an in-place linear time sort assuming distinct numbers, but
   16311     // avoid hanging in case they are not.
   16312     for (i = 0; i < len; i++) {
   16313       uint32_t p;
   16314       uint32_t j = 0;
   16315       // While the current element at i is not at its correct position p,
   16316       // swap the elements at these two positions.
   16317       while ((p = NumberToUint32(numbers->get(i)) - min_index) != i &&
   16318              j++ < len) {
   16319         SwapPairs(numbers, i, p);
   16320       }
   16321     }
   16322   } else {
   16323     HeapSortPairs(this, numbers, len);
   16324     return;
   16325   }
   16326 }
   16327 
   16328 bool JSObject::WasConstructedFromApiFunction() {
   16329   auto instance_type = map()->instance_type();
   16330   bool is_api_object = instance_type == JS_API_OBJECT_TYPE ||
   16331                        instance_type == JS_SPECIAL_API_OBJECT_TYPE;
   16332 #ifdef ENABLE_SLOW_DCHECKS
   16333   if (FLAG_enable_slow_asserts) {
   16334     Object* maybe_constructor = map()->GetConstructor();
   16335     if (!maybe_constructor->IsJSFunction()) return false;
   16336     JSFunction* constructor = JSFunction::cast(maybe_constructor);
   16337     if (constructor->shared()->IsApiFunction()) {
   16338       DCHECK(is_api_object);
   16339     } else {
   16340       DCHECK(!is_api_object);
   16341     }
   16342   }
   16343 #endif
   16344   return is_api_object;
   16345 }
   16346 
   16347 MaybeHandle<String> Object::ObjectProtoToString(Isolate* isolate,
   16348                                                 Handle<Object> object) {
   16349   if (*object == isolate->heap()->undefined_value()) {
   16350     return isolate->factory()->undefined_to_string();
   16351   }
   16352   if (*object == isolate->heap()->null_value()) {
   16353     return isolate->factory()->null_to_string();
   16354   }
   16355 
   16356   Handle<JSReceiver> receiver =
   16357       Object::ToObject(isolate, object).ToHandleChecked();
   16358 
   16359   // For proxies, we must check IsArray() before get(toStringTag) to comply
   16360   // with the specification
   16361   Maybe<bool> is_array = Nothing<bool>();
   16362   InstanceType instance_type = receiver->map()->instance_type();
   16363   if (instance_type == JS_PROXY_TYPE) {
   16364     is_array = Object::IsArray(receiver);
   16365     MAYBE_RETURN(is_array, MaybeHandle<String>());
   16366   }
   16367 
   16368   Handle<String> tag;
   16369   Handle<Object> to_string_tag;
   16370   ASSIGN_RETURN_ON_EXCEPTION(
   16371       isolate, to_string_tag,
   16372       JSReceiver::GetProperty(receiver,
   16373                               isolate->factory()->to_string_tag_symbol()),
   16374       String);
   16375   if (to_string_tag->IsString()) {
   16376     tag = Handle<String>::cast(to_string_tag);
   16377   } else {
   16378     switch (instance_type) {
   16379       case JS_API_OBJECT_TYPE:
   16380       case JS_SPECIAL_API_OBJECT_TYPE:
   16381         tag = handle(receiver->class_name(), isolate);
   16382         break;
   16383       case JS_ARGUMENTS_TYPE:
   16384         return isolate->factory()->arguments_to_string();
   16385       case JS_ARRAY_TYPE:
   16386         return isolate->factory()->array_to_string();
   16387       case JS_BOUND_FUNCTION_TYPE:
   16388       case JS_FUNCTION_TYPE:
   16389         return isolate->factory()->function_to_string();
   16390       case JS_ERROR_TYPE:
   16391         return isolate->factory()->error_to_string();
   16392       case JS_DATE_TYPE:
   16393         return isolate->factory()->date_to_string();
   16394       case JS_REGEXP_TYPE:
   16395         return isolate->factory()->regexp_to_string();
   16396       case JS_PROXY_TYPE: {
   16397         if (is_array.FromJust()) {
   16398           return isolate->factory()->array_to_string();
   16399         }
   16400         if (receiver->IsCallable()) {
   16401           return isolate->factory()->function_to_string();
   16402         }
   16403         return isolate->factory()->object_to_string();
   16404       }
   16405       case JS_VALUE_TYPE: {
   16406         Object* value = JSValue::cast(*receiver)->value();
   16407         if (value->IsString()) {
   16408           return isolate->factory()->string_to_string();
   16409         }
   16410         if (value->IsNumber()) {
   16411           return isolate->factory()->number_to_string();
   16412         }
   16413         if (value->IsBoolean()) {
   16414           return isolate->factory()->boolean_to_string();
   16415         }
   16416         if (value->IsSymbol()) {
   16417           return isolate->factory()->object_to_string();
   16418         }
   16419         UNREACHABLE();
   16420         tag = handle(receiver->class_name(), isolate);
   16421         break;
   16422       }
   16423       default:
   16424         return isolate->factory()->object_to_string();
   16425     }
   16426   }
   16427 
   16428   IncrementalStringBuilder builder(isolate);
   16429   builder.AppendCString("[object ");
   16430   builder.AppendString(tag);
   16431   builder.AppendCharacter(']');
   16432   return builder.Finish();
   16433 }
   16434 
   16435 const char* Symbol::PrivateSymbolToName() const {
   16436   Heap* heap = GetIsolate()->heap();
   16437 #define SYMBOL_CHECK_AND_PRINT(name) \
   16438   if (this == heap->name()) return #name;
   16439   PRIVATE_SYMBOL_LIST(SYMBOL_CHECK_AND_PRINT)
   16440 #undef SYMBOL_CHECK_AND_PRINT
   16441   return "UNKNOWN";
   16442 }
   16443 
   16444 
   16445 void Symbol::SymbolShortPrint(std::ostream& os) {
   16446   os << "<Symbol:";
   16447   if (!name()->IsUndefined(GetIsolate())) {
   16448     os << " ";
   16449     HeapStringAllocator allocator;
   16450     StringStream accumulator(&allocator);
   16451     String::cast(name())->StringShortPrint(&accumulator, false);
   16452     os << accumulator.ToCString().get();
   16453   } else {
   16454     os << " (" << PrivateSymbolToName() << ")";
   16455   }
   16456   os << ">";
   16457 }
   16458 
   16459 
   16460 // StringSharedKeys are used as keys in the eval cache.
   16461 class StringSharedKey : public HashTableKey {
   16462  public:
   16463   StringSharedKey(Handle<String> source, Handle<SharedFunctionInfo> shared,
   16464                   LanguageMode language_mode, int scope_position)
   16465       : source_(source),
   16466         shared_(shared),
   16467         language_mode_(language_mode),
   16468         scope_position_(scope_position) {}
   16469 
   16470   bool IsMatch(Object* other) override {
   16471     DisallowHeapAllocation no_allocation;
   16472     if (!other->IsFixedArray()) {
   16473       if (!other->IsNumber()) return false;
   16474       uint32_t other_hash = static_cast<uint32_t>(other->Number());
   16475       return Hash() == other_hash;
   16476     }
   16477     FixedArray* other_array = FixedArray::cast(other);
   16478     SharedFunctionInfo* shared = SharedFunctionInfo::cast(other_array->get(0));
   16479     if (shared != *shared_) return false;
   16480     int language_unchecked = Smi::cast(other_array->get(2))->value();
   16481     DCHECK(is_valid_language_mode(language_unchecked));
   16482     LanguageMode language_mode = static_cast<LanguageMode>(language_unchecked);
   16483     if (language_mode != language_mode_) return false;
   16484     int scope_position = Smi::cast(other_array->get(3))->value();
   16485     if (scope_position != scope_position_) return false;
   16486     String* source = String::cast(other_array->get(1));
   16487     return source->Equals(*source_);
   16488   }
   16489 
   16490   static uint32_t StringSharedHashHelper(String* source,
   16491                                          SharedFunctionInfo* shared,
   16492                                          LanguageMode language_mode,
   16493                                          int scope_position) {
   16494     uint32_t hash = source->Hash();
   16495     if (shared->HasSourceCode()) {
   16496       // Instead of using the SharedFunctionInfo pointer in the hash
   16497       // code computation, we use a combination of the hash of the
   16498       // script source code and the start position of the calling scope.
   16499       // We do this to ensure that the cache entries can survive garbage
   16500       // collection.
   16501       Script* script(Script::cast(shared->script()));
   16502       hash ^= String::cast(script->source())->Hash();
   16503       STATIC_ASSERT(LANGUAGE_END == 2);
   16504       if (is_strict(language_mode)) hash ^= 0x8000;
   16505       hash += scope_position;
   16506     }
   16507     return hash;
   16508   }
   16509 
   16510   uint32_t Hash() override {
   16511     return StringSharedHashHelper(*source_, *shared_, language_mode_,
   16512                                   scope_position_);
   16513   }
   16514 
   16515   uint32_t HashForObject(Object* obj) override {
   16516     DisallowHeapAllocation no_allocation;
   16517     if (obj->IsNumber()) {
   16518       return static_cast<uint32_t>(obj->Number());
   16519     }
   16520     FixedArray* other_array = FixedArray::cast(obj);
   16521     SharedFunctionInfo* shared = SharedFunctionInfo::cast(other_array->get(0));
   16522     String* source = String::cast(other_array->get(1));
   16523     int language_unchecked = Smi::cast(other_array->get(2))->value();
   16524     DCHECK(is_valid_language_mode(language_unchecked));
   16525     LanguageMode language_mode = static_cast<LanguageMode>(language_unchecked);
   16526     int scope_position = Smi::cast(other_array->get(3))->value();
   16527     return StringSharedHashHelper(source, shared, language_mode,
   16528                                   scope_position);
   16529   }
   16530 
   16531 
   16532   Handle<Object> AsHandle(Isolate* isolate) override {
   16533     Handle<FixedArray> array = isolate->factory()->NewFixedArray(4);
   16534     array->set(0, *shared_);
   16535     array->set(1, *source_);
   16536     array->set(2, Smi::FromInt(language_mode_));
   16537     array->set(3, Smi::FromInt(scope_position_));
   16538     return array;
   16539   }
   16540 
   16541  private:
   16542   Handle<String> source_;
   16543   Handle<SharedFunctionInfo> shared_;
   16544   LanguageMode language_mode_;
   16545   int scope_position_;
   16546 };
   16547 
   16548 
   16549 namespace {
   16550 
   16551 JSRegExp::Flags RegExpFlagsFromString(Handle<String> flags, bool* success) {
   16552   JSRegExp::Flags value = JSRegExp::kNone;
   16553   int length = flags->length();
   16554   // A longer flags string cannot be valid.
   16555   if (length > 5) return JSRegExp::Flags(0);
   16556   for (int i = 0; i < length; i++) {
   16557     JSRegExp::Flag flag = JSRegExp::kNone;
   16558     switch (flags->Get(i)) {
   16559       case 'g':
   16560         flag = JSRegExp::kGlobal;
   16561         break;
   16562       case 'i':
   16563         flag = JSRegExp::kIgnoreCase;
   16564         break;
   16565       case 'm':
   16566         flag = JSRegExp::kMultiline;
   16567         break;
   16568       case 'u':
   16569         flag = JSRegExp::kUnicode;
   16570         break;
   16571       case 'y':
   16572         flag = JSRegExp::kSticky;
   16573         break;
   16574       default:
   16575         return JSRegExp::Flags(0);
   16576     }
   16577     // Duplicate flag.
   16578     if (value & flag) return JSRegExp::Flags(0);
   16579     value |= flag;
   16580   }
   16581   *success = true;
   16582   return value;
   16583 }
   16584 
   16585 }  // namespace
   16586 
   16587 
   16588 // static
   16589 MaybeHandle<JSRegExp> JSRegExp::New(Handle<String> pattern, Flags flags) {
   16590   Isolate* isolate = pattern->GetIsolate();
   16591   Handle<JSFunction> constructor = isolate->regexp_function();
   16592   Handle<JSRegExp> regexp =
   16593       Handle<JSRegExp>::cast(isolate->factory()->NewJSObject(constructor));
   16594 
   16595   return JSRegExp::Initialize(regexp, pattern, flags);
   16596 }
   16597 
   16598 
   16599 // static
   16600 Handle<JSRegExp> JSRegExp::Copy(Handle<JSRegExp> regexp) {
   16601   Isolate* const isolate = regexp->GetIsolate();
   16602   return Handle<JSRegExp>::cast(isolate->factory()->CopyJSObject(regexp));
   16603 }
   16604 
   16605 
   16606 template <typename Char>
   16607 inline int CountRequiredEscapes(Handle<String> source) {
   16608   DisallowHeapAllocation no_gc;
   16609   int escapes = 0;
   16610   Vector<const Char> src = source->GetCharVector<Char>();
   16611   for (int i = 0; i < src.length(); i++) {
   16612     if (src[i] == '\\') {
   16613       // Escape. Skip next character;
   16614       i++;
   16615     } else if (src[i] == '/') {
   16616       // Not escaped forward-slash needs escape.
   16617       escapes++;
   16618     }
   16619   }
   16620   return escapes;
   16621 }
   16622 
   16623 
   16624 template <typename Char, typename StringType>
   16625 inline Handle<StringType> WriteEscapedRegExpSource(Handle<String> source,
   16626                                                    Handle<StringType> result) {
   16627   DisallowHeapAllocation no_gc;
   16628   Vector<const Char> src = source->GetCharVector<Char>();
   16629   Vector<Char> dst(result->GetChars(), result->length());
   16630   int s = 0;
   16631   int d = 0;
   16632   while (s < src.length()) {
   16633     if (src[s] == '\\') {
   16634       // Escape. Copy this and next character.
   16635       dst[d++] = src[s++];
   16636       if (s == src.length()) break;
   16637     } else if (src[s] == '/') {
   16638       // Not escaped forward-slash needs escape.
   16639       dst[d++] = '\\';
   16640     }
   16641     dst[d++] = src[s++];
   16642   }
   16643   DCHECK_EQ(result->length(), d);
   16644   return result;
   16645 }
   16646 
   16647 
   16648 MaybeHandle<String> EscapeRegExpSource(Isolate* isolate,
   16649                                        Handle<String> source) {
   16650   String::Flatten(source);
   16651   if (source->length() == 0) return isolate->factory()->query_colon_string();
   16652   bool one_byte = source->IsOneByteRepresentationUnderneath();
   16653   int escapes = one_byte ? CountRequiredEscapes<uint8_t>(source)
   16654                          : CountRequiredEscapes<uc16>(source);
   16655   if (escapes == 0) return source;
   16656   int length = source->length() + escapes;
   16657   if (one_byte) {
   16658     Handle<SeqOneByteString> result;
   16659     ASSIGN_RETURN_ON_EXCEPTION(isolate, result,
   16660                                isolate->factory()->NewRawOneByteString(length),
   16661                                String);
   16662     return WriteEscapedRegExpSource<uint8_t>(source, result);
   16663   } else {
   16664     Handle<SeqTwoByteString> result;
   16665     ASSIGN_RETURN_ON_EXCEPTION(isolate, result,
   16666                                isolate->factory()->NewRawTwoByteString(length),
   16667                                String);
   16668     return WriteEscapedRegExpSource<uc16>(source, result);
   16669   }
   16670 }
   16671 
   16672 
   16673 // static
   16674 MaybeHandle<JSRegExp> JSRegExp::Initialize(Handle<JSRegExp> regexp,
   16675                                            Handle<String> source,
   16676                                            Handle<String> flags_string) {
   16677   Isolate* isolate = source->GetIsolate();
   16678   bool success = false;
   16679   Flags flags = RegExpFlagsFromString(flags_string, &success);
   16680   if (!success) {
   16681     THROW_NEW_ERROR(
   16682         isolate,
   16683         NewSyntaxError(MessageTemplate::kInvalidRegExpFlags, flags_string),
   16684         JSRegExp);
   16685   }
   16686   return Initialize(regexp, source, flags);
   16687 }
   16688 
   16689 
   16690 // static
   16691 MaybeHandle<JSRegExp> JSRegExp::Initialize(Handle<JSRegExp> regexp,
   16692                                            Handle<String> source, Flags flags) {
   16693   Isolate* isolate = regexp->GetIsolate();
   16694   Factory* factory = isolate->factory();
   16695   // If source is the empty string we set it to "(?:)" instead as
   16696   // suggested by ECMA-262, 5th, section 15.10.4.1.
   16697   if (source->length() == 0) source = factory->query_colon_string();
   16698 
   16699   Handle<String> escaped_source;
   16700   ASSIGN_RETURN_ON_EXCEPTION(isolate, escaped_source,
   16701                              EscapeRegExpSource(isolate, source), JSRegExp);
   16702 
   16703   RETURN_ON_EXCEPTION(isolate, RegExpImpl::Compile(regexp, source, flags),
   16704                       JSRegExp);
   16705 
   16706   regexp->set_source(*escaped_source);
   16707   regexp->set_flags(Smi::FromInt(flags));
   16708 
   16709   Map* map = regexp->map();
   16710   Object* constructor = map->GetConstructor();
   16711   if (constructor->IsJSFunction() &&
   16712       JSFunction::cast(constructor)->initial_map() == map) {
   16713     // If we still have the original map, set in-object properties directly.
   16714     regexp->InObjectPropertyAtPut(JSRegExp::kLastIndexFieldIndex, Smi::kZero,
   16715                                   SKIP_WRITE_BARRIER);
   16716   } else {
   16717     // Map has changed, so use generic, but slower, method.
   16718     RETURN_ON_EXCEPTION(isolate, JSReceiver::SetProperty(
   16719                                      regexp, factory->lastIndex_string(),
   16720                                      Handle<Smi>(Smi::kZero, isolate), STRICT),
   16721                         JSRegExp);
   16722   }
   16723 
   16724   return regexp;
   16725 }
   16726 
   16727 
   16728 // RegExpKey carries the source and flags of a regular expression as key.
   16729 class RegExpKey : public HashTableKey {
   16730  public:
   16731   RegExpKey(Handle<String> string, JSRegExp::Flags flags)
   16732       : string_(string), flags_(Smi::FromInt(flags)) {}
   16733 
   16734   // Rather than storing the key in the hash table, a pointer to the
   16735   // stored value is stored where the key should be.  IsMatch then
   16736   // compares the search key to the found object, rather than comparing
   16737   // a key to a key.
   16738   bool IsMatch(Object* obj) override {
   16739     FixedArray* val = FixedArray::cast(obj);
   16740     return string_->Equals(String::cast(val->get(JSRegExp::kSourceIndex)))
   16741         && (flags_ == val->get(JSRegExp::kFlagsIndex));
   16742   }
   16743 
   16744   uint32_t Hash() override { return RegExpHash(*string_, flags_); }
   16745 
   16746   Handle<Object> AsHandle(Isolate* isolate) override {
   16747     // Plain hash maps, which is where regexp keys are used, don't
   16748     // use this function.
   16749     UNREACHABLE();
   16750     return MaybeHandle<Object>().ToHandleChecked();
   16751   }
   16752 
   16753   uint32_t HashForObject(Object* obj) override {
   16754     FixedArray* val = FixedArray::cast(obj);
   16755     return RegExpHash(String::cast(val->get(JSRegExp::kSourceIndex)),
   16756                       Smi::cast(val->get(JSRegExp::kFlagsIndex)));
   16757   }
   16758 
   16759   static uint32_t RegExpHash(String* string, Smi* flags) {
   16760     return string->Hash() + flags->value();
   16761   }
   16762 
   16763   Handle<String> string_;
   16764   Smi* flags_;
   16765 };
   16766 
   16767 
   16768 Handle<Object> OneByteStringKey::AsHandle(Isolate* isolate) {
   16769   if (hash_field_ == 0) Hash();
   16770   return isolate->factory()->NewOneByteInternalizedString(string_, hash_field_);
   16771 }
   16772 
   16773 
   16774 Handle<Object> TwoByteStringKey::AsHandle(Isolate* isolate) {
   16775   if (hash_field_ == 0) Hash();
   16776   return isolate->factory()->NewTwoByteInternalizedString(string_, hash_field_);
   16777 }
   16778 
   16779 
   16780 Handle<Object> SeqOneByteSubStringKey::AsHandle(Isolate* isolate) {
   16781   if (hash_field_ == 0) Hash();
   16782   return isolate->factory()->NewOneByteInternalizedSubString(
   16783       string_, from_, length_, hash_field_);
   16784 }
   16785 
   16786 
   16787 bool SeqOneByteSubStringKey::IsMatch(Object* string) {
   16788   Vector<const uint8_t> chars(string_->GetChars() + from_, length_);
   16789   return String::cast(string)->IsOneByteEqualTo(chars);
   16790 }
   16791 
   16792 
   16793 // InternalizedStringKey carries a string/internalized-string object as key.
   16794 class InternalizedStringKey : public HashTableKey {
   16795  public:
   16796   explicit InternalizedStringKey(Handle<String> string)
   16797       : string_(String::Flatten(string)) {}
   16798 
   16799   bool IsMatch(Object* string) override {
   16800     return String::cast(string)->Equals(*string_);
   16801   }
   16802 
   16803   uint32_t Hash() override { return string_->Hash(); }
   16804 
   16805   uint32_t HashForObject(Object* other) override {
   16806     return String::cast(other)->Hash();
   16807   }
   16808 
   16809   Handle<Object> AsHandle(Isolate* isolate) override {
   16810     // Internalize the string if possible.
   16811     MaybeHandle<Map> maybe_map =
   16812         isolate->factory()->InternalizedStringMapForString(string_);
   16813     Handle<Map> map;
   16814     if (maybe_map.ToHandle(&map)) {
   16815       string_->set_map_no_write_barrier(*map);
   16816       DCHECK(string_->IsInternalizedString());
   16817       return string_;
   16818     }
   16819     // Otherwise allocate a new internalized string.
   16820     return isolate->factory()->NewInternalizedStringImpl(
   16821         string_, string_->length(), string_->hash_field());
   16822   }
   16823 
   16824   static uint32_t StringHash(Object* obj) {
   16825     return String::cast(obj)->Hash();
   16826   }
   16827 
   16828   Handle<String> string_;
   16829 };
   16830 
   16831 
   16832 template<typename Derived, typename Shape, typename Key>
   16833 void HashTable<Derived, Shape, Key>::IteratePrefix(ObjectVisitor* v) {
   16834   BodyDescriptorBase::IteratePointers(this, 0, kElementsStartOffset, v);
   16835 }
   16836 
   16837 
   16838 template<typename Derived, typename Shape, typename Key>
   16839 void HashTable<Derived, Shape, Key>::IterateElements(ObjectVisitor* v) {
   16840   BodyDescriptorBase::IteratePointers(this, kElementsStartOffset,
   16841                                       kHeaderSize + length() * kPointerSize, v);
   16842 }
   16843 
   16844 
   16845 template<typename Derived, typename Shape, typename Key>
   16846 Handle<Derived> HashTable<Derived, Shape, Key>::New(
   16847     Isolate* isolate,
   16848     int at_least_space_for,
   16849     MinimumCapacity capacity_option,
   16850     PretenureFlag pretenure) {
   16851   DCHECK(0 <= at_least_space_for);
   16852   DCHECK_IMPLIES(capacity_option == USE_CUSTOM_MINIMUM_CAPACITY,
   16853                  base::bits::IsPowerOfTwo32(at_least_space_for));
   16854 
   16855   int capacity = (capacity_option == USE_CUSTOM_MINIMUM_CAPACITY)
   16856                      ? at_least_space_for
   16857                      : ComputeCapacity(at_least_space_for);
   16858   if (capacity > HashTable::kMaxCapacity) {
   16859     v8::internal::Heap::FatalProcessOutOfMemory("invalid table size", true);
   16860   }
   16861 
   16862   Factory* factory = isolate->factory();
   16863   int length = EntryToIndex(capacity);
   16864   Handle<FixedArray> array = factory->NewFixedArray(length, pretenure);
   16865   array->set_map_no_write_barrier(Shape::GetMap(isolate));
   16866   Handle<Derived> table = Handle<Derived>::cast(array);
   16867 
   16868   table->SetNumberOfElements(0);
   16869   table->SetNumberOfDeletedElements(0);
   16870   table->SetCapacity(capacity);
   16871   return table;
   16872 }
   16873 
   16874 
   16875 // Find entry for key otherwise return kNotFound.
   16876 template <typename Derived, typename Shape>
   16877 int NameDictionaryBase<Derived, Shape>::FindEntry(Handle<Name> key) {
   16878   if (!key->IsUniqueName()) {
   16879     return DerivedDictionary::FindEntry(key);
   16880   }
   16881 
   16882   // Optimized for unique names. Knowledge of the key type allows:
   16883   // 1. Move the check if the key is unique out of the loop.
   16884   // 2. Avoid comparing hash codes in unique-to-unique comparison.
   16885   // 3. Detect a case when a dictionary key is not unique but the key is.
   16886   //    In case of positive result the dictionary key may be replaced by the
   16887   //    internalized string with minimal performance penalty. It gives a chance
   16888   //    to perform further lookups in code stubs (and significant performance
   16889   //    boost a certain style of code).
   16890 
   16891   // EnsureCapacity will guarantee the hash table is never full.
   16892   uint32_t capacity = this->Capacity();
   16893   uint32_t entry = Derived::FirstProbe(key->Hash(), capacity);
   16894   uint32_t count = 1;
   16895   Isolate* isolate = this->GetIsolate();
   16896   while (true) {
   16897     Object* element = this->KeyAt(entry);
   16898     if (element->IsUndefined(isolate)) break;  // Empty entry.
   16899     if (*key == element) return entry;
   16900     DCHECK(element->IsTheHole(isolate) || element->IsUniqueName());
   16901     entry = Derived::NextProbe(entry, count++, capacity);
   16902   }
   16903   return Derived::kNotFound;
   16904 }
   16905 
   16906 
   16907 template<typename Derived, typename Shape, typename Key>
   16908 void HashTable<Derived, Shape, Key>::Rehash(
   16909     Handle<Derived> new_table,
   16910     Key key) {
   16911   DCHECK(NumberOfElements() < new_table->Capacity());
   16912 
   16913   DisallowHeapAllocation no_gc;
   16914   WriteBarrierMode mode = new_table->GetWriteBarrierMode(no_gc);
   16915 
   16916   // Copy prefix to new array.
   16917   for (int i = kPrefixStartIndex;
   16918        i < kPrefixStartIndex + Shape::kPrefixSize;
   16919        i++) {
   16920     new_table->set(i, get(i), mode);
   16921   }
   16922 
   16923   // Rehash the elements.
   16924   int capacity = this->Capacity();
   16925   Heap* heap = new_table->GetHeap();
   16926   Object* the_hole = heap->the_hole_value();
   16927   Object* undefined = heap->undefined_value();
   16928   for (int i = 0; i < capacity; i++) {
   16929     uint32_t from_index = EntryToIndex(i);
   16930     Object* k = this->get(from_index);
   16931     if (k != the_hole && k != undefined) {
   16932       uint32_t hash = this->HashForObject(key, k);
   16933       uint32_t insertion_index =
   16934           EntryToIndex(new_table->FindInsertionEntry(hash));
   16935       for (int j = 0; j < Shape::kEntrySize; j++) {
   16936         new_table->set(insertion_index + j, get(from_index + j), mode);
   16937       }
   16938     }
   16939   }
   16940   new_table->SetNumberOfElements(NumberOfElements());
   16941   new_table->SetNumberOfDeletedElements(0);
   16942 }
   16943 
   16944 
   16945 template<typename Derived, typename Shape, typename Key>
   16946 uint32_t HashTable<Derived, Shape, Key>::EntryForProbe(
   16947     Key key,
   16948     Object* k,
   16949     int probe,
   16950     uint32_t expected) {
   16951   uint32_t hash = this->HashForObject(key, k);
   16952   uint32_t capacity = this->Capacity();
   16953   uint32_t entry = FirstProbe(hash, capacity);
   16954   for (int i = 1; i < probe; i++) {
   16955     if (entry == expected) return expected;
   16956     entry = NextProbe(entry, i, capacity);
   16957   }
   16958   return entry;
   16959 }
   16960 
   16961 
   16962 template<typename Derived, typename Shape, typename Key>
   16963 void HashTable<Derived, Shape, Key>::Swap(uint32_t entry1,
   16964                                           uint32_t entry2,
   16965                                           WriteBarrierMode mode) {
   16966   int index1 = EntryToIndex(entry1);
   16967   int index2 = EntryToIndex(entry2);
   16968   Object* temp[Shape::kEntrySize];
   16969   for (int j = 0; j < Shape::kEntrySize; j++) {
   16970     temp[j] = get(index1 + j);
   16971   }
   16972   for (int j = 0; j < Shape::kEntrySize; j++) {
   16973     set(index1 + j, get(index2 + j), mode);
   16974   }
   16975   for (int j = 0; j < Shape::kEntrySize; j++) {
   16976     set(index2 + j, temp[j], mode);
   16977   }
   16978 }
   16979 
   16980 
   16981 template<typename Derived, typename Shape, typename Key>
   16982 void HashTable<Derived, Shape, Key>::Rehash(Key key) {
   16983   DisallowHeapAllocation no_gc;
   16984   WriteBarrierMode mode = GetWriteBarrierMode(no_gc);
   16985   Isolate* isolate = GetIsolate();
   16986   uint32_t capacity = Capacity();
   16987   bool done = false;
   16988   for (int probe = 1; !done; probe++) {
   16989     // All elements at entries given by one of the first _probe_ probes
   16990     // are placed correctly. Other elements might need to be moved.
   16991     done = true;
   16992     for (uint32_t current = 0; current < capacity; current++) {
   16993       Object* current_key = KeyAt(current);
   16994       if (IsKey(isolate, current_key)) {
   16995         uint32_t target = EntryForProbe(key, current_key, probe, current);
   16996         if (current == target) continue;
   16997         Object* target_key = KeyAt(target);
   16998         if (!IsKey(target_key) ||
   16999             EntryForProbe(key, target_key, probe, target) != target) {
   17000           // Put the current element into the correct position.
   17001           Swap(current, target, mode);
   17002           // The other element will be processed on the next iteration.
   17003           current--;
   17004         } else {
   17005           // The place for the current element is occupied. Leave the element
   17006           // for the next probe.
   17007           done = false;
   17008         }
   17009       }
   17010     }
   17011   }
   17012   // Wipe deleted entries.
   17013   Object* the_hole = isolate->heap()->the_hole_value();
   17014   Object* undefined = isolate->heap()->undefined_value();
   17015   for (uint32_t current = 0; current < capacity; current++) {
   17016     if (KeyAt(current) == the_hole) {
   17017       set(EntryToIndex(current) + Derived::kEntryKeyIndex, undefined);
   17018     }
   17019   }
   17020   SetNumberOfDeletedElements(0);
   17021 }
   17022 
   17023 
   17024 template<typename Derived, typename Shape, typename Key>
   17025 Handle<Derived> HashTable<Derived, Shape, Key>::EnsureCapacity(
   17026     Handle<Derived> table,
   17027     int n,
   17028     Key key,
   17029     PretenureFlag pretenure) {
   17030   Isolate* isolate = table->GetIsolate();
   17031   int capacity = table->Capacity();
   17032   int nof = table->NumberOfElements() + n;
   17033 
   17034   if (table->HasSufficientCapacityToAdd(n)) return table;
   17035 
   17036   const int kMinCapacityForPretenure = 256;
   17037   bool should_pretenure = pretenure == TENURED ||
   17038       ((capacity > kMinCapacityForPretenure) &&
   17039           !isolate->heap()->InNewSpace(*table));
   17040   Handle<Derived> new_table = HashTable::New(
   17041       isolate,
   17042       nof * 2,
   17043       USE_DEFAULT_MINIMUM_CAPACITY,
   17044       should_pretenure ? TENURED : NOT_TENURED);
   17045 
   17046   table->Rehash(new_table, key);
   17047   return new_table;
   17048 }
   17049 
   17050 template <typename Derived, typename Shape, typename Key>
   17051 bool HashTable<Derived, Shape, Key>::HasSufficientCapacityToAdd(
   17052     int number_of_additional_elements) {
   17053   int capacity = Capacity();
   17054   int nof = NumberOfElements() + number_of_additional_elements;
   17055   int nod = NumberOfDeletedElements();
   17056   // Return true if:
   17057   //   50% is still free after adding number_of_additional_elements elements and
   17058   //   at most 50% of the free elements are deleted elements.
   17059   if ((nof < capacity) && ((nod <= (capacity - nof) >> 1))) {
   17060     int needed_free = nof >> 1;
   17061     if (nof + needed_free <= capacity) return true;
   17062   }
   17063   return false;
   17064 }
   17065 
   17066 
   17067 template<typename Derived, typename Shape, typename Key>
   17068 Handle<Derived> HashTable<Derived, Shape, Key>::Shrink(Handle<Derived> table,
   17069                                                        Key key) {
   17070   int capacity = table->Capacity();
   17071   int nof = table->NumberOfElements();
   17072 
   17073   // Shrink to fit the number of elements if only a quarter of the
   17074   // capacity is filled with elements.
   17075   if (nof > (capacity >> 2)) return table;
   17076   // Allocate a new dictionary with room for at least the current
   17077   // number of elements. The allocation method will make sure that
   17078   // there is extra room in the dictionary for additions. Don't go
   17079   // lower than room for 16 elements.
   17080   int at_least_room_for = nof;
   17081   if (at_least_room_for < 16) return table;
   17082 
   17083   Isolate* isolate = table->GetIsolate();
   17084   const int kMinCapacityForPretenure = 256;
   17085   bool pretenure =
   17086       (at_least_room_for > kMinCapacityForPretenure) &&
   17087       !isolate->heap()->InNewSpace(*table);
   17088   Handle<Derived> new_table = HashTable::New(
   17089       isolate,
   17090       at_least_room_for,
   17091       USE_DEFAULT_MINIMUM_CAPACITY,
   17092       pretenure ? TENURED : NOT_TENURED);
   17093 
   17094   table->Rehash(new_table, key);
   17095   return new_table;
   17096 }
   17097 
   17098 
   17099 template<typename Derived, typename Shape, typename Key>
   17100 uint32_t HashTable<Derived, Shape, Key>::FindInsertionEntry(uint32_t hash) {
   17101   uint32_t capacity = Capacity();
   17102   uint32_t entry = FirstProbe(hash, capacity);
   17103   uint32_t count = 1;
   17104   // EnsureCapacity will guarantee the hash table is never full.
   17105   Isolate* isolate = GetIsolate();
   17106   while (true) {
   17107     Object* element = KeyAt(entry);
   17108     if (!IsKey(isolate, element)) break;
   17109     entry = NextProbe(entry, count++, capacity);
   17110   }
   17111   return entry;
   17112 }
   17113 
   17114 
   17115 // Force instantiation of template instances class.
   17116 // Please note this list is compiler dependent.
   17117 
   17118 template class HashTable<StringTable, StringTableShape, HashTableKey*>;
   17119 
   17120 template class HashTable<CompilationCacheTable,
   17121                          CompilationCacheShape,
   17122                          HashTableKey*>;
   17123 
   17124 template class HashTable<ObjectHashTable,
   17125                          ObjectHashTableShape,
   17126                          Handle<Object> >;
   17127 
   17128 template class HashTable<WeakHashTable, WeakHashTableShape<2>, Handle<Object> >;
   17129 
   17130 template class Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >;
   17131 
   17132 template class Dictionary<GlobalDictionary, GlobalDictionaryShape,
   17133                           Handle<Name> >;
   17134 
   17135 template class Dictionary<SeededNumberDictionary,
   17136                           SeededNumberDictionaryShape,
   17137                           uint32_t>;
   17138 
   17139 template class Dictionary<UnseededNumberDictionary,
   17140                           UnseededNumberDictionaryShape,
   17141                           uint32_t>;
   17142 
   17143 template Handle<SeededNumberDictionary>
   17144 Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::New(
   17145     Isolate*, int at_least_space_for, PretenureFlag pretenure,
   17146     MinimumCapacity capacity_option);
   17147 
   17148 template Handle<UnseededNumberDictionary>
   17149 Dictionary<UnseededNumberDictionary, UnseededNumberDictionaryShape,
   17150            uint32_t>::New(Isolate*, int at_least_space_for,
   17151                           PretenureFlag pretenure,
   17152                           MinimumCapacity capacity_option);
   17153 
   17154 template Handle<NameDictionary>
   17155 Dictionary<NameDictionary, NameDictionaryShape, Handle<Name>>::New(
   17156     Isolate*, int n, PretenureFlag pretenure, MinimumCapacity capacity_option);
   17157 
   17158 template Handle<GlobalDictionary>
   17159 Dictionary<GlobalDictionary, GlobalDictionaryShape, Handle<Name>>::New(
   17160     Isolate*, int n, PretenureFlag pretenure, MinimumCapacity capacity_option);
   17161 
   17162 template Handle<SeededNumberDictionary>
   17163 Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
   17164     AtPut(Handle<SeededNumberDictionary>, uint32_t, Handle<Object>);
   17165 
   17166 template Handle<UnseededNumberDictionary>
   17167 Dictionary<UnseededNumberDictionary, UnseededNumberDictionaryShape, uint32_t>::
   17168     AtPut(Handle<UnseededNumberDictionary>, uint32_t, Handle<Object>);
   17169 
   17170 template Object*
   17171 Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
   17172     SlowReverseLookup(Object* value);
   17173 
   17174 template Object*
   17175 Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::
   17176     SlowReverseLookup(Object* value);
   17177 
   17178 template Handle<Object>
   17179 Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::DeleteProperty(
   17180     Handle<NameDictionary>, int);
   17181 
   17182 template Handle<Object>
   17183 Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape,
   17184            uint32_t>::DeleteProperty(Handle<SeededNumberDictionary>, int);
   17185 
   17186 template Handle<Object>
   17187 Dictionary<UnseededNumberDictionary, UnseededNumberDictionaryShape,
   17188            uint32_t>::DeleteProperty(Handle<UnseededNumberDictionary>, int);
   17189 
   17190 template Handle<NameDictionary>
   17191 HashTable<NameDictionary, NameDictionaryShape, Handle<Name> >::
   17192     New(Isolate*, int, MinimumCapacity, PretenureFlag);
   17193 
   17194 template Handle<ObjectHashSet> HashTable<ObjectHashSet, ObjectHashSetShape,
   17195                                          Handle<Object>>::New(Isolate*, int n,
   17196                                                               MinimumCapacity,
   17197                                                               PretenureFlag);
   17198 
   17199 template Handle<NameDictionary>
   17200 HashTable<NameDictionary, NameDictionaryShape, Handle<Name> >::
   17201     Shrink(Handle<NameDictionary>, Handle<Name>);
   17202 
   17203 template Handle<SeededNumberDictionary>
   17204 HashTable<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
   17205     Shrink(Handle<SeededNumberDictionary>, uint32_t);
   17206 
   17207 template Handle<UnseededNumberDictionary>
   17208     HashTable<UnseededNumberDictionary, UnseededNumberDictionaryShape,
   17209               uint32_t>::Shrink(Handle<UnseededNumberDictionary>, uint32_t);
   17210 
   17211 template Handle<NameDictionary>
   17212 Dictionary<NameDictionary, NameDictionaryShape, Handle<Name>>::Add(
   17213     Handle<NameDictionary>, Handle<Name>, Handle<Object>, PropertyDetails,
   17214     int*);
   17215 
   17216 template Handle<GlobalDictionary>
   17217 Dictionary<GlobalDictionary, GlobalDictionaryShape, Handle<Name>>::Add(
   17218     Handle<GlobalDictionary>, Handle<Name>, Handle<Object>, PropertyDetails,
   17219     int*);
   17220 
   17221 template Handle<FixedArray> Dictionary<
   17222     NameDictionary, NameDictionaryShape,
   17223     Handle<Name> >::BuildIterationIndicesArray(Handle<NameDictionary>);
   17224 
   17225 template Handle<FixedArray> Dictionary<
   17226     NameDictionary, NameDictionaryShape,
   17227     Handle<Name> >::GenerateNewEnumerationIndices(Handle<NameDictionary>);
   17228 
   17229 template Handle<SeededNumberDictionary>
   17230 Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::Add(
   17231     Handle<SeededNumberDictionary>, uint32_t, Handle<Object>, PropertyDetails,
   17232     int*);
   17233 
   17234 template Handle<UnseededNumberDictionary>
   17235 Dictionary<UnseededNumberDictionary, UnseededNumberDictionaryShape,
   17236            uint32_t>::Add(Handle<UnseededNumberDictionary>, uint32_t,
   17237                           Handle<Object>, PropertyDetails, int*);
   17238 
   17239 template Handle<SeededNumberDictionary>
   17240 Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
   17241     EnsureCapacity(Handle<SeededNumberDictionary>, int, uint32_t);
   17242 
   17243 template Handle<UnseededNumberDictionary>
   17244 Dictionary<UnseededNumberDictionary, UnseededNumberDictionaryShape, uint32_t>::
   17245     EnsureCapacity(Handle<UnseededNumberDictionary>, int, uint32_t);
   17246 
   17247 template void Dictionary<NameDictionary, NameDictionaryShape,
   17248                          Handle<Name> >::SetRequiresCopyOnCapacityChange();
   17249 
   17250 template Handle<NameDictionary>
   17251 Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::
   17252     EnsureCapacity(Handle<NameDictionary>, int, Handle<Name>);
   17253 
   17254 template int HashTable<SeededNumberDictionary, SeededNumberDictionaryShape,
   17255                        uint32_t>::FindEntry(uint32_t);
   17256 
   17257 template int NameDictionaryBase<NameDictionary, NameDictionaryShape>::FindEntry(
   17258     Handle<Name>);
   17259 
   17260 template int Dictionary<GlobalDictionary, GlobalDictionaryShape, Handle<Name>>::
   17261     NumberOfElementsFilterAttributes(PropertyFilter filter);
   17262 
   17263 template int Dictionary<NameDictionary, NameDictionaryShape, Handle<Name>>::
   17264     NumberOfElementsFilterAttributes(PropertyFilter filter);
   17265 
   17266 template void
   17267 Dictionary<GlobalDictionary, GlobalDictionaryShape, Handle<Name>>::
   17268     CopyEnumKeysTo(Handle<Dictionary<GlobalDictionary, GlobalDictionaryShape,
   17269                                      Handle<Name>>>
   17270                        dictionary,
   17271                    Handle<FixedArray> storage, KeyCollectionMode mode,
   17272                    KeyAccumulator* accumulator);
   17273 
   17274 template void
   17275 Dictionary<NameDictionary, NameDictionaryShape, Handle<Name>>::CopyEnumKeysTo(
   17276     Handle<Dictionary<NameDictionary, NameDictionaryShape, Handle<Name>>>
   17277         dictionary,
   17278     Handle<FixedArray> storage, KeyCollectionMode mode,
   17279     KeyAccumulator* accumulator);
   17280 
   17281 template void
   17282 Dictionary<GlobalDictionary, GlobalDictionaryShape, Handle<Name>>::
   17283     CollectKeysTo(Handle<Dictionary<GlobalDictionary, GlobalDictionaryShape,
   17284                                     Handle<Name>>>
   17285                       dictionary,
   17286                   KeyAccumulator* keys);
   17287 
   17288 template void
   17289 Dictionary<NameDictionary, NameDictionaryShape, Handle<Name>>::CollectKeysTo(
   17290     Handle<Dictionary<NameDictionary, NameDictionaryShape, Handle<Name>>>
   17291         dictionary,
   17292     KeyAccumulator* keys);
   17293 
   17294 Handle<Object> JSObject::PrepareSlowElementsForSort(
   17295     Handle<JSObject> object, uint32_t limit) {
   17296   DCHECK(object->HasDictionaryElements());
   17297   Isolate* isolate = object->GetIsolate();
   17298   // Must stay in dictionary mode, either because of requires_slow_elements,
   17299   // or because we are not going to sort (and therefore compact) all of the
   17300   // elements.
   17301   Handle<SeededNumberDictionary> dict(object->element_dictionary(), isolate);
   17302   Handle<SeededNumberDictionary> new_dict =
   17303       SeededNumberDictionary::New(isolate, dict->NumberOfElements());
   17304 
   17305   uint32_t pos = 0;
   17306   uint32_t undefs = 0;
   17307   int capacity = dict->Capacity();
   17308   Handle<Smi> bailout(Smi::FromInt(-1), isolate);
   17309   // Entry to the new dictionary does not cause it to grow, as we have
   17310   // allocated one that is large enough for all entries.
   17311   DisallowHeapAllocation no_gc;
   17312   for (int i = 0; i < capacity; i++) {
   17313     Object* k = dict->KeyAt(i);
   17314     if (!dict->IsKey(isolate, k)) continue;
   17315 
   17316     DCHECK(k->IsNumber());
   17317     DCHECK(!k->IsSmi() || Smi::cast(k)->value() >= 0);
   17318     DCHECK(!k->IsHeapNumber() || HeapNumber::cast(k)->value() >= 0);
   17319     DCHECK(!k->IsHeapNumber() || HeapNumber::cast(k)->value() <= kMaxUInt32);
   17320 
   17321     HandleScope scope(isolate);
   17322     Handle<Object> value(dict->ValueAt(i), isolate);
   17323     PropertyDetails details = dict->DetailsAt(i);
   17324     if (details.type() == ACCESSOR_CONSTANT || details.IsReadOnly()) {
   17325       // Bail out and do the sorting of undefineds and array holes in JS.
   17326       // Also bail out if the element is not supposed to be moved.
   17327       return bailout;
   17328     }
   17329 
   17330     uint32_t key = NumberToUint32(k);
   17331     if (key < limit) {
   17332       if (value->IsUndefined(isolate)) {
   17333         undefs++;
   17334       } else if (pos > static_cast<uint32_t>(Smi::kMaxValue)) {
   17335         // Adding an entry with the key beyond smi-range requires
   17336         // allocation. Bailout.
   17337         return bailout;
   17338       } else {
   17339         Handle<Object> result = SeededNumberDictionary::AddNumberEntry(
   17340             new_dict, pos, value, details, object->map()->is_prototype_map());
   17341         DCHECK(result.is_identical_to(new_dict));
   17342         USE(result);
   17343         pos++;
   17344       }
   17345     } else if (key > static_cast<uint32_t>(Smi::kMaxValue)) {
   17346       // Adding an entry with the key beyond smi-range requires
   17347       // allocation. Bailout.
   17348       return bailout;
   17349     } else {
   17350       Handle<Object> result = SeededNumberDictionary::AddNumberEntry(
   17351           new_dict, key, value, details, object->map()->is_prototype_map());
   17352       DCHECK(result.is_identical_to(new_dict));
   17353       USE(result);
   17354     }
   17355   }
   17356 
   17357   uint32_t result = pos;
   17358   PropertyDetails no_details = PropertyDetails::Empty();
   17359   while (undefs > 0) {
   17360     if (pos > static_cast<uint32_t>(Smi::kMaxValue)) {
   17361       // Adding an entry with the key beyond smi-range requires
   17362       // allocation. Bailout.
   17363       return bailout;
   17364     }
   17365     HandleScope scope(isolate);
   17366     Handle<Object> result = SeededNumberDictionary::AddNumberEntry(
   17367         new_dict, pos, isolate->factory()->undefined_value(), no_details,
   17368         object->map()->is_prototype_map());
   17369     DCHECK(result.is_identical_to(new_dict));
   17370     USE(result);
   17371     pos++;
   17372     undefs--;
   17373   }
   17374 
   17375   object->set_elements(*new_dict);
   17376 
   17377   AllowHeapAllocation allocate_return_value;
   17378   return isolate->factory()->NewNumberFromUint(result);
   17379 }
   17380 
   17381 
   17382 // Collects all defined (non-hole) and non-undefined (array) elements at
   17383 // the start of the elements array.
   17384 // If the object is in dictionary mode, it is converted to fast elements
   17385 // mode.
   17386 Handle<Object> JSObject::PrepareElementsForSort(Handle<JSObject> object,
   17387                                                 uint32_t limit) {
   17388   Isolate* isolate = object->GetIsolate();
   17389   if (object->HasSloppyArgumentsElements()) {
   17390     return handle(Smi::FromInt(-1), isolate);
   17391   }
   17392 
   17393   if (object->HasStringWrapperElements()) {
   17394     int len = String::cast(Handle<JSValue>::cast(object)->value())->length();
   17395     return handle(Smi::FromInt(len), isolate);
   17396   }
   17397 
   17398   if (object->HasDictionaryElements()) {
   17399     // Convert to fast elements containing only the existing properties.
   17400     // Ordering is irrelevant, since we are going to sort anyway.
   17401     Handle<SeededNumberDictionary> dict(object->element_dictionary());
   17402     if (object->IsJSArray() || dict->requires_slow_elements() ||
   17403         dict->max_number_key() >= limit) {
   17404       return JSObject::PrepareSlowElementsForSort(object, limit);
   17405     }
   17406     // Convert to fast elements.
   17407 
   17408     Handle<Map> new_map =
   17409         JSObject::GetElementsTransitionMap(object, FAST_HOLEY_ELEMENTS);
   17410 
   17411     PretenureFlag tenure = isolate->heap()->InNewSpace(*object) ?
   17412         NOT_TENURED: TENURED;
   17413     Handle<FixedArray> fast_elements =
   17414         isolate->factory()->NewFixedArray(dict->NumberOfElements(), tenure);
   17415     dict->CopyValuesTo(*fast_elements);
   17416     JSObject::ValidateElements(object);
   17417 
   17418     JSObject::SetMapAndElements(object, new_map, fast_elements);
   17419   } else if (object->HasFixedTypedArrayElements()) {
   17420     // Typed arrays cannot have holes or undefined elements.
   17421     return handle(Smi::FromInt(
   17422         FixedArrayBase::cast(object->elements())->length()), isolate);
   17423   } else if (!object->HasFastDoubleElements()) {
   17424     EnsureWritableFastElements(object);
   17425   }
   17426   DCHECK(object->HasFastSmiOrObjectElements() ||
   17427          object->HasFastDoubleElements());
   17428 
   17429   // Collect holes at the end, undefined before that and the rest at the
   17430   // start, and return the number of non-hole, non-undefined values.
   17431 
   17432   Handle<FixedArrayBase> elements_base(object->elements());
   17433   uint32_t elements_length = static_cast<uint32_t>(elements_base->length());
   17434   if (limit > elements_length) {
   17435     limit = elements_length;
   17436   }
   17437   if (limit == 0) {
   17438     return handle(Smi::kZero, isolate);
   17439   }
   17440 
   17441   uint32_t result = 0;
   17442   if (elements_base->map() == isolate->heap()->fixed_double_array_map()) {
   17443     FixedDoubleArray* elements = FixedDoubleArray::cast(*elements_base);
   17444     // Split elements into defined and the_hole, in that order.
   17445     unsigned int holes = limit;
   17446     // Assume most arrays contain no holes and undefined values, so minimize the
   17447     // number of stores of non-undefined, non-the-hole values.
   17448     for (unsigned int i = 0; i < holes; i++) {
   17449       if (elements->is_the_hole(i)) {
   17450         holes--;
   17451       } else {
   17452         continue;
   17453       }
   17454       // Position i needs to be filled.
   17455       while (holes > i) {
   17456         if (elements->is_the_hole(holes)) {
   17457           holes--;
   17458         } else {
   17459           elements->set(i, elements->get_scalar(holes));
   17460           break;
   17461         }
   17462       }
   17463     }
   17464     result = holes;
   17465     while (holes < limit) {
   17466       elements->set_the_hole(holes);
   17467       holes++;
   17468     }
   17469   } else {
   17470     FixedArray* elements = FixedArray::cast(*elements_base);
   17471     DisallowHeapAllocation no_gc;
   17472 
   17473     // Split elements into defined, undefined and the_hole, in that order.  Only
   17474     // count locations for undefined and the hole, and fill them afterwards.
   17475     WriteBarrierMode write_barrier = elements->GetWriteBarrierMode(no_gc);
   17476     unsigned int undefs = limit;
   17477     unsigned int holes = limit;
   17478     // Assume most arrays contain no holes and undefined values, so minimize the
   17479     // number of stores of non-undefined, non-the-hole values.
   17480     for (unsigned int i = 0; i < undefs; i++) {
   17481       Object* current = elements->get(i);
   17482       if (current->IsTheHole(isolate)) {
   17483         holes--;
   17484         undefs--;
   17485       } else if (current->IsUndefined(isolate)) {
   17486         undefs--;
   17487       } else {
   17488         continue;
   17489       }
   17490       // Position i needs to be filled.
   17491       while (undefs > i) {
   17492         current = elements->get(undefs);
   17493         if (current->IsTheHole(isolate)) {
   17494           holes--;
   17495           undefs--;
   17496         } else if (current->IsUndefined(isolate)) {
   17497           undefs--;
   17498         } else {
   17499           elements->set(i, current, write_barrier);
   17500           break;
   17501         }
   17502       }
   17503     }
   17504     result = undefs;
   17505     while (undefs < holes) {
   17506       elements->set_undefined(undefs);
   17507       undefs++;
   17508     }
   17509     while (holes < limit) {
   17510       elements->set_the_hole(holes);
   17511       holes++;
   17512     }
   17513   }
   17514 
   17515   return isolate->factory()->NewNumberFromUint(result);
   17516 }
   17517 
   17518 
   17519 ExternalArrayType JSTypedArray::type() {
   17520   switch (elements()->map()->instance_type()) {
   17521 #define INSTANCE_TYPE_TO_ARRAY_TYPE(Type, type, TYPE, ctype, size)            \
   17522     case FIXED_##TYPE##_ARRAY_TYPE:                                           \
   17523       return kExternal##Type##Array;
   17524 
   17525     TYPED_ARRAYS(INSTANCE_TYPE_TO_ARRAY_TYPE)
   17526 #undef INSTANCE_TYPE_TO_ARRAY_TYPE
   17527 
   17528     default:
   17529       UNREACHABLE();
   17530       return static_cast<ExternalArrayType>(-1);
   17531   }
   17532 }
   17533 
   17534 
   17535 size_t JSTypedArray::element_size() {
   17536   switch (elements()->map()->instance_type()) {
   17537 #define INSTANCE_TYPE_TO_ELEMENT_SIZE(Type, type, TYPE, ctype, size) \
   17538   case FIXED_##TYPE##_ARRAY_TYPE:                                    \
   17539     return size;
   17540 
   17541     TYPED_ARRAYS(INSTANCE_TYPE_TO_ELEMENT_SIZE)
   17542 #undef INSTANCE_TYPE_TO_ELEMENT_SIZE
   17543 
   17544     default:
   17545       UNREACHABLE();
   17546       return 0;
   17547   }
   17548 }
   17549 
   17550 
   17551 void JSGlobalObject::InvalidatePropertyCell(Handle<JSGlobalObject> global,
   17552                                             Handle<Name> name) {
   17553   DCHECK(!global->HasFastProperties());
   17554   auto dictionary = handle(global->global_dictionary());
   17555   int entry = dictionary->FindEntry(name);
   17556   if (entry == GlobalDictionary::kNotFound) return;
   17557   PropertyCell::InvalidateEntry(dictionary, entry);
   17558 }
   17559 
   17560 Handle<PropertyCell> JSGlobalObject::EnsureEmptyPropertyCell(
   17561     Handle<JSGlobalObject> global, Handle<Name> name,
   17562     PropertyCellType cell_type, int* entry_out) {
   17563   Isolate* isolate = global->GetIsolate();
   17564   DCHECK(!global->HasFastProperties());
   17565   Handle<GlobalDictionary> dictionary(global->global_dictionary(), isolate);
   17566   int entry = dictionary->FindEntry(name);
   17567   Handle<PropertyCell> cell;
   17568   if (entry != GlobalDictionary::kNotFound) {
   17569     if (entry_out) *entry_out = entry;
   17570     // This call should be idempotent.
   17571     DCHECK(dictionary->ValueAt(entry)->IsPropertyCell());
   17572     cell = handle(PropertyCell::cast(dictionary->ValueAt(entry)));
   17573     PropertyCellType original_cell_type = cell->property_details().cell_type();
   17574     DCHECK(original_cell_type == PropertyCellType::kInvalidated ||
   17575            original_cell_type == PropertyCellType::kUninitialized);
   17576     DCHECK(cell->value()->IsTheHole(isolate));
   17577     if (original_cell_type == PropertyCellType::kInvalidated) {
   17578       cell = PropertyCell::InvalidateEntry(dictionary, entry);
   17579     }
   17580     PropertyDetails details(NONE, DATA, 0, cell_type);
   17581     cell->set_property_details(details);
   17582     return cell;
   17583   }
   17584   cell = isolate->factory()->NewPropertyCell();
   17585   PropertyDetails details(NONE, DATA, 0, cell_type);
   17586   dictionary =
   17587       GlobalDictionary::Add(dictionary, name, cell, details, entry_out);
   17588   // {*entry_out} is initialized inside GlobalDictionary::Add().
   17589   global->set_properties(*dictionary);
   17590   return cell;
   17591 }
   17592 
   17593 
   17594 // This class is used for looking up two character strings in the string table.
   17595 // If we don't have a hit we don't want to waste much time so we unroll the
   17596 // string hash calculation loop here for speed.  Doesn't work if the two
   17597 // characters form a decimal integer, since such strings have a different hash
   17598 // algorithm.
   17599 class TwoCharHashTableKey : public HashTableKey {
   17600  public:
   17601   TwoCharHashTableKey(uint16_t c1, uint16_t c2, uint32_t seed)
   17602     : c1_(c1), c2_(c2) {
   17603     // Char 1.
   17604     uint32_t hash = seed;
   17605     hash += c1;
   17606     hash += hash << 10;
   17607     hash ^= hash >> 6;
   17608     // Char 2.
   17609     hash += c2;
   17610     hash += hash << 10;
   17611     hash ^= hash >> 6;
   17612     // GetHash.
   17613     hash += hash << 3;
   17614     hash ^= hash >> 11;
   17615     hash += hash << 15;
   17616     if ((hash & String::kHashBitMask) == 0) hash = StringHasher::kZeroHash;
   17617     hash_ = hash;
   17618 #ifdef DEBUG
   17619     // If this assert fails then we failed to reproduce the two-character
   17620     // version of the string hashing algorithm above.  One reason could be
   17621     // that we were passed two digits as characters, since the hash
   17622     // algorithm is different in that case.
   17623     uint16_t chars[2] = {c1, c2};
   17624     uint32_t check_hash = StringHasher::HashSequentialString(chars, 2, seed);
   17625     hash = (hash << String::kHashShift) | String::kIsNotArrayIndexMask;
   17626     DCHECK_EQ(static_cast<int32_t>(hash), static_cast<int32_t>(check_hash));
   17627 #endif
   17628   }
   17629 
   17630   bool IsMatch(Object* o) override {
   17631     if (!o->IsString()) return false;
   17632     String* other = String::cast(o);
   17633     if (other->length() != 2) return false;
   17634     if (other->Get(0) != c1_) return false;
   17635     return other->Get(1) == c2_;
   17636   }
   17637 
   17638   uint32_t Hash() override { return hash_; }
   17639   uint32_t HashForObject(Object* key) override {
   17640     if (!key->IsString()) return 0;
   17641     return String::cast(key)->Hash();
   17642   }
   17643 
   17644   Handle<Object> AsHandle(Isolate* isolate) override {
   17645     // The TwoCharHashTableKey is only used for looking in the string
   17646     // table, not for adding to it.
   17647     UNREACHABLE();
   17648     return MaybeHandle<Object>().ToHandleChecked();
   17649   }
   17650 
   17651  private:
   17652   uint16_t c1_;
   17653   uint16_t c2_;
   17654   uint32_t hash_;
   17655 };
   17656 
   17657 
   17658 MaybeHandle<String> StringTable::InternalizeStringIfExists(
   17659     Isolate* isolate,
   17660     Handle<String> string) {
   17661   if (string->IsInternalizedString()) {
   17662     return string;
   17663   }
   17664   return LookupStringIfExists(isolate, string);
   17665 }
   17666 
   17667 
   17668 MaybeHandle<String> StringTable::LookupStringIfExists(
   17669     Isolate* isolate,
   17670     Handle<String> string) {
   17671   Handle<StringTable> string_table = isolate->factory()->string_table();
   17672   InternalizedStringKey key(string);
   17673   int entry = string_table->FindEntry(&key);
   17674   if (entry == kNotFound) {
   17675     return MaybeHandle<String>();
   17676   } else {
   17677     Handle<String> result(String::cast(string_table->KeyAt(entry)), isolate);
   17678     DCHECK(StringShape(*result).IsInternalized());
   17679     return result;
   17680   }
   17681 }
   17682 
   17683 
   17684 MaybeHandle<String> StringTable::LookupTwoCharsStringIfExists(
   17685     Isolate* isolate,
   17686     uint16_t c1,
   17687     uint16_t c2) {
   17688   Handle<StringTable> string_table = isolate->factory()->string_table();
   17689   TwoCharHashTableKey key(c1, c2, isolate->heap()->HashSeed());
   17690   int entry = string_table->FindEntry(&key);
   17691   if (entry == kNotFound) {
   17692     return MaybeHandle<String>();
   17693   } else {
   17694     Handle<String> result(String::cast(string_table->KeyAt(entry)), isolate);
   17695     DCHECK(StringShape(*result).IsInternalized());
   17696     return result;
   17697   }
   17698 }
   17699 
   17700 
   17701 void StringTable::EnsureCapacityForDeserialization(Isolate* isolate,
   17702                                                    int expected) {
   17703   Handle<StringTable> table = isolate->factory()->string_table();
   17704   // We need a key instance for the virtual hash function.
   17705   InternalizedStringKey dummy_key(isolate->factory()->empty_string());
   17706   table = StringTable::EnsureCapacity(table, expected, &dummy_key);
   17707   isolate->heap()->SetRootStringTable(*table);
   17708 }
   17709 
   17710 
   17711 Handle<String> StringTable::LookupString(Isolate* isolate,
   17712                                          Handle<String> string) {
   17713   if (string->IsConsString() && string->IsFlat()) {
   17714     string = String::Flatten(string);
   17715     if (string->IsInternalizedString()) return string;
   17716   }
   17717 
   17718   InternalizedStringKey key(string);
   17719   Handle<String> result = LookupKey(isolate, &key);
   17720 
   17721   if (string->IsConsString()) {
   17722     Handle<ConsString> cons = Handle<ConsString>::cast(string);
   17723     cons->set_first(*result);
   17724     cons->set_second(isolate->heap()->empty_string());
   17725   } else if (string->IsSlicedString()) {
   17726     STATIC_ASSERT(ConsString::kSize == SlicedString::kSize);
   17727     DisallowHeapAllocation no_gc;
   17728     bool one_byte = result->IsOneByteRepresentation();
   17729     Handle<Map> map = one_byte ? isolate->factory()->cons_one_byte_string_map()
   17730                                : isolate->factory()->cons_string_map();
   17731     string->set_map(*map);
   17732     Handle<ConsString> cons = Handle<ConsString>::cast(string);
   17733     cons->set_first(*result);
   17734     cons->set_second(isolate->heap()->empty_string());
   17735   }
   17736   return result;
   17737 }
   17738 
   17739 
   17740 Handle<String> StringTable::LookupKey(Isolate* isolate, HashTableKey* key) {
   17741   Handle<StringTable> table = isolate->factory()->string_table();
   17742   int entry = table->FindEntry(key);
   17743 
   17744   // String already in table.
   17745   if (entry != kNotFound) {
   17746     return handle(String::cast(table->KeyAt(entry)), isolate);
   17747   }
   17748 
   17749   // Adding new string. Grow table if needed.
   17750   table = StringTable::EnsureCapacity(table, 1, key);
   17751 
   17752   // Create string object.
   17753   Handle<Object> string = key->AsHandle(isolate);
   17754   // There must be no attempts to internalize strings that could throw
   17755   // InvalidStringLength error.
   17756   CHECK(!string.is_null());
   17757 
   17758   // Add the new string and return it along with the string table.
   17759   entry = table->FindInsertionEntry(key->Hash());
   17760   table->set(EntryToIndex(entry), *string);
   17761   table->ElementAdded();
   17762 
   17763   isolate->heap()->SetRootStringTable(*table);
   17764   return Handle<String>::cast(string);
   17765 }
   17766 
   17767 
   17768 String* StringTable::LookupKeyIfExists(Isolate* isolate, HashTableKey* key) {
   17769   Handle<StringTable> table = isolate->factory()->string_table();
   17770   int entry = table->FindEntry(key);
   17771   if (entry != kNotFound) return String::cast(table->KeyAt(entry));
   17772   return NULL;
   17773 }
   17774 
   17775 Handle<StringSet> StringSet::New(Isolate* isolate) {
   17776   return HashTable::New(isolate, 0);
   17777 }
   17778 
   17779 Handle<StringSet> StringSet::Add(Handle<StringSet> stringset,
   17780                                  Handle<String> name) {
   17781   if (!stringset->Has(name)) {
   17782     stringset = EnsureCapacity(stringset, 1, *name);
   17783     uint32_t hash = StringSetShape::Hash(*name);
   17784     int entry = stringset->FindInsertionEntry(hash);
   17785     stringset->set(EntryToIndex(entry), *name);
   17786     stringset->ElementAdded();
   17787   }
   17788   return stringset;
   17789 }
   17790 
   17791 bool StringSet::Has(Handle<String> name) {
   17792   return FindEntry(*name) != kNotFound;
   17793 }
   17794 
   17795 Handle<ObjectHashSet> ObjectHashSet::Add(Handle<ObjectHashSet> set,
   17796                                          Handle<Object> key) {
   17797   Isolate* isolate = set->GetIsolate();
   17798   int32_t hash = Object::GetOrCreateHash(isolate, key)->value();
   17799 
   17800   if (!set->Has(isolate, key, hash)) {
   17801     set = EnsureCapacity(set, 1, key);
   17802     int entry = set->FindInsertionEntry(hash);
   17803     set->set(EntryToIndex(entry), *key);
   17804     set->ElementAdded();
   17805   }
   17806   return set;
   17807 }
   17808 
   17809 Handle<Object> CompilationCacheTable::Lookup(Handle<String> src,
   17810                                              Handle<Context> context,
   17811                                              LanguageMode language_mode) {
   17812   Isolate* isolate = GetIsolate();
   17813   Handle<SharedFunctionInfo> shared(context->closure()->shared());
   17814   StringSharedKey key(src, shared, language_mode, kNoSourcePosition);
   17815   int entry = FindEntry(&key);
   17816   if (entry == kNotFound) return isolate->factory()->undefined_value();
   17817   int index = EntryToIndex(entry);
   17818   if (!get(index)->IsFixedArray()) return isolate->factory()->undefined_value();
   17819   return Handle<Object>(get(index + 1), isolate);
   17820 }
   17821 
   17822 
   17823 Handle<Object> CompilationCacheTable::LookupEval(
   17824     Handle<String> src, Handle<SharedFunctionInfo> outer_info,
   17825     LanguageMode language_mode, int scope_position) {
   17826   Isolate* isolate = GetIsolate();
   17827   // Cache key is the tuple (source, outer shared function info, scope position)
   17828   // to unambiguously identify the context chain the cached eval code assumes.
   17829   StringSharedKey key(src, outer_info, language_mode, scope_position);
   17830   int entry = FindEntry(&key);
   17831   if (entry == kNotFound) return isolate->factory()->undefined_value();
   17832   int index = EntryToIndex(entry);
   17833   if (!get(index)->IsFixedArray()) return isolate->factory()->undefined_value();
   17834   return Handle<Object>(get(EntryToIndex(entry) + 1), isolate);
   17835 }
   17836 
   17837 
   17838 Handle<Object> CompilationCacheTable::LookupRegExp(Handle<String> src,
   17839                                                    JSRegExp::Flags flags) {
   17840   Isolate* isolate = GetIsolate();
   17841   DisallowHeapAllocation no_allocation;
   17842   RegExpKey key(src, flags);
   17843   int entry = FindEntry(&key);
   17844   if (entry == kNotFound) return isolate->factory()->undefined_value();
   17845   return Handle<Object>(get(EntryToIndex(entry) + 1), isolate);
   17846 }
   17847 
   17848 
   17849 Handle<CompilationCacheTable> CompilationCacheTable::Put(
   17850     Handle<CompilationCacheTable> cache, Handle<String> src,
   17851     Handle<Context> context, LanguageMode language_mode, Handle<Object> value) {
   17852   Isolate* isolate = cache->GetIsolate();
   17853   Handle<SharedFunctionInfo> shared(context->closure()->shared());
   17854   StringSharedKey key(src, shared, language_mode, kNoSourcePosition);
   17855   Handle<Object> k = key.AsHandle(isolate);
   17856   cache = EnsureCapacity(cache, 1, &key);
   17857   int entry = cache->FindInsertionEntry(key.Hash());
   17858   cache->set(EntryToIndex(entry), *k);
   17859   cache->set(EntryToIndex(entry) + 1, *value);
   17860   cache->ElementAdded();
   17861   return cache;
   17862 }
   17863 
   17864 
   17865 Handle<CompilationCacheTable> CompilationCacheTable::PutEval(
   17866     Handle<CompilationCacheTable> cache, Handle<String> src,
   17867     Handle<SharedFunctionInfo> outer_info, Handle<SharedFunctionInfo> value,
   17868     int scope_position) {
   17869   Isolate* isolate = cache->GetIsolate();
   17870   StringSharedKey key(src, outer_info, value->language_mode(), scope_position);
   17871   {
   17872     Handle<Object> k = key.AsHandle(isolate);
   17873     DisallowHeapAllocation no_allocation_scope;
   17874     int entry = cache->FindEntry(&key);
   17875     if (entry != kNotFound) {
   17876       cache->set(EntryToIndex(entry), *k);
   17877       cache->set(EntryToIndex(entry) + 1, *value);
   17878       return cache;
   17879     }
   17880   }
   17881 
   17882   cache = EnsureCapacity(cache, 1, &key);
   17883   int entry = cache->FindInsertionEntry(key.Hash());
   17884   Handle<Object> k =
   17885       isolate->factory()->NewNumber(static_cast<double>(key.Hash()));
   17886   cache->set(EntryToIndex(entry), *k);
   17887   cache->set(EntryToIndex(entry) + 1, Smi::FromInt(kHashGenerations));
   17888   cache->ElementAdded();
   17889   return cache;
   17890 }
   17891 
   17892 
   17893 Handle<CompilationCacheTable> CompilationCacheTable::PutRegExp(
   17894       Handle<CompilationCacheTable> cache, Handle<String> src,
   17895       JSRegExp::Flags flags, Handle<FixedArray> value) {
   17896   RegExpKey key(src, flags);
   17897   cache = EnsureCapacity(cache, 1, &key);
   17898   int entry = cache->FindInsertionEntry(key.Hash());
   17899   // We store the value in the key slot, and compare the search key
   17900   // to the stored value with a custon IsMatch function during lookups.
   17901   cache->set(EntryToIndex(entry), *value);
   17902   cache->set(EntryToIndex(entry) + 1, *value);
   17903   cache->ElementAdded();
   17904   return cache;
   17905 }
   17906 
   17907 
   17908 void CompilationCacheTable::Age() {
   17909   DisallowHeapAllocation no_allocation;
   17910   Object* the_hole_value = GetHeap()->the_hole_value();
   17911   for (int entry = 0, size = Capacity(); entry < size; entry++) {
   17912     int entry_index = EntryToIndex(entry);
   17913     int value_index = entry_index + 1;
   17914 
   17915     if (get(entry_index)->IsNumber()) {
   17916       Smi* count = Smi::cast(get(value_index));
   17917       count = Smi::FromInt(count->value() - 1);
   17918       if (count->value() == 0) {
   17919         NoWriteBarrierSet(this, entry_index, the_hole_value);
   17920         NoWriteBarrierSet(this, value_index, the_hole_value);
   17921         ElementRemoved();
   17922       } else {
   17923         NoWriteBarrierSet(this, value_index, count);
   17924       }
   17925     } else if (get(entry_index)->IsFixedArray()) {
   17926       SharedFunctionInfo* info = SharedFunctionInfo::cast(get(value_index));
   17927       if (info->code()->kind() != Code::FUNCTION || info->code()->IsOld()) {
   17928         NoWriteBarrierSet(this, entry_index, the_hole_value);
   17929         NoWriteBarrierSet(this, value_index, the_hole_value);
   17930         ElementRemoved();
   17931       }
   17932     }
   17933   }
   17934 }
   17935 
   17936 
   17937 void CompilationCacheTable::Remove(Object* value) {
   17938   DisallowHeapAllocation no_allocation;
   17939   Object* the_hole_value = GetHeap()->the_hole_value();
   17940   for (int entry = 0, size = Capacity(); entry < size; entry++) {
   17941     int entry_index = EntryToIndex(entry);
   17942     int value_index = entry_index + 1;
   17943     if (get(value_index) == value) {
   17944       NoWriteBarrierSet(this, entry_index, the_hole_value);
   17945       NoWriteBarrierSet(this, value_index, the_hole_value);
   17946       ElementRemoved();
   17947     }
   17948   }
   17949   return;
   17950 }
   17951 
   17952 template <typename Derived, typename Shape, typename Key>
   17953 Handle<Derived> Dictionary<Derived, Shape, Key>::New(
   17954     Isolate* isolate, int at_least_space_for, PretenureFlag pretenure,
   17955     MinimumCapacity capacity_option) {
   17956   DCHECK(0 <= at_least_space_for);
   17957   Handle<Derived> dict = DerivedHashTable::New(isolate, at_least_space_for,
   17958                                                capacity_option, pretenure);
   17959 
   17960   // Initialize the next enumeration index.
   17961   dict->SetNextEnumerationIndex(PropertyDetails::kInitialIndex);
   17962   return dict;
   17963 }
   17964 
   17965 
   17966 template <typename Derived, typename Shape, typename Key>
   17967 Handle<FixedArray> Dictionary<Derived, Shape, Key>::BuildIterationIndicesArray(
   17968     Handle<Derived> dictionary) {
   17969   Isolate* isolate = dictionary->GetIsolate();
   17970   Factory* factory = isolate->factory();
   17971   int length = dictionary->NumberOfElements();
   17972 
   17973   Handle<FixedArray> iteration_order = factory->NewFixedArray(length);
   17974   Handle<FixedArray> enumeration_order = factory->NewFixedArray(length);
   17975 
   17976   // Fill both the iteration order array and the enumeration order array
   17977   // with property details.
   17978   int capacity = dictionary->Capacity();
   17979   int pos = 0;
   17980   for (int i = 0; i < capacity; i++) {
   17981     if (dictionary->IsKey(isolate, dictionary->KeyAt(i))) {
   17982       int index = dictionary->DetailsAt(i).dictionary_index();
   17983       iteration_order->set(pos, Smi::FromInt(i));
   17984       enumeration_order->set(pos, Smi::FromInt(index));
   17985       pos++;
   17986     }
   17987   }
   17988   DCHECK(pos == length);
   17989 
   17990   // Sort the arrays wrt. enumeration order.
   17991   iteration_order->SortPairs(*enumeration_order, enumeration_order->length());
   17992   return iteration_order;
   17993 }
   17994 
   17995 
   17996 template <typename Derived, typename Shape, typename Key>
   17997 Handle<FixedArray>
   17998 Dictionary<Derived, Shape, Key>::GenerateNewEnumerationIndices(
   17999     Handle<Derived> dictionary) {
   18000   int length = dictionary->NumberOfElements();
   18001 
   18002   Handle<FixedArray> iteration_order = BuildIterationIndicesArray(dictionary);
   18003   DCHECK(iteration_order->length() == length);
   18004 
   18005   // Iterate over the dictionary using the enumeration order and update
   18006   // the dictionary with new enumeration indices.
   18007   for (int i = 0; i < length; i++) {
   18008     int index = Smi::cast(iteration_order->get(i))->value();
   18009     DCHECK(dictionary->IsKey(dictionary->KeyAt(index)));
   18010 
   18011     int enum_index = PropertyDetails::kInitialIndex + i;
   18012 
   18013     PropertyDetails details = dictionary->DetailsAt(index);
   18014     PropertyDetails new_details = details.set_index(enum_index);
   18015     dictionary->DetailsAtPut(index, new_details);
   18016   }
   18017 
   18018   // Set the next enumeration index.
   18019   dictionary->SetNextEnumerationIndex(PropertyDetails::kInitialIndex+length);
   18020   return iteration_order;
   18021 }
   18022 
   18023 
   18024 template <typename Derived, typename Shape, typename Key>
   18025 void Dictionary<Derived, Shape, Key>::SetRequiresCopyOnCapacityChange() {
   18026   DCHECK_EQ(0, DerivedHashTable::NumberOfElements());
   18027   DCHECK_EQ(0, DerivedHashTable::NumberOfDeletedElements());
   18028   // Make sure that HashTable::EnsureCapacity will create a copy.
   18029   DerivedHashTable::SetNumberOfDeletedElements(DerivedHashTable::Capacity());
   18030   DCHECK(!DerivedHashTable::HasSufficientCapacityToAdd(1));
   18031 }
   18032 
   18033 
   18034 template <typename Derived, typename Shape, typename Key>
   18035 Handle<Derived> Dictionary<Derived, Shape, Key>::EnsureCapacity(
   18036     Handle<Derived> dictionary, int n, Key key) {
   18037   // Check whether there are enough enumeration indices to add n elements.
   18038   if (Shape::kIsEnumerable &&
   18039       !PropertyDetails::IsValidIndex(dictionary->NextEnumerationIndex() + n)) {
   18040     // If not, we generate new indices for the properties.
   18041     GenerateNewEnumerationIndices(dictionary);
   18042   }
   18043   return DerivedHashTable::EnsureCapacity(dictionary, n, key);
   18044 }
   18045 
   18046 
   18047 template <typename Derived, typename Shape, typename Key>
   18048 Handle<Object> Dictionary<Derived, Shape, Key>::DeleteProperty(
   18049     Handle<Derived> dictionary, int entry) {
   18050   Factory* factory = dictionary->GetIsolate()->factory();
   18051   PropertyDetails details = dictionary->DetailsAt(entry);
   18052   if (!details.IsConfigurable()) return factory->false_value();
   18053 
   18054   dictionary->SetEntry(
   18055       entry, factory->the_hole_value(), factory->the_hole_value());
   18056   dictionary->ElementRemoved();
   18057   return factory->true_value();
   18058 }
   18059 
   18060 
   18061 template<typename Derived, typename Shape, typename Key>
   18062 Handle<Derived> Dictionary<Derived, Shape, Key>::AtPut(
   18063     Handle<Derived> dictionary, Key key, Handle<Object> value) {
   18064   int entry = dictionary->FindEntry(key);
   18065 
   18066   // If the entry is present set the value;
   18067   if (entry != Dictionary::kNotFound) {
   18068     dictionary->ValueAtPut(entry, *value);
   18069     return dictionary;
   18070   }
   18071 
   18072   // Check whether the dictionary should be extended.
   18073   dictionary = EnsureCapacity(dictionary, 1, key);
   18074 #ifdef DEBUG
   18075   USE(Shape::AsHandle(dictionary->GetIsolate(), key));
   18076 #endif
   18077   PropertyDetails details = PropertyDetails::Empty();
   18078 
   18079   AddEntry(dictionary, key, value, details, dictionary->Hash(key));
   18080   return dictionary;
   18081 }
   18082 
   18083 template <typename Derived, typename Shape, typename Key>
   18084 Handle<Derived> Dictionary<Derived, Shape, Key>::Add(Handle<Derived> dictionary,
   18085                                                      Key key,
   18086                                                      Handle<Object> value,
   18087                                                      PropertyDetails details,
   18088                                                      int* entry_out) {
   18089   // Valdate key is absent.
   18090   SLOW_DCHECK((dictionary->FindEntry(key) == Dictionary::kNotFound));
   18091   // Check whether the dictionary should be extended.
   18092   dictionary = EnsureCapacity(dictionary, 1, key);
   18093 
   18094   int entry = AddEntry(dictionary, key, value, details, dictionary->Hash(key));
   18095   if (entry_out) *entry_out = entry;
   18096   return dictionary;
   18097 }
   18098 
   18099 // Add a key, value pair to the dictionary. Returns entry value.
   18100 template <typename Derived, typename Shape, typename Key>
   18101 int Dictionary<Derived, Shape, Key>::AddEntry(Handle<Derived> dictionary,
   18102                                               Key key, Handle<Object> value,
   18103                                               PropertyDetails details,
   18104                                               uint32_t hash) {
   18105   // Compute the key object.
   18106   Handle<Object> k = Shape::AsHandle(dictionary->GetIsolate(), key);
   18107 
   18108   uint32_t entry = dictionary->FindInsertionEntry(hash);
   18109   // Insert element at empty or deleted entry
   18110   if (details.dictionary_index() == 0 && Shape::kIsEnumerable) {
   18111     // Assign an enumeration index to the property and update
   18112     // SetNextEnumerationIndex.
   18113     int index = dictionary->NextEnumerationIndex();
   18114     details = details.set_index(index);
   18115     dictionary->SetNextEnumerationIndex(index + 1);
   18116   }
   18117   dictionary->SetEntry(entry, k, value, details);
   18118   DCHECK((dictionary->KeyAt(entry)->IsNumber() ||
   18119           dictionary->KeyAt(entry)->IsName()));
   18120   dictionary->ElementAdded();
   18121   return entry;
   18122 }
   18123 
   18124 bool SeededNumberDictionary::HasComplexElements() {
   18125   if (!requires_slow_elements()) return false;
   18126   Isolate* isolate = this->GetIsolate();
   18127   int capacity = this->Capacity();
   18128   for (int i = 0; i < capacity; i++) {
   18129     Object* k = this->KeyAt(i);
   18130     if (!this->IsKey(isolate, k)) continue;
   18131     DCHECK(!IsDeleted(i));
   18132     PropertyDetails details = this->DetailsAt(i);
   18133     if (details.type() == ACCESSOR_CONSTANT) return true;
   18134     PropertyAttributes attr = details.attributes();
   18135     if (attr & ALL_ATTRIBUTES_MASK) return true;
   18136   }
   18137   return false;
   18138 }
   18139 
   18140 void SeededNumberDictionary::UpdateMaxNumberKey(uint32_t key,
   18141                                                 bool used_as_prototype) {
   18142   DisallowHeapAllocation no_allocation;
   18143   // If the dictionary requires slow elements an element has already
   18144   // been added at a high index.
   18145   if (requires_slow_elements()) return;
   18146   // Check if this index is high enough that we should require slow
   18147   // elements.
   18148   if (key > kRequiresSlowElementsLimit) {
   18149     if (used_as_prototype) {
   18150       // TODO(verwaest): Remove this hack.
   18151       TypeFeedbackVector::ClearAllKeyedStoreICs(GetIsolate());
   18152     }
   18153     set_requires_slow_elements();
   18154     return;
   18155   }
   18156   // Update max key value.
   18157   Object* max_index_object = get(kMaxNumberKeyIndex);
   18158   if (!max_index_object->IsSmi() || max_number_key() < key) {
   18159     FixedArray::set(kMaxNumberKeyIndex,
   18160                     Smi::FromInt(key << kRequiresSlowElementsTagSize));
   18161   }
   18162 }
   18163 
   18164 
   18165 Handle<SeededNumberDictionary> SeededNumberDictionary::AddNumberEntry(
   18166     Handle<SeededNumberDictionary> dictionary, uint32_t key,
   18167     Handle<Object> value, PropertyDetails details, bool used_as_prototype) {
   18168   dictionary->UpdateMaxNumberKey(key, used_as_prototype);
   18169   SLOW_DCHECK(dictionary->FindEntry(key) == kNotFound);
   18170   return Add(dictionary, key, value, details);
   18171 }
   18172 
   18173 
   18174 Handle<UnseededNumberDictionary> UnseededNumberDictionary::AddNumberEntry(
   18175     Handle<UnseededNumberDictionary> dictionary,
   18176     uint32_t key,
   18177     Handle<Object> value) {
   18178   SLOW_DCHECK(dictionary->FindEntry(key) == kNotFound);
   18179   return Add(dictionary, key, value, PropertyDetails::Empty());
   18180 }
   18181 
   18182 Handle<UnseededNumberDictionary> UnseededNumberDictionary::DeleteKey(
   18183     Handle<UnseededNumberDictionary> dictionary, uint32_t key) {
   18184   int entry = dictionary->FindEntry(key);
   18185   if (entry == kNotFound) return dictionary;
   18186 
   18187   Factory* factory = dictionary->GetIsolate()->factory();
   18188   dictionary->SetEntry(entry, factory->the_hole_value(),
   18189                        factory->the_hole_value());
   18190   dictionary->ElementRemoved();
   18191   return dictionary->Shrink(dictionary, key);
   18192 }
   18193 
   18194 Handle<SeededNumberDictionary> SeededNumberDictionary::AtNumberPut(
   18195     Handle<SeededNumberDictionary> dictionary, uint32_t key,
   18196     Handle<Object> value, bool used_as_prototype) {
   18197   dictionary->UpdateMaxNumberKey(key, used_as_prototype);
   18198   return AtPut(dictionary, key, value);
   18199 }
   18200 
   18201 
   18202 Handle<UnseededNumberDictionary> UnseededNumberDictionary::AtNumberPut(
   18203     Handle<UnseededNumberDictionary> dictionary,
   18204     uint32_t key,
   18205     Handle<Object> value) {
   18206   return AtPut(dictionary, key, value);
   18207 }
   18208 
   18209 
   18210 Handle<SeededNumberDictionary> SeededNumberDictionary::Set(
   18211     Handle<SeededNumberDictionary> dictionary, uint32_t key,
   18212     Handle<Object> value, PropertyDetails details, bool used_as_prototype) {
   18213   int entry = dictionary->FindEntry(key);
   18214   if (entry == kNotFound) {
   18215     return AddNumberEntry(dictionary, key, value, details, used_as_prototype);
   18216   }
   18217   // Preserve enumeration index.
   18218   details = details.set_index(dictionary->DetailsAt(entry).dictionary_index());
   18219   Handle<Object> object_key =
   18220       SeededNumberDictionaryShape::AsHandle(dictionary->GetIsolate(), key);
   18221   dictionary->SetEntry(entry, object_key, value, details);
   18222   return dictionary;
   18223 }
   18224 
   18225 
   18226 Handle<UnseededNumberDictionary> UnseededNumberDictionary::Set(
   18227     Handle<UnseededNumberDictionary> dictionary,
   18228     uint32_t key,
   18229     Handle<Object> value) {
   18230   int entry = dictionary->FindEntry(key);
   18231   if (entry == kNotFound) return AddNumberEntry(dictionary, key, value);
   18232   Handle<Object> object_key =
   18233       UnseededNumberDictionaryShape::AsHandle(dictionary->GetIsolate(), key);
   18234   dictionary->SetEntry(entry, object_key, value);
   18235   return dictionary;
   18236 }
   18237 
   18238 
   18239 template <typename Derived, typename Shape, typename Key>
   18240 int Dictionary<Derived, Shape, Key>::NumberOfElementsFilterAttributes(
   18241     PropertyFilter filter) {
   18242   Isolate* isolate = this->GetIsolate();
   18243   int capacity = this->Capacity();
   18244   int result = 0;
   18245   for (int i = 0; i < capacity; i++) {
   18246     Object* k = this->KeyAt(i);
   18247     if (this->IsKey(isolate, k) && !k->FilterKey(filter)) {
   18248       if (this->IsDeleted(i)) continue;
   18249       PropertyDetails details = this->DetailsAt(i);
   18250       PropertyAttributes attr = details.attributes();
   18251       if ((attr & filter) == 0) result++;
   18252     }
   18253   }
   18254   return result;
   18255 }
   18256 
   18257 
   18258 template <typename Dictionary>
   18259 struct EnumIndexComparator {
   18260   explicit EnumIndexComparator(Dictionary* dict) : dict(dict) {}
   18261   bool operator() (Smi* a, Smi* b) {
   18262     PropertyDetails da(dict->DetailsAt(a->value()));
   18263     PropertyDetails db(dict->DetailsAt(b->value()));
   18264     return da.dictionary_index() < db.dictionary_index();
   18265   }
   18266   Dictionary* dict;
   18267 };
   18268 
   18269 template <typename Derived, typename Shape, typename Key>
   18270 void Dictionary<Derived, Shape, Key>::CopyEnumKeysTo(
   18271     Handle<Dictionary<Derived, Shape, Key>> dictionary,
   18272     Handle<FixedArray> storage, KeyCollectionMode mode,
   18273     KeyAccumulator* accumulator) {
   18274   Isolate* isolate = dictionary->GetIsolate();
   18275   int length = storage->length();
   18276   int capacity = dictionary->Capacity();
   18277   int properties = 0;
   18278   for (int i = 0; i < capacity; i++) {
   18279     Object* key = dictionary->KeyAt(i);
   18280     bool is_shadowing_key = false;
   18281     if (!dictionary->IsKey(isolate, key)) continue;
   18282     if (key->IsSymbol()) continue;
   18283     PropertyDetails details = dictionary->DetailsAt(i);
   18284     if (details.IsDontEnum()) {
   18285       if (mode == KeyCollectionMode::kIncludePrototypes) {
   18286         is_shadowing_key = true;
   18287       } else {
   18288         continue;
   18289       }
   18290     }
   18291     if (dictionary->IsDeleted(i)) continue;
   18292     if (is_shadowing_key) {
   18293       accumulator->AddShadowingKey(key);
   18294       continue;
   18295     } else {
   18296       storage->set(properties, Smi::FromInt(i));
   18297     }
   18298     properties++;
   18299     if (properties == length) break;
   18300   }
   18301 
   18302   CHECK_EQ(length, properties);
   18303   DisallowHeapAllocation no_gc;
   18304   Dictionary<Derived, Shape, Key>* raw_dictionary = *dictionary;
   18305   FixedArray* raw_storage = *storage;
   18306   EnumIndexComparator<Derived> cmp(static_cast<Derived*>(*dictionary));
   18307   Smi** start = reinterpret_cast<Smi**>(storage->GetFirstElementAddress());
   18308   std::sort(start, start + length, cmp);
   18309   for (int i = 0; i < length; i++) {
   18310     int index = Smi::cast(raw_storage->get(i))->value();
   18311     raw_storage->set(i, raw_dictionary->KeyAt(index));
   18312   }
   18313 }
   18314 
   18315 template <typename Derived, typename Shape, typename Key>
   18316 void Dictionary<Derived, Shape, Key>::CollectKeysTo(
   18317     Handle<Dictionary<Derived, Shape, Key>> dictionary, KeyAccumulator* keys) {
   18318   Isolate* isolate = keys->isolate();
   18319   int capacity = dictionary->Capacity();
   18320   Handle<FixedArray> array =
   18321       isolate->factory()->NewFixedArray(dictionary->NumberOfElements());
   18322   int array_size = 0;
   18323   PropertyFilter filter = keys->filter();
   18324   {
   18325     DisallowHeapAllocation no_gc;
   18326     Dictionary<Derived, Shape, Key>* raw_dict = *dictionary;
   18327     for (int i = 0; i < capacity; i++) {
   18328       Object* k = raw_dict->KeyAt(i);
   18329       if (!raw_dict->IsKey(isolate, k) || k->FilterKey(filter)) continue;
   18330       if (raw_dict->IsDeleted(i)) continue;
   18331       PropertyDetails details = raw_dict->DetailsAt(i);
   18332       if ((details.attributes() & filter) != 0) {
   18333         keys->AddShadowingKey(k);
   18334         continue;
   18335       }
   18336       if (filter & ONLY_ALL_CAN_READ) {
   18337         if (details.kind() != kAccessor) continue;
   18338         Object* accessors = raw_dict->ValueAt(i);
   18339         if (accessors->IsPropertyCell()) {
   18340           accessors = PropertyCell::cast(accessors)->value();
   18341         }
   18342         if (!accessors->IsAccessorInfo()) continue;
   18343         if (!AccessorInfo::cast(accessors)->all_can_read()) continue;
   18344       }
   18345       array->set(array_size++, Smi::FromInt(i));
   18346     }
   18347 
   18348     EnumIndexComparator<Derived> cmp(static_cast<Derived*>(raw_dict));
   18349     Smi** start = reinterpret_cast<Smi**>(array->GetFirstElementAddress());
   18350     std::sort(start, start + array_size, cmp);
   18351   }
   18352 
   18353   bool has_seen_symbol = false;
   18354   for (int i = 0; i < array_size; i++) {
   18355     int index = Smi::cast(array->get(i))->value();
   18356     Object* key = dictionary->KeyAt(index);
   18357     if (key->IsSymbol()) {
   18358       has_seen_symbol = true;
   18359       continue;
   18360     }
   18361     keys->AddKey(key, DO_NOT_CONVERT);
   18362   }
   18363   if (has_seen_symbol) {
   18364     for (int i = 0; i < array_size; i++) {
   18365       int index = Smi::cast(array->get(i))->value();
   18366       Object* key = dictionary->KeyAt(index);
   18367       if (!key->IsSymbol()) continue;
   18368       keys->AddKey(key, DO_NOT_CONVERT);
   18369     }
   18370   }
   18371 }
   18372 
   18373 
   18374 // Backwards lookup (slow).
   18375 template<typename Derived, typename Shape, typename Key>
   18376 Object* Dictionary<Derived, Shape, Key>::SlowReverseLookup(Object* value) {
   18377   Isolate* isolate = this->GetIsolate();
   18378   int capacity = this->Capacity();
   18379   for (int i = 0; i < capacity; i++) {
   18380     Object* k = this->KeyAt(i);
   18381     if (!this->IsKey(isolate, k)) continue;
   18382     Object* e = this->ValueAt(i);
   18383     // TODO(dcarney): this should be templatized.
   18384     if (e->IsPropertyCell()) {
   18385       e = PropertyCell::cast(e)->value();
   18386     }
   18387     if (e == value) return k;
   18388   }
   18389   return isolate->heap()->undefined_value();
   18390 }
   18391 
   18392 
   18393 Object* ObjectHashTable::Lookup(Isolate* isolate, Handle<Object> key,
   18394                                 int32_t hash) {
   18395   DisallowHeapAllocation no_gc;
   18396   DCHECK(IsKey(isolate, *key));
   18397 
   18398   int entry = FindEntry(isolate, key, hash);
   18399   if (entry == kNotFound) return isolate->heap()->the_hole_value();
   18400   return get(EntryToIndex(entry) + 1);
   18401 }
   18402 
   18403 
   18404 Object* ObjectHashTable::Lookup(Handle<Object> key) {
   18405   DisallowHeapAllocation no_gc;
   18406 
   18407   Isolate* isolate = GetIsolate();
   18408   DCHECK(IsKey(isolate, *key));
   18409 
   18410   // If the object does not have an identity hash, it was never used as a key.
   18411   Object* hash = key->GetHash();
   18412   if (hash->IsUndefined(isolate)) {
   18413     return isolate->heap()->the_hole_value();
   18414   }
   18415   return Lookup(isolate, key, Smi::cast(hash)->value());
   18416 }
   18417 
   18418 Object* ObjectHashTable::ValueAt(int entry) {
   18419   return get(EntryToValueIndex(entry));
   18420 }
   18421 
   18422 Object* ObjectHashTable::Lookup(Handle<Object> key, int32_t hash) {
   18423   return Lookup(GetIsolate(), key, hash);
   18424 }
   18425 
   18426 
   18427 Handle<ObjectHashTable> ObjectHashTable::Put(Handle<ObjectHashTable> table,
   18428                                              Handle<Object> key,
   18429                                              Handle<Object> value) {
   18430   Isolate* isolate = table->GetIsolate();
   18431   DCHECK(table->IsKey(isolate, *key));
   18432   DCHECK(!value->IsTheHole(isolate));
   18433 
   18434   // Make sure the key object has an identity hash code.
   18435   int32_t hash = Object::GetOrCreateHash(isolate, key)->value();
   18436 
   18437   return Put(table, key, value, hash);
   18438 }
   18439 
   18440 
   18441 Handle<ObjectHashTable> ObjectHashTable::Put(Handle<ObjectHashTable> table,
   18442                                              Handle<Object> key,
   18443                                              Handle<Object> value,
   18444                                              int32_t hash) {
   18445   Isolate* isolate = table->GetIsolate();
   18446   DCHECK(table->IsKey(isolate, *key));
   18447   DCHECK(!value->IsTheHole(isolate));
   18448 
   18449   int entry = table->FindEntry(isolate, key, hash);
   18450 
   18451   // Key is already in table, just overwrite value.
   18452   if (entry != kNotFound) {
   18453     table->set(EntryToIndex(entry) + 1, *value);
   18454     return table;
   18455   }
   18456 
   18457   // Rehash if more than 33% of the entries are deleted entries.
   18458   // TODO(jochen): Consider to shrink the fixed array in place.
   18459   if ((table->NumberOfDeletedElements() << 1) > table->NumberOfElements()) {
   18460     table->Rehash(isolate->factory()->undefined_value());
   18461   }
   18462   // If we're out of luck, we didn't get a GC recently, and so rehashing
   18463   // isn't enough to avoid a crash.
   18464   if (!table->HasSufficientCapacityToAdd(1)) {
   18465     int nof = table->NumberOfElements() + 1;
   18466     int capacity = ObjectHashTable::ComputeCapacity(nof * 2);
   18467     if (capacity > ObjectHashTable::kMaxCapacity) {
   18468       for (size_t i = 0; i < 2; ++i) {
   18469         isolate->heap()->CollectAllGarbage(
   18470             Heap::kFinalizeIncrementalMarkingMask,
   18471             GarbageCollectionReason::kFullHashtable);
   18472       }
   18473       table->Rehash(isolate->factory()->undefined_value());
   18474     }
   18475   }
   18476 
   18477   // Check whether the hash table should be extended.
   18478   table = EnsureCapacity(table, 1, key);
   18479   table->AddEntry(table->FindInsertionEntry(hash), *key, *value);
   18480   return table;
   18481 }
   18482 
   18483 
   18484 Handle<ObjectHashTable> ObjectHashTable::Remove(Handle<ObjectHashTable> table,
   18485                                                 Handle<Object> key,
   18486                                                 bool* was_present) {
   18487   DCHECK(table->IsKey(table->GetIsolate(), *key));
   18488 
   18489   Object* hash = key->GetHash();
   18490   if (hash->IsUndefined(table->GetIsolate())) {
   18491     *was_present = false;
   18492     return table;
   18493   }
   18494 
   18495   return Remove(table, key, was_present, Smi::cast(hash)->value());
   18496 }
   18497 
   18498 
   18499 Handle<ObjectHashTable> ObjectHashTable::Remove(Handle<ObjectHashTable> table,
   18500                                                 Handle<Object> key,
   18501                                                 bool* was_present,
   18502                                                 int32_t hash) {
   18503   Isolate* isolate = table->GetIsolate();
   18504   DCHECK(table->IsKey(isolate, *key));
   18505 
   18506   int entry = table->FindEntry(isolate, key, hash);
   18507   if (entry == kNotFound) {
   18508     *was_present = false;
   18509     return table;
   18510   }
   18511 
   18512   *was_present = true;
   18513   table->RemoveEntry(entry);
   18514   return Shrink(table, key);
   18515 }
   18516 
   18517 
   18518 void ObjectHashTable::AddEntry(int entry, Object* key, Object* value) {
   18519   set(EntryToIndex(entry), key);
   18520   set(EntryToIndex(entry) + 1, value);
   18521   ElementAdded();
   18522 }
   18523 
   18524 
   18525 void ObjectHashTable::RemoveEntry(int entry) {
   18526   set_the_hole(EntryToIndex(entry));
   18527   set_the_hole(EntryToIndex(entry) + 1);
   18528   ElementRemoved();
   18529 }
   18530 
   18531 
   18532 Object* WeakHashTable::Lookup(Handle<HeapObject> key) {
   18533   DisallowHeapAllocation no_gc;
   18534   Isolate* isolate = GetIsolate();
   18535   DCHECK(IsKey(isolate, *key));
   18536   int entry = FindEntry(key);
   18537   if (entry == kNotFound) return isolate->heap()->the_hole_value();
   18538   return get(EntryToValueIndex(entry));
   18539 }
   18540 
   18541 
   18542 Handle<WeakHashTable> WeakHashTable::Put(Handle<WeakHashTable> table,
   18543                                          Handle<HeapObject> key,
   18544                                          Handle<HeapObject> value) {
   18545   Isolate* isolate = key->GetIsolate();
   18546   DCHECK(table->IsKey(isolate, *key));
   18547   int entry = table->FindEntry(key);
   18548   // Key is already in table, just overwrite value.
   18549   if (entry != kNotFound) {
   18550     table->set(EntryToValueIndex(entry), *value);
   18551     return table;
   18552   }
   18553 
   18554   Handle<WeakCell> key_cell = isolate->factory()->NewWeakCell(key);
   18555 
   18556   // Check whether the hash table should be extended.
   18557   table = EnsureCapacity(table, 1, key, TENURED);
   18558 
   18559   table->AddEntry(table->FindInsertionEntry(table->Hash(key)), key_cell, value);
   18560   return table;
   18561 }
   18562 
   18563 
   18564 void WeakHashTable::AddEntry(int entry, Handle<WeakCell> key_cell,
   18565                              Handle<HeapObject> value) {
   18566   DisallowHeapAllocation no_allocation;
   18567   set(EntryToIndex(entry), *key_cell);
   18568   set(EntryToValueIndex(entry), *value);
   18569   ElementAdded();
   18570 }
   18571 
   18572 
   18573 template<class Derived, class Iterator, int entrysize>
   18574 Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Allocate(
   18575     Isolate* isolate, int capacity, PretenureFlag pretenure) {
   18576   // Capacity must be a power of two, since we depend on being able
   18577   // to divide and multiple by 2 (kLoadFactor) to derive capacity
   18578   // from number of buckets. If we decide to change kLoadFactor
   18579   // to something other than 2, capacity should be stored as another
   18580   // field of this object.
   18581   capacity = base::bits::RoundUpToPowerOfTwo32(Max(kMinCapacity, capacity));
   18582   if (capacity > kMaxCapacity) {
   18583     v8::internal::Heap::FatalProcessOutOfMemory("invalid table size", true);
   18584   }
   18585   int num_buckets = capacity / kLoadFactor;
   18586   Handle<FixedArray> backing_store = isolate->factory()->NewFixedArray(
   18587       kHashTableStartIndex + num_buckets + (capacity * kEntrySize), pretenure);
   18588   backing_store->set_map_no_write_barrier(
   18589       isolate->heap()->ordered_hash_table_map());
   18590   Handle<Derived> table = Handle<Derived>::cast(backing_store);
   18591   for (int i = 0; i < num_buckets; ++i) {
   18592     table->set(kHashTableStartIndex + i, Smi::FromInt(kNotFound));
   18593   }
   18594   table->SetNumberOfBuckets(num_buckets);
   18595   table->SetNumberOfElements(0);
   18596   table->SetNumberOfDeletedElements(0);
   18597   return table;
   18598 }
   18599 
   18600 
   18601 template<class Derived, class Iterator, int entrysize>
   18602 Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::EnsureGrowable(
   18603     Handle<Derived> table) {
   18604   DCHECK(!table->IsObsolete());
   18605 
   18606   int nof = table->NumberOfElements();
   18607   int nod = table->NumberOfDeletedElements();
   18608   int capacity = table->Capacity();
   18609   if ((nof + nod) < capacity) return table;
   18610   // Don't need to grow if we can simply clear out deleted entries instead.
   18611   // Note that we can't compact in place, though, so we always allocate
   18612   // a new table.
   18613   return Rehash(table, (nod < (capacity >> 1)) ? capacity << 1 : capacity);
   18614 }
   18615 
   18616 
   18617 template<class Derived, class Iterator, int entrysize>
   18618 Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Shrink(
   18619     Handle<Derived> table) {
   18620   DCHECK(!table->IsObsolete());
   18621 
   18622   int nof = table->NumberOfElements();
   18623   int capacity = table->Capacity();
   18624   if (nof >= (capacity >> 2)) return table;
   18625   return Rehash(table, capacity / 2);
   18626 }
   18627 
   18628 
   18629 template<class Derived, class Iterator, int entrysize>
   18630 Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Clear(
   18631     Handle<Derived> table) {
   18632   DCHECK(!table->IsObsolete());
   18633 
   18634   Handle<Derived> new_table =
   18635       Allocate(table->GetIsolate(),
   18636                kMinCapacity,
   18637                table->GetHeap()->InNewSpace(*table) ? NOT_TENURED : TENURED);
   18638 
   18639   table->SetNextTable(*new_table);
   18640   table->SetNumberOfDeletedElements(kClearedTableSentinel);
   18641 
   18642   return new_table;
   18643 }
   18644 
   18645 template <class Derived, class Iterator, int entrysize>
   18646 bool OrderedHashTable<Derived, Iterator, entrysize>::HasKey(
   18647     Handle<Derived> table, Handle<Object> key) {
   18648   DisallowHeapAllocation no_gc;
   18649   Isolate* isolate = table->GetIsolate();
   18650   Object* raw_key = *key;
   18651   int entry = table->KeyToFirstEntry(isolate, raw_key);
   18652   // Walk the chain in the bucket to find the key.
   18653   while (entry != kNotFound) {
   18654     Object* candidate_key = table->KeyAt(entry);
   18655     if (candidate_key->SameValueZero(raw_key)) return true;
   18656     entry = table->NextChainEntry(entry);
   18657   }
   18658   return false;
   18659 }
   18660 
   18661 
   18662 Handle<OrderedHashSet> OrderedHashSet::Add(Handle<OrderedHashSet> table,
   18663                                            Handle<Object> key) {
   18664   int hash = Object::GetOrCreateHash(table->GetIsolate(), key)->value();
   18665   int entry = table->HashToEntry(hash);
   18666   // Walk the chain of the bucket and try finding the key.
   18667   while (entry != kNotFound) {
   18668     Object* candidate_key = table->KeyAt(entry);
   18669     // Do not add if we have the key already
   18670     if (candidate_key->SameValueZero(*key)) return table;
   18671     entry = table->NextChainEntry(entry);
   18672   }
   18673 
   18674   table = OrderedHashSet::EnsureGrowable(table);
   18675   // Read the existing bucket values.
   18676   int bucket = table->HashToBucket(hash);
   18677   int previous_entry = table->HashToEntry(hash);
   18678   int nof = table->NumberOfElements();
   18679   // Insert a new entry at the end,
   18680   int new_entry = nof + table->NumberOfDeletedElements();
   18681   int new_index = table->EntryToIndex(new_entry);
   18682   table->set(new_index, *key);
   18683   table->set(new_index + kChainOffset, Smi::FromInt(previous_entry));
   18684   // and point the bucket to the new entry.
   18685   table->set(kHashTableStartIndex + bucket, Smi::FromInt(new_entry));
   18686   table->SetNumberOfElements(nof + 1);
   18687   return table;
   18688 }
   18689 
   18690 Handle<FixedArray> OrderedHashSet::ConvertToKeysArray(
   18691     Handle<OrderedHashSet> table, GetKeysConversion convert) {
   18692   Isolate* isolate = table->GetIsolate();
   18693   int length = table->NumberOfElements();
   18694   int nof_buckets = table->NumberOfBuckets();
   18695   // Convert the dictionary to a linear list.
   18696   Handle<FixedArray> result = Handle<FixedArray>::cast(table);
   18697   // From this point on table is no longer a valid OrderedHashSet.
   18698   result->set_map(isolate->heap()->fixed_array_map());
   18699   for (int i = 0; i < length; i++) {
   18700     int index = kHashTableStartIndex + nof_buckets + (i * kEntrySize);
   18701     Object* key = table->get(index);
   18702     if (convert == GetKeysConversion::kConvertToString && key->IsNumber()) {
   18703       key = *isolate->factory()->NumberToString(handle(key, isolate));
   18704     }
   18705     result->set(i, key);
   18706   }
   18707   result->Shrink(length);
   18708   return result;
   18709 }
   18710 
   18711 template<class Derived, class Iterator, int entrysize>
   18712 Handle<Derived> OrderedHashTable<Derived, Iterator, entrysize>::Rehash(
   18713     Handle<Derived> table, int new_capacity) {
   18714   Isolate* isolate = table->GetIsolate();
   18715   DCHECK(!table->IsObsolete());
   18716 
   18717   Handle<Derived> new_table =
   18718       Allocate(isolate, new_capacity,
   18719                isolate->heap()->InNewSpace(*table) ? NOT_TENURED : TENURED);
   18720   int nof = table->NumberOfElements();
   18721   int nod = table->NumberOfDeletedElements();
   18722   int new_buckets = new_table->NumberOfBuckets();
   18723   int new_entry = 0;
   18724   int removed_holes_index = 0;
   18725 
   18726   DisallowHeapAllocation no_gc;
   18727   for (int old_entry = 0; old_entry < (nof + nod); ++old_entry) {
   18728     Object* key = table->KeyAt(old_entry);
   18729     if (key->IsTheHole(isolate)) {
   18730       table->SetRemovedIndexAt(removed_holes_index++, old_entry);
   18731       continue;
   18732     }
   18733 
   18734     Object* hash = key->GetHash();
   18735     int bucket = Smi::cast(hash)->value() & (new_buckets - 1);
   18736     Object* chain_entry = new_table->get(kHashTableStartIndex + bucket);
   18737     new_table->set(kHashTableStartIndex + bucket, Smi::FromInt(new_entry));
   18738     int new_index = new_table->EntryToIndex(new_entry);
   18739     int old_index = table->EntryToIndex(old_entry);
   18740     for (int i = 0; i < entrysize; ++i) {
   18741       Object* value = table->get(old_index + i);
   18742       new_table->set(new_index + i, value);
   18743     }
   18744     new_table->set(new_index + kChainOffset, chain_entry);
   18745     ++new_entry;
   18746   }
   18747 
   18748   DCHECK_EQ(nod, removed_holes_index);
   18749 
   18750   new_table->SetNumberOfElements(nof);
   18751   table->SetNextTable(*new_table);
   18752 
   18753   return new_table;
   18754 }
   18755 
   18756 
   18757 template Handle<OrderedHashSet>
   18758 OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::Allocate(
   18759     Isolate* isolate, int capacity, PretenureFlag pretenure);
   18760 
   18761 template Handle<OrderedHashSet>
   18762 OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::EnsureGrowable(
   18763     Handle<OrderedHashSet> table);
   18764 
   18765 template Handle<OrderedHashSet>
   18766 OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::Shrink(
   18767     Handle<OrderedHashSet> table);
   18768 
   18769 template Handle<OrderedHashSet>
   18770 OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::Clear(
   18771     Handle<OrderedHashSet> table);
   18772 
   18773 template bool OrderedHashTable<OrderedHashSet, JSSetIterator, 1>::HasKey(
   18774     Handle<OrderedHashSet> table, Handle<Object> key);
   18775 
   18776 
   18777 template Handle<OrderedHashMap>
   18778 OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::Allocate(
   18779     Isolate* isolate, int capacity, PretenureFlag pretenure);
   18780 
   18781 template Handle<OrderedHashMap>
   18782 OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::EnsureGrowable(
   18783     Handle<OrderedHashMap> table);
   18784 
   18785 template Handle<OrderedHashMap>
   18786 OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::Shrink(
   18787     Handle<OrderedHashMap> table);
   18788 
   18789 template Handle<OrderedHashMap>
   18790 OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::Clear(
   18791     Handle<OrderedHashMap> table);
   18792 
   18793 template bool OrderedHashTable<OrderedHashMap, JSMapIterator, 2>::HasKey(
   18794     Handle<OrderedHashMap> table, Handle<Object> key);
   18795 
   18796 
   18797 template<class Derived, class TableType>
   18798 void OrderedHashTableIterator<Derived, TableType>::Transition() {
   18799   DisallowHeapAllocation no_allocation;
   18800   TableType* table = TableType::cast(this->table());
   18801   if (!table->IsObsolete()) return;
   18802 
   18803   int index = Smi::cast(this->index())->value();
   18804   while (table->IsObsolete()) {
   18805     TableType* next_table = table->NextTable();
   18806 
   18807     if (index > 0) {
   18808       int nod = table->NumberOfDeletedElements();
   18809 
   18810       if (nod == TableType::kClearedTableSentinel) {
   18811         index = 0;
   18812       } else {
   18813         int old_index = index;
   18814         for (int i = 0; i < nod; ++i) {
   18815           int removed_index = table->RemovedIndexAt(i);
   18816           if (removed_index >= old_index) break;
   18817           --index;
   18818         }
   18819       }
   18820     }
   18821 
   18822     table = next_table;
   18823   }
   18824 
   18825   set_table(table);
   18826   set_index(Smi::FromInt(index));
   18827 }
   18828 
   18829 
   18830 template<class Derived, class TableType>
   18831 bool OrderedHashTableIterator<Derived, TableType>::HasMore() {
   18832   DisallowHeapAllocation no_allocation;
   18833   Isolate* isolate = this->GetIsolate();
   18834   if (this->table()->IsUndefined(isolate)) return false;
   18835 
   18836   Transition();
   18837 
   18838   TableType* table = TableType::cast(this->table());
   18839   int index = Smi::cast(this->index())->value();
   18840   int used_capacity = table->UsedCapacity();
   18841 
   18842   while (index < used_capacity && table->KeyAt(index)->IsTheHole(isolate)) {
   18843     index++;
   18844   }
   18845 
   18846   set_index(Smi::FromInt(index));
   18847 
   18848   if (index < used_capacity) return true;
   18849 
   18850   set_table(isolate->heap()->undefined_value());
   18851   return false;
   18852 }
   18853 
   18854 
   18855 template<class Derived, class TableType>
   18856 Smi* OrderedHashTableIterator<Derived, TableType>::Next(JSArray* value_array) {
   18857   DisallowHeapAllocation no_allocation;
   18858   if (HasMore()) {
   18859     FixedArray* array = FixedArray::cast(value_array->elements());
   18860     static_cast<Derived*>(this)->PopulateValueArray(array);
   18861     MoveNext();
   18862     return Smi::cast(kind());
   18863   }
   18864   return Smi::kZero;
   18865 }
   18866 
   18867 
   18868 template Smi*
   18869 OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::Next(
   18870     JSArray* value_array);
   18871 
   18872 template bool
   18873 OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::HasMore();
   18874 
   18875 template void
   18876 OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::MoveNext();
   18877 
   18878 template Object*
   18879 OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::CurrentKey();
   18880 
   18881 template void
   18882 OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::Transition();
   18883 
   18884 
   18885 template Smi*
   18886 OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::Next(
   18887     JSArray* value_array);
   18888 
   18889 template bool
   18890 OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::HasMore();
   18891 
   18892 template void
   18893 OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::MoveNext();
   18894 
   18895 template Object*
   18896 OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::CurrentKey();
   18897 
   18898 template void
   18899 OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::Transition();
   18900 
   18901 
   18902 void JSSet::Initialize(Handle<JSSet> set, Isolate* isolate) {
   18903   Handle<OrderedHashSet> table = isolate->factory()->NewOrderedHashSet();
   18904   set->set_table(*table);
   18905 }
   18906 
   18907 
   18908 void JSSet::Clear(Handle<JSSet> set) {
   18909   Handle<OrderedHashSet> table(OrderedHashSet::cast(set->table()));
   18910   table = OrderedHashSet::Clear(table);
   18911   set->set_table(*table);
   18912 }
   18913 
   18914 
   18915 void JSMap::Initialize(Handle<JSMap> map, Isolate* isolate) {
   18916   Handle<OrderedHashMap> table = isolate->factory()->NewOrderedHashMap();
   18917   map->set_table(*table);
   18918 }
   18919 
   18920 
   18921 void JSMap::Clear(Handle<JSMap> map) {
   18922   Handle<OrderedHashMap> table(OrderedHashMap::cast(map->table()));
   18923   table = OrderedHashMap::Clear(table);
   18924   map->set_table(*table);
   18925 }
   18926 
   18927 
   18928 void JSWeakCollection::Initialize(Handle<JSWeakCollection> weak_collection,
   18929                                   Isolate* isolate) {
   18930   Handle<ObjectHashTable> table = ObjectHashTable::New(isolate, 0);
   18931   weak_collection->set_table(*table);
   18932 }
   18933 
   18934 
   18935 void JSWeakCollection::Set(Handle<JSWeakCollection> weak_collection,
   18936                            Handle<Object> key, Handle<Object> value,
   18937                            int32_t hash) {
   18938   DCHECK(key->IsJSReceiver() || key->IsSymbol());
   18939   Handle<ObjectHashTable> table(
   18940       ObjectHashTable::cast(weak_collection->table()));
   18941   DCHECK(table->IsKey(*key));
   18942   Handle<ObjectHashTable> new_table =
   18943       ObjectHashTable::Put(table, key, value, hash);
   18944   weak_collection->set_table(*new_table);
   18945   if (*table != *new_table) {
   18946     // Zap the old table since we didn't record slots for its elements.
   18947     table->FillWithHoles(0, table->length());
   18948   }
   18949 }
   18950 
   18951 
   18952 bool JSWeakCollection::Delete(Handle<JSWeakCollection> weak_collection,
   18953                               Handle<Object> key, int32_t hash) {
   18954   DCHECK(key->IsJSReceiver() || key->IsSymbol());
   18955   Handle<ObjectHashTable> table(
   18956       ObjectHashTable::cast(weak_collection->table()));
   18957   DCHECK(table->IsKey(*key));
   18958   bool was_present = false;
   18959   Handle<ObjectHashTable> new_table =
   18960       ObjectHashTable::Remove(table, key, &was_present, hash);
   18961   weak_collection->set_table(*new_table);
   18962   if (*table != *new_table) {
   18963     // Zap the old table since we didn't record slots for its elements.
   18964     table->FillWithHoles(0, table->length());
   18965   }
   18966   return was_present;
   18967 }
   18968 
   18969 // Check if there is a break point at this source position.
   18970 bool DebugInfo::HasBreakPoint(int source_position) {
   18971   // Get the break point info object for this code offset.
   18972   Object* break_point_info = GetBreakPointInfo(source_position);
   18973 
   18974   // If there is no break point info object or no break points in the break
   18975   // point info object there is no break point at this code offset.
   18976   if (break_point_info->IsUndefined(GetIsolate())) return false;
   18977   return BreakPointInfo::cast(break_point_info)->GetBreakPointCount() > 0;
   18978 }
   18979 
   18980 // Get the break point info object for this source position.
   18981 Object* DebugInfo::GetBreakPointInfo(int source_position) {
   18982   Isolate* isolate = GetIsolate();
   18983   if (!break_points()->IsUndefined(isolate)) {
   18984     for (int i = 0; i < break_points()->length(); i++) {
   18985       if (!break_points()->get(i)->IsUndefined(isolate)) {
   18986         BreakPointInfo* break_point_info =
   18987             BreakPointInfo::cast(break_points()->get(i));
   18988         if (break_point_info->source_position() == source_position) {
   18989           return break_point_info;
   18990         }
   18991       }
   18992     }
   18993   }
   18994   return isolate->heap()->undefined_value();
   18995 }
   18996 
   18997 bool DebugInfo::ClearBreakPoint(Handle<DebugInfo> debug_info,
   18998                                 Handle<Object> break_point_object) {
   18999   Isolate* isolate = debug_info->GetIsolate();
   19000   if (debug_info->break_points()->IsUndefined(isolate)) return false;
   19001 
   19002   for (int i = 0; i < debug_info->break_points()->length(); i++) {
   19003     if (debug_info->break_points()->get(i)->IsUndefined(isolate)) continue;
   19004     Handle<BreakPointInfo> break_point_info = Handle<BreakPointInfo>(
   19005         BreakPointInfo::cast(debug_info->break_points()->get(i)), isolate);
   19006     if (BreakPointInfo::HasBreakPointObject(break_point_info,
   19007                                             break_point_object)) {
   19008       BreakPointInfo::ClearBreakPoint(break_point_info, break_point_object);
   19009       return true;
   19010     }
   19011   }
   19012   return false;
   19013 }
   19014 
   19015 void DebugInfo::SetBreakPoint(Handle<DebugInfo> debug_info, int source_position,
   19016                               Handle<Object> break_point_object) {
   19017   Isolate* isolate = debug_info->GetIsolate();
   19018   Handle<Object> break_point_info(
   19019       debug_info->GetBreakPointInfo(source_position), isolate);
   19020   if (!break_point_info->IsUndefined(isolate)) {
   19021     BreakPointInfo::SetBreakPoint(
   19022         Handle<BreakPointInfo>::cast(break_point_info),
   19023         break_point_object);
   19024     return;
   19025   }
   19026 
   19027   // Adding a new break point for a code offset which did not have any
   19028   // break points before. Try to find a free slot.
   19029   static const int kNoBreakPointInfo = -1;
   19030   int index = kNoBreakPointInfo;
   19031   for (int i = 0; i < debug_info->break_points()->length(); i++) {
   19032     if (debug_info->break_points()->get(i)->IsUndefined(isolate)) {
   19033       index = i;
   19034       break;
   19035     }
   19036   }
   19037   if (index == kNoBreakPointInfo) {
   19038     // No free slot - extend break point info array.
   19039     Handle<FixedArray> old_break_points = Handle<FixedArray>(
   19040         FixedArray::cast(debug_info->break_points()), isolate);
   19041     Handle<FixedArray> new_break_points =
   19042         isolate->factory()->NewFixedArray(
   19043             old_break_points->length() +
   19044             DebugInfo::kEstimatedNofBreakPointsInFunction);
   19045 
   19046     debug_info->set_break_points(*new_break_points);
   19047     for (int i = 0; i < old_break_points->length(); i++) {
   19048       new_break_points->set(i, old_break_points->get(i));
   19049     }
   19050     index = old_break_points->length();
   19051   }
   19052   DCHECK(index != kNoBreakPointInfo);
   19053 
   19054   // Allocate new BreakPointInfo object and set the break point.
   19055   Handle<BreakPointInfo> new_break_point_info = Handle<BreakPointInfo>::cast(
   19056       isolate->factory()->NewStruct(BREAK_POINT_INFO_TYPE));
   19057   new_break_point_info->set_source_position(source_position);
   19058   new_break_point_info->set_break_point_objects(
   19059       isolate->heap()->undefined_value());
   19060   BreakPointInfo::SetBreakPoint(new_break_point_info, break_point_object);
   19061   debug_info->break_points()->set(index, *new_break_point_info);
   19062 }
   19063 
   19064 // Get the break point objects for a source position.
   19065 Handle<Object> DebugInfo::GetBreakPointObjects(int source_position) {
   19066   Object* break_point_info = GetBreakPointInfo(source_position);
   19067   Isolate* isolate = GetIsolate();
   19068   if (break_point_info->IsUndefined(isolate)) {
   19069     return isolate->factory()->undefined_value();
   19070   }
   19071   return Handle<Object>(
   19072       BreakPointInfo::cast(break_point_info)->break_point_objects(), isolate);
   19073 }
   19074 
   19075 
   19076 // Get the total number of break points.
   19077 int DebugInfo::GetBreakPointCount() {
   19078   Isolate* isolate = GetIsolate();
   19079   if (break_points()->IsUndefined(isolate)) return 0;
   19080   int count = 0;
   19081   for (int i = 0; i < break_points()->length(); i++) {
   19082     if (!break_points()->get(i)->IsUndefined(isolate)) {
   19083       BreakPointInfo* break_point_info =
   19084           BreakPointInfo::cast(break_points()->get(i));
   19085       count += break_point_info->GetBreakPointCount();
   19086     }
   19087   }
   19088   return count;
   19089 }
   19090 
   19091 
   19092 Handle<Object> DebugInfo::FindBreakPointInfo(
   19093     Handle<DebugInfo> debug_info, Handle<Object> break_point_object) {
   19094   Isolate* isolate = debug_info->GetIsolate();
   19095   if (!debug_info->break_points()->IsUndefined(isolate)) {
   19096     for (int i = 0; i < debug_info->break_points()->length(); i++) {
   19097       if (!debug_info->break_points()->get(i)->IsUndefined(isolate)) {
   19098         Handle<BreakPointInfo> break_point_info = Handle<BreakPointInfo>(
   19099             BreakPointInfo::cast(debug_info->break_points()->get(i)), isolate);
   19100         if (BreakPointInfo::HasBreakPointObject(break_point_info,
   19101                                                 break_point_object)) {
   19102           return break_point_info;
   19103         }
   19104       }
   19105     }
   19106   }
   19107   return isolate->factory()->undefined_value();
   19108 }
   19109 
   19110 // Remove the specified break point object.
   19111 void BreakPointInfo::ClearBreakPoint(Handle<BreakPointInfo> break_point_info,
   19112                                      Handle<Object> break_point_object) {
   19113   Isolate* isolate = break_point_info->GetIsolate();
   19114   // If there are no break points just ignore.
   19115   if (break_point_info->break_point_objects()->IsUndefined(isolate)) return;
   19116   // If there is a single break point clear it if it is the same.
   19117   if (!break_point_info->break_point_objects()->IsFixedArray()) {
   19118     if (break_point_info->break_point_objects() == *break_point_object) {
   19119       break_point_info->set_break_point_objects(
   19120           isolate->heap()->undefined_value());
   19121     }
   19122     return;
   19123   }
   19124   // If there are multiple break points shrink the array
   19125   DCHECK(break_point_info->break_point_objects()->IsFixedArray());
   19126   Handle<FixedArray> old_array =
   19127       Handle<FixedArray>(
   19128           FixedArray::cast(break_point_info->break_point_objects()));
   19129   Handle<FixedArray> new_array =
   19130       isolate->factory()->NewFixedArray(old_array->length() - 1);
   19131   int found_count = 0;
   19132   for (int i = 0; i < old_array->length(); i++) {
   19133     if (old_array->get(i) == *break_point_object) {
   19134       DCHECK(found_count == 0);
   19135       found_count++;
   19136     } else {
   19137       new_array->set(i - found_count, old_array->get(i));
   19138     }
   19139   }
   19140   // If the break point was found in the list change it.
   19141   if (found_count > 0) break_point_info->set_break_point_objects(*new_array);
   19142 }
   19143 
   19144 
   19145 // Add the specified break point object.
   19146 void BreakPointInfo::SetBreakPoint(Handle<BreakPointInfo> break_point_info,
   19147                                    Handle<Object> break_point_object) {
   19148   Isolate* isolate = break_point_info->GetIsolate();
   19149 
   19150   // If there was no break point objects before just set it.
   19151   if (break_point_info->break_point_objects()->IsUndefined(isolate)) {
   19152     break_point_info->set_break_point_objects(*break_point_object);
   19153     return;
   19154   }
   19155   // If the break point object is the same as before just ignore.
   19156   if (break_point_info->break_point_objects() == *break_point_object) return;
   19157   // If there was one break point object before replace with array.
   19158   if (!break_point_info->break_point_objects()->IsFixedArray()) {
   19159     Handle<FixedArray> array = isolate->factory()->NewFixedArray(2);
   19160     array->set(0, break_point_info->break_point_objects());
   19161     array->set(1, *break_point_object);
   19162     break_point_info->set_break_point_objects(*array);
   19163     return;
   19164   }
   19165   // If there was more than one break point before extend array.
   19166   Handle<FixedArray> old_array =
   19167       Handle<FixedArray>(
   19168           FixedArray::cast(break_point_info->break_point_objects()));
   19169   Handle<FixedArray> new_array =
   19170       isolate->factory()->NewFixedArray(old_array->length() + 1);
   19171   for (int i = 0; i < old_array->length(); i++) {
   19172     // If the break point was there before just ignore.
   19173     if (old_array->get(i) == *break_point_object) return;
   19174     new_array->set(i, old_array->get(i));
   19175   }
   19176   // Add the new break point.
   19177   new_array->set(old_array->length(), *break_point_object);
   19178   break_point_info->set_break_point_objects(*new_array);
   19179 }
   19180 
   19181 
   19182 bool BreakPointInfo::HasBreakPointObject(
   19183     Handle<BreakPointInfo> break_point_info,
   19184     Handle<Object> break_point_object) {
   19185   // No break point.
   19186   Isolate* isolate = break_point_info->GetIsolate();
   19187   if (break_point_info->break_point_objects()->IsUndefined(isolate)) {
   19188     return false;
   19189   }
   19190   // Single break point.
   19191   if (!break_point_info->break_point_objects()->IsFixedArray()) {
   19192     return break_point_info->break_point_objects() == *break_point_object;
   19193   }
   19194   // Multiple break points.
   19195   FixedArray* array = FixedArray::cast(break_point_info->break_point_objects());
   19196   for (int i = 0; i < array->length(); i++) {
   19197     if (array->get(i) == *break_point_object) {
   19198       return true;
   19199     }
   19200   }
   19201   return false;
   19202 }
   19203 
   19204 
   19205 // Get the number of break points.
   19206 int BreakPointInfo::GetBreakPointCount() {
   19207   // No break point.
   19208   if (break_point_objects()->IsUndefined(GetIsolate())) return 0;
   19209   // Single break point.
   19210   if (!break_point_objects()->IsFixedArray()) return 1;
   19211   // Multiple break points.
   19212   return FixedArray::cast(break_point_objects())->length();
   19213 }
   19214 
   19215 
   19216 // static
   19217 MaybeHandle<JSDate> JSDate::New(Handle<JSFunction> constructor,
   19218                                 Handle<JSReceiver> new_target, double tv) {
   19219   Isolate* const isolate = constructor->GetIsolate();
   19220   Handle<JSObject> result;
   19221   ASSIGN_RETURN_ON_EXCEPTION(isolate, result,
   19222                              JSObject::New(constructor, new_target), JSDate);
   19223   if (-DateCache::kMaxTimeInMs <= tv && tv <= DateCache::kMaxTimeInMs) {
   19224     tv = DoubleToInteger(tv) + 0.0;
   19225   } else {
   19226     tv = std::numeric_limits<double>::quiet_NaN();
   19227   }
   19228   Handle<Object> value = isolate->factory()->NewNumber(tv);
   19229   Handle<JSDate>::cast(result)->SetValue(*value, std::isnan(tv));
   19230   return Handle<JSDate>::cast(result);
   19231 }
   19232 
   19233 
   19234 // static
   19235 double JSDate::CurrentTimeValue(Isolate* isolate) {
   19236   if (FLAG_log_timer_events || FLAG_prof_cpp) LOG(isolate, CurrentTimeEvent());
   19237 
   19238   // According to ECMA-262, section 15.9.1, page 117, the precision of
   19239   // the number in a Date object representing a particular instant in
   19240   // time is milliseconds. Therefore, we floor the result of getting
   19241   // the OS time.
   19242   return Floor(FLAG_verify_predictable
   19243                    ? isolate->heap()->MonotonicallyIncreasingTimeInMs()
   19244                    : base::OS::TimeCurrentMillis());
   19245 }
   19246 
   19247 
   19248 // static
   19249 Object* JSDate::GetField(Object* object, Smi* index) {
   19250   return JSDate::cast(object)->DoGetField(
   19251       static_cast<FieldIndex>(index->value()));
   19252 }
   19253 
   19254 
   19255 Object* JSDate::DoGetField(FieldIndex index) {
   19256   DCHECK(index != kDateValue);
   19257 
   19258   DateCache* date_cache = GetIsolate()->date_cache();
   19259 
   19260   if (index < kFirstUncachedField) {
   19261     Object* stamp = cache_stamp();
   19262     if (stamp != date_cache->stamp() && stamp->IsSmi()) {
   19263       // Since the stamp is not NaN, the value is also not NaN.
   19264       int64_t local_time_ms =
   19265           date_cache->ToLocal(static_cast<int64_t>(value()->Number()));
   19266       SetCachedFields(local_time_ms, date_cache);
   19267     }
   19268     switch (index) {
   19269       case kYear: return year();
   19270       case kMonth: return month();
   19271       case kDay: return day();
   19272       case kWeekday: return weekday();
   19273       case kHour: return hour();
   19274       case kMinute: return min();
   19275       case kSecond: return sec();
   19276       default: UNREACHABLE();
   19277     }
   19278   }
   19279 
   19280   if (index >= kFirstUTCField) {
   19281     return GetUTCField(index, value()->Number(), date_cache);
   19282   }
   19283 
   19284   double time = value()->Number();
   19285   if (std::isnan(time)) return GetIsolate()->heap()->nan_value();
   19286 
   19287   int64_t local_time_ms = date_cache->ToLocal(static_cast<int64_t>(time));
   19288   int days = DateCache::DaysFromTime(local_time_ms);
   19289 
   19290   if (index == kDays) return Smi::FromInt(days);
   19291 
   19292   int time_in_day_ms = DateCache::TimeInDay(local_time_ms, days);
   19293   if (index == kMillisecond) return Smi::FromInt(time_in_day_ms % 1000);
   19294   DCHECK(index == kTimeInDay);
   19295   return Smi::FromInt(time_in_day_ms);
   19296 }
   19297 
   19298 
   19299 Object* JSDate::GetUTCField(FieldIndex index,
   19300                             double value,
   19301                             DateCache* date_cache) {
   19302   DCHECK(index >= kFirstUTCField);
   19303 
   19304   if (std::isnan(value)) return GetIsolate()->heap()->nan_value();
   19305 
   19306   int64_t time_ms = static_cast<int64_t>(value);
   19307 
   19308   if (index == kTimezoneOffset) {
   19309     return Smi::FromInt(date_cache->TimezoneOffset(time_ms));
   19310   }
   19311 
   19312   int days = DateCache::DaysFromTime(time_ms);
   19313 
   19314   if (index == kWeekdayUTC) return Smi::FromInt(date_cache->Weekday(days));
   19315 
   19316   if (index <= kDayUTC) {
   19317     int year, month, day;
   19318     date_cache->YearMonthDayFromDays(days, &year, &month, &day);
   19319     if (index == kYearUTC) return Smi::FromInt(year);
   19320     if (index == kMonthUTC) return Smi::FromInt(month);
   19321     DCHECK(index == kDayUTC);
   19322     return Smi::FromInt(day);
   19323   }
   19324 
   19325   int time_in_day_ms = DateCache::TimeInDay(time_ms, days);
   19326   switch (index) {
   19327     case kHourUTC: return Smi::FromInt(time_in_day_ms / (60 * 60 * 1000));
   19328     case kMinuteUTC: return Smi::FromInt((time_in_day_ms / (60 * 1000)) % 60);
   19329     case kSecondUTC: return Smi::FromInt((time_in_day_ms / 1000) % 60);
   19330     case kMillisecondUTC: return Smi::FromInt(time_in_day_ms % 1000);
   19331     case kDaysUTC: return Smi::FromInt(days);
   19332     case kTimeInDayUTC: return Smi::FromInt(time_in_day_ms);
   19333     default: UNREACHABLE();
   19334   }
   19335 
   19336   UNREACHABLE();
   19337   return NULL;
   19338 }
   19339 
   19340 
   19341 // static
   19342 Handle<Object> JSDate::SetValue(Handle<JSDate> date, double v) {
   19343   Isolate* const isolate = date->GetIsolate();
   19344   Handle<Object> value = isolate->factory()->NewNumber(v);
   19345   bool value_is_nan = std::isnan(v);
   19346   date->SetValue(*value, value_is_nan);
   19347   return value;
   19348 }
   19349 
   19350 
   19351 void JSDate::SetValue(Object* value, bool is_value_nan) {
   19352   set_value(value);
   19353   if (is_value_nan) {
   19354     HeapNumber* nan = GetIsolate()->heap()->nan_value();
   19355     set_cache_stamp(nan, SKIP_WRITE_BARRIER);
   19356     set_year(nan, SKIP_WRITE_BARRIER);
   19357     set_month(nan, SKIP_WRITE_BARRIER);
   19358     set_day(nan, SKIP_WRITE_BARRIER);
   19359     set_hour(nan, SKIP_WRITE_BARRIER);
   19360     set_min(nan, SKIP_WRITE_BARRIER);
   19361     set_sec(nan, SKIP_WRITE_BARRIER);
   19362     set_weekday(nan, SKIP_WRITE_BARRIER);
   19363   } else {
   19364     set_cache_stamp(Smi::FromInt(DateCache::kInvalidStamp), SKIP_WRITE_BARRIER);
   19365   }
   19366 }
   19367 
   19368 
   19369 // static
   19370 MaybeHandle<Object> JSDate::ToPrimitive(Handle<JSReceiver> receiver,
   19371                                         Handle<Object> hint) {
   19372   Isolate* const isolate = receiver->GetIsolate();
   19373   if (hint->IsString()) {
   19374     Handle<String> hint_string = Handle<String>::cast(hint);
   19375     if (hint_string->Equals(isolate->heap()->number_string())) {
   19376       return JSReceiver::OrdinaryToPrimitive(receiver,
   19377                                              OrdinaryToPrimitiveHint::kNumber);
   19378     }
   19379     if (hint_string->Equals(isolate->heap()->default_string()) ||
   19380         hint_string->Equals(isolate->heap()->string_string())) {
   19381       return JSReceiver::OrdinaryToPrimitive(receiver,
   19382                                              OrdinaryToPrimitiveHint::kString);
   19383     }
   19384   }
   19385   THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kInvalidHint, hint),
   19386                   Object);
   19387 }
   19388 
   19389 
   19390 void JSDate::SetCachedFields(int64_t local_time_ms, DateCache* date_cache) {
   19391   int days = DateCache::DaysFromTime(local_time_ms);
   19392   int time_in_day_ms = DateCache::TimeInDay(local_time_ms, days);
   19393   int year, month, day;
   19394   date_cache->YearMonthDayFromDays(days, &year, &month, &day);
   19395   int weekday = date_cache->Weekday(days);
   19396   int hour = time_in_day_ms / (60 * 60 * 1000);
   19397   int min = (time_in_day_ms / (60 * 1000)) % 60;
   19398   int sec = (time_in_day_ms / 1000) % 60;
   19399   set_cache_stamp(date_cache->stamp());
   19400   set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER);
   19401   set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER);
   19402   set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER);
   19403   set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER);
   19404   set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER);
   19405   set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER);
   19406   set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER);
   19407 }
   19408 
   19409 namespace {
   19410 
   19411 Script* ScriptFromJSValue(Object* in) {
   19412   DCHECK(in->IsJSValue());
   19413   JSValue* jsvalue = JSValue::cast(in);
   19414   DCHECK(jsvalue->value()->IsScript());
   19415   return Script::cast(jsvalue->value());
   19416 }
   19417 
   19418 }  // namespace
   19419 
   19420 int JSMessageObject::GetLineNumber() const {
   19421   if (start_position() == -1) return Message::kNoLineNumberInfo;
   19422 
   19423   Handle<Script> the_script = handle(ScriptFromJSValue(script()));
   19424 
   19425   Script::PositionInfo info;
   19426   const Script::OffsetFlag offset_flag = Script::WITH_OFFSET;
   19427   if (!Script::GetPositionInfo(the_script, start_position(), &info,
   19428                                offset_flag)) {
   19429     return Message::kNoLineNumberInfo;
   19430   }
   19431 
   19432   return info.line + 1;
   19433 }
   19434 
   19435 int JSMessageObject::GetColumnNumber() const {
   19436   if (start_position() == -1) return -1;
   19437 
   19438   Handle<Script> the_script = handle(ScriptFromJSValue(script()));
   19439 
   19440   Script::PositionInfo info;
   19441   const Script::OffsetFlag offset_flag = Script::WITH_OFFSET;
   19442   if (!Script::GetPositionInfo(the_script, start_position(), &info,
   19443                                offset_flag)) {
   19444     return -1;
   19445   }
   19446 
   19447   return info.column;  // Note: No '+1' in contrast to GetLineNumber.
   19448 }
   19449 
   19450 Handle<String> JSMessageObject::GetSourceLine() const {
   19451   Handle<Script> the_script = handle(ScriptFromJSValue(script()));
   19452 
   19453   Isolate* isolate = the_script->GetIsolate();
   19454   if (the_script->type() == Script::TYPE_WASM) {
   19455     return isolate->factory()->empty_string();
   19456   }
   19457 
   19458   Script::PositionInfo info;
   19459   const Script::OffsetFlag offset_flag = Script::WITH_OFFSET;
   19460   if (!Script::GetPositionInfo(the_script, start_position(), &info,
   19461                                offset_flag)) {
   19462     return isolate->factory()->empty_string();
   19463   }
   19464 
   19465   Handle<String> src = handle(String::cast(the_script->source()), isolate);
   19466   return isolate->factory()->NewSubString(src, info.line_start, info.line_end);
   19467 }
   19468 
   19469 void JSArrayBuffer::Neuter() {
   19470   CHECK(is_neuterable());
   19471   CHECK(is_external());
   19472   set_backing_store(NULL);
   19473   set_byte_length(Smi::kZero);
   19474   set_was_neutered(true);
   19475 }
   19476 
   19477 
   19478 void JSArrayBuffer::Setup(Handle<JSArrayBuffer> array_buffer, Isolate* isolate,
   19479                           bool is_external, void* data, size_t allocated_length,
   19480                           SharedFlag shared) {
   19481   DCHECK(array_buffer->GetInternalFieldCount() ==
   19482          v8::ArrayBuffer::kInternalFieldCount);
   19483   for (int i = 0; i < v8::ArrayBuffer::kInternalFieldCount; i++) {
   19484     array_buffer->SetInternalField(i, Smi::kZero);
   19485   }
   19486   array_buffer->set_bit_field(0);
   19487   array_buffer->set_is_external(is_external);
   19488   array_buffer->set_is_neuterable(shared == SharedFlag::kNotShared);
   19489   array_buffer->set_is_shared(shared == SharedFlag::kShared);
   19490 
   19491   Handle<Object> byte_length =
   19492       isolate->factory()->NewNumberFromSize(allocated_length);
   19493   CHECK(byte_length->IsSmi() || byte_length->IsHeapNumber());
   19494   array_buffer->set_byte_length(*byte_length);
   19495   // Initialize backing store at last to avoid handling of |JSArrayBuffers| that
   19496   // are currently being constructed in the |ArrayBufferTracker|. The
   19497   // registration method below handles the case of registering a buffer that has
   19498   // already been promoted.
   19499   array_buffer->set_backing_store(data);
   19500 
   19501   if (data && !is_external) {
   19502     isolate->heap()->RegisterNewArrayBuffer(*array_buffer);
   19503   }
   19504 }
   19505 
   19506 
   19507 bool JSArrayBuffer::SetupAllocatingData(Handle<JSArrayBuffer> array_buffer,
   19508                                         Isolate* isolate,
   19509                                         size_t allocated_length,
   19510                                         bool initialize, SharedFlag shared) {
   19511   void* data;
   19512   CHECK(isolate->array_buffer_allocator() != NULL);
   19513   // Prevent creating array buffers when serializing.
   19514   DCHECK(!isolate->serializer_enabled());
   19515   if (allocated_length != 0) {
   19516     if (initialize) {
   19517       data = isolate->array_buffer_allocator()->Allocate(allocated_length);
   19518     } else {
   19519       data = isolate->array_buffer_allocator()->AllocateUninitialized(
   19520           allocated_length);
   19521     }
   19522     if (data == NULL) return false;
   19523   } else {
   19524     data = NULL;
   19525   }
   19526 
   19527   JSArrayBuffer::Setup(array_buffer, isolate, false, data, allocated_length,
   19528                        shared);
   19529   return true;
   19530 }
   19531 
   19532 
   19533 Handle<JSArrayBuffer> JSTypedArray::MaterializeArrayBuffer(
   19534     Handle<JSTypedArray> typed_array) {
   19535 
   19536   Handle<Map> map(typed_array->map());
   19537   Isolate* isolate = typed_array->GetIsolate();
   19538 
   19539   DCHECK(IsFixedTypedArrayElementsKind(map->elements_kind()));
   19540 
   19541   Handle<FixedTypedArrayBase> fixed_typed_array(
   19542       FixedTypedArrayBase::cast(typed_array->elements()));
   19543 
   19544   Handle<JSArrayBuffer> buffer(JSArrayBuffer::cast(typed_array->buffer()),
   19545                                isolate);
   19546   void* backing_store =
   19547       isolate->array_buffer_allocator()->AllocateUninitialized(
   19548           fixed_typed_array->DataSize());
   19549   buffer->set_is_external(false);
   19550   DCHECK(buffer->byte_length()->IsSmi() ||
   19551          buffer->byte_length()->IsHeapNumber());
   19552   DCHECK(NumberToInt32(buffer->byte_length()) == fixed_typed_array->DataSize());
   19553   // Initialize backing store at last to avoid handling of |JSArrayBuffers| that
   19554   // are currently being constructed in the |ArrayBufferTracker|. The
   19555   // registration method below handles the case of registering a buffer that has
   19556   // already been promoted.
   19557   buffer->set_backing_store(backing_store);
   19558   isolate->heap()->RegisterNewArrayBuffer(*buffer);
   19559   memcpy(buffer->backing_store(),
   19560          fixed_typed_array->DataPtr(),
   19561          fixed_typed_array->DataSize());
   19562   Handle<FixedTypedArrayBase> new_elements =
   19563       isolate->factory()->NewFixedTypedArrayWithExternalPointer(
   19564           fixed_typed_array->length(), typed_array->type(),
   19565           static_cast<uint8_t*>(buffer->backing_store()));
   19566 
   19567   typed_array->set_elements(*new_elements);
   19568 
   19569   return buffer;
   19570 }
   19571 
   19572 
   19573 Handle<JSArrayBuffer> JSTypedArray::GetBuffer() {
   19574   Handle<JSArrayBuffer> array_buffer(JSArrayBuffer::cast(buffer()),
   19575                                      GetIsolate());
   19576   if (array_buffer->was_neutered() ||
   19577       array_buffer->backing_store() != nullptr) {
   19578     return array_buffer;
   19579   }
   19580   Handle<JSTypedArray> self(this);
   19581   return MaterializeArrayBuffer(self);
   19582 }
   19583 
   19584 Handle<PropertyCell> PropertyCell::InvalidateEntry(
   19585     Handle<GlobalDictionary> dictionary, int entry) {
   19586   Isolate* isolate = dictionary->GetIsolate();
   19587   // Swap with a copy.
   19588   DCHECK(dictionary->ValueAt(entry)->IsPropertyCell());
   19589   Handle<PropertyCell> cell(PropertyCell::cast(dictionary->ValueAt(entry)));
   19590   Handle<PropertyCell> new_cell = isolate->factory()->NewPropertyCell();
   19591   new_cell->set_value(cell->value());
   19592   dictionary->ValueAtPut(entry, *new_cell);
   19593   bool is_the_hole = cell->value()->IsTheHole(isolate);
   19594   // Cell is officially mutable henceforth.
   19595   PropertyDetails details = cell->property_details();
   19596   details = details.set_cell_type(is_the_hole ? PropertyCellType::kUninitialized
   19597                                               : PropertyCellType::kMutable);
   19598   new_cell->set_property_details(details);
   19599   // Old cell is ready for invalidation.
   19600   if (is_the_hole) {
   19601     cell->set_value(isolate->heap()->undefined_value());
   19602   } else {
   19603     cell->set_value(isolate->heap()->the_hole_value());
   19604   }
   19605   details = details.set_cell_type(PropertyCellType::kInvalidated);
   19606   cell->set_property_details(details);
   19607   cell->dependent_code()->DeoptimizeDependentCodeGroup(
   19608       isolate, DependentCode::kPropertyCellChangedGroup);
   19609   return new_cell;
   19610 }
   19611 
   19612 
   19613 PropertyCellConstantType PropertyCell::GetConstantType() {
   19614   if (value()->IsSmi()) return PropertyCellConstantType::kSmi;
   19615   return PropertyCellConstantType::kStableMap;
   19616 }
   19617 
   19618 
   19619 static bool RemainsConstantType(Handle<PropertyCell> cell,
   19620                                 Handle<Object> value) {
   19621   // TODO(dcarney): double->smi and smi->double transition from kConstant
   19622   if (cell->value()->IsSmi() && value->IsSmi()) {
   19623     return true;
   19624   } else if (cell->value()->IsHeapObject() && value->IsHeapObject()) {
   19625     return HeapObject::cast(cell->value())->map() ==
   19626                HeapObject::cast(*value)->map() &&
   19627            HeapObject::cast(*value)->map()->is_stable();
   19628   }
   19629   return false;
   19630 }
   19631 
   19632 
   19633 PropertyCellType PropertyCell::UpdatedType(Handle<PropertyCell> cell,
   19634                                            Handle<Object> value,
   19635                                            PropertyDetails details) {
   19636   PropertyCellType type = details.cell_type();
   19637   Isolate* isolate = cell->GetIsolate();
   19638   DCHECK(!value->IsTheHole(isolate));
   19639   if (cell->value()->IsTheHole(isolate)) {
   19640     switch (type) {
   19641       // Only allow a cell to transition once into constant state.
   19642       case PropertyCellType::kUninitialized:
   19643         if (value->IsUndefined(isolate)) return PropertyCellType::kUndefined;
   19644         return PropertyCellType::kConstant;
   19645       case PropertyCellType::kInvalidated:
   19646         return PropertyCellType::kMutable;
   19647       default:
   19648         UNREACHABLE();
   19649         return PropertyCellType::kMutable;
   19650     }
   19651   }
   19652   switch (type) {
   19653     case PropertyCellType::kUndefined:
   19654       return PropertyCellType::kConstant;
   19655     case PropertyCellType::kConstant:
   19656       if (*value == cell->value()) return PropertyCellType::kConstant;
   19657     // Fall through.
   19658     case PropertyCellType::kConstantType:
   19659       if (RemainsConstantType(cell, value)) {
   19660         return PropertyCellType::kConstantType;
   19661       }
   19662     // Fall through.
   19663     case PropertyCellType::kMutable:
   19664       return PropertyCellType::kMutable;
   19665   }
   19666   UNREACHABLE();
   19667   return PropertyCellType::kMutable;
   19668 }
   19669 
   19670 Handle<PropertyCell> PropertyCell::PrepareForValue(
   19671     Handle<GlobalDictionary> dictionary, int entry, Handle<Object> value,
   19672     PropertyDetails details) {
   19673   Isolate* isolate = dictionary->GetIsolate();
   19674   DCHECK(!value->IsTheHole(isolate));
   19675   DCHECK(dictionary->ValueAt(entry)->IsPropertyCell());
   19676   Handle<PropertyCell> cell(PropertyCell::cast(dictionary->ValueAt(entry)));
   19677   const PropertyDetails original_details = cell->property_details();
   19678   // Data accesses could be cached in ics or optimized code.
   19679   bool invalidate =
   19680       original_details.kind() == kData && details.kind() == kAccessor;
   19681   int index = original_details.dictionary_index();
   19682   PropertyCellType old_type = original_details.cell_type();
   19683   // Preserve the enumeration index unless the property was deleted or never
   19684   // initialized.
   19685   if (cell->value()->IsTheHole(isolate)) {
   19686     index = dictionary->NextEnumerationIndex();
   19687     dictionary->SetNextEnumerationIndex(index + 1);
   19688   }
   19689   DCHECK(index > 0);
   19690   details = details.set_index(index);
   19691 
   19692   PropertyCellType new_type = UpdatedType(cell, value, original_details);
   19693   if (invalidate) cell = PropertyCell::InvalidateEntry(dictionary, entry);
   19694 
   19695   // Install new property details.
   19696   details = details.set_cell_type(new_type);
   19697   cell->set_property_details(details);
   19698 
   19699   // Deopt when transitioning from a constant type.
   19700   if (!invalidate && (old_type != new_type ||
   19701                       original_details.IsReadOnly() != details.IsReadOnly())) {
   19702     cell->dependent_code()->DeoptimizeDependentCodeGroup(
   19703         isolate, DependentCode::kPropertyCellChangedGroup);
   19704   }
   19705   return cell;
   19706 }
   19707 
   19708 
   19709 // static
   19710 void PropertyCell::SetValueWithInvalidation(Handle<PropertyCell> cell,
   19711                                             Handle<Object> new_value) {
   19712   if (cell->value() != *new_value) {
   19713     cell->set_value(*new_value);
   19714     Isolate* isolate = cell->GetIsolate();
   19715     cell->dependent_code()->DeoptimizeDependentCodeGroup(
   19716         isolate, DependentCode::kPropertyCellChangedGroup);
   19717   }
   19718 }
   19719 
   19720 int JSGeneratorObject::source_position() const {
   19721   CHECK(is_suspended());
   19722   AbstractCode* code;
   19723   int code_offset;
   19724   if (function()->shared()->HasBytecodeArray()) {
   19725     // New-style generators.
   19726     DCHECK(!function()->shared()->HasBaselineCode());
   19727     code_offset = Smi::cast(input_or_debug_pos())->value();
   19728     // The stored bytecode offset is relative to a different base than what
   19729     // is used in the source position table, hence the subtraction.
   19730     code_offset -= BytecodeArray::kHeaderSize - kHeapObjectTag;
   19731     code = AbstractCode::cast(function()->shared()->bytecode_array());
   19732   } else {
   19733     // Old-style generators.
   19734     DCHECK(function()->shared()->HasBaselineCode());
   19735     code_offset = continuation();
   19736     CHECK(0 <= code_offset);
   19737     CHECK(code_offset < function()->code()->instruction_size());
   19738     code = AbstractCode::cast(function()->shared()->code());
   19739   }
   19740   return code->SourcePosition(code_offset);
   19741 }
   19742 
   19743 // static
   19744 AccessCheckInfo* AccessCheckInfo::Get(Isolate* isolate,
   19745                                       Handle<JSObject> receiver) {
   19746   DisallowHeapAllocation no_gc;
   19747   DCHECK(receiver->map()->is_access_check_needed());
   19748   Object* maybe_constructor = receiver->map()->GetConstructor();
   19749   // Might happen for a detached context.
   19750   if (!maybe_constructor->IsJSFunction()) return nullptr;
   19751   JSFunction* constructor = JSFunction::cast(maybe_constructor);
   19752   // Might happen for the debug context.
   19753   if (!constructor->shared()->IsApiFunction()) return nullptr;
   19754 
   19755   Object* data_obj =
   19756       constructor->shared()->get_api_func_data()->access_check_info();
   19757   if (data_obj->IsUndefined(isolate)) return nullptr;
   19758 
   19759   return AccessCheckInfo::cast(data_obj);
   19760 }
   19761 
   19762 bool JSReceiver::HasProxyInPrototype(Isolate* isolate) {
   19763   for (PrototypeIterator iter(isolate, this, kStartAtReceiver,
   19764                               PrototypeIterator::END_AT_NULL);
   19765        !iter.IsAtEnd(); iter.AdvanceIgnoringProxies()) {
   19766     if (iter.GetCurrent<Object>()->IsJSProxy()) return true;
   19767   }
   19768   return false;
   19769 }
   19770 
   19771 MaybeHandle<Object> JSModuleNamespace::GetExport(Handle<String> name) {
   19772   Isolate* isolate = name->GetIsolate();
   19773 
   19774   Handle<Object> object(module()->exports()->Lookup(name), isolate);
   19775   if (object->IsTheHole(isolate)) {
   19776     return isolate->factory()->undefined_value();
   19777   }
   19778 
   19779   Handle<Object> value(Handle<Cell>::cast(object)->value(), isolate);
   19780   if (value->IsTheHole(isolate)) {
   19781     THROW_NEW_ERROR(
   19782         isolate, NewReferenceError(MessageTemplate::kNotDefined, name), Object);
   19783   }
   19784 
   19785   return value;
   19786 }
   19787 
   19788 namespace {
   19789 
   19790 struct ModuleHandleHash {
   19791   V8_INLINE size_t operator()(Handle<Module> module) const {
   19792     return module->hash();
   19793   }
   19794 };
   19795 
   19796 struct ModuleHandleEqual {
   19797   V8_INLINE bool operator()(Handle<Module> lhs, Handle<Module> rhs) const {
   19798     return *lhs == *rhs;
   19799   }
   19800 };
   19801 
   19802 struct StringHandleHash {
   19803   V8_INLINE size_t operator()(Handle<String> string) const {
   19804     return string->Hash();
   19805   }
   19806 };
   19807 
   19808 struct StringHandleEqual {
   19809   V8_INLINE bool operator()(Handle<String> lhs, Handle<String> rhs) const {
   19810     return lhs->Equals(*rhs);
   19811   }
   19812 };
   19813 
   19814 class UnorderedStringSet
   19815     : public std::unordered_set<Handle<String>, StringHandleHash,
   19816                                 StringHandleEqual,
   19817                                 zone_allocator<Handle<String>>> {
   19818  public:
   19819   explicit UnorderedStringSet(Zone* zone)
   19820       : std::unordered_set<Handle<String>, StringHandleHash, StringHandleEqual,
   19821                            zone_allocator<Handle<String>>>(
   19822             2 /* bucket count */, StringHandleHash(), StringHandleEqual(),
   19823             zone_allocator<Handle<String>>(zone)) {}
   19824 };
   19825 
   19826 class UnorderedModuleSet
   19827     : public std::unordered_set<Handle<Module>, ModuleHandleHash,
   19828                                 ModuleHandleEqual,
   19829                                 zone_allocator<Handle<Module>>> {
   19830  public:
   19831   explicit UnorderedModuleSet(Zone* zone)
   19832       : std::unordered_set<Handle<Module>, ModuleHandleHash, ModuleHandleEqual,
   19833                            zone_allocator<Handle<Module>>>(
   19834             2 /* bucket count */, ModuleHandleHash(), ModuleHandleEqual(),
   19835             zone_allocator<Handle<Module>>(zone)) {}
   19836 };
   19837 
   19838 class UnorderedStringMap
   19839     : public std::unordered_map<
   19840           Handle<String>, Handle<Object>, StringHandleHash, StringHandleEqual,
   19841           zone_allocator<std::pair<const Handle<String>, Handle<Object>>>> {
   19842  public:
   19843   explicit UnorderedStringMap(Zone* zone)
   19844       : std::unordered_map<
   19845             Handle<String>, Handle<Object>, StringHandleHash, StringHandleEqual,
   19846             zone_allocator<std::pair<const Handle<String>, Handle<Object>>>>(
   19847             2 /* bucket count */, StringHandleHash(), StringHandleEqual(),
   19848             zone_allocator<std::pair<const Handle<String>, Handle<Object>>>(
   19849                 zone)) {}
   19850 };
   19851 
   19852 }  // anonymous namespace
   19853 
   19854 class Module::ResolveSet
   19855     : public std::unordered_map<
   19856           Handle<Module>, UnorderedStringSet*, ModuleHandleHash,
   19857           ModuleHandleEqual, zone_allocator<std::pair<const Handle<Module>,
   19858                                                       UnorderedStringSet*>>> {
   19859  public:
   19860   explicit ResolveSet(Zone* zone)
   19861       : std::unordered_map<Handle<Module>, UnorderedStringSet*,
   19862                            ModuleHandleHash, ModuleHandleEqual,
   19863                            zone_allocator<std::pair<const Handle<Module>,
   19864                                                     UnorderedStringSet*>>>(
   19865             2 /* bucket count */, ModuleHandleHash(), ModuleHandleEqual(),
   19866             zone_allocator<
   19867                 std::pair<const Handle<Module>, UnorderedStringSet*>>(zone)),
   19868         zone_(zone) {}
   19869 
   19870   Zone* zone() const { return zone_; }
   19871 
   19872  private:
   19873   Zone* zone_;
   19874 };
   19875 
   19876 namespace {
   19877 
   19878 int ExportIndex(int cell_index) {
   19879   DCHECK_EQ(ModuleDescriptor::GetCellIndexKind(cell_index),
   19880             ModuleDescriptor::kExport);
   19881   return cell_index - 1;
   19882 }
   19883 
   19884 int ImportIndex(int cell_index) {
   19885   DCHECK_EQ(ModuleDescriptor::GetCellIndexKind(cell_index),
   19886             ModuleDescriptor::kImport);
   19887   return -cell_index - 1;
   19888 }
   19889 
   19890 }  // anonymous namespace
   19891 
   19892 void Module::CreateIndirectExport(Handle<Module> module, Handle<String> name,
   19893                                   Handle<ModuleInfoEntry> entry) {
   19894   Isolate* isolate = module->GetIsolate();
   19895   Handle<ObjectHashTable> exports(module->exports(), isolate);
   19896   DCHECK(exports->Lookup(name)->IsTheHole(isolate));
   19897   exports = ObjectHashTable::Put(exports, name, entry);
   19898   module->set_exports(*exports);
   19899 }
   19900 
   19901 void Module::CreateExport(Handle<Module> module, int cell_index,
   19902                           Handle<FixedArray> names) {
   19903   DCHECK_LT(0, names->length());
   19904   Isolate* isolate = module->GetIsolate();
   19905 
   19906   Handle<Cell> cell =
   19907       isolate->factory()->NewCell(isolate->factory()->undefined_value());
   19908   module->regular_exports()->set(ExportIndex(cell_index), *cell);
   19909 
   19910   Handle<ObjectHashTable> exports(module->exports(), isolate);
   19911   for (int i = 0, n = names->length(); i < n; ++i) {
   19912     Handle<String> name(String::cast(names->get(i)), isolate);
   19913     DCHECK(exports->Lookup(name)->IsTheHole(isolate));
   19914     exports = ObjectHashTable::Put(exports, name, cell);
   19915   }
   19916   module->set_exports(*exports);
   19917 }
   19918 
   19919 Handle<Object> Module::LoadVariable(Handle<Module> module, int cell_index) {
   19920   Isolate* isolate = module->GetIsolate();
   19921   Handle<Object> object;
   19922   switch (ModuleDescriptor::GetCellIndexKind(cell_index)) {
   19923     case ModuleDescriptor::kImport:
   19924       object = handle(module->regular_imports()->get(ImportIndex(cell_index)),
   19925                       isolate);
   19926       break;
   19927     case ModuleDescriptor::kExport:
   19928       object = handle(module->regular_exports()->get(ExportIndex(cell_index)),
   19929                       isolate);
   19930       break;
   19931     case ModuleDescriptor::kInvalid:
   19932       UNREACHABLE();
   19933       break;
   19934   }
   19935   return handle(Handle<Cell>::cast(object)->value(), isolate);
   19936 }
   19937 
   19938 void Module::StoreVariable(Handle<Module> module, int cell_index,
   19939                            Handle<Object> value) {
   19940   Isolate* isolate = module->GetIsolate();
   19941   DCHECK_EQ(ModuleDescriptor::GetCellIndexKind(cell_index),
   19942             ModuleDescriptor::kExport);
   19943   Handle<Object> object(module->regular_exports()->get(ExportIndex(cell_index)),
   19944                         isolate);
   19945   Handle<Cell>::cast(object)->set_value(*value);
   19946 }
   19947 
   19948 MaybeHandle<Cell> Module::ResolveImport(Handle<Module> module,
   19949                                         Handle<String> name, int module_request,
   19950                                         MessageLocation loc, bool must_resolve,
   19951                                         Module::ResolveSet* resolve_set) {
   19952   Isolate* isolate = module->GetIsolate();
   19953   Handle<Module> requested_module(
   19954       Module::cast(module->requested_modules()->get(module_request)), isolate);
   19955   return Module::ResolveExport(requested_module, name, loc, must_resolve,
   19956                                resolve_set);
   19957 }
   19958 
   19959 MaybeHandle<Cell> Module::ResolveExport(Handle<Module> module,
   19960                                         Handle<String> name,
   19961                                         MessageLocation loc, bool must_resolve,
   19962                                         Module::ResolveSet* resolve_set) {
   19963   Isolate* isolate = module->GetIsolate();
   19964   Handle<Object> object(module->exports()->Lookup(name), isolate);
   19965   if (object->IsCell()) {
   19966     // Already resolved (e.g. because it's a local export).
   19967     return Handle<Cell>::cast(object);
   19968   }
   19969 
   19970   // Check for cycle before recursing.
   19971   {
   19972     // Attempt insertion with a null string set.
   19973     auto result = resolve_set->insert({module, nullptr});
   19974     UnorderedStringSet*& name_set = result.first->second;
   19975     if (result.second) {
   19976       // |module| wasn't in the map previously, so allocate a new name set.
   19977       Zone* zone = resolve_set->zone();
   19978       name_set =
   19979           new (zone->New(sizeof(UnorderedStringSet))) UnorderedStringSet(zone);
   19980     } else if (name_set->count(name)) {
   19981       // Cycle detected.
   19982       if (must_resolve) {
   19983         return isolate->Throw<Cell>(
   19984             isolate->factory()->NewSyntaxError(
   19985                 MessageTemplate::kCyclicModuleDependency, name),
   19986             &loc);
   19987       }
   19988       return MaybeHandle<Cell>();
   19989     }
   19990     name_set->insert(name);
   19991   }
   19992 
   19993   if (object->IsModuleInfoEntry()) {
   19994     // Not yet resolved indirect export.
   19995     Handle<ModuleInfoEntry> entry = Handle<ModuleInfoEntry>::cast(object);
   19996     Handle<String> import_name(String::cast(entry->import_name()), isolate);
   19997     Handle<Script> script(
   19998         Script::cast(JSFunction::cast(module->code())->shared()->script()),
   19999         isolate);
   20000     MessageLocation new_loc(script, entry->beg_pos(), entry->end_pos());
   20001 
   20002     Handle<Cell> cell;
   20003     if (!ResolveImport(module, import_name, entry->module_request(), new_loc,
   20004                        true, resolve_set)
   20005              .ToHandle(&cell)) {
   20006       DCHECK(isolate->has_pending_exception());
   20007       return MaybeHandle<Cell>();
   20008     }
   20009 
   20010     // The export table may have changed but the entry in question should be
   20011     // unchanged.
   20012     Handle<ObjectHashTable> exports(module->exports(), isolate);
   20013     DCHECK(exports->Lookup(name)->IsModuleInfoEntry());
   20014 
   20015     exports = ObjectHashTable::Put(exports, name, cell);
   20016     module->set_exports(*exports);
   20017     return cell;
   20018   }
   20019 
   20020   DCHECK(object->IsTheHole(isolate));
   20021   return Module::ResolveExportUsingStarExports(module, name, loc, must_resolve,
   20022                                                resolve_set);
   20023 }
   20024 
   20025 MaybeHandle<Cell> Module::ResolveExportUsingStarExports(
   20026     Handle<Module> module, Handle<String> name, MessageLocation loc,
   20027     bool must_resolve, Module::ResolveSet* resolve_set) {
   20028   Isolate* isolate = module->GetIsolate();
   20029   if (!name->Equals(isolate->heap()->default_string())) {
   20030     // Go through all star exports looking for the given name.  If multiple star
   20031     // exports provide the name, make sure they all map it to the same cell.
   20032     Handle<Cell> unique_cell;
   20033     Handle<FixedArray> special_exports(module->info()->special_exports(),
   20034                                        isolate);
   20035     for (int i = 0, n = special_exports->length(); i < n; ++i) {
   20036       i::Handle<i::ModuleInfoEntry> entry(
   20037           i::ModuleInfoEntry::cast(special_exports->get(i)), isolate);
   20038       if (!entry->export_name()->IsUndefined(isolate)) {
   20039         continue;  // Indirect export.
   20040       }
   20041 
   20042       Handle<Script> script(
   20043           Script::cast(JSFunction::cast(module->code())->shared()->script()),
   20044           isolate);
   20045       MessageLocation new_loc(script, entry->beg_pos(), entry->end_pos());
   20046 
   20047       Handle<Cell> cell;
   20048       if (ResolveImport(module, name, entry->module_request(), new_loc, false,
   20049                         resolve_set)
   20050               .ToHandle(&cell)) {
   20051         if (unique_cell.is_null()) unique_cell = cell;
   20052         if (*unique_cell != *cell) {
   20053           return isolate->Throw<Cell>(
   20054               isolate->factory()->NewSyntaxError(
   20055                   MessageTemplate::kAmbiguousExport, name),
   20056               &loc);
   20057         }
   20058       } else if (isolate->has_pending_exception()) {
   20059         return MaybeHandle<Cell>();
   20060       }
   20061     }
   20062 
   20063     if (!unique_cell.is_null()) {
   20064       // Found a unique star export for this name.
   20065       Handle<ObjectHashTable> exports(module->exports(), isolate);
   20066       DCHECK(exports->Lookup(name)->IsTheHole(isolate));
   20067       exports = ObjectHashTable::Put(exports, name, unique_cell);
   20068       module->set_exports(*exports);
   20069       return unique_cell;
   20070     }
   20071   }
   20072 
   20073   // Unresolvable.
   20074   if (must_resolve) {
   20075     return isolate->Throw<Cell>(isolate->factory()->NewSyntaxError(
   20076                                     MessageTemplate::kUnresolvableExport, name),
   20077                                 &loc);
   20078   }
   20079   return MaybeHandle<Cell>();
   20080 }
   20081 
   20082 bool Module::Instantiate(Handle<Module> module, v8::Local<v8::Context> context,
   20083                          v8::Module::ResolveCallback callback) {
   20084   if (module->instantiated()) return true;
   20085 
   20086   Isolate* isolate = module->GetIsolate();
   20087   Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(module->code()),
   20088                                     isolate);
   20089   Handle<JSFunction> function =
   20090       isolate->factory()->NewFunctionFromSharedFunctionInfo(
   20091           shared,
   20092           handle(Utils::OpenHandle(*context)->native_context(), isolate));
   20093   module->set_code(*function);
   20094   DCHECK(module->instantiated());
   20095 
   20096   Handle<ModuleInfo> module_info(shared->scope_info()->ModuleDescriptorInfo(),
   20097                                  isolate);
   20098 
   20099   // Set up local exports.
   20100   // TODO(neis): Create regular_exports array here instead of in factory method?
   20101   for (int i = 0, n = module_info->RegularExportCount(); i < n; ++i) {
   20102     int cell_index = module_info->RegularExportCellIndex(i);
   20103     Handle<FixedArray> export_names(module_info->RegularExportExportNames(i),
   20104                                     isolate);
   20105     CreateExport(module, cell_index, export_names);
   20106   }
   20107 
   20108   // Partially set up indirect exports.
   20109   // For each indirect export, we create the appropriate slot in the export
   20110   // table and store its ModuleInfoEntry there.  When we later find the correct
   20111   // Cell in the module that actually provides the value, we replace the
   20112   // ModuleInfoEntry by that Cell (see ResolveExport).
   20113   Handle<FixedArray> special_exports(module_info->special_exports(), isolate);
   20114   for (int i = 0, n = special_exports->length(); i < n; ++i) {
   20115     Handle<ModuleInfoEntry> entry(
   20116         ModuleInfoEntry::cast(special_exports->get(i)), isolate);
   20117     Handle<Object> export_name(entry->export_name(), isolate);
   20118     if (export_name->IsUndefined(isolate)) continue;  // Star export.
   20119     CreateIndirectExport(module, Handle<String>::cast(export_name), entry);
   20120   }
   20121 
   20122   Handle<FixedArray> module_requests(module_info->module_requests(), isolate);
   20123   for (int i = 0, length = module_requests->length(); i < length; ++i) {
   20124     Handle<String> specifier(String::cast(module_requests->get(i)), isolate);
   20125     v8::Local<v8::Module> api_requested_module;
   20126     // TODO(adamk): Revisit these failure cases once d8 knows how to
   20127     // persist a module_map across multiple top-level module loads, as
   20128     // the current module is left in a "half-instantiated" state.
   20129     if (!callback(context, v8::Utils::ToLocal(specifier),
   20130                   v8::Utils::ToLocal(module))
   20131              .ToLocal(&api_requested_module)) {
   20132       // TODO(adamk): Give this a better error message. But this is a
   20133       // misuse of the API anyway.
   20134       isolate->ThrowIllegalOperation();
   20135       return false;
   20136     }
   20137     Handle<Module> requested_module = Utils::OpenHandle(*api_requested_module);
   20138     module->requested_modules()->set(i, *requested_module);
   20139     if (!Instantiate(requested_module, context, callback)) {
   20140       return false;
   20141     }
   20142   }
   20143 
   20144   Zone zone(isolate->allocator(), ZONE_NAME);
   20145 
   20146   // Resolve imports.
   20147   Handle<FixedArray> regular_imports(module_info->regular_imports(), isolate);
   20148   for (int i = 0, n = regular_imports->length(); i < n; ++i) {
   20149     Handle<ModuleInfoEntry> entry(
   20150         ModuleInfoEntry::cast(regular_imports->get(i)), isolate);
   20151     Handle<String> name(String::cast(entry->import_name()), isolate);
   20152     Handle<Script> script(
   20153         Script::cast(JSFunction::cast(module->code())->shared()->script()),
   20154         isolate);
   20155     MessageLocation loc(script, entry->beg_pos(), entry->end_pos());
   20156     ResolveSet resolve_set(&zone);
   20157     Handle<Cell> cell;
   20158     if (!ResolveImport(module, name, entry->module_request(), loc, true,
   20159                        &resolve_set)
   20160              .ToHandle(&cell)) {
   20161       return false;
   20162     }
   20163     module->regular_imports()->set(ImportIndex(entry->cell_index()), *cell);
   20164   }
   20165 
   20166   // Resolve indirect exports.
   20167   for (int i = 0, n = special_exports->length(); i < n; ++i) {
   20168     Handle<ModuleInfoEntry> entry(
   20169         ModuleInfoEntry::cast(special_exports->get(i)), isolate);
   20170     Handle<Object> name(entry->export_name(), isolate);
   20171     if (name->IsUndefined(isolate)) continue;  // Star export.
   20172     Handle<Script> script(
   20173         Script::cast(JSFunction::cast(module->code())->shared()->script()),
   20174         isolate);
   20175     MessageLocation loc(script, entry->beg_pos(), entry->end_pos());
   20176     ResolveSet resolve_set(&zone);
   20177     if (ResolveExport(module, Handle<String>::cast(name), loc, true,
   20178                       &resolve_set)
   20179             .is_null()) {
   20180       return false;
   20181     }
   20182   }
   20183 
   20184   return true;
   20185 }
   20186 
   20187 MaybeHandle<Object> Module::Evaluate(Handle<Module> module) {
   20188   DCHECK(module->instantiated());
   20189 
   20190   // Each module can only be evaluated once.
   20191   Isolate* isolate = module->GetIsolate();
   20192   if (module->evaluated()) return isolate->factory()->undefined_value();
   20193   Handle<JSFunction> function(JSFunction::cast(module->code()), isolate);
   20194   module->set_evaluated();
   20195 
   20196   // Initialization.
   20197   DCHECK_EQ(MODULE_SCOPE, function->shared()->scope_info()->scope_type());
   20198   Handle<Object> receiver = isolate->factory()->undefined_value();
   20199   Handle<Object> argv[] = {module};
   20200   Handle<Object> generator;
   20201   ASSIGN_RETURN_ON_EXCEPTION(
   20202       isolate, generator,
   20203       Execution::Call(isolate, function, receiver, arraysize(argv), argv),
   20204       Object);
   20205 
   20206   // Recursion.
   20207   Handle<FixedArray> requested_modules(module->requested_modules(), isolate);
   20208   for (int i = 0, length = requested_modules->length(); i < length; ++i) {
   20209     Handle<Module> import(Module::cast(requested_modules->get(i)), isolate);
   20210     RETURN_ON_EXCEPTION(isolate, Evaluate(import), Object);
   20211   }
   20212 
   20213   // Evaluation of module body.
   20214   Handle<JSFunction> resume(
   20215       isolate->native_context()->generator_next_internal(), isolate);
   20216   return Execution::Call(isolate, resume, generator, 0, nullptr);
   20217 }
   20218 
   20219 namespace {
   20220 
   20221 void FetchStarExports(Handle<Module> module, Zone* zone,
   20222                       UnorderedModuleSet* visited) {
   20223   DCHECK(module->instantiated());
   20224 
   20225   bool cycle = !visited->insert(module).second;
   20226   if (cycle) return;
   20227 
   20228   Isolate* isolate = module->GetIsolate();
   20229   Handle<ObjectHashTable> exports(module->exports(), isolate);
   20230   UnorderedStringMap more_exports(zone);
   20231 
   20232   // TODO(neis): Only allocate more_exports if there are star exports.
   20233   // Maybe split special_exports into indirect_exports and star_exports.
   20234 
   20235   Handle<FixedArray> special_exports(module->info()->special_exports(),
   20236                                      isolate);
   20237   for (int i = 0, n = special_exports->length(); i < n; ++i) {
   20238     Handle<ModuleInfoEntry> entry(
   20239         ModuleInfoEntry::cast(special_exports->get(i)), isolate);
   20240     if (!entry->export_name()->IsUndefined(isolate)) {
   20241       continue;  // Indirect export.
   20242     }
   20243 
   20244     Handle<Module> requested_module(
   20245         Module::cast(module->requested_modules()->get(entry->module_request())),
   20246         isolate);
   20247 
   20248     // Recurse.
   20249     FetchStarExports(requested_module, zone, visited);
   20250 
   20251     // Collect all of [requested_module]'s exports that must be added to
   20252     // [module]'s exports (i.e. to [exports]).  We record these in
   20253     // [more_exports].  Ambiguities (conflicting exports) are marked by mapping
   20254     // the name to undefined instead of a Cell.
   20255     Handle<ObjectHashTable> requested_exports(requested_module->exports(),
   20256                                               isolate);
   20257     for (int i = 0, n = requested_exports->Capacity(); i < n; ++i) {
   20258       Handle<Object> key(requested_exports->KeyAt(i), isolate);
   20259       if (!requested_exports->IsKey(isolate, *key)) continue;
   20260       Handle<String> name = Handle<String>::cast(key);
   20261 
   20262       if (name->Equals(isolate->heap()->default_string())) continue;
   20263       if (!exports->Lookup(name)->IsTheHole(isolate)) continue;
   20264 
   20265       Handle<Cell> cell(Cell::cast(requested_exports->ValueAt(i)), isolate);
   20266       auto insert_result = more_exports.insert(std::make_pair(name, cell));
   20267       if (!insert_result.second) {
   20268         auto it = insert_result.first;
   20269         if (*it->second == *cell || it->second->IsUndefined(isolate)) {
   20270           // We already recorded this mapping before, or the name is already
   20271           // known to be ambiguous.  In either case, there's nothing to do.
   20272         } else {
   20273           DCHECK(it->second->IsCell());
   20274           // Different star exports provide different cells for this name, hence
   20275           // mark the name as ambiguous.
   20276           it->second = isolate->factory()->undefined_value();
   20277         }
   20278       }
   20279     }
   20280   }
   20281 
   20282   // Copy [more_exports] into [exports].
   20283   for (const auto& elem : more_exports) {
   20284     if (elem.second->IsUndefined(isolate)) continue;  // Ambiguous export.
   20285     DCHECK(!elem.first->Equals(isolate->heap()->default_string()));
   20286     DCHECK(elem.second->IsCell());
   20287     exports = ObjectHashTable::Put(exports, elem.first, elem.second);
   20288   }
   20289   module->set_exports(*exports);
   20290 }
   20291 
   20292 }  // anonymous namespace
   20293 
   20294 Handle<JSModuleNamespace> Module::GetModuleNamespace(Handle<Module> module,
   20295                                                      int module_request) {
   20296   Isolate* isolate = module->GetIsolate();
   20297   Handle<Module> requested_module(
   20298       Module::cast(module->requested_modules()->get(module_request)), isolate);
   20299   return Module::GetModuleNamespace(requested_module);
   20300 }
   20301 
   20302 Handle<JSModuleNamespace> Module::GetModuleNamespace(Handle<Module> module) {
   20303   Isolate* isolate = module->GetIsolate();
   20304 
   20305   Handle<HeapObject> object(module->module_namespace(), isolate);
   20306   if (!object->IsUndefined(isolate)) {
   20307     // Namespace object already exists.
   20308     return Handle<JSModuleNamespace>::cast(object);
   20309   }
   20310 
   20311   // Create the namespace object (initially empty).
   20312   Handle<JSModuleNamespace> ns = isolate->factory()->NewJSModuleNamespace();
   20313   ns->set_module(*module);
   20314   module->set_module_namespace(*ns);
   20315 
   20316   // Collect the export names.
   20317   Zone zone(isolate->allocator(), ZONE_NAME);
   20318   UnorderedModuleSet visited(&zone);
   20319   FetchStarExports(module, &zone, &visited);
   20320   Handle<ObjectHashTable> exports(module->exports(), isolate);
   20321   ZoneVector<Handle<String>> names(&zone);
   20322   names.reserve(exports->NumberOfElements());
   20323   for (int i = 0, n = exports->Capacity(); i < n; ++i) {
   20324     Handle<Object> key(exports->KeyAt(i), isolate);
   20325     if (!exports->IsKey(isolate, *key)) continue;
   20326     DCHECK(exports->ValueAt(i)->IsCell());
   20327     names.push_back(Handle<String>::cast(key));
   20328   }
   20329   DCHECK_EQ(static_cast<int>(names.size()), exports->NumberOfElements());
   20330 
   20331   // Sort them alphabetically.
   20332   struct {
   20333     bool operator()(Handle<String> a, Handle<String> b) {
   20334       return String::Compare(a, b) == ComparisonResult::kLessThan;
   20335     }
   20336   } StringLess;
   20337   std::sort(names.begin(), names.end(), StringLess);
   20338 
   20339   // Create the corresponding properties in the namespace object.
   20340   PropertyAttributes attr = DONT_DELETE;
   20341   for (const auto& name : names) {
   20342     JSObject::SetAccessor(
   20343         ns, Accessors::ModuleNamespaceEntryInfo(isolate, name, attr))
   20344         .Check();
   20345   }
   20346   JSObject::PreventExtensions(ns, THROW_ON_ERROR).ToChecked();
   20347 
   20348   return ns;
   20349 }
   20350 
   20351 MaybeHandle<Name> FunctionTemplateInfo::TryGetCachedPropertyName(
   20352     Isolate* isolate, Handle<Object> getter) {
   20353   if (getter->IsFunctionTemplateInfo()) {
   20354     Handle<FunctionTemplateInfo> fti =
   20355         Handle<FunctionTemplateInfo>::cast(getter);
   20356     // Check if the accessor uses a cached property.
   20357     if (!fti->cached_property_name()->IsTheHole(isolate)) {
   20358       return handle(Name::cast(fti->cached_property_name()));
   20359     }
   20360   }
   20361   return MaybeHandle<Name>();
   20362 }
   20363 
   20364 // static
   20365 ElementsKind JSArrayIterator::ElementsKindForInstanceType(InstanceType type) {
   20366   DCHECK_GE(type, FIRST_ARRAY_ITERATOR_TYPE);
   20367   DCHECK_LE(type, LAST_ARRAY_ITERATOR_TYPE);
   20368 
   20369   if (type <= LAST_ARRAY_KEY_ITERATOR_TYPE) {
   20370     // Should be ignored for key iterators.
   20371     return FAST_ELEMENTS;
   20372   } else {
   20373     ElementsKind kind;
   20374     if (type < FIRST_ARRAY_VALUE_ITERATOR_TYPE) {
   20375       // Convert `type` to a value iterator from an entries iterator
   20376       type = static_cast<InstanceType>(type +
   20377                                        (FIRST_ARRAY_VALUE_ITERATOR_TYPE -
   20378                                         FIRST_ARRAY_KEY_VALUE_ITERATOR_TYPE));
   20379       DCHECK_GE(type, FIRST_ARRAY_VALUE_ITERATOR_TYPE);
   20380       DCHECK_LE(type, LAST_ARRAY_ITERATOR_TYPE);
   20381     }
   20382 
   20383     if (type <= JS_UINT8_CLAMPED_ARRAY_VALUE_ITERATOR_TYPE) {
   20384       kind =
   20385           static_cast<ElementsKind>(FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND +
   20386                                     (type - FIRST_ARRAY_VALUE_ITERATOR_TYPE));
   20387       DCHECK_LE(kind, LAST_FIXED_TYPED_ARRAY_ELEMENTS_KIND);
   20388     } else if (type < JS_GENERIC_ARRAY_VALUE_ITERATOR_TYPE) {
   20389       kind = static_cast<ElementsKind>(
   20390           FIRST_FAST_ELEMENTS_KIND +
   20391           (type - JS_FAST_SMI_ARRAY_VALUE_ITERATOR_TYPE));
   20392       DCHECK_LE(kind, LAST_FAST_ELEMENTS_KIND);
   20393     } else {
   20394       // For any slow element cases, the actual elements kind is not known.
   20395       // Simply
   20396       // return a slow elements kind in this case. Users of this function must
   20397       // not
   20398       // depend on this.
   20399       return DICTIONARY_ELEMENTS;
   20400     }
   20401     DCHECK_LE(kind, LAST_ELEMENTS_KIND);
   20402     return kind;
   20403   }
   20404 }
   20405 
   20406 }  // namespace internal
   20407 }  // namespace v8
   20408